From efa88c722fcb6c8fea7a86e1b3b8a83f1f59eb31 Mon Sep 17 00:00:00 2001 From: Hop311 Date: Thu, 24 Aug 2023 00:32:23 +0100 Subject: Big Dataloader Commit (openvic-simulation) --- src/openvic/dataloader/NodeTools.cpp | 198 +++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 src/openvic/dataloader/NodeTools.cpp (limited to 'src/openvic/dataloader/NodeTools.cpp') diff --git a/src/openvic/dataloader/NodeTools.cpp b/src/openvic/dataloader/NodeTools.cpp new file mode 100644 index 0000000..a37892f --- /dev/null +++ b/src/openvic/dataloader/NodeTools.cpp @@ -0,0 +1,198 @@ +#include "NodeTools.hpp" + +#include + +using namespace OpenVic; + +template +return_t NodeTools::expect_type(ast::NodeCPtr node, std::function callback) { + if (node != nullptr) { + if (node->is_type()) { + return callback(ast::cast_node_cptr(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 FAILURE; +} + +static return_t identifier_callback_wrapper(std::function callback, std::string_view identifier) { + if (!identifier.empty()) { + return callback(identifier); + } + Logger::error("Empty identifier node string"); + return FAILURE; +} + +return_t NodeTools::expect_identifier(ast::NodeCPtr node, std::function callback) { + return expect_type(node, [callback](ast::IdentifierNode const& identifier_node) -> return_t { + return identifier_callback_wrapper(callback, identifier_node._name); + }); +} + +return_t NodeTools::expect_string(ast::NodeCPtr node, std::function callback) { + return expect_type(node, [callback](ast::StringNode const& string_node) -> return_t { + return callback(string_node._name); + }); +} + +return_t NodeTools::expect_identifier_or_string(ast::NodeCPtr node, std::function callback) { + if (node != nullptr) { + if (node->is_type()) { + return identifier_callback_wrapper(callback, ast::cast_node_cptr(node)._name); + } else if (node->is_type()) { + return callback(ast::cast_node_cptr(node)._name); + } else { + 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 FAILURE; +} + +return_t NodeTools::expect_bool(ast::NodeCPtr node, std::function callback) { + return expect_identifier(node, [callback](std::string_view identifier) -> return_t { + if (identifier == "yes") { + return callback(true); + } else if (identifier == "no") { + return callback(false); + } + Logger::error("Invalid bool identifier text: ", identifier); + return FAILURE; + }); +} + +return_t NodeTools::expect_int(ast::NodeCPtr node, std::function callback) { + return expect_identifier(node, [callback](std::string_view identifier) -> return_t { + int64_t val; + char const* const start = identifier.data(); + char const* const end = start + identifier.size(); + const std::from_chars_result result = std::from_chars(start, end, val); + if (result.ec == std::errc{} && result.ptr == end) { + return callback(val); + } + Logger::error("Invalid int identifier text: ", identifier); + return FAILURE; + }); +} + +return_t NodeTools::expect_uint(ast::NodeCPtr node, std::function callback) { + return expect_identifier(node, [callback](std::string_view identifier) -> return_t { + uint64_t val; + char const* identifier_end = identifier.data() + identifier.size(); + const std::from_chars_result result = std::from_chars(identifier.data(), identifier_end, val); + if (result.ec == std::errc{} && result.ptr == identifier_end) { + return callback(val); + } + Logger::error("Invalid uint identifier text: ", identifier); + return FAILURE; + }); +} + +return_t NodeTools::expect_fixed_point(ast::NodeCPtr node, std::function callback) { + return expect_identifier(node, [callback](std::string_view identifier) -> return_t { + bool successful = false; + FP val = FP::parse(identifier.data(), identifier.length(), &successful); + if (successful) { + return callback(val); + } + Logger::error("Invalid fixed point identifier text: ", identifier); + return FAILURE; + }); +} + +return_t NodeTools::expect_colour(ast::NodeCPtr node, std::function callback) { + colour_t col = NULL_COLOUR; + uint32_t components = 0; + return_t ret = expect_list(node, std::bind(expect_fixed_point, std::placeholders::_1, + [&col, &components](FP val) -> return_t { + return_t ret = SUCCESS; + if (val < 0 || val > 255) { + Logger::error("Invalid colour component: ", val); + val = FP::_0(); + ret = FAILURE; + } + if (val <= 1) val *= 255; + col = (col << 8) | val.to_int32_t(); + components++; + return ret; + }), 3); + if (components < 3) col <<= 8 * (3 - components); + if (callback(col) != SUCCESS) ret = FAILURE; + return ret; +} + +return_t NodeTools::expect_date(ast::NodeCPtr node, std::function callback) { + return expect_identifier(node, [callback](std::string_view identifier) -> return_t { + bool successful = false; + Date date = Date::from_string(identifier, &successful); + if (successful) { + return callback(date); + } + Logger::error("Invalid date identifier text: ", identifier); + return FAILURE; + }); +} + +return_t NodeTools::expect_assign(ast::NodeCPtr node, std::function callback) { + return expect_type(node, [callback](ast::AssignNode const& assign_node) -> return_t { + return callback(assign_node._name, assign_node._initializer.get()); + }); +} + +return_t NodeTools::expect_list(ast::NodeCPtr node, std::function callback, size_t length, bool file_node) { + const std::function const&)> list_func = [length, callback](std::vector const& list) -> return_t { + return_t ret = SUCCESS; + size_t size = list.size(); + if (length > 0 && size != length) { + Logger::error("List length ", size, " does not match expected length ", length); + ret = FAILURE; + if (length < size) size = length; + } + std::for_each(list.begin(), list.begin() + size, [callback, &ret](ast::NodeUPtr const& sub_node) { + if (callback(sub_node.get()) != SUCCESS) ret = FAILURE; + }); + return ret; + }; + if (!file_node) { + return expect_type(node, [list_func](ast::ListNode const& list_node) -> return_t { + return list_func(list_node._statements); + }); + } else { + return expect_type(node, [list_func](ast::FileNode const& file_node) -> return_t { + return list_func(file_node._statements); + }); + } +} + +return_t NodeTools::expect_dictionary(ast::NodeCPtr node, std::function callback, bool file_node) { + return expect_list(node, std::bind(expect_assign, std::placeholders::_1, callback), 0, file_node); +} + +return_t NodeTools::expect_dictionary_keys(ast::NodeCPtr node, dictionary_key_map_t const& keys, bool allow_other_keys, bool file_node) { + std::map> key_count; + return_t ret = expect_dictionary(node, [keys, allow_other_keys, &key_count](const std::string_view key, ast::NodeCPtr value) -> return_t { + const dictionary_key_map_t::const_iterator it = keys.find(key); + if (it == keys.end()) { + if (allow_other_keys) return SUCCESS; + Logger::error("Invalid dictionary key: ", key); + return FAILURE; + } + const size_t count = ++key_count[it->first]; + dictionary_entry_t const& entry = it->second; + if (!entry.can_repeat && count > 1) { + Logger::error("Invalid repeat of dictionary key: ", key); + return FAILURE; + } + return entry.callback(value); + }, file_node); + for (dictionary_key_map_t::value_type const& entry : keys) { + if (entry.second.must_appear && key_count.find(entry.first) == key_count.end()) { + Logger::error("Mandatory dictionary key not present: ", entry.first); + ret = FAILURE; + } + } + return ret; +} -- cgit v1.2.3-56-ga3b1