From 3cd1d62ec00690a1b29070dd4903754e8f089a21 Mon Sep 17 00:00:00 2001 From: Hop311 Date: Wed, 6 Sep 2023 23:54:09 +0100 Subject: NodeTools cleanup+province definition csv loading --- src/openvic/dataloader/NodeTools.hpp | 169 ++++++++++++++++++++++++++++------- 1 file changed, 136 insertions(+), 33 deletions(-) (limited to 'src/openvic/dataloader/NodeTools.hpp') diff --git a/src/openvic/dataloader/NodeTools.hpp b/src/openvic/dataloader/NodeTools.hpp index 48c3710..6dbaa1c 100644 --- a/src/openvic/dataloader/NodeTools.hpp +++ b/src/openvic/dataloader/NodeTools.hpp @@ -14,46 +14,149 @@ namespace OpenVic { namespace NodeTools { + using node_callback_t = std::function; + constexpr return_t success_callback(ast::NodeCPtr) { return SUCCESS; } + + using key_value_callback_t = std::function; + + node_callback_t expect_identifier(std::function callback); + node_callback_t expect_string(std::function callback); + node_callback_t expect_identifier_or_string(std::function callback); + node_callback_t expect_bool(std::function callback); + node_callback_t expect_int(std::function callback); + node_callback_t expect_uint(std::function callback); + node_callback_t expect_fixed_point(std::function callback); + node_callback_t expect_colour(std::function callback); + node_callback_t expect_date(std::function callback); + node_callback_t expect_assign(key_value_callback_t callback); + + using length_callback_t = std::function; + 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(expected_count) & static_cast(expected_count_t::_MUST_APPEAR); + } + constexpr bool can_repeat() const { + return static_cast(expected_count) & static_cast(expected_count_t::_CAN_REPEAT); + } + }; + using enum dictionary_entry_t::expected_count_t; + using key_map_t = std::map>; + + 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 + 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 + 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 + 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 + node_callback_t expect_dictionary_keys(Args... args) { + return expect_dictionary_keys_and_length(default_length_callback, args...); + } + template - return_t expect_type(ast::NodeCPtr node, std::function callback); - - return_t expect_identifier(ast::NodeCPtr node, std::function callback); - return_t expect_string(ast::NodeCPtr node, std::function callback); - return_t expect_identifier_or_string(ast::NodeCPtr node, std::function callback); - return_t expect_bool(ast::NodeCPtr node, std::function callback); - return_t expect_int(ast::NodeCPtr node, std::function callback); - return_t expect_uint(ast::NodeCPtr node, std::function callback); - return_t expect_fixed_point(ast::NodeCPtr node, std::function callback); - return_t expect_colour(ast::NodeCPtr node, std::function callback); - return_t expect_date(ast::NodeCPtr node, std::function callback); - return_t expect_assign(ast::NodeCPtr node, std::function callback); - - static const std::function default_length_callback = [](size_t size) -> size_t { return size; }; - - template requires requires(T& t) { + concept Reservable = requires(T& t) { { t.size() } -> std::same_as; t.reserve( size_t {} ); + }; + template + 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 + ); } - std::function reserve_length_callback(T& t) { - return [&t](size_t size) -> size_t { - t.reserve(t.size() + size); - return size; - }; + template + node_callback_t expect_dictionary_reserve_length(T& t, key_value_callback_t callback) { + return expect_list_reserve_length(t, expect_assign(callback)); } - return_t expect_list_and_length(ast::NodeCPtr node, std::function length_callback, std::function callback, bool file_node = false); - return_t expect_list_of_length(ast::NodeCPtr node, std::function callback, size_t length, bool file_node = false); - return_t expect_list(ast::NodeCPtr node, std::function callback, bool file_node = false); - return_t expect_dictionary_and_length(ast::NodeCPtr node, std::function length_callback, std::function callback, bool file_node = false); - return_t expect_dictionary(ast::NodeCPtr node, std::function callback, bool file_node = false); + node_callback_t name_list_callback(std::vector& list); + + template + std::function assign_variable_callback(T& var) { + return [&var](T val) -> return_t { + var = val; + return SUCCESS; + }; + } - static const std::function success_callback = [](ast::NodeCPtr) -> return_t { return SUCCESS; }; + template + requires(std::integral) + std::function assign_variable_callback_uint(const std::string_view name, T& var) { + return [&var, name](uint64_t val) -> return_t { + if (val <= std::numeric_limits::max()) { + var = val; + return SUCCESS; + } + Logger::error("Invalid ", name, ": ", val, " (valid range: [0, ", static_cast(std::numeric_limits::max()), "])"); + return FAILURE; + }; + } - struct dictionary_entry_t { - bool must_appear, can_repeat; - std::function callback; - }; - using dictionary_key_map_t = std::map>; - return_t expect_dictionary_keys(ast::NodeCPtr node, dictionary_key_map_t const& keys, bool allow_other_keys = false, bool file_node = false); + template + requires(std::integral) + std::function assign_variable_callback_int(const std::string_view name, T& var) { + return [&var, name](int64_t val) -> return_t { + if (std::numeric_limits::lowest() <= val && val <= std::numeric_limits::max()) { + var = val; + return SUCCESS; + } + Logger::error("Invalid ", name, ": ", val, " (valid range: [", + static_cast(std::numeric_limits::lowest()), ", ", + static_cast(std::numeric_limits::max()), "])"); + return FAILURE; + }; + } } } -- cgit v1.2.3-56-ga3b1