From 14ba9531d118fab87b360db4aae765807fca3cec Mon Sep 17 00:00:00 2001 From: hop311 Date: Wed, 24 Jan 2024 23:28:09 +0000 Subject: Added StringMapCase and case insensitive expect_dictionary_keys --- src/openvic-simulation/dataloader/NodeTools.hpp | 183 +++++++++++++++++------- 1 file changed, 135 insertions(+), 48 deletions(-) (limited to 'src/openvic-simulation/dataloader/NodeTools.hpp') diff --git a/src/openvic-simulation/dataloader/NodeTools.hpp b/src/openvic-simulation/dataloader/NodeTools.hpp index 9137d6a..54b61d0 100644 --- a/src/openvic-simulation/dataloader/NodeTools.hpp +++ b/src/openvic-simulation/dataloader/NodeTools.hpp @@ -14,21 +14,11 @@ #include "openvic-simulation/types/HasIdentifier.hpp" #include "openvic-simulation/types/OrderedContainers.hpp" #include "openvic-simulation/types/Vector.hpp" +#include "openvic-simulation/utility/TslHelper.hpp" namespace OpenVic { namespace ast = ovdl::v2script::ast; - /* Template for map from strings to Ts, in which string_views can be - * searched for without needing to be copied into a string */ - template, class KeyEqual = std::equal_to<>> - using string_map_t = ordered_map; - template - using case_insensitive_string_map_t = string_map_t; - - /* String set type supporting heterogeneous key lookup */ - using string_set_t = ordered_set; - using case_insensitive_string_set_t = case_insensitive_ordered_set; - using name_list_t = std::vector; std::ostream& operator<<(std::ostream& stream, name_list_t const& name_list); @@ -178,22 +168,80 @@ namespace OpenVic { } }; using enum dictionary_entry_t::expected_count_t; - using key_map_t = string_map_t; + template + using template_key_map_t = template_string_map_t; + + using key_map_t = template_key_map_t; + using case_insensitive_key_map_t = template_key_map_t; + + template bool add_key_map_entry( - key_map_t& key_map, std::string_view key, dictionary_entry_t::expected_count_t expected_count, - node_callback_t callback - ); - bool remove_key_map_entry(key_map_t& key_map, std::string_view key); - key_value_callback_t dictionary_keys_callback(key_map_t& key_map, key_value_callback_t default_callback); - bool check_key_map_counts(key_map_t& key_map); + template_key_map_t& key_map, std::string_view key, dictionary_entry_t::expected_count_t expected_count, + NodeCallback auto callback + ) { + if (!key_map.contains(key)) { + key_map.emplace(key, dictionary_entry_t { expected_count, callback }); + return true; + } + Logger::error("Duplicate expected dictionary key: ", key); + return false; + } - constexpr bool add_key_map_entries(key_map_t& key_map) { + template + bool remove_key_map_entry(template_key_map_t& key_map, std::string_view key) { + if (key_map.erase(key) == 0) { + Logger::error("Failed to find dictionary key to remove: ", key); + return false; + } return true; } - template + + template + KeyValueCallback auto dictionary_keys_callback( + template_key_map_t& key_map, KeyValueCallback auto default_callback + ) { + return [&key_map, default_callback](std::string_view key, ast::NodeCPtr value) -> bool { + typename template_key_map_t::iterator it = key_map.find(key); + if (it == key_map.end()) { + return default_callback(key, value); + } + dictionary_entry_t& entry = it.value(); + if (++entry.count > 1 && !entry.can_repeat()) { + Logger::error("Invalid repeat of dictionary key: ", key); + return false; + } + if (entry.callback(value)) { + return true; + } else { + Logger::error("Callback failed for dictionary key: ", key); + return false; + } + }; + } + + template + bool check_key_map_counts(template_key_map_t& key_map) { + bool ret = true; + for (auto key_entry : mutable_iterator(key_map)) { + dictionary_entry_t& entry = key_entry.second; + if (entry.must_appear() && entry.count < 1) { + Logger::error("Mandatory dictionary key not present: ", key_entry.first); + ret = false; + } + entry.count = 0; + } + return ret; + } + + template + constexpr bool add_key_map_entries(template_key_map_t& key_map) { + return true; + } + + template bool add_key_map_entries( - key_map_t& key_map, std::string_view key, dictionary_entry_t::expected_count_t expected_count, + template_key_map_t& key_map, std::string_view key, dictionary_entry_t::expected_count_t expected_count, NodeCallback auto callback, Args... args ) { bool ret = add_key_map_entry(key_map, key, expected_count, callback); @@ -201,43 +249,81 @@ namespace OpenVic { return ret; } - node_callback_t expect_dictionary_key_map_and_length_and_default( - key_map_t key_map, length_callback_t length_callback, key_value_callback_t default_callback - ); - node_callback_t expect_dictionary_key_map_and_length(key_map_t key_map, length_callback_t length_callback); - node_callback_t expect_dictionary_key_map_and_default(key_map_t key_map, key_value_callback_t default_callback); - node_callback_t expect_dictionary_key_map(key_map_t key_map); + template + NodeCallback auto expect_dictionary_key_map_and_length_and_default( + template_key_map_t key_map, LengthCallback auto length_callback, KeyValueCallback auto default_callback + ) { + return [length_callback, default_callback, key_map = std::move(key_map)](ast::NodeCPtr node) mutable -> bool { + bool ret = expect_dictionary_and_length( + length_callback, dictionary_keys_callback(key_map, default_callback) + )(node); + ret &= check_key_map_counts(key_map); + return ret; + }; + } - template + template + NodeCallback auto expect_dictionary_key_map_and_length( + template_key_map_t key_map, LengthCallback auto length_callback + ) { + return expect_dictionary_key_map_and_length_and_default( + std::move(key_map), length_callback, key_value_invalid_callback + ); + } + + template + NodeCallback auto expect_dictionary_key_map_and_default( + template_key_map_t key_map, KeyValueCallback auto default_callback + ) { + return expect_dictionary_key_map_and_length_and_default( + std::move(key_map), default_length_callback, default_callback + ); + } + + template + NodeCallback auto expect_dictionary_key_map(template_key_map_t key_map) { + return expect_dictionary_key_map_and_length_and_default( + std::move(key_map), default_length_callback, key_value_invalid_callback + ); + } + + template NodeCallback auto expect_dictionary_key_map_and_length_and_default( - key_map_t key_map, length_callback_t length_callback, key_value_callback_t default_callback, Args... args + template_key_map_t key_map, LengthCallback auto length_callback, KeyValueCallback auto default_callback, + Args... args ) { // TODO - pass return value back up (part of big key_map_t rewrite?) add_key_map_entries(key_map, args...); return expect_dictionary_key_map_and_length_and_default(std::move(key_map), length_callback, default_callback); } - template + template NodeCallback auto expect_dictionary_keys_and_length_and_default( LengthCallback auto length_callback, KeyValueCallback auto default_callback, Args... args ) { - return expect_dictionary_key_map_and_length_and_default({}, length_callback, default_callback, args...); + return expect_dictionary_key_map_and_length_and_default( + template_key_map_t {}, length_callback, default_callback, args... + ); } - template + template NodeCallback auto expect_dictionary_keys_and_length(LengthCallback auto length_callback, Args... args) { - return expect_dictionary_key_map_and_length_and_default({}, length_callback, key_value_invalid_callback, args...); + return expect_dictionary_key_map_and_length_and_default( + template_key_map_t {}, length_callback, key_value_invalid_callback, args... + ); } - template + template NodeCallback auto expect_dictionary_keys_and_default(KeyValueCallback auto default_callback, Args... args) { - return expect_dictionary_key_map_and_length_and_default({}, default_length_callback, default_callback, args...); + return expect_dictionary_key_map_and_length_and_default( + template_key_map_t {}, default_length_callback, default_callback, args... + ); } - template + template NodeCallback auto expect_dictionary_keys(Args... args) { return expect_dictionary_key_map_and_length_and_default( - {}, default_length_callback, key_value_invalid_callback, args... + template_key_map_t {}, default_length_callback, key_value_invalid_callback, args... ); } @@ -253,41 +339,42 @@ namespace OpenVic { NodeCallback auto expect_dictionary_reserve_length(Reservable auto& reservable, KeyValueCallback auto callback) { return expect_dictionary_and_length(reserve_length_callback(reservable), callback); } - template + template NodeCallback auto expect_dictionary_key_map_reserve_length_and_default( - Reservable auto& reservable, key_map_t key_map, KeyValueCallback auto default_callback, Args... args + Reservable auto& reservable, template_key_map_t key_map, KeyValueCallback auto default_callback, + Args... args ) { return expect_dictionary_key_map_and_length_and_default( std::move(key_map), reserve_length_callback(reservable), default_callback, args... ); } - template + template NodeCallback auto expect_dictionary_key_map_reserve_length( - Reservable auto& reservable, key_map_t key_map, Args... args + Reservable auto& reservable, template_key_map_t key_map, Args... args ) { return expect_dictionary_key_map_and_length(std::move(key_map), reserve_length_callback(reservable), args...); } - template + template NodeCallback auto expect_dictionary_keys_reserve_length_and_default( Reservable auto& reservable, KeyValueCallback auto default_callback, Args... args ) { - return expect_dictionary_keys_and_length_and_default( + return expect_dictionary_keys_and_length_and_default( reserve_length_callback(reservable), default_callback, args... ); } - template + template NodeCallback auto expect_dictionary_keys_reserve_length(Reservable auto& reservable, Args... args) { - return expect_dictionary_keys_and_length(reserve_length_callback(reservable), args...); + return expect_dictionary_keys_and_length(reserve_length_callback(reservable), args...); } node_callback_t name_list_callback(callback_t callback); - template + template Callback auto expect_mapped_string( - string_map_t const& map, Callback auto callback + template_string_map_t const& map, Callback auto callback ) { return [&map, callback](std::string_view string) -> bool { - const typename string_map_t::const_iterator it = map.find(string); + const typename template_string_map_t::const_iterator it = map.find(string); if (it != map.end()) { return callback(it->second); } -- cgit v1.2.3-56-ga3b1