You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

93 lines
2.6 KiB

#pragma once
#include <array>
#include <string_view>
#include <type_traits>
#include <expected.hpp>
#include <function_ref.hpp>
#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 <typename T, typename F>
void readValue(std::string_view expectedKey, T &outValue, F &&readFn)
{
DataFileField valueField = getValueField(expectedKey);
if (const tl::expected<void, devilution::DataFileField::Error> result = readFn(valueField, outValue);
!result.has_value()) {
DataFile::reportFatalFieldError(result.error(), filename_, "Value", valueField);
}
++it_;
}
template <typename T, typename F>
void read(std::string_view expectedKey, T &outValue, F &&parseFn)
{
readValue(expectedKey, outValue, [&parseFn](DataFileField &valueField, T &outValue) -> tl::expected<void, devilution::DataFileField::Error> {
const auto result = parseFn(valueField.value());
if (!result.has_value()) {
return tl::make_unexpected(devilution::DataFileField::Error::InvalidValue);
}
outValue = result.value();
return {};
});
}
template <typename T>
typename std::enable_if_t<std::is_integral_v<T>, void>
readInt(std::string_view expectedKey, T &outValue)
{
readValue(expectedKey, outValue, [](DataFileField &valueField, T &outValue) {
return valueField.parseInt(outValue);
});
}
template <typename T>
typename std::enable_if_t<std::is_integral_v<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, devilution::DataFileField::Error> {};
});
}
void readChar(std::string_view expectedKey, char &outValue)
{
readValue(expectedKey, outValue, [](DataFileField &valueField, char &outValue) -> tl::expected<void, devilution::DataFileField::Error> {
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