// Copyright (c) 2023 Dominic Masters // // This software is released under the MIT License. // https://opensource.org/licenses/MIT #pragma once #include "util/Xml.hpp" namespace Dawn { template class XmlParser { protected: /** * Get the required attributes for this Xml Node to have. * * @return Vector of strings of required attribute keys. */ virtual std::vector getRequiredAttributes() = 0; /** * Return optional attributes with defaults for this node to have. * * @return Key-Value Pair of optional attributes and defaults. */ virtual std::map getOptionalAttributes() = 0; /** * Callback to be invoked upon successful parse of this node. * * @param node Node that was parsed. * @param values KVP of values from the required and optional attrs. * @param output Templated output of the parse from this method. * @param error Pointer to a string to write-out any errors. * @return Non 0 for error, 0 for success. */ virtual int32_t onParse( Xml *node, std::map values, T *output, std::string *error ) = 0; public: /** * Common parse method to parse a duration from a value string. * * @param duration Duration string to parse. * @return The parsed duration. */ static std::string parseDuration(std::string duration) { std::string dur = duration; if(dur.find('.') == std::string::npos) dur += ".0"; return dur + "f"; } /** * Common parse method to parse an easing from a value string. * * @param e Easing string to parse. * @return The parsed ease. */ static std::string parseEase(std::string e) { if(e == "out-quad") return "&easeOutQuad"; if(e == "linear") return "&easeLinear"; return ""; } /** * Handles parsing of an Xml node. * * @param xml Xml node to parse. * @param output Output struct to put the output data. * @param error Pointer to the string for errors to be stored. * @return 0 for success, otherwise for error. */ int32_t parse(Xml *xml, T *output, std::string *error) { std::map values; // First get the required attributes auto required = this->getRequiredAttributes(); auto itRequired = required.begin(); while(itRequired != required.end()) { auto s = *itRequired; auto attr = xml->attributes.find(s); if(attr == xml->attributes.end()) { std::cout << "Missing required attribute \"" << s << "\" on node \"" << xml->node << "\"" << std::endl; return 1; } values[s] = attr->second; ++itRequired; } // Now get the optional attributes auto optional = this->getOptionalAttributes(); auto itOptional = optional.begin(); while(itOptional != optional.end()) { auto key = itOptional->first; auto defaultValue = itOptional->second; auto attr = xml->attributes.find(key); if(attr == xml->attributes.end()) { values[key] = defaultValue; } else { values[key] = attr->second; } ++itOptional; } // Now send to parser return this->onParse(xml, values, output, error); } }; }