From f3b3d937ae274d0eec4a737d11ba19a7f4ceef03 Mon Sep 17 00:00:00 2001
From: Florent Le Coz <louiz@louiz.org>
Date: Tue, 1 Sep 2015 14:47:57 +0200
Subject: =?UTF-8?q?Use=20unique=5Fptr=20to=20store=20the=20XmlNode?=
 =?UTF-8?q?=E2=80=99s=20children?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Also fix some constness things
---
 louloulibs/xmpp/adhoc_command.cpp  |  8 ++++----
 louloulibs/xmpp/xmpp_component.cpp |  6 +++---
 louloulibs/xmpp/xmpp_parser.cpp    | 19 ++++++++++---------
 louloulibs/xmpp/xmpp_parser.hpp    |  5 +++++
 louloulibs/xmpp/xmpp_stanza.cpp    | 36 ++++++++++++++----------------------
 louloulibs/xmpp/xmpp_stanza.hpp    | 18 ++++++++----------
 6 files changed, 44 insertions(+), 48 deletions(-)

(limited to 'louloulibs/xmpp')

diff --git a/louloulibs/xmpp/adhoc_command.cpp b/louloulibs/xmpp/adhoc_command.cpp
index c17f1d9..b8b07c6 100644
--- a/louloulibs/xmpp/adhoc_command.cpp
+++ b/louloulibs/xmpp/adhoc_command.cpp
@@ -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");
diff --git a/louloulibs/xmpp/xmpp_component.cpp b/louloulibs/xmpp/xmpp_component.cpp
index 19111ba..8cd722d 100644
--- a/louloulibs/xmpp/xmpp_component.cpp
+++ b/louloulibs/xmpp/xmpp_component.cpp
@@ -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);
diff --git a/louloulibs/xmpp/xmpp_parser.cpp b/louloulibs/xmpp/xmpp_parser.cpp
index 3903b73..c1fd63a 100644
--- a/louloulibs/xmpp/xmpp_parser.cpp
+++ b/louloulibs/xmpp/xmpp_parser.cpp
@@ -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();
diff --git a/louloulibs/xmpp/xmpp_parser.hpp b/louloulibs/xmpp/xmpp_parser.hpp
index 79c9f8f..4de639d 100644
--- a/louloulibs/xmpp/xmpp_parser.hpp
+++ b/louloulibs/xmpp/xmpp_parser.hpp
@@ -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.
diff --git a/louloulibs/xmpp/xmpp_stanza.cpp b/louloulibs/xmpp/xmpp_stanza.cpp
index aec91a7..3ba8483 100644
--- a/louloulibs/xmpp/xmpp_stanza.cpp
+++ b/louloulibs/xmpp/xmpp_stanza.cpp
@@ -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
diff --git a/louloulibs/xmpp/xmpp_stanza.hpp b/louloulibs/xmpp/xmpp_stanza.hpp
index ee6b25b..4a54379 100644
--- a/louloulibs/xmpp/xmpp_stanza.hpp
+++ b/louloulibs/xmpp/xmpp_stanza.hpp
@@ -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;
 
-- 
cgit v1.2.3