From f259658c97795fdd8429eabbce951033feeee6d6 Mon Sep 17 00:00:00 2001 From: Daniel Schwen Date: Tue, 6 Apr 2021 16:49:50 -0600 Subject: [PATCH] Add error check, homogenize parse methods (#100) --- src/parse.cxx | 77 +++++++++++++++++++++++++-------------------------- src/parse.h | 68 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 90 insertions(+), 55 deletions(-) diff --git a/src/parse.cxx b/src/parse.cxx index 0885c814..310a4879 100644 --- a/src/parse.cxx +++ b/src/parse.cxx @@ -2,7 +2,7 @@ namespace neml { -void recurseSubstitute(rapidxml::xml_node<> * node, std::map substitutions) +void recurseSubstitute(rapidxml::xml_node<> * node, const std::map & substitutions, std::set & used_keys) { auto * doc = node->document(); @@ -21,6 +21,7 @@ void recurseSubstitute(rapidxml::xml_node<> * node, std::mapsecond); + used_keys.insert(var); open = value.find("{", open + 1); close = value.find("}", open); @@ -40,21 +41,41 @@ void recurseSubstitute(rapidxml::xml_node<> * node, std::map * child = node->first_node(); child; child = child->next_sibling()) - recurseSubstitute(child, substitutions); + for (rapidxml::xml_node<> * child = node->first_node(); child; child = child->next_sibling()) + recurseSubstitute(child, substitutions, used_keys); } -std::shared_ptr parse_string(std::string input, std::map substitutions) +rapidxml::xml_node<> * processNode(rapidxml::xml_document<> & doc, std::string mname, const std::map & substitutions) { - // Parse the string to the rapidxml representation - rapidxml::xml_document<> doc; - doc.parse<0>(&input[0]); + // Grab the root node + rapidxml::xml_node<> * root = doc.first_node(); - // The model is the root node - rapidxml::xml_node<> * found = doc.first_node(); + // Find the node with the right name + rapidxml::xml_node<> * found = (mname == "" ? root->first_node(mname.c_str()) : root); + if (!found) + throw ModelNotFound(mname); + + // make a set of used substitutions + std::set used_keys; // substitute {variables} in DOM tree - recurseSubstitute(found, substitutions); + recurseSubstitute(found, substitutions, used_keys); + + // check if all keys were used + if (used_keys.size() < substitutions.size()) + { + + } + + return found; +} + +std::shared_ptr parse_string(std::string input, std::string mname, const std::map & substitutions) +{ + // Parse the string to the rapidxml representation + rapidxml::xml_document<> doc; + doc.parse<0>(&input[0]); + auto found = processNode(doc, mname, substitutions); // Get the NEMLObject std::shared_ptr obj = get_object(found); @@ -69,20 +90,12 @@ std::shared_ptr parse_string(std::string input, std::map parse_string_unique(std::string input, std::string mname, std::map substitutions) +std::unique_ptr parse_string_unique(std::string input, std::string mname, const std::map & substitutions) { // Parse the string to the rapidxml representation rapidxml::xml_document<> doc; doc.parse<0>(&input[0]); - - // Grab the root node - rapidxml::xml_node<> * root = doc.first_node(); - - // Find the node with the right name - rapidxml::xml_node<> * found = root->first_node(mname.c_str()); - - // substitute {variables} in DOM tree - recurseSubstitute(found, substitutions); + auto found = processNode(doc, mname, substitutions); // Get the NEMLObject std::unique_ptr obj = get_object_unique(found); @@ -97,21 +110,13 @@ std::unique_ptr parse_string_unique(std::string input, std::string mn } } -std::shared_ptr parse_xml(std::string fname, std::string mname, std::map substitutions) +std::shared_ptr parse_xml(std::string fname, std::string mname, const std::map & substitutions) { // Parse the XML file rapidxml::file <> xmlFile(fname.c_str()); rapidxml::xml_document<> doc; doc.parse<0>(xmlFile.data()); - - // Grab the root node - rapidxml::xml_node<> * root = doc.first_node(); - - // Find the node with the right name - rapidxml::xml_node<> * found = root->first_node(mname.c_str()); - - // substitute {variables} in DOM tree - recurseSubstitute(found, substitutions); + auto found = processNode(doc, mname, substitutions); // Get the NEMLObject std::shared_ptr obj = get_object(found); @@ -126,21 +131,13 @@ std::shared_ptr parse_xml(std::string fname, std::string mname, std:: } } -std::unique_ptr parse_xml_unique(std::string fname, std::string mname, std::map substitutions) +std::unique_ptr parse_xml_unique(std::string fname, std::string mname, const std::map & substitutions) { // Parse the XML file rapidxml::file <> xmlFile(fname.c_str()); rapidxml::xml_document<> doc; doc.parse<0>(xmlFile.data()); - - // Grab the root node - rapidxml::xml_node<> * root = doc.first_node(); - - // Find the node with the right name - rapidxml::xml_node<> * found = root->first_node(mname.c_str()); - - // substitute {variables} in DOM tree - recurseSubstitute(found, substitutions); + auto found = processNode(doc, mname, substitutions); // Get the NEMLObject std::unique_ptr obj = get_object_unique(found); diff --git a/src/parse.h b/src/parse.h index cfbe6238..ecdbabe4 100644 --- a/src/parse.h +++ b/src/parse.h @@ -1,38 +1,41 @@ #ifndef PARSE_H #define PARSE_H -#include "objects.h" -#include "models.h" #include "damage.h" +#include "models.h" +#include "objects.h" #include "windows.h" #include "rapidxml.hpp" #include "rapidxml_utils.hpp" +#include +#include #include -#include #include +#include #include -#include -#include namespace neml { /// perform {variable} substitution in DOM tree -void recurseSubstitute(rapidxml::xml_node<> * node, std::map substitutions); +void recurseSubstitute(rapidxml::xml_node<> * node, const std::map & substitutions, std::set & used_keys); + +/// perform {variable} substitution in DOM tree +rapidxml::xml_node<> * processNode(rapidxml::xml_document<> & doc, std::string mname, const std::map & substitutions); /// Parse from a string to a shared_ptr - std::shared_ptr parse_string(std::string input, std::map substitutions = std::map()); +NEML_EXPORT std::shared_ptr parse_string(std::string input, std::string mname = "", const std::map & substitutions = std::map()); /// Parse from a string to a unique_ptr -std::unique_ptr parse_string_unique(std::string input, std::string mname, std::map substitutions = std::map()); +NEML_EXPORT std::unique_ptr parse_string_unique(std::string input, std::string mname = "", const std::map & substitutions = std::map()); /// Parse from file to a shared_ptr -NEML_EXPORT std::shared_ptr parse_xml(std::string fname, std::string mname, std::map substitutions = std::map()); +NEML_EXPORT std::shared_ptr parse_xml(std::string fname, std::string mname = "", const std::map & substitutions = std::map()); /// Parse from file to a unique_ptr -NEML_EXPORT std::unique_ptr parse_xml_unique(std::string fname, std::string mname, std::map substitutions = std::map()); +NEML_EXPORT std::unique_ptr parse_xml_unique(std::string fname, std::string mname = "", const std::map & substitutions = std::map()); /// Extract a NEMLObject from a xml node as a unique_ptr NEML_EXPORT std::unique_ptr get_object_unique(const rapidxml::xml_node<> * node); @@ -113,6 +116,26 @@ class NodeNotFound: public std::exception { std::string message_; }; +/// If a model is not found +class ModelNotFound: public std::exception { + public: + ModelNotFound(std::string model_name) + { + std::stringstream ss; + ss << "Model with name " << model_name + << " was not found in the supplied XML!"; + message_ = ss.str(); + }; + + const char * what() const throw () + { + return message_.c_str(); + }; + + private: + std::string message_; +}; + /// If a node is not unique (and it should be) class DuplicateNode: public std::exception { public: @@ -161,13 +184,29 @@ class InvalidType: public std::exception { /// If a parameter doesn't exist class UnknownParameterXML: public std::exception { public: - UnknownParameterXML(std::string name, std::string param) : - name_(name), param_(param) + UnknownParameterXML(std::string name, std::string param) { std::stringstream ss; + ss << "Object " << name << " does not have an XML variable called '" << param << "'!"; + message_ = ss.str(); + }; - ss << "Object " << name_ << " does not have a parameter called " << param_ << "!"; + const char * what() const throw () + { + return message_.c_str(); + }; + private: + std::string message_; +}; + +/// If a parameter doesn't exist +class UnusedParameterXML: public std::exception { + public: + UnusedParameterXML(std::string name, std::string params) + { + std::stringstream ss; + ss << "XML variables '" << params << "' supplied to object '" << name << "' were unused!"; message_ = ss.str(); }; @@ -177,8 +216,7 @@ class UnknownParameterXML: public std::exception { }; private: - std::string name_, param_, message_; - + std::string message_; }; /// The object isn't in the factory