From 86b9899e74816801977c68ee8bc489ad5ed5fb32 Mon Sep 17 00:00:00 2001 From: Harry Moffat Date: Wed, 17 Sep 2008 20:03:31 +0000 Subject: [PATCH] More carriage return issues. Strip now uses the ISO C isspace() routine. --- Cantera/src/base/xml.cpp | 400 ++++++++++++++++++++------------------- Cantera/src/base/xml.h | 370 ++++++++++++++++++++---------------- 2 files changed, 416 insertions(+), 354 deletions(-) diff --git a/Cantera/src/base/xml.cpp b/Cantera/src/base/xml.cpp index 23aa3c8e0..3889b9bf7 100755 --- a/Cantera/src/base/xml.cpp +++ b/Cantera/src/base/xml.cpp @@ -18,6 +18,8 @@ using namespace std; #include "xml.h" +#include + #define XML_INDENT 4 namespace Cantera { @@ -85,213 +87,229 @@ namespace Cantera { //////////////////// XML_Reader methods /////////////////////// - /// Get a single character from the input stream. If the character - /// is a new-line character, then increment the line count. - void XML_Reader::getchr(char& ch) { - m_s.get(ch); - if (ch == '\n') m_line++; + XML_Reader::XML_Reader(std::istream& input) : + m_s(input), + m_line(0) + { + } + + //! Get a single character from the input stream. + /*! + * If the character + * is a new-line character, then increment the line count. + */ + void XML_Reader::getchr(char& ch) { + m_s.get(ch); + if (ch == '\n') { + m_line++; + } + } + + + // Returns string 'aline' stripped of leading and trailing white + // space. + // @todo why is this a class method? + string XML_Reader::strip(const string& aline) { + int len = static_cast(aline.size()); + int i, j, ll; + for (i = len-1; i >= 0; i--) { + ll = aline[i]; + if (! isspace(ll)) break; } - - - /// Returns string 'aline' stripped of leading and trailing white - /// space. - /// @todo why is this a class method? - string XML_Reader::strip(const string& aline) { - int len = static_cast(aline.size()); - int i, j; - for (i = len-1; i >= 0; i--) - if (aline[i] != ' ' && aline[i] != '\n') break; - for (j = 0; j < i; j++) - if (aline[j] != ' ' && aline[j] != '\n') break; - return aline.substr(j, i - j + 1); + for (j = 0; j < i; j++) { + ll = aline[j]; + if (! isspace(ll)) break; } + // if (aline[j] != ' ' && aline[j] != '\n') break; + return aline.substr(j, i - j + 1); + } - /// Looks for a substring within 'aline' enclosed in double - /// quotes, and returns this substring (without the quotes) if - /// found. If not, an empty string is returned. - /// @todo why is this a class method? - string XML_Reader::inquotes(const string& aline) { - int len = static_cast(aline.size()); - int i, j; - for (i = len-1; i >= 0; i--) - if (aline[i] == '"') break; - for (j = 0; j < i; j++) - if (aline[j] == '"') break; - if (j == i) return ""; - else return aline.substr(j+1, i - j - 1); + /// Looks for a substring within 'aline' enclosed in double + /// quotes, and returns this substring (without the quotes) if + /// found. If not, an empty string is returned. + /// @todo why is this a class method? + string XML_Reader::inquotes(const string& aline) { + int len = static_cast(aline.size()); + int i, j; + for (i = len-1; i >= 0; i--) + if (aline[i] == '"') break; + for (j = 0; j < i; j++) + if (aline[j] == '"') break; + if (j == i) return ""; + else return aline.substr(j+1, i - j - 1); + } + + /** + * Find the first position of a character, q, in string s, + * which is not immediately preceded by the backslash character + * '\' + */ + static string::size_type findUnbackslashed(string s, const char q, + string::size_type istart = 0) { + string::size_type iloc, icurrent, len; + icurrent = istart; + len = s.size(); + while (1) { + iloc = s.find(q, icurrent); + if (iloc == string::npos || iloc == 0) { + return iloc; + } + char cm1 = s[iloc-1]; + if (cm1 == '\\') { + if (iloc >= (len -1)) return string::npos; + icurrent = iloc + 1; + } else { + return iloc; + } } + } - /** - * Find the first position of a character, q, in string s, - * which is not immediately preceded by the backslash character - * '\' + /** + * Searches a string for the first occurrence of a valid + * quoted string. Quotes can start with either a single + * quote or a double quote, but must also end with the same + * type. Quotes may be commented out by preceding with a + * backslash character, '\\'. + */ + int XML_Reader::findQuotedString(const string& s, string &rstring) { + const char q1 = '\''; + const char q2 = '"'; + rstring = ""; + char qtype = ' '; + string::size_type iloc1, iloc2, ilocStart = 0; + iloc1 = findUnbackslashed(s, q1); + iloc2 = findUnbackslashed(s, q2); + if (iloc2 != string::npos) { + ilocStart = iloc2; + qtype = q2; + } + if (iloc1 != string::npos) { + if (iloc1 < ilocStart) { + ilocStart = iloc1; + qtype = q1; + } + } + if (qtype == ' ') return 0; + + iloc1 = findUnbackslashed(s, qtype, ilocStart+1); + + if (iloc1 == string::npos) { + return 0; + } + /* + * Define the return string by the two endpoints. + * Strip the surrounding quotes as well */ - static string::size_type findUnbackslashed(string s, const char q, - string::size_type istart = 0) { - string::size_type iloc, icurrent, len; - icurrent = istart; - len = s.size(); - while (1) { - iloc = s.find(q, icurrent); - if (iloc == string::npos || iloc == 0) { - return iloc; - } - char cm1 = s[iloc-1]; - if (cm1 == '\\') { - if (iloc >= (len -1)) return string::npos; - icurrent = iloc + 1; - } else { - return iloc; - } - } - } - - /** - * Searches a string for the first occurrence of a valid - * quoted string. Quotes can start with either a single - * quote or a double quote, but must also end with the same - * type. Quotes may be commented out by preceding with a - * backslash character, '\\'. + rstring = s.substr(ilocStart + 1, iloc1 - 1); + /* + * Return the first character position past the quotes */ - int XML_Reader::findQuotedString(const string& s, string &rstring) { - const char q1 = '\''; - const char q2 = '"'; - rstring = ""; - char qtype = ' '; - string::size_type iloc1, iloc2, ilocStart = 0; - iloc1 = findUnbackslashed(s, q1); - iloc2 = findUnbackslashed(s, q2); - if (iloc2 != string::npos) { - ilocStart = iloc2; - qtype = q2; - } - if (iloc1 != string::npos) { - if (iloc1 < ilocStart) { - ilocStart = iloc1; - qtype = q1; - } - } - if (qtype == ' ') return 0; - - iloc1 = findUnbackslashed(s, qtype, ilocStart+1); - - if (iloc1 == string::npos) { - return 0; - } - /* - * Define the return string by the two endpoints. - * Strip the surrounding quotes as well - */ - rstring = s.substr(ilocStart + 1, iloc1 - 1); - /* - * Return the first character position past the quotes - */ - return static_cast(iloc1)+1; - } + return static_cast(iloc1)+1; + } - /** - * parseTag parses XML tags, i.e., the XML elements that are - * inbetween angle brackets. - */ - void XML_Reader::parseTag(string tag, string& name, - map& attribs) { - string::size_type iloc; - string attr, val; - string s = strip(tag); - iloc = s.find(' '); - if (iloc != string::npos) { - name = s.substr(0, iloc); - s = strip(s.substr(iloc+1,s.size())); - if (s[s.size()-1] == '/') { - name += "/"; - } + /** + * parseTag parses XML tags, i.e., the XML elements that are + * inbetween angle brackets. + */ + void XML_Reader::parseTag(string tag, string& name, + map& attribs) { + string::size_type iloc; + string attr, val; + string s = strip(tag); + iloc = s.find(' '); + if (iloc != string::npos) { + name = s.substr(0, iloc); + s = strip(s.substr(iloc+1,s.size())); + if (s[s.size()-1] == '/') { + name += "/"; + } - // get attributes - while (1) { - iloc = s.find('='); - if (iloc == string::npos) break; - attr = strip(s.substr(0,iloc)); - if (attr == "") break; - s = strip(s.substr(iloc+1,s.size())); - iloc = findQuotedString(s, val); - attribs[attr] = val; - if (iloc != string::npos) { - if (iloc < s.size()) - s = strip(s.substr(iloc,s.size())); - else - break; - } - } - } - else { - name = s; - } + // get attributes + while (1) { + iloc = s.find('='); + if (iloc == string::npos) break; + attr = strip(s.substr(0,iloc)); + if (attr == "") break; + s = strip(s.substr(iloc+1,s.size())); + iloc = findQuotedString(s, val); + attribs[attr] = val; + if (iloc != string::npos) { + if (iloc < s.size()) + s = strip(s.substr(iloc,s.size())); + else + break; + } + } } + else { + name = s; + } + } - string XML_Reader::readTag(map& attribs) { - string name, tag = ""; - bool incomment = false; - char ch = '-'; - while (1) { - if (m_s.eof() || (getchr(ch), ch == '<')) break; - } - char ch1 = ' ', ch2 = ' '; - while (1) { - if (m_s.eof()) { tag = "EOF"; break;} - ch2 = ch1; - ch1 = ch; - getchr(ch); - if (ch == '-') { - if (ch1 == '-' && ch2 == '!') { - incomment = true; - tag = "-"; - } - } - else if (ch == '>') { - if (incomment) { - if (ch1 == '-' && ch2 == '-') break; - } - else - break; - } - if (isprint(ch)) tag += ch; - } - if (incomment) { - attribs.clear(); - return tag; - } - else { - parseTag(tag, name, attribs); - return name; - } + string XML_Reader::readTag(map& attribs) { + string name, tag = ""; + bool incomment = false; + char ch = '-'; + while (1) { + if (m_s.eof() || (getchr(ch), ch == '<')) break; } - - string XML_Reader::readValue() { - string tag = ""; - char ch, lastch; - ch = '\n'; - bool front = true; - while (1) { - if (m_s.eof()) break; - lastch = ch; - getchr(ch); - if (ch == '\n') - front = true; - else if (ch != ' ') - front = false; - if (ch == '<') { - m_s.putback(ch); - break; - } - if (front && lastch == ' ' && ch == ' ') ; - else tag += ch; - } - return strip(tag); + char ch1 = ' ', ch2 = ' '; + while (1) { + if (m_s.eof()) { tag = "EOF"; break;} + ch2 = ch1; + ch1 = ch; + getchr(ch); + if (ch == '-') { + if (ch1 == '-' && ch2 == '!') { + incomment = true; + tag = "-"; + } + } + else if (ch == '>') { + if (incomment) { + if (ch1 == '-' && ch2 == '-') break; + } + else + break; + } + if (isprint(ch)) tag += ch; } + if (incomment) { + attribs.clear(); + return tag; + } + else { + parseTag(tag, name, attribs); + return name; + } + } + + string XML_Reader::readValue() { + string tag = ""; + char ch, lastch; + ch = '\n'; + bool front = true; + while (1) { + if (m_s.eof()) break; + lastch = ch; + getchr(ch); + if (ch == '\n') + front = true; + else if (ch != ' ') + front = false; + if (ch == '<') { + m_s.putback(ch); + break; + } + if (front && lastch == ' ' && ch == ' ') ; + else tag += ch; + } + return strip(tag); + } - ////////////////////////// XML_Node ///////////////////////////////// + ////////////////////////// XML_Node ///////////////////////////////// XML_Node::XML_Node(string nm, XML_Node* p) diff --git a/Cantera/src/base/xml.h b/Cantera/src/base/xml.h index 55457c8b2..8bde0265b 100755 --- a/Cantera/src/base/xml.h +++ b/Cantera/src/base/xml.h @@ -34,20 +34,64 @@ namespace Cantera { /** * Class XML_Reader is designed for internal use. + * This function reads an XML file into an XML_Node object. */ class XML_Reader { public: - XML_Reader(std::istream& input) : m_s(input), m_line(0) {} + //! Sole Constructor for the XML_Reader class + /*! + * @param input Reference to the istream object containing + * the XML file + */ + XML_Reader(std::istream& input); + + //! Input Stream containing the XML file std::istream& m_s; + + //! Line count int m_line; + //! Read a single character from the input stream + //! and return it + /*! + * All low level reads occur through this function. + * The function also keeps track of the line numbers. + * + * @param ch Character to be returned. + */ void getchr(char& ch); + + //! Returns string 'aline' stripped of leading and trailing white + //! space. + /*! + * White space is defined by the ISO C function isspace(), and + * includes tabs, spaces, \n. \r, \v, and \f. + * + * @param aline Input line to be stripped + * + * @return Returns a string stripped of leading and trailing white + * space. + * + * @todo why is this a class method? + */ std::string strip(const std::string& aline); + + /// Looks for a substring within 'aline' enclosed in double + /// quotes, and returns this substring (without the quotes) if + /// found. If not, an empty string is returned. + /// @todo why is this a class method? std::string inquotes(const std::string& aline); + /** + * Searches a string for the first occurrence of a valid + * quoted string. Quotes can start with either a single + * quote or a double quote, but must also end with the same + * type. Quotes may be commented out by preceding with a + * backslash character, '\\'. + */ int findQuotedString(const std::string& aline, std::string &rstring); - + void parseTag(std::string line, std::string& name, std::map& attribs); std::string readTag(std::map& attribs); @@ -55,193 +99,193 @@ namespace Cantera { }; - ////////////////////////// XML_Node ///////////////////////////////// + ////////////////////////// XML_Node ///////////////////////////////// - class XML_Node { - public: + class XML_Node { + public: - XML_Node(std::string nm = "--", XML_Node* p = 0); + XML_Node(std::string nm = "--", XML_Node* p = 0); - XML_Node(const XML_Node &right); + XML_Node(const XML_Node &right); - //! Assignment operator for XML trees - /*! - * @param right XML tree to copy - */ - XML_Node& operator=(const XML_Node &right); + //! Assignment operator for XML trees + /*! + * @param right XML tree to copy + */ + XML_Node& operator=(const XML_Node &right); - virtual ~XML_Node(); - void addComment(std::string comment); - XML_Node& addChild(XML_Node& node); - XML_Node& addChild(std::string name); - XML_Node& addChild(std::string name, std::string value); - XML_Node& addChild(std::string name, double value, std::string fmt="%g"); - void removeChild(XML_Node* node); - void addValue(std::string val); - void addValue(doublereal val, std::string fmt="%g"); - void addAttribute(std::string attrib, std::string value); - void addAttribute(std::string attrib, double value, std::string fmt="%g"); - void writeHeader(std::ostream& s); - std::string value() const { return m_value; } - std::string value(std::string loc) const { return child(loc).value(); } - void setLineNumber(int n) {m_linenum = n;} - int lineNumber() const {return m_linenum;} - doublereal fp_value() const { - return std::atof(m_value.c_str()); - } - integer int_value() const { - return std::atoi(m_value.c_str()); - } - std::string operator()() const { return m_value; } - std::string operator()(std::string loc) const { return value(loc); } + virtual ~XML_Node(); + void addComment(std::string comment); + XML_Node& addChild(XML_Node& node); + XML_Node& addChild(std::string name); + XML_Node& addChild(std::string name, std::string value); + XML_Node& addChild(std::string name, double value, std::string fmt="%g"); + void removeChild(XML_Node* node); + void addValue(std::string val); + void addValue(doublereal val, std::string fmt="%g"); + void addAttribute(std::string attrib, std::string value); + void addAttribute(std::string attrib, double value, std::string fmt="%g"); + void writeHeader(std::ostream& s); + std::string value() const { return m_value; } + std::string value(std::string loc) const { return child(loc).value(); } + void setLineNumber(int n) {m_linenum = n;} + int lineNumber() const {return m_linenum;} + doublereal fp_value() const { + return std::atof(m_value.c_str()); + } + integer int_value() const { + return std::atoi(m_value.c_str()); + } + std::string operator()() const { return m_value; } + std::string operator()(std::string loc) const { return value(loc); } - //! 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 operator[](std::string attr) const { - return attrib(attr); - } + //! 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 operator[](std::string attr) const { + return attrib(attr); + } - /** - * 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. - */ - 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 ""; - } + /** + * 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. + */ + 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::map& attribs() { return m_attribs; } - XML_Node* parent() const { return m_parent; } - XML_Node* setParent(XML_Node* p) { m_parent = p; return p; } + std::map& attribs() { return m_attribs; } + XML_Node* parent() const { return m_parent; } + XML_Node* setParent(XML_Node* p) { m_parent = p; return p; } - //! Tests whether the current node has a child node with a particular name - /*! - * @param ch Name of the child node to test - * - * @return Returns true if the child node exists, false otherwise. - */ - bool hasChild(const std::string ch) const { - return (m_childindex.find(ch) != m_childindex.end()); - } - bool hasAttrib(std::string a) const { - return (m_attribs.find(a) != m_attribs.end()); - } + //! Tests whether the current node has a child node with a particular name + /*! + * @param ch Name of the child node to test + * + * @return Returns true if the child node exists, false otherwise. + */ + bool hasChild(const std::string ch) const { + return (m_childindex.find(ch) != m_childindex.end()); + } + bool hasAttrib(std::string a) const { + return (m_attribs.find(a) != m_attribs.end()); + } - //! Returns the name of the XML node - /*! - * The name is the XML node is the XML node name - */ - std::string name() const { return m_name; } + //! Returns the name of the XML node + /*! + * The name is the XML node is the XML node name + */ + std::string name() const { return m_name; } - //! Return the id attribute, if present - /*! - * Returns the id attribute if present. If not - * it return the empty string - */ - std::string id() const; + //! Return the id attribute, if present + /*! + * Returns the id attribute if present. If not + * it return the empty string + */ + std::string id() const; - XML_Node& child(int n) const { return *m_children[n]; } - std::vector& children() { return m_children; } - const std::vector& children() const { return m_children; } - int nChildren() const { return m_nchildren; } + XML_Node& child(int n) const { return *m_children[n]; } + std::vector& children() { return m_children; } + const std::vector& children() const { return m_children; } + int nChildren() const { return m_nchildren; } - void build(std::istream& f); + void build(std::istream& f); - void _require(std::string a, std::string v) const; + void _require(std::string a, std::string v) const; - /** - * This routine carries out a search for an XML node based - * on both the xml element name and the attribute ID. - * If exact matches are found for both fields, the pointer - * to the matching XML Node is returned. - * - * The ID attribute may be defaulted by setting it to "". - * In this case the pointer to the first xml element matching the name - * only is returned. - * @internal - * This algorithm does a lateral search of first generation children - * first before diving deeper into each tree branch. - */ - XML_Node* findNameID(const std::string &nameTarget, - const std::string &idTarget) const; + /** + * This routine carries out a search for an XML node based + * on both the xml element name and the attribute ID. + * If exact matches are found for both fields, the pointer + * to the matching XML Node is returned. + * + * The ID attribute may be defaulted by setting it to "". + * In this case the pointer to the first xml element matching the name + * only is returned. + * @internal + * This algorithm does a lateral search of first generation children + * first before diving deeper into each tree branch. + */ + XML_Node* findNameID(const std::string &nameTarget, + const std::string &idTarget) const; - XML_Node* findID(const std::string& id, int depth=100) const; - XML_Node* findByAttr(const std::string& attr, const std::string& val); - const XML_Node* findByName(const std::string& nm) const; - XML_Node* findByName(const std::string& nm); - void getChildren(std::string name, std::vector& children) const; - XML_Node& child(std::string loc) const; - void write(std::ostream& s, int level = 0) const; - XML_Node& root() const { return *m_root; } - void setRoot(XML_Node& root) { m_root = &root; } - void copyUnion(XML_Node *node_dest) const; - void copy(XML_Node *node_dest) const; - void lock() {m_locked = true;} - void unlock() {m_locked = false; } + XML_Node* findID(const std::string& id, int depth=100) const; + XML_Node* findByAttr(const std::string& attr, const std::string& val); + const XML_Node* findByName(const std::string& nm) const; + XML_Node* findByName(const std::string& nm); + void getChildren(std::string name, std::vector& children) const; + XML_Node& child(std::string loc) const; + void write(std::ostream& s, int level = 0) const; + XML_Node& root() const { return *m_root; } + void setRoot(XML_Node& root) { m_root = &root; } + void copyUnion(XML_Node *node_dest) const; + void copy(XML_Node *node_dest) const; + void lock() {m_locked = true;} + void unlock() {m_locked = false; } - private: - void write_int(std::ostream& s, int level = 0) const; + private: + void write_int(std::ostream& s, int level = 0) const; - protected: + protected: - //! XML node name of the node. - /*! - * For example, if we were in the XML_Node where - * - * - * Then, this string would be equal to "phase". "dim" and "id" - * are attributes of the XML_Node. - */ - std::string m_name; + //! XML node name of the node. + /*! + * For example, if we were in the XML_Node where + * + * + * Then, this string would be equal to "phase". "dim" and "id" + * are attributes of the XML_Node. + */ + std::string m_name; - //! Value of the xml node - /*! - * This is the string contents of the XML node. For - * example. The xml node named eps: - * - * - * valueString - * - * - * has a m_value string containing "valueString". - */ - std::string m_value; - std::map m_childindex; - std::map m_attribs; - XML_Node* m_parent; - XML_Node* m_root; - bool m_locked; - std::vector m_children; + //! Value of the xml node + /*! + * This is the string contents of the XML node. For + * example. The xml node named eps: + * + * + * valueString + * + * + * has a m_value string containing "valueString". + */ + std::string m_value; + std::map m_childindex; + std::map m_attribs; + XML_Node* m_parent; + XML_Node* m_root; + bool m_locked; + std::vector m_children; - //! Number of children of this node - int m_nchildren; - bool m_iscomment; - int m_linenum; - }; + //! Number of children of this node + int m_nchildren; + bool m_iscomment; + int m_linenum; + }; - XML_Node * findXMLPhase(XML_Node* root, const std::string &id); + XML_Node * findXMLPhase(XML_Node* root, const std::string &id); }