forked from chinosk/gkms-local
124 lines
4.6 KiB
C++
124 lines
4.6 KiB
C++
#include <unordered_set>
|
||
#include "StringParser.hpp"
|
||
#include "fmt/core.h"
|
||
#include "fmt/ranges.h"
|
||
#include "../Misc.hpp"
|
||
|
||
namespace StringParser {
|
||
|
||
std::string ParseItems::ToFmtString() {
|
||
std::vector<std::string> 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<std::string> ParseItems::GetFlagValues() {
|
||
std::vector<std::string> 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<char16_t> 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;
|
||
}
|
||
|
||
}
|