diff options
| author | Oskari Timperi <oskari.timperi@iki.fi> | 2011-06-01 10:52:04 +0300 |
|---|---|---|
| committer | Oskari Timperi <oskari.timperi@iki.fi> | 2011-06-01 10:52:04 +0300 |
| commit | a71564984253ade92fc4d3c9bf185807efc570bf (patch) | |
| tree | 93e267348605dda8f32262a4d912c33e7720c074 | |
| parent | 5fb5bb1c7cc0ce266f60ab272915a48770d1443f (diff) | |
| download | sxml-a71564984253ade92fc4d3c9bf185807efc570bf.tar.gz sxml-a71564984253ade92fc4d3c9bf185807efc570bf.zip | |
New classes: node and comment.
Move functionality from element to node and derive element
from node. This allows nodes to contain different types of
nodes, e.g. comments mixed with normal elements.
| -rw-r--r-- | example.cpp | 30 | ||||
| -rw-r--r-- | sxml.cpp | 192 | ||||
| -rw-r--r-- | sxml.h | 104 |
3 files changed, 211 insertions, 115 deletions
diff --git a/example.cpp b/example.cpp index fa1574c..bbc3bbd 100644 --- a/example.cpp +++ b/example.cpp @@ -22,27 +22,29 @@ * 3. This notice may not be removed or altered from any source * distribution. */ - + #include <iostream> #include "sxml.h" using sxml::element; - +using sxml::comment; int main() { - element root("summary"); - - root.add_child(element("foo", "lorem ipsum")) - - .add_child(element("bar") - .add_child(element("foobar", "bazinga!")) - .set_attr("id", "1337")) - - .add_child(element("mother").add_child(element("child"))); - - std::cout << root.to_string(true) << std::endl; - + element *root = new element("root"); + + root->add_element("node")->set_attr("id", 0); + + root->add_child(new comment("yay, a comment!")); + root->add_element("node")->set_attr("id", 1); + + element *node = root->add_element("node")->set_attr("id", 3.1); + node = node->add_element("subnode") + node->add_element("subsubnode")->add_child( + new comment("i am in pretty deep waters here, man ..")); + + std::cout << root->to_string(true) << std::endl; + return 0; } @@ -26,16 +26,13 @@ #include "sxml.h" #include <sstream> -//#include <iostream> using std::string; using std::ostringstream; -//using std::cout; -//using std::endl; namespace sxml { -element::element(element *parent) +node::node(node *parent) : m_parent(parent), m_modified(true) { @@ -45,41 +42,127 @@ element::element(element *parent) } } -element::element(const element &elem) - : m_parent(elem.m_parent), - m_children(elem.clone_children()), - m_attributes(elem.m_attributes), - m_name(elem.m_name), - m_text(elem.m_text), - m_cached(elem.m_cached), - m_modified(elem.m_modified) +node::node(const node &n) + : m_parent(NULL), + m_children(n.m_children), + m_modified(n.m_modified) {} -element::element(const string &name, element *parent) - : m_parent(parent), - m_name(name), - m_modified(true) +node::~node() { - if (parent != NULL) + node_list::iterator i = m_children.begin(); + for (; i != m_children.end(); ++i) { - parent->add_child(this); + delete (*i); } } -element::~element() +node *node::add_child(node *child) +{ + child->m_parent = this; + m_children.push_back(child); + set_modified(true); + return child; +} + +string node::to_string(bool nice , int indent) const +{ + nice = nice; + indent = indent; + return string(); +} + +const node_list &node::children() const +{ + return m_children; +} + +node *node::clone() +{ + node *n = new node; + n->m_children = clone_children(); + n->m_modified = m_modified; + return n; +} + +node_list node::clone_children() const { - //cout << __FUNCTION__ << " " << m_name << endl; + node_list clones; - element_list::iterator ei = m_children.begin(); - for (; ei != m_children.end(); ++ei) + node_list::const_iterator i = m_children.begin(); + for (; i != m_children.end(); ++i) { - delete (*ei); + clones.push_back((*i)->clone()); } + + return clones; +} + +bool node::modified() const +{ + return m_modified; +} + +void node::set_modified(bool modified) const +{ + m_modified = modified; + + if (modified && m_parent != NULL) + { + m_parent->set_modified(true); + } +} + +// ******************************************************************* + +comment::comment(node *parent) + : node(parent) +{} + +comment::comment(const string &text, node *parent) + : node(parent) +{ + m_text = text; } -string element::to_string(bool nice, int indent) +string comment::to_string(bool nice, int indent) const { - if (!m_modified) + string result; + + if (nice) + result = string(indent, ' '); + + result += string("<!-- ") + m_text + string(" -->"); + + return result; +} + +// ******************************************************************* + +element::element(node *parent) + : node(parent) +{} + +element::element(const element &elem) + : node(elem), + m_attributes(elem.m_attributes), + m_name(elem.m_name), + m_text(elem.m_text), + m_cached(elem.m_cached) +{} + +element::element(const string &name, node *parent) + : node(parent), + m_name(name) +{} + +element::~element() +{ +} + +string element::to_string(bool nice, int indent) const +{ + if (!modified()) return m_cached; string xmlstr; @@ -90,32 +173,28 @@ string element::to_string(bool nice, int indent) xml << "<" << m_name; - attribute_map::iterator ai = m_attributes.begin(); + attribute_map::const_iterator ai = m_attributes.begin(); for (; ai != m_attributes.end(); ++ai) { xml << " " << ai->first << "=\"" << ai->second << "\""; } - if (m_children.empty() && m_text.empty()) + if (children().empty() && m_text.empty()) { xml << " />"; return xml.str(); } - else if (nice) - { - xml << ">\n"; - } else { - xml << ">"; + xml << (nice ? ">\n" : ">"); } - if (!m_children.empty()) + if (!children().empty()) { - element_list::const_iterator ei = m_children.begin(); - for (; ei != m_children.end(); ++ei) + node_list::const_iterator ni = children().begin(); + for (; ni != children().end(); ++ni) { - xml << (*ei)->to_string(nice, indent + 2); + xml << (*ni)->to_string(nice, indent + 2); if (nice) xml << "\n"; @@ -141,21 +220,7 @@ string element::to_string(bool nice, int indent) return xml.str(); } -element *element::add_child(element *child) -{ - child->m_parent = this; - m_children.push_back(child); - set_modified(true); - return child; -} - -element *element::add_child(const element &child) -{ - element *c = new element(child); - return add_child(c); -} - -element *element::add_child(const std::string &tag) +element *element::add_element(const std::string &tag) { return new element(tag, this); } @@ -175,30 +240,5 @@ template<> element *element::set_attr<>(const string &name, return this; } -element_list element::clone_children() const -{ - element_list clones; - - element_list::const_iterator ei = m_children.begin(); - for (; ei != m_children.end(); ++ei) - { - element *orig = *ei; - element *clone = new element(*orig); - clones.push_back(clone); - } - - return clones; -} - -void element::set_modified(bool modified) -{ - m_modified = modified; - - if (modified && m_parent != NULL) - { - m_parent->set_modified(true); - } -} - } // namespace sxml @@ -33,21 +33,90 @@ namespace sxml { -class element; +class node; -typedef std::vector<element *> element_list; -typedef std::map<std::string, std::string> attribute_map; +typedef std::vector<node *> node_list; -class element +//! Base class for nodes, e.g. an element, a comment, text, ... +class node +{ + public: + + //! Constructs an empty node. If parent is not NULL, the constructed node + //! is added to the given parent as a child. + explicit node(node *parent = NULL); + + //! Copy constructor. + node(const node &n); + + //! Destructor. Frees the children of this node. + virtual ~node(); + + //! Adds a child node to this node. Takes the ownership of the given + //! node. Returns a pointer to the child. + node *add_child(node *child); + + //! Returns a string representation of this node. Derived classes should + //! implement this. + virtual std::string to_string(bool nice , int indent = 0) const; + + protected: + + //! Returns a list of children in this node. + const node_list &children() const; + + //! Clones this node. The cloned node has clones of all the children of + //! the original. The cloned node doesn't have a parent. + virtual node *clone(); + + //! Clone the children of this node. The children do not have a parent set. + node_list clone_children() const; + + //! Is this node modified? Derived classes can use this information for + //! caching. + bool modified() const; + + //! Set the modified status of this node. If modified is true and the node + //! has a parent, set_modified() also calls the parents set_modified(). + void set_modified(bool modified) const; + + private: + + //! Pointer to the parent node. + node *m_parent; + + //! List of the children. + node_list m_children; + + //! Is this node modified. + mutable bool m_modified; +}; + +//! A node used for comments. +class comment: public node +{ + public: + + explicit comment(node *parent = NULL); + explicit comment(const std::string &text, node *parent = NULL); + + virtual std::string to_string(bool nice = false, int indent = 0) const; + + private: + + std::string m_text; +}; + +class element: public node { public: //! Constructs an empty element (i.e., no name, //! children, attributes) with the specified parent. - explicit element(element *parent = NULL); + explicit element(node *parent = NULL); //! Constructs an element with the specified name and parent. - explicit element(const std::string &name, element *parent = NULL); + explicit element(const std::string &name, node *parent = NULL); //! Copy constructor. element(const element &elem); @@ -57,20 +126,11 @@ class element //! Creates a textual representation of the element. If nice //! is true, the returned string is formatted with indentations //! and newlines. - std::string to_string(bool nice = false, int indent = 0); - - //! Adds a child element to this element. This version doesn't allocate - //! memory and takes the ownership of the given element. Returns a - //! pointer to the child. - element *add_child(element *child); - - //! Adds a child element to this element. This version allocates memory - //! for a new child. Returns a pointer to the child. - element *add_child(const element &child); + virtual std::string to_string(bool nice = false, int indent = 0) const; //! Adds a child with the given tag to this element. Returns a pointer //! to the child. - element *add_child(const std::string &tag); + element *add_element(const std::string &tag); //! Set the text for this element. An element can either have text //! or children. If an element has both, children take precedence @@ -84,20 +144,14 @@ class element private: - element_list clone_children() const; - - void set_modified(bool modified); - - element *m_parent; + typedef std::map<std::string, std::string> attribute_map; - element_list m_children; attribute_map m_attributes; std::string m_name; std::string m_text; - std::string m_cached; - bool m_modified; + mutable std::string m_cached; }; template<class T> element *element::set_text(const T &text) |
