git / moonbite-core / src/libmw/include/mw/util/StringUtil.h · raw

#pragma once// Copyright (c) 2018-2019 David Burkett// Distributed under the MIT software license, see the accompanying// file LICENSE or http://www.opensource.org/licenses/mit-license.php.#include <mw/common/Traits.h>#include <fmt/format.h>#include <memory>#include <iostream>#include <string>#include <cstdio>#include <cstdarg>#include <vector>#include <locale>#include <codecvt>#include <algorithm>#include <system_error>#include <util/strencodings.h>#ifdef _MSC_VER#pragma warning(disable : 4840)#endifclass StringUtil{public:    template<typename ... Args>    static std::string Format(const char* format, const Args& ... args)    {        return fmt::format(format, ConvertArg(args) ...);    }    static bool StartsWith(const std::string& value, const std::string& beginning)    {        if (beginning.size() > value.size()) {            return false;        }        return std::equal(beginning.begin(), beginning.end(), value.begin());    }    static bool EndsWith(const std::string& value, const std::string& ending)    {        if (ending.size() > value.size()) {            return false;        }        return std::equal(ending.rbegin(), ending.rend(), value.rbegin());    }    static std::vector<std::string> Split(const std::string& str, const std::string& delimiter)    {        // Skip delimiters at beginning.        std::string::size_type lastPos = str.find_first_not_of(delimiter, 0);        // Find first non-delimiter.        std::string::size_type pos = str.find_first_of(delimiter, lastPos);        std::vector<std::string> tokens;        while (std::string::npos != pos || std::string::npos != lastPos) {            // Found a token, add it to the vector.            tokens.push_back(str.substr(lastPos, pos - lastPos));            // Skip delimiters.            lastPos = str.find_first_not_of(delimiter, pos);            // Find next non-delimiter.            pos = str.find_first_of(delimiter, lastPos);        }        return tokens;    }    static std::string ToLower(const std::string& str)    {        std::locale loc;        std::string output = "";        for (char elem : str) {            output += std::tolower(elem, loc);        }        return output;    }    static std::string ToUTF8(const std::wstring& wstr)    {        std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;        return converter.to_bytes(wstr);    }    static std::wstring ToWide(const std::string& str)    {        std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;        return converter.from_bytes(str);    }    static std::string Trim(const std::string& s)    {        std::string copy = s;        // trim from start        copy.erase(copy.begin(), std::find_if(copy.begin(), copy.end(), [](char ch) {            return !IsSpace(ch);        }));        // trim from end (in place)        copy.erase(std::find_if(copy.rbegin(), copy.rend(), [](char ch) {            return !IsSpace(ch) && ch != '\r' && ch != '\n';        }).base(), copy.end());        return copy;    }private:    static std::string ConvertArg(const std::string& x)    {        return x;    }    static std::string ConvertArg(const char* x)    {        return std::string(x);    }    static std::string ConvertArg(const std::wstring& x)    {        return StringUtil::ToUTF8(x);    }    static std::string ConvertArg(const Traits::IPrintable& x)    {        return x.Format();    }    template <class T>    static std::string ConvertArg(const std::vector<T>& x)    {        std::string str;        for (const T& value : x) {            if (str.empty()) {                str += ConvertArg(value);            } else {                str += "," + ConvertArg(value);            }        }        return "[" + str + "]";    }    static std::string ConvertArg(const std::shared_ptr<const Traits::IPrintable>& x)    {        if (x == nullptr) {            return "NULL";        }        return x->Format();    }    static std::string ConvertArg(const std::exception& e)    {        return std::string(e.what());    }    static std::string ConvertArg(const std::error_code& ec)    {        return std::to_string(ec.value()) + " - " + ec.message();    }    template <class T, typename SFINAE = std::enable_if_t<std::is_fundamental<T>::value>>    static decltype(auto) ConvertArg(const T& x)    {        return x;    }};