Anonymous avatar Anonymous committed 7d758b3

Re-implemented xmlNodePtr as a proxy object so that we can store the document in there and increment it's refcnt when we do setOwnerDocument and so forth.
Fixed NoGCDocument typos

Comments (0)

Files changed (3)

 @XML::LibXML::Text::ISA         = 'XML::LibXML::Node';
 @XML::LibXML::Comment::ISA      = 'XML::LibXML::Text';
 @XML::LibXML::CDATASection::ISA = 'XML::LibXML::Text';
-@XML::LibXML::NoGCDocment       = 'XML::LibXML::Document';
+@XML::LibXML::NoGCDocument::ISA  = 'XML::LibXML::Document';
 
 sub XML::LibXML::NoGCDocument::DESTROY () { }
 
         cb = newSVsv(fld);\
     }
 
+typedef struct _ProxyObject ProxyObject;
+
+struct _ProxyObject {
+    void * object;
+    SV * extra;
+};
+
 static SV * LibXML_match_cb = NULL;
 static SV * LibXML_read_cb = NULL;
 static SV * LibXML_open_cb = NULL;
 static SV * LibXML_close_cb = NULL;
 static SV * LibXML_error = NULL;
 
+ProxyObject *
+make_proxy_node (xmlNodePtr node)
+{
+    ProxyObject * proxy;
+    
+    proxy = (ProxyObject*)New(0, proxy, 1, ProxyObject);
+    if (proxy != NULL) {
+        proxy->object = (void*)node;
+        proxy->extra = NULL;
+    }
+    return proxy;
+}
+
 void
 LibXML_free_all_callbacks(void)
 {
 DESTROY(self)
         xmlDocPtr self
     CODE:
-        /* if (self == NULL) { */
-        /*    XSRETURN_UNDEF; */
-        /* } */
-        /* xmlFreeDoc(self); */
+        if (self == NULL) {
+           XSRETURN_UNDEF;
+        }
+        # warn("xmlFreeDoc(%d)\n", self);
+        xmlFreeDoc(self);
 
 SV *
 toString(self)
     OUTPUT:
         RETVAL
 
-xmlNodePtr
+ProxyObject *
 createElement( dom, name )
-        xmlDocPtr dom
+        SV * dom
         char* name
     PREINIT:
         char * CLASS = "XML::LibXML::Element";
+        xmlNodePtr newNode;
     CODE:
-        RETVAL = xmlNewNode( 0 , name );
-        RETVAL->doc = dom;
+        newNode = xmlNewNode( 0 , name );
+        newNode->doc = (xmlDocPtr)SvIV((SV*)SvRV(dom));
+        RETVAL = make_proxy_node(newNode);
+        RETVAL->extra = dom;
+        SvREFCNT_inc(dom);
     OUTPUT:
         RETVAL
 
-xmlNodePtr
+ProxyObject *
 createTextNode( dom, content )
-        xmlDocPtr dom
+        SV * dom
         char * content
     PREINIT:
         char * CLASS = "XML::LibXML::Text";
+        xmlNodePtr newNode;
     CODE:
-        RETVAL = xmlNewDocText( dom, content );
+        newNode = xmlNewDocText( (xmlDocPtr)SvIV((SV*)SvRV(dom)), content );
+        RETVAL = make_proxy_node(newNode);
+        RETVAL->extra = dom;
+        SvREFCNT_inc(dom);
     OUTPUT:
         RETVAL
 
-xmlNodePtr 
+ProxyObject *
 createComment( dom , content )
-        xmlDocPtr dom
+        SV * dom
         char * content
     PREINIT:
         char * CLASS = "XML::LibXML::Comment";
+        xmlNodePtr newNode;
     CODE:
-        RETVAL = xmlNewDocComment( dom, content );
+        newNode = xmlNewDocComment( (xmlDocPtr)SvIV((SV*)SvRV(dom)), content );
+        RETVAL = make_proxy_node(newNode);
+        RETVAL->extra = dom;
+        SvREFCNT_inc(dom);
     OUTPUT:
         RETVAL
 
-xmlNodePtr
+ProxyObject *
 createCDATASection( dom, content )
-        xmlDocPtr dom
+        SV * dom
         char * content
     PREINIT:
         char * CLASS = "XML::LibXML::CDATASection";
+        xmlNodePtr newNode;
     CODE:
-        RETVAL = domCreateCDATASection( dom, content );
+        newNode = domCreateCDATASection( (xmlDocPtr)SvIV((SV*)SvRV(dom)), content );
+        RETVAL = make_proxy_node(newNode);
+        RETVAL->extra = dom;
+        SvREFCNT_inc(dom);
     OUTPUT:
         RETVAL
 
 void 
-setDocumentElement( dom , elem )
-        xmlDocPtr dom
-        xmlNodePtr elem
+setDocumentElement( dom , proxy )
+        SV * dom
+        ProxyObject * proxy
+    PREINIT:
+        xmlDocPtr real_dom;
+        xmlNodePtr elem;
     CODE:
-        domSetDocumentElement( dom, elem );
+        real_dom = (xmlDocPtr)SvIV((SV*)SvRV(dom));
+        SvREFCNT_dec(proxy->extra);
+        elem = (xmlNodePtr)proxy->object;
+        domSetDocumentElement( real_dom, elem );
+        proxy->extra = dom;
+        SvREFCNT_inc(dom);
 
-xmlNodePtr
+ProxyObject *
 getDocumentElement( dom )
-        xmlDocPtr dom
+        SV * dom
     PREINIT:
         const char * CLASS = "XML::LibXML::Node";
+        xmlNodePtr elem;
+        xmlDocPtr real_dom;
     CODE:
-        RETVAL = domDocumentElement( dom ) ;
-        if ( RETVAL ) {
-            CLASS = domNodeTypeName( RETVAL );
+        real_dom = (xmlDocPtr)SvIV((SV*)SvRV(dom));
+        RETVAL = NULL;
+        elem = domDocumentElement( real_dom ) ;
+        if ( elem ) {
+            CLASS = domNodeTypeName( elem );
+            RETVAL = make_proxy_node(elem);
+            RETVAL->extra = dom;
+            SvREFCNT_inc(dom);
         }
     OUTPUT:
         RETVAL
     OUTPUT:
         RETVAL
 
+void
+DESTROY( self )
+        xmlDtdPtr self
+    CODE:
+        xmlFreeDtd(self);
 
 
 MODULE = XML::LibXML         PACKAGE = XML::LibXML::Node
 
 void
 DESTROY( node )
-        xmlNodePtr node 
+        ProxyObject * node
     CODE:
         /**
          * this block should remove old (unbound) nodes from the system
          * but for some reason this condition is not valid ... :(
          **/
+        if (node->extra != NULL) {
+            SvREFCNT_dec(node->extra);
+        }
+        Safefree(node);
         /* warn( "Free node\n" ); */
         /*domUnbindNode( node );  * before freeing we unbind the node from
 		                          * possible siblings */
     CODE:
         domUnbindNode( elem );
 
-xmlNodePtr
+ProxyObject *
 removeChild( paren, child ) 
         xmlNodePtr paren
         xmlNodePtr child
     PREINIT:
         const char * CLASS = "XML::LibXML::Node";
+        xmlNodePtr ret;
     CODE:
-        RETVAL = domRemoveNode( paren, child );
+        ret = domRemoveNode( paren, child );
+        RETVAL = NULL;
+        if (ret != 0) {
+            RETVAL = make_proxy_node(ret);
+        }
     OUTPUT:
         RETVAL
 
-xmlNodePtr
+ProxyObject *
 replaceChild( paren, newChild, oldChild ) 
         xmlNodePtr paren
         xmlNodePtr newChild
         xmlNodePtr oldChild
     PREINIT:
         const char * CLASS = "XML::LibXML::Node";
+        xmlNodePtr ret;
     CODE:
-        RETVAL = domReplaceChild( paren, newChild, oldChild );
+        ret = domReplaceChild( paren, newChild, oldChild );
+        RETVAL = NULL;
+        if (ret != 0) {
+            RETVAL = make_proxy_node(ret);
+        }
     OUTPUT:
         RETVAL
 
     CODE:
         domAppendChild( parent, child );
 
-xmlNodePtr
+ProxyObject *
 cloneNode( self, deep ) 
         xmlNodePtr self
         int deep
     PREINIT:
         const char * CLASS = "XML::LibXML::Node";
+        xmlNodePtr ret;
     CODE:
-        RETVAL = xmlCopyNode( self, deep );
+        ret = xmlCopyNode( self, deep );
+        RETVAL = NULL;
+        if (ret != 0) {
+            RETVAL = make_proxy_node(ret);
+        }
     OUTPUT:
         RETVAL
 
 
-xmlNodePtr
+ProxyObject *
 getParentNode( self )
         xmlNodePtr self
     PREINIT:
         const char * CLASS = "XML::LibXML::Element";
+        xmlNodePtr ret;
     CODE:
-        RETVAL = self->parent;
+        ret = self->parent;
+        RETVAL = NULL;
+        if (ret != 0) {
+            RETVAL = make_proxy_node(ret);
+        }
     OUTPUT:
         RETVAL
 
     OUTPUT:
         RETVAL
 
-xmlNodePtr
+ProxyObject *
 getNextSibling( elem )
         xmlNodePtr elem
     PREINIT:
         const char * CLASS = "XML::LibXML::Node";
+        xmlNodePtr ret;
     CODE:
-        RETVAL = elem->next ;
-        if ( RETVAL ) {
-            CLASS = domNodeTypeName( RETVAL );
+        ret = elem->next ;
+        RETVAL = NULL;
+        if ( ret ) {
+            CLASS = domNodeTypeName( ret );
+            RETVAL = make_proxy_node(ret);
         }	
     OUTPUT:
         RETVAL
 
-xmlNodePtr
+ProxyObject *
 getPreviousSibling( elem )
         xmlNodePtr elem
     PREINIT:
         const char * CLASS = "XML::LibXML::Node";
+        xmlNodePtr ret;
     CODE:
-        RETVAL = elem->prev;
-        if ( RETVAL ) {
-            CLASS = domNodeTypeName( RETVAL );
+        ret = elem->prev;
+        RETVAL = NULL;
+        if ( ret ) {
+            CLASS = domNodeTypeName( ret );
+            RETVAL = make_proxy_node(ret);
         }
     OUTPUT:
         RETVAL
 
-xmlNodePtr
+ProxyObject *
 getFirstChild( elem )
         xmlNodePtr elem
     PREINIT:
         const char * CLASS = "XML::LibXML::Node";
+        xmlNodePtr ret;
     CODE:
-        RETVAL = elem->children;
-        if ( RETVAL ) {
-            CLASS = domNodeTypeName( RETVAL );
+        ret = elem->children;
+        RETVAL = NULL;
+        if ( ret ) {
+            CLASS = domNodeTypeName( ret );
+            RETVAL = make_proxy_node(ret);
         }
     OUTPUT:
         RETVAL
 
 
-xmlNodePtr
+ProxyObject *
 getLastChild( elem )
         xmlNodePtr elem
     PREINIT:
         const char * CLASS = "XML::LibXML::Node";
+        xmlNodePtr ret;
     CODE:
-        RETVAL = elem->last;
-        if ( RETVAL ) {
-            CLASS = domNodeTypeName( RETVAL );
+        ret = elem->last;
+        RETVAL = NULL;
+        if ( ret ) {
+            CLASS = domNodeTypeName( ret );
+            RETVAL = make_proxy_node(ret);
         }
     OUTPUT:
         RETVAL
 getOwnerDocument( elem )
         xmlNodePtr elem
     PREINIT:
-        const char * CLASS = "XML::LibXML::Document";
+        const char * CLASS = "XML::LibXML::NoGCDocument";
     CODE:
         RETVAL = elem->doc;
     OUTPUT:
             int i = 0 ;
             const char * cls = "XML::LibXML::Node";
             xmlNodePtr tnode;
+            ProxyObject * proxy;
 
             len = nodelist->nodeNr;
          
                  */
                 element = 0;
                 tnode = nodelist->nodeTab[i];
-                element = sv_newmortal(); 
+                element = sv_newmortal();
+                
+                proxy = make_proxy_node(tnode);
 
                 cls = domNodeTypeName( tnode );
-                XPUSHs( sv_setref_pv( element, (char *)cls, (void*)tnode ) );
+                XPUSHs( sv_setref_pv( element, (char *)cls, (void*)proxy ) );
             }
 
             xmlXPathFreeNodeSet( nodelist );
         SV * element;
         int len;
         const char * cls = "XML::LibXML::Node";
+        ProxyObject * proxy;
     PPCODE:
         len = 0;
 	
         while ( cld ) {	
             element = sv_newmortal();
             cls = domNodeTypeName( cld );
-            XPUSHs( sv_setref_pv( element, (char *)cls, (void*)cld ) );
+            proxy = make_proxy_node(cld);
+            XPUSHs( sv_setref_pv( element, (char *)cls, (void*)proxy ) );
             cld = cld->next;
             len++;
         }
 
 MODULE = XML::LibXML         PACKAGE = XML::LibXML::Element
 
-xmlNodePtr
+ProxyObject *
 new(CLASS, name )
         char * CLASS
         char * name
+    PREINIT:
+        xmlNodePtr newNode;
     CODE:
-        CLASS = "XML::LibXML::Element";
-        RETVAL = xmlNewNode( 0, name );
-        if ( RETVAL != 0 ) {
-            RETVAL->next     = 0;
-            RETVAL->prev     = 0;
-            RETVAL->children = 0 ;
-            RETVAL->last     = 0;
-            RETVAL->doc      = 0;
+        # CLASS = "XML::LibXML::Element";
+        newNode = xmlNewNode( 0, name );
+        if ( newNode != 0 ) {
+            newNode->next     = 0;
+            newNode->prev     = 0;
+            newNode->children = 0 ;
+            newNode->last     = 0;
+            newNode->doc      = 0;
+            RETVAL = make_proxy_node(newNode);
         }
     OUTPUT:
         RETVAL
 
-void
-DESTROY( node )
-        xmlNodePtr node 
-    CODE:
 
 void
 setAttribute( elem, name, value )
             int i = 0 ;
             const char * cls = "XML::LibXML::Node";
             xmlNodePtr tnode;
+            ProxyObject * proxy;
 
             len = nodelist->nodeNr;
          
                  */
                 element = 0;
                 tnode = nodelist->nodeTab[i];
-                element = sv_newmortal(); 
+                element = sv_newmortal();
+                
+                proxy = make_proxy_node(tnode);
 
-                cls = domNodeTypeName( tnode ); 
-                XPUSHs( sv_setref_pv( element, (char *)cls, (void*)tnode ) );
+                cls = domNodeTypeName( tnode );
+                XPUSHs( sv_setref_pv( element, (char *)cls, (void*)proxy ) );
             }
 
             xmlXPathFreeNodeSet( nodelist );
     CODE:
         domSetNodeValue( node, value );
 
-xmlNodePtr
+ProxyObject *
 new( CLASS, content )
         const char * CLASS
         char * content
     PREINIT:
         xmlBufferPtr in, out;
+        xmlNodePtr newNode;
     CODE:
         in = xmlBufferCreate();
         out =xmlBufferCreate();
         xmlCharEncInFunc( xmlGetCharEncodingHandler( xmlParseCharEncoding("UTF-8") ), 
                           out, 
                           in);
-        RETVAL = xmlNewText( out->content );
+        newNode = xmlNewText( out->content );
+        RETVAL = make_proxy_node(newNode);
     OUTPUT:
         RETVAL
 
-void
-DESTROY( node )
-        xmlNodePtr node 
-    CODE:
-
 MODULE = XML::LibXML         PACKAGE = XML::LibXML::Comment
 
-xmlNodePtr
+ProxyObject *
 new( CLASS, content ) 
         const char * CLASS
         char * content
     PREINIT:
         xmlBufferPtr in, out;
+        xmlNodePtr newNode;
     CODE:
         in = xmlBufferCreate();
         out =xmlBufferCreate();
         xmlCharEncInFunc( xmlGetCharEncodingHandler( xmlParseCharEncoding("UTF-8") ), 
                           out, 
                           in);
-        RETVAL = xmlNewComment( out->content );
+        newNode = xmlNewComment( out->content );
+        RETVAL = make_proxy_node(newNode);
     OUTPUT:
         RETVAL
 
-void
-DESTROY( node )
-        xmlNodePtr node 
-    CODE:
-
 MODULE = XML::LibXML         PACKAGE = XML::LibXML::CDATASection
 
-xmlNodePtr
+ProxyObject *
 new( CLASS , content )
         const char * CLASS
         char * content
     PREINIT:
         xmlBufferPtr in, out;
+        xmlNodePtr newNode;
     CODE:
         in = xmlBufferCreate();
         out =xmlBufferCreate();
         xmlCharEncInFunc( xmlGetCharEncodingHandler( xmlParseCharEncoding("UTF-8") ), 
                           out, 
                           in);
-        RETVAL = xmlNewCDataBlock( 0 , out->content, xmlStrlen( out->content ) );
+        newNode = xmlNewCDataBlock( 0 , out->content, xmlStrlen( out->content ) );
+        RETVAL = make_proxy_node(newNode);
     OUTPUT:
     RETVAL
 
-void
-DESTROY( node )
-        xmlNodePtr node 
-    CODE:
 TYPEMAP
 const char *        T_PV
 xmlDocPtr           O_OBJECT
-xmlNodePtr          O_OBJECT
+xmlNodePtr          PROXY_OBJECT
 xmlParserCtxtPtr    O_OBJECT
 xmlDtdPtr           O_OBJECT
 xmlNodeSetPtr       O_OBJECT
+ProxyObject *       O_OBJECT
+
 
 INPUT
 O_OBJECT
             XSRETURN_UNDEF;
     }
 
+PROXY_OBJECT
+    if( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) )
+            $var = ($type)(((ProxyObject *)SvIV((SV*)SvRV( $arg )))->object);
+    else{
+            warn( \"${Package}::$func_name() -- $var is not a blessed SV reference\" );
+            XSRETURN_UNDEF;
+    }
+
 OUTPUT
 
 # The Perl object is blessed into 'CLASS', which should be a
 O_OBJECT
         sv_setref_pv( $arg, (char *)CLASS, (void*)$var );
 
+PROXY_OBJECT
+        sv_setref_pv( $arg, (char *)CLASS, (void*)$var );
+
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.