mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Support old message placeholder syntax
This allows the next release of libloot to be used with existing masterlists and userlists, and they can then be converted to the new syntax before a future libloot release drops support for the old syntax. While it's based on Boost.Format's syntax, which is more complex than supported by this commit, the masterlist syntax docs only mentioned and gave examples of what is supported by this commit, and the masterlists only contain placeholders %1%, %2% and %3%.
This commit is contained in:
@@ -110,10 +110,38 @@ struct convert<loot::Message> {
|
||||
formatArgStore.push_back(sub);
|
||||
}
|
||||
|
||||
static const std::regex boostSyntax(
|
||||
"%(\\d+)%", std::regex::ECMAScript | std::regex::icase);
|
||||
|
||||
for (auto& mc : content) {
|
||||
// Replace the old Boost.Format placeholder syntax for backward
|
||||
// compatibility. To be removed after at least one major release of
|
||||
// libloot to allow migration to the new syntax.
|
||||
auto text = mc.GetText();
|
||||
std::smatch match;
|
||||
while (
|
||||
std::regex_search(text.cbegin(), text.cend(), match, boostSyntax)) {
|
||||
if (match.size() > 1) {
|
||||
const auto n = std::stoul(match[1]);
|
||||
if (n > 0) {
|
||||
const auto newPlaceholder = "{" + std::to_string(n - 1) + "}";
|
||||
text.replace(match[0].first, match[0].second, newPlaceholder);
|
||||
} else {
|
||||
throw RepresentationException(
|
||||
node.Mark(),
|
||||
"bad conversion: found zero-indexed placeholder using old "
|
||||
"syntax");
|
||||
}
|
||||
} else {
|
||||
throw RepresentationException(node.Mark(),
|
||||
"bad conversion: only partially "
|
||||
"matched old placeholder syntax");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const auto text = fmt::vformat(mc.GetText(), formatArgStore);
|
||||
mc = loot::MessageContent(text, mc.GetLanguage());
|
||||
const auto formattedText = fmt::vformat(text, formatArgStore);
|
||||
mc = loot::MessageContent(formattedText, mc.GetLanguage());
|
||||
} catch (const fmt::format_error& e) {
|
||||
throw RepresentationException(
|
||||
node.Mark(),
|
||||
|
||||
@@ -669,6 +669,28 @@ TEST_P(MessageTest,
|
||||
message.GetContent());
|
||||
}
|
||||
|
||||
TEST_P(MessageTest, decodingFromYamlShouldAcceptPercentagePlaceholderSyntax) {
|
||||
YAML::Node node = YAML::Load(
|
||||
"type: say\n"
|
||||
"content: content %1% %2% %3% %4% %5% %6% %7% %8% %9% %10% %11%\n"
|
||||
"subs:\n"
|
||||
" - a\n"
|
||||
" - b\n"
|
||||
" - c\n"
|
||||
" - d\n"
|
||||
" - e\n"
|
||||
" - f\n"
|
||||
" - g\n"
|
||||
" - h\n"
|
||||
" - i\n"
|
||||
" - j\n"
|
||||
" - k");
|
||||
Message message = node.as<Message>();
|
||||
|
||||
ASSERT_EQ(1, message.GetContent().size());
|
||||
EXPECT_EQ("content a b c d e f g h i j k", message.GetContent()[0].GetText());
|
||||
}
|
||||
|
||||
TEST_P(MessageTest, decodingFromYamlShouldThrowIfAnInvalidConditionIsGiven) {
|
||||
YAML::Node node = YAML::Load(
|
||||
"type: say\n"
|
||||
|
||||
Reference in New Issue
Block a user