Use unique_ptr to store the XmlNode’s children
Also fix some constness things
This commit is contained in:
@@ -51,11 +51,11 @@ void HelloStep1(XmppComponent*, AdhocSession&, XmlNode& command_node)
|
||||
void HelloStep2(XmppComponent*, AdhocSession& session, XmlNode& command_node)
|
||||
{
|
||||
// Find out if the name was provided in the form.
|
||||
XmlNode* x = command_node.get_child("x", "jabber:x:data");
|
||||
const XmlNode* x = command_node.get_child("x", "jabber:x:data");
|
||||
if (x)
|
||||
{
|
||||
XmlNode* name_field = nullptr;
|
||||
for (XmlNode* field: x->get_children("field", "jabber:x:data"))
|
||||
const XmlNode* name_field = nullptr;
|
||||
for (const XmlNode* field: x->get_children("field", "jabber:x:data"))
|
||||
if (field->get_tag("var") == "name")
|
||||
{
|
||||
name_field = field;
|
||||
@@ -63,7 +63,7 @@ void HelloStep2(XmppComponent*, AdhocSession& session, XmlNode& command_node)
|
||||
}
|
||||
if (name_field)
|
||||
{
|
||||
XmlNode* value = name_field->get_child("value", "jabber:x:data");
|
||||
const XmlNode* value = name_field->get_child("value", "jabber:x:data");
|
||||
if (value)
|
||||
{
|
||||
XmlNode note("note");
|
||||
|
||||
@@ -256,7 +256,7 @@ void XmppComponent::handle_handshake(const Stanza& stanza)
|
||||
|
||||
void XmppComponent::handle_error(const Stanza& stanza)
|
||||
{
|
||||
XmlNode* text = stanza.get_child("text", STREAMS_NS);
|
||||
const XmlNode* text = stanza.get_child("text", STREAMS_NS);
|
||||
std::string error_message("Unspecified error");
|
||||
if (text)
|
||||
error_message = text->get_inner();
|
||||
@@ -291,7 +291,7 @@ void XmppComponent::send_message(const std::string& from, Xmpp::body&& body, con
|
||||
XmlNode html("html");
|
||||
html["xmlns"] = XHTMLIM_NS;
|
||||
// Pass the ownership of the pointer to this xmlnode
|
||||
html.add_child(std::get<1>(body).release());
|
||||
html.add_child(std::move(std::get<1>(body)));
|
||||
node.add_child(std::move(html));
|
||||
}
|
||||
this->send_stanza(node);
|
||||
@@ -420,7 +420,7 @@ void XmppComponent::send_muc_message(const std::string& muc_name, const std::str
|
||||
XmlNode html("html");
|
||||
html["xmlns"] = XHTMLIM_NS;
|
||||
// Pass the ownership of the pointer to this xmlnode
|
||||
html.add_child(std::get<1>(xmpp_body).release());
|
||||
html.add_child(std::move(std::get<1>(xmpp_body)));
|
||||
message.add_child(std::move(html));
|
||||
}
|
||||
this->send_stanza(message);
|
||||
|
||||
@@ -29,7 +29,8 @@ static void character_data_handler(void *user_data, const XML_Char *s, int len)
|
||||
|
||||
XmppParser::XmppParser():
|
||||
level(0),
|
||||
current_node(nullptr)
|
||||
current_node(nullptr),
|
||||
root(nullptr)
|
||||
{
|
||||
this->init_xml_parser();
|
||||
}
|
||||
@@ -47,8 +48,6 @@ void XmppParser::init_xml_parser()
|
||||
|
||||
XmppParser::~XmppParser()
|
||||
{
|
||||
if (this->current_node)
|
||||
delete this->current_node;
|
||||
XML_ParserFree(this->parser);
|
||||
}
|
||||
|
||||
@@ -75,9 +74,8 @@ void XmppParser::reset()
|
||||
{
|
||||
XML_ParserFree(this->parser);
|
||||
this->init_xml_parser();
|
||||
if (this->current_node)
|
||||
delete this->current_node;
|
||||
this->current_node = nullptr;
|
||||
this->root.reset(nullptr);
|
||||
this->level = 0;
|
||||
}
|
||||
|
||||
@@ -90,10 +88,13 @@ void XmppParser::start_element(const XML_Char* name, const XML_Char** attribute)
|
||||
{
|
||||
level++;
|
||||
|
||||
XmlNode* new_node = new XmlNode(name, this->current_node);
|
||||
auto new_node = std::make_unique<XmlNode>(name, this->current_node);
|
||||
auto new_node_ptr = new_node.get();
|
||||
if (this->current_node)
|
||||
this->current_node->add_child(new_node);
|
||||
this->current_node = new_node;
|
||||
this->current_node->add_child(std::move(new_node));
|
||||
else
|
||||
this->root = std::move(new_node);
|
||||
this->current_node = new_node_ptr;
|
||||
for (size_t i = 0; attribute[i]; i += 2)
|
||||
this->current_node->set_attribute(attribute[i], attribute[i+1]);
|
||||
if (this->level == 1)
|
||||
@@ -111,8 +112,8 @@ void XmppParser::end_element(const XML_Char* name)
|
||||
if (level == 0)
|
||||
{
|
||||
this->stream_close_event(*this->current_node);
|
||||
delete this->current_node;
|
||||
this->current_node = nullptr;
|
||||
this->root.reset();
|
||||
}
|
||||
else
|
||||
this->current_node = this->current_node->get_parent();
|
||||
|
||||
@@ -111,6 +111,11 @@ private:
|
||||
* new children, inner or tail)
|
||||
*/
|
||||
XmlNode* current_node;
|
||||
/**
|
||||
* The root node has no parent, so we keep it here: the XmppParser object
|
||||
* is its owner.
|
||||
*/
|
||||
std::unique_ptr<XmlNode> root;
|
||||
/**
|
||||
* A list of callbacks to be called on an *_event, receiving the
|
||||
* concerned Stanza/XmlNode.
|
||||
|
||||
@@ -103,17 +103,8 @@ XmlNode::XmlNode(const std::string& name):
|
||||
{
|
||||
}
|
||||
|
||||
XmlNode::~XmlNode()
|
||||
{
|
||||
this->delete_all_children();
|
||||
}
|
||||
|
||||
void XmlNode::delete_all_children()
|
||||
{
|
||||
for (auto& child: this->children)
|
||||
{
|
||||
delete child;
|
||||
}
|
||||
this->children.clear();
|
||||
}
|
||||
|
||||
@@ -152,43 +143,44 @@ std::string XmlNode::get_tail() const
|
||||
return this->tail;
|
||||
}
|
||||
|
||||
XmlNode* XmlNode::get_child(const std::string& name, const std::string& xmlns) const
|
||||
const XmlNode* XmlNode::get_child(const std::string& name, const std::string& xmlns) const
|
||||
{
|
||||
for (auto& child: this->children)
|
||||
for (const auto& child: this->children)
|
||||
{
|
||||
if (child->name == name && child->get_tag("xmlns") == xmlns)
|
||||
return child;
|
||||
return child.get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<XmlNode*> XmlNode::get_children(const std::string& name, const std::string& xmlns) const
|
||||
std::vector<const XmlNode*> XmlNode::get_children(const std::string& name, const std::string& xmlns) const
|
||||
{
|
||||
std::vector<XmlNode*> res;
|
||||
for (auto& child: this->children)
|
||||
std::vector<const XmlNode*> res;
|
||||
for (const auto& child: this->children)
|
||||
{
|
||||
if (child->name == name && child->get_tag("xmlns") == xmlns)
|
||||
res.push_back(child);
|
||||
res.push_back(child.get());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
XmlNode* XmlNode::add_child(XmlNode* child)
|
||||
XmlNode* XmlNode::add_child(std::unique_ptr<XmlNode> child)
|
||||
{
|
||||
child->parent = this;
|
||||
this->children.push_back(child);
|
||||
return child;
|
||||
auto ret = child.get();
|
||||
this->children.push_back(std::move(child));
|
||||
return ret;
|
||||
}
|
||||
|
||||
XmlNode* XmlNode::add_child(XmlNode&& child)
|
||||
{
|
||||
XmlNode* new_node = new XmlNode(std::move(child));
|
||||
return this->add_child(new_node);
|
||||
auto new_node = std::make_unique<XmlNode>(std::move(child));
|
||||
return this->add_child(std::move(new_node));
|
||||
}
|
||||
|
||||
XmlNode* XmlNode::get_last_child() const
|
||||
{
|
||||
return this->children.back();
|
||||
return this->children.back().get();
|
||||
}
|
||||
|
||||
XmlNode* XmlNode::get_parent() const
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
std::string xml_escape(const std::string& data);
|
||||
std::string xml_unescape(const std::string& data);
|
||||
@@ -37,14 +38,11 @@ public:
|
||||
inner(node.inner),
|
||||
tail(node.tail)
|
||||
{
|
||||
for (XmlNode* child: node.children)
|
||||
{
|
||||
XmlNode* child_copy = new XmlNode(*child);
|
||||
this->add_child(child_copy);
|
||||
}
|
||||
for (const auto& child: node.children)
|
||||
this->add_child(std::make_unique<XmlNode>(*child));
|
||||
}
|
||||
|
||||
~XmlNode();
|
||||
~XmlNode() = default;
|
||||
|
||||
void delete_all_children();
|
||||
void set_attribute(const std::string& name, const std::string& value);
|
||||
@@ -78,16 +76,16 @@ public:
|
||||
/**
|
||||
* Get a pointer to the first child element with that name and that xml namespace
|
||||
*/
|
||||
XmlNode* get_child(const std::string& name, const std::string& xmlns) const;
|
||||
const XmlNode* get_child(const std::string& name, const std::string& xmlns) const;
|
||||
/**
|
||||
* Get a vector of all the children that have that name and that xml namespace.
|
||||
*/
|
||||
std::vector<XmlNode*> get_children(const std::string& name, const std::string& xmlns) const;
|
||||
std::vector<const XmlNode*> get_children(const std::string& name, const std::string& xmlns) const;
|
||||
/**
|
||||
* Add a node child to this node. Assign this node to the child’s parent.
|
||||
* Returns a pointer to the newly added child.
|
||||
*/
|
||||
XmlNode* add_child(XmlNode* child);
|
||||
XmlNode* add_child(std::unique_ptr<XmlNode> child);
|
||||
XmlNode* add_child(XmlNode&& child);
|
||||
/**
|
||||
* Returns the last of the children. If the node doesn't have any child,
|
||||
@@ -126,7 +124,7 @@ private:
|
||||
std::string name;
|
||||
XmlNode* parent;
|
||||
std::map<std::string, std::string> attributes;
|
||||
std::vector<XmlNode*> children;
|
||||
std::vector<std::unique_ptr<XmlNode>> children;
|
||||
std::string inner;
|
||||
std::string tail;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user