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);