diff options
author | Hop311 <hop3114@gmail.com> | 2023-09-08 18:12:22 +0200 |
---|---|---|
committer | Hop311 <hop3114@gmail.com> | 2023-09-08 18:12:22 +0200 |
commit | 7772f8871348b7b52cb0a478bb76df68d8799a07 (patch) | |
tree | fd8c4626b2cee69a9fe9250365af6b18eea63c70 /src/openvic/dataloader | |
parent | 7f9a9a8241ba81be9213e6606b8be4a48f1cbaab (diff) |
More refactoring and duplicate code removal
Diffstat (limited to 'src/openvic/dataloader')
-rw-r--r-- | src/openvic/dataloader/Dataloader.cpp | 288 | ||||
-rw-r--r-- | src/openvic/dataloader/Dataloader.hpp | 35 | ||||
-rw-r--r-- | src/openvic/dataloader/NodeTools.cpp | 256 | ||||
-rw-r--r-- | src/openvic/dataloader/NodeTools.hpp | 161 |
4 files changed, 0 insertions, 740 deletions
diff --git a/src/openvic/dataloader/Dataloader.cpp b/src/openvic/dataloader/Dataloader.cpp deleted file mode 100644 index 55994d3..0000000 --- a/src/openvic/dataloader/Dataloader.cpp +++ /dev/null @@ -1,288 +0,0 @@ -#include "Dataloader.hpp" - -#include "openvic/GameManager.hpp" -#include "openvic/utility/Logger.hpp" - -#include <openvic-dataloader/csv/Parser.hpp> -#include <openvic-dataloader/detail/CallbackOStream.hpp> -#include <openvic-dataloader/v2script/Parser.hpp> - -using namespace OpenVic; -using namespace OpenVic::NodeTools; -using namespace ovdl; - -bool Dataloader::set_roots(std::vector<std::filesystem::path> new_roots) { - if (!roots.empty()) { - Logger::error("Overriding existing dataloader roots!"); - roots.clear(); - } - bool ret = true; - for (std::reverse_iterator<std::vector<std::filesystem::path>::const_iterator> it = new_roots.crbegin(); it != new_roots.crend(); ++it) { - if (std::find(roots.begin(), roots.end(), *it) == roots.end()) { - if (std::filesystem::is_directory(*it)) { - Logger::info("Adding dataloader root: ", *it); - roots.push_back(*it); - } else { - Logger::error("Invalid dataloader root (must be an existing directory): ", *it); - ret = false; - } - } else { - Logger::error("Duplicate dataloader root: ", *it); - ret = false; - } - } - if (roots.empty()) { - Logger::error("Dataloader has no roots after attempting to add ", new_roots.size()); - ret = false; - } - return ret; -} - -std::filesystem::path Dataloader::lookup_file(std::filesystem::path const& path) const { - for (std::filesystem::path const& root : roots) { - const std::filesystem::path composed = root / path; - if (std::filesystem::is_regular_file(composed)) { - return composed; - } - } - Logger::error("Lookup for ", path, " failed!"); - return {}; -} - -const std::filesystem::path Dataloader::TXT = ".txt"; - -static bool contains_file_with_name(std::vector<std::filesystem::path> const& paths, - std::filesystem::path const& name) { - - for (std::filesystem::path const& path : paths) { - if (path.filename() == name) return true; - } - return false; -} - -std::vector<std::filesystem::path> Dataloader::lookup_files_in_dir(std::filesystem::path const& path, - std::filesystem::path const* extension) const { - - std::vector<std::filesystem::path> ret; - for (std::filesystem::path const& root : roots) { - const std::filesystem::path composed = root / path; - std::error_code ec; - for (std::filesystem::directory_entry const& entry : std::filesystem::directory_iterator { composed, ec }) { - if (entry.is_regular_file()) { - const std::filesystem::path file = entry; - if (extension == nullptr || file.extension() == *extension) { - if (!contains_file_with_name(ret, file.filename())) { - ret.push_back(file); - } - } - } - } - } - return ret; -} - -bool Dataloader::apply_to_files_in_dir(std::filesystem::path const& path, - std::function<bool(std::filesystem::path const&)> callback, - std::filesystem::path const* extension) const { - - bool ret = true; - for (std::filesystem::path const& file : lookup_files_in_dir(path, extension)) { - ret &= callback(file); - } - return ret; -} - -template<std::derived_from<detail::BasicParser> Parser, bool(Parser::*parse_func)()> -static Parser _run_ovdl_parser(std::filesystem::path const& path) { - Parser parser; - std::string buffer; - auto error_log_stream = ovdl::detail::CallbackStream { - [](void const* s, std::streamsize n, void* user_data) -> std::streamsize { - if (s != nullptr && n > 0 && user_data != nullptr) { - static_cast<std::string*>(user_data)->append(static_cast<char const*>(s), n); - return n; - } else { - Logger::error("Invalid input to parser error log callback: ", s, " / ", n, " / ", user_data); - return 0; - } - }, &buffer - }; - parser.set_error_log_to(error_log_stream); - parser.load_from_file(path); - if (!buffer.empty()) { - Logger::error("Parser load errors:\n\n", buffer, "\n"); - buffer.clear(); - } - if (parser.has_fatal_error() || parser.has_error()) { - Logger::error("Parser errors while loading ", path); - return parser; - } - if (!(parser.*parse_func)()) { - Logger::error("Parse function returned false!"); - } - if (!buffer.empty()) { - Logger::error("Parser parse errors:\n\n", buffer, "\n"); - buffer.clear(); - } - if (parser.has_fatal_error() || parser.has_error()) { - Logger::error("Parser errors while parsing ", path); - } - return parser; -} - -static v2script::Parser _parse_defines(std::filesystem::path const& path) { - return _run_ovdl_parser<v2script::Parser, &v2script::Parser::simple_parse>(path); -} - -static csv::Windows1252Parser _parse_csv(std::filesystem::path const& path) { - return _run_ovdl_parser<csv::Windows1252Parser, &csv::Windows1252Parser::parse_csv>(path); -} - -bool Dataloader::_load_pop_types(PopManager& pop_manager, std::filesystem::path const& pop_type_directory) const { - const bool ret = apply_to_files_in_dir(pop_type_directory, - [&pop_manager](std::filesystem::path const& file) -> bool { - return pop_manager.load_pop_type_file(file, _parse_defines(file).get_file_node()); - } - ); - if (!ret) { - Logger::error("Failed to load pop types!"); - } - pop_manager.lock_pop_types(); - return ret; -} - -bool Dataloader::_load_map_dir(Map& map, std::filesystem::path const& map_directory) const { - static const std::filesystem::path defaults_filename = "default.map"; - static const std::string default_definitions = "definition.csv"; - static const std::string default_provinces = "provinces.bmp"; - static const std::string default_positions = "positions.txt"; - static const std::string default_terrain = "terrain.bmp"; - static const std::string default_rivers = "rivers.bmp"; - static const std::string default_terrain_definition = "terrain.txt"; - static const std::string default_tree_definition = "trees.txt"; - static const std::string default_continent = "continent.txt"; - static const std::string default_adjacencies = "adjacencies.csv"; - static const std::string default_region = "region.txt"; - static const std::string default_region_sea = "region_sea.txt"; - static const std::string default_province_flag_sprite = "province_flag_sprites"; - - const v2script::Parser parser = _parse_defines(lookup_file(map_directory / defaults_filename)); - - std::vector<std::string_view> water_province_identifiers; - -#define APPLY_TO_MAP_PATHS(F) \ - F(definitions) F(provinces) F(positions) F(terrain) F(rivers) \ - F(terrain_definition) F(tree_definition) F(continent) F(adjacencies) \ - F(region) F(region_sea) F(province_flag_sprite) - -#define MAP_PATH_VAR(X) std::string_view X = default_##X; - APPLY_TO_MAP_PATHS(MAP_PATH_VAR) -#undef MAP_PATH_VAR - - bool ret = expect_dictionary_keys( - "max_provinces", ONE_EXACTLY, - expect_uint( - [&map](uint64_t val) -> bool { - if (Province::NULL_INDEX < val && val <= Province::MAX_INDEX) { - return map.set_max_provinces(val); - } - Logger::error("Invalid max province count ", val, " (out of valid range ", Province::NULL_INDEX, " < max_provinces <= ", Province::MAX_INDEX, ")"); - return false; - } - ), - "sea_starts", ONE_EXACTLY, - expect_list_reserve_length( - water_province_identifiers, - expect_identifier( - [&water_province_identifiers](std::string_view identifier) -> bool { - water_province_identifiers.push_back(identifier); - return true; - } - ) - ), - -#define MAP_PATH_DICT_ENTRY(X) \ - #X, ONE_EXACTLY, expect_string(assign_variable_callback(X)), - APPLY_TO_MAP_PATHS(MAP_PATH_DICT_ENTRY) -#undef MAP_PATH_DICT_ENTRY - -#undef APPLY_TO_MAP_PATHS - - "border_heights", ZERO_OR_ONE, success_callback, - "terrain_sheet_heights", ZERO_OR_ONE, success_callback, - "tree", ZERO_OR_ONE, success_callback, - "border_cutoff", ZERO_OR_ONE, success_callback - )(parser.get_file_node()); - - if (!ret) { - Logger::error("Failed to load map default file!"); - } - - if (!map.load_province_definitions(_parse_csv(lookup_file(map_directory / definitions)).get_lines())) { - Logger::error("Failed to load province definitions file!"); - ret = false; - } - - if (!map.set_water_province_list(water_province_identifiers)) { - Logger::error("Failed to set water provinces!"); - ret = false; - } - map.lock_water_provinces(); - - return ret; -} - -bool Dataloader::load_defines(GameManager& game_manager) const { - static const std::filesystem::path good_file = "common/goods.txt"; - static const std::filesystem::path pop_type_directory = "poptypes"; - static const std::filesystem::path graphical_culture_type_file = "common/graphicalculturetype.txt"; - static const std::filesystem::path culture_file = "common/cultures.txt"; - static const std::filesystem::path religion_file = "common/religion.txt"; - static const std::filesystem::path map_directory = "map"; - - bool ret = true; - - if (!game_manager.good_manager.load_good_file(_parse_defines(lookup_file(good_file)).get_file_node())) { - Logger::error("Failed to load goods!"); - ret = false; - } - if (!_load_pop_types(game_manager.pop_manager, pop_type_directory)) { - Logger::error("Failed to load pop types!"); - ret = false; - } - if (!game_manager.pop_manager.culture_manager.load_graphical_culture_type_file(_parse_defines(lookup_file(graphical_culture_type_file)).get_file_node())) { - Logger::error("Failed to load graphical culture types!"); - ret = false; - } - if (!game_manager.pop_manager.culture_manager.load_culture_file(_parse_defines(lookup_file(culture_file)).get_file_node())) { - Logger::error("Failed to load cultures!"); - ret = false; - } - if (!game_manager.pop_manager.religion_manager.load_religion_file(_parse_defines(lookup_file(religion_file)).get_file_node())) { - Logger::error("Failed to load religions!"); - ret = false; - } - if (!_load_map_dir(game_manager.map, map_directory)) { - Logger::error("Failed to load map!"); - ret = false; - } - - return ret; -} - -bool Dataloader::load_pop_history(GameManager& game_manager, std::filesystem::path const& path) const { - return apply_to_files_in_dir(path, - [&game_manager](std::filesystem::path const& file) -> bool { - return expect_dictionary( - [&game_manager](std::string_view province_key, ast::NodeCPtr province_node) -> bool { - Province* province = game_manager.map.get_province_by_identifier(province_key); - if (province == nullptr) { - Logger::error("Invalid province id: ", province_key); - return false; - } - return province->load_pop_list(game_manager.pop_manager, province_node); - } - )(_parse_defines(file).get_file_node()); - } - ); -} diff --git a/src/openvic/dataloader/Dataloader.hpp b/src/openvic/dataloader/Dataloader.hpp deleted file mode 100644 index f723803..0000000 --- a/src/openvic/dataloader/Dataloader.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include <filesystem> -#include <functional> -#include <vector> - -namespace OpenVic { - struct GameManager; - struct PopManager; - struct Map; - - class Dataloader { - std::vector<std::filesystem::path> roots; - - bool _load_pop_types(PopManager& pop_manager, std::filesystem::path const& pop_type_directory) const; - bool _load_map_dir(Map& map, std::filesystem::path const& map_directory) const; - - public: - Dataloader() = default; - - /* In reverse-load order, so base defines first and final loaded mod last */ - bool set_roots(std::vector<std::filesystem::path> new_roots); - - std::filesystem::path lookup_file(std::filesystem::path const& path) const; - static const std::filesystem::path TXT; - std::vector<std::filesystem::path> lookup_files_in_dir(std::filesystem::path const& path, - std::filesystem::path const* extension = &TXT) const; - bool apply_to_files_in_dir(std::filesystem::path const& path, - std::function<bool(std::filesystem::path const&)> callback, - std::filesystem::path const* extension = &TXT) const; - - bool load_defines(GameManager& game_manager) const; - bool load_pop_history(GameManager& game_manager, std::filesystem::path const& path) const; - }; -} diff --git a/src/openvic/dataloader/NodeTools.cpp b/src/openvic/dataloader/NodeTools.cpp deleted file mode 100644 index 499527f..0000000 --- a/src/openvic/dataloader/NodeTools.cpp +++ /dev/null @@ -1,256 +0,0 @@ -#include "NodeTools.hpp" - -#include <charconv> - -using namespace OpenVic; -using namespace OpenVic::NodeTools; - -template<typename T> -static node_callback_t _expect_type(std::function<bool(T const&)> callback) { - return [callback](ast::NodeCPtr node) -> bool { - if (node != nullptr) { - T const* cast_node = node->cast_to<T>(); - if (cast_node != nullptr) { - return callback(*cast_node); - } - Logger::error("Invalid node type ", node->get_type(), " when expecting ", T::get_type_static()); - } else { - Logger::error("Null node when expecting ", T::get_type_static()); - } - return false; - }; -} - -template<typename T = ast::AbstractStringNode> -requires(std::derived_from<T, ast::AbstractStringNode>) -static std::function<bool(T const&)> abstract_string_node_callback(std::function<bool(std::string_view)> callback) { - return [callback](T const& node) -> bool { - return callback(node._name); - }; -} - -node_callback_t NodeTools::expect_identifier(std::function<bool(std::string_view)> callback) { - return _expect_type<ast::IdentifierNode>(abstract_string_node_callback<ast::IdentifierNode>(callback)); -} - -node_callback_t NodeTools::expect_string(std::function<bool(std::string_view)> callback) { - return _expect_type<ast::StringNode>(abstract_string_node_callback<ast::StringNode>(callback)); -} - -node_callback_t NodeTools::expect_identifier_or_string(std::function<bool(std::string_view)> callback) { - return [callback](ast::NodeCPtr node) -> bool { - if (node != nullptr) { - ast::AbstractStringNode const* cast_node = node->cast_to<ast::IdentifierNode>(); - if (cast_node == nullptr) { - cast_node = node->cast_to<ast::StringNode>(); - } - if (cast_node != nullptr) { - return abstract_string_node_callback(callback)(*cast_node); - } - Logger::error("Invalid node type ", node->get_type(), " when expecting ", ast::IdentifierNode::get_type_static(), " or ", ast::StringNode::get_type_static()); - } else { - Logger::error("Null node when expecting ", ast::IdentifierNode::get_type_static(), " or ", ast::StringNode::get_type_static()); - } - return false; - }; -} - -node_callback_t NodeTools::expect_bool(std::function<bool(bool)> callback) { - return expect_identifier( - [callback](std::string_view identifier) -> bool { - if (identifier == "yes") { - return callback(true); - } else if (identifier == "no") { - return callback(false); - } - Logger::error("Invalid bool identifier text: ", identifier); - return false; - } - ); -} - -node_callback_t NodeTools::expect_int(std::function<bool(int64_t)> callback) { - return expect_identifier( - [callback](std::string_view identifier) -> bool { - bool successful = false; - const int64_t val = StringUtils::string_to_int64(identifier, &successful, 10); - if (successful) { - return callback(val); - } - Logger::error("Invalid int identifier text: ", identifier); - return false; - } - ); -} - -node_callback_t NodeTools::expect_uint(std::function<bool(uint64_t)> callback) { - return expect_identifier( - [callback](std::string_view identifier) -> bool { - bool successful = false; - const uint64_t val = StringUtils::string_to_uint64(identifier, &successful, 10); - if (successful) { - return callback(val); - } - Logger::error("Invalid uint identifier text: ", identifier); - return false; - } - ); -} - -node_callback_t NodeTools::expect_fixed_point(std::function<bool(FP)> callback) { - return expect_identifier( - [callback](std::string_view identifier) -> bool { - bool successful = false; - const FP val = FP::parse(identifier.data(), identifier.length(), &successful); - if (successful) { - return callback(val); - } - Logger::error("Invalid fixed point identifier text: ", identifier); - return false; - } - ); -} - -node_callback_t NodeTools::expect_colour(std::function<bool(colour_t)> callback) { - return [callback](ast::NodeCPtr node) -> bool { - colour_t col = NULL_COLOUR; - uint32_t components = 0; - bool ret = expect_list_of_length(3, - expect_fixed_point( - [&col, &components](FP val) -> bool { - components++; - col <<= 8; - if (val < 0 || val > 255) { - Logger::error("Invalid colour component: ", val); - return false; - } else { - if (val <= 1) val *= 255; - col |= val.to_int32_t(); - return true; - } - } - ) - )(node); - ret &= callback(col << 8 * (3 - components)); - return ret; - }; -} - -node_callback_t NodeTools::expect_date(std::function<bool(Date)> callback) { - return expect_identifier( - [callback](std::string_view identifier) -> bool { - bool successful = false; - const Date date = Date::from_string(identifier, &successful); - if (successful) { - return callback(date); - } - Logger::error("Invalid date identifier text: ", identifier); - return false; - } - ); -} - -node_callback_t NodeTools::expect_assign(key_value_callback_t callback) { - return _expect_type<ast::AssignNode>( - [callback](ast::AssignNode const& assign_node) -> bool { - return callback(assign_node._name, assign_node._initializer.get()); - } - ); -} - -node_callback_t NodeTools::expect_list_and_length(length_callback_t length_callback, node_callback_t callback) { - return _expect_type<ast::AbstractListNode>( - [length_callback, callback](ast::AbstractListNode const& list_node) -> bool { - std::vector<ast::NodeUPtr> const& list = list_node._statements; - bool ret = true; - size_t size = length_callback(list.size()); - if (size > list.size()) { - Logger::error("Trying to read more values than the list contains: ", size, " > ", list.size()); - size = list.size(); - ret = false; - } - std::for_each(list.begin(), list.begin() + size, - [callback, &ret](ast::NodeUPtr const& sub_node) -> void { - ret &= callback(sub_node.get()); - } - ); - return ret; - } - ); -} - -node_callback_t NodeTools::expect_list_of_length(size_t length, node_callback_t callback) { - return [length, callback](ast::NodeCPtr node) -> bool { - bool ret = true; - ret &= expect_list_and_length( - [length, &ret](size_t size) -> size_t { - if (size != length) { - Logger::error("List length ", size, " does not match expected length ", length); - ret = false; - if (length < size) return length; - } - return size; - }, - callback - )(node); - return ret; - }; -} - -node_callback_t NodeTools::expect_list(node_callback_t callback) { - return expect_list_and_length(default_length_callback, callback); -} - -node_callback_t NodeTools::expect_dictionary_and_length(length_callback_t length_callback, key_value_callback_t callback) { - return expect_list_and_length(length_callback, expect_assign(callback)); -} - -node_callback_t NodeTools::expect_dictionary(key_value_callback_t callback) { - return expect_dictionary_and_length(default_length_callback, callback); -} - -node_callback_t NodeTools::_expect_dictionary_keys_and_length(length_callback_t length_callback, bool allow_other_keys, key_map_t&& key_map) { - return [length_callback, allow_other_keys, key_map = std::move(key_map)](ast::NodeCPtr node) mutable -> bool { - bool ret = expect_dictionary_and_length( - length_callback, - [&key_map, allow_other_keys](std::string_view key, ast::NodeCPtr value) -> bool { - const key_map_t::iterator it = key_map.find(key); - if (it == key_map.end()) { - if (allow_other_keys) return true; - Logger::error("Invalid dictionary key: ", key); - return false; - } - dictionary_entry_t& entry = it->second; - if (++entry.count > 1 && !entry.can_repeat()) { - Logger::error("Invalid repeat of dictionary key: ", key); - return false; - } - return entry.callback(value); - } - )(node); - for (key_map_t::value_type const& key_entry : key_map) { - dictionary_entry_t const& entry = key_entry.second; - if (entry.must_appear() && entry.count < 1) { - Logger::error("Mandatory dictionary key not present: ", key_entry.first); - ret = false; - } - } - return ret; - }; -} - -node_callback_t NodeTools::name_list_callback(std::vector<std::string>& list) { - return expect_list_reserve_length( - list, - expect_identifier_or_string( - [&list](std::string_view str) -> bool { - if (!str.empty()) { - list.push_back(std::string { str }); - return true; - } - Logger::error("Empty identifier or string"); - return false; - } - ) - ); -} diff --git a/src/openvic/dataloader/NodeTools.hpp b/src/openvic/dataloader/NodeTools.hpp deleted file mode 100644 index daea8ce..0000000 --- a/src/openvic/dataloader/NodeTools.hpp +++ /dev/null @@ -1,161 +0,0 @@ -#pragma once - -#include <map> - -#include "openvic/types/Colour.hpp" -#include "openvic/types/Date.hpp" -#include "openvic/types/fixed_point/FP.hpp" - -#include <openvic-dataloader/v2script/AbstractSyntaxTree.hpp> - -namespace OpenVic { - namespace ast = ovdl::v2script::ast; - - namespace NodeTools { - - using node_callback_t = std::function<bool(ast::NodeCPtr)>; - constexpr bool success_callback(ast::NodeCPtr) { return true; } - - using key_value_callback_t = std::function<bool(std::string_view, ast::NodeCPtr)>; - - node_callback_t expect_identifier(std::function<bool(std::string_view)> callback); - node_callback_t expect_string(std::function<bool(std::string_view)> callback); - node_callback_t expect_identifier_or_string(std::function<bool(std::string_view)> callback); - node_callback_t expect_bool(std::function<bool(bool)> callback); - node_callback_t expect_int(std::function<bool(int64_t)> callback); - node_callback_t expect_uint(std::function<bool(uint64_t)> callback); - node_callback_t expect_fixed_point(std::function<bool(FP)> callback); - node_callback_t expect_colour(std::function<bool(colour_t)> callback); - node_callback_t expect_date(std::function<bool(Date)> callback); - node_callback_t expect_assign(key_value_callback_t callback); - - using length_callback_t = std::function<size_t(size_t)>; - constexpr size_t default_length_callback(size_t size) { return size; }; - - node_callback_t expect_list_and_length(length_callback_t length_callback, node_callback_t callback); - node_callback_t expect_list_of_length(size_t length, node_callback_t callback); - node_callback_t expect_list(node_callback_t callback); - - node_callback_t expect_dictionary_and_length(length_callback_t length_callback, key_value_callback_t callback); - node_callback_t expect_dictionary(key_value_callback_t callback); - - struct dictionary_entry_t { - const enum class expected_count_t : uint8_t { - _MUST_APPEAR = 0b01, - _CAN_REPEAT = 0b10, - - ZERO_OR_ONE = 0, - ONE_EXACTLY = _MUST_APPEAR, - ZERO_OR_MORE = _CAN_REPEAT, - ONE_OR_MORE = _MUST_APPEAR | _CAN_REPEAT - } expected_count; - const node_callback_t callback; - size_t count; - - dictionary_entry_t(expected_count_t new_expected_count, node_callback_t new_callback) - : expected_count { new_expected_count }, callback { new_callback }, count { 0 } {} - - constexpr bool must_appear() const { - return static_cast<uint8_t>(expected_count) & static_cast<uint8_t>(expected_count_t::_MUST_APPEAR); - } - constexpr bool can_repeat() const { - return static_cast<uint8_t>(expected_count) & static_cast<uint8_t>(expected_count_t::_CAN_REPEAT); - } - }; - using enum dictionary_entry_t::expected_count_t; - using key_map_t = std::map<std::string, dictionary_entry_t, std::less<void>>; - - constexpr struct allow_other_keys_t {} ALLOW_OTHER_KEYS; - - node_callback_t _expect_dictionary_keys_and_length(length_callback_t length_callback, bool allow_other_keys, key_map_t&& key_map); - - template<typename... Args> - node_callback_t _expect_dictionary_keys_and_length(length_callback_t length_callback, - bool allow_other_keys, key_map_t&& key_map, - const std::string_view key, dictionary_entry_t::expected_count_t expected_count, node_callback_t callback, - Args... args) { - if (key_map.find(key) == key_map.end()) { - key_map.emplace(key, dictionary_entry_t { expected_count, callback }); - } else { - Logger::error("Duplicate expected dictionary key: ", key); - } - return _expect_dictionary_keys_and_length(length_callback, allow_other_keys, std::move(key_map), args...); - } - - template<typename... Args> - node_callback_t expect_dictionary_keys_and_length(length_callback_t length_callback, - const std::string_view key, dictionary_entry_t::expected_count_t expected_count, node_callback_t callback, - Args... args) { - return _expect_dictionary_keys_and_length(length_callback, false, {}, key, expected_count, callback, args...); - } - - template<typename... Args> - node_callback_t expect_dictionary_keys_and_length(length_callback_t length_callback, - allow_other_keys_t, Args... args) { - return _expect_dictionary_keys_and_length(length_callback, true, {}, args...); - } - - template<typename... Args> - node_callback_t expect_dictionary_keys(Args... args) { - return expect_dictionary_keys_and_length(default_length_callback, args...); - } - - template<typename T> - concept Reservable = requires(T& t) { - { t.size() } -> std::same_as<size_t>; - t.reserve( size_t {} ); - }; - template<Reservable T> - node_callback_t expect_list_reserve_length(T& t, node_callback_t callback) { - return expect_list_and_length( - [&t](size_t size) -> size_t { - t.reserve(t.size() + size); - return size; - }, - callback - ); - } - template<Reservable T> - node_callback_t expect_dictionary_reserve_length(T& t, key_value_callback_t callback) { - return expect_list_reserve_length(t, expect_assign(callback)); - } - - node_callback_t name_list_callback(std::vector<std::string>& list); - - template<typename T> - std::function<bool(T)> assign_variable_callback(T& var) { - return [&var](T val) -> bool { - var = val; - return true; - }; - } - - template<typename T> - requires(std::integral<T>) - std::function<bool(uint64_t)> assign_variable_callback_uint(const std::string_view name, T& var) { - return [&var, name](uint64_t val) -> bool { - if (val <= std::numeric_limits<T>::max()) { - var = val; - return true; - } - Logger::error("Invalid ", name, ": ", val, " (valid range: [0, ", static_cast<uint64_t>(std::numeric_limits<T>::max()), "])"); - return false; - }; - } - - template<typename T> - requires(std::integral<T>) - std::function<bool(int64_t)> assign_variable_callback_int(const std::string_view name, T& var) { - return [&var, name](int64_t val) -> bool { - if (std::numeric_limits<T>::lowest() <= val && val <= std::numeric_limits<T>::max()) { - var = val; - return true; - } - Logger::error("Invalid ", name, ": ", val, " (valid range: [", - static_cast<int64_t>(std::numeric_limits<T>::lowest()), ", ", - static_cast<uint64_t>(std::numeric_limits<T>::max()), "])"); - return false; - }; - } - } -} |