summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/util/xmlfile.cpp
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2016-11-17 01:44:03 +1100
committer Vas Crabb <vas@vastheman.com>2016-11-17 01:44:03 +1100
commit2354a42010b3a024f3c767105f95d0593641c4f1 (patch)
tree5c50e6db5f444ca4961c391b3efa983f3faabe50 /src/lib/util/xmlfile.cpp
parent31e0041051aaf5e14d2ec1be99bf26f4bdae743a (diff)
Turn xmlfile API into something that looks like C++
It's still a bit quirky but it's far better encapsulated before, and it plays nice with const (nw)
Diffstat (limited to 'src/lib/util/xmlfile.cpp')
-rw-r--r--src/lib/util/xmlfile.cpp879
1 files changed, 387 insertions, 492 deletions
diff --git a/src/lib/util/xmlfile.cpp b/src/lib/util/xmlfile.cpp
index 2b9bc8ed20d..08512611668 100644
--- a/src/lib/util/xmlfile.cpp
+++ b/src/lib/util/xmlfile.cpp
@@ -11,9 +11,13 @@
#include <assert.h>
#include "xmlfile.h"
-#include <ctype.h>
#include <expat.h>
+#include <algorithm>
+#include <cctype>
+#include <cstdlib>
+#include <cstring>
+
/***************************************************************************
CONSTANTS
@@ -32,7 +36,7 @@ struct xml_parse_info
XML_Parser parser;
xml_data_node * rootnode;
xml_data_node * curnode;
- uint32_t flags;
+ uint32_t flags;
};
@@ -42,19 +46,11 @@ struct xml_parse_info
***************************************************************************/
/* expat interfaces */
-static bool expat_setup_parser(xml_parse_info *parse_info, xml_parse_options *opts);
+static bool expat_setup_parser(xml_parse_info &info, xml_parse_options const *opts);
static void expat_element_start(void *data, const XML_Char *name, const XML_Char **attributes);
static void expat_data(void *data, const XML_Char *s, int len);
static void expat_element_end(void *data, const XML_Char *name);
-/* node/attributes additions */
-static xml_data_node *add_child(xml_data_node *parent, const char *name, const char *value);
-static xml_attribute_node *add_attribute(xml_data_node *node, const char *name, const char *value);
-
-/* recursive tree operations */
-static void write_node_recursive(xml_data_node *node, int indent, util::core_file &file);
-static void free_node_recursive(xml_data_node *node);
-
/***************************************************************************
@@ -66,7 +62,7 @@ static void free_node_recursive(xml_data_node *node);
string
-------------------------------------------------*/
-static const char *copystring(const char *input)
+static char *copystring(const char *input)
{
char *newstr;
@@ -89,7 +85,7 @@ static const char *copystring(const char *input)
the way
-------------------------------------------------*/
-static const char *copystring_lower(const char *input)
+static char *copystring_lower(const char *input)
{
char *newstr;
int i;
@@ -121,16 +117,10 @@ static const char *copystring_lower(const char *input)
object
-------------------------------------------------*/
-xml_data_node *xml_file_create(void)
+xml_data_node *xml_data_node::file_create()
{
- xml_data_node *rootnode;
-
- /* create a root node */
- rootnode = (xml_data_node *)malloc(sizeof(*rootnode));
- if (rootnode == nullptr)
- return nullptr;
- memset(rootnode, 0, sizeof(*rootnode));
- return rootnode;
+ try { return new xml_data_node(); }
+ catch (...) { return nullptr; }
}
@@ -139,13 +129,13 @@ xml_data_node *xml_file_create(void)
nodes
-------------------------------------------------*/
-xml_data_node *xml_file_read(util::core_file &file, xml_parse_options *opts)
+xml_data_node *xml_data_node::file_read(util::core_file &file, xml_parse_options const *opts)
{
- xml_parse_info parse_info;
+ xml_parse_info info;
int done;
/* set up the parser */
- if (!expat_setup_parser(&parse_info, opts))
+ if (!expat_setup_parser(info, opts))
return nullptr;
/* loop through the file and parse it */
@@ -158,27 +148,27 @@ xml_data_node *xml_file_read(util::core_file &file, xml_parse_options *opts)
done = file.eof();
/* parse the data */
- if (XML_Parse(parse_info.parser, tempbuf, bytes, done) == XML_STATUS_ERROR)
+ if (XML_Parse(info.parser, tempbuf, bytes, done) == XML_STATUS_ERROR)
{
if (opts != nullptr && opts->error != nullptr)
{
- opts->error->error_message = XML_ErrorString(XML_GetErrorCode(parse_info.parser));
- opts->error->error_line = XML_GetCurrentLineNumber(parse_info.parser);
- opts->error->error_column = XML_GetCurrentColumnNumber(parse_info.parser);
+ opts->error->error_message = XML_ErrorString(XML_GetErrorCode(info.parser));
+ opts->error->error_line = XML_GetCurrentLineNumber(info.parser);
+ opts->error->error_column = XML_GetCurrentColumnNumber(info.parser);
}
- xml_file_free(parse_info.rootnode);
- XML_ParserFree(parse_info.parser);
+ info.rootnode->file_free();
+ XML_ParserFree(info.parser);
return nullptr;
}
} while (!done);
/* free the parser */
- XML_ParserFree(parse_info.parser);
+ XML_ParserFree(info.parser);
/* return the root node */
- return parse_info.rootnode;
+ return info.rootnode;
}
@@ -187,35 +177,35 @@ xml_data_node *xml_file_read(util::core_file &file, xml_parse_options *opts)
nodes
-------------------------------------------------*/
-xml_data_node *xml_string_read(const char *string, xml_parse_options *opts)
+xml_data_node *xml_data_node::string_read(const char *string, xml_parse_options const *opts)
{
- xml_parse_info parse_info;
+ xml_parse_info info;
int length = (int)strlen(string);
/* set up the parser */
- if (!expat_setup_parser(&parse_info, opts))
+ if (!expat_setup_parser(info, opts))
return nullptr;
/* parse the data */
- if (XML_Parse(parse_info.parser, string, length, 1) == XML_STATUS_ERROR)
+ if (XML_Parse(info.parser, string, length, 1) == XML_STATUS_ERROR)
{
if (opts != nullptr && opts->error != nullptr)
{
- opts->error->error_message = XML_ErrorString(XML_GetErrorCode(parse_info.parser));
- opts->error->error_line = XML_GetCurrentLineNumber(parse_info.parser);
- opts->error->error_column = XML_GetCurrentColumnNumber(parse_info.parser);
+ opts->error->error_message = XML_ErrorString(XML_GetErrorCode(info.parser));
+ opts->error->error_line = XML_GetCurrentLineNumber(info.parser);
+ opts->error->error_column = XML_GetCurrentColumnNumber(info.parser);
}
- xml_file_free(parse_info.rootnode);
- XML_ParserFree(parse_info.parser);
+ info.rootnode->file_free();
+ XML_ParserFree(info.parser);
return nullptr;
}
/* free the parser */
- XML_ParserFree(parse_info.parser);
+ XML_ParserFree(info.parser);
/* return the root node */
- return parse_info.rootnode;
+ return info.rootnode;
}
@@ -223,10 +213,10 @@ xml_data_node *xml_string_read(const char *string, xml_parse_options *opts)
xml_file_write - write an XML tree to a file
-------------------------------------------------*/
-void xml_file_write(xml_data_node *node, util::core_file &file)
+void xml_data_node::file_write(util::core_file &file) const
{
/* ensure this is a root node */
- if (node->name != nullptr)
+ if (get_name())
return;
/* output a simple header */
@@ -234,8 +224,8 @@ void xml_file_write(xml_data_node *node, util::core_file &file)
file.printf("<!-- This file is autogenerated; comments and unknown tags will be stripped -->\n");
/* loop over children of the root and output */
- for (node = node->child; node; node = node->next)
- write_node_recursive(node, 0, file);
+ for (xml_data_node const *node = get_first_child(); node; node = node->get_next_sibling())
+ node->write_recursive(0, file);
}
@@ -243,13 +233,13 @@ void xml_file_write(xml_data_node *node, util::core_file &file)
xml_file_free - free an XML file object
-------------------------------------------------*/
-void xml_file_free(xml_data_node *node)
+void xml_data_node::file_free()
{
/* ensure this is a root node */
- if (node->name != nullptr)
+ if (get_name())
return;
- free_node_recursive(node);
+ delete this;
}
@@ -258,58 +248,199 @@ void xml_file_free(xml_data_node *node)
XML NODE MANAGEMENT
***************************************************************************/
+xml_data_node::xml_data_node()
+ : line(0)
+ , m_next(nullptr)
+ , m_first_child(nullptr)
+ , m_name(nullptr)
+ , m_value(nullptr)
+ , m_parent(nullptr)
+ , m_attributes()
+{
+}
+
+xml_data_node::xml_data_node(xml_data_node *parent, const char *name, const char *value)
+ : line(0)
+ , m_next(nullptr)
+ , m_first_child(nullptr)
+ , m_name(::copystring_lower(name))
+ , m_value(::copystring(value))
+ , m_parent(parent)
+ , m_attributes()
+{
+}
+
+
/*-------------------------------------------------
- xml_count_children - count the number of
- child nodes
+ free_node_recursive - recursively free
+ the data allocated to an XML node
-------------------------------------------------*/
-int xml_count_children(xml_data_node *node)
+xml_data_node::~xml_data_node()
+{
+ /* free name/value */
+ if (m_name)
+ std::free((void *)m_name);
+ if (m_value)
+ std::free((void *)m_value);
+
+ /* free the children */
+ for (xml_data_node *nchild = nullptr; m_first_child; m_first_child = nchild)
+ {
+ /* note the next node and free this node */
+ nchild = m_first_child->get_next_sibling();
+ delete m_first_child;
+ }
+}
+
+
+void xml_data_node::set_value(char const *value)
+{
+ if (m_value)
+ std::free((void *)m_value);
+
+ m_value = ::copystring(value);
+}
+
+
+void xml_data_node::append_value(char const *value, int length)
+{
+ if (length)
+ {
+ /* determine how much data we currently have */
+ int const oldlen = m_value ? int(std::strlen(m_value)) : 0;
+
+ /* realloc */
+ char *const newdata = reinterpret_cast<char *>(std::malloc(oldlen + length + 1));
+ if (newdata)
+ {
+ if (m_value)
+ {
+ std::memcpy(newdata, m_value, oldlen);
+ std::free((void *)m_value);
+ }
+ m_value = newdata;
+
+ /* copy in the new data and NUL-terminate */
+ std::memcpy(&newdata[oldlen], value, length);
+ newdata[oldlen + length] = '\0';
+ }
+ }
+}
+
+
+void xml_data_node::trim_whitespace()
+{
+ if (m_value)
+ {
+ char *start = m_value;
+ char *end = start + strlen(m_value);
+
+ /* first strip leading spaces */
+ while (*start && std::isspace(uint8_t(*start)))
+ start++;
+
+ /* then strip trailing spaces */
+ while ((end > start) && std::isspace(uint8_t(end[-1])))
+ end--;
+
+ if (start == end)
+ {
+ /* if nothing left, just free it */
+ std::free(m_value);
+ m_value = nullptr;
+ }
+ else
+ {
+ /* otherwise, memmove the data */
+ std::memmove(m_value, start, end - start);
+ m_value[end - start] = '\0';
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ xml_data_node::count_children - count the
+ number of child nodes
+-------------------------------------------------*/
+
+int xml_data_node::count_children() const
{
int count = 0;
/* loop over children and count */
- for (node = node->child; node; node = node->next)
+ for (xml_data_node const *node = get_first_child(); node; node = node->get_next_sibling())
count++;
return count;
}
/*-------------------------------------------------
- xml_get_sibling - find the next sibling of
- the specified node with the specified tag
+ xml_data_node::get_child - find the first
+ child of the specified node with the specified
+ tag
-------------------------------------------------*/
-xml_data_node *xml_get_sibling(xml_data_node *node, const char *name)
+xml_data_node *xml_data_node::get_child(const char *name)
{
- /* loop over siblings and find a matching name */
- for ( ; node; node = node->next)
- if (strcmp(node->name, name) == 0)
- return node;
- return nullptr;
+ return m_first_child ? m_first_child->get_sibling(name) : nullptr;
+}
+
+xml_data_node const *xml_data_node::get_child(const char *name) const
+{
+ return m_first_child ? m_first_child->get_sibling(name) : nullptr;
}
/*-------------------------------------------------
- xml_find_matching_sibling - find the next
+ xml_find_first_matching_child - find the first
+ child of the specified node with the
+ specified tag or attribute/value pair
+-------------------------------------------------*/
+
+xml_data_node *xml_data_node::find_first_matching_child(const char *name, const char *attribute, const char *matchval)
+{
+ return m_first_child ? m_first_child->find_matching_sibling(name, attribute, matchval) : nullptr;
+}
+
+xml_data_node const *xml_data_node::find_first_matching_child(const char *name, const char *attribute, const char *matchval) const
+{
+ return m_first_child ? m_first_child->find_matching_sibling(name, attribute, matchval) : nullptr;
+}
+
+
+/*-------------------------------------------------
+ xml_data_node::get_next_sibling - find the
+ next sibling of the specified node with the
+ specified tag
+-------------------------------------------------*/
+
+xml_data_node *xml_data_node::get_next_sibling(const char *name)
+{
+ return m_next ? m_next->get_sibling(name) : nullptr;
+}
+
+xml_data_node const *xml_data_node::get_next_sibling(const char *name) const
+{
+ return m_next ? m_next->get_sibling(name) : nullptr;
+}
+
+
+/*-------------------------------------------------
+ xml_find_next_matching_sibling - find the next
sibling of the specified node with the
specified tag or attribute/value pair
-------------------------------------------------*/
-xml_data_node *xml_find_matching_sibling(xml_data_node *node, const char *name, const char *attribute, const char *matchval)
+xml_data_node *xml_data_node::find_next_matching_sibling(const char *name, const char *attribute, const char *matchval)
{
- /* loop over siblings and find a matching attribute */
- for ( ; node; node = node->next)
- {
- /* can pass nullptr as a wildcard for the node name */
- if (name == nullptr || strcmp(name, node->name) == 0)
- {
- /* find a matching attribute */
- xml_attribute_node *attr = xml_get_attribute(node, attribute);
- if (attr != nullptr && strcmp(attr->value, matchval) == 0)
- return node;
- }
- }
- return nullptr;
+ return m_next ? m_next->find_matching_sibling(name, attribute, matchval) : nullptr;
+}
+
+xml_data_node const *xml_data_node::find_next_matching_sibling(const char *name, const char *attribute, const char *matchval) const
+{
+ return m_next ? m_next->find_matching_sibling(name, attribute, matchval) : nullptr;
}
@@ -318,10 +449,25 @@ xml_data_node *xml_find_matching_sibling(xml_data_node *node, const char *name,
given node
-------------------------------------------------*/
-xml_data_node *xml_add_child(xml_data_node *node, const char *name, const char *value)
+xml_data_node *xml_data_node::add_child(const char *name, const char *value)
{
- /* just a standard add child */
- return add_child(node, name, value);
+ /* new element: create a new node */
+ xml_data_node *node;
+ try { node = new xml_data_node(this, name, value); }
+ catch (...) { return nullptr; }
+
+ if (!node->get_name() || (!node->get_value() && value))
+ {
+ delete node;
+ return nullptr;
+ }
+
+ /* add us to the end of the list of siblings */
+ xml_data_node **pnode;
+ for (pnode = &m_first_child; *pnode; pnode = &(*pnode)->m_next) { }
+ *pnode = node;
+
+ return node;
}
@@ -330,17 +476,15 @@ xml_data_node *xml_add_child(xml_data_node *node, const char *name, const char *
the specified type; if not found, add one
-------------------------------------------------*/
-xml_data_node *xml_get_or_add_child(xml_data_node *node, const char *name, const char *value)
+xml_data_node *xml_data_node::get_or_add_child(const char *name, const char *value)
{
- xml_data_node *child;
-
/* find the child first */
- child = xml_get_sibling(node->child, name);
- if (child != nullptr)
+ xml_data_node *const child = m_first_child->get_sibling(name);
+ if (child)
return child;
/* if not found, do a standard add child */
- return add_child(node, name, value);
+ return add_child(name, value);
}
@@ -349,20 +493,88 @@ xml_data_node *xml_get_or_add_child(xml_data_node *node, const char *name, const
children
-------------------------------------------------*/
-void xml_delete_node(xml_data_node *node)
+void xml_data_node::delete_node()
{
- xml_data_node **pnode;
-
/* first unhook us from the list of children of our parent */
- for (pnode = &node->parent->child; *pnode; pnode = &(*pnode)->next)
- if (*pnode == node)
+ if (m_parent)
+ {
+ for (xml_data_node **pnode = &m_parent->m_first_child; *pnode; pnode = &(*pnode)->m_next)
{
- *pnode = node->next;
- break;
+ if (*pnode == this)
+ {
+ *pnode = this->m_next;
+ break;
+ }
}
+ }
/* now free ourselves and our children */
- free_node_recursive(node);
+ delete this;
+}
+
+
+/*-------------------------------------------------
+ xml_get_next_sibling - find the next sibling of
+ the specified node with the specified tag
+-------------------------------------------------*/
+
+xml_data_node *xml_data_node::get_sibling(const char *name)
+{
+ /* loop over siblings and find a matching name */
+ for (xml_data_node *node = this; node; node = node->get_next_sibling())
+ if (strcmp(node->get_name(), name) == 0)
+ return node;
+ return nullptr;
+}
+
+xml_data_node const *xml_data_node::get_sibling(const char *name) const
+{
+ /* loop over siblings and find a matching name */
+ for (xml_data_node const *node = this; node; node = node->get_next_sibling())
+ if (strcmp(node->get_name(), name) == 0)
+ return node;
+ return nullptr;
+}
+
+
+/*-------------------------------------------------
+ xml_find_matching_sibling - find the next
+ sibling of the specified node with the
+ specified tag or attribute/value pair
+-------------------------------------------------*/
+
+xml_data_node *xml_data_node::find_matching_sibling(const char *name, const char *attribute, const char *matchval)
+{
+ /* loop over siblings and find a matching attribute */
+ for (xml_data_node *node = this; node; node = node->get_next_sibling())
+ {
+ /* can pass nullptr as a wildcard for the node name */
+ if (!name || !strcmp(name, node->get_name()))
+ {
+ /* find a matching attribute */
+ attribute_node const *const attr = node->get_attribute(attribute);
+ if (attr && !strcmp(attr->value.c_str(), matchval))
+ return node;
+ }
+ }
+ return nullptr;
+}
+
+xml_data_node const *xml_data_node::find_matching_sibling(const char *name, const char *attribute, const char *matchval) const
+{
+ /* loop over siblings and find a matching attribute */
+ for (xml_data_node const *node = this; node; node = node->get_next_sibling())
+ {
+ /* can pass nullptr as a wildcard for the node name */
+ if (!name || !strcmp(name, node->get_name()))
+ {
+ /* find a matching attribute */
+ attribute_node const *const attr = node->get_attribute(attribute);
+ if (attr && !strcmp(attr->value.c_str(), matchval))
+ return node;
+ }
+ }
+ return nullptr;
}
@@ -371,19 +583,32 @@ void xml_delete_node(xml_data_node *node)
XML ATTRIBUTE MANAGEMENT
***************************************************************************/
+bool xml_data_node::has_attribute(const char *attribute) const
+{
+ return get_attribute(attribute) != nullptr;
+}
+
+
/*-------------------------------------------------
xml_get_attribute - get the value of the
specified attribute, or nullptr if not found
-------------------------------------------------*/
-xml_attribute_node *xml_get_attribute(xml_data_node *node, const char *attribute)
+xml_data_node::attribute_node *xml_data_node::get_attribute(const char *attribute)
{
- xml_attribute_node *anode;
+ /* loop over attributes and find a match */
+ for (attribute_node &anode : m_attributes)
+ if (strcmp(anode.name.c_str(), attribute) == 0)
+ return &anode;
+ return nullptr;
+}
+xml_data_node::attribute_node const *xml_data_node::get_attribute(const char *attribute) const
+{
/* loop over attributes and find a match */
- for (anode = node->attribute; anode; anode = anode->next)
- if (strcmp(anode->name, attribute) == 0)
- return anode;
+ for (attribute_node const &anode : m_attributes)
+ if (strcmp(anode.name.c_str(), attribute) == 0)
+ return &anode;
return nullptr;
}
@@ -394,10 +619,10 @@ xml_attribute_node *xml_get_attribute(xml_data_node *node, const char *attribute
found, return = the provided default
-------------------------------------------------*/
-const char *xml_get_attribute_string(xml_data_node *node, const char *attribute, const char *defvalue)
+const char *xml_data_node::get_attribute_string(const char *attribute, const char *defvalue) const
{
- xml_attribute_node *attr = xml_get_attribute(node, attribute);
- return attr ? attr->value : defvalue;
+ attribute_node const *attr = get_attribute(attribute);
+ return attr ? attr->value.c_str() : defvalue;
}
@@ -407,9 +632,9 @@ const char *xml_get_attribute_string(xml_data_node *node, const char *attribute,
found, return = the provided default
-------------------------------------------------*/
-int xml_get_attribute_int(xml_data_node *node, const char *attribute, int defvalue)
+int xml_data_node::get_attribute_int(const char *attribute, int defvalue) const
{
- const char *string = xml_get_attribute_string(node, attribute, nullptr);
+ char const *const string = get_attribute_string(attribute, nullptr);
int value;
unsigned int uvalue;
@@ -430,9 +655,9 @@ int xml_get_attribute_int(xml_data_node *node, const char *attribute, int defval
format of the given integer attribute
-------------------------------------------------*/
-int xml_get_attribute_int_format(xml_data_node *node, const char *attribute)
+int xml_data_node::get_attribute_int_format(const char *attribute) const
{
- const char *string = xml_get_attribute_string(node, attribute, nullptr);
+ char const *const string = get_attribute_string(attribute, nullptr);
if (string == nullptr)
return XML_INT_FORMAT_DECIMAL;
@@ -452,21 +677,9 @@ int xml_get_attribute_int_format(xml_data_node *node, const char *attribute)
found, return = the provided default
-------------------------------------------------*/
-/**
- * @fn float xml_get_attribute_float(xml_data_node *node, const char *attribute, float defvalue)
- *
- * @brief XML get attribute float.
- *
- * @param [in,out] node If non-null, the node.
- * @param attribute The attribute.
- * @param defvalue The defvalue.
- *
- * @return A float.
- */
-
-float xml_get_attribute_float(xml_data_node *node, const char *attribute, float defvalue)
+float xml_data_node::get_attribute_float(const char *attribute, float defvalue) const
{
- const char *string = xml_get_attribute_string(node, attribute, nullptr);
+ char const *const string = get_attribute_string(attribute, nullptr);
float value;
if (string == nullptr || sscanf(string, "%f", &value) != 1)
@@ -480,38 +693,23 @@ float xml_get_attribute_float(xml_data_node *node, const char *attribute, float
string value on the node
-------------------------------------------------*/
-/**
- * @fn xml_attribute_node *xml_set_attribute(xml_data_node *node, const char *name, const char *value)
- *
- * @brief XML set attribute.
- *
- * @param [in,out] node If non-null, the node.
- * @param name The name.
- * @param value The value.
- *
- * @return null if it fails, else an xml_attribute_node*.
- */
-
-xml_attribute_node *xml_set_attribute(xml_data_node *node, const char *name, const char *value)
+void xml_data_node::set_attribute(const char *name, const char *value)
{
- xml_attribute_node *anode;
+ attribute_node *anode;
/* first find an existing one to replace */
- anode = xml_get_attribute(node, name);
+ anode = get_attribute(name);
- /* if we found it, free the old value and replace it */
if (anode != nullptr)
{
- if (anode->value != nullptr)
- free((void *)anode->value);
- anode->value = copystring(value);
+ /* if we found it, free the old value and replace it */
+ anode->value = value;
}
-
- /* otherwise, create a new node */
else
- anode = add_attribute(node, name, value);
-
- return anode;
+ {
+ /* otherwise, create a new node */
+ add_attribute(name, value);
+ }
}
@@ -520,23 +718,11 @@ xml_attribute_node *xml_set_attribute(xml_data_node *node, const char *name, con
integer value on the node
-------------------------------------------------*/
-/**
- * @fn xml_attribute_node *xml_set_attribute_int(xml_data_node *node, const char *name, int value)
- *
- * @brief XML set attribute int.
- *
- * @param [in,out] node If non-null, the node.
- * @param name The name.
- * @param value The value.
- *
- * @return null if it fails, else an xml_attribute_node*.
- */
-
-xml_attribute_node *xml_set_attribute_int(xml_data_node *node, const char *name, int value)
+void xml_data_node::set_attribute_int(const char *name, int value)
{
char buffer[100];
sprintf(buffer, "%d", value);
- return xml_set_attribute(node, name, buffer);
+ set_attribute(name, buffer);
}
@@ -545,23 +731,11 @@ xml_attribute_node *xml_set_attribute_int(xml_data_node *node, const char *name,
float value on the node
-------------------------------------------------*/
-/**
- * @fn xml_attribute_node *xml_set_attribute_float(xml_data_node *node, const char *name, float value)
- *
- * @brief XML set attribute float.
- *
- * @param [in,out] node If non-null, the node.
- * @param name The name.
- * @param value The value.
- *
- * @return null if it fails, else an xml_attribute_node*.
- */
-
-xml_attribute_node *xml_set_attribute_float(xml_data_node *node, const char *name, float value)
+void xml_data_node::set_attribute_float(const char *name, float value)
{
char buffer[100];
sprintf(buffer, "%f", (double) value);
- return xml_set_attribute(node, name, buffer);
+ set_attribute(name, buffer);
}
@@ -575,16 +749,6 @@ xml_attribute_node *xml_set_attribute_float(xml_data_node *node, const char *nam
to ensure it doesn't contain embedded tags
-------------------------------------------------*/
-/**
- * @fn const char *xml_normalize_string(const char *string)
- *
- * @brief XML normalize string.
- *
- * @param string The string.
- *
- * @return null if it fails, else a char*.
- */
-
const char *xml_normalize_string(const char *string)
{
static char buffer[1024];
@@ -623,16 +787,6 @@ const char *xml_normalize_string(const char *string)
systems
-------------------------------------------------*/
-/**
- * @fn static void *expat_malloc(size_t size)
- *
- * @brief Expat malloc.
- *
- * @param size The size.
- *
- * @return null if it fails, else a void*.
- */
-
static void *expat_malloc(size_t size)
{
uint32_t *result = (uint32_t *)malloc(size + 4 * sizeof(uint32_t));
@@ -640,31 +794,12 @@ static void *expat_malloc(size_t size)
return &result[4];
}
-/**
- * @fn static void expat_free(void *ptr)
- *
- * @brief Expat free.
- *
- * @param [in,out] ptr If non-null, the pointer.
- */
-
static void expat_free(void *ptr)
{
if (ptr != nullptr)
free(&((uint32_t *)ptr)[-4]);
}
-/**
- * @fn static void *expat_realloc(void *ptr, size_t size)
- *
- * @brief Expat realloc.
- *
- * @param [in,out] ptr If non-null, the pointer.
- * @param size The size.
- *
- * @return null if it fails, else a void*.
- */
-
static void *expat_realloc(void *ptr, size_t size)
{
void *newptr = expat_malloc(size);
@@ -684,26 +819,15 @@ static void *expat_realloc(void *ptr, size_t size)
expat_setup_parser - set up expat for parsing
-------------------------------------------------*/
-/**
- * @fn static int expat_setup_parser(xml_parse_info *parse_info, xml_parse_options *opts)
- *
- * @brief Expat setup parser.
- *
- * @param [in,out] parse_info If non-null, information describing the parse.
- * @param [in,out] opts If non-null, options for controlling the operation.
- *
- * @return An int.
- */
-
-static bool expat_setup_parser(xml_parse_info *parse_info, xml_parse_options *opts)
+static bool expat_setup_parser(xml_parse_info &info, xml_parse_options const *opts)
{
XML_Memory_Handling_Suite memcallbacks;
- /* setup parse_info structure */
- memset(parse_info, 0, sizeof(*parse_info));
+ /* setup info structure */
+ memset(&info, 0, sizeof(info));
if (opts != nullptr)
{
- parse_info->flags = opts->flags;
+ info.flags = opts->flags;
if (opts->error != nullptr)
{
opts->error->error_message = nullptr;
@@ -713,30 +837,30 @@ static bool expat_setup_parser(xml_parse_info *parse_info, xml_parse_options *op
}
/* create a root node */
- parse_info->rootnode = xml_file_create();
- if (parse_info->rootnode == nullptr)
+ info.rootnode = xml_data_node::file_create();
+ if (info.rootnode == nullptr)
return false;
- parse_info->curnode = parse_info->rootnode;
+ info.curnode = info.rootnode;
/* create the XML parser */
memcallbacks.malloc_fcn = expat_malloc;
memcallbacks.realloc_fcn = expat_realloc;
memcallbacks.free_fcn = expat_free;
- parse_info->parser = XML_ParserCreate_MM(nullptr, &memcallbacks, nullptr);
- if (parse_info->parser == nullptr)
+ info.parser = XML_ParserCreate_MM(nullptr, &memcallbacks, nullptr);
+ if (info.parser == nullptr)
{
- free(parse_info->rootnode);
+ info.rootnode->file_free();
return false;
}
/* configure the parser */
- XML_SetElementHandler(parse_info->parser, expat_element_start, expat_element_end);
- XML_SetCharacterDataHandler(parse_info->parser, expat_data);
- XML_SetUserData(parse_info->parser, parse_info);
+ XML_SetElementHandler(info.parser, expat_element_start, expat_element_end);
+ XML_SetCharacterDataHandler(info.parser, expat_data);
+ XML_SetUserData(info.parser, &info);
/* optional parser initialization step */
if (opts != nullptr && opts->init_parser != nullptr)
- (*opts->init_parser)(parse_info->parser);
+ (*opts->init_parser)(info.parser);
return true;
}
@@ -746,16 +870,6 @@ static bool expat_setup_parser(xml_parse_info *parse_info, xml_parse_options *op
element
-------------------------------------------------*/
-/**
- * @fn static void expat_element_start(void *data, const XML_Char *name, const XML_Char **attributes)
- *
- * @brief Expat element start.
- *
- * @param [in,out] data If non-null, the data.
- * @param name The name.
- * @param attributes The attributes.
- */
-
static void expat_element_start(void *data, const XML_Char *name, const XML_Char **attributes)
{
xml_parse_info *parse_info = (xml_parse_info *) data;
@@ -764,7 +878,7 @@ static void expat_element_start(void *data, const XML_Char *name, const XML_Char
int attr;
/* add a new child node to the current node */
- newnode = add_child(*curnode, name, nullptr);
+ newnode = (*curnode)->add_child(name, nullptr);
if (newnode == nullptr)
return;
@@ -773,7 +887,7 @@ static void expat_element_start(void *data, const XML_Char *name, const XML_Char
/* add all the attributes as well */
for (attr = 0; attributes[attr]; attr += 2)
- add_attribute(newnode, attributes[attr+0], attributes[attr+1]);
+ newnode->add_attribute(attributes[attr+0], attributes[attr+1]);
/* set us up as the current node */
*curnode = newnode;
@@ -785,46 +899,11 @@ static void expat_element_start(void *data, const XML_Char *name, const XML_Char
element data
-------------------------------------------------*/
-/**
- * @fn static void expat_data(void *data, const XML_Char *s, int len)
- *
- * @brief Expat data.
- *
- * @param [in,out] data If non-null, the data.
- * @param s The const XML_Char * to process.
- * @param len The length.
- */
-
static void expat_data(void *data, const XML_Char *s, int len)
{
xml_parse_info *parse_info = (xml_parse_info *) data;
xml_data_node **curnode = &parse_info->curnode;
- int oldlen = 0;
- char *newdata;
-
- /* if no data, skip */
- if (len == 0)
- return;
-
- /* determine how much data we currently have */
- if ((*curnode)->value != nullptr)
- oldlen = (int)strlen((*curnode)->value);
-
- /* realloc */
- newdata = (char *)malloc(oldlen + len + 1);
- if (newdata == nullptr)
- return;
- if ((*curnode)->value != nullptr)
- {
- memcpy(newdata, (*curnode)->value, oldlen);
- free((void *)(*curnode)->value);
- }
- (*curnode)->value = newdata;
-
- /* copy in the new data a NULL-terminate */
- memcpy(&newdata[oldlen], s, len);
- newdata[oldlen + len] = 0;
- (*curnode)->value = newdata;
+ (*curnode)->append_value(s, len);
}
@@ -833,53 +912,17 @@ static void expat_data(void *data, const XML_Char *s, int len)
of an element
-------------------------------------------------*/
-/**
- * @fn static void expat_element_end(void *data, const XML_Char *name)
- *
- * @brief Expat element end.
- *
- * @param [in,out] data If non-null, the data.
- * @param name The name.
- */
-
static void expat_element_end(void *data, const XML_Char *name)
{
xml_parse_info *parse_info = (xml_parse_info *) data;
xml_data_node **curnode = &parse_info->curnode;
- char *orig;
/* strip leading/trailing spaces from the value data */
- orig = (char *)(*curnode)->value;
- if (orig != nullptr && !(parse_info->flags & XML_PARSE_FLAG_WHITESPACE_SIGNIFICANT))
- {
- char *start = orig;
- char *end = start + strlen(start);
-
- /* first strip leading spaces */
- while (*start && isspace((uint8_t)*start))
- start++;
-
- /* then strip trailing spaces */
- while (end > start && isspace((uint8_t)end[-1]))
- end--;
-
- /* if nothing left, just free it */
- if (start == end)
- {
- free(orig);
- (*curnode)->value = nullptr;
- }
-
- /* otherwise, memmove the data */
- else
- {
- memmove(orig, start, end - start);
- orig[end - start] = 0;
- }
- }
+ if (!(parse_info->flags & XML_PARSE_FLAG_WHITESPACE_SIGNIFICANT))
+ (*curnode)->trim_whitespace();
/* back us up a node */
- *curnode = (*curnode)->parent;
+ *curnode = (*curnode)->get_parent();
}
@@ -889,105 +932,20 @@ static void expat_element_end(void *data, const XML_Char *name)
***************************************************************************/
/*-------------------------------------------------
- add_child - add a new node to the parent
--------------------------------------------------*/
-
-/**
- * @fn static xml_data_node *add_child(xml_data_node *parent, const char *name, const char *value)
- *
- * @brief Adds a child.
- *
- * @param [in,out] parent If non-null, the parent.
- * @param name The name.
- * @param value The value.
- *
- * @return null if it fails, else an xml_data_node*.
- */
-
-static xml_data_node *add_child(xml_data_node *parent, const char *name, const char *value)
-{
- xml_data_node **pnode;
- xml_data_node *node;
-
- /* new element: create a new node */
- node = (xml_data_node *)malloc(sizeof(*node));
- if (node == nullptr)
- return nullptr;
-
- /* initialize the members */
- node->next = nullptr;
- node->parent = parent;
- node->child = nullptr;
- node->name = copystring_lower(name);
- if (node->name == nullptr)
- {
- free(node);
- return nullptr;
- }
- node->value = copystring(value);
- if (node->value == nullptr && value != nullptr)
- {
- free((void *)node->name);
- free(node);
- return nullptr;
- }
- node->attribute = nullptr;
-
- /* add us to the end of the list of siblings */
- for (pnode = &parent->child; *pnode; pnode = &(*pnode)->next) { }
- *pnode = node;
-
- return node;
-}
-
-
-/*-------------------------------------------------
add_attribute - add a new attribute to the
given node
-------------------------------------------------*/
-/**
- * @fn static xml_attribute_node *add_attribute(xml_data_node *node, const char *name, const char *value)
- *
- * @brief Adds an attribute.
- *
- * @param [in,out] node If non-null, the node.
- * @param name The name.
- * @param value The value.
- *
- * @return null if it fails, else an xml_attribute_node*.
- */
-
-static xml_attribute_node *add_attribute(xml_data_node *node, const char *name, const char *value)
+void xml_data_node::add_attribute(const char *name, const char *value)
{
- xml_attribute_node *anode, **panode;
-
- /* allocate a new attribute node */
- anode = (xml_attribute_node *)malloc(sizeof(*anode));
- if (anode == nullptr)
- return nullptr;
-
- /* fill it in */
- anode->next = nullptr;
- anode->name = copystring_lower(name);
- if (anode->name == nullptr)
+ try
{
- free(anode);
- return nullptr;
+ attribute_node &anode = *m_attributes.emplace(m_attributes.end(), name, value);
+ std::transform(anode.name.begin(), anode.name.end(), anode.name.begin(), [] (char ch) { return std::tolower(uint8_t(ch)); });
}
- anode->value = copystring(value);
- if (anode->value == nullptr)
+ catch (...)
{
- free((void *)anode->name);
- free(anode);
- return nullptr;
}
-
- /* add us to the end of the list of attributes */
- for (panode = &node->attribute; *panode; panode = &(*panode)->next) { }
- *panode = anode;
-
- return anode;
}
@@ -1001,100 +959,37 @@ static xml_attribute_node *add_attribute(xml_data_node *node, const char *name,
an XML node and its children to a file
-------------------------------------------------*/
-/**
- * @fn static void write_node_recursive(xml_data_node *node, int indent, util::core_file &file)
- *
- * @brief Writes a node recursive.
- *
- * @param [in,out] node If non-null, the node.
- * @param indent The indent.
- * @param [in,out] file If non-null, the file.
- */
-
-static void write_node_recursive(xml_data_node *node, int indent, util::core_file &file)
+void xml_data_node::write_recursive(int indent, util::core_file &file) const
{
- xml_attribute_node *anode;
- xml_data_node *child;
-
/* output this tag */
- file.printf("%*s<%s", indent, "", node->name);
+ file.printf("%*s<%s", indent, "", get_name());
/* output any attributes */
- for (anode = node->attribute; anode; anode = anode->next)
- file.printf(" %s=\"%s\"", anode->name, anode->value);
+ for (attribute_node const &anode : m_attributes)
+ file.printf(" %s=\"%s\"", anode.name, anode.value);
- /* if there are no children and no value, end the tag here */
- if (node->child == nullptr && node->value == nullptr)
+ if (!get_first_child() && !get_value())
+ {
+ /* if there are no children and no value, end the tag here */
file.printf(" />\n");
-
- /* otherwise, close this tag and output more stuff */
+ }
else
{
+ /* otherwise, close this tag and output more stuff */
file.printf(">\n");
/* if there is a value, output that here */
- if (node->value != nullptr)
- file.printf("%*s%s\n", indent + 4, "", node->value);
+ if (get_value())
+ file.printf("%*s%s\n", indent + 4, "", get_value());
/* loop over children and output them as well */
- if (node->child != nullptr)
+ if (get_first_child())
{
- for (child = node->child; child; child = child->next)
- write_node_recursive(child, indent + 4, file);
+ for (xml_data_node const *child = this->get_first_child(); child; child = child->get_next_sibling())
+ child->write_recursive(indent + 4, file);
}
/* write a closing tag */
- file.printf("%*s</%s>\n", indent, "", node->name);
- }
-}
-
-
-/*-------------------------------------------------
- free_node_recursive - recursively free
- the data allocated to an XML node
--------------------------------------------------*/
-
-/**
- * @fn static void free_node_recursive(xml_data_node *node)
- *
- * @brief Free node recursive.
- *
- * @param [in,out] node If non-null, the node.
- */
-
-static void free_node_recursive(xml_data_node *node)
-{
- xml_attribute_node *anode, *nanode;
- xml_data_node *child, *nchild;
-
- /* free name/value */
- if (node->name != nullptr)
- free((void *)node->name);
- if (node->value != nullptr)
- free((void *)node->value);
-
- /* free attributes */
- for (anode = node->attribute; anode; anode = nanode)
- {
- /* free name/value */
- if (anode->name != nullptr)
- free((void *)anode->name);
- if (anode->value != nullptr)
- free((void *)anode->value);
-
- /* note the next node and free this node */
- nanode = anode->next;
- free(anode);
- }
-
- /* free the children */
- for (child = node->child; child; child = nchild)
- {
- /* note the next node and free this node */
- nchild = child->next;
- free_node_recursive(child);
+ file.printf("%*s</%s>\n", indent, "", get_name());
}
-
- /* finally free ourself */
- free(node);
}