1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 The PHP Group |
6 : +----------------------------------------------------------------------+
7 : | This source file is SplSubject 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: Marcus Boerger <helly@php.net> |
16 : | Etienne Kneuss <colder@php.net> |
17 : +----------------------------------------------------------------------+
18 : */
19 :
20 : /* $Id: spl_observer.c 289250 2009-10-06 13:34:56Z colder $ */
21 :
22 : #ifdef HAVE_CONFIG_H
23 : # include "config.h"
24 : #endif
25 :
26 : #include "php.h"
27 : #include "php_ini.h"
28 : #include "ext/standard/info.h"
29 : #include "ext/standard/php_var.h"
30 : #include "ext/standard/php_smart_str.h"
31 : #include "zend_interfaces.h"
32 : #include "zend_exceptions.h"
33 :
34 : #include "php_spl.h"
35 : #include "spl_functions.h"
36 : #include "spl_engine.h"
37 : #include "spl_observer.h"
38 : #include "spl_iterators.h"
39 : #include "spl_array.h"
40 : #include "spl_exceptions.h"
41 :
42 : SPL_METHOD(SplObserver, update);
43 : SPL_METHOD(SplSubject, attach);
44 : SPL_METHOD(SplSubject, detach);
45 : SPL_METHOD(SplSubject, notify);
46 :
47 : ZEND_BEGIN_ARG_INFO(arginfo_SplObserver_update, 0)
48 : ZEND_ARG_OBJ_INFO(0, SplSubject, SplSubject, 0)
49 : ZEND_END_ARG_INFO();
50 :
51 : static const zend_function_entry spl_funcs_SplObserver[] = {
52 : SPL_ABSTRACT_ME(SplObserver, update, arginfo_SplObserver_update)
53 : {NULL, NULL, NULL}
54 : };
55 :
56 : ZEND_BEGIN_ARG_INFO(arginfo_SplSubject_attach, 0)
57 : ZEND_ARG_OBJ_INFO(0, SplObserver, SplObserver, 0)
58 : ZEND_END_ARG_INFO();
59 :
60 : ZEND_BEGIN_ARG_INFO(arginfo_SplSubject_void, 0)
61 : ZEND_END_ARG_INFO();
62 :
63 : /*ZEND_BEGIN_ARG_INFO_EX(arginfo_SplSubject_notify, 0, 0, 1)
64 : ZEND_ARG_OBJ_INFO(0, ignore, SplObserver, 1)
65 : ZEND_END_ARG_INFO();*/
66 :
67 : static const zend_function_entry spl_funcs_SplSubject[] = {
68 : SPL_ABSTRACT_ME(SplSubject, attach, arginfo_SplSubject_attach)
69 : SPL_ABSTRACT_ME(SplSubject, detach, arginfo_SplSubject_attach)
70 : SPL_ABSTRACT_ME(SplSubject, notify, arginfo_SplSubject_void)
71 : {NULL, NULL, NULL}
72 : };
73 :
74 : PHPAPI zend_class_entry *spl_ce_SplObserver;
75 : PHPAPI zend_class_entry *spl_ce_SplSubject;
76 : PHPAPI zend_class_entry *spl_ce_SplObjectStorage;
77 : PHPAPI zend_class_entry *spl_ce_MultipleIterator;
78 :
79 : PHPAPI zend_object_handlers spl_handler_SplObjectStorage;
80 :
81 : typedef struct _spl_SplObjectStorage { /* {{{ */
82 : zend_object std;
83 : HashTable storage;
84 : long index;
85 : HashPosition pos;
86 : long flags;
87 : HashTable *debug_info;
88 : } spl_SplObjectStorage; /* }}} */
89 :
90 : /* {{{ storage is an assoc aray of [zend_object_value]=>[zval *obj, zval *inf] */
91 : typedef struct _spl_SplObjectStorageElement {
92 : zval* obj;
93 : zval* inf;
94 : } spl_SplObjectStorageElement; /* }}} */
95 :
96 : void spl_SplOjectStorage_free_storage(void *object TSRMLS_DC) /* {{{ */
97 67 : {
98 67 : spl_SplObjectStorage *intern = (spl_SplObjectStorage *)object;
99 :
100 67 : zend_object_std_dtor(&intern->std TSRMLS_CC);
101 :
102 67 : zend_hash_destroy(&intern->storage);
103 :
104 67 : if (intern->debug_info != NULL) {
105 11 : zend_hash_destroy(intern->debug_info);
106 11 : efree(intern->debug_info);
107 : }
108 :
109 67 : efree(object);
110 67 : } /* }}} */
111 :
112 : static void spl_object_storage_dtor(spl_SplObjectStorageElement *element) /* {{{ */
113 65 : {
114 65 : zval_ptr_dtor(&element->obj);
115 65 : zval_ptr_dtor(&element->inf);
116 65 : } /* }}} */
117 :
118 : spl_SplObjectStorageElement* spl_object_storage_get(spl_SplObjectStorage *intern, zval *obj TSRMLS_DC) /* {{{ */
119 74 : {
120 : spl_SplObjectStorageElement *element;
121 : zend_object_value *pzvalue;
122 : #if HAVE_PACKED_OBJECT_VALUE
123 74 : pzvalue = &Z_OBJVAL_P(obj);
124 : #else
125 : zend_object_value zvalue;
126 : memset(&zvalue, 0, sizeof(zend_object_value));
127 : zvalue.handle = Z_OBJ_HANDLE_P(obj);
128 : zvalue.handlers = Z_OBJ_HT_P(obj);
129 : pzvalue = &zvalue;
130 : #endif
131 74 : if (zend_hash_find(&intern->storage, (char*)pzvalue, sizeof(zend_object_value), (void**)&element) == SUCCESS) {
132 8 : return element;
133 : } else {
134 66 : return NULL;
135 : }
136 : } /* }}} */
137 :
138 : void spl_object_storage_attach(spl_SplObjectStorage *intern, zval *obj, zval *inf TSRMLS_DC) /* {{{ */
139 72 : {
140 : spl_SplObjectStorageElement *pelement, element;
141 72 : pelement = spl_object_storage_get(intern, obj TSRMLS_CC);
142 72 : if (inf) {
143 50 : Z_ADDREF_P(inf);
144 : } else {
145 22 : ALLOC_INIT_ZVAL(inf);
146 : }
147 72 : if (pelement) {
148 7 : zval_ptr_dtor(&pelement->inf);
149 7 : pelement->inf = inf;
150 7 : return;
151 : }
152 65 : Z_ADDREF_P(obj);
153 65 : element.obj = obj;
154 65 : element.inf = inf;
155 : #if HAVE_PACKED_OBJECT_VALUE
156 65 : zend_hash_update(&intern->storage, (char*)&Z_OBJVAL_P(obj), sizeof(zend_object_value), &element, sizeof(spl_SplObjectStorageElement), NULL);
157 : #else
158 : {
159 : zend_object_value zvalue;
160 : memset(&zvalue, 0, sizeof(zend_object_value));
161 : zvalue.handle = Z_OBJ_HANDLE_P(obj);
162 : zvalue.handlers = Z_OBJ_HT_P(obj);
163 : zend_hash_update(&intern->storage, (char*)&zvalue, sizeof(zend_object_value), &element, sizeof(spl_SplObjectStorageElement), NULL);
164 : }
165 : #endif
166 : } /* }}} */
167 :
168 : void spl_object_storage_detach(spl_SplObjectStorage *intern, zval *obj TSRMLS_DC) /* {{{ */
169 7 : {
170 : #if HAVE_PACKED_OBJECT_VALUE
171 7 : zend_hash_del(&intern->storage, (char*)&Z_OBJVAL_P(obj), sizeof(zend_object_value));
172 : #else
173 : {
174 : zend_object_value zvalue;
175 : memset(&zvalue, 0, sizeof(zend_object_value));
176 : zvalue.handle = Z_OBJ_HANDLE_P(obj);
177 : zvalue.handlers = Z_OBJ_HT_P(obj);
178 : zend_hash_del(&intern->storage, (char*)&zvalue, sizeof(zend_object_value));
179 : }
180 : #endif
181 7 : } /* }}}*/
182 :
183 2 : void spl_object_storage_addall(spl_SplObjectStorage *intern, spl_SplObjectStorage *other TSRMLS_DC) { /* {{{ */
184 : HashPosition pos;
185 : spl_SplObjectStorageElement *element;
186 :
187 2 : zend_hash_internal_pointer_reset_ex(&other->storage, &pos);
188 8 : while (zend_hash_get_current_data_ex(&other->storage, (void **)&element, &pos) == SUCCESS) {
189 4 : spl_object_storage_attach(intern, element->obj, element->inf TSRMLS_CC);
190 4 : zend_hash_move_forward_ex(&other->storage, &pos);
191 : }
192 :
193 2 : zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
194 2 : intern->index = 0;
195 2 : } /* }}} */
196 :
197 : static zend_object_value spl_object_storage_new_ex(zend_class_entry *class_type, spl_SplObjectStorage **obj, zval *orig TSRMLS_DC) /* {{{ */
198 67 : {
199 : zend_object_value retval;
200 : spl_SplObjectStorage *intern;
201 : zval *tmp;
202 :
203 67 : intern = emalloc(sizeof(spl_SplObjectStorage));
204 67 : memset(intern, 0, sizeof(spl_SplObjectStorage));
205 67 : *obj = intern;
206 :
207 67 : zend_object_std_init(&intern->std, class_type TSRMLS_CC);
208 67 : zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
209 :
210 67 : zend_hash_init(&intern->storage, 0, NULL, (void (*)(void *))spl_object_storage_dtor, 0);
211 :
212 67 : retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_SplOjectStorage_free_storage, NULL TSRMLS_CC);
213 67 : retval.handlers = &spl_handler_SplObjectStorage;
214 :
215 67 : if (orig) {
216 1 : spl_SplObjectStorage *other = (spl_SplObjectStorage*)zend_object_store_get_object(orig TSRMLS_CC);
217 1 : spl_object_storage_addall(intern, other TSRMLS_CC);
218 : }
219 :
220 67 : return retval;
221 : }
222 : /* }}} */
223 :
224 : /* {{{ spl_object_storage_clone */
225 : static zend_object_value spl_object_storage_clone(zval *zobject TSRMLS_DC)
226 1 : {
227 : zend_object_value new_obj_val;
228 : zend_object *old_object;
229 : zend_object *new_object;
230 1 : zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
231 : spl_SplObjectStorage *intern;
232 :
233 1 : old_object = zend_objects_get_address(zobject TSRMLS_CC);
234 1 : new_obj_val = spl_object_storage_new_ex(old_object->ce, &intern, zobject TSRMLS_CC);
235 1 : new_object = &intern->std;
236 :
237 1 : zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC);
238 :
239 1 : return new_obj_val;
240 : }
241 : /* }}} */
242 :
243 : static HashTable* spl_object_storage_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{ */
244 13 : {
245 13 : spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(obj TSRMLS_CC);
246 : spl_SplObjectStorageElement *element;
247 : HashTable *props;
248 : HashPosition pos;
249 : zval *tmp, *storage;
250 : char md5str[33];
251 : int name_len;
252 : char *zname;
253 :
254 13 : *is_temp = 0;
255 :
256 13 : props = Z_OBJPROP_P(obj);
257 13 : if (intern->debug_info == NULL) {
258 11 : ALLOC_HASHTABLE(intern->debug_info);
259 11 : ZEND_INIT_SYMTABLE_EX(intern->debug_info, zend_hash_num_elements(props) + 1, 0);
260 : }
261 :
262 13 : if (intern->debug_info->nApplyCount == 0) {
263 11 : zend_hash_copy(intern->debug_info, props, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
264 :
265 11 : MAKE_STD_ZVAL(storage);
266 11 : array_init(storage);
267 :
268 11 : zend_hash_internal_pointer_reset_ex(&intern->storage, &pos);
269 49 : while (zend_hash_get_current_data_ex(&intern->storage, (void **)&element, &pos) == SUCCESS) {
270 27 : php_spl_object_hash(element->obj, md5str TSRMLS_CC);
271 27 : Z_ADDREF_P(element->obj);
272 27 : Z_ADDREF_P(element->inf);
273 27 : MAKE_STD_ZVAL(tmp);
274 27 : array_init(tmp);
275 27 : add_assoc_zval_ex(tmp, "obj", sizeof("obj"), element->obj);
276 27 : add_assoc_zval_ex(tmp, "inf", sizeof("inf"), element->inf);
277 27 : add_assoc_zval_ex(storage, md5str, 33, tmp);
278 27 : zend_hash_move_forward_ex(&intern->storage, &pos);
279 : }
280 :
281 11 : zname = spl_gen_private_prop_name(spl_ce_SplObjectStorage, "storage", sizeof("storage")-1, &name_len TSRMLS_CC);
282 11 : zend_symtable_update(intern->debug_info, zname, name_len+1, &storage, sizeof(zval *), NULL);
283 11 : efree(zname);
284 : }
285 :
286 13 : return intern->debug_info;
287 : }
288 : /* }}} */
289 :
290 : static int spl_object_storage_compare_info(spl_SplObjectStorageElement *e1, spl_SplObjectStorageElement *e2 TSRMLS_DC) /* {{{ */
291 2 : {
292 : zval result;
293 :
294 2 : if (compare_function(&result, e1->inf, e2->inf TSRMLS_CC) == FAILURE) {
295 0 : return 1;
296 : }
297 :
298 2 : return Z_LVAL(result);
299 : }
300 : /* }}} */
301 :
302 : static int spl_object_storage_compare_objects(zval *o1, zval *o2 TSRMLS_DC) /* {{{ */
303 4 : {
304 4 : zend_object *zo1 = (zend_object *)zend_object_store_get_object(o1 TSRMLS_CC);
305 4 : zend_object *zo2 = (zend_object *)zend_object_store_get_object(o2 TSRMLS_CC);
306 :
307 4 : if (zo1->ce != spl_ce_SplObjectStorage || zo2->ce != spl_ce_SplObjectStorage) {
308 0 : return 1;
309 : }
310 :
311 4 : return zend_hash_compare(&((spl_SplObjectStorage *)zo1)->storage, &((spl_SplObjectStorage *)zo2)->storage, (compare_func_t) spl_object_storage_compare_info, 0 TSRMLS_CC);
312 : }
313 : /* }}} */
314 :
315 : /* {{{ spl_array_object_new */
316 : static zend_object_value spl_SplObjectStorage_new(zend_class_entry *class_type TSRMLS_DC)
317 66 : {
318 : spl_SplObjectStorage *tmp;
319 66 : return spl_object_storage_new_ex(class_type, &tmp, NULL TSRMLS_CC);
320 : }
321 : /* }}} */
322 :
323 : int spl_object_storage_contains(spl_SplObjectStorage *intern, zval *obj TSRMLS_DC) /* {{{ */
324 4 : {
325 : #if HAVE_PACKED_OBJECT_VALUE
326 4 : return zend_hash_exists(&intern->storage, (char*)&Z_OBJVAL_P(obj), sizeof(zend_object_value));
327 : #else
328 : {
329 : zend_object_value zvalue;
330 : memset(&zvalue, 0, sizeof(zend_object_value));
331 : zvalue.handle = Z_OBJ_HANDLE_P(obj);
332 : zvalue.handlers = Z_OBJ_HT_P(obj);
333 : return zend_hash_exists(&intern->storage, (char*)&zvalue, sizeof(zend_object_value));
334 : }
335 : #endif
336 : } /* }}} */
337 :
338 : /* {{{ proto void SplObjectStorage::attach($obj, $inf = NULL)
339 : Attaches an object to the storage if not yet contained */
340 : SPL_METHOD(SplObjectStorage, attach)
341 39 : {
342 39 : zval *obj, *inf = NULL;
343 :
344 39 : spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
345 :
346 39 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o|z!", &obj, &inf) == FAILURE) {
347 2 : return;
348 : }
349 37 : spl_object_storage_attach(intern, obj, inf TSRMLS_CC);
350 : } /* }}} */
351 :
352 : /* {{{ proto void SplObjectStorage::detach($obj)
353 : Detaches an object from the storage */
354 : SPL_METHOD(SplObjectStorage, detach)
355 11 : {
356 : zval *obj;
357 11 : spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
358 :
359 11 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
360 6 : return;
361 : }
362 5 : spl_object_storage_detach(intern, obj TSRMLS_CC);
363 :
364 5 : zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
365 5 : intern->index = 0;
366 : } /* }}} */
367 :
368 : /* {{{ proto mixed SplObjectStorage::offsetGet($object)
369 : Returns associated information for a stored object */
370 : SPL_METHOD(SplObjectStorage, offsetGet)
371 8 : {
372 : zval *obj;
373 : spl_SplObjectStorageElement *element;
374 8 : spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
375 :
376 8 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
377 6 : return;
378 : }
379 2 : element = spl_object_storage_get(intern, obj TSRMLS_CC);
380 2 : if (!element) {
381 1 : zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Object not found");
382 : } else {
383 1 : RETURN_ZVAL(element->inf,1, 0);
384 : }
385 : } /* }}} */
386 :
387 : /* {{{ proto bool SplObjectStorage::addAll(SplObjectStorage $os)
388 : Add all elements contained in $os */
389 : SPL_METHOD(SplObjectStorage, addAll)
390 7 : {
391 : zval *obj;
392 7 : spl_SplObjectStorage *intern = (spl_SplObjectStorage *)zend_object_store_get_object(getThis() TSRMLS_CC);
393 : spl_SplObjectStorage *other;
394 :
395 7 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &obj, spl_ce_SplObjectStorage) == FAILURE) {
396 6 : return;
397 : }
398 :
399 1 : other = (spl_SplObjectStorage *)zend_object_store_get_object(obj TSRMLS_CC);
400 :
401 1 : spl_object_storage_addall(intern, other TSRMLS_CC);
402 :
403 1 : RETURN_LONG(zend_hash_num_elements(&intern->storage));
404 : } /* }}} */
405 :
406 : /* {{{ proto bool SplObjectStorage::removeAll(SplObjectStorage $os)
407 : Remove all elements contained in $os */
408 : SPL_METHOD(SplObjectStorage, removeAll)
409 7 : {
410 : zval *obj;
411 7 : spl_SplObjectStorage *intern = (spl_SplObjectStorage *)zend_object_store_get_object(getThis() TSRMLS_CC);
412 : spl_SplObjectStorage *other;
413 : spl_SplObjectStorageElement *element;
414 : HashPosition pos;
415 :
416 7 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &obj, spl_ce_SplObjectStorage) == FAILURE) {
417 6 : return;
418 : }
419 :
420 1 : other = (spl_SplObjectStorage *)zend_object_store_get_object(obj TSRMLS_CC);
421 :
422 1 : zend_hash_internal_pointer_reset_ex(&other->storage, &pos);
423 4 : while (zend_hash_get_current_data_ex(&other->storage, (void **)&element, &pos) == SUCCESS) {
424 2 : spl_object_storage_detach(intern, element->obj TSRMLS_CC);
425 2 : zend_hash_move_forward_ex(&other->storage, &pos);
426 : }
427 :
428 1 : zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
429 1 : intern->index = 0;
430 :
431 1 : RETURN_LONG(zend_hash_num_elements(&intern->storage));
432 : } /* }}} */
433 :
434 : /* {{{ proto bool SplObjectStorage::contains($obj)
435 : Determine whethe an object is contained in the storage */
436 : SPL_METHOD(SplObjectStorage, contains)
437 10 : {
438 : zval *obj;
439 10 : spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
440 :
441 10 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
442 6 : return;
443 : }
444 4 : RETURN_BOOL(spl_object_storage_contains(intern, obj TSRMLS_CC));
445 : } /* }}} */
446 :
447 : /* {{{ proto int SplObjectStorage::count()
448 : Determine number of objects in storage */
449 : SPL_METHOD(SplObjectStorage, count)
450 19 : {
451 19 : spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
452 :
453 19 : RETURN_LONG(zend_hash_num_elements(&intern->storage));
454 : } /* }}} */
455 :
456 : /* {{{ proto void SplObjectStorage::rewind()
457 : Rewind to first position */
458 : SPL_METHOD(SplObjectStorage, rewind)
459 16 : {
460 16 : spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
461 :
462 16 : zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
463 16 : intern->index = 0;
464 16 : } /* }}} */
465 :
466 : /* {{{ proto bool SplObjectStorage::valid()
467 : Returns whether current position is valid */
468 : SPL_METHOD(SplObjectStorage, valid)
469 54 : {
470 54 : spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
471 :
472 54 : RETURN_BOOL(zend_hash_has_more_elements_ex(&intern->storage, &intern->pos) == SUCCESS);
473 : } /* }}} */
474 :
475 : /* {{{ proto mixed SplObjectStorage::key()
476 : Returns current key */
477 : SPL_METHOD(SplObjectStorage, key)
478 14 : {
479 14 : spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
480 :
481 14 : RETURN_LONG(intern->index);
482 : } /* }}} */
483 :
484 : /* {{{ proto mixed SplObjectStorage::current()
485 : Returns current element */
486 : SPL_METHOD(SplObjectStorage, current)
487 40 : {
488 : spl_SplObjectStorageElement *element;
489 40 : spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
490 :
491 40 : if (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == FAILURE) {
492 1 : return;
493 : }
494 39 : RETVAL_ZVAL(element->obj, 1, 0);
495 : } /* }}} */
496 :
497 : /* {{{ proto mixed SplObjectStorage::getInfo()
498 : Returns associated information to current element */
499 : SPL_METHOD(SplObjectStorage, getInfo)
500 3 : {
501 : spl_SplObjectStorageElement *element;
502 3 : spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
503 :
504 3 : if (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == FAILURE) {
505 1 : return;
506 : }
507 2 : RETVAL_ZVAL(element->inf, 1, 0);
508 : } /* }}} */
509 :
510 : /* {{{ proto mixed SplObjectStorage::setInfo(mixed $inf)
511 : Sets associated information of current element to $inf */
512 : SPL_METHOD(SplObjectStorage, setInfo)
513 3 : {
514 : spl_SplObjectStorageElement *element;
515 3 : spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
516 : zval *inf;
517 :
518 3 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &inf) == FAILURE) {
519 1 : return;
520 : }
521 :
522 2 : if (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == FAILURE) {
523 1 : return;
524 : }
525 1 : zval_ptr_dtor(&element->inf);
526 1 : element->inf = inf;
527 1 : Z_ADDREF_P(inf);
528 : } /* }}} */
529 :
530 : /* {{{ proto void SplObjectStorage::next()
531 : Moves position forward */
532 : SPL_METHOD(SplObjectStorage, next)
533 33 : {
534 33 : spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
535 :
536 33 : zend_hash_move_forward_ex(&intern->storage, &intern->pos);
537 33 : intern->index++;
538 33 : } /* }}} */
539 :
540 : /* {{{ proto string SplObjectStorage::serialize()
541 : Serializes storage */
542 : SPL_METHOD(SplObjectStorage, serialize)
543 12 : {
544 12 : spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
545 :
546 : spl_SplObjectStorageElement *element;
547 : zval members, *pmembers;
548 : HashPosition pos;
549 : php_serialize_data_t var_hash;
550 12 : smart_str buf = {0};
551 :
552 12 : PHP_VAR_SERIALIZE_INIT(var_hash);
553 :
554 : /* storage */
555 12 : smart_str_appendl(&buf, "x:i:", 4);
556 12 : smart_str_append_long(&buf, zend_hash_num_elements(&intern->storage));
557 12 : smart_str_appendc(&buf, ';');
558 :
559 12 : zend_hash_internal_pointer_reset_ex(&intern->storage, &pos);
560 :
561 58 : while(zend_hash_has_more_elements_ex(&intern->storage, &pos) == SUCCESS) {
562 34 : if (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &pos) == FAILURE) {
563 0 : smart_str_free(&buf);
564 0 : PHP_VAR_SERIALIZE_DESTROY(var_hash);
565 0 : RETURN_NULL();
566 : }
567 34 : php_var_serialize(&buf, &element->obj, &var_hash TSRMLS_CC);
568 34 : smart_str_appendc(&buf, ',');
569 34 : php_var_serialize(&buf, &element->inf, &var_hash TSRMLS_CC);
570 34 : smart_str_appendc(&buf, ';');
571 34 : zend_hash_move_forward_ex(&intern->storage, &pos);
572 : }
573 :
574 : /* members */
575 12 : smart_str_appendl(&buf, "m:", 2);
576 12 : INIT_PZVAL(&members);
577 12 : Z_ARRVAL(members) = intern->std.properties;
578 12 : Z_TYPE(members) = IS_ARRAY;
579 12 : pmembers = &members;
580 12 : php_var_serialize(&buf, &pmembers, &var_hash TSRMLS_CC); /* finishes the string */
581 :
582 : /* done */
583 12 : PHP_VAR_SERIALIZE_DESTROY(var_hash);
584 :
585 12 : if (buf.c) {
586 12 : RETURN_STRINGL(buf.c, buf.len, 0);
587 : } else {
588 0 : RETURN_NULL();
589 : }
590 :
591 : } /* }}} */
592 :
593 : /* {{{ proto void SplObjectStorage::unserialize(string serialized)
594 : Unserializes storage */
595 : SPL_METHOD(SplObjectStorage, unserialize)
596 16 : {
597 16 : spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
598 :
599 : char *buf;
600 : int buf_len;
601 : const unsigned char *p, *s;
602 : php_unserialize_data_t var_hash;
603 16 : zval *pentry, *pmembers, *pcount = NULL, *pinf;
604 : long count;
605 :
606 16 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) {
607 2 : return;
608 : }
609 :
610 14 : if (buf_len == 0) {
611 1 : zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Empty serialized string cannot be empty");
612 1 : return;
613 : }
614 :
615 : /* storage */
616 13 : s = p = (const unsigned char*)buf;
617 13 : PHP_VAR_UNSERIALIZE_INIT(var_hash);
618 :
619 13 : if (*p!= 'x' || *++p != ':') {
620 : goto outexcept;
621 : }
622 10 : ++p;
623 :
624 10 : ALLOC_INIT_ZVAL(pcount);
625 10 : if (!php_var_unserialize(&pcount, &p, s + buf_len, NULL TSRMLS_CC) || Z_TYPE_P(pcount) != IS_LONG) {
626 1 : zval_ptr_dtor(&pcount);
627 1 : goto outexcept;
628 : }
629 :
630 9 : --p; /* for ';' */
631 9 : count = Z_LVAL_P(pcount);
632 9 : zval_ptr_dtor(&pcount);
633 :
634 43 : while(count-- > 0) {
635 26 : if (*p != ';') {
636 0 : goto outexcept;
637 : }
638 26 : ++p;
639 26 : ALLOC_INIT_ZVAL(pentry);
640 26 : if (!php_var_unserialize(&pentry, &p, s + buf_len, &var_hash TSRMLS_CC)) {
641 1 : zval_ptr_dtor(&pentry);
642 1 : goto outexcept;
643 : }
644 25 : ALLOC_INIT_ZVAL(pinf);
645 25 : if (*p == ',') { /* new version has inf */
646 25 : ++p;
647 25 : if (!php_var_unserialize(&pinf, &p, s + buf_len, &var_hash TSRMLS_CC)) {
648 0 : zval_ptr_dtor(&pinf);
649 0 : goto outexcept;
650 : }
651 : }
652 25 : spl_object_storage_attach(intern, pentry, pinf TSRMLS_CC);
653 25 : zval_ptr_dtor(&pentry);
654 25 : zval_ptr_dtor(&pinf);
655 : }
656 :
657 8 : if (*p != ';') {
658 0 : goto outexcept;
659 : }
660 8 : ++p;
661 :
662 : /* members */
663 8 : if (*p!= 'm' || *++p != ':') {
664 : goto outexcept;
665 : }
666 8 : ++p;
667 :
668 8 : ALLOC_INIT_ZVAL(pmembers);
669 8 : if (!php_var_unserialize(&pmembers, &p, s + buf_len, &var_hash TSRMLS_CC)) {
670 0 : zval_ptr_dtor(&pmembers);
671 0 : goto outexcept;
672 : }
673 :
674 : /* copy members */
675 8 : zend_hash_copy(intern->std.properties, Z_ARRVAL_P(pmembers), (copy_ctor_func_t) zval_add_ref, (void *) NULL, sizeof(zval *));
676 8 : zval_ptr_dtor(&pmembers);
677 :
678 : /* done reading $serialized */
679 :
680 8 : PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
681 8 : return;
682 :
683 5 : outexcept:
684 5 : PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
685 5 : zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Error at offset %ld of %d bytes", (long)((char*)p - buf), buf_len);
686 5 : return;
687 :
688 : } /* }}} */
689 :
690 : ZEND_BEGIN_ARG_INFO(arginfo_Object, 0)
691 : ZEND_ARG_INFO(0, object)
692 : ZEND_END_ARG_INFO();
693 :
694 : ZEND_BEGIN_ARG_INFO_EX(arginfo_attach, 0, 0, 1)
695 : ZEND_ARG_INFO(0, object)
696 : ZEND_ARG_INFO(0, inf)
697 : ZEND_END_ARG_INFO();
698 :
699 : ZEND_BEGIN_ARG_INFO(arginfo_Serialized, 0)
700 : ZEND_ARG_INFO(0, serialized)
701 : ZEND_END_ARG_INFO();
702 :
703 : ZEND_BEGIN_ARG_INFO(arginfo_setInfo, 0)
704 : ZEND_ARG_INFO(0, info)
705 : ZEND_END_ARG_INFO();
706 :
707 : ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1)
708 : ZEND_ARG_INFO(0, object)
709 : ZEND_END_ARG_INFO()
710 :
711 : ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetSet, 0, 0, 2)
712 : ZEND_ARG_INFO(0, object)
713 : ZEND_ARG_INFO(0, info)
714 : ZEND_END_ARG_INFO()
715 :
716 : ZEND_BEGIN_ARG_INFO(arginfo_splobject_void, 0)
717 : ZEND_END_ARG_INFO()
718 :
719 : static const zend_function_entry spl_funcs_SplObjectStorage[] = {
720 : SPL_ME(SplObjectStorage, attach, arginfo_attach, 0)
721 : SPL_ME(SplObjectStorage, detach, arginfo_Object, 0)
722 : SPL_ME(SplObjectStorage, contains, arginfo_Object, 0)
723 : SPL_ME(SplObjectStorage, addAll, arginfo_Object, 0)
724 : SPL_ME(SplObjectStorage, removeAll, arginfo_Object, 0)
725 : SPL_ME(SplObjectStorage, getInfo, arginfo_splobject_void,0)
726 : SPL_ME(SplObjectStorage, setInfo, arginfo_setInfo, 0)
727 : /* Countable */
728 : SPL_ME(SplObjectStorage, count, arginfo_splobject_void,0)
729 : /* Iterator */
730 : SPL_ME(SplObjectStorage, rewind, arginfo_splobject_void,0)
731 : SPL_ME(SplObjectStorage, valid, arginfo_splobject_void,0)
732 : SPL_ME(SplObjectStorage, key, arginfo_splobject_void,0)
733 : SPL_ME(SplObjectStorage, current, arginfo_splobject_void,0)
734 : SPL_ME(SplObjectStorage, next, arginfo_splobject_void,0)
735 : /* Serializable */
736 : SPL_ME(SplObjectStorage, unserialize, arginfo_Serialized, 0)
737 : SPL_ME(SplObjectStorage, serialize, arginfo_splobject_void,0)
738 : /* ArrayAccess */
739 : SPL_MA(SplObjectStorage, offsetExists, SplObjectStorage, contains, arginfo_offsetGet, 0)
740 : SPL_MA(SplObjectStorage, offsetSet, SplObjectStorage, attach, arginfo_offsetSet, 0)
741 : SPL_MA(SplObjectStorage, offsetUnset, SplObjectStorage, detach, arginfo_offsetGet, 0)
742 : SPL_ME(SplObjectStorage, offsetGet, arginfo_offsetGet, 0)
743 : {NULL, NULL, NULL}
744 : };
745 :
746 : typedef enum {
747 : MIT_NEED_ANY = 0,
748 : MIT_NEED_ALL = 1,
749 : MIT_KEYS_NUMERIC = 0,
750 : MIT_KEYS_ASSOC = 2
751 : } MultipleIteratorFlags;
752 :
753 : #define SPL_MULTIPLE_ITERATOR_GET_ALL_CURRENT 1
754 : #define SPL_MULTIPLE_ITERATOR_GET_ALL_KEY 2
755 :
756 : /* {{{ proto void MultipleIterator::__construct([int flags = MIT_NEED_ALL|MIT_KEYS_NUMERIC])
757 : Iterator that iterates over several iterators one after the other */
758 : SPL_METHOD(MultipleIterator, __construct)
759 1 : {
760 : spl_SplObjectStorage *intern;
761 1 : long flags = MIT_NEED_ALL|MIT_KEYS_NUMERIC;
762 : zend_error_handling error_handling;
763 :
764 1 : zend_replace_error_handling(EH_THROW, spl_ce_InvalidArgumentException, &error_handling TSRMLS_CC);
765 :
766 1 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags) == FAILURE) {
767 0 : zend_restore_error_handling(&error_handling TSRMLS_CC);
768 0 : return;
769 : }
770 :
771 1 : intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
772 1 : intern->flags = flags;
773 1 : zend_restore_error_handling(&error_handling TSRMLS_CC);
774 : }
775 : /* }}} */
776 :
777 : /* {{{ proto int MultipleIterator::getFlags()
778 : Return current flags */
779 : SPL_METHOD(MultipleIterator, getFlags)
780 2 : {
781 2 : spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
782 2 : RETURN_LONG(intern->flags);
783 : }
784 : /* }}} */
785 :
786 : /* {{{ proto int MultipleIterator::setFlags(int flags)
787 : Set flags */
788 : SPL_METHOD(MultipleIterator, setFlags)
789 3 : {
790 : spl_SplObjectStorage *intern;
791 3 : intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
792 :
793 3 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &intern->flags) == FAILURE) {
794 : return;
795 : }
796 : }
797 : /* }}} */
798 :
799 : /* {{{ proto void attachIterator(Iterator iterator[, mixed info]) throws InvalidArgumentException
800 : Attach a new iterator */
801 : SPL_METHOD(MultipleIterator, attachIterator)
802 8 : {
803 : spl_SplObjectStorage *intern;
804 8 : zval *iterator = NULL, *info = NULL;
805 :
806 8 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|z!", &iterator, zend_ce_iterator, &info) == FAILURE) {
807 0 : return;
808 : }
809 :
810 8 : intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
811 :
812 8 : if (info != NULL) {
813 : spl_SplObjectStorageElement *element;
814 : zval compare_result;
815 :
816 5 : if (Z_TYPE_P(info) != IS_LONG && Z_TYPE_P(info) != IS_STRING) {
817 1 : zend_throw_exception(spl_ce_InvalidArgumentException, "Info must be NULL, integer or string", 0 TSRMLS_CC);
818 1 : return;
819 : }
820 :
821 4 : zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
822 17 : while (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == SUCCESS) {
823 10 : is_identical_function(&compare_result, info, element->inf TSRMLS_CC);
824 10 : if (Z_LVAL(compare_result)) {
825 1 : zend_throw_exception(spl_ce_InvalidArgumentException, "Key duplication error", 0 TSRMLS_CC);
826 1 : return;
827 : }
828 9 : zend_hash_move_forward_ex(&intern->storage, &intern->pos);
829 : }
830 : }
831 :
832 6 : spl_object_storage_attach(intern, iterator, info TSRMLS_CC);
833 : }
834 : /* }}} */
835 :
836 : /* {{{ proto void MultipleIterator::rewind()
837 : Rewind all attached iterator instances */
838 : SPL_METHOD(MultipleIterator, rewind)
839 7 : {
840 : spl_SplObjectStorage *intern;
841 : spl_SplObjectStorageElement *element;
842 : zval *it;
843 :
844 7 : intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
845 :
846 7 : zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
847 31 : while (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == SUCCESS && !EG(exception)) {
848 17 : it = element->obj;
849 17 : zend_call_method_with_0_params(&it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_rewind, "rewind", NULL);
850 17 : zend_hash_move_forward_ex(&intern->storage, &intern->pos);
851 : }
852 7 : }
853 : /* }}} */
854 :
855 : /* {{{ proto void MultipleIterator::next()
856 : Move all attached iterator instances forward */
857 : SPL_METHOD(MultipleIterator, next)
858 14 : {
859 : spl_SplObjectStorage *intern;
860 : spl_SplObjectStorageElement *element;
861 : zval *it;
862 :
863 14 : intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
864 :
865 14 : zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
866 67 : while (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == SUCCESS && !EG(exception)) {
867 39 : it = element->obj;
868 39 : zend_call_method_with_0_params(&it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_next, "next", NULL);
869 39 : zend_hash_move_forward_ex(&intern->storage, &intern->pos);
870 : }
871 14 : }
872 : /* }}} */
873 :
874 : /* {{{ proto bool MultipleIterator::valid()
875 : Return whether all or one sub iterator is valid depending on flags */
876 : SPL_METHOD(MultipleIterator, valid)
877 20 : {
878 : spl_SplObjectStorage *intern;
879 : spl_SplObjectStorageElement *element;
880 20 : zval *it, *retval = NULL;
881 : long expect, valid;
882 :
883 20 : intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
884 :
885 20 : if (!zend_hash_num_elements(&intern->storage)) {
886 1 : RETURN_FALSE;
887 : }
888 :
889 19 : expect = (intern->flags & MIT_NEED_ALL) ? 1 : 0;
890 :
891 19 : zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
892 72 : while (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == SUCCESS && !EG(exception)) {
893 41 : it = element->obj;
894 41 : zend_call_method_with_0_params(&it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_valid, "valid", &retval);
895 :
896 41 : if (retval) {
897 41 : valid = Z_LVAL_P(retval);
898 41 : zval_ptr_dtor(&retval);
899 : } else {
900 0 : valid = 0;
901 : }
902 :
903 41 : if (expect != valid) {
904 7 : RETURN_BOOL(!expect);
905 : }
906 :
907 34 : zend_hash_move_forward_ex(&intern->storage, &intern->pos);
908 : }
909 :
910 12 : RETURN_BOOL(expect);
911 : }
912 : /* }}} */
913 :
914 : static void spl_multiple_iterator_get_all(spl_SplObjectStorage *intern, int get_type, zval *return_value TSRMLS_DC) /* {{{ */
915 32 : {
916 : spl_SplObjectStorageElement *element;
917 32 : zval *it, *retval = NULL;
918 32 : int valid = 1, num_elements;
919 :
920 32 : num_elements = zend_hash_num_elements(&intern->storage);
921 32 : if (num_elements < 1) {
922 1 : RETURN_FALSE;
923 : }
924 :
925 31 : array_init_size(return_value, num_elements);
926 :
927 31 : zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
928 142 : while (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == SUCCESS && !EG(exception)) {
929 83 : it = element->obj;
930 83 : zend_call_method_with_0_params(&it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_valid, "valid", &retval);
931 :
932 83 : if (retval) {
933 83 : valid = Z_LVAL_P(retval);
934 83 : zval_ptr_dtor(&retval);
935 : } else {
936 0 : valid = 0;
937 : }
938 :
939 83 : if (valid) {
940 79 : if (SPL_MULTIPLE_ITERATOR_GET_ALL_CURRENT == get_type) {
941 40 : zend_call_method_with_0_params(&it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_current, "current", &retval);
942 : } else {
943 39 : zend_call_method_with_0_params(&it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_key, "key", &retval);
944 : }
945 79 : if (!retval) {
946 0 : zend_throw_exception(spl_ce_RuntimeException, "Failed to call sub iterator method", 0 TSRMLS_CC);
947 0 : return;
948 : }
949 4 : } else if (intern->flags & MIT_NEED_ALL) {
950 2 : if (SPL_MULTIPLE_ITERATOR_GET_ALL_CURRENT == get_type) {
951 1 : zend_throw_exception(spl_ce_RuntimeException, "Called current() with non valid sub iterator", 0 TSRMLS_CC);
952 : } else {
953 1 : zend_throw_exception(spl_ce_RuntimeException, "Called key() with non valid sub iterator", 0 TSRMLS_CC);
954 : }
955 2 : return;
956 : } else {
957 2 : ALLOC_INIT_ZVAL(retval);
958 : }
959 :
960 81 : if (intern->flags & MIT_KEYS_ASSOC) {
961 31 : switch (Z_TYPE_P(element->inf)) {
962 : case IS_LONG:
963 12 : add_index_zval(return_value, Z_LVAL_P(element->inf), retval);
964 12 : break;
965 : case IS_STRING:
966 18 : add_assoc_zval_ex(return_value, Z_STRVAL_P(element->inf), Z_STRLEN_P(element->inf)+1U, retval);
967 18 : break;
968 : default:
969 1 : zval_ptr_dtor(&retval);
970 1 : zend_throw_exception(spl_ce_InvalidArgumentException, "Sub-Iterator is associated with NULL", 0 TSRMLS_CC);
971 1 : return;
972 : }
973 : } else {
974 50 : add_next_index_zval(return_value, retval);
975 : }
976 :
977 80 : zend_hash_move_forward_ex(&intern->storage, &intern->pos);
978 : }
979 : }
980 : /* }}} */
981 :
982 : /* {{{ proto array current() throws RuntimeException throws InvalidArgumentException
983 : Return an array of all registered Iterator instances current() result */
984 : SPL_METHOD(MultipleIterator, current)
985 17 : {
986 : spl_SplObjectStorage *intern;
987 17 : intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
988 :
989 17 : spl_multiple_iterator_get_all(intern, SPL_MULTIPLE_ITERATOR_GET_ALL_CURRENT, return_value TSRMLS_CC);
990 17 : }
991 : /* }}} */
992 :
993 : /* {{{ proto array MultipleIterator::key()
994 : Return an array of all registered Iterator instances key() result */
995 : SPL_METHOD(MultipleIterator, key)
996 15 : {
997 : spl_SplObjectStorage *intern;
998 15 : intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
999 :
1000 15 : spl_multiple_iterator_get_all(intern, SPL_MULTIPLE_ITERATOR_GET_ALL_KEY, return_value TSRMLS_CC);
1001 15 : }
1002 : /* }}} */
1003 :
1004 : ZEND_BEGIN_ARG_INFO_EX(arginfo_MultipleIterator_attachIterator, 0, 0, 1)
1005 : ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
1006 : ZEND_ARG_INFO(0, infos)
1007 : ZEND_END_ARG_INFO();
1008 :
1009 : ZEND_BEGIN_ARG_INFO_EX(arginfo_MultipleIterator_detachIterator, 0, 0, 1)
1010 : ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
1011 : ZEND_END_ARG_INFO();
1012 :
1013 : ZEND_BEGIN_ARG_INFO_EX(arginfo_MultipleIterator_containsIterator, 0, 0, 1)
1014 : ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
1015 : ZEND_END_ARG_INFO();
1016 :
1017 : ZEND_BEGIN_ARG_INFO_EX(arginfo_MultipleIterator_setflags, 0, 0, 1)
1018 : ZEND_ARG_INFO(0, flags)
1019 : ZEND_END_ARG_INFO();
1020 :
1021 : static const zend_function_entry spl_funcs_MultipleIterator[] = {
1022 : SPL_ME(MultipleIterator, __construct, arginfo_MultipleIterator_setflags, 0)
1023 : SPL_ME(MultipleIterator, getFlags, arginfo_splobject_void, 0)
1024 : SPL_ME(MultipleIterator, setFlags, arginfo_MultipleIterator_setflags, 0)
1025 : SPL_ME(MultipleIterator, attachIterator, arginfo_MultipleIterator_attachIterator, 0)
1026 : SPL_MA(MultipleIterator, detachIterator, SplObjectStorage, detach, arginfo_MultipleIterator_detachIterator, 0)
1027 : SPL_MA(MultipleIterator, containsIterator, SplObjectStorage, contains, arginfo_MultipleIterator_containsIterator, 0)
1028 : SPL_MA(MultipleIterator, countIterators, SplObjectStorage, count, arginfo_splobject_void, 0)
1029 : /* Iterator */
1030 : SPL_ME(MultipleIterator, rewind, arginfo_splobject_void, 0)
1031 : SPL_ME(MultipleIterator, valid, arginfo_splobject_void, 0)
1032 : SPL_ME(MultipleIterator, key, arginfo_splobject_void, 0)
1033 : SPL_ME(MultipleIterator, current, arginfo_splobject_void, 0)
1034 : SPL_ME(MultipleIterator, next, arginfo_splobject_void, 0)
1035 : {NULL, NULL, NULL}
1036 : };
1037 :
1038 : /* {{{ PHP_MINIT_FUNCTION(spl_observer) */
1039 : PHP_MINIT_FUNCTION(spl_observer)
1040 17633 : {
1041 17633 : REGISTER_SPL_INTERFACE(SplObserver);
1042 17633 : REGISTER_SPL_INTERFACE(SplSubject);
1043 :
1044 17633 : REGISTER_SPL_STD_CLASS_EX(SplObjectStorage, spl_SplObjectStorage_new, spl_funcs_SplObjectStorage);
1045 17633 : memcpy(&spl_handler_SplObjectStorage, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1046 :
1047 17633 : spl_handler_SplObjectStorage.get_debug_info = spl_object_storage_debug_info;
1048 17633 : spl_handler_SplObjectStorage.compare_objects = spl_object_storage_compare_objects;
1049 17633 : spl_handler_SplObjectStorage.clone_obj = spl_object_storage_clone;
1050 :
1051 17633 : REGISTER_SPL_IMPLEMENTS(SplObjectStorage, Countable);
1052 17633 : REGISTER_SPL_IMPLEMENTS(SplObjectStorage, Iterator);
1053 17633 : REGISTER_SPL_IMPLEMENTS(SplObjectStorage, Serializable);
1054 17633 : REGISTER_SPL_IMPLEMENTS(SplObjectStorage, ArrayAccess);
1055 :
1056 17633 : REGISTER_SPL_STD_CLASS_EX(MultipleIterator, spl_SplObjectStorage_new, spl_funcs_MultipleIterator);
1057 17633 : REGISTER_SPL_ITERATOR(MultipleIterator);
1058 :
1059 17633 : REGISTER_SPL_CLASS_CONST_LONG(MultipleIterator, "MIT_NEED_ANY", MIT_NEED_ANY);
1060 17633 : REGISTER_SPL_CLASS_CONST_LONG(MultipleIterator, "MIT_NEED_ALL", MIT_NEED_ALL);
1061 17633 : REGISTER_SPL_CLASS_CONST_LONG(MultipleIterator, "MIT_KEYS_NUMERIC", MIT_KEYS_NUMERIC);
1062 17633 : REGISTER_SPL_CLASS_CONST_LONG(MultipleIterator, "MIT_KEYS_ASSOC", MIT_KEYS_ASSOC);
1063 :
1064 17633 : return SUCCESS;
1065 : }
1066 : /* }}} */
1067 :
1068 : /*
1069 : * Local variables:
1070 : * tab-width: 4
1071 : * c-basic-offset: 4
1072 : * End:
1073 : * vim600: fdm=marker
1074 : * vim: noet sw=4 ts=4
1075 : */
|