#include #include "StringParser.hpp" #include "fmt/core.h" #include "fmt/ranges.h" #include "../Misc.hpp" namespace StringParser { std::string ParseItems::ToFmtString() { std::vector ret{}; int currFlagIndex = 0; for (const auto& i : items) { if (i.type == ParseItemType::FLAG) { ret.push_back(fmt::format("{{{}}}", currFlagIndex)); currFlagIndex++; } else { ret.push_back(i.content); } } return fmt::format("{}", fmt::join(ret, "")); } std::vector ParseItems::GetFlagValues() { std::vector ret{}; for (const auto& i : items) { if (i.type == ParseItemType::FLAG) { ret.push_back(i.content); } } return ret; } ParseItems ParseItems::parse(const std::string &str, bool parseTags) { static const std::unordered_set splitFlags = {u'0', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'+', u'+', u'-', u'-', u'%', u'%', u'.', u'×', u',', u','}; ParseItems result; if (str.contains("{")) { result.isValid = false; return result; } std::u16string origText = GakumasLocal::Misc::ToUTF16(str); bool isInTag = false; bool isInFlagSequence = false; std::u16string currentCacheText; for (char16_t currChar : origText) { if (parseTags && currChar == u'<') { if (!currentCacheText.empty()) { result.items.push_back({isInFlagSequence ? ParseItemType::FLAG : ParseItemType::TEXT, GakumasLocal::Misc::ToUTF8(currentCacheText)}); currentCacheText.clear(); isInFlagSequence = false; } isInTag = true; currentCacheText.push_back(currChar); } else if (parseTags && currChar == u'>') { isInTag = false; currentCacheText.push_back(currChar); result.items.push_back({ParseItemType::FLAG, GakumasLocal::Misc::ToUTF8(currentCacheText)}); currentCacheText.clear(); } else if (isInTag) { currentCacheText.push_back(currChar); } else if (splitFlags.contains(currChar)) { if (!isInFlagSequence && !currentCacheText.empty()) { result.items.push_back({ParseItemType::TEXT, GakumasLocal::Misc::ToUTF8(currentCacheText)}); currentCacheText.clear(); } isInFlagSequence = true; currentCacheText.push_back(currChar); } else { if (isInFlagSequence && !currentCacheText.empty()) { result.items.push_back({ParseItemType::FLAG, GakumasLocal::Misc::ToUTF8(currentCacheText)}); currentCacheText.clear(); isInFlagSequence = false; } currentCacheText.push_back(currChar); } } if (!currentCacheText.empty()) { result.items.push_back({isInFlagSequence ? ParseItemType::FLAG : ParseItemType::TEXT, GakumasLocal::Misc::ToUTF8(currentCacheText)}); } for (auto& i : result.items) { if (i.type == ParseItemType::FLAG) { return result; } } result.isValid = false; return result; } std::string ParseItems::MergeText(ParseItems &textTarget, ParseItems &valueTarget) { if (!textTarget.isValid) return ""; if (!valueTarget.isValid) return ""; const auto fmtText = textTarget.ToFmtString(); const auto values = valueTarget.GetFlagValues(); const std::string ret = GakumasLocal::Misc::StringFormat::stringFormatString(fmtText, values); return {ret.begin(), ret.end()}; } std::string ParseItems::MergeText(const std::string &newStr) { if (!isValid) return ""; const auto values = GetFlagValues(); return GakumasLocal::Misc::StringFormat::stringFormatString(newStr, values); } int ParseItems::GetFlagCount() { int ret = 0; for (auto& i : items) { if (i.type == ParseItemType::FLAG) { ret++; } } return ret; } }