84 lines
2.7 KiB
C++
84 lines
2.7 KiB
C++
// game::data -- internal helper: typed reads of a Block's scalars that record
|
|
// a Problem when a value is present but has the wrong shape. Shared by the
|
|
// loaders; not part of the public API.
|
|
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <vector>
|
|
|
|
#include "game/data/block.h"
|
|
#include "game/data/common.h"
|
|
|
|
namespace game::data::detail {
|
|
|
|
class Fields {
|
|
public:
|
|
Fields(const Block& b, std::string file, std::vector<Problem>& problems)
|
|
: b_(b), file_(std::move(file)), problems_(problems) {}
|
|
|
|
const Block& block() const { return b_; }
|
|
|
|
// Last occurrence wins for every accessor (the rule for repeated scalar keys).
|
|
std::string str(std::string_view key) const { return b_.str(key); }
|
|
std::optional<std::string> opt_str(std::string_view key) const { return b_.opt_str(key); }
|
|
std::vector<std::string> strs(std::string_view key) const { return b_.strs(key); }
|
|
|
|
std::string required_str(std::string_view key) {
|
|
const Attr* a = b_.find(key);
|
|
if (!a) {
|
|
missing(key);
|
|
return {};
|
|
}
|
|
return a->value;
|
|
}
|
|
|
|
std::optional<std::int64_t> opt_int(std::string_view key) {
|
|
const Attr* a = b_.find(key);
|
|
if (!a) return std::nullopt;
|
|
auto v = a->as_int();
|
|
if (!v) bad(*a, "expected an integer");
|
|
return v;
|
|
}
|
|
|
|
std::optional<double> opt_double(std::string_view key) {
|
|
const Attr* a = b_.find(key);
|
|
if (!a) return std::nullopt;
|
|
auto v = a->as_double();
|
|
if (!v) bad(*a, "expected a number");
|
|
return v;
|
|
}
|
|
|
|
std::optional<bool> opt_bool(std::string_view key) {
|
|
const Attr* a = b_.find(key);
|
|
if (!a) return std::nullopt;
|
|
auto v = a->as_bool();
|
|
if (!v) bad(*a, "expected true/false or 0/1");
|
|
return v;
|
|
}
|
|
|
|
void missing(std::string_view key) {
|
|
problems_.push_back({Problem::Kind::MissingKey, file_, b_.line, std::string(key),
|
|
"required key `" + std::string(key) + "` missing in block `" + b_.name + "`"});
|
|
}
|
|
|
|
void bad(const Attr& a, std::string_view what) {
|
|
problems_.push_back({Problem::Kind::BadValue, file_, a.line, a.key,
|
|
std::string(what) + " for `" + a.key + "`, got `" + a.value + "`"});
|
|
}
|
|
|
|
void problem(Problem::Kind kind, int line, std::string key, std::string message) {
|
|
problems_.push_back({kind, file_, line, std::move(key), std::move(message)});
|
|
}
|
|
|
|
Fields sub(const Block& child) const { return Fields(child, file_, problems_); }
|
|
|
|
private:
|
|
const Block& b_;
|
|
std::string file_;
|
|
std::vector<Problem>& problems_;
|
|
};
|
|
|
|
} // namespace game::data::detail
|