Return to dom_iterators.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / dom |
1.1 ! misho 1: /* ! 2: +----------------------------------------------------------------------+ ! 3: | PHP Version 5 | ! 4: +----------------------------------------------------------------------+ ! 5: | Copyright (c) 1997-2012 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: dom_iterators.c 321634 2012-01-01 13:15:04Z felipe $ */ ! 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 TSRMLS_DC) /* {{{ */ ! 126: { ! 127: php_dom_iterator *iterator = (php_dom_iterator *)iter; ! 128: ! 129: zval_ptr_dtor((zval**)&iterator->intern.data); ! 130: ! 131: if (iterator->curobj) { ! 132: zval_ptr_dtor((zval**)&iterator->curobj); ! 133: } ! 134: ! 135: efree(iterator); ! 136: } ! 137: /* }}} */ ! 138: ! 139: static int php_dom_iterator_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ ! 140: { ! 141: ! 142: php_dom_iterator *iterator = (php_dom_iterator *)iter; ! 143: ! 144: if (iterator->curobj) { ! 145: return SUCCESS; ! 146: } else { ! 147: return FAILURE; ! 148: } ! 149: } ! 150: /* }}} */ ! 151: ! 152: static void php_dom_iterator_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */ ! 153: { ! 154: php_dom_iterator *iterator = (php_dom_iterator *)iter; ! 155: ! 156: *data = &iterator->curobj; ! 157: } ! 158: /* }}} */ ! 159: ! 160: static int php_dom_iterator_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */ ! 161: { ! 162: zval *curobj; ! 163: xmlNodePtr curnode = NULL; ! 164: dom_object *intern; ! 165: zval *object; ! 166: int namelen; ! 167: ! 168: php_dom_iterator *iterator = (php_dom_iterator *)iter; ! 169: ! 170: object = (zval *)iterator->intern.data; ! 171: ! 172: if (instanceof_function(Z_OBJCE_P(object), dom_nodelist_class_entry TSRMLS_CC)) { ! 173: *int_key = iter->index; ! 174: return HASH_KEY_IS_LONG; ! 175: } else { ! 176: curobj = iterator->curobj; ! 177: ! 178: intern = (dom_object *)zend_object_store_get_object(curobj TSRMLS_CC); ! 179: if (intern != NULL && intern->ptr != NULL) { ! 180: curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->ptr)->node; ! 181: } else { ! 182: return HASH_KEY_NON_EXISTANT; ! 183: } ! 184: ! 185: namelen = xmlStrlen(curnode->name); ! 186: *str_key = estrndup(curnode->name, namelen); ! 187: *str_key_len = namelen + 1; ! 188: return HASH_KEY_IS_STRING; ! 189: } ! 190: } ! 191: /* }}} */ ! 192: ! 193: static void php_dom_iterator_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ ! 194: { ! 195: zval *curobj, *curattr = NULL; ! 196: zval *object; ! 197: xmlNodePtr curnode = NULL, basenode; ! 198: dom_object *intern; ! 199: dom_object *nnmap; ! 200: dom_nnodemap_object *objmap; ! 201: int ret, previndex=0; ! 202: HashTable *nodeht; ! 203: zval **entry; ! 204: ! 205: php_dom_iterator *iterator = (php_dom_iterator *)iter; ! 206: ! 207: object = (zval *)iterator->intern.data; ! 208: nnmap = (dom_object *)zend_object_store_get_object(object TSRMLS_CC); ! 209: objmap = (dom_nnodemap_object *)nnmap->ptr; ! 210: ! 211: curobj = iterator->curobj; ! 212: intern = (dom_object *)zend_object_store_get_object(curobj TSRMLS_CC); ! 213: if (intern != NULL && intern->ptr != NULL) { ! 214: if (objmap->nodetype != XML_ENTITY_NODE && ! 215: objmap->nodetype != XML_NOTATION_NODE) { ! 216: if (objmap->nodetype == DOM_NODESET) { ! 217: nodeht = HASH_OF(objmap->baseobjptr); ! 218: zend_hash_move_forward(nodeht); ! 219: if (zend_hash_get_current_data(nodeht, (void **) &entry)==SUCCESS) { ! 220: curattr = *entry; ! 221: Z_ADDREF_P(curattr); ! 222: } ! 223: } else { ! 224: curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->ptr)->node; ! 225: if (objmap->nodetype == XML_ATTRIBUTE_NODE || ! 226: objmap->nodetype == XML_ELEMENT_NODE) { ! 227: curnode = curnode->next; ! 228: } else { ! 229: /* Nav the tree evey time as this is LIVE */ ! 230: basenode = dom_object_get_node(objmap->baseobj); ! 231: if (basenode && (basenode->type == XML_DOCUMENT_NODE || ! 232: basenode->type == XML_HTML_DOCUMENT_NODE)) { ! 233: basenode = xmlDocGetRootElement((xmlDoc *) basenode); ! 234: } else if (basenode) { ! 235: basenode = basenode->children; ! 236: } else { ! 237: goto err; ! 238: } ! 239: curnode = dom_get_elements_by_tag_name_ns_raw(basenode, objmap->ns, objmap->local, &previndex, iter->index); ! 240: } ! 241: } ! 242: } else { ! 243: if (objmap->nodetype == XML_ENTITY_NODE) { ! 244: curnode = php_dom_libxml_hash_iter(objmap->ht, iter->index); ! 245: } else { ! 246: curnode = php_dom_libxml_notation_iter(objmap->ht, iter->index); ! 247: } ! 248: } ! 249: } ! 250: err: ! 251: zval_ptr_dtor((zval**)&curobj); ! 252: if (curnode) { ! 253: MAKE_STD_ZVAL(curattr); ! 254: curattr = php_dom_create_object(curnode, &ret, NULL, curattr, objmap->baseobj TSRMLS_CC); ! 255: } ! 256: ! 257: iterator->curobj = curattr; ! 258: } ! 259: /* }}} */ ! 260: ! 261: zend_object_iterator_funcs php_dom_iterator_funcs = { ! 262: php_dom_iterator_dtor, ! 263: php_dom_iterator_valid, ! 264: php_dom_iterator_current_data, ! 265: php_dom_iterator_current_key, ! 266: php_dom_iterator_move_forward, ! 267: NULL ! 268: }; ! 269: ! 270: zend_object_iterator *php_dom_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */ ! 271: { ! 272: dom_object *intern; ! 273: dom_nnodemap_object *objmap; ! 274: xmlNodePtr nodep, curnode=NULL; ! 275: zval *curattr = NULL; ! 276: int ret, curindex = 0; ! 277: HashTable *nodeht; ! 278: zval **entry; ! 279: php_dom_iterator *iterator; ! 280: ! 281: if (by_ref) { ! 282: zend_error(E_ERROR, "An iterator cannot be used with foreach by reference"); ! 283: } ! 284: iterator = emalloc(sizeof(php_dom_iterator)); ! 285: ! 286: Z_ADDREF_P(object); ! 287: iterator->intern.data = (void*)object; ! 288: iterator->intern.funcs = &php_dom_iterator_funcs; ! 289: ! 290: intern = (dom_object *)zend_object_store_get_object(object TSRMLS_CC); ! 291: objmap = (dom_nnodemap_object *)intern->ptr; ! 292: if (objmap != NULL) { ! 293: if (objmap->nodetype != XML_ENTITY_NODE && ! 294: objmap->nodetype != XML_NOTATION_NODE) { ! 295: if (objmap->nodetype == DOM_NODESET) { ! 296: nodeht = HASH_OF(objmap->baseobjptr); ! 297: zend_hash_internal_pointer_reset(nodeht); ! 298: if (zend_hash_get_current_data(nodeht, (void **) &entry)==SUCCESS) { ! 299: curattr = *entry; ! 300: Z_ADDREF_P(curattr); ! 301: } ! 302: } else { ! 303: nodep = (xmlNode *)dom_object_get_node(objmap->baseobj); ! 304: if (!nodep) { ! 305: goto err; ! 306: } ! 307: if (objmap->nodetype == XML_ATTRIBUTE_NODE || objmap->nodetype == XML_ELEMENT_NODE) { ! 308: if (objmap->nodetype == XML_ATTRIBUTE_NODE) { ! 309: curnode = (xmlNodePtr) nodep->properties; ! 310: } else { ! 311: curnode = (xmlNodePtr) nodep->children; ! 312: } ! 313: } else { ! 314: if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) { ! 315: nodep = xmlDocGetRootElement((xmlDoc *) nodep); ! 316: } else { ! 317: nodep = nodep->children; ! 318: } ! 319: curnode = dom_get_elements_by_tag_name_ns_raw(nodep, objmap->ns, objmap->local, &curindex, 0); ! 320: } ! 321: } ! 322: } else { ! 323: if (objmap->nodetype == XML_ENTITY_NODE) { ! 324: curnode = php_dom_libxml_hash_iter(objmap->ht, 0); ! 325: } else { ! 326: curnode = php_dom_libxml_notation_iter(objmap->ht, 0); ! 327: } ! 328: } ! 329: } ! 330: err: ! 331: if (curnode) { ! 332: MAKE_STD_ZVAL(curattr); ! 333: curattr = php_dom_create_object(curnode, &ret, NULL, curattr, objmap->baseobj TSRMLS_CC); ! 334: } ! 335: ! 336: iterator->curobj = curattr; ! 337: ! 338: return (zend_object_iterator*)iterator; ! 339: } ! 340: /* }}} */ ! 341: ! 342: #endif ! 343: ! 344: /* ! 345: * Local variables: ! 346: * tab-width: 4 ! 347: * c-basic-offset: 4 ! 348: * End: ! 349: * vim600: noet sw=4 ts=4 fdm=marker ! 350: * vim<600: noet sw=4 ts=4 ! 351: */