root/ext/dom/dom_iterators.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. itemHashScanner
  2. create_notation
  3. php_dom_libxml_hash_iter
  4. php_dom_libxml_notation_iter
  5. php_dom_iterator_dtor
  6. php_dom_iterator_valid
  7. php_dom_iterator_current_data
  8. php_dom_iterator_current_key
  9. php_dom_iterator_move_forward
  10. php_dom_get_iterator

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 7                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP license,      |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Authors: Christian Stocker <chregu@php.net>                          |
  16    |          Rob Richards <rrichards@php.net>                            |
  17    +----------------------------------------------------------------------+
  18 */
  19 
  20 /* $Id$ */
  21 
  22 #ifdef HAVE_CONFIG_H
  23 #include "config.h"
  24 #endif
  25 
  26 #include "php.h"
  27 #if HAVE_LIBXML && HAVE_DOM
  28 #include "php_dom.h"
  29 #include "dom_ce.h"
  30 
  31 typedef struct _nodeIterator nodeIterator;
  32 struct _nodeIterator {
  33         int cur;
  34         int index;
  35         xmlNode *node;
  36 };
  37 
  38 typedef struct _notationIterator notationIterator;
  39 struct _notationIterator {
  40         int cur;
  41         int index;
  42         xmlNotation *notation;
  43 };
  44 
  45 static void itemHashScanner (void *payload, void *data, xmlChar *name) /* {{{ */
  46 {
  47         nodeIterator *priv = (nodeIterator *)data;
  48 
  49         if(priv->cur < priv->index) {
  50                 priv->cur++;
  51         } else {
  52                 if(priv->node == NULL) {
  53                         priv->node = (xmlNode *)payload;
  54                 }
  55         }
  56 }
  57 /* }}} */
  58 
  59 xmlNodePtr create_notation(const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID) /* {{{ */
  60 {
  61         xmlEntityPtr ret;
  62 
  63         ret = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
  64     memset(ret, 0, sizeof(xmlEntity));
  65     ret->type = XML_NOTATION_NODE;
  66     ret->name = xmlStrdup(name);
  67         ret->ExternalID = xmlStrdup(ExternalID);
  68         ret->SystemID = xmlStrdup(SystemID);
  69         ret->length = 0;
  70         ret->content = NULL;
  71         ret->URI = NULL;
  72         ret->orig = NULL;
  73         ret->children = NULL;
  74         ret->parent = NULL;
  75         ret->doc = NULL;
  76         ret->_private = NULL;
  77         ret->last = NULL;
  78         ret->prev = NULL;
  79         return((xmlNodePtr) ret);
  80 }
  81 /* }}} */
  82 
  83 xmlNode *php_dom_libxml_hash_iter(xmlHashTable *ht, int index) /* {{{ */
  84 {
  85         xmlNode *nodep = NULL;
  86         nodeIterator *iter;
  87         int htsize;
  88 
  89         if ((htsize = xmlHashSize(ht)) > 0 && index < htsize) {
  90                 iter = emalloc(sizeof(nodeIterator));
  91                 iter->cur = 0;
  92                 iter->index = index;
  93                 iter->node = NULL;
  94                 xmlHashScan(ht, itemHashScanner, iter);
  95                 nodep = iter->node;
  96                 efree(iter);
  97                 return nodep;
  98         } else {
  99                 return NULL;
 100         }
 101 }
 102 /* }}} */
 103 
 104 xmlNode *php_dom_libxml_notation_iter(xmlHashTable *ht, int index) /* {{{ */
 105 {
 106         notationIterator *iter;
 107         xmlNotation *notep = NULL;
 108         int htsize;
 109 
 110         if ((htsize = xmlHashSize(ht)) > 0 && index < htsize) {
 111                 iter = emalloc(sizeof(notationIterator));
 112                 iter->cur = 0;
 113                 iter->index = index;
 114                 iter->notation = NULL;
 115                 xmlHashScan(ht, itemHashScanner, iter);
 116                 notep = iter->notation;
 117                 efree(iter);
 118                 return create_notation(notep->name, notep->PublicID, notep->SystemID);
 119         } else {
 120                 return NULL;
 121         }
 122 }
 123 /* }}} */
 124 
 125 static void php_dom_iterator_dtor(zend_object_iterator *iter) /* {{{ */
 126 {
 127         php_dom_iterator *iterator = (php_dom_iterator *)iter;
 128 
 129         zval_ptr_dtor(&iterator->intern.data);
 130         zval_ptr_dtor(&iterator->curobj);
 131 }
 132 /* }}} */
 133 
 134 static int php_dom_iterator_valid(zend_object_iterator *iter) /* {{{ */
 135 {
 136 
 137         php_dom_iterator *iterator = (php_dom_iterator *)iter;
 138 
 139         if (Z_TYPE(iterator->curobj) != IS_UNDEF) {
 140                 return SUCCESS;
 141         } else {
 142                 return FAILURE;
 143         }
 144 }
 145 /* }}} */
 146 
 147 zval *php_dom_iterator_current_data(zend_object_iterator *iter) /* {{{ */
 148 {
 149         php_dom_iterator *iterator = (php_dom_iterator *)iter;
 150 
 151         return &iterator->curobj;
 152 }
 153 /* }}} */
 154 
 155 static void php_dom_iterator_current_key(zend_object_iterator *iter, zval *key) /* {{{ */
 156 {
 157         php_dom_iterator *iterator = (php_dom_iterator *)iter;
 158         zval *object = &iterator->intern.data;
 159 
 160         if (instanceof_function(Z_OBJCE_P(object), dom_nodelist_class_entry)) {
 161                 ZVAL_LONG(key, iter->index);
 162         } else {
 163                 dom_object *intern = Z_DOMOBJ_P(&iterator->curobj);
 164 
 165                 if (intern != NULL && intern->ptr != NULL) {
 166                         xmlNodePtr curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->ptr)->node;
 167                         ZVAL_STRINGL(key, (char *) curnode->name, xmlStrlen(curnode->name));
 168                 } else {
 169                         ZVAL_NULL(key);
 170                 }
 171         }
 172 }
 173 /* }}} */
 174 
 175 static void php_dom_iterator_move_forward(zend_object_iterator *iter) /* {{{ */
 176 {
 177         zval *object;
 178         xmlNodePtr curnode = NULL, basenode;
 179         dom_object *intern;
 180         dom_object *nnmap;
 181         dom_nnodemap_object *objmap;
 182         int previndex=0;
 183         HashTable *nodeht;
 184         zval *entry;
 185         zend_bool do_curobj_undef = 1;
 186 
 187         php_dom_iterator *iterator = (php_dom_iterator *)iter;
 188 
 189         object = &iterator->intern.data;
 190         nnmap = Z_DOMOBJ_P(object);
 191         objmap = (dom_nnodemap_object *)nnmap->ptr;
 192 
 193         intern = Z_DOMOBJ_P(&iterator->curobj);
 194 
 195         if (intern != NULL && intern->ptr != NULL) {
 196                 if (objmap->nodetype != XML_ENTITY_NODE &&
 197                         objmap->nodetype != XML_NOTATION_NODE) {
 198                         if (objmap->nodetype == DOM_NODESET) {
 199                                 nodeht = HASH_OF(&objmap->baseobj_zv);
 200                                 zend_hash_move_forward(nodeht);
 201                                 if ((entry = zend_hash_get_current_data(nodeht))) {
 202                                         zval_ptr_dtor(&iterator->curobj);
 203                                         ZVAL_UNDEF(&iterator->curobj);
 204                                         ZVAL_COPY(&iterator->curobj, entry);
 205                                         do_curobj_undef = 0;
 206                                 }
 207                         } else {
 208                                 curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->ptr)->node;
 209                                 if (objmap->nodetype == XML_ATTRIBUTE_NODE ||
 210                                         objmap->nodetype == XML_ELEMENT_NODE) {
 211                                         curnode = curnode->next;
 212                                 } else {
 213                                         /* Nav the tree evey time as this is LIVE */
 214                                         basenode = dom_object_get_node(objmap->baseobj);
 215                                         if (basenode && (basenode->type == XML_DOCUMENT_NODE ||
 216                                                 basenode->type == XML_HTML_DOCUMENT_NODE)) {
 217                                                 basenode = xmlDocGetRootElement((xmlDoc *) basenode);
 218                                         } else if (basenode) {
 219                                                 basenode = basenode->children;
 220                                         } else {
 221                                                 goto err;
 222                                         }
 223                                         curnode = dom_get_elements_by_tag_name_ns_raw(
 224                                                 basenode, (char *) objmap->ns, (char *) objmap->local, &previndex, iter->index);
 225                                 }
 226                         }
 227                 } else {
 228                         if (objmap->nodetype == XML_ENTITY_NODE) {
 229                                 curnode = php_dom_libxml_hash_iter(objmap->ht, iter->index);
 230                         } else {
 231                                 curnode = php_dom_libxml_notation_iter(objmap->ht, iter->index);
 232                         }
 233                 }
 234         }
 235 err:
 236         if (do_curobj_undef) {
 237                 zval_ptr_dtor(&iterator->curobj);
 238                 ZVAL_UNDEF(&iterator->curobj);
 239         }
 240         if (curnode) {
 241                 php_dom_create_object(curnode, &iterator->curobj, objmap->baseobj);
 242         }
 243 }
 244 /* }}} */
 245 
 246 zend_object_iterator_funcs php_dom_iterator_funcs = {
 247         php_dom_iterator_dtor,
 248         php_dom_iterator_valid,
 249         php_dom_iterator_current_data,
 250         php_dom_iterator_current_key,
 251         php_dom_iterator_move_forward,
 252         NULL
 253 };
 254 
 255 zend_object_iterator *php_dom_get_iterator(zend_class_entry *ce, zval *object, int by_ref) /* {{{ */
 256 {
 257         dom_object *intern;
 258         dom_nnodemap_object *objmap;
 259         xmlNodePtr nodep, curnode=NULL;
 260         int curindex = 0;
 261         HashTable *nodeht;
 262         zval *entry;
 263         php_dom_iterator *iterator;
 264 
 265         if (by_ref) {
 266                 zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
 267         }
 268         iterator = emalloc(sizeof(php_dom_iterator));
 269         zend_iterator_init(&iterator->intern);
 270 
 271         ZVAL_COPY(&iterator->intern.data, object);
 272         iterator->intern.funcs = &php_dom_iterator_funcs;
 273 
 274         ZVAL_UNDEF(&iterator->curobj);
 275 
 276         intern = Z_DOMOBJ_P(object);
 277         objmap = (dom_nnodemap_object *)intern->ptr;
 278         if (objmap != NULL) {
 279                 if (objmap->nodetype != XML_ENTITY_NODE &&
 280                         objmap->nodetype != XML_NOTATION_NODE) {
 281                         if (objmap->nodetype == DOM_NODESET) {
 282                                 nodeht = HASH_OF(&objmap->baseobj_zv);
 283                                 zend_hash_internal_pointer_reset(nodeht);
 284                                 if ((entry = zend_hash_get_current_data(nodeht))) {
 285                                         ZVAL_COPY(&iterator->curobj, entry);
 286                                 }
 287                         } else {
 288                                 nodep = (xmlNode *)dom_object_get_node(objmap->baseobj);
 289                                 if (!nodep) {
 290                                         goto err;
 291                                 }
 292                                 if (objmap->nodetype == XML_ATTRIBUTE_NODE || objmap->nodetype == XML_ELEMENT_NODE) {
 293                                         if (objmap->nodetype == XML_ATTRIBUTE_NODE) {
 294                                                 curnode = (xmlNodePtr) nodep->properties;
 295                                         } else {
 296                                                 curnode = (xmlNodePtr) nodep->children;
 297                                         }
 298                                 } else {
 299                                         if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) {
 300                                                 nodep = xmlDocGetRootElement((xmlDoc *) nodep);
 301                                         } else {
 302                                                 nodep = nodep->children;
 303                                         }
 304                                         curnode = dom_get_elements_by_tag_name_ns_raw(
 305                                                 nodep, (char *) objmap->ns, (char *) objmap->local, &curindex, 0);
 306                                 }
 307                         }
 308                 } else {
 309                         if (objmap->nodetype == XML_ENTITY_NODE) {
 310                                 curnode = php_dom_libxml_hash_iter(objmap->ht, 0);
 311                         } else {
 312                                 curnode = php_dom_libxml_notation_iter(objmap->ht, 0);
 313                         }
 314                 }
 315         }
 316 err:
 317         if (curnode) {
 318                 php_dom_create_object(curnode, &iterator->curobj, objmap->baseobj);
 319         }
 320 
 321         return &iterator->intern;
 322 }
 323 /* }}} */
 324 
 325 #endif
 326 
 327 /*
 328  * Local variables:
 329  * tab-width: 4
 330  * c-basic-offset: 4
 331  * End:
 332  * vim600: noet sw=4 ts=4 fdm=marker
 333  * vim<600: noet sw=4 ts=4
 334  */

/* [<][>][^][v][top][bottom][index][help] */