rrichards Sun Oct 26 10:53:20 2003 EDT Modified files: /php-src/ext/libxml libxml.c php_libxml.h Log: common functions for interoperability
Index: php-src/ext/libxml/libxml.c diff -u php-src/ext/libxml/libxml.c:1.6 php-src/ext/libxml/libxml.c:1.7 --- php-src/ext/libxml/libxml.c:1.6 Mon Oct 20 11:33:40 2003 +++ php-src/ext/libxml/libxml.c Sun Oct 26 10:53:20 2003 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: libxml.c,v 1.6 2003/10/20 15:33:40 moriyoshi Exp $ */ +/* $Id: libxml.c,v 1.7 2003/10/26 15:53:20 rrichards Exp $ */ #define IS_EXT_MODULE @@ -91,6 +91,131 @@ /* }}} */ +/* {{{ internal functions for interoperability */ +static int php_libxml_dec_node(php_libxml_node_ptr *nodeptr) +{ + int ret_refcount; + + ret_refcount = --nodeptr->refcount; + if (ret_refcount == 0) { + if (nodeptr->node != NULL && nodeptr->node->type != XML_DOCUMENT_NODE) { + nodeptr->node->_private = NULL; + } + /* node is destroyed by another object. reset ret_refcount to 1 and node to NULL + so the php_libxml_node_ptr is detroyed when the object is destroyed */ + nodeptr->refcount = 1; + nodeptr->node = NULL; + } + + return ret_refcount; +} + +static int php_libxml_clear_object(php_libxml_node_object *object TSRMLS_DC) +{ + if (object->properties) { + object->properties = NULL; + } + php_libxml_decrement_node_ptr(object TSRMLS_CC); + return php_libxml_decrement_doc_ref(object TSRMLS_CC); +} + +static int php_libxml_unregister_node(xmlNodePtr nodep TSRMLS_DC) +{ + php_libxml_node_object *wrapper; + + php_libxml_node_ptr *nodeptr = nodep->_private; + + if (nodeptr != NULL) { + wrapper = nodeptr->_private; + if (wrapper) { + php_libxml_clear_object(wrapper TSRMLS_CC); + } else { + php_libxml_dec_node(nodeptr); + } + } + + return -1; +} + +static void php_libxml_node_free(xmlNodePtr node) +{ + if(node) { + if (node->_private != NULL) { + ((php_libxml_node_ptr *) node->_private)->node = NULL; + } + switch (node->type) { + case XML_ATTRIBUTE_NODE: + xmlFreeProp((xmlAttrPtr) node); + break; + case XML_ENTITY_DECL: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + break; + case XML_NOTATION_NODE: + /* These require special handling */ + if (node->name != NULL) { + xmlFree((char *) node->name); + } + if (((xmlEntityPtr) node)->ExternalID != NULL) { + xmlFree((char *) ((xmlEntityPtr) node)->ExternalID); + } + if (((xmlEntityPtr) node)->SystemID != NULL) { + xmlFree((char *) ((xmlEntityPtr) node)->SystemID); + } + xmlFree(node); + break; + case XML_NAMESPACE_DECL: + if (node->ns) { + xmlFreeNs(node->ns); + node->ns = NULL; + } + node->type = XML_ELEMENT_NODE; + default: + xmlFreeNode(node); + } + } +} + +static void php_libxml_node_free_list(xmlNodePtr node TSRMLS_DC) +{ + xmlNodePtr curnode; + + if (node != NULL) { + curnode = node; + while (curnode != NULL) { + node = curnode; + switch (node->type) { + /* Skip property freeing for the following types */ + case XML_NOTATION_NODE: + break; + case XML_ENTITY_REF_NODE: + php_libxml_node_free_list((xmlNodePtr) node->properties TSRMLS_CC); + break; + case XML_ATTRIBUTE_DECL: + case XML_DTD_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_ENTITY_DECL: + case XML_ATTRIBUTE_NODE: + case XML_NAMESPACE_DECL: + php_libxml_node_free_list(node->children TSRMLS_CC); + break; + default: + php_libxml_node_free_list(node->children TSRMLS_CC); + php_libxml_node_free_list((xmlNodePtr) node->properties TSRMLS_CC); + } + + curnode = node->next; + xmlUnlinkNode(node); + if (php_libxml_unregister_node(node TSRMLS_CC) == 0) { + node->doc = NULL; + } + php_libxml_node_free(node); + } + } +} + +/* }}} */ + /* {{{ startup, shutdown and info functions */ #ifdef ZTS static void php_libxml_init_globals(php_libxml_globals *libxml_globals_p TSRMLS_DC) @@ -273,6 +398,149 @@ } ZVAL_ADDREF(arg); LIBXML(stream_context) = arg; +} +/* }}} */ + +/* {{{ Common functions shared by extensions */ +int php_libxml_increment_node_ptr(php_libxml_node_object *object, xmlNodePtr node, void *private_data TSRMLS_DC) +{ + int ret_refcount = -1; + + if (object != NULL && node != NULL) { + if (object->node != NULL) { + if (object->node->node == node) { + return object->node->refcount; + } else { + php_libxml_decrement_node_ptr(object TSRMLS_CC); + } + } + if (node->_private != NULL) { + object->node = node->_private; + ret_refcount = ++object->node->refcount; + /* Only dom uses _private */ + if (object->node->_private == NULL) { + object->node->_private = private_data; + } + } else { + ret_refcount = 1; + object->node = emalloc(sizeof(php_libxml_node_ptr)); + object->node->node = node; + object->node->refcount = 1; + object->node->_private = private_data; + node->_private = object->node; + } + } + + return ret_refcount; +} + +int php_libxml_decrement_node_ptr(php_libxml_node_object *object TSRMLS_DC) { + int ret_refcount = -1; + php_libxml_node_ptr *obj_node; + + if (object != NULL && object->node != NULL) { + obj_node = (php_libxml_node_ptr *) object->node; + ret_refcount = --obj_node->refcount; + if (ret_refcount == 0) { + if (obj_node->node != NULL && obj_node->node->type != XML_DOCUMENT_NODE) { + obj_node->node->_private = NULL; + } + efree(obj_node); + } + object->node = NULL; + } + + return ret_refcount; +} + +int php_libxml_increment_doc_ref(php_libxml_node_object *object, xmlDocPtr docp TSRMLS_DC) { + int ret_refcount = -1; + + if (object->document != NULL) { + object->document->refcount++; + ret_refcount = object->document->refcount; + } else if (docp != NULL) { + ret_refcount = 1; + object->document = emalloc(sizeof(php_libxml_ref_obj)); + object->document->ptr = docp; + object->document->refcount = ret_refcount; + object->document->doc_props = NULL; + } + + return ret_refcount; +} + +int php_libxml_decrement_doc_ref(php_libxml_node_object *object TSRMLS_DC) { + int ret_refcount = -1; + + if (object != NULL && object->document != NULL) { + ret_refcount = --object->document->refcount; + if (ret_refcount == 0) { + if (object->document->ptr != NULL) { + xmlFreeDoc((xmlDoc *) object->document->ptr); + } + if (object->document->doc_props != NULL) { + efree(object->document->doc_props); + } + efree(object->document); + } + object->document = NULL; + } + + return ret_refcount; +} + +void php_libxml_node_free_resource(xmlNodePtr node TSRMLS_DC) +{ + if (!node) { + return; + } + + switch (node->type) { + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: + break; + default: + if (node->parent == NULL || node->type == XML_NAMESPACE_DECL) { + php_libxml_node_free_list((xmlNodePtr) node->children TSRMLS_CC); + switch (node->type) { + /* Skip property freeing for the following types */ + case XML_ATTRIBUTE_DECL: + case XML_DTD_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_ENTITY_DECL: + case XML_ATTRIBUTE_NODE: + case XML_NAMESPACE_DECL: + break; + default: + php_libxml_node_free_list((xmlNodePtr) node->properties TSRMLS_CC); + } + if (php_libxml_unregister_node(node TSRMLS_CC) == 0) { + node->doc = NULL; + } + php_libxml_node_free(node); + } else { + php_libxml_unregister_node(node TSRMLS_CC); + } + } +} + +void php_libxml_node_decrement_resource(php_libxml_node_object *object TSRMLS_DC) +{ + int ret_refcount = -1; + xmlNodePtr nodep; + php_libxml_node_ptr *obj_node; + + if (object != NULL && object->node != NULL) { + obj_node = (php_libxml_node_ptr *) object->node; + nodep = object->node->node; + ret_refcount = php_libxml_decrement_node_ptr(object TSRMLS_CC); + if (ret_refcount == 0) { + php_libxml_node_free_resource(nodep TSRMLS_CC); + } + /* Safe to call as if the resource were freed then doc pointer is NULL */ + php_libxml_decrement_doc_ref(object TSRMLS_CC); + } } /* }}} */ Index: php-src/ext/libxml/php_libxml.h diff -u php-src/ext/libxml/php_libxml.h:1.2 php-src/ext/libxml/php_libxml.h:1.3 --- php-src/ext/libxml/php_libxml.h:1.2 Sun Oct 19 19:17:56 2003 +++ php-src/ext/libxml/php_libxml.h Sun Oct 26 10:53:20 2003 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_libxml.h,v 1.2 2003/10/19 23:17:56 shane Exp $ */ +/* $Id: php_libxml.h,v 1.3 2003/10/26 15:53:20 rrichards Exp $ */ #ifndef PHP_LIBXML_H #define PHP_LIBXML_H @@ -37,14 +37,40 @@ #define PHP_LIBXML_API #endif - +#include <libxml/tree.h> typedef struct { zval *stream_context; } php_libxml_globals; - +typedef struct _php_libxml_ref_obj { + void *ptr; + int refcount; + void *doc_props; +} php_libxml_ref_obj; + +typedef struct _php_libxml_node_ptr { + xmlNodePtr node; + int refcount; + void *_private; +} php_libxml_node_ptr; + +typedef struct _php_libxml_node_object { + zend_object std; + php_libxml_node_ptr *node; + php_libxml_ref_obj *document; + HashTable *properties; +} php_libxml_node_object; + PHP_FUNCTION(libxml_set_streams_context); +int php_libxml_increment_node_ptr(php_libxml_node_object *object, xmlNodePtr node, void *private_data TSRMLS_DC); +int php_libxml_decrement_node_ptr(php_libxml_node_object *object TSRMLS_DC); +int php_libxml_increment_doc_ref(php_libxml_node_object *object, xmlDocPtr docp TSRMLS_DC); +int php_libxml_decrement_doc_ref(php_libxml_node_object *object TSRMLS_DC); +/* When an explicit freeing of node and children is required */ +void php_libxml_node_free_resource(xmlNodePtr node TSRMLS_DC); +/* When object dtor is called as node may still be referenced */ +void php_libxml_node_decrement_resource(php_libxml_node_object *object TSRMLS_DC); #endif /* HAVE_LIBXML */
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php