#include "utility/utilityString.h" #include #include #include #include #include namespace { template StringType doReplace(StringType str, const StringType& from, const StringType& to) { size_t pos = 0; if (from.size() == 0) { return str; } while ((pos = str.find(from, pos)) != std::string::npos) { str.replace(pos, from.length(), to); pos += to.length(); } return str; } template StringType doReplaceBetween(const StringType& str, typename StringType::value_type startDelimiter, typename StringType::value_type endDelimiter, const StringType& to) { size_t startPos = str.find(startDelimiter); if (startPos == StringType::npos) { return str; } size_t depth = 1; for (size_t pos = startPos + 1; pos < str.size(); pos++) { if (str[pos] == endDelimiter && depth) { depth--; if (depth == 0) { StringType end = doReplaceBetween(str.substr(pos + 1), startDelimiter, endDelimiter, to); return str.substr(0, startPos) + startDelimiter + to + endDelimiter + end; } } if (str[pos] == startDelimiter) { depth++; } } return str; } } namespace utility { std::string encodeToUtf8(const std::wstring& s) { return boost::locale::conv::utf_to_utf(s.c_str(), s.c_str() + s.size()); } std::wstring decodeFromUtf8(const std::string& s) { return boost::locale::conv::utf_to_utf(s.c_str(), s.c_str() + s.size()); } std::deque split(const std::string& str, char delimiter) { return split>(str, std::string(1, delimiter)); } std::deque split(const std::string& str, const std::string& delimiter) { return split>(str, delimiter); } std::vector splitToVector(const std::string& str, char delimiter) { return split>(str, std::string(1, delimiter)); } std::vector splitToVector(const std::string& str, const std::string& delimiter) { return split>(str, delimiter); } std::vector splitToVector(const std::wstring& str, wchar_t delimiter) { return split>(str, std::wstring(1, delimiter)); } std::vector splitToVector(const std::wstring& str, const std::wstring& delimiter) { return split>(str, delimiter); } std::string join(const std::deque& list, char delimiter) { return join >(list, std::string(1, delimiter)); } std::string join(const std::deque& list, const std::string& delimiter) { return join >(list, delimiter); } std::string join(const std::vector& list, char delimiter) { return join >(list, std::string(1, delimiter)); } std::string join(const std::vector& list, const std::string& delimiter) { return join >(list, delimiter); } std::deque tokenize(const std::string& str, char delimiter) { return tokenize(str, std::string(1, delimiter)); } std::deque tokenize(const std::string& str, const std::string& delimiter) { size_t pos = 0; size_t oldPos = 0; std::deque c; do { pos = str.find(delimiter, oldPos); if (pos != oldPos) { c.push_back(str.substr(oldPos, pos - oldPos)); } if (pos != std::string::npos) { c.push_back(str.substr(pos, delimiter.size())); } oldPos = pos + delimiter.size(); } while (pos != std::string::npos && oldPos < str.size()); return c; } std::deque tokenize(const std::deque& list, char delimiter) { return tokenize(list, std::string(1, delimiter)); } std::deque tokenize(const std::deque& list, const std::string& delimiter) { std::deque c; for (const std::string& str : list) { if (str.size()) { std::deque c2 = tokenize(str, delimiter); c.insert(c.end(), c2.begin(), c2.end()); } } return c; } std::string substrBeforeFirst(const std::string& str, char delimiter) { size_t pos = str.find(delimiter); if (pos != std::string::npos) { return str.substr(0, pos); } return str; } std::string substrBeforeFirst(const std::string& str, const std::string& delimiter) { size_t pos = str.find(delimiter); if (pos != std::string::npos) { return str.substr(0, pos); } return str; } std::string substrBeforeLast(const std::string& str, char delimiter) { size_t pos = str.rfind(delimiter); if (pos != std::string::npos) { return str.substr(0, pos); } return str; } std::wstring substrBeforeLast(const std::wstring& str, wchar_t delimiter) { size_t pos = str.rfind(delimiter); if (pos != std::wstring::npos) { return str.substr(0, pos); } return str; } std::wstring substrAfterLast(const std::wstring& str, wchar_t delimiter) { size_t pos = str.rfind(delimiter); if (pos != std::wstring::npos) { return str.substr(pos + 1, std::wstring::npos); } return str; } std::string substrAfter(const std::string& str, char delimiter) { size_t pos = str.find(delimiter); if (pos != std::string::npos) { return str.substr(pos + 1, std::wstring::npos); } return str; } std::string substrAfter(const std::string& str, const std::string& delimiter) { size_t pos = str.find(delimiter); if (pos != std::string::npos) { return str.substr(pos + delimiter.size(), str.size()); } return str; } std::string toUpperCase(const std::string& in) { std::string out; std::transform(in.begin(), in.end(), std::back_inserter(out), toupper); return out; } std::wstring toUpperCase(const std::wstring& in) { std::wstring out; std::transform(in.begin(), in.end(), std::back_inserter(out), towupper); return out; } std::string toLowerCase(const std::string& in) { std::string out; std::transform(in.begin(), in.end(), std::back_inserter(out), tolower); return out; } std::wstring toLowerCase(const std::wstring& in) { std::wstring out; std::transform(in.begin(), in.end(), std::back_inserter(out), towlower); return out; } std::string replace(std::string str, const std::string& from, const std::string& to) { return doReplace(str, from, to); } std::wstring replace(std::wstring str, const std::wstring& from, const std::wstring& to) { return doReplace(str, from, to); } std::string replaceBetween(const std::string& str, char startDelimiter, char endDelimiter, const std::string& to) { return doReplaceBetween(str, startDelimiter, endDelimiter, to); } std::wstring replaceBetween(const std::wstring& str, wchar_t startDelimiter, wchar_t endDelimiter, const std::wstring& to) { return doReplaceBetween(str, startDelimiter, endDelimiter, to); } std::string insertLineBreaksAtBlankSpaces(const std::string& s, size_t maxLineLength) { const std::vector atoms = splitToVector(s, " "); std::string ret = ""; std::string currentLine = ""; for (const std::string& atom: atoms) { if (currentLine.size() + 1 + atom.size() <= maxLineLength) { currentLine += " " + atom; } else { if (!ret.empty()) { ret += "\n"; } if (currentLine.empty()) { ret += atom; } else { ret += currentLine; currentLine = atom; } } } if (!currentLine.empty()) { if (!ret.empty()) { ret += "\n"; } ret += currentLine; } return ret; } std::wstring breakSignature( std::wstring returnPart, std::wstring namePart, std::wstring paramPart, size_t maxLineLength, size_t tabWidth) { namePart = L' ' + namePart; size_t totalSize = returnPart.size() + namePart.size() + paramPart.size(); if (totalSize <= maxLineLength) { return returnPart + namePart + paramPart; } if (!paramPart.empty()) { namePart += paramPart[0]; paramPart.erase(0, 1); } size_t parenPos = paramPart.rfind(L')'); std::wstring endPart; if (parenPos == 0) { namePart += paramPart; paramPart = L""; } else if (parenPos != std::wstring::npos) { endPart = paramPart.substr(parenPos); paramPart = paramPart.substr(0, parenPos); } if (!paramPart.empty() && paramPart.size() + tabWidth - endPart.size() > maxLineLength) { std::vector paramLines; while (true) { size_t parenCount = 0; bool split = false; for (size_t i = 0; i < paramPart.size(); i++) { const wchar_t c = paramPart[i]; if (parenCount == 0 && c == L',') { paramLines.push_back(paramPart.substr(0, i + 1)); paramPart = paramPart.substr(i + 2); split = true; break; } else if (c == L'<' || c == L'(') { parenCount++; } else if (c == L'>' || c == L')') { parenCount--; } } if (!split) { paramLines.push_back(paramPart); break; } } paramPart = L""; for (const std::wstring& str : paramLines) { paramPart += L"\n\t" + str; const size_t length = tabWidth + str.size(); maxLineLength = std::max(length, maxLineLength); } } else if (!paramPart.empty()) { paramPart = L"\n\t" + paramPart; } if (returnPart.size() + namePart.size() <= maxLineLength) { namePart = returnPart + namePart; returnPart = L""; } std::wstring sig; if (!returnPart.empty()) { sig += returnPart + L'\n'; } sig += namePart; if (!paramPart.empty()) { sig += paramPart; } if (!endPart.empty()) { sig += L'\n' + endPart; } return sig; } std::string trim(const std::string &str) { auto wsfront = std::find_if_not(str.begin(), str.end(), [](int c) { return std::isspace(c); }); auto wsback = std::find_if_not(str.rbegin(), str.rend(), [](int c) { return std::isspace(c); }).base(); return (wsback <= wsfront ? std::string() : std::string(wsfront, wsback)); } std::wstring trim(const std::wstring &str) { auto wsfront = std::find_if_not(str.begin(), str.end(), [](int c) { return std::isspace(c); }); auto wsback = std::find_if_not(str.rbegin(), str.rend(), [](int c) { return std::isspace(c); }).base(); return (wsback <= wsfront ? std::wstring() : std::wstring(wsfront, wsback)); } std::string elide(const std::string& str, ElideMode mode, size_t size) { if (str.size() <= size || str.size() <= 3) { return str; } switch (mode) { case ELIDE_LEFT: return "..." + str.substr(str.size() - size - 3, str.size()); case ELIDE_MIDDLE: return str.substr(0, size / 2 - 1) + "..." + str.substr(str.size() - (size / 2 - 2), str.size()); case ELIDE_RIGHT: return str.substr(0, size - 3) + "..."; } } std::wstring elide(const std::wstring& str, ElideMode mode, size_t size) { if (str.size() <= size || str.size() <= 3) { return str; } switch (mode) { case ELIDE_LEFT: return L"..." + str.substr(str.size() - size - 3, str.size()); case ELIDE_MIDDLE: return str.substr(0, size / 2 - 1) + L"..." + str.substr(str.size() - (size / 2 - 2), str.size()); case ELIDE_RIGHT: return str.substr(0, size - 3) + L"..."; } } }