#include "ppsspp_config.h" #ifdef _WIN32 #include #undef min #undef max #endif #if PPSSPP_PLATFORM(SWITCH) #define _GNU_SOURCE #include #endif #include #include #include #include #include #include #include #include #include "base/buffer.h" #include "base/stringutil.h" #ifdef _WIN32 void OutputDebugStringUTF8(const char *p) { wchar_t temp[4096]; int len = std::min(4095, (int)strlen(p)); int size = (int)MultiByteToWideChar(CP_UTF8, 0, p, len, NULL, 0); MultiByteToWideChar(CP_UTF8, 0, p, len, temp, size); temp[size] = 0; OutputDebugString(temp); } #else void OutputDebugStringUTF8(const char *p) { ILOG("%s", p); } #endif std::string LineNumberString(const std::string &str) { std::stringstream input(str); std::stringstream output; std::string line; int lineNumber = 1; while (std::getline(input, line)) { output << std::setw(4) << lineNumber++ << ": " << line << std::endl; } return output.str(); } void StringTrimEndNonAlphaNum(char *str) { ssize_t n = strlen(str); while (!isalnum(str[n]) && n >= 0) { str[n--] = '\0'; } } void SkipSpace(const char **ptr) { while (**ptr && isspace(**ptr)) { (*ptr)++; } } void StringUpper(char *str) { while (*str) { *str = toupper(*str); str++; } } void StringUpper(char *str, int len) { while (len--) { *str = toupper(*str); str++; } } void DataToHexString(const uint8_t *data, size_t size, std::string *output) { Buffer buffer; for (size_t i = 0; i < size; i++) { buffer.Printf("%02x ", data[i]); if (i && !(i & 15)) buffer.Printf("\n"); } buffer.TakeAll(output); } std::string StringFromFormat(const char* format, ...) { va_list args; std::string temp = ""; #ifdef _WIN32 int required = 0; va_start(args, format); required = _vscprintf(format, args); // Using + 2 to be safe between MSVC versions. // In MSVC 2015 and later, vsnprintf counts the trailing zero (per c++11.) temp.resize(required + 2); if (vsnprintf(&temp[0], required + 1, format, args) < 0) { temp.resize(0); } else { temp.resize(required); } va_end(args); #else char *buf = nullptr; va_start(args, format); if (vasprintf(&buf, format, args) < 0) buf = nullptr; va_end(args); if (buf != nullptr) { temp = buf; free(buf); } #endif return temp; } std::string StringFromInt(int value) { char temp[16]; sprintf(temp, "%i", value); return temp; } std::string StringFromBool(bool value) { return value ? "True" : "False"; } // Turns " hej " into "hej". Also handles tabs. std::string StripSpaces(const std::string &str) { const size_t s = str.find_first_not_of(" \t\r\n"); if (str.npos != s) return str.substr(s, str.find_last_not_of(" \t\r\n") - s + 1); else return ""; } // "\"hello\"" is turned to "hello" // This one assumes that the string has already been space stripped in both // ends, as done by StripSpaces above, for example. std::string StripQuotes(const std::string& s) { if (s.size() && '\"' == s[0] && '\"' == *s.rbegin()) return s.substr(1, s.size() - 2); else return s; } // For Debugging. Read out an u8 array. std::string ArrayToString(const uint8_t *data, uint32_t size, int line_len, bool spaces) { std::ostringstream oss; oss << std::setfill('0') << std::hex; for (int line = 0; size; ++data, --size) { oss << std::setw(2) << (int)*data; if (line_len == ++line) { oss << '\n'; line = 0; } else if (spaces) oss << ' '; } return oss.str(); } void SplitString(const std::string& str, const char delim, std::vector& output) { size_t next = 0; for (size_t pos = 0, len = str.length(); pos < len; ++pos) { if (str[pos] == delim) { output.push_back(str.substr(next, pos - next)); // Skip the delimiter itself. next = pos + 1; } } if (next == 0) { output.push_back(str); } else if (next < str.length()) { output.push_back(str.substr(next)); } } void GetQuotedStrings(const std::string& str, std::vector& output) { size_t next = 0; bool even = 0; for (size_t pos = 0, len = str.length(); pos < len; ++pos) { if (str[pos] == '\"' || str[pos] == '\'') { if (even) { //quoted text output.push_back(str.substr(next, pos - next)); even = 0; } else { //non quoted text even = 1; } // Skip the delimiter itself. next = pos + 1; } } } std::string ReplaceAll(std::string result, const std::string& src, const std::string& dest) { size_t pos = 0; if (src == dest) return result; while(1) { pos = result.find(src, pos); if (pos == result.npos) break; result.replace(pos, src.size(), dest); pos += dest.size(); } return result; } int strcmpIgnore(std::string str1, std::string str2, std::string ignorestr1, std::string ignorestr2) { str1 = ReplaceAll(str1, ignorestr1, ignorestr2); str2 = ReplaceAll(str2, ignorestr1, ignorestr2); return strcmp(str1.c_str(),str2.c_str()); }