Back to index

php5  5.3.10
zend_interfaces.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | Zend Engine                                                          |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1998-2012 Zend Technologies Ltd. (http://www.zend.com) |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 2.00 of the Zend license,     |
00008    | that is bundled with this package in the file LICENSE, and is        | 
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.zend.com/license/2_00.txt.                                |
00011    | If you did not receive a copy of the Zend license and are unable to  |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@zend.com so we can mail you a copy immediately.              |
00014    +----------------------------------------------------------------------+
00015    | Authors: Marcus Boerger <helly@php.net>                              |
00016    +----------------------------------------------------------------------+
00017 */
00018 
00019 /* $Id: zend_interfaces.c 321634 2012-01-01 13:15:04Z felipe $ */
00020 
00021 #include "zend.h"
00022 #include "zend_API.h"
00023 #include "zend_interfaces.h"
00024 #include "zend_exceptions.h"
00025 
00026 ZEND_API zend_class_entry *zend_ce_traversable;
00027 ZEND_API zend_class_entry *zend_ce_aggregate;
00028 ZEND_API zend_class_entry *zend_ce_iterator;
00029 ZEND_API zend_class_entry *zend_ce_arrayaccess;
00030 ZEND_API zend_class_entry *zend_ce_serializable;
00031 
00032 /* {{{ zend_call_method
00033  Only returns the returned zval if retval_ptr != NULL */
00034 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)
00035 {
00036        int result;
00037        zend_fcall_info fci;
00038        zval z_fname;
00039        zval *retval;
00040        HashTable *function_table;
00041 
00042        zval **params[2];
00043 
00044        params[0] = &arg1;
00045        params[1] = &arg2;
00046 
00047        fci.size = sizeof(fci);
00048        /*fci.function_table = NULL; will be read form zend_class_entry of object if needed */
00049        fci.object_ptr = object_pp ? *object_pp : NULL;
00050        fci.function_name = &z_fname;
00051        fci.retval_ptr_ptr = retval_ptr_ptr ? retval_ptr_ptr : &retval;
00052        fci.param_count = param_count;
00053        fci.params = params;
00054        fci.no_separation = 1;
00055        fci.symbol_table = NULL;
00056 
00057        if (!fn_proxy && !obj_ce) {
00058               /* no interest in caching and no information already present that is
00059                * needed later inside zend_call_function. */
00060               ZVAL_STRINGL(&z_fname, function_name, function_name_len, 0);
00061               fci.function_table = !object_pp ? EG(function_table) : NULL;
00062               result = zend_call_function(&fci, NULL TSRMLS_CC);
00063        } else {
00064               zend_fcall_info_cache fcic;
00065 
00066               fcic.initialized = 1;
00067               if (!obj_ce) {
00068                      obj_ce = object_pp ? Z_OBJCE_PP(object_pp) : NULL;
00069               }
00070               if (obj_ce) {
00071                      function_table = &obj_ce->function_table;
00072               } else {
00073                      function_table = EG(function_table);
00074               }
00075               if (!fn_proxy || !*fn_proxy) {
00076                      if (zend_hash_find(function_table, function_name, function_name_len+1, (void **) &fcic.function_handler) == FAILURE) {
00077                             /* error at c-level */
00078                             zend_error(E_CORE_ERROR, "Couldn't find implementation for method %s%s%s", obj_ce ? obj_ce->name : "", obj_ce ? "::" : "", function_name);
00079                      }
00080                      if (fn_proxy) {
00081                             *fn_proxy = fcic.function_handler;
00082                      }
00083               } else {
00084                      fcic.function_handler = *fn_proxy;
00085               }
00086               fcic.calling_scope = obj_ce;
00087               if (object_pp) {
00088                      fcic.called_scope = Z_OBJCE_PP(object_pp);
00089               } else if (obj_ce &&
00090                          !(EG(called_scope) &&
00091                            instanceof_function(EG(called_scope), obj_ce TSRMLS_CC))) {
00092                      fcic.called_scope = obj_ce;
00093               } else {
00094                      fcic.called_scope = EG(called_scope);
00095               }
00096               fcic.object_ptr = object_pp ? *object_pp : NULL;
00097               result = zend_call_function(&fci, &fcic TSRMLS_CC);
00098        }
00099        if (result == FAILURE) {
00100               /* error at c-level */
00101               if (!obj_ce) {
00102                      obj_ce = object_pp ? Z_OBJCE_PP(object_pp) : NULL;
00103               }
00104               if (!EG(exception)) {
00105                      zend_error(E_CORE_ERROR, "Couldn't execute method %s%s%s", obj_ce ? obj_ce->name : "", obj_ce ? "::" : "", function_name);
00106               }
00107        }
00108        if (!retval_ptr_ptr) {
00109               if (retval) {
00110                      zval_ptr_dtor(&retval);
00111               }
00112               return NULL;
00113        }
00114        return *retval_ptr_ptr;
00115 }
00116 /* }}} */
00117 
00118 /* iterator interface, c-level functions used by engine */
00119 
00120 /* {{{ zend_user_it_new_iterator */
00121 ZEND_API zval *zend_user_it_new_iterator(zend_class_entry *ce, zval *object TSRMLS_DC)
00122 {
00123        zval *retval;
00124 
00125        return zend_call_method_with_0_params(&object, ce, &ce->iterator_funcs.zf_new_iterator, "getiterator", &retval);
00126 
00127 }
00128 /* }}} */
00129 
00130 /* {{{ zend_user_it_dtor */
00131 ZEND_API void zend_user_it_invalidate_current(zend_object_iterator *_iter TSRMLS_DC)
00132 {
00133        zend_user_iterator *iter = (zend_user_iterator*)_iter;
00134 
00135        if (iter->value) {
00136               zval_ptr_dtor(&iter->value);
00137               iter->value = NULL;
00138        }
00139 }
00140 /* }}} */
00141 
00142 /* {{{ zend_user_it_dtor */
00143 static void zend_user_it_dtor(zend_object_iterator *_iter TSRMLS_DC)
00144 {
00145        zend_user_iterator *iter = (zend_user_iterator*)_iter;
00146        zval *object = (zval*)iter->it.data;
00147 
00148        zend_user_it_invalidate_current(_iter TSRMLS_CC);
00149        zval_ptr_dtor(&object);
00150        efree(iter);
00151 }
00152 /* }}} */
00153 
00154 /* {{{ zend_user_it_valid */
00155 ZEND_API int zend_user_it_valid(zend_object_iterator *_iter TSRMLS_DC)
00156 {
00157        if (_iter) {
00158               zend_user_iterator *iter = (zend_user_iterator*)_iter;
00159               zval *object = (zval*)iter->it.data;
00160               zval *more;
00161               int result;
00162 
00163               zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_valid, "valid", &more);
00164               if (more) {
00165                      result = i_zend_is_true(more);
00166                      zval_ptr_dtor(&more);
00167                      return result ? SUCCESS : FAILURE;
00168               }
00169        }
00170        return FAILURE;
00171 }
00172 /* }}} */
00173 
00174 /* {{{ zend_user_it_get_current_data */
00175 ZEND_API void zend_user_it_get_current_data(zend_object_iterator *_iter, zval ***data TSRMLS_DC)
00176 {
00177        zend_user_iterator *iter = (zend_user_iterator*)_iter;
00178        zval *object = (zval*)iter->it.data;
00179 
00180        if (!iter->value) {
00181               zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_current, "current", &iter->value);
00182        }
00183        *data = &iter->value;
00184 }
00185 /* }}} */
00186 
00187 /* {{{ zend_user_it_get_current_key_default */
00188 #if 0
00189 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)
00190 {
00191        *int_key = _iter->index;
00192        return HASH_KEY_IS_LONG;
00193 }
00194 #endif
00195 /* }}} */
00196 
00197 /* {{{ zend_user_it_get_current_key */
00198 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)
00199 {
00200        zend_user_iterator *iter = (zend_user_iterator*)_iter;
00201        zval *object = (zval*)iter->it.data;
00202        zval *retval;
00203 
00204        zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_key, "key", &retval);
00205 
00206        if (!retval) {
00207               *int_key = 0;
00208               if (!EG(exception))
00209               {
00210                      zend_error(E_WARNING, "Nothing returned from %s::key()", iter->ce->name);
00211               }
00212               return HASH_KEY_IS_LONG;
00213        }
00214        switch (Z_TYPE_P(retval)) {
00215               default:
00216                      zend_error(E_WARNING, "Illegal type returned from %s::key()", iter->ce->name);
00217               case IS_NULL:
00218                      *int_key = 0;
00219                      zval_ptr_dtor(&retval);
00220                      return HASH_KEY_IS_LONG;
00221 
00222               case IS_STRING:
00223                      *str_key = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
00224                      *str_key_len = Z_STRLEN_P(retval)+1;
00225                      zval_ptr_dtor(&retval);
00226                      return HASH_KEY_IS_STRING;
00227 
00228               case IS_DOUBLE:
00229                      *int_key = (long)Z_DVAL_P(retval);
00230                      zval_ptr_dtor(&retval);
00231                      return HASH_KEY_IS_LONG;
00232 
00233               case IS_RESOURCE:
00234               case IS_BOOL:
00235               case IS_LONG:
00236                      *int_key = (long)Z_LVAL_P(retval);
00237                      zval_ptr_dtor(&retval);
00238                      return HASH_KEY_IS_LONG;
00239        }
00240 }
00241 /* }}} */
00242 
00243 /* {{{ zend_user_it_move_forward */
00244 ZEND_API void zend_user_it_move_forward(zend_object_iterator *_iter TSRMLS_DC)
00245 {
00246        zend_user_iterator *iter = (zend_user_iterator*)_iter;
00247        zval *object = (zval*)iter->it.data;
00248 
00249        zend_user_it_invalidate_current(_iter TSRMLS_CC);
00250        zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_next, "next", NULL);
00251 }
00252 /* }}} */
00253 
00254 /* {{{ zend_user_it_rewind */
00255 ZEND_API void zend_user_it_rewind(zend_object_iterator *_iter TSRMLS_DC)
00256 {
00257        zend_user_iterator *iter = (zend_user_iterator*)_iter;
00258        zval *object = (zval*)iter->it.data;
00259 
00260        zend_user_it_invalidate_current(_iter TSRMLS_CC);
00261        zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_rewind, "rewind", NULL);
00262 }
00263 /* }}} */
00264 
00265 zend_object_iterator_funcs zend_interface_iterator_funcs_iterator = {
00266        zend_user_it_dtor,
00267        zend_user_it_valid,
00268        zend_user_it_get_current_data,
00269        zend_user_it_get_current_key,
00270        zend_user_it_move_forward,
00271        zend_user_it_rewind,
00272        zend_user_it_invalidate_current
00273 };
00274 
00275 /* {{{ zend_user_it_get_iterator */
00276 static zend_object_iterator *zend_user_it_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
00277 {
00278        zend_user_iterator *iterator;
00279 
00280        if (by_ref) {
00281               zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
00282        }
00283 
00284        iterator = emalloc(sizeof(zend_user_iterator));
00285 
00286        Z_ADDREF_P(object);
00287        iterator->it.data = (void*)object;
00288        iterator->it.funcs = ce->iterator_funcs.funcs;
00289        iterator->ce = Z_OBJCE_P(object);
00290        iterator->value = NULL;
00291        return (zend_object_iterator*)iterator;
00292 }
00293 /* }}} */
00294 
00295 /* {{{ zend_user_it_get_new_iterator */
00296 ZEND_API zend_object_iterator *zend_user_it_get_new_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
00297 {
00298        zval *iterator = zend_user_it_new_iterator(ce, object TSRMLS_CC);
00299        zend_object_iterator *new_iterator;
00300 
00301        zend_class_entry *ce_it = iterator && Z_TYPE_P(iterator) == IS_OBJECT ? Z_OBJCE_P(iterator) : NULL;
00302 
00303        if (!ce_it || !ce_it->get_iterator || (ce_it->get_iterator == zend_user_it_get_new_iterator && iterator == object)) {
00304               if (!EG(exception)) {
00305                      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);
00306               }
00307               if (iterator) {
00308                      zval_ptr_dtor(&iterator);
00309               }
00310               return NULL;
00311        }
00312 
00313        new_iterator = ce_it->get_iterator(ce_it, iterator, by_ref TSRMLS_CC);
00314        zval_ptr_dtor(&iterator);
00315        return new_iterator;
00316 }
00317 /* }}} */
00318 
00319 /* {{{ zend_implement_traversable */
00320 static int zend_implement_traversable(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
00321 {
00322        /* check that class_type is traversable at c-level or implements at least one of 'aggregate' and 'Iterator' */
00323        zend_uint i;
00324 
00325        if (class_type->get_iterator || (class_type->parent && class_type->parent->get_iterator)) {
00326               return SUCCESS;
00327        }
00328        for (i = 0; i < class_type->num_interfaces; i++) {
00329               if (class_type->interfaces[i] == zend_ce_aggregate || class_type->interfaces[i] == zend_ce_iterator) {
00330                      return SUCCESS;
00331               }
00332        }
00333        zend_error(E_CORE_ERROR, "Class %s must implement interface %s as part of either %s or %s",
00334               class_type->name,
00335               zend_ce_traversable->name,
00336               zend_ce_iterator->name,
00337               zend_ce_aggregate->name);
00338        return FAILURE;
00339 }
00340 /* }}} */
00341 
00342 /* {{{ zend_implement_aggregate */
00343 static int zend_implement_aggregate(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
00344 {
00345        int i, t = -1;
00346 
00347        if (class_type->get_iterator) {
00348               if (class_type->type == ZEND_INTERNAL_CLASS) {
00349                      /* inheritance ensures the class has necessary userland methods */
00350                      return SUCCESS;
00351               } else if (class_type->get_iterator != zend_user_it_get_new_iterator) {
00352                      /* c-level get_iterator cannot be changed (exception being only Traversable is implmented) */
00353                      if (class_type->num_interfaces) {
00354                             for (i = 0; i < class_type->num_interfaces; i++) {
00355                                    if (class_type->interfaces[i] == zend_ce_iterator) {
00356                                           zend_error(E_ERROR, "Class %s cannot implement both %s and %s at the same time",
00357                                                                class_type->name,
00358                                                                interface->name,
00359                                                                zend_ce_iterator->name);
00360                                           return FAILURE;
00361                                    }
00362                                    if (class_type->interfaces[i] == zend_ce_traversable) {
00363                                           t = i;
00364                                    }
00365                             }
00366                      }
00367                      if (t == -1) {
00368                             return FAILURE;
00369                      }
00370               }
00371        }
00372        class_type->iterator_funcs.zf_new_iterator = NULL;
00373        class_type->get_iterator = zend_user_it_get_new_iterator;
00374        return SUCCESS;
00375 }
00376 /* }}} */
00377 
00378 /* {{{ zend_implement_iterator */
00379 static int zend_implement_iterator(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
00380 {
00381        if (class_type->get_iterator && class_type->get_iterator != zend_user_it_get_iterator) {
00382               if (class_type->type == ZEND_INTERNAL_CLASS) {
00383                      /* inheritance ensures the class has the necessary userland methods */
00384                      return SUCCESS;
00385               } else {
00386                      /* c-level get_iterator cannot be changed */
00387                      if (class_type->get_iterator == zend_user_it_get_new_iterator) {
00388                             zend_error(E_ERROR, "Class %s cannot implement both %s and %s at the same time",
00389                                                  class_type->name,
00390                                                  interface->name,
00391                                                  zend_ce_aggregate->name);
00392                      }
00393                      return FAILURE;
00394               }
00395        }
00396        class_type->get_iterator = zend_user_it_get_iterator;
00397        class_type->iterator_funcs.zf_valid = NULL;
00398        class_type->iterator_funcs.zf_current = NULL;
00399        class_type->iterator_funcs.zf_key = NULL;
00400        class_type->iterator_funcs.zf_next = NULL;
00401        class_type->iterator_funcs.zf_rewind = NULL;
00402        if (!class_type->iterator_funcs.funcs) {
00403               class_type->iterator_funcs.funcs = &zend_interface_iterator_funcs_iterator;
00404        }
00405        return SUCCESS;
00406 }
00407 /* }}} */
00408 
00409 /* {{{ zend_implement_arrayaccess */
00410 static int zend_implement_arrayaccess(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
00411 {
00412 #if 0
00413        /* get ht from ce */
00414        if (ht->read_dimension != zend_std_read_dimension
00415        ||  ht->write_dimension != zend_std_write_dimension
00416        ||  ht->has_dimension != zend_std_has_dimension
00417        ||  ht->unset_dimension != zend_std_unset_dimension) {
00418               return FAILURE;
00419        }
00420 #endif
00421        return SUCCESS;
00422 }
00423 /* }}}*/
00424 
00425 /* {{{ zend_user_serialize */
00426 ZEND_API int zend_user_serialize(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC)
00427 {
00428        zend_class_entry * ce = Z_OBJCE_P(object);
00429        zval *retval;
00430        int result;
00431 
00432        zend_call_method_with_0_params(&object, ce, &ce->serialize_func, "serialize", &retval);
00433 
00434 
00435        if (!retval || EG(exception)) {
00436               result = FAILURE;
00437        } else {
00438               switch(Z_TYPE_P(retval)) {
00439               case IS_NULL:
00440                      /* we could also make this '*buf_len = 0' but this allows to skip variables */
00441                      zval_ptr_dtor(&retval);
00442                      return FAILURE;
00443               case IS_STRING:
00444                      *buffer = (unsigned char*)estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
00445                      *buf_len = Z_STRLEN_P(retval);
00446                      result = SUCCESS;
00447                      break;
00448               default: /* failure */
00449                      result = FAILURE;
00450                      break;
00451               }
00452               zval_ptr_dtor(&retval);
00453        }
00454 
00455        if (result == FAILURE) {
00456               zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "%s::serialize() must return a string or NULL", ce->name);
00457        }
00458        return result;
00459 }
00460 /* }}} */
00461 
00462 /* {{{ zend_user_unserialize */
00463 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)
00464 {
00465        zval * zdata;
00466 
00467        object_init_ex(*object, ce);
00468 
00469        MAKE_STD_ZVAL(zdata);
00470        ZVAL_STRINGL(zdata, (char*)buf, buf_len, 1);
00471 
00472        zend_call_method_with_1_params(object, ce, &ce->unserialize_func, "unserialize", NULL, zdata);
00473 
00474        zval_ptr_dtor(&zdata);
00475 
00476        if (EG(exception)) {
00477               return FAILURE;
00478        } else {
00479               return SUCCESS;
00480        }
00481 }
00482 /* }}} */
00483 
00484 ZEND_API int zend_class_serialize_deny(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC) /* {{{ */
00485 {
00486        zend_class_entry *ce = Z_OBJCE_P(object);
00487        zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Serialization of '%s' is not allowed", ce->name);
00488        return FAILURE;
00489 }
00490 /* }}} */
00491 
00492 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) /* {{{ */
00493 {
00494        zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Unserialization of '%s' is not allowed", ce->name);
00495        return FAILURE;
00496 }
00497 /* }}} */
00498 
00499 /* {{{ zend_implement_serializable */
00500 static int zend_implement_serializable(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
00501 {
00502        if (class_type->parent
00503               && (class_type->parent->serialize || class_type->parent->unserialize)
00504               && !instanceof_function_ex(class_type->parent, zend_ce_serializable, 1 TSRMLS_CC)) {
00505               return FAILURE;
00506        }
00507        if (!class_type->serialize) {
00508               class_type->serialize = zend_user_serialize;
00509        }
00510        if (!class_type->unserialize) {
00511               class_type->unserialize = zend_user_unserialize;
00512        }
00513        return SUCCESS;
00514 }
00515 /* }}}*/
00516 
00517 /* {{{ function tables */
00518 const zend_function_entry zend_funcs_aggregate[] = {
00519        ZEND_ABSTRACT_ME(iterator, getIterator, NULL)
00520        {NULL, NULL, NULL}
00521 };
00522 
00523 const zend_function_entry zend_funcs_iterator[] = {
00524        ZEND_ABSTRACT_ME(iterator, current,  NULL)
00525        ZEND_ABSTRACT_ME(iterator, next,     NULL)
00526        ZEND_ABSTRACT_ME(iterator, key,      NULL)
00527        ZEND_ABSTRACT_ME(iterator, valid,    NULL)
00528        ZEND_ABSTRACT_ME(iterator, rewind,   NULL)
00529        {NULL, NULL, NULL}
00530 };
00531 
00532 const zend_function_entry *zend_funcs_traversable    = NULL;
00533 
00534 ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offset, 0, 0, 1)
00535        ZEND_ARG_INFO(0, offset)
00536 ZEND_END_ARG_INFO()
00537 
00538 ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offset_get, 0, 0, 1) /* actually this should be return by ref but atm cannot be */
00539        ZEND_ARG_INFO(0, offset)
00540 ZEND_END_ARG_INFO()
00541 
00542 ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offset_value, 0, 0, 2)
00543        ZEND_ARG_INFO(0, offset)
00544        ZEND_ARG_INFO(0, value)
00545 ZEND_END_ARG_INFO()
00546 
00547 const zend_function_entry zend_funcs_arrayaccess[] = {
00548        ZEND_ABSTRACT_ME(arrayaccess, offsetExists, arginfo_arrayaccess_offset)
00549        ZEND_ABSTRACT_ME(arrayaccess, offsetGet,    arginfo_arrayaccess_offset_get)
00550        ZEND_ABSTRACT_ME(arrayaccess, offsetSet,    arginfo_arrayaccess_offset_value)
00551        ZEND_ABSTRACT_ME(arrayaccess, offsetUnset,  arginfo_arrayaccess_offset)
00552        {NULL, NULL, NULL}
00553 };
00554 
00555 ZEND_BEGIN_ARG_INFO(arginfo_serializable_serialize, 0)
00556        ZEND_ARG_INFO(0, serialized)
00557 ZEND_END_ARG_INFO()
00558 
00559 const zend_function_entry zend_funcs_serializable[] = {
00560        ZEND_ABSTRACT_ME(serializable, serialize,   NULL)
00561        ZEND_FENTRY(unserialize, NULL, arginfo_serializable_serialize, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT|ZEND_ACC_CTOR)
00562        {NULL, NULL, NULL}
00563 };
00564 /* }}} */
00565 
00566 #define REGISTER_ITERATOR_INTERFACE(class_name, class_name_str) \
00567        {\
00568               zend_class_entry ce;\
00569               INIT_CLASS_ENTRY(ce, # class_name_str, zend_funcs_ ## class_name) \
00570               zend_ce_ ## class_name = zend_register_internal_interface(&ce TSRMLS_CC);\
00571               zend_ce_ ## class_name->interface_gets_implemented = zend_implement_ ## class_name;\
00572        }
00573 
00574 #define REGISTER_ITERATOR_IMPLEMENT(class_name, interface_name) \
00575        zend_class_implements(zend_ce_ ## class_name TSRMLS_CC, 1, zend_ce_ ## interface_name)
00576 
00577 /* {{{ zend_register_interfaces */
00578 ZEND_API void zend_register_interfaces(TSRMLS_D)
00579 {
00580        REGISTER_ITERATOR_INTERFACE(traversable, Traversable);
00581 
00582        REGISTER_ITERATOR_INTERFACE(aggregate, IteratorAggregate);
00583        REGISTER_ITERATOR_IMPLEMENT(aggregate, traversable);
00584 
00585        REGISTER_ITERATOR_INTERFACE(iterator, Iterator);
00586        REGISTER_ITERATOR_IMPLEMENT(iterator, traversable);
00587 
00588        REGISTER_ITERATOR_INTERFACE(arrayaccess, ArrayAccess);
00589 
00590        REGISTER_ITERATOR_INTERFACE(serializable, Serializable)
00591 }
00592 /* }}} */
00593 
00594 /*
00595  * Local variables:
00596  * tab-width: 4
00597  * c-basic-offset: 4
00598  * indent-tabs-mode: t
00599  * End:
00600  */