1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 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 272370 2008-12-31 11:15:49Z sebastian $ */
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 24 : {
47 24 : nodeIterator *priv = (nodeIterator *)data;
48 :
49 24 : if(priv->cur < priv->index) {
50 6 : priv->cur++;
51 : } else {
52 18 : if(priv->node == NULL) {
53 12 : priv->node = (xmlNode *)payload;
54 : }
55 : }
56 24 : }
57 : /* }}} */
58 :
59 : xmlNodePtr create_notation(const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID) /* {{{ */
60 5 : {
61 : xmlEntityPtr ret;
62 :
63 5 : ret = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
64 5 : memset(ret, 0, sizeof(xmlEntity));
65 5 : ret->type = XML_NOTATION_NODE;
66 5 : ret->name = xmlStrdup(name);
67 5 : ret->ExternalID = xmlStrdup(ExternalID);
68 5 : ret->SystemID = xmlStrdup(SystemID);
69 5 : ret->length = 0;
70 5 : ret->content = NULL;
71 5 : ret->URI = NULL;
72 5 : ret->orig = NULL;
73 5 : ret->children = NULL;
74 5 : ret->parent = NULL;
75 5 : ret->doc = NULL;
76 5 : ret->_private = NULL;
77 5 : ret->last = NULL;
78 5 : ret->prev = NULL;
79 5 : return((xmlNodePtr) ret);
80 : }
81 : /* }}} */
82 :
83 : xmlNode *php_dom_libxml_hash_iter(xmlHashTable *ht, int index) /* {{{ */
84 9 : {
85 9 : xmlNode *nodep = NULL;
86 : nodeIterator *iter;
87 : int htsize;
88 :
89 9 : if ((htsize = xmlHashSize(ht)) > 0 && index < htsize) {
90 7 : iter = emalloc(sizeof(nodeIterator));
91 7 : iter->cur = 0;
92 7 : iter->index = index;
93 7 : iter->node = NULL;
94 7 : xmlHashScan(ht, itemHashScanner, iter);
95 7 : nodep = iter->node;
96 7 : efree(iter);
97 7 : return nodep;
98 : } else {
99 2 : return NULL;
100 : }
101 : }
102 : /* }}} */
103 :
104 : xmlNode *php_dom_libxml_notation_iter(xmlHashTable *ht, int index) /* {{{ */
105 6 : {
106 : notationIterator *iter;
107 6 : xmlNotation *notep = NULL;
108 : int htsize;
109 :
110 6 : if ((htsize = xmlHashSize(ht)) > 0 && index < htsize) {
111 5 : iter = emalloc(sizeof(notationIterator));
112 5 : iter->cur = 0;
113 5 : iter->index = index;
114 5 : iter->notation = NULL;
115 5 : xmlHashScan(ht, itemHashScanner, iter);
116 5 : notep = iter->notation;
117 5 : efree(iter);
118 5 : return create_notation(notep->name, notep->PublicID, notep->SystemID);
119 : } else {
120 1 : return NULL;
121 : }
122 : }
123 : /* }}} */
124 :
125 : static void php_dom_iterator_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
126 74 : {
127 74 : php_dom_iterator *iterator = (php_dom_iterator *)iter;
128 :
129 74 : zval_ptr_dtor((zval**)&iterator->intern.data);
130 :
131 74 : if (iterator->curobj) {
132 0 : zval_ptr_dtor((zval**)&iterator->curobj);
133 : }
134 :
135 74 : efree(iterator);
136 74 : }
137 : /* }}} */
138 :
139 : static int php_dom_iterator_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
140 209 : {
141 :
142 209 : php_dom_iterator *iterator = (php_dom_iterator *)iter;
143 :
144 209 : if (iterator->curobj) {
145 135 : return SUCCESS;
146 : } else {
147 74 : return FAILURE;
148 : }
149 : }
150 : /* }}} */
151 :
152 : static void php_dom_iterator_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */
153 135 : {
154 135 : php_dom_iterator *iterator = (php_dom_iterator *)iter;
155 :
156 135 : *data = &iterator->curobj;
157 135 : }
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 4 : {
162 : zval *curobj;
163 4 : xmlNodePtr curnode = NULL;
164 : dom_object *intern;
165 : zval *object;
166 : int namelen;
167 :
168 4 : php_dom_iterator *iterator = (php_dom_iterator *)iter;
169 :
170 4 : object = (zval *)iterator->intern.data;
171 :
172 4 : if (instanceof_function(Z_OBJCE_P(object), dom_nodelist_class_entry TSRMLS_CC)) {
173 0 : *int_key = iter->index;
174 0 : return HASH_KEY_IS_LONG;
175 : } else {
176 4 : curobj = iterator->curobj;
177 :
178 4 : intern = (dom_object *)zend_object_store_get_object(curobj TSRMLS_CC);
179 4 : if (intern != NULL && intern->ptr != NULL) {
180 4 : curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->ptr)->node;
181 : } else {
182 0 : return HASH_KEY_NON_EXISTANT;
183 : }
184 :
185 4 : namelen = xmlStrlen(curnode->name);
186 4 : *str_key = estrndup(curnode->name, namelen);
187 4 : *str_key_len = namelen + 1;
188 4 : return HASH_KEY_IS_STRING;
189 : }
190 : }
191 : /* }}} */
192 :
193 : static void php_dom_iterator_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
194 135 : {
195 135 : zval *curobj, *curattr = NULL;
196 : zval *object;
197 135 : xmlNodePtr curnode = NULL, basenode;
198 : dom_object *intern;
199 : dom_object *nnmap;
200 : dom_nnodemap_object *objmap;
201 135 : int ret, previndex=0;
202 : HashTable *nodeht;
203 : zval **entry;
204 :
205 135 : php_dom_iterator *iterator = (php_dom_iterator *)iter;
206 :
207 135 : object = (zval *)iterator->intern.data;
208 135 : nnmap = (dom_object *)zend_object_store_get_object(object TSRMLS_CC);
209 135 : objmap = (dom_nnodemap_object *)nnmap->ptr;
210 :
211 135 : curobj = iterator->curobj;
212 135 : intern = (dom_object *)zend_object_store_get_object(curobj TSRMLS_CC);
213 135 : if (intern != NULL && intern->ptr != NULL) {
214 266 : if (objmap->nodetype != XML_ENTITY_NODE &&
215 : objmap->nodetype != XML_NOTATION_NODE) {
216 131 : if (objmap->nodetype == DOM_NODESET) {
217 0 : nodeht = HASH_OF(objmap->baseobjptr);
218 0 : zend_hash_move_forward(nodeht);
219 0 : if (zend_hash_get_current_data(nodeht, (void **) &entry)==SUCCESS) {
220 0 : curattr = *entry;
221 0 : Z_ADDREF_P(curattr);
222 : }
223 : } else {
224 131 : curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->ptr)->node;
225 246 : if (objmap->nodetype == XML_ATTRIBUTE_NODE ||
226 : objmap->nodetype == XML_ELEMENT_NODE) {
227 115 : curnode = curnode->next;
228 : } else {
229 : /* Nav the tree evey time as this is LIVE */
230 16 : basenode = dom_object_get_node(objmap->baseobj);
231 25 : if (basenode && (basenode->type == XML_DOCUMENT_NODE ||
232 : basenode->type == XML_HTML_DOCUMENT_NODE)) {
233 9 : basenode = xmlDocGetRootElement((xmlDoc *) basenode);
234 7 : } else if (basenode) {
235 7 : basenode = basenode->children;
236 : } else {
237 0 : goto err;
238 : }
239 16 : curnode = dom_get_elements_by_tag_name_ns_raw(basenode, objmap->ns, objmap->local, &previndex, iter->index);
240 : }
241 : }
242 : } else {
243 4 : if (objmap->nodetype == XML_ENTITY_NODE) {
244 3 : curnode = php_dom_libxml_hash_iter(objmap->ht, iter->index);
245 : } else {
246 1 : curnode = php_dom_libxml_notation_iter(objmap->ht, iter->index);
247 : }
248 : }
249 : }
250 135 : err:
251 135 : zval_ptr_dtor((zval**)&curobj);
252 135 : if (curnode) {
253 73 : MAKE_STD_ZVAL(curattr);
254 73 : curattr = php_dom_create_object(curnode, &ret, NULL, curattr, objmap->baseobj TSRMLS_CC);
255 : }
256 :
257 135 : iterator->curobj = curattr;
258 135 : }
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 74 : {
272 : dom_object *intern;
273 : dom_nnodemap_object *objmap;
274 74 : xmlNodePtr nodep, curnode=NULL;
275 74 : zval *curattr = NULL;
276 74 : int ret, curindex = 0;
277 : HashTable *nodeht;
278 : zval **entry;
279 : php_dom_iterator *iterator;
280 :
281 74 : if (by_ref) {
282 0 : zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
283 : }
284 74 : iterator = emalloc(sizeof(php_dom_iterator));
285 :
286 74 : Z_ADDREF_P(object);
287 74 : iterator->intern.data = (void*)object;
288 74 : iterator->intern.funcs = &php_dom_iterator_funcs;
289 :
290 74 : intern = (dom_object *)zend_object_store_get_object(object TSRMLS_CC);
291 74 : objmap = (dom_nnodemap_object *)intern->ptr;
292 74 : if (objmap != NULL) {
293 146 : if (objmap->nodetype != XML_ENTITY_NODE &&
294 : objmap->nodetype != XML_NOTATION_NODE) {
295 72 : if (objmap->nodetype == DOM_NODESET) {
296 0 : nodeht = HASH_OF(objmap->baseobjptr);
297 0 : zend_hash_internal_pointer_reset(nodeht);
298 0 : if (zend_hash_get_current_data(nodeht, (void **) &entry)==SUCCESS) {
299 0 : curattr = *entry;
300 0 : Z_ADDREF_P(curattr);
301 : }
302 : } else {
303 72 : nodep = (xmlNode *)dom_object_get_node(objmap->baseobj);
304 72 : if (!nodep) {
305 0 : goto err;
306 : }
307 137 : if (objmap->nodetype == XML_ATTRIBUTE_NODE || objmap->nodetype == XML_ELEMENT_NODE) {
308 65 : if (objmap->nodetype == XML_ATTRIBUTE_NODE) {
309 2 : curnode = (xmlNodePtr) nodep->properties;
310 : } else {
311 63 : curnode = (xmlNodePtr) nodep->children;
312 : }
313 : } else {
314 11 : if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) {
315 4 : nodep = xmlDocGetRootElement((xmlDoc *) nodep);
316 : } else {
317 3 : nodep = nodep->children;
318 : }
319 7 : curnode = dom_get_elements_by_tag_name_ns_raw(nodep, objmap->ns, objmap->local, &curindex, 0);
320 : }
321 : }
322 : } else {
323 2 : if (objmap->nodetype == XML_ENTITY_NODE) {
324 1 : curnode = php_dom_libxml_hash_iter(objmap->ht, 0);
325 : } else {
326 1 : curnode = php_dom_libxml_notation_iter(objmap->ht, 0);
327 : }
328 : }
329 : }
330 74 : err:
331 74 : if (curnode) {
332 62 : MAKE_STD_ZVAL(curattr);
333 62 : curattr = php_dom_create_object(curnode, &ret, NULL, curattr, objmap->baseobj TSRMLS_CC);
334 : }
335 :
336 74 : iterator->curobj = curattr;
337 :
338 74 : 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 : */
|