Back to index

php5  5.3.10
dom_iterators.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Authors: Christian Stocker <chregu@php.net>                          |
00016    |          Rob Richards <rrichards@php.net>                            |
00017    +----------------------------------------------------------------------+
00018 */
00019 
00020 /* $Id: dom_iterators.c 321634 2012-01-01 13:15:04Z felipe $ */
00021 
00022 #ifdef HAVE_CONFIG_H
00023 #include "config.h"
00024 #endif
00025 
00026 #include "php.h"
00027 #if HAVE_LIBXML && HAVE_DOM
00028 #include "php_dom.h"
00029 #include "dom_ce.h"
00030 
00031 typedef struct _nodeIterator nodeIterator;
00032 struct _nodeIterator {
00033        int cur;
00034        int index;
00035        xmlNode *node;
00036 };
00037 
00038 typedef struct _notationIterator notationIterator;
00039 struct _notationIterator {
00040        int cur;
00041        int index;
00042        xmlNotation *notation;
00043 };
00044 
00045 static void itemHashScanner (void *payload, void *data, xmlChar *name) /* {{{ */
00046 {
00047        nodeIterator *priv = (nodeIterator *)data;
00048 
00049        if(priv->cur < priv->index) {
00050               priv->cur++;
00051        } else {
00052               if(priv->node == NULL) {
00053                      priv->node = (xmlNode *)payload;
00054               }
00055        }
00056 }
00057 /* }}} */
00058 
00059 xmlNodePtr create_notation(const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID) /* {{{ */
00060 {
00061        xmlEntityPtr ret;
00062 
00063        ret = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
00064     memset(ret, 0, sizeof(xmlEntity));
00065     ret->type = XML_NOTATION_NODE;
00066     ret->name = xmlStrdup(name);
00067        ret->ExternalID = xmlStrdup(ExternalID);
00068        ret->SystemID = xmlStrdup(SystemID);
00069        ret->length = 0;
00070        ret->content = NULL;
00071        ret->URI = NULL;
00072        ret->orig = NULL;
00073        ret->children = NULL;
00074        ret->parent = NULL;
00075        ret->doc = NULL;
00076        ret->_private = NULL;
00077        ret->last = NULL;
00078        ret->prev = NULL;
00079        return((xmlNodePtr) ret);
00080 }
00081 /* }}} */
00082 
00083 xmlNode *php_dom_libxml_hash_iter(xmlHashTable *ht, int index) /* {{{ */
00084 {
00085        xmlNode *nodep = NULL;
00086        nodeIterator *iter;
00087        int htsize;
00088 
00089        if ((htsize = xmlHashSize(ht)) > 0 && index < htsize) {
00090               iter = emalloc(sizeof(nodeIterator));
00091               iter->cur = 0;
00092               iter->index = index;
00093               iter->node = NULL;
00094               xmlHashScan(ht, itemHashScanner, iter);
00095               nodep = iter->node;
00096               efree(iter);
00097               return nodep;
00098        } else {
00099               return NULL;
00100        }
00101 }
00102 /* }}} */
00103 
00104 xmlNode *php_dom_libxml_notation_iter(xmlHashTable *ht, int index) /* {{{ */
00105 {
00106        notationIterator *iter;
00107        xmlNotation *notep = NULL;
00108        int htsize;
00109 
00110        if ((htsize = xmlHashSize(ht)) > 0 && index < htsize) {
00111               iter = emalloc(sizeof(notationIterator));
00112               iter->cur = 0;
00113               iter->index = index;
00114               iter->notation = NULL;
00115               xmlHashScan(ht, itemHashScanner, iter);
00116               notep = iter->notation;
00117               efree(iter);
00118               return create_notation(notep->name, notep->PublicID, notep->SystemID);
00119        } else {
00120               return NULL;
00121        }
00122 }
00123 /* }}} */
00124 
00125 static void php_dom_iterator_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
00126 {
00127        php_dom_iterator *iterator = (php_dom_iterator *)iter;
00128 
00129        zval_ptr_dtor((zval**)&iterator->intern.data);
00130 
00131        if (iterator->curobj) {
00132               zval_ptr_dtor((zval**)&iterator->curobj);
00133        }
00134 
00135        efree(iterator);
00136 }
00137 /* }}} */
00138 
00139 static int php_dom_iterator_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
00140 {
00141 
00142        php_dom_iterator *iterator = (php_dom_iterator *)iter;
00143 
00144        if (iterator->curobj) {
00145               return SUCCESS;
00146        } else {
00147               return FAILURE;
00148        }
00149 }
00150 /* }}} */
00151 
00152 static void php_dom_iterator_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */
00153 {
00154        php_dom_iterator *iterator = (php_dom_iterator *)iter;
00155 
00156        *data = &iterator->curobj;
00157 }
00158 /* }}} */
00159 
00160 static int php_dom_iterator_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */
00161 {
00162        zval *curobj;
00163        xmlNodePtr curnode = NULL;
00164        dom_object *intern;
00165        zval *object;
00166        int namelen;
00167 
00168        php_dom_iterator *iterator = (php_dom_iterator *)iter;
00169 
00170        object = (zval *)iterator->intern.data;
00171 
00172        if (instanceof_function(Z_OBJCE_P(object), dom_nodelist_class_entry TSRMLS_CC)) {
00173               *int_key = iter->index;
00174               return HASH_KEY_IS_LONG;
00175        } else {
00176               curobj = iterator->curobj;
00177 
00178               intern = (dom_object *)zend_object_store_get_object(curobj TSRMLS_CC);
00179               if (intern != NULL && intern->ptr != NULL) {
00180                      curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->ptr)->node;
00181               } else {
00182                      return HASH_KEY_NON_EXISTANT;
00183               }
00184 
00185               namelen = xmlStrlen(curnode->name);
00186               *str_key = estrndup(curnode->name, namelen);
00187               *str_key_len = namelen + 1;
00188               return HASH_KEY_IS_STRING;
00189        }
00190 }
00191 /* }}} */
00192 
00193 static void php_dom_iterator_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
00194 {
00195        zval *curobj, *curattr = NULL;
00196        zval *object;
00197        xmlNodePtr curnode = NULL, basenode;
00198        dom_object *intern;
00199        dom_object *nnmap;
00200        dom_nnodemap_object *objmap;
00201        int ret, previndex=0;
00202        HashTable *nodeht;
00203        zval **entry;
00204 
00205        php_dom_iterator *iterator = (php_dom_iterator *)iter;
00206 
00207        object = (zval *)iterator->intern.data;
00208        nnmap = (dom_object *)zend_object_store_get_object(object TSRMLS_CC);
00209        objmap = (dom_nnodemap_object *)nnmap->ptr;
00210 
00211        curobj = iterator->curobj;
00212        intern = (dom_object *)zend_object_store_get_object(curobj TSRMLS_CC);
00213        if (intern != NULL && intern->ptr != NULL) {
00214               if (objmap->nodetype != XML_ENTITY_NODE && 
00215                      objmap->nodetype != XML_NOTATION_NODE) {
00216                      if (objmap->nodetype == DOM_NODESET) {
00217                             nodeht = HASH_OF(objmap->baseobjptr);
00218                             zend_hash_move_forward(nodeht);
00219                             if (zend_hash_get_current_data(nodeht, (void **) &entry)==SUCCESS) {
00220                                    curattr = *entry;
00221                                    Z_ADDREF_P(curattr);
00222                             }
00223                      } else {
00224                             curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->ptr)->node;
00225                             if (objmap->nodetype == XML_ATTRIBUTE_NODE || 
00226                                    objmap->nodetype == XML_ELEMENT_NODE) {
00227                                    curnode = curnode->next;
00228                             } else {
00229                                    /* Nav the tree evey time as this is LIVE */
00230                                    basenode = dom_object_get_node(objmap->baseobj);
00231                                    if (basenode && (basenode->type == XML_DOCUMENT_NODE || 
00232                                           basenode->type == XML_HTML_DOCUMENT_NODE)) {
00233                                           basenode = xmlDocGetRootElement((xmlDoc *) basenode);
00234                                    } else if (basenode) {
00235                                           basenode = basenode->children;
00236                                    } else {
00237                                           goto err;
00238                                    }
00239                                    curnode = dom_get_elements_by_tag_name_ns_raw(basenode, objmap->ns, objmap->local, &previndex, iter->index);
00240                             }
00241                      }
00242               } else {
00243                      if (objmap->nodetype == XML_ENTITY_NODE) {
00244                             curnode = php_dom_libxml_hash_iter(objmap->ht, iter->index);
00245                      } else {
00246                             curnode = php_dom_libxml_notation_iter(objmap->ht, iter->index);
00247                      }
00248               }
00249        }
00250 err:
00251        zval_ptr_dtor((zval**)&curobj);
00252        if (curnode) {
00253               MAKE_STD_ZVAL(curattr);
00254               curattr = php_dom_create_object(curnode, &ret, NULL, curattr, objmap->baseobj TSRMLS_CC);
00255        }
00256 
00257        iterator->curobj = curattr;
00258 }
00259 /* }}} */
00260 
00261 zend_object_iterator_funcs php_dom_iterator_funcs = {
00262        php_dom_iterator_dtor,
00263        php_dom_iterator_valid,
00264        php_dom_iterator_current_data,
00265        php_dom_iterator_current_key,
00266        php_dom_iterator_move_forward,
00267        NULL
00268 };
00269 
00270 zend_object_iterator *php_dom_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */
00271 {
00272        dom_object *intern;
00273        dom_nnodemap_object *objmap;
00274        xmlNodePtr nodep, curnode=NULL;
00275        zval *curattr = NULL;
00276        int ret, curindex = 0;
00277        HashTable *nodeht;
00278        zval **entry;
00279        php_dom_iterator *iterator;
00280 
00281        if (by_ref) {
00282               zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
00283        }
00284        iterator = emalloc(sizeof(php_dom_iterator));
00285 
00286        Z_ADDREF_P(object);
00287        iterator->intern.data = (void*)object;
00288        iterator->intern.funcs = &php_dom_iterator_funcs;
00289 
00290        intern = (dom_object *)zend_object_store_get_object(object TSRMLS_CC);
00291        objmap = (dom_nnodemap_object *)intern->ptr;
00292        if (objmap != NULL) {
00293               if (objmap->nodetype != XML_ENTITY_NODE && 
00294                      objmap->nodetype != XML_NOTATION_NODE) {
00295                      if (objmap->nodetype == DOM_NODESET) {
00296                             nodeht = HASH_OF(objmap->baseobjptr);
00297                             zend_hash_internal_pointer_reset(nodeht);
00298                             if (zend_hash_get_current_data(nodeht, (void **) &entry)==SUCCESS) {
00299                                    curattr = *entry;
00300                                    Z_ADDREF_P(curattr);
00301                             }
00302                      } else {
00303                             nodep = (xmlNode *)dom_object_get_node(objmap->baseobj);
00304                             if (!nodep) {
00305                                    goto err;
00306                             }
00307                             if (objmap->nodetype == XML_ATTRIBUTE_NODE || objmap->nodetype == XML_ELEMENT_NODE) {
00308                                    if (objmap->nodetype == XML_ATTRIBUTE_NODE) {
00309                                           curnode = (xmlNodePtr) nodep->properties;
00310                                    } else {
00311                                           curnode = (xmlNodePtr) nodep->children;
00312                                    }
00313                             } else {
00314                                    if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) {
00315                                           nodep = xmlDocGetRootElement((xmlDoc *) nodep);
00316                                    } else {
00317                                           nodep = nodep->children;
00318                                    }
00319                                    curnode = dom_get_elements_by_tag_name_ns_raw(nodep, objmap->ns, objmap->local, &curindex, 0);
00320                             }
00321                      }
00322               } else {
00323                      if (objmap->nodetype == XML_ENTITY_NODE) {
00324                             curnode = php_dom_libxml_hash_iter(objmap->ht, 0);
00325                      } else {
00326                             curnode = php_dom_libxml_notation_iter(objmap->ht, 0);
00327                      }
00328               }
00329        }
00330 err:
00331        if (curnode) {
00332               MAKE_STD_ZVAL(curattr);
00333               curattr = php_dom_create_object(curnode, &ret, NULL, curattr, objmap->baseobj TSRMLS_CC);
00334        }
00335 
00336        iterator->curobj = curattr;
00337 
00338        return (zend_object_iterator*)iterator;
00339 }
00340 /* }}} */
00341 
00342 #endif
00343 
00344 /*
00345  * Local variables:
00346  * tab-width: 4
00347  * c-basic-offset: 4
00348  * End:
00349  * vim600: noet sw=4 ts=4 fdm=marker
00350  * vim<600: noet sw=4 ts=4
00351  */