vermont/src/core/XMLNode.cpp
Nicholas Brown eefb9e8d61 Don't leak the xmlString in Cfg
Valgrind was reporting lots of leaks of the form:

==5048==    at 0x4C2BBAF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5048==    by 0x5D50D18: xmlBufCreateSize (in /usr/lib/x86_64-linux-gnu/libxml2.so.2.9.4)
==5048==    by 0x5CDDD91: xmlNodeGetContent (in /usr/lib/x86_64-linux-gnu/libxml2.so.2.9.4)
==5048==    by 0x38EB01: XMLNode::getContent[abi:cxx11]() const (in /usr/sbin/vermont)
==5048==    by 0x285B62: CollectorCfg::CollectorCfg(XMLElement*, unsigned int) (in /usr/sbin/vermont)

The API guide for xmlNodeGetContent() states:

Returns: a new #xmlChar * or NULL if no content is available. It's up to the caller to free the memory with xmlFree().

So call xmlFree() after using the std:string copy constructor

Fixes #117
2018-11-05 10:56:14 +00:00

94 lines
2.1 KiB
C++

#include "XMLNode.h"
#include <cassert>
XMLNode::XMLNode(xmlNodePtr doc)
: xmlNode(doc)
{
xmlNode->_private = this;
}
XMLNode::~XMLNode()
{
}
std::string XMLNode::getName() const
{
if (!xmlNode->name)
return "";
return std::string((const char*)xmlNode->name);
}
const std::string XMLNode::getContent() const
{
xmlChar *xmlString = xmlNodeGetContent(xmlNode);
std::string string ((const char*)xmlString);
xmlFree(xmlString);
return string;
}
XMLNode::XMLNodeSet XMLNode::findChildren(const std::string& name)
{
XMLNode::XMLNodeSet children;
for (xmlNodePtr child = xmlNode->children; child; child = child->next) {
if(child->_private &&
(name.empty() || name == (const char*)child->name)) {
children.push_back(reinterpret_cast<XMLNode*>(child->_private));
}
}
return children;
}
XMLNode* XMLNode::getFirstChild(const std::string& name)
{
for (xmlNodePtr child = xmlNode->children; child; child = child->next) {
if(child->_private &&
(name.empty() || name == (const char*)child->name)) {
return reinterpret_cast<XMLNode*>(child->_private);
}
}
return NULL;
}
XMLNode::XMLSet<XMLTextNode*> XMLNode::getTextChildren()
{
XMLNode::XMLSet<XMLTextNode*> children;
assert(xmlNode != NULL);
for (xmlNodePtr child = xmlNode->children; child; child = child->next) {
// check if name and/or type matches
if (child->_private && child->type == XML_TEXT_NODE) {
XMLTextNode* tn = reinterpret_cast<XMLTextNode*>(child->_private);
if (!tn->isBlank())
children.push_back(tn);
}
}
return children;
}
std::string XMLNode::getFirstText()
{
XMLNode::XMLSet<XMLTextNode*> set = getTextChildren();
if (set.size() <= 0)
return "";
return set.front()->getContent();
}
XMLNode::XMLSet<XMLElement*> XMLNode::getElementChildren()
{
XMLNode::XMLSet<XMLElement*> children;
for (xmlNodePtr child = xmlNode->children; child; child = child->next) {
// check if name and/or type matches
if (child->_private && child->type == XML_ELEMENT_NODE) {
XMLElement* e = reinterpret_cast<XMLElement*>(child->_private);
children.push_back(e);
}
}
return children;
}