aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOskari Timperi <oskari.timperi@iki.fi>2011-05-26 16:02:22 +0300
committerOskari Timperi <oskari.timperi@iki.fi>2011-05-26 16:02:22 +0300
commitb7a61ba83cbfa0f9684ce9cf476d4c819d1f04ba (patch)
tree65d7e04a8f1930555b654ff2757bc9696434dbbb
parent279a262eab521434cdcf1ab33dab84bb9c0df923 (diff)
downloadsxml-b7a61ba83cbfa0f9684ce9cf476d4c819d1f04ba.tar.gz
sxml-b7a61ba83cbfa0f9684ce9cf476d4c819d1f04ba.zip
Use element* instead of element& and introduce parenting
-rw-r--r--sxml.cpp116
-rw-r--r--sxml.h62
2 files changed, 122 insertions, 56 deletions
diff --git a/sxml.cpp b/sxml.cpp
index 916352b..8b0cf0c 100644
--- a/sxml.cpp
+++ b/sxml.cpp
@@ -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
diff --git a/sxml.h b/sxml.h
index 2080a59..527288f 100644
--- a/sxml.h
+++ b/sxml.h
@@ -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