Skip to content

Commit

Permalink
#6097: All xml::Document or xml::Node operations now require the mute…
Browse files Browse the repository at this point in the history
…x to be locked
  • Loading branch information
codereader committed Sep 11, 2022
1 parent 050f5e0 commit 24399fa
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 27 deletions.
2 changes: 2 additions & 0 deletions libs/xmlutil/Document.cpp
Expand Up @@ -127,6 +127,8 @@ Node Document::addTopLevelNode(const std::string& name)

Node Document::getTopLevelNode() const
{
std::lock_guard lock(_lock);

if (!isValid())
{
// Invalid Document, return a NULL node
Expand Down
73 changes: 46 additions & 27 deletions libs/xmlutil/Node.cpp
@@ -1,7 +1,10 @@
#include "Node.h"

#include <mutex>
#include <libxml/parser.h>

#include "Document.h"

namespace xml
{

Expand All @@ -15,38 +18,41 @@ bool Node::isValid() const
return _xmlNode != nullptr;
}

// Return the name of a node
std::string Node::getName() const
{
if (_xmlNode) {
return std::string( reinterpret_cast<const char*>(_xmlNode->name) );
}
else {
return "";
std::lock_guard lock(_owner->getLock());

if (_xmlNode)
{
return std::string(reinterpret_cast<const char*>(_xmlNode->name));
}

return {};
}

// Return a NodeList of all children of this node
NodeList Node::getChildren() const
{
// Lock the document to collect the children
std::lock_guard lock(_owner->getLock());

NodeList retval;

// Iterate throught the list of children, adding each child node
// to the return list if it matches the requested name
for (xmlNodePtr child = _xmlNode->children; child != NULL; child = child->next) {
for (auto child = _xmlNode->children; child != nullptr; child = child->next)
{
retval.emplace_back(_owner, child);
}

return retval;
}

// Creates a new child with no content (i.e. <name />)
Node Node::createChild(const std::string& name)
{
std::lock_guard lock(_owner->getLock());

xmlChar* nodeName = xmlCharStrdup(name.c_str());

// Create a new child under the contained node
xmlNodePtr newChild = xmlNewChild(_xmlNode, NULL, nodeName, NULL);
xmlNodePtr newChild = xmlNewChild(_xmlNode, nullptr, nodeName, nullptr);

xmlFree(nodeName);

Expand All @@ -56,12 +62,16 @@ Node Node::createChild(const std::string& name)

NodeList Node::getNamedChildren(const std::string& name) const
{
std::lock_guard lock(_owner->getLock());

NodeList retval;

// Iterate throught the list of children, adding each child node
// to the return list if it matches the requested name
for (xmlNodePtr child = _xmlNode->children; child != NULL; child = child->next) {
if (xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>(name.c_str())) == 0) {
for (auto child = _xmlNode->children; child != nullptr; child = child->next)
{
if (xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>(name.c_str())) == 0)
{
retval.emplace_back(_owner, child);
}
}
Expand All @@ -71,6 +81,8 @@ NodeList Node::getNamedChildren(const std::string& name) const

void Node::setAttributeValue(const std::string& key, const std::string& value)
{
std::lock_guard lock(_owner->getLock());

xmlChar* k = xmlCharStrdup(key.c_str());
xmlChar* v = xmlCharStrdup(value.c_str());

Expand All @@ -85,32 +97,37 @@ void Node::setAttributeValue(const std::string& key, const std::string& value)

std::string Node::getAttributeValue(const std::string& key) const
{
std::lock_guard lock(_owner->getLock());

// Iterate through the chain of attributes to find the requested one.
for (xmlAttrPtr attr = _xmlNode->properties; attr != NULL; attr = attr->next) {
if (xmlStrcmp(attr->name, reinterpret_cast<const xmlChar*>(key.c_str())) == 0) {
for (auto attr = _xmlNode->properties; attr != nullptr; attr = attr->next)
{
if (xmlStrcmp(attr->name, reinterpret_cast<const xmlChar*>(key.c_str())) == 0)
{
return reinterpret_cast<const char*>(attr->children->content);
}
}

// Not found, return an empty string
return "";
return {};
}

// Return the textual content of a given node. This may be an empty string if there is no
// content available.

std::string Node::getContent() const
{
if (_xmlNode->children && _xmlNode->children->content) {
std::lock_guard lock(_owner->getLock());

if (_xmlNode->children && _xmlNode->children->content)
{
return std::string(reinterpret_cast<const char*>(_xmlNode->children->content));
}
else {
return "";
}

return {};
}

void Node::setContent(const std::string& content)
{
std::lock_guard lock(_owner->getLock());

// Remove all text children first
for (xmlNodePtr child = _xmlNode->children; child != nullptr; )
{
Expand All @@ -131,17 +148,19 @@ void Node::setContent(const std::string& content)

void Node::addText(const std::string& text)
{
std::lock_guard lock(_owner->getLock());

// Allocate a new text node
xmlNodePtr whitespace = xmlNewText(
reinterpret_cast<const xmlChar*>(text.c_str())
);
auto whitespace = xmlNewText(reinterpret_cast<const xmlChar*>(text.c_str()));

// Add the newly allocated text as sibling of this node
xmlAddNextSibling(_xmlNode, whitespace);
}

void Node::erase()
{
std::lock_guard lock(_owner->getLock());

// unlink the node from the list first, otherwise: crashes ahead!
xmlUnlinkNode(_xmlNode);

Expand Down

0 comments on commit 24399fa

Please sign in to comment.