1 : /*
2 : +----------------------------------------------------------------------+
3 : | Zend Engine |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1998-2009 Zend Technologies Ltd. (http://www.zend.com) |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 2.00 of the Zend 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.zend.com/license/2_00.txt. |
11 : | If you did not receive a copy of the Zend license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@zend.com so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Authors: Marcus Boerger <helly@php.net> |
16 : +----------------------------------------------------------------------+
17 : */
18 :
19 : /* $Id: zend_interfaces.c 286510 2009-07-29 14:27:43Z felipe $ */
20 :
21 : #include "zend.h"
22 : #include "zend_API.h"
23 : #include "zend_interfaces.h"
24 : #include "zend_exceptions.h"
25 :
26 : ZEND_API zend_class_entry *zend_ce_traversable;
27 : ZEND_API zend_class_entry *zend_ce_aggregate;
28 : ZEND_API zend_class_entry *zend_ce_iterator;
29 : ZEND_API zend_class_entry *zend_ce_arrayaccess;
30 : ZEND_API zend_class_entry *zend_ce_serializable;
31 :
32 : /* {{{ zend_call_method
33 : Only returns the returned zval if retval_ptr != NULL */
34 : ZEND_API zval* zend_u_call_method(zval **object_pp, zend_class_entry *obj_ce, zend_function **fn_proxy, int function_name_type, zstr function_name, int function_name_len, zval **retval_ptr_ptr, int param_count, zval* arg1, zval* arg2 TSRMLS_DC)
35 150161 : {
36 : int result;
37 : zend_fcall_info fci;
38 : zval z_fname;
39 : zval *retval;
40 : HashTable *function_table;
41 :
42 : zval **params[2];
43 :
44 150161 : params[0] = &arg1;
45 150161 : params[1] = &arg2;
46 :
47 150161 : fci.size = sizeof(fci);
48 : /*fci.function_table = NULL; will be read form zend_class_entry of object if needed */
49 150161 : fci.object_ptr = object_pp ? *object_pp : NULL;
50 150161 : fci.function_name = &z_fname;
51 150161 : fci.retval_ptr_ptr = retval_ptr_ptr ? retval_ptr_ptr : &retval;
52 150161 : fci.param_count = param_count;
53 150161 : fci.params = params;
54 150161 : fci.no_separation = 1;
55 150161 : fci.symbol_table = NULL;
56 :
57 150199 : if (!fn_proxy && !obj_ce) {
58 : /* no interest in caching and no information already present that is
59 : * needed later inside zend_call_function. */
60 38 : ZVAL_ZSTRL(&z_fname, function_name_type, function_name, function_name_len, ZSTR_DUPLICATE);
61 38 : fci.function_table = !object_pp ? EG(function_table) : NULL;
62 38 : result = zend_call_function(&fci, NULL TSRMLS_CC);
63 38 : zval_dtor(&z_fname);
64 : } else {
65 : zend_fcall_info_cache fcic;
66 :
67 150123 : fcic.initialized = 1;
68 150123 : if (!obj_ce) {
69 27 : obj_ce = object_pp ? Z_OBJCE_PP(object_pp) : NULL;
70 : }
71 150123 : if (obj_ce) {
72 150096 : function_table = &obj_ce->function_table;
73 : } else {
74 27 : function_table = EG(function_table);
75 : }
76 161672 : if (!fn_proxy || !*fn_proxy) {
77 11549 : if (zend_u_hash_find(function_table, function_name_type, function_name, function_name_len+1, (void **) &fcic.function_handler) == FAILURE) {
78 : /* error at c-level */
79 0 : zend_error(E_CORE_ERROR, "Couldn't find implementation for method %v%s%s", obj_ce ? obj_ce->name : EMPTY_ZSTR, obj_ce ? "::" : "", function_name);
80 : }
81 11549 : if (fn_proxy) {
82 868 : *fn_proxy = fcic.function_handler;
83 : }
84 : } else {
85 138574 : fcic.function_handler = *fn_proxy;
86 : }
87 150123 : fcic.calling_scope = obj_ce;
88 150123 : if (object_pp) {
89 150049 : fcic.called_scope = Z_OBJCE_PP(object_pp);
90 84 : } else if (obj_ce &&
91 : !(EG(called_scope) &&
92 : instanceof_function(EG(called_scope), obj_ce TSRMLS_CC))) {
93 10 : fcic.called_scope = obj_ce;
94 : } else {
95 64 : fcic.called_scope = EG(called_scope);
96 : }
97 150123 : fcic.object_ptr = object_pp ? *object_pp : NULL;
98 150123 : result = zend_call_function(&fci, &fcic TSRMLS_CC);
99 : }
100 150151 : if (result == FAILURE) {
101 : /* error at c-level */
102 5 : if (!obj_ce) {
103 1 : obj_ce = object_pp ? Z_OBJCE_PP(object_pp) : NULL;
104 : }
105 5 : if (!EG(exception)) {
106 0 : zend_error(E_CORE_ERROR, "Couldn't execute method %v%s%s", obj_ce ? obj_ce->name : EMPTY_ZSTR, obj_ce ? "::" : "", function_name);
107 : }
108 : }
109 150151 : if (!retval_ptr_ptr) {
110 11380 : if (retval) {
111 11321 : zval_ptr_dtor(&retval);
112 : }
113 11380 : return NULL;
114 : }
115 138771 : return *retval_ptr_ptr;
116 : }
117 : /* }}} */
118 :
119 : /* iterator interface, c-level functions used by engine */
120 :
121 : /* {{{ zend_user_it_new_iterator */
122 : ZEND_API zval *zend_user_it_new_iterator(zend_class_entry *ce, zval *object TSRMLS_DC)
123 91 : {
124 : zval *retval;
125 :
126 91 : return zend_call_method_with_0_params(&object, ce, &ce->iterator_funcs.zf_new_iterator, "getiterator", &retval);
127 :
128 : }
129 : /* }}} */
130 :
131 : /* {{{ zend_user_it_dtor */
132 : ZEND_API void zend_user_it_invalidate_current(zend_object_iterator *_iter TSRMLS_DC)
133 11044 : {
134 11044 : zend_user_iterator *iter = (zend_user_iterator*)_iter;
135 :
136 11044 : if (iter->value) {
137 7491 : zval_ptr_dtor(&iter->value);
138 7491 : iter->value = NULL;
139 : }
140 11044 : }
141 : /* }}} */
142 :
143 : /* {{{ zend_user_it_dtor */
144 : static void zend_user_it_dtor(zend_object_iterator *_iter TSRMLS_DC)
145 524 : {
146 524 : zend_user_iterator *iter = (zend_user_iterator*)_iter;
147 524 : zval *object = (zval*)iter->it.data;
148 :
149 524 : zend_user_it_invalidate_current(_iter TSRMLS_CC);
150 524 : zval_ptr_dtor(&object);
151 524 : efree(iter);
152 524 : }
153 : /* }}} */
154 :
155 : /* {{{ zend_user_it_valid */
156 : ZEND_API int zend_user_it_valid(zend_object_iterator *_iter TSRMLS_DC)
157 11697 : {
158 11697 : if (_iter) {
159 11697 : zend_user_iterator *iter = (zend_user_iterator*)_iter;
160 11697 : zval *object = (zval*)iter->it.data;
161 : zval *more;
162 : int result;
163 :
164 11697 : zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_valid, "valid", &more);
165 11697 : if (more) {
166 11690 : result = i_zend_is_true(more);
167 11690 : zval_ptr_dtor(&more);
168 11690 : return result ? SUCCESS : FAILURE;
169 : }
170 : }
171 7 : return FAILURE;
172 : }
173 : /* }}} */
174 :
175 : /* {{{ zend_user_it_get_current_data */
176 : ZEND_API void zend_user_it_get_current_data(zend_object_iterator *_iter, zval ***data TSRMLS_DC)
177 7536 : {
178 7536 : zend_user_iterator *iter = (zend_user_iterator*)_iter;
179 7536 : zval *object = (zval*)iter->it.data;
180 :
181 7536 : if (!iter->value) {
182 7500 : zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_current, "current", &iter->value);
183 : }
184 7536 : *data = &iter->value;
185 7536 : }
186 : /* }}} */
187 :
188 : /* {{{ zend_user_it_get_current_key_default */
189 : #if 0
190 : static int zend_user_it_get_current_key_default(zend_object_iterator *_iter, zstr *str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
191 : {
192 : *int_key = _iter->index;
193 : return HASH_KEY_IS_LONG;
194 : }
195 : #endif
196 : /* }}} */
197 :
198 : /* {{{ zend_user_it_get_current_key */
199 : ZEND_API int zend_user_it_get_current_key(zend_object_iterator *_iter, zstr *str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
200 7034 : {
201 7034 : zend_user_iterator *iter = (zend_user_iterator*)_iter;
202 7034 : zval *object = (zval*)iter->it.data;
203 : zval *retval;
204 :
205 7034 : zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_key, "key", &retval);
206 :
207 7034 : if (!retval) {
208 4 : *int_key = 0;
209 4 : if (!EG(exception))
210 : {
211 0 : zend_error(E_WARNING, "Nothing returned from %v::key()", iter->ce->name);
212 : }
213 4 : return HASH_KEY_IS_LONG;
214 : }
215 7030 : switch (Z_TYPE_P(retval)) {
216 : default:
217 0 : zend_error(E_WARNING, "Illegal type returned from %v::key()", iter->ce->name);
218 : case IS_NULL:
219 0 : *int_key = 0;
220 0 : zval_ptr_dtor(&retval);
221 0 : return HASH_KEY_IS_LONG;
222 :
223 : case IS_STRING:
224 146 : str_key->s = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
225 146 : *str_key_len = Z_STRLEN_P(retval)+1;
226 146 : zval_ptr_dtor(&retval);
227 146 : return HASH_KEY_IS_STRING;
228 :
229 : case IS_UNICODE:
230 6242 : str_key->u = eustrndup(Z_USTRVAL_P(retval), Z_USTRLEN_P(retval));
231 6242 : *str_key_len = Z_USTRLEN_P(retval)+1;
232 6242 : zval_ptr_dtor(&retval);
233 6242 : return HASH_KEY_IS_UNICODE;
234 :
235 : case IS_DOUBLE:
236 0 : *int_key = (long)Z_DVAL_P(retval);
237 0 : zval_ptr_dtor(&retval);
238 0 : return HASH_KEY_IS_LONG;
239 :
240 : case IS_RESOURCE:
241 : case IS_BOOL:
242 : case IS_LONG:
243 642 : *int_key = (long)Z_LVAL_P(retval);
244 642 : zval_ptr_dtor(&retval);
245 642 : return HASH_KEY_IS_LONG;
246 : }
247 : }
248 : /* }}} */
249 :
250 : /* {{{ zend_user_it_move_forward */
251 : ZEND_API void zend_user_it_move_forward(zend_object_iterator *_iter TSRMLS_DC)
252 7611 : {
253 7611 : zend_user_iterator *iter = (zend_user_iterator*)_iter;
254 7611 : zval *object = (zval*)iter->it.data;
255 :
256 7611 : zend_user_it_invalidate_current(_iter TSRMLS_CC);
257 7611 : zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_next, "next", NULL);
258 7611 : }
259 : /* }}} */
260 :
261 : /* {{{ zend_user_it_rewind */
262 : ZEND_API void zend_user_it_rewind(zend_object_iterator *_iter TSRMLS_DC)
263 594 : {
264 594 : zend_user_iterator *iter = (zend_user_iterator*)_iter;
265 594 : zval *object = (zval*)iter->it.data;
266 :
267 594 : zend_user_it_invalidate_current(_iter TSRMLS_CC);
268 594 : zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_rewind, "rewind", NULL);
269 594 : }
270 : /* }}} */
271 :
272 : zend_object_iterator_funcs zend_interface_iterator_funcs_iterator = {
273 : zend_user_it_dtor,
274 : zend_user_it_valid,
275 : zend_user_it_get_current_data,
276 : zend_user_it_get_current_key,
277 : zend_user_it_move_forward,
278 : zend_user_it_rewind,
279 : zend_user_it_invalidate_current
280 : };
281 :
282 : /* {{{ zend_user_it_get_iterator */
283 : static zend_object_iterator *zend_user_it_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
284 527 : {
285 : zend_user_iterator *iterator;
286 :
287 527 : if (by_ref) {
288 2 : zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
289 : }
290 :
291 525 : iterator = emalloc(sizeof(zend_user_iterator));
292 :
293 525 : Z_ADDREF_P(object);
294 525 : iterator->it.data = (void*)object;
295 525 : iterator->it.funcs = ce->iterator_funcs.funcs;
296 525 : iterator->ce = Z_OBJCE_P(object);
297 525 : iterator->value = NULL;
298 525 : return (zend_object_iterator*)iterator;
299 : }
300 : /* }}} */
301 :
302 : /* {{{ zend_user_it_get_new_iterator */
303 : ZEND_API zend_object_iterator *zend_user_it_get_new_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
304 91 : {
305 91 : zval *iterator = zend_user_it_new_iterator(ce, object TSRMLS_CC);
306 : zend_object_iterator *new_iterator;
307 :
308 91 : zend_class_entry *ce_it = iterator && Z_TYPE_P(iterator) == IS_OBJECT ? Z_OBJCE_P(iterator) : NULL;
309 :
310 91 : if (!ce_it || !ce_it->get_iterator || (ce_it->get_iterator == zend_user_it_get_new_iterator && iterator == object)) {
311 6 : if (!EG(exception)) {
312 5 : zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Objects returned by %v::getIterator() must be traversable or implement interface Iterator", ce ? ce->name : Z_OBJCE_P(object)->name);
313 : }
314 6 : if (iterator) {
315 5 : zval_ptr_dtor(&iterator);
316 : }
317 6 : return NULL;
318 : }
319 :
320 85 : new_iterator = ce_it->get_iterator(ce_it, iterator, by_ref TSRMLS_CC);
321 85 : zval_ptr_dtor(&iterator);
322 85 : return new_iterator;
323 : }
324 : /* }}} */
325 :
326 : /* {{{ zend_implement_traversable */
327 : static int zend_implement_traversable(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
328 731557 : {
329 : /* check that class_type is traversable at c-level or implements at least one of 'aggregate' and 'Iterator' */
330 : zend_uint i;
331 :
332 731557 : if (class_type->get_iterator || (class_type->parent && class_type->parent->get_iterator)) {
333 714548 : return SUCCESS;
334 : }
335 51026 : for (i = 0; i < class_type->num_interfaces; i++) {
336 51025 : if (class_type->interfaces[i] == zend_ce_aggregate || class_type->interfaces[i] == zend_ce_iterator) {
337 17008 : return SUCCESS;
338 : }
339 : }
340 1 : zend_error(E_CORE_ERROR, "Class %v must implement interface %v as part of either %v or %v",
341 : class_type->name,
342 : zend_ce_traversable->name,
343 : zend_ce_iterator->name,
344 : zend_ce_aggregate->name);
345 0 : return FAILURE;
346 : }
347 : /* }}} */
348 :
349 : /* {{{ zend_implement_aggregate */
350 : static int zend_implement_aggregate(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
351 17060 : {
352 : unsigned int i;
353 17060 : int t = -1;
354 :
355 17060 : if (class_type->get_iterator) {
356 0 : if (class_type->type == ZEND_INTERNAL_CLASS) {
357 : /* inheritance ensures the class has necessary userland methods */
358 0 : return SUCCESS;
359 0 : } else if (class_type->get_iterator != zend_user_it_get_new_iterator) {
360 : /* c-level get_iterator cannot be changed (exception being only Traversable is implmented) */
361 0 : if (class_type->num_interfaces) {
362 0 : for (i = 0; i < class_type->num_interfaces; i++) {
363 0 : if (class_type->interfaces[i] == zend_ce_iterator) {
364 0 : return FAILURE;
365 : }
366 0 : if (class_type->interfaces[i] == zend_ce_traversable) {
367 0 : t = i;
368 : }
369 : }
370 : }
371 0 : if (t == -1) {
372 0 : return FAILURE;
373 : }
374 : }
375 : }
376 17060 : class_type->iterator_funcs.zf_new_iterator = NULL;
377 17060 : class_type->get_iterator = zend_user_it_get_new_iterator;
378 17060 : return SUCCESS;
379 : }
380 : /* }}} */
381 :
382 : /* {{{ zend_implement_iterator */
383 : static int zend_implement_iterator(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
384 663439 : {
385 663439 : if (class_type->get_iterator && class_type->get_iterator != zend_user_it_get_iterator) {
386 51021 : if (class_type->type == ZEND_INTERNAL_CLASS) {
387 : /* inheritance ensures the class has the necessary userland methods */
388 51021 : return SUCCESS;
389 0 : } else if (class_type->get_iterator != zend_user_it_get_new_iterator) {
390 : /* c-level get_iterator cannot be changed */
391 0 : return FAILURE;
392 : }
393 : }
394 612418 : class_type->get_iterator = zend_user_it_get_iterator;
395 612418 : class_type->iterator_funcs.zf_valid = NULL;
396 612418 : class_type->iterator_funcs.zf_current = NULL;
397 612418 : class_type->iterator_funcs.zf_key = NULL;
398 612418 : class_type->iterator_funcs.zf_next = NULL;
399 612418 : class_type->iterator_funcs.zf_rewind = NULL;
400 612418 : if (!class_type->iterator_funcs.funcs) {
401 612418 : class_type->iterator_funcs.funcs = &zend_interface_iterator_funcs_iterator;
402 : }
403 612418 : return SUCCESS;
404 : }
405 : /* }}} */
406 :
407 : /* {{{ zend_implement_arrayaccess */
408 : static int zend_implement_arrayaccess(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
409 204188 : {
410 : #if 0
411 : /* get ht from ce */
412 : if (ht->read_dimension != zend_std_read_dimension
413 : || ht->write_dimension != zend_std_write_dimension
414 : || ht->has_dimension != zend_std_has_dimension
415 : || ht->unset_dimension != zend_std_unset_dimension) {
416 : return FAILURE;
417 : }
418 : #endif
419 204188 : return SUCCESS;
420 : }
421 : /* }}}*/
422 :
423 : /* {{{ zend_user_serialize */
424 : ZEND_API int zend_user_serialize(zval *object, int *type, zstr *buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC)
425 23 : {
426 23 : zend_class_entry * ce = Z_OBJCE_P(object);
427 : zval *retval;
428 : int result;
429 :
430 23 : zend_call_method_with_0_params(&object, ce, &ce->serialize_func, "serialize", &retval);
431 :
432 23 : if (!retval || EG(exception)) {
433 0 : result = FAILURE;
434 : } else {
435 23 : switch(Z_TYPE_P(retval)) {
436 : case IS_NULL:
437 : /* we could also make this '*buf_len = 0' but this allows to skip variables */
438 2 : zval_ptr_dtor(&retval);
439 2 : return FAILURE;
440 : case IS_UNICODE:
441 : case IS_STRING:
442 18 : *buffer = ezstrndup(Z_TYPE_P(retval), Z_UNIVAL_P(retval), Z_UNILEN_P(retval));
443 18 : *buf_len = Z_UNILEN_P(retval);
444 18 : *type = Z_TYPE_P(retval);
445 18 : result = SUCCESS;
446 18 : break;
447 : default: /* failure */
448 3 : result = FAILURE;
449 : break;
450 : }
451 21 : zval_ptr_dtor(&retval);
452 : }
453 :
454 21 : if (result == FAILURE) {
455 3 : zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "%v::serialize() must return a string or NULL", ce->name);
456 : }
457 21 : return result;
458 : }
459 : /* }}} */
460 :
461 : /* {{{ zend_user_unserialize */
462 : ZEND_API int zend_user_unserialize(zval **object, zend_class_entry *ce, int type, const zstr buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC)
463 13 : {
464 : zval * zdata;
465 :
466 13 : object_init_ex(*object, ce);
467 :
468 13 : MAKE_STD_ZVAL(zdata);
469 13 : ZVAL_ZSTRL(zdata, type, buf, buf_len, 1);
470 :
471 13 : zend_call_method_with_1_params(object, ce, &ce->unserialize_func, "unserialize", NULL, zdata);
472 :
473 13 : zval_ptr_dtor(&zdata);
474 :
475 13 : if (EG(exception)) {
476 0 : return FAILURE;
477 : } else {
478 13 : return SUCCESS;
479 : }
480 : }
481 : /* }}} */
482 :
483 : ZEND_API int zend_class_serialize_deny(zval *object, int *type, zstr *buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC) /* {{{ */
484 0 : {
485 0 : zend_class_entry *ce = Z_OBJCE_P(object);
486 0 : zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Serialization of '%v' is not allowed", ce->name);
487 0 : return FAILURE;
488 : } /* }}} */
489 :
490 : ZEND_API int zend_class_unserialize_deny(zval **object, zend_class_entry *ce, int type, const zstr buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC) /* {{{ */
491 0 : {
492 0 : zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Unserialization of '%v' is not allowed", ce->name);
493 0 : return FAILURE;
494 : } /* }}} */
495 :
496 : /* {{{ zend_implement_serializable */
497 : static int zend_implement_serializable(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
498 68126 : {
499 68126 : if (class_type->parent
500 : && (class_type->parent->serialize || class_type->parent->unserialize)
501 : && !instanceof_function_ex(class_type->parent, zend_ce_serializable, 1 TSRMLS_CC)) {
502 0 : return FAILURE;
503 : }
504 68126 : if (!class_type->serialize) {
505 51039 : class_type->serialize = zend_user_serialize;
506 : }
507 68126 : if (!class_type->unserialize) {
508 51039 : class_type->unserialize = zend_user_unserialize;
509 : }
510 68126 : return SUCCESS;
511 : }
512 : /* }}}*/
513 :
514 : /* {{{ function tables */
515 : const zend_function_entry zend_funcs_aggregate[] = {
516 : ZEND_ABSTRACT_ME(iterator, getIterator, NULL)
517 : {NULL, NULL, NULL}
518 : };
519 :
520 : const zend_function_entry zend_funcs_iterator[] = {
521 : ZEND_ABSTRACT_ME(iterator, current, NULL)
522 : ZEND_ABSTRACT_ME(iterator, next, NULL)
523 : ZEND_ABSTRACT_ME(iterator, key, NULL)
524 : ZEND_ABSTRACT_ME(iterator, valid, NULL)
525 : ZEND_ABSTRACT_ME(iterator, rewind, NULL)
526 : {NULL, NULL, NULL}
527 : };
528 :
529 : const zend_function_entry *zend_funcs_traversable = NULL;
530 :
531 : ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offset, 0, 0, 1)
532 : ZEND_ARG_INFO(0, offset)
533 : ZEND_END_ARG_INFO()
534 :
535 : ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offset_get, 0, 0, 1) /* actually this should be return by ref but atm cannot be */
536 : ZEND_ARG_INFO(0, offset)
537 : ZEND_END_ARG_INFO()
538 :
539 : ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offset_value, 0, 0, 2)
540 : ZEND_ARG_INFO(0, offset)
541 : ZEND_ARG_INFO(0, value)
542 : ZEND_END_ARG_INFO()
543 :
544 : const zend_function_entry zend_funcs_arrayaccess[] = {
545 : ZEND_ABSTRACT_ME(arrayaccess, offsetExists, arginfo_arrayaccess_offset)
546 : ZEND_ABSTRACT_ME(arrayaccess, offsetGet, arginfo_arrayaccess_offset_get)
547 : ZEND_ABSTRACT_ME(arrayaccess, offsetSet, arginfo_arrayaccess_offset_value)
548 : ZEND_ABSTRACT_ME(arrayaccess, offsetUnset, arginfo_arrayaccess_offset)
549 : {NULL, NULL, NULL}
550 : };
551 :
552 : ZEND_BEGIN_ARG_INFO(arginfo_serializable_serialize, 0)
553 : ZEND_ARG_INFO(0, serialized)
554 : ZEND_END_ARG_INFO()
555 :
556 : const zend_function_entry zend_funcs_serializable[] = {
557 : ZEND_ABSTRACT_ME(serializable, serialize, NULL)
558 : ZEND_FENTRY(unserialize, NULL, arginfo_serializable_serialize, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT|ZEND_ACC_CTOR)
559 : {NULL, NULL, NULL}
560 : };
561 : /* }}} */
562 :
563 : #define REGISTER_ITERATOR_INTERFACE(class_name, class_name_str) \
564 : {\
565 : zend_class_entry ce;\
566 : INIT_CLASS_ENTRY(ce, # class_name_str, zend_funcs_ ## class_name) \
567 : zend_ce_ ## class_name = zend_register_internal_interface(&ce TSRMLS_CC);\
568 : zend_ce_ ## class_name->interface_gets_implemented = zend_implement_ ## class_name;\
569 : }
570 :
571 : #define REGISTER_ITERATOR_IMPLEMENT(class_name, interface_name) \
572 : zend_class_implements(zend_ce_ ## class_name TSRMLS_CC, 1, zend_ce_ ## interface_name)
573 :
574 : /* {{{ zend_register_interfaces */
575 : ZEND_API void zend_register_interfaces(TSRMLS_D)
576 17007 : {
577 17007 : REGISTER_ITERATOR_INTERFACE(traversable, Traversable);
578 :
579 17007 : REGISTER_ITERATOR_INTERFACE(aggregate, IteratorAggregate);
580 17007 : REGISTER_ITERATOR_IMPLEMENT(aggregate, traversable);
581 :
582 17007 : REGISTER_ITERATOR_INTERFACE(iterator, Iterator);
583 17007 : REGISTER_ITERATOR_IMPLEMENT(iterator, traversable);
584 :
585 17007 : REGISTER_ITERATOR_INTERFACE(arrayaccess, ArrayAccess);
586 :
587 17007 : REGISTER_ITERATOR_INTERFACE(serializable, Serializable)
588 17007 : }
589 : /* }}} */
590 :
591 : /*
592 : * Local variables:
593 : * tab-width: 4
594 : * c-basic-offset: 4
595 : * indent-tabs-mode: t
596 : * End:
597 : */
|