ext/xml/ruby_xml_node.c in libxml-ruby-0.5.1.0 vs ext/xml/ruby_xml_node.c in libxml-ruby-0.5.2.0

- old
+ new

@@ -1,6 +1,6 @@ -/* $Id: ruby_xml_node.c 167 2007-09-05 12:47:54Z danj $ */ +/* $Id: ruby_xml_node.c 192 2007-10-05 15:13:17Z danj $ */ /* Please see the LICENSE file for copyright and distribution information */ #include "libxml.h" #include "ruby_xml_node.h" @@ -307,20 +307,16 @@ return(Qfalse); else return(Qtrue); } - -// TODO Fixes below should be applied to sibling, prev, etc ? /* - * call-seq: - * node.child = node - * - * Set a child node for this node. + * underlying for child_set and child_add, difference being + * former raises on implicit copy, latter does not. */ VALUE -ruby_xml_node_child_set(VALUE self, VALUE rnode) { +ruby_xml_node_child_set_aux(VALUE self, VALUE rnode, int do_raise) { ruby_xml_node *cnode, *pnode; xmlNodePtr chld, ret; int copied=0; if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse) @@ -332,11 +328,12 @@ chld = cnode->node; if ( chld->parent != NULL || chld->doc != NULL ) { chld=xmlCopyNode(chld,1); copied=1; - rb_warning("implicit copy of %s",chld->name); + if ( do_raise == 1 ) + rb_raise(rb_eRuntimeError, "implicit copy not legal for child= or <<"); } ret = xmlAddChild(pnode->node, chld); if (ret == NULL) { if ( copied == 1 ) @@ -348,10 +345,32 @@ return ruby_xml_node2_wrap(cXMLNode,chld); } /* * call-seq: + * node.child = node + * + * Set a child node for this node. Also called for << + */ +VALUE +ruby_xml_node_child_set(VALUE self, VALUE rnode) { + return ruby_xml_node_child_set_aux(self,rnode,1); +} + +/* + * call-seq: + * node.child_add(node) + * + * Set a child node for this node. + */ +VALUE +ruby_xml_node_child_add(VALUE self, VALUE rnode) { + return ruby_xml_node_child_set_aux(self,rnode,0); +} + +/* + * call-seq: * node.doc => document * * Obtain the XML::Document this node belongs to. */ VALUE @@ -626,23 +645,14 @@ * Find nodes matching the specified xpath expression, optionally * using the specified namespaces. Returns an XML::Node::Set. */ VALUE ruby_xml_node_find(int argc, VALUE *argv, VALUE self) { - int i, vargc; - VALUE *vargv; - if (argc > 2 || argc < 1) rb_raise(rb_eArgError, "wrong number of arguments (need 1 or 2)"); - vargc = argc + 1; - vargv = ALLOC_N(VALUE, vargc + 1); - vargv[0] = self; - for (i = 0; i<argc; i++) - vargv[i + 1] = argv[i]; - - return(ruby_xml_xpath_find2(vargc, vargv)); + return(ruby_xml_xpath_find2(self,argv[0],(argc==2)?argv[1]:Qnil)); } /* * call-seq: * node.find_first(xpath_expr, namespace = [any]) => nodeset @@ -650,27 +660,11 @@ * Find the first node matching the specified xpath expression, optionally * using the specified namespaces. Returns an XML::Node. */ VALUE ruby_xml_node_find_first(int argc, VALUE *argv, VALUE self) { - VALUE ns = ruby_xml_node_find(argc, argv, self); - ruby_xml_node_set *rxnset; - VALUE nodeobj; - - Data_Get_Struct(ns, ruby_xml_node_set, rxnset); - if (rxnset->node_set == NULL || rxnset->node_set->nodeNr < 1) - return(Qnil); - - switch(rxnset->node_set->nodeTab[0]->type) { - case XML_ATTRIBUTE_NODE: - nodeobj = ruby_xml_attr_wrap(cXMLAttr, (xmlAttrPtr)rxnset->node_set->nodeTab[0]); - break; - default: - nodeobj = ruby_xml_node2_wrap(cXMLNode, rxnset->node_set->nodeTab[0]); - } - - return(nodeobj); + return ruby_xml_xpath_object_first(ruby_xml_node_find(argc, argv, self)); } /* * call-seq: @@ -1244,79 +1238,92 @@ * If the xmlNode has no parent or document, then call xmlFree. */ void ruby_xml_node2_free(ruby_xml_node *rxn) { - if (rxn->node == NULL ) return; + if (rxn == NULL ) return; - if (rxn->node->parent == NULL && rxn->node->doc == NULL ) { + if (rxn->node != NULL ) { + rxn->node->_private=NULL; + + if ( rxn->node->doc==NULL && rxn->node->parent==NULL ) { #ifdef NODE_DEBUG - fprintf(stderr,"free rxn=0x%x xn=0x%x o=0x%x\n",(long)rxn,(long)rxn->node,(long)rxn->node->_private); + fprintf(stderr,"ruby_xml_node2_free free rxn=0x%x xn=0x%x o=0x%x\n",(long)rxn,(long)rxn->node,(long)rxn->node->_private); #endif - rxn->node->_private=NULL; - xmlFreeNode(rxn->node); + xmlFreeNode(rxn->node); + } + + rxn->node=NULL; } - rxn->node=NULL; - // fprintf(stderr,"%0x ",(long)rxn); free(rxn); } void +ruby_xml_node_mark_common(xmlNodePtr node) { + if (node->parent == NULL ) { +#ifdef NODE_DEBUG + fprintf(stderr,"mark no parent r=0x%x *n=0x%x\n",rxn,node); +#endif + } else if ( node->doc != NULL ) { + if (node->doc->_private == NULL) { + rb_bug("XmlNode Doc is not bound! (%s:%d)", + __FILE__,__LINE__); + } + rb_gc_mark((VALUE)node->doc->_private); + } else { + while (node->parent != NULL ) + node=node->parent; + if (node->_private == NULL ) + rb_warning("XmlNode Root Parent is not bound! (%s:%d)", + __FILE__,__LINE__); + else { +#ifdef NODE_DEBUG + fprintf(stderr,"mark rxn=0x%x xn=0x%x o=0x%x doc=0x%x\n",(long)rxn,(long)node,(long)node->_private,node->doc); +#endif + rb_gc_mark((VALUE)node->_private); + } + } +} + +void ruby_xml_node2_mark(ruby_xml_node *rxn) { xmlNodePtr node; if (rxn->node == NULL ) return; if (rxn->node->_private == NULL ) { rb_warning("XmlNode is not bound! (%s:%d)", __FILE__,__LINE__); return; } - if (rxn->node->doc != NULL ) { - if (rxn->node->doc->_private == NULL ) - rb_warning("XmlNode Doc is not bound! (%s:%d)", - __FILE__,__LINE__); - else { - rb_gc_mark((VALUE)rxn->node->doc->_private); -#ifdef NODE_DEBUG - fprintf(stderr,"mark rxn=0x%x xn=0x%x o=0x%x\n",(long)rxn,(long)rxn->node,(long)rxn->node->_private); -#endif - } - } else if (rxn->node->parent != NULL ) { - if (rxn->node->parent->_private == NULL ) - rb_warning("XmlNode Parent is not bound! (%s:%d)", - __FILE__,__LINE__); - node=rxn->node; - while (node->parent != NULL ) - node=node->parent; - if (node->_private != NULL) { - rb_gc_mark((VALUE)node->_private); -#ifdef NODE_DEBUG - fprintf(stderr,"mark rxn=0x%x xn=0x%x o=0x%x\n",(long)0,(long)node,(long)node->_private); -#endif - } - } + ruby_xml_node_mark_common(rxn->node); } VALUE ruby_xml_node2_wrap(VALUE class, xmlNodePtr xnode) { VALUE obj; ruby_xml_node *rxn; // This node is already wrapped - if (xnode->_private != NULL) + if (xnode->_private != NULL) { +#ifdef NODE_DEBUG + Data_Get_Struct((VALUE)xnode->_private,ruby_xml_node,rxn); + fprintf(stderr,"re-wrap rn=0x%x n*=0x%x\n",(long)rxn,(long)xnode); +#endif return (VALUE)xnode->_private; + } obj=Data_Make_Struct(class,ruby_xml_node,ruby_xml_node2_mark, ruby_xml_node2_free,rxn); rxn->node=xnode; xnode->_private=(void*)obj; #ifdef NODE_DEBUG - fprintf(stderr,"wrap rxn=0x%x xn=0x%x o=0x%x\n",(long)rxn,(long)xnode,(long)obj); + fprintf(stderr,"wrap rn=0x%x n*=0x%x d*=0x%x\n", + (long)rxn,(long)xnode,xnode->doc); #endif return obj; } VALUE @@ -2207,20 +2214,30 @@ ruby_xml_node_registerNode(xmlNodePtr node) { node->_private=NULL; } +void +ruby_xml_node_deregisterNode(xmlNodePtr node) +{ + ruby_xml_node *rxn; + if ( node->_private==NULL ) return; + Data_Get_Struct(node->_private, ruby_xml_node, rxn); + rxn->node=NULL; +} + // Rdoc needs to know #ifdef RDOC_NEVER_DEFINED mXML = rb_define_module("XML"); #endif void ruby_init_xml_node(void) { VALUE singleton; xmlRegisterNodeDefault(ruby_xml_node_registerNode); + xmlDeregisterNodeDefault(ruby_xml_node_deregisterNode); cXMLNode = rb_define_class_under(mXML, "Node", rb_cObject); eXMLNodeSetNamespace = rb_define_class_under(cXMLNode, "SetNamespace", eXMLError); eXMLNodeFailedModify = rb_define_class_under(cXMLNode, "FailedModify", eXMLError); eXMLNodeUnknownType = rb_define_class_under(cXMLNode, "UnknownType", eXMLError); @@ -2261,10 +2278,10 @@ rb_define_method(cXMLNode, "comment?", ruby_xml_node_comment_q, 0); rb_define_method(cXMLNode, "copy", ruby_xml_node_copy, 1); rb_define_method(cXMLNode, "child", ruby_xml_node_child_get, 0); rb_define_method(cXMLNode, "child?", ruby_xml_node_child_q, 0); rb_define_method(cXMLNode, "child=", ruby_xml_node_child_set, 1); - rb_define_method(cXMLNode, "child_add", ruby_xml_node_child_set, 1); + rb_define_method(cXMLNode, "child_add", ruby_xml_node_child_add, 1); rb_define_method(cXMLNode, "children", ruby_xml_node_child_get, 0); rb_define_method(cXMLNode, "children?", ruby_xml_node_child_q, 0); rb_define_method(cXMLNode, "content", ruby_xml_node_content_get, 0); rb_define_method(cXMLNode, "content=", ruby_xml_node_content_set, 1); rb_define_method(cXMLNode, "content_stripped", ruby_xml_node_content_stripped_get, 0);