ext/xml/ruby_xml_attr.c in libxml-ruby-0.3.8 vs ext/xml/ruby_xml_attr.c in libxml-ruby-0.3.8.2

- old
+ new

@@ -1,22 +1,29 @@ -/* $Id: ruby_xml_attr.c,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */ +/* $Id: ruby_xml_attr.c,v 1.2 2006/11/20 01:22:07 roscopeco Exp $ */ /* Please see the LICENSE file for copyright and distribution information */ #include "libxml.h" #include "ruby_xml_attr.h" VALUE cXMLAttr; void ruby_xml_attr_free(ruby_xml_attr *rxa) { - if (rxa->attr != NULL && !rxa->is_ptr) { - xmlUnlinkNode((xmlNodePtr)rxa->attr); - xmlFreeNode((xmlNodePtr)rxa->attr); - rxa->attr = NULL; + if (rxa->attr != NULL && // got an attr? + rxa->attr->parent == NULL && // unparented (otherwise, it gets freed with parent) + rxa->attr->doc == NULL) { // No document? (otherwise, freed with doc) + if ((int)rxa->attr->_private <= 1) { + // is null or last reference, + xmlFreeNode((xmlNodePtr)rxa->attr); + } else { + // other pointers remain + rxa->attr->_private--; + } } + rxa->attr = NULL; free(rxa); } /* @@ -30,11 +37,11 @@ ruby_xml_attr *rxa; Data_Get_Struct(self, ruby_xml_attr, rxa); if (rxa->attr->children == NULL) return(Qnil); else - return(ruby_xml_node_new2(cXMLNode, rxa->xd, rxa->attr->children)); + return(ruby_xml_node_new_ptr(cXMLNode, rxa->xd, rxa->attr->children)); } /* * call-seq: @@ -100,11 +107,11 @@ ruby_xml_attr *rxa; Data_Get_Struct(self, ruby_xml_attr, rxa); if (rxa->attr->last == NULL) return(Qnil); else - return(ruby_xml_node_new2(cXMLNode, rxa->xd, rxa->attr->last)); + return(ruby_xml_node_new_ptr(cXMLNode, rxa->xd, rxa->attr->last)); } /* * call-seq: @@ -148,29 +155,39 @@ } VALUE ruby_xml_attr_new(VALUE class, VALUE xd, xmlAttrPtr attr) { - ruby_xml_attr *rxa; - - rxa = ALLOC(ruby_xml_attr); - rxa->attr = attr; - rxa->xd = xd; - rxa->is_ptr = 0; - return(Data_Wrap_Struct(class, ruby_xml_attr_mark, - ruby_xml_attr_free, rxa)); + return(ruby_xml_attr_new2(class, xd, attr)); } VALUE ruby_xml_attr_new2(VALUE class, VALUE xd, xmlAttrPtr attr) { ruby_xml_attr *rxa; rxa = ALLOC(ruby_xml_attr); - rxa->attr = xmlCopyProp(attr->parent, attr); - rxa->xd = xd; - rxa->is_ptr = 0; + + rxa->attr = attr; + if (attr->_private) { + attr->_private++; + } else { + attr->_private = (void*)1; + } + + if (NIL_P(xd)) { + rxa->xd = Qnil; + rxa->attr->doc = NULL; + } else { + /* Have to set node->doc too so we don't doublefree this node */ + ruby_xml_document *xdoc; + Data_Get_Struct(xd, ruby_xml_document, xdoc); + + rxa->xd = xd; + rxa->attr->doc = xdoc->doc; + } + return(Data_Wrap_Struct(class, ruby_xml_attr_mark, ruby_xml_attr_free, rxa)); } @@ -214,11 +231,10 @@ * * Obtain this attribute node's type name. */ VALUE ruby_xml_attr_node_type_name(VALUE self) { - /* I think libxml2's naming convention blows monkey ass */ return(rb_str_new2("attribute")); } /* @@ -267,10 +283,10 @@ ruby_xml_attr *rxa; Data_Get_Struct(self, ruby_xml_attr, rxa); if (rxa->attr->parent == NULL) return(Qnil); else - return(ruby_xml_node_new2(cXMLNode, rxa->xd, rxa->attr->parent)); + return(ruby_xml_node_new_ptr(cXMLNode, rxa->xd, rxa->attr->parent)); } /* * call-seq: