diff --git a/Cantera/src/base/ctml.cpp b/Cantera/src/base/ctml.cpp index c5c9d3596..ab3fd2d2f 100755 --- a/Cantera/src/base/ctml.cpp +++ b/Cantera/src/base/ctml.cpp @@ -222,47 +222,97 @@ namespace ctml { } - /** - * Get a floating-point value from a child element. Returns a - * double value for the child named 'name' of element 'parent'. If - * 'type' is supplied and matches a known unit type, unit - * conversion to SI will be done if the child element has an attribute - * 'units'. - */ - doublereal getFloat(const XML_Node& parent, string name, string type) { - if (!parent.hasChild(name)) - throw CanteraError("getFloat (called from XML Node \"" + - parent.name() + "\"): ", - "no child XML element named " + name); - const XML_Node& node = parent.child(name); - doublereal x, x0, x1, fctr = 1.0; - string units, vmin, vmax; - x = atof(node().c_str()); - x0 = Undef; - x1 = Undef; - units = node["units"]; - vmin = node["min"]; - vmax = node["max"]; - if (vmin != "") { - x0 = atof(vmin.c_str()); - if (x < x0 - Tiny) { - writelog("\nWarning: value "+node()+" is below lower limit of " - +vmin+".\n"); - } - } - if (node["max"] != "") { - x1 = atof(vmax.c_str()); - if (x > x1 + Tiny) { - writelog("\nWarning: value "+node()+" is above upper limit of " - +vmax+".\n"); - } - } - if (type == "actEnergy" && units != "") - fctr = actEnergyToSI(units); - else if (type != "" && units != "") - fctr = toSI(units); - return fctr*x; + // Get a floating-point value from a child element. + /* + * Returns a double value for the child named 'name' of element 'parent'. If + * 'type' is supplied and matches a known unit type, unit + * conversion to SI will be done if the child element has an attribute + * 'units'. + * + * Note, it's an error for the child element not to exist. + * + * Example: + * + * Code snipet: + * @verbatum + const XML_Node &State_XMLNode; + doublereal pres = OneAtm; + if (state_XMLNode.hasChild("pressure")) { + pres = getFloat(State_XMLNode, "pressure", "toSI"); + } + @endverbatum + * + * reads the corresponding XML file: + * @verbatum + + 101325.0 + <\state> + @endverbatum + * + * @param parent reference to the XML_Node object of the parent XML element + * @param name Name of the XML child element + * @param type String type. Currently known types are "toSI" and "actEnergy", + * and "" , for no conversion. The default value is "" + * which implies that no conversion is allowed. + */ + doublereal getFloat(const XML_Node& parent, string name, string type) { + if (!parent.hasChild(name)) + throw CanteraError("getFloat (called from XML Node \"" + + parent.name() + "\"): ", + "no child XML element named \"" + name + "\" exists"); + const XML_Node& node = parent.child(name); + doublereal x, x0, x1, fctr = 1.0; + string units, vmin, vmax; + x = atof(node().c_str()); + x0 = Undef; + x1 = Undef; + units = node["units"]; + vmin = node["min"]; + vmax = node["max"]; + if (vmin != "") { + x0 = atof(vmin.c_str()); + if (x < x0 - Tiny) { + writelog("\nWarning: value "+node()+" is below lower limit of " + +vmin+".\n"); + } } + if (node["max"] != "") { + x1 = atof(vmax.c_str()); + if (x > x1 + Tiny) { + writelog("\nWarning: value "+node()+" is above upper limit of " + +vmax+".\n"); + } + } + // Note, most type's of converters default to toSI() type atm. + // This may change and become more specific in the future. + if (type == "actEnergy" && units != "") { + fctr = actEnergyToSI(units); + } else if (type == "toSI" && units != "") { + fctr = toSI(units); + } else if (type == "temperature" && units != "") { + fctr = toSI(units); + } else if (type == "density" && units != "") { + fctr = toSI(units); + } else if (type == "pressure" && units != "") { + fctr = toSI(units); + } else if (type != "" && units != "") { + fctr = toSI(units); +#ifdef DEBUG_MODE + writelog("\nWarning: conversion toSI() was done on node value " + node.name() + + "but wasn't explicity requested. Type was \"" + type + "\"\n"); +#endif + } + // Note, below currently produces a lot of output due to transport blocks. + // This needs to be addressed. +#ifdef DEBUG_MODE_MORE + else if (type == "" && units != "") { + writelog("\nWarning: XML node " + node.name() + + "has a units attribute, \"" + units + "\"," + "but no conversion was done because the getFloat() command didn't have a type\n"); + } +#endif + return fctr*x; + } /** @@ -416,46 +466,47 @@ namespace ctml { } } - /** - * This function interprets the value portion of an XML element - * as a series of "Pairs" separated by white space. - * Each pair consists of nonwhite-space characters. - * The first ":" found in the pair string is used to separate - * the string into two parts. The first part is called the "key" - * The second part is called the "val". - * String vectors of key[i] and val[i] are returned in the - * argument list. - * Warning: No spaces are allowed in each pair. Quotes are part - * of the string. - * Example - * - * red:112 blue:34 - * green:banana - * - * - * Returns: - * key val - * 0: "red" "112" - * 1: "blue" "34" - * 2: "green" "banana" - */ - void getPairs(const XML_Node& node, vector& key, - vector& val) { - vector v; - getStringArray(node, v); - int n = static_cast(v.size()); - string::size_type icolon; - for (int i = 0; i < n; i++) { - icolon = v[i].find(":"); - if (icolon == string::npos) { - throw CanteraError("getPairs","Missing a colon in the Pair entry (" - +v[i]+")"); - } - key.push_back(v[i].substr(0,icolon)); - val.push_back(v[i].substr(icolon+1, v[i].size())); - //cout << "getPairs: " << key.back() << " " << val.back() << endl; - } + + //! This function interprets the value portion of an XML element + //! as a series of "Pairs" separated by white space. + /*! + * Each pair consists of nonwhite-space characters. + * The first ":" found in the pair string is used to separate + * the string into two parts. The first part is called the "key" + * The second part is called the "val". + * String vectors of key[i] and val[i] are returned in the + * argument list. + * Warning: No spaces are allowed in each pair. Quotes are part + * of the string. + * Example: @verbatum + * + red:112 blue:34 + green:banana + @endverbatum + * + * Returns: + * key val + * 0: "red" "112" + * 1: "blue" "34" + * 2: "green" "banana" + */ + void getPairs(const XML_Node& node, vector& key, + vector& val) { + vector v; + getStringArray(node, v); + int n = static_cast(v.size()); + string::size_type icolon; + for (int i = 0; i < n; i++) { + icolon = v[i].find(":"); + if (icolon == string::npos) { + throw CanteraError("getPairs","Missing a colon in the Pair entry (" + +v[i]+")"); + } + key.push_back(v[i].substr(0,icolon)); + val.push_back(v[i].substr(icolon+1, v[i].size())); + //cout << "getPairs: " << key.back() << " " << val.back() << endl; } + } /** * This function interprets the value portion of an XML element diff --git a/Cantera/src/base/ctml.h b/Cantera/src/base/ctml.h index 0ee3b80dd..04ea2b5e8 100755 --- a/Cantera/src/base/ctml.h +++ b/Cantera/src/base/ctml.h @@ -75,21 +75,82 @@ namespace ctml { void getStringArray(const Cantera::XML_Node& node, std::vector& v); void getStringArray(const std::string& val, std::vector& v); - void getMap(const Cantera::XML_Node& node, std::map& m); - void getPairs(const Cantera::XML_Node& node, std::vector& key, - std::vector& val); - void getMatrixValues(const Cantera::XML_Node& node, - const std::vector& keyString1, - const std::vector& keyString2, - Cantera::Array2D &returnValues, bool convert = true, - bool matrixSymmetric = false); + void getMap(const Cantera::XML_Node& node, std::map& m); + + //! This function interprets the value portion of an XML element + //! as a series of "Pairs" separated by white space. + /*! + * Each pair consists of nonwhite-space characters. + * The first ":" found in the pair string is used to separate + * the string into two parts. The first part is called the "key" + * The second part is called the "val". + * String vectors of key[i] and val[i] are returned in the + * argument list. + * Warning: No spaces are allowed in each pair. Quotes are part + * of the string. + * Example: @verbatum + * + red:112 blue:34 + green:banana + @endverbatum + * + * Returns: + * key val + * 0: "red" "112" + * 1: "blue" "34" + * 2: "green" "banana" + */ + void getPairs(const Cantera::XML_Node& node, std::vector& key, + std::vector& val); + + void getMatrixValues(const Cantera::XML_Node& node, + const std::vector& keyString1, + const std::vector& keyString2, + Cantera::Array2D &returnValues, bool convert = true, + bool matrixSymmetric = false); void getIntegers(const Cantera::XML_Node& node, std::map& v); void getFloats(const Cantera::XML_Node& node, std::map& v, bool convert=true); - doublereal getFloat(const Cantera::XML_Node& parent, std::string name, - std::string type=""); - int getInteger(const Cantera::XML_Node& parent, std::string name); + + + //! Get a floating-point value from a child element. + /*! + * Returns a double value for the child named 'name' of element 'parent'. If + * 'type' is supplied and matches a known unit type, unit + * conversion to SI will be done if the child element has an attribute + * 'units'. + * + * Note, it's an error for the child element not to exist. + * + * Example: + * + * Code snipet: + * @verbatum + const XML_Node &State_XMLNode; + doublereal pres = OneAtm; + if (state_XMLNode.hasChild("pressure")) { + pres = getFloat(State_XMLNode, "pressure", "toSI"); + } + @endverbatum + * + * reads the corresponding XML file: + * @verbatum + + 101325.0 + <\state> + @endverbatum + * + * @param parent reference to the XML_Node object of the parent XML element + * @param name Name of the XML child element + * @param type String type. Currently known types are "toSI" and "actEnergy", + * and "" , for no conversion. The default value is "", + * which implies that no conversion is allowed. + */ + doublereal getFloat(const Cantera::XML_Node& parent, std::string name, + std::string type=""); + + int getInteger(const Cantera::XML_Node& parent, std::string name); void getStrings(const Cantera::XML_Node& node, std::map& v); diff --git a/Cantera/src/base/xml.cpp b/Cantera/src/base/xml.cpp index 3889b9bf7..0f3bc9e6a 100755 --- a/Cantera/src/base/xml.cpp +++ b/Cantera/src/base/xml.cpp @@ -352,24 +352,24 @@ namespace Cantera { - XML_Node::~XML_Node() { - if (m_locked) - throw CanteraError("XML_Node::~XML_Node", - "attempt to delete locked XML_Node "+name()); - int n = static_cast(m_children.size()); - for (int i = 0; i < n; i++) { - if (m_children[i]) { - if (m_children[i]->parent() == this) { - delete m_children[i]; - m_children[i] = 0; - } - } - } + XML_Node::~XML_Node() { + if (m_locked) + throw CanteraError("XML_Node::~XML_Node", + "attempt to delete locked XML_Node "+name()); + int n = static_cast(m_children.size()); + for (int i = 0; i < n; i++) { + if (m_children[i]) { + if (m_children[i]->parent() == this) { + delete m_children[i]; + m_children[i] = 0; + } + } } + } - void XML_Node::addComment(string comment) { - addChild("comment",comment); - } + void XML_Node::addComment(string comment) { + addChild("comment",comment); + } XML_Node& XML_Node::addChild(XML_Node& node) { m_children.push_back(&node); @@ -400,6 +400,45 @@ namespace Cantera { if (hasAttrib("id")) return attrib("id"); return std::string(""); } + + + // The operator[] is overloaded to provide a lookup capability + // on attributes for the current XML element. + /* + * For example + * xmlNode["id"] + * will return the value of the attribute "id" for the current + * XML element. It will return the blank std::string if there isn't + * an attribute with that name. + * + * @param attr attribute string to look up + * + * @return Returns a string representing the value of the attribute + * within the XML node. If there is no attribute + * with the given name, it returns the null string. + */ + std::string XML_Node::operator[](std::string attr) const { + return attrib(attr); + } + + // Function returns the value of an attribute + /* + * This function searches the attibutes vector for the parameter + * std::string attribute. If a match is found, the attribute value + * is returned as a string. If no match is found, the empty string + * is returned. + * + * @param attr Std::String containing the attribute to be searched for. + * + * @return Returns If a match is found, the attribute value + * is returned as a string. If no match is found, the empty string + * is returned. + */ + std::string XML_Node::attrib(std::string attr) const { + std::map::const_iterator i = m_attribs.find(attr); + if (i != m_attribs.end()) return i->second; + return ""; + } /** * This routine carries out a search for an XML node based @@ -636,25 +675,25 @@ namespace Cantera { } } - void XML_Node::copy(XML_Node *node_dest) const { - XML_Node *sc, *dc; - int ndc; - node_dest->addValue(m_value); - if (m_name == "") return; - map::const_iterator b = m_attribs.begin(); - for (; b != m_attribs.end(); ++b) { - node_dest->addAttribute(b->first, b->second); - } - const vector &vsc = node_dest->children(); - - for (int n = 0; n < m_nchildren; n++) { - sc = m_children[n]; - ndc = node_dest->nChildren(); - (void) node_dest->addChild(sc->name()); - dc = vsc[ndc]; - sc->copy(dc); - } + void XML_Node::copy(XML_Node *node_dest) const { + XML_Node *sc, *dc; + int ndc; + node_dest->addValue(m_value); + if (m_name == "") return; + map::const_iterator b = m_attribs.begin(); + for (; b != m_attribs.end(); ++b) { + node_dest->addAttribute(b->first, b->second); } + const vector &vsc = node_dest->children(); + + for (int n = 0; n < m_nchildren; n++) { + sc = m_children[n]; + ndc = node_dest->nChildren(); + (void) node_dest->addChild(sc->name()); + dc = vsc[ndc]; + sc->copy(dc); + } + } void XML_Node::getChildren(string nm, vector& children) const { diff --git a/Cantera/src/base/xml.h b/Cantera/src/base/xml.h index 8bde0265b..9c9d191c2 100755 --- a/Cantera/src/base/xml.h +++ b/Cantera/src/base/xml.h @@ -156,23 +156,22 @@ namespace Cantera { * within the XML node. If there is no attribute * with the given name, it returns the null string. */ - std::string operator[](std::string attr) const { - return attrib(attr); - } + std::string operator[](std::string attr) const; - /** + //! Function returns the value of an attribute + /*! * This function searches the attibutes vector for the parameter * std::string attribute. If a match is found, the attribute value * is returned as a string. If no match is found, the empty string * is returned. * - * @param(attr) Std::String containing the attribute to be searched for. + * @param attr Std::String containing the attribute to be searched for. + * + * @return Returns If a match is found, the attribute value + * is returned as a string. If no match is found, the empty string + * is returned. */ - std::string attrib(std::string attr) const { - std::map::const_iterator i = m_attribs.find(attr); - if (i != m_attribs.end()) return i->second; - return ""; - } + std::string attrib(std::string attr) const; std::map& attribs() { return m_attribs; } XML_Node* parent() const { return m_parent; } @@ -187,6 +186,13 @@ namespace Cantera { bool hasChild(const std::string ch) const { return (m_childindex.find(ch) != m_childindex.end()); } + + //! Tests whether the current node has an attribute with a particular name + /*! + * @param a Name of the attribute to test + * + * @return Returns true if the attribute exists, false otherwise. + */ bool hasAttrib(std::string a) const { return (m_attribs.find(a) != m_attribs.end()); }