summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2017-07-21 13:03:44 +1000
committer Vas Crabb <vas@vastheman.com>2017-07-21 13:03:44 +1000
commitd7984c7d0ce594ecb34275fdabb817bdbe261647 (patch)
treeb8a771b129db3ca6105111e202b0d1deab813999 /src/lib
parent05e84dccc04849857ebc4460084bdafc872d5815 (diff)
Add a method for copying part of an XML tree into another tree and use it to fix Cocoa debugger fatal error
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/util/xmlfile.cpp60
-rw-r--r--src/lib/util/xmlfile.h7
2 files changed, 60 insertions, 7 deletions
diff --git a/src/lib/util/xmlfile.cpp b/src/lib/util/xmlfile.cpp
index 893018f5384..11d18482e33 100644
--- a/src/lib/util/xmlfile.cpp
+++ b/src/lib/util/xmlfile.cpp
@@ -70,7 +70,7 @@ file::~file() { }
file::ptr file::create()
{
- try { return ptr(new file()); }
+ try { return ptr(new file); }
catch (...) { return ptr(); }
}
@@ -213,7 +213,12 @@ data_node::data_node(data_node *parent, const char *name, const char *value)
data_node::~data_node()
{
- /* free the children */
+ free_children();
+}
+
+
+void data_node::free_children()
+{
for (data_node *nchild = nullptr; m_first_child; m_first_child = nchild)
{
/* note the next node and free this node */
@@ -382,6 +387,43 @@ data_node *data_node::get_or_add_child(const char *name, const char *value)
}
+// recursively copy as child of another node
+data_node *data_node::copy_into(data_node &parent) const
+{
+ data_node *const result = parent.add_child(get_name(), get_value());
+ result->m_attributes = m_attributes;
+
+ data_node *dst = result;
+ data_node const *src = get_first_child();
+ while (src && (&parent != dst))
+ {
+ dst = dst->add_child(src->get_name(), src->get_value());
+ dst->m_attributes = src->m_attributes;
+ data_node const *next = src->get_first_child();
+ if (next)
+ {
+ src = next;
+ }
+ else
+ {
+ dst = dst->get_parent();
+ next = src->get_next_sibling();
+ if (next)
+ {
+ src = next;
+ }
+ else
+ {
+ dst = dst->get_parent();
+ src = src->get_parent()->get_next_sibling();
+ }
+ }
+ }
+
+ return result;
+}
+
+
/*-------------------------------------------------
delete_node - delete a node and its
children
@@ -389,9 +431,10 @@ data_node *data_node::get_or_add_child(const char *name, const char *value)
void data_node::delete_node()
{
- /* first unhook us from the list of children of our parent */
+ /* don't allow deletion of document root */
if (m_parent)
{
+ /* first unhook us from the list of children of our parent */
for (data_node **pnode = &m_parent->m_first_child; *pnode; pnode = &(*pnode)->m_next)
{
if (*pnode == this)
@@ -400,10 +443,15 @@ void data_node::delete_node()
break;
}
}
- }
- /* now free ourselves and our children */
- delete this;
+ /* now free ourselves and our children */
+ delete this;
+ }
+ else
+ {
+ /* remove all children of document root */
+ free_children();
+ }
}
diff --git a/src/lib/util/xmlfile.h b/src/lib/util/xmlfile.h
index 5c4672373d3..5e55dbf310e 100644
--- a/src/lib/util/xmlfile.h
+++ b/src/lib/util/xmlfile.h
@@ -118,6 +118,9 @@ public:
// either return an existing child node or create one if it doesn't exist
data_node *get_or_add_child(const char *name, const char *value);
+ // recursively copy as child of another node
+ data_node *copy_into(data_node &parent) const;
+
// delete a node and its children
void delete_node();
@@ -189,6 +192,8 @@ private:
attribute_node *get_attribute(const char *attribute);
attribute_node const *get_attribute(const char *attribute) const;
+ void free_children();
+
data_node * m_next;
data_node * m_first_child;
@@ -208,7 +213,7 @@ public:
~file();
- // create a new empty xml file object
+ // create a new, empty XML file
static ptr create();
// parse an XML file into its nodes