[gxml: 16/18] libxml-2.0.vapi, Attr.vala, Document.vala, Element.vala: stop leaking memory from xmlAttrs



commit 6f03bd2f6eb829eb8ece9c1d9df7d3035ac78d92
Author: Richard Schwarting <aquarichy gmail com>
Date:   Sun Jun 9 23:37:46 2013 -0400

    libxml-2.0.vapi, Attr.vala, Document.vala, Element.vala: stop leaking memory from xmlAttrs

 gxml/Attr.vala       |    2 +-
 gxml/Document.vala   |   11 ++++++++---
 gxml/Element.vala    |   16 ++++++++++------
 vapi/libxml-2.0.vapi |    3 +++
 4 files changed, 22 insertions(+), 10 deletions(-)
---
diff --git a/gxml/Attr.vala b/gxml/Attr.vala
index e0f270d..2770d7b 100644
--- a/gxml/Attr.vala
+++ b/gxml/Attr.vala
@@ -68,7 +68,7 @@ namespace GXml {
                }
 
                /** Private properties */
-               private Xml.Attr *node;
+               internal Xml.Attr *node;
 
                /** Constructors */
                internal Attr (Xml.Attr *node, Document doc) {
diff --git a/gxml/Document.vala b/gxml/Document.vala
index af08c2e..840b18d 100644
--- a/gxml/Document.vala
+++ b/gxml/Document.vala
@@ -186,6 +186,8 @@ namespace GXml {
                ~Document () {
                        List<Xml.Node*> to_free = new List<Xml.Node*> ();
 
+                       sync_dirty_elements ();
+
                        /* we use two separate loops, because freeing
                           a node frees its descendants, and we might
                           have a branch with children that might be
@@ -328,10 +330,11 @@ namespace GXml {
 
                        try {
                                instream = fin.read (null);
+                               this.from_stream (instream, can);
+                               instream.close ();
                        } catch (GLib.Error e) {
                                throw new DomError.INVALID_DOC (e.message);
                        }
-                       this.from_stream (instream, can);
                }
                /**
                 * Creates a Document from data provided through the InputStream instream.
@@ -342,13 +345,13 @@ namespace GXml {
                        // TODO: accept Cancellable
                        // Cancellable can = new Cancellable ();
                        InputStreamBox box = { instream, can };
-
+                       Xml.Doc *doc;
                        Xml.TextReader reader = new Xml.TextReader.for_io ((Xml.InputReadCallback)_ioread,
                                                                           (Xml.InputCloseCallback)_ioinclose,
                                                                           &box, "", null, 0);
                        reader.read ();
                        reader.expand ();
-                       Xml.Doc *doc = reader.current_doc ();
+                       doc = reader.current_doc ();
                        reader.close ();
 
                        this.from_libxml2 (doc);
@@ -393,6 +396,8 @@ namespace GXml {
                                        elem.save_attributes (tmp_node);
                                }
                                this.dirty_elements = new List<Element> (); // clear the old list
+
+                               tmp_node->free ();
                        }
                }
 
diff --git a/gxml/Element.vala b/gxml/Element.vala
index 1c3ed8e..0ee8b89 100644
--- a/gxml/Element.vala
+++ b/gxml/Element.vala
@@ -95,7 +95,7 @@ namespace GXml {
                                if (this._attributes == null) {
                                        this.owner_document.dirty_elements.append (this);
                                        this._attributes = new HashTable<string,Attr> (GLib.str_hash, 
GLib.str_equal);
-                                               // TODO: make sure other HashTables have appropriate hash, 
equal functions
+                                       // TODO: make sure other HashTables have appropriate hash, equal 
functions
 
                                        for (Xml.Attr *prop = base.node->properties; prop != null; prop = 
prop->next) {
                                                attr = new Attr (prop, this.owner_document);
@@ -144,16 +144,21 @@ namespace GXml {
                                }
 
                                // Go through the GXml table of attributes for this element and add 
corresponding libxml2 ones
-                               foreach (string propname in this.attributes.get_keys ()) {
-                                       attr = this.attributes.lookup (propname);
+                               foreach (string propname in this._attributes.get_keys ()) {
+                                       attr = this._attributes.lookup (propname);
+                                       Xml.Attr* saved_attr;
 
                                        if (attr.namespace_uri != null || attr.prefix != null) {
                                                // I hate namespace handling between libxml2 and DOM Level 
2/3 Core!
                                                ns = tmp_node->new_ns (attr.namespace_uri, attr.prefix);
-                                               this.node->set_ns_prop (ns, propname, attr.node_value);
+                                               saved_attr = this.node->set_ns_prop (ns, propname, 
attr.node_value);
                                        } else {
-                                               this.node->set_prop (propname, attr.node_value);
+                                               saved_attr = this.node->set_prop (propname, attr.node_value);
                                        }
+
+                                       // Replace the old out-of-tree attr with the newly allocated one in 
the tree, that way xmlFreeDoc can clean up correctly
+                                       attr.node->free ();
+                                       attr.node = saved_attr;
                                }
                        }
                }
@@ -214,7 +219,6 @@ namespace GXml {
 
                        this.attributes.replace (name, attr);
                        // TODO: replace wanted 'owned', look up what to do
-
                }
                /**
                 * Remove the attribute named name from this element.
diff --git a/vapi/libxml-2.0.vapi b/vapi/libxml-2.0.vapi
index 6743b1c..b434a7e 100644
--- a/vapi/libxml-2.0.vapi
+++ b/vapi/libxml-2.0.vapi
@@ -277,6 +277,9 @@ namespace Xml {
                public Ns* ns;
                public AttributeType atype;
 
+               [CCode (cname = "xmlFreeProp")]
+               public int free();
+
                [CCode (cname = "xmlRemoveProp")]
                public int remove();
        }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]