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