diff options
| author | Oskari Timperi <oskari.timperi@iki.fi> | 2011-05-26 16:02:22 +0300 |
|---|---|---|
| committer | Oskari Timperi <oskari.timperi@iki.fi> | 2011-05-26 16:02:22 +0300 |
| commit | b7a61ba83cbfa0f9684ce9cf476d4c819d1f04ba (patch) | |
| tree | 65d7e04a8f1930555b654ff2757bc9696434dbbb | |
| parent | 279a262eab521434cdcf1ab33dab84bb9c0df923 (diff) | |
| download | sxml-b7a61ba83cbfa0f9684ce9cf476d4c819d1f04ba.tar.gz sxml-b7a61ba83cbfa0f9684ce9cf476d4c819d1f04ba.zip | |
Use element* instead of element& and introduce parenting
| -rw-r--r-- | sxml.cpp | 116 | ||||
| -rw-r--r-- | sxml.h | 62 |
2 files changed, 122 insertions, 56 deletions
@@ -25,38 +25,62 @@ #include "sxml.h" +using std::string; +using std::ostringstream; + namespace sxml { -element::element() +element::element(element *parent) + : m_parent(parent), + m_modified(true) {} element::element(const element &elem) - : m_children(elem.m_children), + : 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_text(elem.m_text), + m_cached(elem.m_cached), + m_modified(elem.m_modified) {} -element::element(const std::string &name) - : m_name(name) +element::element(const string &name, element *parent) + : m_parent(parent), + m_name(name), + m_modified(true) {} -std::string element::to_string(bool nice, int indent) const +element::~element() +{ + //cout << __FUNCTION__ << " " << m_name << endl; + + element_list::iterator ei = m_children.begin(); + for (; ei != m_children.end(); ++ei) + { + delete (*ei); + } +} + +string element::to_string(bool nice, int indent) { - std::string xmlstr; - std::ostringstream xml(xmlstr); - + if (!m_modified) + return m_cached; + + string xmlstr; + ostringstream xml(xmlstr); + if (nice) - xml << std::string(indent, ' '); - + xml << string(indent, ' '); + xml << "<" << m_name; - - attribute_map::const_iterator ai = m_attributes.begin(); + + attribute_map::iterator ai = m_attributes.begin(); for (; ai != m_attributes.end(); ++ai) { xml << " " << ai->first << "=\"" << ai->second << "\""; } - + if (m_children.empty() && m_text.empty()) { xml << " />"; @@ -76,45 +100,77 @@ std::string element::to_string(bool nice, int indent) const element_list::const_iterator ei = m_children.begin(); for (; ei != m_children.end(); ++ei) { - xml << ei->to_string(nice, indent + 2); - + xml << (*ei)->to_string(nice, indent + 2); + if (nice) xml << "\n"; - } + } } else if (!m_text.empty()) { if (nice) - xml << std::string(indent + 2, ' '); - + xml << string(indent + 2, ' '); + xml << m_text << (nice ? "\n" : ""); } - + if (nice) - xml << std::string(indent, ' '); - + xml << string(indent, ' '); + xml << "</" << m_name << ">"; - + + m_cached = xml.str(); + + set_modified(false); + return xml.str(); } -element &element::add_child(const element &child) +element *element::add_child(element *child) { m_children.push_back(child); - return *this; + m_modified = true; + return this; } -template<> element &element::set_text<>(const std::string &text) +template<> element *element::set_text<>(const string &text) { m_text = text; - return *this; + m_modified = true; + return this; } -template<> element &element::set_attr<>(const std::string &name, - const std::string &value) +template<> element *element::set_attr<>(const string &name, + const string &value) { m_attributes[name] = value; - return *this; + m_modified = true; + 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 *clone = new element(*(*ei)); + clones.push_back(clone); + } + + return clones; +} + +void element::set_modified(bool modified) +{ + m_modified = modified; + + if (modified) + { + if (m_parent != NULL) + m_parent->set_modified(true); + } } } // namespace sxml @@ -35,52 +35,62 @@ namespace sxml { class element; -typedef std::vector<element> element_list; +typedef std::vector<element *> element_list; typedef std::map<std::string, std::string> attribute_map; class element { public: - + //! Constructs an empty element (i.e., no name, - //! children, attributes). - element(); - + //! children, attributes) with the specified parent. + explicit element(element *parent = NULL); + //! Copy constructor. element(const element &elem); - - //! Construcst an element with the specified name and text. - element(const std::string &name); - + + //! Constructs an element with the specified name and parent. + explicit element(const std::string &name, element *parent = NULL); + + virtual ~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) const; - - //! Adds a child element to this element. - element &add_child(const element &child); - + std::string to_string(bool nice = false, int indent = 0); + + //! Adds a child element to this element. + element *add_child(element *child); + //! Set the text for this element. An element can either have text //! or children. If an element has both, children take precedence //! when calling to_string(). - template<class T> - element &set_text(const T &text); + template<class T> element *set_text(const T &text); //! Set an attribute for this element with the specified name and //! value. - template<class T> - element &set_attr(const std::string &name, const T &value); + template<class T> element *set_attr(const std::string &name, + const T &value); private: - + + element_list clone_children() const; + + void set_modified(bool modified); + + element *m_parent; + element_list m_children; attribute_map m_attributes; - + std::string m_name; std::string m_text; + + std::string m_cached; + bool m_modified; }; -template<class T> element &element::set_text(const T &text) +template<class T> element *element::set_text(const T &text) { std::string s; std::stringstream ss(s); @@ -89,10 +99,10 @@ template<class T> element &element::set_text(const T &text) return set_text<std::string>(ss.str()); } -template<> element &element::set_text<>(const std::string &text); +template<> element *element::set_text<>(const std::string &text); -template<class T> -element &element::set_attr(const std::string &name, const T &value) +template<class T> element *element::set_attr(const std::string &name, + const T &value) { std::string s; std::stringstream ss(s); @@ -101,8 +111,8 @@ element &element::set_attr(const std::string &name, const T &value) return set_attr<std::string>(name, ss.str()); } -template<> -element &element::set_attr(const std::string &name, const std::string &value); +template<> element *element::set_attr(const std::string &name, + const std::string &value); } // namespace sxml |
