@@ -30,9 +30,9 @@ VALUE cXMLNode;
3030 * have a parent and do not belong to a document). In these cases,
3131 * the bindings manage the memory. They do this by installing a free
3232 * function and storing a back pointer to the Ruby object from the xmlnode
33- * using the _private member on libxml structures. When the Ruby object
34- * goes out of scope, the underlying libxml structure is freed. Libxml
35- * itself then frees all child node (recursively).
33+ * using a pointer-keyed registry (see ruby_xml_registry.c). When the
34+ * Ruby object goes out of scope, the underlying libxml structure is freed.
35+ * Libxml itself then frees all child node (recursively).
3636 *
3737 * For all other nodes (the vast majority), the bindings create temporary
3838 * Ruby objects that get freed once they go out of scope. Thus there can be
@@ -60,8 +60,7 @@ static void rxml_node_free(void *data)
6060 responsible for freeing the underlying node.*/
6161 if (xnode -> doc == NULL && xnode -> parent == NULL )
6262 {
63- // Remove the back linkage from libxml to Ruby
64- xnode -> _private = NULL ;
63+ rxml_registry_unregister (xnode );
6564 xmlFreeNode (xnode );
6665 }
6766}
@@ -108,14 +107,14 @@ void rxml_node_manage(xmlNodePtr xnode, VALUE node)
108107{
109108 VALUE * type_ptr = (VALUE * )& RTYPEDDATA (node )-> type ;
110109 * type_ptr = (* type_ptr & TYPED_DATA_EMBEDDED ) | (VALUE )& rxml_node_managed_data_type ;
111- xnode -> _private = ( void * ) node ;
110+ rxml_registry_register ( xnode , node ) ;
112111}
113112
114113void rxml_node_unmanage (xmlNodePtr xnode , VALUE node )
115114{
116115 VALUE * type_ptr = (VALUE * )& RTYPEDDATA (node )-> type ;
117116 * type_ptr = (* type_ptr & TYPED_DATA_EMBEDDED ) | (VALUE )& rxml_node_data_type ;
118- xnode -> _private = NULL ;
117+ rxml_registry_unregister ( xnode ) ;
119118}
120119
121120xmlNodePtr rxml_node_root (xmlNodePtr xnode )
@@ -134,20 +133,16 @@ void rxml_node_mark(xmlNodePtr xnode)
134133{
135134 if (xnode -> doc )
136135 {
137- if (xnode -> doc -> _private )
138- {
139- VALUE doc = (VALUE )xnode -> doc -> _private ;
140- rb_gc_mark (doc );
141- }
136+ VALUE doc = rxml_registry_lookup (xnode -> doc );
137+ if (!NIL_P (doc ))
138+ rb_gc_mark (doc );
142139 }
143140 else if (xnode -> parent )
144141 {
145142 xmlNodePtr root = rxml_node_root (xnode );
146- if (root -> _private )
147- {
148- VALUE node = (VALUE )root -> _private ;
143+ VALUE node = rxml_registry_lookup (root );
144+ if (!NIL_P (node ))
149145 rb_gc_mark (node );
150- }
151146 }
152147}
153148
@@ -156,11 +151,8 @@ VALUE rxml_node_wrap(xmlNodePtr xnode)
156151 VALUE result = Qnil ;
157152
158153 // Is this node already wrapped?
159- if (xnode -> _private )
160- {
161- result = (VALUE )xnode -> _private ;
162- }
163- else
154+ result = rxml_registry_lookup (xnode );
155+ if (NIL_P (result ))
164156 {
165157 result = TypedData_Wrap_Struct (cXMLNode , & rxml_node_data_type , xnode );
166158 }
@@ -580,7 +572,7 @@ static VALUE rxml_node_doc(VALUE self)
580572 if (xdoc == NULL )
581573 return (Qnil );
582574
583- return ( VALUE ) xdoc -> _private ;
575+ return rxml_registry_lookup ( xdoc ) ;
584576}
585577
586578/*
0 commit comments