#pragma once #include #include #include #include #include #include #include #include #include #include #include #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& ua); void split_str(const std::wstring& s, wchar_t delim, std::vector& ua); std::vector split_str(const std::string& s, char delim); std::vector split_str(const std::wstring& s, wchar_t delim); template String RemoveSpaces(const String& str, size_t stayBegin = 0, size_t stayEnd = 0) { using C = std::conditional_t, char, wchar_t>; constexpr C charspace = std::is_same_v ? ' ' : L' '; constexpr C chartab = std::is_same_v ? '\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(spacesAtBegin) - static_cast(stayBegin); int diffEnd = static_cast(spacesAtEnd) - static_cast(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 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 String merge_arg(const std::vector& 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) { if (i != start) { ret += L" "; } } else { if (i != start) { ret += " "; } } ret += vect.at(i); } return ret; } template 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 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 bool IsEmpty(const String& str) { if (str.empty()) { return true; } using C = std::conditional_t, char, wchar_t>; constexpr C charspace = std::is_same_v ? ' ' : L' '; constexpr C chartab = std::is_same_v ? '\t' : L'\t'; for (C b : str) { if (b != charspace && b != chartab) { return false; } } return true; } template 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 std::vector Split(String str) { std::vector ret; if constexpr (std::is_same_v) { 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) { 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 void Parse(Vec& vec, const String& str) { using sstream = std::conditional_t, 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 T FromStr(const String& str) //TODO glm::mat { using sstream = std::conditional_t, std::stringstream, std::wstringstream>; constexpr bool is_this_string = std::is_same_v; constexpr bool is_this_wstring = std::is_same_v; constexpr bool is_char = std::is_same::value || std::is_same::value; constexpr bool is_string = std::is_same::value; constexpr bool is_wstring = std::is_same::value; constexpr bool is_angle = std::is_same::value; constexpr bool is_angles = std::is_same::value; constexpr bool is_color = std::is_same::value; constexpr bool is_colorint = std::is_same::value; constexpr bool is_anycolor = is_color || is_colorint; constexpr bool is_quat = are_same_template::value; constexpr bool is_vec2 = are_same_template::value; constexpr bool is_vec3 = are_same_template::value; constexpr bool is_vec4 = are_same_template::value; constexpr bool is_ivec2 = are_same_template::value; constexpr bool is_ivec3 = are_same_template::value; constexpr bool is_ivec4 = are_same_template::value; constexpr bool is_uvec2 = are_same_template::value; constexpr bool is_uvec3 = are_same_template::value; constexpr bool is_uvec4 = are_same_template::value; constexpr bool is_vec_or_quat = is_glm_quat_v || is_glm_vec_v; constexpr bool is_bool = std::is_same::value; constexpr bool is_int8 = std::is_same::value; constexpr bool is_uint8 = std::is_same::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 String ToStr(const T& val) //TODO glm::mat { using sstream = std::conditional_t, std::stringstream, std::wstringstream>; constexpr bool is_int8 = std::is_same::value; constexpr bool is_uint8 = std::is_same::value; constexpr bool is_this_string = std::is_same_v; constexpr bool is_this_wstring = std::is_same_v; constexpr bool is_char = std::is_same::value || std::is_same::value; constexpr bool is_double = std::is_floating_point::value; constexpr bool is_string = std::is_same::value; constexpr bool is_wstring = std::is_same::value; constexpr bool is_angle = std::is_same::value; constexpr bool is_angles = std::is_same::value; constexpr bool is_quat = are_same_template::value; constexpr bool is_vec2 = are_same_template::value; constexpr bool is_vec3 = are_same_template::value; constexpr bool is_vec4 = are_same_template::value; constexpr bool is_ivec2 = are_same_template::value; constexpr bool is_ivec3 = are_same_template::value; constexpr bool is_ivec4 = are_same_template::value; constexpr bool is_uvec2 = are_same_template::value; constexpr bool is_uvec3 = are_same_template::value; constexpr bool is_uvec4 = are_same_template::value; constexpr bool is_color = std::is_same::value; constexpr bool is_colorint = std::is_same::value; constexpr bool is_anycolor = is_color || is_colorint; constexpr bool is_vec_or_quat = is_glm_quat_v || is_glm_vec_v; 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::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::value) { strs.precision(std::numeric_limits::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::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 SplitCommands(const std::wstring& input); std::vector ParseArguments(const std::wstring& command); std::vector> PreProcessString(std::wstring cmdline); } namespace ArgumentsPreprocess { void ReplaceEscapes(std::string& str); std::vector ParseArguments(std::string cmdline); bool Compare(const std::string& str, const std::string& op, const std::string& arg); }