summaryrefslogtreecommitdiff
path: root/ext/dom/php_dom.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/dom/php_dom.c')
-rw-r--r--ext/dom/php_dom.c131
1 files changed, 71 insertions, 60 deletions
diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c
index f811ef892d..78ee524f61 100644
--- a/ext/dom/php_dom.c
+++ b/ext/dom/php_dom.c
@@ -74,7 +74,7 @@ static zend_function_entry dom_functions[] = {
};
-/* {{{ void increment_document_reference(dom_object *object) */
+/* {{{ int increment_document_reference(dom_object *object) */
int increment_document_reference(dom_object *object, xmlDocPtr docp TSRMLS_DC) {
int ret_refcount = -1;
@@ -82,16 +82,17 @@ int increment_document_reference(dom_object *object, xmlDocPtr docp TSRMLS_DC) {
object->document->refcount++;
ret_refcount = object->document->refcount;
} else if (docp != NULL) {
+ ret_refcount = 1;
object->document = emalloc(sizeof(dom_ref_obj));
object->document->ptr = docp;
- object->document->refcount = 1;
+ object->document->refcount = ret_refcount;
}
return ret_refcount;
}
/* }}} end increment_document_reference */
-/* {{{ void decrement_document_reference(dom_object *object) */
+/* {{{ int decrement_document_reference(dom_object *object) */
int decrement_document_reference(dom_object *object TSRMLS_DC) {
int ret_refcount = -1;
@@ -104,46 +105,93 @@ int decrement_document_reference(dom_object *object TSRMLS_DC) {
object->document->ptr = NULL;
}
efree(object->document);
- object->document = NULL;
}
+ object->document = NULL;
}
return ret_refcount;
}
/* }}} end decrement_document_reference */
+/* {{{ int decrement_node_ptr(dom_object *object) */
+int decrement_node_ptr(dom_object *object TSRMLS_DC) {
+ int ret_refcount = -1;
+
+ if (object != NULL && object->ptr != NULL) {
+ ret_refcount = --object->ptr->refcount;
+ if (ret_refcount == 0) {
+ if (object->ptr->node != NULL) {
+ object->ptr->node->_private = NULL;
+ }
+ efree(object->ptr);
+ }
+ object->ptr = NULL;
+ }
+
+ return ret_refcount;
+}
+/* }}} end decrement_node_ptr */
+
+/* {{{ xmlNodePtr dom_object_get_node(dom_object *obj) */
+xmlNodePtr dom_object_get_node(dom_object *obj)
+{
+ if (obj->ptr != NULL) {
+ return obj->ptr->node;
+ } else {
+ return NULL;
+ }
+}
+/* }}} end dom_object_get_node */
+
/* {{{ dom_object_set_data */
static void dom_object_set_data(xmlNodePtr obj, dom_object *wrapper TSRMLS_DC)
{
-
- obj->_private = wrapper;
+ if (wrapper == NULL) {
+ obj->_private = NULL;
+ } else {
+ obj->_private = wrapper->ptr;
+ }
}
/* }}} end dom_object_set_data */
-/* {{{ dom_object_get_data */
+/* {{{ dom_object *dom_object_get_data(xmlNodePtr obj) */
dom_object *dom_object_get_data(xmlNodePtr obj)
{
- return (dom_object *) obj->_private;
+ if (obj->_private != NULL) {
+ return (dom_object *) ((node_ptr *) obj->_private)->_private;
+ } else {
+ return NULL;
+ }
}
/* }}} end dom_object_get_data */
/* {{{ php_dom_clear_object */
static void php_dom_clear_object(dom_object *object TSRMLS_DC)
{
- object->ptr = NULL;
if (object->prop_handler) {
object->prop_handler = NULL;
}
+ decrement_node_ptr(object TSRMLS_CC);
decrement_document_reference(object TSRMLS_CC);
- object->document = NULL;
}
-/* }}} end dom_object_get_data */
+/* }}} end php_dom_clear_object */
-/* {{{ php_dom_set_object */
-void php_dom_set_object(dom_object *object, void *obj TSRMLS_DC)
+/* {{{ void php_dom_set_object(dom_object *object, xmlNodePtr obj TSRMLS_DC) */
+void php_dom_set_object(dom_object *object, xmlNodePtr obj TSRMLS_DC)
{
- object->ptr = obj;
- dom_object_set_data(obj, object TSRMLS_CC);
+ if (obj->_private == NULL) {
+ object->ptr = emalloc(sizeof(node_ptr));
+ object->ptr->node = obj;
+ object->ptr->refcount = 1;
+ object->ptr->_private = object;
+ dom_object_set_data(obj, object TSRMLS_CC);
+ } else if (object->ptr == NULL) {
+ object->ptr = obj->_private;
+ object->ptr->refcount++;
+ if (object->ptr->_private == NULL) {
+ object->ptr->_private = object;
+ }
+ }
}
/* }}} end php_dom_set_object */
@@ -154,7 +202,6 @@ void dom_unregister_node(xmlNodePtr nodep TSRMLS_DC)
wrapper = dom_object_get_data(nodep);
if (wrapper != NULL ) {
- dom_object_set_data(nodep, NULL TSRMLS_CC);
php_dom_clear_object(wrapper TSRMLS_CC);
}
}
@@ -635,6 +682,9 @@ void node_list_unlink(xmlNodePtr node TSRMLS_DC)
void dom_node_free(xmlNodePtr node)
{
if(node) {
+ if (node->_private != NULL) {
+ ((node_ptr *) node->_private)->node = NULL;
+ }
switch (node->type) {
case XML_ATTRIBUTE_NODE:
xmlFreeProp((xmlAttrPtr) node);
@@ -686,9 +736,6 @@ void node_free_list(xmlNodePtr node TSRMLS_DC)
/* {{{ node_free_resource */
void node_free_resource(xmlNodePtr node TSRMLS_DC)
{
- xmlDtdPtr extSubset, intSubset;
- xmlDocPtr docp;
-
if (!node) {
return;
}
@@ -696,34 +743,7 @@ void node_free_resource(xmlNodePtr node TSRMLS_DC)
switch (node->type) {
case XML_DOCUMENT_NODE:
case XML_HTML_DOCUMENT_NODE:
- {
- docp = (xmlDocPtr) node;
- if (docp->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) docp->ids);
- docp->ids = NULL;
- if (docp->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) docp->refs);
- docp->refs = NULL;
- extSubset = docp->extSubset;
- intSubset = docp->intSubset;
- if (intSubset == extSubset)
- extSubset = NULL;
- if (extSubset != NULL) {
- node_free_list((xmlNodePtr) extSubset->children TSRMLS_CC);
- xmlUnlinkNode((xmlNodePtr) docp->extSubset);
- docp->extSubset = NULL;
- xmlFreeDtd(extSubset);
- }
- if (intSubset != NULL) {
- node_free_list((xmlNodePtr) intSubset->children TSRMLS_CC);
- xmlUnlinkNode((xmlNodePtr) docp->intSubset);
- docp->intSubset = NULL;
- xmlFreeDtd(intSubset);
- }
-
- node_free_list(node->children TSRMLS_CC);
- node_free_list((xmlNodePtr) node->properties TSRMLS_CC);
- xmlFreeDoc((xmlDoc *) node);
break;
- }
default:
if (node->parent == NULL) {
node_free_list((xmlNodePtr) node->children TSRMLS_CC);
@@ -739,13 +759,7 @@ void node_free_resource(xmlNodePtr node TSRMLS_DC)
node_free_list((xmlNodePtr) node->properties TSRMLS_CC);
}
dom_unregister_node(node TSRMLS_CC);
- switch (node->type) {
- case XML_ATTRIBUTE_NODE:
- xmlFreeProp((xmlAttrPtr) node);
- break;
- default:
- xmlFreeNode((xmlNode *) node);
- }
+ dom_node_free(node);
} else {
dom_unregister_node(node TSRMLS_CC);
}
@@ -769,15 +783,12 @@ void dom_objects_dtor(void *object, zend_object_handle handle TSRMLS_DC)
zend_hash_destroy(intern->std.properties);
FREE_HASHTABLE(intern->std.properties);
- if (intern->ptr) {
- if (((xmlNodePtr) intern->ptr)->type != XML_DOCUMENT_NODE && ((xmlNodePtr) intern->ptr)->type != XML_HTML_DOCUMENT_NODE) {
- node_free_resource(intern->ptr TSRMLS_CC);
+ if (intern->ptr != NULL && intern->ptr->node != NULL) {
+ if (((xmlNodePtr) intern->ptr->node)->type != XML_DOCUMENT_NODE && ((xmlNodePtr) intern->ptr->node)->type != XML_HTML_DOCUMENT_NODE) {
+ node_free_resource(dom_object_get_node(intern) TSRMLS_CC);
} else {
+ decrement_node_ptr(intern TSRMLS_CC);
retcount = decrement_document_reference(intern TSRMLS_CC);
- if (retcount != 0) {
- dom_object_set_data(intern->ptr, NULL TSRMLS_CC);
- }
- intern->document = NULL;
}
intern->ptr = NULL;
}