![]() ![]() | ![]() |
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
1.1.1.3 ! misho 5: | Copyright (c) 1997-2013 The PHP Group |
1.1 misho 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:
1.1.1.2 misho 20: /* $Id$ */
1.1 misho 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);
1.1.1.2 misho 254: curattr = php_dom_create_object(curnode, &ret, curattr, objmap->baseobj TSRMLS_CC);
1.1 misho 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);
1.1.1.2 misho 333: curattr = php_dom_create_object(curnode, &ret, curattr, objmap->baseobj TSRMLS_CC);
1.1 misho 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: */