From e49c604618c7b77e5ae5357abd8a1e3276c32772 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Sat, 16 Sep 2023 12:50:25 +0100 Subject: [PATCH] `LoadClassAttributes`: Mandate field order Makes parsing simpler. Additional columns and rows are ignored. --- Source/playerdat.cpp | 88 +++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 50 deletions(-) diff --git a/Source/playerdat.cpp b/Source/playerdat.cpp index f888e607f7f..bf1234c799c 100644 --- a/Source/playerdat.cpp +++ b/Source/playerdat.cpp @@ -11,8 +11,6 @@ #include #include #include -#include -#include #include #include @@ -169,65 +167,55 @@ void LoadClassAttributes(std::string_view classPath, ClassAttributes &out) DataFile::reportFatalError(result.error(), filename); } - struct KeyInfo { - std::variant out; - bool found = false; - }; - std::unordered_map keyToField { - { "baseStr", KeyInfo { &out.baseStr } }, - { "baseMag", KeyInfo { &out.baseMag } }, - { "baseDex", KeyInfo { &out.baseDex } }, - { "baseVit", KeyInfo { &out.baseVit } }, - { "maxStr", KeyInfo { &out.maxStr } }, - { "maxMag", KeyInfo { &out.maxMag } }, - { "maxDex", KeyInfo { &out.maxDex } }, - { "maxVit", KeyInfo { &out.maxVit } }, - { "blockBonus", KeyInfo { &out.blockBonus } }, - { "adjLife", KeyInfo { &out.adjLife } }, - { "adjMana", KeyInfo { &out.adjMana } }, - { "lvlLife", KeyInfo { &out.lvlLife } }, - { "lvlMana", KeyInfo { &out.lvlMana } }, - { "chrLife", KeyInfo { &out.chrLife } }, - { "chrMana", KeyInfo { &out.chrMana } }, - { "itmLife", KeyInfo { &out.itmLife } }, - { "itmMana", KeyInfo { &out.itmMana } }, - }; - for (DataFileRecord record : dataFile) { + auto recordIt = dataFile.begin(); + const auto recordEnd = dataFile.end(); + + const auto getValueField = [&](std::string_view expectedKey) { + if (recordIt == recordEnd) { + app_fatal(fmt::format("Missing field {} in {}", expectedKey, filename)); + } + DataFileRecord record = *recordIt; FieldIterator fieldIt = record.begin(); const FieldIterator endField = record.end(); const std::string_view key = (*fieldIt).value(); + if (key != expectedKey) { + app_fatal(fmt::format("Unexpected field in {}: got {}, expected {}", filename, key, expectedKey)); + } + ++fieldIt; if (fieldIt == endField) { DataFile::reportFatalError(DataFile::Error::NotEnoughColumns, filename); } - DataFileField valueField = *fieldIt; + return *fieldIt; + }; - auto mappingIt = keyToField.find(key); - if (mappingIt == keyToField.end()) { - app_fatal(fmt::format("Unknown field {} in {}", key, filename)); + const auto readRecord = [&](std::string_view expectedKey, auto &outValue) { + DataFileField valueField = getValueField(expectedKey); + const std::errc parseIntResult = valueField.parseInt(outValue); + if (parseIntResult != std::errc()) { + DataFile::reportFatalFieldError(parseIntResult, filename, "Value", valueField); } - KeyInfo &keyInfo = mappingIt->second; - if (keyInfo.found) { - app_fatal(fmt::format("Duplicate field {} in {}", key, filename)); - } - std::visit([&](auto *outField) { - auto parseIntResult = valueField.parseInt(*outField); - if (parseIntResult != std::errc()) { - DataFile::reportFatalFieldError(parseIntResult, filename, "Value", valueField); - } - }, - keyInfo.out); - keyInfo.found = true; - - ++fieldIt; - } + ++recordIt; + }; - for (const auto &[key, keyInfo] : keyToField) { - if (!keyInfo.found) { - app_fatal(fmt::format("Missing field {} in {}", key, filename)); - } - } + readRecord("baseStr", out.baseStr); + readRecord("baseMag", out.baseMag); + readRecord("baseDex", out.baseDex); + readRecord("baseVit", out.baseVit); + readRecord("maxStr", out.maxStr); + readRecord("maxMag", out.maxMag); + readRecord("maxDex", out.maxDex); + readRecord("maxVit", out.maxVit); + readRecord("blockBonus", out.blockBonus); + readRecord("adjLife", out.adjLife); + readRecord("adjMana", out.adjMana); + readRecord("lvlLife", out.lvlLife); + readRecord("lvlMana", out.lvlMana); + readRecord("chrLife", out.chrLife); + readRecord("chrMana", out.chrMana); + readRecord("itmLife", out.itmLife); + readRecord("itmMana", out.itmMana); } std::vector ClassAttributesPerClass;