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