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