← Back to file list Raw

src/U_String.h

#pragma once
#include <string>
#include <sstream>
#include <locale>
#include <codecvt>
#include <vector>
#include <algorithm>
#include <type_traits>
#include <regex>
#include <iostream>
#include <string_view>
#include <boost/locale.hpp>
#include "U_General.h"
#include "U_Types.h"
#include "glm/glm.hpp"
#include "glm/gtc/quaternion.hpp"
#include "CAngle.h"
#include "CColor.h"
#include "CColorInt.h"
namespace StringUtils
{
std::wstring StrToWstr(const std::string& str);
std::string WstrToStr(const std::wstring& wstr);
std::u16string Utf8ToU16(const std::string& str);
std::string U16ToUtf8(const std::u16string& str);
std::u16string WstrToU16(const std::wstring& wstr);
std::wstring U16ToWstr(const std::u16string& str);
void split_str(const std::string& s, char delim, std::vector<std::string>& ua);
void split_str(const std::wstring& s, wchar_t delim, std::vector<std::wstring>& ua);
std::vector<std::string> split_str(const std::string& s, char delim);
std::vector<std::wstring> split_str(const std::wstring& s, wchar_t delim);
template<typename String = std::string>
String RemoveSpaces(const String& str, size_t stayBegin = 0, size_t stayEnd = 0)
{
using C = std::conditional_t<std::is_same_v<String, std::string>, char, wchar_t>;
constexpr C charspace = std::is_same_v<C, char> ? ' ' : L' ';
constexpr C chartab = std::is_same_v<C, char> ? '\t' : L'\t';
String ret = str;
size_t spacesAtBegin = 0, spacesAtEnd = 0;
for(auto it = str.begin(); it != str.end(); ++it)
{
if(*it == charspace || *it == chartab)
{
spacesAtBegin++;
}
else
{
break;
}
}
for(auto it = str.rbegin(); it != str.rend(); ++it)
{
if(*it == charspace || *it == chartab)
{
spacesAtEnd++;
}
else
{
break;
}
}
int diffBegin = static_cast<int>(spacesAtBegin) - static_cast<int>(stayBegin);
int diffEnd = static_cast<int>(spacesAtEnd) - static_cast<int>(stayEnd);
//3 - 1 = 2
//1 - 1 = 0
//3 - 4 = -1
if(diffBegin < 0) { diffBegin = 0; }
if(diffEnd < 0) { diffEnd = 0; }
if (diffBegin > ret.size()) { diffBegin = ret.size(); }
ret.erase(0, diffBegin);
if (diffEnd > ret.size()) { diffEnd = ret.size(); }
ret.erase(ret.size() - diffEnd, diffEnd);
//mleb***
//0123456 size = 7
//diffEnd = 3
//7 - 3 = 4
return ret;
}
template<typename String = std::string>
String SafeSubstring(const String& str, size_t count, size_t offset = 0)
{
//substr
//0, 3 -> sub
//substr
//0, 6 -> substr
//substr
//1, 3 -> ubs
//substr
//4, 4 -> tr (6 - 4) = 2
//substr
//4, 5 -> tr (6 - 4) = 2
if (str.empty()) { return String(); }
size_t startIndex = offset;
size_t endIndex = offset + count;
if (startIndex >= str.size()) { return String(); }
if (endIndex >= str.size()) { return str.substr(startIndex, str.size() - startIndex); }
return str.substr(startIndex, count);
}
bool StartsWith(const std::string& str, const std::string& startswith);
bool StartsWith(const std::wstring& str, const std::wstring& startswith);
template<typename String = std::string>
String merge_arg(const std::vector<String>& vect, size_t start, size_t end)
{
if (vect.empty()) { return {}; }
String ret;
for (size_t i = start; i <= end; ++i)
{
if constexpr (std::is_same_v<String, std::wstring>)
{
if (i != start) { ret += L" "; }
}
else
{
if (i != start) { ret += " "; }
}
ret += vect.at(i);
}
return ret;
}
template<typename String = std::string>
void replace(String& str, const String& from, const String& to)
{
if (from.empty()) { return; }
size_t start_pos = 0;
while ((start_pos = str.find(from, start_pos)) != String::npos)
{
str.replace(start_pos, from.length(), to);
start_pos += to.length();
}
}
template<typename String = std::string>
bool hasEnding(const String& fullString, const String& ending)
{
if (fullString.length() >= ending.length())
{
return (0 == fullString.compare(fullString.length() - ending.length(), ending.length(), ending));
}
return false;
}
template<typename String = std::string>
bool IsEmpty(const String& str)
{
if (str.empty()) { return true; }
using C = std::conditional_t<std::is_same_v<String, std::string>, char, wchar_t>;
constexpr C charspace = std::is_same_v<C, char> ? ' ' : L' ';
constexpr C chartab = std::is_same_v<C, char> ? '\t' : L'\t';
for (C b : str)
{
if (b != charspace && b != chartab)
{
return false;
}
}
return true;
}
template <typename StringType>
bool isNumber(const StringType& str)
{
if (str.empty()) { return false; }
typename StringType::const_iterator it = str.begin();
bool decimalPoint = false;
bool hasDigits = false;
typename StringType::value_type dotChar = '.';
typename StringType::value_type minusChar = '-';
if (*it == minusChar) { ++it; }
for (; it != str.end(); ++it)
{
if (*it == dotChar)
{
if (decimalPoint)
{
return false;
}
decimalPoint = true;
}
else if (!std::isdigit(*it, std::locale()))
{
return false;
}
else
{
hasDigits = true;
}
}
return hasDigits;
}
void remove_consecutive_commas(std::string& str);
void remove_consecutive_commas(std::wstring& str);
namespace SequentVectorParse
{
template<typename String>
std::vector<String> Split(String str)
{
std::vector<String> ret;
if constexpr (std::is_same_v<String, std::string>)
{
replace(str, std::string(" "), std::string(","));
replace(str, std::string(";"), std::string(","));
replace(str, std::string("\t"), std::string(","));
replace(str, std::string(":"), std::string(","));
remove_consecutive_commas(str);
split_str(str, ',', ret);
}
else if constexpr (std::is_same_v<String, std::wstring>)
{
replace(str, std::wstring(L" "), std::wstring(L","));
replace(str, std::wstring(L";"), std::wstring(L","));
replace(str, std::wstring(L"\t"), std::wstring(L","));
replace(str, std::wstring(L":"), std::wstring(L","));
remove_consecutive_commas(str);
split_str(str, L',', ret);
}
return ret;
}
template<typename Vec, typename String = std::string>
void Parse(Vec& vec, const String& str)
{
using sstream = std::conditional_t<std::is_same_v<String, std::string>, std::stringstream, std::wstringstream>;
auto splitted = Split(str);
for (auto i = 0; i < vec.length() && i < splitted.size(); i++)
{
typename Vec::value_type single;
sstream ss(splitted[i]);
ss >> single;
vec[i] = single;
}
}
}
template<typename T, typename String = std::string>
T FromStr(const String& str) //TODO glm::mat
{
using sstream = std::conditional_t<std::is_same_v<String, std::string>, std::stringstream, std::wstringstream>;
constexpr bool is_this_string = std::is_same_v<String, std::string>;
constexpr bool is_this_wstring = std::is_same_v<String, std::wstring>;
constexpr bool is_char = std::is_same<T, char>::value || std::is_same<T, unsigned char>::value;
constexpr bool is_string = std::is_same<T, std::string>::value;
constexpr bool is_wstring = std::is_same<T, std::wstring>::value;
constexpr bool is_angle = std::is_same<T, CAngle>::value;
constexpr bool is_angles = std::is_same<T, CAngles>::value;
constexpr bool is_color = std::is_same<T, CColor>::value;
constexpr bool is_colorint = std::is_same<T, CColorInt>::value;
constexpr bool is_anycolor = is_color || is_colorint;
constexpr bool is_quat = are_same_template<T, glm::quat>::value;
constexpr bool is_vec2 = are_same_template<T, glm::vec2>::value;
constexpr bool is_vec3 = are_same_template<T, glm::vec3>::value;
constexpr bool is_vec4 = are_same_template<T, glm::vec4>::value;
constexpr bool is_ivec2 = are_same_template<T, glm::ivec2>::value;
constexpr bool is_ivec3 = are_same_template<T, glm::ivec3>::value;
constexpr bool is_ivec4 = are_same_template<T, glm::ivec4>::value;
constexpr bool is_uvec2 = are_same_template<T, glm::uvec2>::value;
constexpr bool is_uvec3 = are_same_template<T, glm::uvec3>::value;
constexpr bool is_uvec4 = are_same_template<T, glm::uvec4>::value;
constexpr bool is_vec_or_quat = is_glm_quat_v<T> || is_glm_vec_v<T>;
constexpr bool is_bool = std::is_same<T, bool>::value;
constexpr bool is_int8 = std::is_same<T, std::int8_t>::value;
constexpr bool is_uint8 = std::is_same<T, std::uint8_t>::value;
sstream ss(str);
if constexpr (is_int8 || is_uint8)
{
int ret;
ss >> ret;
return ret;
}
else if constexpr (is_wstring && is_this_string)
{
return StrToWstr(str);
}
else if constexpr (is_string && is_this_wstring)
{
return WstrToStr(str);
}
else if constexpr (is_bool)
{
String str_lower = str;
if constexpr (is_this_string)
{
std::transform(str_lower.begin(), str_lower.end(), str_lower.begin(), ::tolower);
if (str_lower == "true" || str_lower == "yes")
{
return true;
}
}
else
{
std::transform(str_lower.begin(), str_lower.end(), str_lower.begin(), ::towlower);
if (str_lower == L"true" || str_lower == L"yes")
{
return true;
}
}
int num;
float fl_num;
ss >> num;
if (ss.fail())
{
ss.clear();
ss.str(str);
ss >> fl_num;
if (ss.fail() || std::isnan(fl_num))
{
return false;
}
else
{
return (fl_num > 0.0f);
}
}
else
{
return (num > 0);
}
}
else if constexpr (is_vec_or_quat || is_angles || is_anycolor)
{
T ret{};
SequentVectorParse::Parse(ret, str);
return ret;
}
else if constexpr (is_angle)
{
float angl;
ss >> angl;
return CAngle::radians(angl);
}
else
{
T ret;
ss >> ret;
return ret;
}
}
template<typename String = std::string, typename T>
String ToStr(const T& val) //TODO glm::mat
{
using sstream = std::conditional_t<std::is_same_v<String, std::string>, std::stringstream, std::wstringstream>;
constexpr bool is_int8 = std::is_same<T, std::int8_t>::value;
constexpr bool is_uint8 = std::is_same<T, std::uint8_t>::value;
constexpr bool is_this_string = std::is_same_v<String, std::string>;
constexpr bool is_this_wstring = std::is_same_v<String, std::wstring>;
constexpr bool is_char = std::is_same<T, char>::value || std::is_same<T, unsigned char>::value;
constexpr bool is_double = std::is_floating_point<T>::value;
constexpr bool is_string = std::is_same<T, std::string>::value;
constexpr bool is_wstring = std::is_same<T, std::wstring>::value;
constexpr bool is_angle = std::is_same<T, CAngle>::value;
constexpr bool is_angles = std::is_same<T, CAngles>::value;
constexpr bool is_quat = are_same_template<T, glm::quat>::value;
constexpr bool is_vec2 = are_same_template<T, glm::vec2>::value;
constexpr bool is_vec3 = are_same_template<T, glm::vec3>::value;
constexpr bool is_vec4 = are_same_template<T, glm::vec4>::value;
constexpr bool is_ivec2 = are_same_template<T, glm::ivec2>::value;
constexpr bool is_ivec3 = are_same_template<T, glm::ivec3>::value;
constexpr bool is_ivec4 = are_same_template<T, glm::ivec4>::value;
constexpr bool is_uvec2 = are_same_template<T, glm::uvec2>::value;
constexpr bool is_uvec3 = are_same_template<T, glm::uvec3>::value;
constexpr bool is_uvec4 = are_same_template<T, glm::uvec4>::value;
constexpr bool is_color = std::is_same<T, CColor>::value;
constexpr bool is_colorint = std::is_same<T, CColorInt>::value;
constexpr bool is_anycolor = is_color || is_colorint;
constexpr bool is_vec_or_quat = is_glm_quat_v<T> || is_glm_vec_v<T>;
if constexpr (is_char)
{
int v = val;
sstream ss;
ss << v;
return ss.str();
}
else if constexpr (is_wstring && is_this_string)
{
return WstrToStr(val);
}
else if constexpr (is_string && is_this_wstring)
{
return StrToWstr(val);
}
else if constexpr (is_angle)
{
sstream strs;
strs.precision(std::numeric_limits<T>::digits10);
strs << std::fixed << val.asRadians();
return strs.str();
}
else if constexpr (is_vec_or_quat || is_angles || is_anycolor)
{
sstream strs;
for (int i = 0; i < val.length(); i++)
{
if constexpr (std::is_floating_point<typename T::value_type>::value)
{
strs.precision(std::numeric_limits<typename T::value_type>::digits10);
strs << std::fixed;
}
strs << val[i];
if (i != (val.length() - 1))
{
if constexpr (is_this_wstring)
{
strs << L' ';
}
else
{
strs << ' ';
}
}
}
return strs.str();
}
else if constexpr (is_double)
{
sstream strs;
strs.precision(std::numeric_limits<T>::digits10);
strs << std::fixed << val;
return strs.str();
}
else
{
sstream ss;
ss << val;
return ss.str();
}
}
}
namespace CommandPreprocess
{
void Trim(std::wstring& str);
void PreprocessEscapes(std::wstring& str);
void ReplaceEscapes(std::wstring& str);
std::vector<std::wstring> SplitCommands(const std::wstring& input);
std::vector<std::wstring> ParseArguments(const std::wstring& command);
std::vector<std::vector<std::wstring>> PreProcessString(std::wstring cmdline);
}
namespace ArgumentsPreprocess
{
void ReplaceEscapes(std::string& str);
std::vector<std::string> ParseArguments(std::string cmdline);
bool Compare(const std::string& str, const std::string& op, const std::string& arg);
}