Program Listing for File string_extra.hpp¶
↰ Return to documentation for file (/home/runner/work/Legion-Engine/Legion-Engine/legion/engine/core/common/string_extra.hpp
)
#pragma once
#include <algorithm>
#include <cctype>
#include <locale>
#include <vector>
#include <sstream>
#include <iterator>
#include <core/types/primitives.hpp>
#include <cstring>
#include <Optick/optick.h>
namespace legion::core::common {
inline bool starts_with(const std::string& src, cstring value)
{
return src.rfind(value,0) == 0;
}
inline bool ends_with(const std::string& src, cstring value)
{
std::string end (value);
if (end.size() > src.size()) return false;
return std::equal(end.rbegin(),end.rend(),src.rbegin());
}
template<typename StringType>
inline size_t replace_items(StringType& source, const std::string& item, const std::string& value)
{
OPTICK_EVENT();
size_t count = 0;
auto it = source.begin();
while ((it = std::search(it, source.end(), item.begin(), item.end())) != source.end()) // While there's items to be found, keep replacing them with value.
{
count++;
source.erase(it, it + item.size());
source.insert(it, value.begin(), value.end());
}
return count;
}
struct isChars
{
isChars(const char* chars) :_chars(chars) {}
bool operator()(char c) const
{
OPTICK_EVENT();
for (auto testChar = _chars; *testChar != 0; ++testChar)
if (*testChar == c) return true;
return false;
}
const char* _chars;
};
template <typename t>
std::string string_from_data(t data);
template <typename T>
T data_from_string_(std::string str);
template <char token, char... tokens>
bool str_tokens_helper(std::ctype<char>::mask* rc)
{
OPTICK_EVENT();
rc[token] = std::ctype<char>::space;
if constexpr (sizeof...(tokens) != 0) str_tokens_helper<tokens...>(rc);
return true;
}
//dilems helper classlo
template <char token, char... tokens>
struct str_tokens : std::ctype<char>
{
str_tokens() : ctype<char>(get_table())
{
}
static mask const* get_table()
{
//create const and normal rc
static const mask* const_rc = std::use_facet<std::ctype<char>>(std::locale()).table();
static mask rc[table_size];
static auto memory = memcpy(rc, const_rc, table_size * sizeof(mask));
static char memory1 = rc[' '] = std::ctype<char>::digit;
static char memory2 = rc['\t'] = std::ctype<char>::digit;
static bool memory3 = str_tokens_helper<token, tokens...>(rc);
//set spaces
return rc;
}
};
//split string at any given char via variadic template and insert into vector
template <char token_1, char... token>
std::vector<std::string> split_string_at(const std::string& string)
{
OPTICK_EVENT();
//copy string into stringstream
std::stringstream ss(string);
//set tokens
ss.imbue(std::locale(std::locale(), new str_tokens<token_1, token...>()));
//create iterators
const std::istream_iterator<std::string> begin(ss);
const std::istream_iterator<std::string> end;
//copy using iterators
const std::vector<std::string> vstrings(begin, end);
return vstrings;
}
template <const char* const delim, typename Range, typename Value = typename Range::value_type>
std::string join_strings_with(Range const& elements) {
OPTICK_EVENT();
std::ostringstream os;
auto b = begin(elements), e = end(elements);
if (b != e) {
std::copy(b, prev(e), std::ostream_iterator<Value>(os, delim));
b = prev(e);
}
if (b != e) {
os << *b;
}
return os.str();
}
template <typename Range, typename Value = typename Range::value_type>
std::string join_strings_with(Range const& elements, const char* const delim) {
OPTICK_EVENT();
std::ostringstream os;
auto b = begin(elements), e = end(elements);
if (b != e) {
std::copy(b, prev(e), std::ostream_iterator<Value>(os, delim));
b = prev(e);
}
if (b != e) {
os << *b;
}
return os.str();
}
template <const char delim, typename Range, typename Value = typename Range::value_type>
std::string join_strings_with(Range const& elements) {
OPTICK_EVENT();
std::ostringstream os;
auto b = begin(elements), e = end(elements);
char promoter[2] = { delim };
if (b != e) {
std::copy(b, prev(e), std::ostream_iterator<Value>(os, delim));
b = prev(e);
}
if (b != e) {
os << *b;
}
return os.str();
}
template <typename Range, typename Value = typename Range::value_type>
std::string join_strings_with(Range const& elements, char delim) {
OPTICK_EVENT();
std::ostringstream os;
auto b = begin(elements), e = end(elements);
char promoter[2] = { delim };
if (b != e) {
std::copy(b, prev(e), std::ostream_iterator<Value>(os, promoter));
b = prev(e);
}
if (b != e) {
os << *b;
}
return os.str();
}
//remove given word from string at offset and return true if success and false on fail
inline bool find_and_remove_at(std::string& src, const std::string& search, size_t offset = 0)
{
OPTICK_EVENT();
//create temporary
size_t loc;
//find given word
if ((loc = src.find(search, offset)) == std::string::npos) return false;
//erase word
src.erase(loc, search.size());
return true;
}
//remove given word from string at offset and return the position
inline size_t locate_and_delete_at(std::string& src, const std::string& search, size_t offset = 0)
{
OPTICK_EVENT();
//create temporary
size_t loc;
//find given word
if ((loc = src.find(search, offset)) == std::string::npos) return std::string::npos;
//erase word
src.erase(loc, search.size());
return loc;
}
//find the nearest of given tokens in a string at an offset
template <char token_1, char... tokens>
inline size_t nearest_of_any_at(std::string string, size_t offset = 0)
{
OPTICK_EVENT();
//create tokens using variadic unfolding
std::vector<char> tokensVector = { token_1 , tokens... };
//create locations
std::vector<size_t> locationsVector(tokensVector.size());
//find locations
for (char& token : tokensVector) locationsVector.push_back(string.find(token, offset));
//find smallest element and return
return *min_element(begin(locationsVector), end(locationsVector));
}
template <>
inline std::string data_from_string_<std::string>(std::string str)
{
return str;
}
template <>
inline std::vector<std::string> data_from_string_<std::vector<std::string>>(std::string str)
{
OPTICK_EVENT();
return split_string_at<',', ' '>(str);
}
template <typename T>
inline T data_from_string_(std::string str)
{
OPTICK_EVENT();
std::stringstream temp(str);
T value;
temp >> value;
return value;
}
template <>
inline std::string string_from_data<std::string>(std::string data)
{
return data;
}
template <>
inline std::string string_from_data<std::vector<std::string>>(std::vector<std::string> data)
{
OPTICK_EVENT();
std::string ret;
for (const std::string& str : data)
ret += str;
return ret;
}
template <typename t>
inline std::string string_from_data(t data)
{
OPTICK_EVENT();
std::stringstream temp;
temp << data;
return temp.str();
}
template <char D = '.'>
constexpr size_t count_delimiter(const char* str)
{
return str[0] == '\0' ? 0 : str[0] == D ? count_delimiter<D>(&str[1]) + 1 : count_delimiter<D>(&str[1]);
}
constexpr size_t cstrptr_length(const char* str)
{
return *str ? 1 + cstrptr_length(str + 1) : 0;
}
template <class T, size_t N> constexpr size_t arr_length(T[N])
{
return N;
}
// trim from start (in place)
static inline void ltrim(std::string& s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) {
return !std::isspace(ch);
}));
}
template <class Trimmer>
static inline void ltrim(std::string& s, Trimmer&& t)
{
s.erase(std::find_if(s.begin(), s.end(), [&t](int ch) {
return !t(ch);
}), s.end());
}
// trim from end (in place)
static inline void rtrim(std::string& s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
return !std::isspace(ch);
}).base(), s.end());
}
template <class Trimmer>
static inline void rtrim(std::string& s, Trimmer&& t)
{
s.erase(std::find_if(s.rbegin(), s.rend(), [&t](int ch) {
return !t(ch);
}).base(), s.end());
}
// trim from both ends (in place)
static inline void trim(std::string& s) {
ltrim(s);
rtrim(s);
}
template <class Trimmer>
static inline void trim(std::string& s, Trimmer&& t)
{
ltrim(s, t);
rtrim(s, t);
}
// trim from start (copying)
static inline std::string ltrim_copy(std::string s) {
ltrim(s);
return s;
}
// trim from end (copying)
static inline std::string rtrim_copy(std::string s) {
rtrim(s);
return s;
}
// trim from both ends (copying)
static inline std::string trim_copy(std::string s) {
trim(s);
return s;
}
template<class Trimmer>
// trim from start (copying)
static inline std::string ltrim_copy(std::string s, Trimmer&& t) {
ltrim(s, t);
return s;
}
template<class Trimmer>
// trim from end (copying)
static inline std::string rtrim_copy(std::string s, Trimmer&& t) {
rtrim(s, t);
return s;
}
template<class Trimmer>
// trim from both ends (copying)
static inline std::string trim_copy(std::string s, Trimmer&& t) {
trim(s, t);
return s;
}
}