#pragma once #ifndef MANGOHUD_STRING_UTILS_H #define MANGOHUD_STRING_UTILS_H #include #include #include #include #include #include #include #include #include #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" // https://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring#217605 // 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); })); } // 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()); } // trim from both ends (in place) static inline void trim(std::string &s) { ltrim(s); rtrim(s); } // 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; } static bool starts_with(const std::string& s, const char *t) { return s.rfind(t, 0) == 0; } static bool ends_with(const std::string& s, const char *t, bool icase = false) { std::string s0(s); std::string s1(t); if (s0.size() < s1.size()) return false; if (icase) { std::transform(s0.begin(), s0.end(), s0.begin(), ::tolower); std::transform(s1.begin(), s1.end(), s1.begin(), ::tolower); } size_t pos = s0.size() - s1.size(); return (s0.rfind(s1, pos) == pos); } template static std::string itox(T i) { std::stringstream ss; ss << "0x" << std::setfill ('0') << std::setw(sizeof(T) * 2) << std::hex << i; return ss.str(); } static bool try_stoi(int& val, const std::string& str) { if (sscanf(str.c_str(), "%d", &val) == 1) return true; return false; } static bool try_stoull(unsigned long long& val, const std::string& str) { if (sscanf(str.c_str(), "%llu", &val) == 1) return true; return false; } static float parse_float(const std::string& s, std::size_t* float_len = nullptr){ std::stringstream ss(s); ss.imbue(std::locale::classic()); float ret; ss >> ret; if(ss.fail()) throw std::invalid_argument("parse_float: Not a float"); if(float_len != nullptr){ auto pos = ss.tellg(); if(ss.fail()) *float_len = s.size(); else *float_len = pos; } return ret; } static std::vector str_tokenize(const std::string& s, const std::string& delims = ",:+") { std::vector v; size_t old_n = 0, new_n = 0; while (old_n < s.size()){ new_n = s.find_first_of(delims, old_n); auto c = s.substr(old_n, new_n - old_n); if (old_n != new_n) v.push_back(c); if (new_n == std::string::npos) break; old_n = new_n + 1; } return v; } static void trim_char(char* str) { if(!str) return; char* ptr = str; int len = strlen(ptr); while(len-1 > 0 && isspace(ptr[len-1])) ptr[--len] = 0; while(*ptr && isspace(*ptr)) ++ptr, --len; memmove(str, ptr, len + 1); } #pragma GCC diagnostic pop #endif //MANGOHUD_STRING_UTILS_H