#pragma once #include #include #include #include #include #include "data/file.hpp" #include "data/iterators.hpp" namespace devilution { /** * @brief A value reader. */ class ValueReader { public: ValueReader(DataFile &dataFile, std::string_view filename); DataFileField getValueField(std::string_view expectedKey); template void readValue(std::string_view expectedKey, T &outValue, F &&readFn) { DataFileField valueField = getValueField(expectedKey); if (const tl::expected result = readFn(valueField, outValue); !result.has_value()) { DataFile::reportFatalFieldError(result.error(), filename_, "Value", valueField); } ++it_; } template void read(std::string_view expectedKey, T &outValue, F &&parseFn) { readValue(expectedKey, outValue, [&parseFn](DataFileField &valueField, T &outValue) -> tl::expected { const auto result = parseFn(valueField.value()); if (!result.has_value()) { return tl::make_unexpected(devilution::DataFileField::Error::InvalidValue); } outValue = result.value(); return {}; }); } template void readEnumList(std::string_view expectedKey, T &outValue, F &&parseFn) { readValue(expectedKey, outValue, [&parseFn](DataFileField &valueField, T &outValue) -> tl::expected { const auto result = valueField.parseEnumList(outValue, std::forward(parseFn)); if (!result.has_value()) { return tl::make_unexpected(devilution::DataFileField::Error::InvalidValue); } return {}; }); } template typename std::enable_if_t, void> readInt(std::string_view expectedKey, T &outValue) { readValue(expectedKey, outValue, [](DataFileField &valueField, T &outValue) { return valueField.parseInt(outValue); }); } template typename std::enable_if_t, void> readDecimal(std::string_view expectedKey, T &outValue) { readValue(expectedKey, outValue, [](DataFileField &valueField, T &outValue) { return valueField.parseFixed6(outValue); }); } void readString(std::string_view expectedKey, std::string &outValue) { readValue(expectedKey, outValue, [](DataFileField &valueField, std::string &outValue) { outValue = valueField.value(); return tl::expected {}; }); } void readChar(std::string_view expectedKey, char &outValue) { readValue(expectedKey, outValue, [](DataFileField &valueField, char &outValue) -> tl::expected { if (valueField.value().size() != 1) { return tl::make_unexpected(devilution::DataFileField::Error::InvalidValue); } outValue = valueField.value().at(0); return {}; }); } private: RecordIterator it_; const RecordIterator end_; std::string_view filename_; }; } // namespace devilution