public
Description: Nokogiri (鋸) is an HTML, XML, SAX, and Reader parser with XPath and CSS selector support.
Homepage: http://nokogiri.rubyforge.org/
Clone URL: git://github.com/tenderlove/nokogiri.git
documents must gc_mark their constituent nodes.

without doing this, the ruby objects for individual nodes (although
not the underlying xmlNodes) can be GC'ed, meaning that the node's
pointer to itself (via _private) is no longer valid.
mdalessio (author)
Tue Sep 30 08:52:43 -0700 2008
commit  ff434d21e8cd63cf0aa15981711df205d75ed53a
tree    b236daeb3b65ed2468d77de5d986b16c718985d5
parent  2b8bd4a6147f669b2eac6cc2c9961cfb98694477
...
47
48
49
50
51
52
 
53
54
55
...
47
48
49
 
 
 
50
51
52
53
0
@@ -47,9 +47,7 @@ static VALUE read_memory( VALUE klass,
0
   if(doc == NULL)
0
     doc = htmlNewDoc((const xmlChar *)c_url, NULL);
0
 
0
- VALUE rb_doc = Data_Wrap_Struct(klass, NULL, dealloc, doc);
0
- doc->_private = (void*)rb_doc;
0
- return rb_doc;
0
+ return Nokogiri_wrap_xml_document(klass, doc);
0
 }
0
 
0
 /*
...
1
2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
4
5
...
78
79
80
81
82
83
 
84
85
86
...
90
91
92
93
94
95
 
96
97
98
...
135
136
137
138
139
 
 
140
141
 
 
 
 
 
142
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
95
96
97
 
 
 
98
99
100
101
...
105
106
107
 
 
 
108
109
110
111
...
148
149
150
 
 
151
152
153
 
154
155
156
157
158
159
0
@@ -1,5 +1,22 @@
0
 #include <xml_document.h>
0
 
0
+/*
0
+ * note that xmlDocPtr is being cast as an xmlNodePtr, which is legal for the
0
+ * "common part" struct header which contains only node pointers. casting like
0
+ * this allows us to recurse through the tree with a single function.
0
+ */
0
+static void gc_mark(xmlNodePtr doc)
0
+{
0
+ xmlNodePtr j ;
0
+ j = doc->children ;
0
+ while (j != NULL) {
0
+ if (j->_private)
0
+ rb_gc_mark((VALUE)j->_private);
0
+ gc_mark(j); /* recurse */
0
+ j = j->next ;
0
+ }
0
+}
0
+
0
 static void dealloc(xmlDocPtr doc)
0
 {
0
   xmlFreeDoc(doc);
0
@@ -78,9 +95,7 @@ static VALUE read_memory( VALUE klass,
0
     rb_raise(rb_eRuntimeError, "Couldn't create a document");
0
   }
0
 
0
- VALUE rb_doc = Data_Wrap_Struct(klass, NULL, dealloc, doc);
0
- doc->_private = (void *)rb_doc;
0
- return rb_doc;
0
+ return Nokogiri_wrap_xml_document(klass, doc);
0
 }
0
 
0
 static VALUE new(int argc, VALUE *argv, VALUE klass)
0
@@ -90,9 +105,7 @@ static VALUE new(int argc, VALUE *argv, VALUE klass)
0
     version = rb_str_new2("1.0");
0
 
0
   xmlDocPtr doc = xmlNewDoc((xmlChar *)StringValuePtr(version));
0
- VALUE rb_doc = Data_Wrap_Struct(klass, NULL, dealloc, doc);
0
- doc->_private = (void *)rb_doc;
0
- return rb_doc;
0
+ return Nokogiri_wrap_xml_document(klass, doc);
0
 }
0
 
0
 /*
0
@@ -135,8 +148,12 @@ void init_xml_document()
0
 }
0
 
0
 
0
-/* public API */
0
-VALUE Nokogiri_wrap_xml_document(xmlDocPtr doc)
0
+/* this takes klass as a param because it's used for HtmlDocument, too. */
0
+VALUE Nokogiri_wrap_xml_document(VALUE klass, xmlDocPtr doc)
0
 {
0
- return Data_Wrap_Struct(cNokogiriXmlDocument, 0, dealloc, doc) ;
0
+ if (doc->_private)
0
+ return (VALUE)doc->_private ;
0
+ VALUE rb_doc = Data_Wrap_Struct(klass ? klass : cNokogiriXmlDocument, gc_mark, dealloc, doc) ;
0
+ doc->_private = (void*)rb_doc ;
0
+ return rb_doc ;
0
 }
...
4
5
6
7
 
8
9
10
...
4
5
6
 
7
8
9
10
0
@@ -4,7 +4,7 @@
0
 #include <native.h>
0
 
0
 void init_xml_document();
0
-VALUE Nokogiri_wrap_xml_document(xmlDocPtr doc);
0
+VALUE Nokogiri_wrap_xml_document(VALUE klass, xmlDocPtr doc);
0
 
0
 extern VALUE cNokogiriXmlDocument ;
0
 #endif
...
68
69
70
71
 
72
73
74
...
68
69
70
 
71
72
73
74
0
@@ -68,7 +68,7 @@ static VALUE apply_to(int argc, VALUE* argv, VALUE self)
0
 
0
     result = xsltApplyStylesheet(ss, xml, params);
0
     free(params);
0
- resultobj = Nokogiri_wrap_xml_document(result) ;
0
+ resultobj = Nokogiri_wrap_xml_document(0, result) ;
0
     return rb_funcall(self, rb_intern("serialize"), 1, resultobj);
0
 }
0
 

Comments

    No one has commented yet.