Annotation of embedaddon/php/Zend/zend_interfaces.c, revision 1.1
1.1 ! misho 1: /*
! 2: +----------------------------------------------------------------------+
! 3: | Zend Engine |
! 4: +----------------------------------------------------------------------+
! 5: | Copyright (c) 1998-2012 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 321634 2012-01-01 13:15:04Z 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_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: {
! 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: params[0] = &arg1;
! 45: params[1] = &arg2;
! 46:
! 47: fci.size = sizeof(fci);
! 48: /*fci.function_table = NULL; will be read form zend_class_entry of object if needed */
! 49: fci.object_ptr = object_pp ? *object_pp : NULL;
! 50: fci.function_name = &z_fname;
! 51: fci.retval_ptr_ptr = retval_ptr_ptr ? retval_ptr_ptr : &retval;
! 52: fci.param_count = param_count;
! 53: fci.params = params;
! 54: fci.no_separation = 1;
! 55: fci.symbol_table = NULL;
! 56:
! 57: 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: ZVAL_STRINGL(&z_fname, function_name, function_name_len, 0);
! 61: fci.function_table = !object_pp ? EG(function_table) : NULL;
! 62: result = zend_call_function(&fci, NULL TSRMLS_CC);
! 63: } else {
! 64: zend_fcall_info_cache fcic;
! 65:
! 66: fcic.initialized = 1;
! 67: if (!obj_ce) {
! 68: obj_ce = object_pp ? Z_OBJCE_PP(object_pp) : NULL;
! 69: }
! 70: if (obj_ce) {
! 71: function_table = &obj_ce->function_table;
! 72: } else {
! 73: function_table = EG(function_table);
! 74: }
! 75: if (!fn_proxy || !*fn_proxy) {
! 76: if (zend_hash_find(function_table, function_name, function_name_len+1, (void **) &fcic.function_handler) == FAILURE) {
! 77: /* error at c-level */
! 78: 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: if (fn_proxy) {
! 81: *fn_proxy = fcic.function_handler;
! 82: }
! 83: } else {
! 84: fcic.function_handler = *fn_proxy;
! 85: }
! 86: fcic.calling_scope = obj_ce;
! 87: if (object_pp) {
! 88: fcic.called_scope = Z_OBJCE_PP(object_pp);
! 89: } else if (obj_ce &&
! 90: !(EG(called_scope) &&
! 91: instanceof_function(EG(called_scope), obj_ce TSRMLS_CC))) {
! 92: fcic.called_scope = obj_ce;
! 93: } else {
! 94: fcic.called_scope = EG(called_scope);
! 95: }
! 96: fcic.object_ptr = object_pp ? *object_pp : NULL;
! 97: result = zend_call_function(&fci, &fcic TSRMLS_CC);
! 98: }
! 99: if (result == FAILURE) {
! 100: /* error at c-level */
! 101: if (!obj_ce) {
! 102: obj_ce = object_pp ? Z_OBJCE_PP(object_pp) : NULL;
! 103: }
! 104: if (!EG(exception)) {
! 105: zend_error(E_CORE_ERROR, "Couldn't execute method %s%s%s", obj_ce ? obj_ce->name : "", obj_ce ? "::" : "", function_name);
! 106: }
! 107: }
! 108: if (!retval_ptr_ptr) {
! 109: if (retval) {
! 110: zval_ptr_dtor(&retval);
! 111: }
! 112: return NULL;
! 113: }
! 114: 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: {
! 123: zval *retval;
! 124:
! 125: 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: {
! 133: zend_user_iterator *iter = (zend_user_iterator*)_iter;
! 134:
! 135: if (iter->value) {
! 136: zval_ptr_dtor(&iter->value);
! 137: iter->value = NULL;
! 138: }
! 139: }
! 140: /* }}} */
! 141:
! 142: /* {{{ zend_user_it_dtor */
! 143: static void zend_user_it_dtor(zend_object_iterator *_iter TSRMLS_DC)
! 144: {
! 145: zend_user_iterator *iter = (zend_user_iterator*)_iter;
! 146: zval *object = (zval*)iter->it.data;
! 147:
! 148: zend_user_it_invalidate_current(_iter TSRMLS_CC);
! 149: zval_ptr_dtor(&object);
! 150: efree(iter);
! 151: }
! 152: /* }}} */
! 153:
! 154: /* {{{ zend_user_it_valid */
! 155: ZEND_API int zend_user_it_valid(zend_object_iterator *_iter TSRMLS_DC)
! 156: {
! 157: if (_iter) {
! 158: zend_user_iterator *iter = (zend_user_iterator*)_iter;
! 159: zval *object = (zval*)iter->it.data;
! 160: zval *more;
! 161: int result;
! 162:
! 163: zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_valid, "valid", &more);
! 164: if (more) {
! 165: result = i_zend_is_true(more);
! 166: zval_ptr_dtor(&more);
! 167: return result ? SUCCESS : FAILURE;
! 168: }
! 169: }
! 170: 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: {
! 177: zend_user_iterator *iter = (zend_user_iterator*)_iter;
! 178: zval *object = (zval*)iter->it.data;
! 179:
! 180: if (!iter->value) {
! 181: zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_current, "current", &iter->value);
! 182: }
! 183: *data = &iter->value;
! 184: }
! 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: {
! 200: zend_user_iterator *iter = (zend_user_iterator*)_iter;
! 201: zval *object = (zval*)iter->it.data;
! 202: zval *retval;
! 203:
! 204: zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_key, "key", &retval);
! 205:
! 206: if (!retval) {
! 207: *int_key = 0;
! 208: if (!EG(exception))
! 209: {
! 210: zend_error(E_WARNING, "Nothing returned from %s::key()", iter->ce->name);
! 211: }
! 212: return HASH_KEY_IS_LONG;
! 213: }
! 214: switch (Z_TYPE_P(retval)) {
! 215: default:
! 216: zend_error(E_WARNING, "Illegal type returned from %s::key()", iter->ce->name);
! 217: case IS_NULL:
! 218: *int_key = 0;
! 219: zval_ptr_dtor(&retval);
! 220: return HASH_KEY_IS_LONG;
! 221:
! 222: case IS_STRING:
! 223: *str_key = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
! 224: *str_key_len = Z_STRLEN_P(retval)+1;
! 225: zval_ptr_dtor(&retval);
! 226: return HASH_KEY_IS_STRING;
! 227:
! 228: case IS_DOUBLE:
! 229: *int_key = (long)Z_DVAL_P(retval);
! 230: zval_ptr_dtor(&retval);
! 231: return HASH_KEY_IS_LONG;
! 232:
! 233: case IS_RESOURCE:
! 234: case IS_BOOL:
! 235: case IS_LONG:
! 236: *int_key = (long)Z_LVAL_P(retval);
! 237: zval_ptr_dtor(&retval);
! 238: 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: {
! 246: zend_user_iterator *iter = (zend_user_iterator*)_iter;
! 247: zval *object = (zval*)iter->it.data;
! 248:
! 249: zend_user_it_invalidate_current(_iter TSRMLS_CC);
! 250: zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_next, "next", NULL);
! 251: }
! 252: /* }}} */
! 253:
! 254: /* {{{ zend_user_it_rewind */
! 255: ZEND_API void zend_user_it_rewind(zend_object_iterator *_iter TSRMLS_DC)
! 256: {
! 257: zend_user_iterator *iter = (zend_user_iterator*)_iter;
! 258: zval *object = (zval*)iter->it.data;
! 259:
! 260: zend_user_it_invalidate_current(_iter TSRMLS_CC);
! 261: zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_rewind, "rewind", NULL);
! 262: }
! 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: {
! 278: zend_user_iterator *iterator;
! 279:
! 280: if (by_ref) {
! 281: zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
! 282: }
! 283:
! 284: iterator = emalloc(sizeof(zend_user_iterator));
! 285:
! 286: Z_ADDREF_P(object);
! 287: iterator->it.data = (void*)object;
! 288: iterator->it.funcs = ce->iterator_funcs.funcs;
! 289: iterator->ce = Z_OBJCE_P(object);
! 290: iterator->value = NULL;
! 291: 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: {
! 298: zval *iterator = zend_user_it_new_iterator(ce, object TSRMLS_CC);
! 299: zend_object_iterator *new_iterator;
! 300:
! 301: zend_class_entry *ce_it = iterator && Z_TYPE_P(iterator) == IS_OBJECT ? Z_OBJCE_P(iterator) : NULL;
! 302:
! 303: if (!ce_it || !ce_it->get_iterator || (ce_it->get_iterator == zend_user_it_get_new_iterator && iterator == object)) {
! 304: if (!EG(exception)) {
! 305: 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: if (iterator) {
! 308: zval_ptr_dtor(&iterator);
! 309: }
! 310: return NULL;
! 311: }
! 312:
! 313: new_iterator = ce_it->get_iterator(ce_it, iterator, by_ref TSRMLS_CC);
! 314: zval_ptr_dtor(&iterator);
! 315: 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: {
! 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: if (class_type->get_iterator || (class_type->parent && class_type->parent->get_iterator)) {
! 326: return SUCCESS;
! 327: }
! 328: for (i = 0; i < class_type->num_interfaces; i++) {
! 329: if (class_type->interfaces[i] == zend_ce_aggregate || class_type->interfaces[i] == zend_ce_iterator) {
! 330: return SUCCESS;
! 331: }
! 332: }
! 333: 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: 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: {
! 345: int i, t = -1;
! 346:
! 347: if (class_type->get_iterator) {
! 348: if (class_type->type == ZEND_INTERNAL_CLASS) {
! 349: /* inheritance ensures the class has necessary userland methods */
! 350: return SUCCESS;
! 351: } 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: if (class_type->num_interfaces) {
! 354: for (i = 0; i < class_type->num_interfaces; i++) {
! 355: if (class_type->interfaces[i] == zend_ce_iterator) {
! 356: zend_error(E_ERROR, "Class %s cannot implement both %s and %s at the same time",
! 357: class_type->name,
! 358: interface->name,
! 359: zend_ce_iterator->name);
! 360: return FAILURE;
! 361: }
! 362: if (class_type->interfaces[i] == zend_ce_traversable) {
! 363: t = i;
! 364: }
! 365: }
! 366: }
! 367: if (t == -1) {
! 368: return FAILURE;
! 369: }
! 370: }
! 371: }
! 372: class_type->iterator_funcs.zf_new_iterator = NULL;
! 373: class_type->get_iterator = zend_user_it_get_new_iterator;
! 374: return SUCCESS;
! 375: }
! 376: /* }}} */
! 377:
! 378: /* {{{ zend_implement_iterator */
! 379: static int zend_implement_iterator(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
! 380: {
! 381: if (class_type->get_iterator && class_type->get_iterator != zend_user_it_get_iterator) {
! 382: if (class_type->type == ZEND_INTERNAL_CLASS) {
! 383: /* inheritance ensures the class has the necessary userland methods */
! 384: return SUCCESS;
! 385: } else {
! 386: /* c-level get_iterator cannot be changed */
! 387: if (class_type->get_iterator == zend_user_it_get_new_iterator) {
! 388: zend_error(E_ERROR, "Class %s cannot implement both %s and %s at the same time",
! 389: class_type->name,
! 390: interface->name,
! 391: zend_ce_aggregate->name);
! 392: }
! 393: return FAILURE;
! 394: }
! 395: }
! 396: class_type->get_iterator = zend_user_it_get_iterator;
! 397: class_type->iterator_funcs.zf_valid = NULL;
! 398: class_type->iterator_funcs.zf_current = NULL;
! 399: class_type->iterator_funcs.zf_key = NULL;
! 400: class_type->iterator_funcs.zf_next = NULL;
! 401: class_type->iterator_funcs.zf_rewind = NULL;
! 402: if (!class_type->iterator_funcs.funcs) {
! 403: class_type->iterator_funcs.funcs = &zend_interface_iterator_funcs_iterator;
! 404: }
! 405: return SUCCESS;
! 406: }
! 407: /* }}} */
! 408:
! 409: /* {{{ zend_implement_arrayaccess */
! 410: static int zend_implement_arrayaccess(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
! 411: {
! 412: #if 0
! 413: /* get ht from ce */
! 414: if (ht->read_dimension != zend_std_read_dimension
! 415: || ht->write_dimension != zend_std_write_dimension
! 416: || ht->has_dimension != zend_std_has_dimension
! 417: || ht->unset_dimension != zend_std_unset_dimension) {
! 418: return FAILURE;
! 419: }
! 420: #endif
! 421: return SUCCESS;
! 422: }
! 423: /* }}}*/
! 424:
! 425: /* {{{ zend_user_serialize */
! 426: ZEND_API int zend_user_serialize(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC)
! 427: {
! 428: zend_class_entry * ce = Z_OBJCE_P(object);
! 429: zval *retval;
! 430: int result;
! 431:
! 432: zend_call_method_with_0_params(&object, ce, &ce->serialize_func, "serialize", &retval);
! 433:
! 434:
! 435: if (!retval || EG(exception)) {
! 436: result = FAILURE;
! 437: } else {
! 438: switch(Z_TYPE_P(retval)) {
! 439: case IS_NULL:
! 440: /* we could also make this '*buf_len = 0' but this allows to skip variables */
! 441: zval_ptr_dtor(&retval);
! 442: return FAILURE;
! 443: case IS_STRING:
! 444: *buffer = (unsigned char*)estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
! 445: *buf_len = Z_STRLEN_P(retval);
! 446: result = SUCCESS;
! 447: break;
! 448: default: /* failure */
! 449: result = FAILURE;
! 450: break;
! 451: }
! 452: zval_ptr_dtor(&retval);
! 453: }
! 454:
! 455: if (result == FAILURE) {
! 456: zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "%s::serialize() must return a string or NULL", ce->name);
! 457: }
! 458: return result;
! 459: }
! 460: /* }}} */
! 461:
! 462: /* {{{ zend_user_unserialize */
! 463: 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)
! 464: {
! 465: zval * zdata;
! 466:
! 467: object_init_ex(*object, ce);
! 468:
! 469: MAKE_STD_ZVAL(zdata);
! 470: ZVAL_STRINGL(zdata, (char*)buf, buf_len, 1);
! 471:
! 472: zend_call_method_with_1_params(object, ce, &ce->unserialize_func, "unserialize", NULL, zdata);
! 473:
! 474: zval_ptr_dtor(&zdata);
! 475:
! 476: if (EG(exception)) {
! 477: return FAILURE;
! 478: } else {
! 479: return SUCCESS;
! 480: }
! 481: }
! 482: /* }}} */
! 483:
! 484: ZEND_API int zend_class_serialize_deny(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC) /* {{{ */
! 485: {
! 486: zend_class_entry *ce = Z_OBJCE_P(object);
! 487: zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Serialization of '%s' is not allowed", ce->name);
! 488: return FAILURE;
! 489: }
! 490: /* }}} */
! 491:
! 492: 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) /* {{{ */
! 493: {
! 494: zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Unserialization of '%s' is not allowed", ce->name);
! 495: return FAILURE;
! 496: }
! 497: /* }}} */
! 498:
! 499: /* {{{ zend_implement_serializable */
! 500: static int zend_implement_serializable(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
! 501: {
! 502: if (class_type->parent
! 503: && (class_type->parent->serialize || class_type->parent->unserialize)
! 504: && !instanceof_function_ex(class_type->parent, zend_ce_serializable, 1 TSRMLS_CC)) {
! 505: return FAILURE;
! 506: }
! 507: if (!class_type->serialize) {
! 508: class_type->serialize = zend_user_serialize;
! 509: }
! 510: if (!class_type->unserialize) {
! 511: class_type->unserialize = zend_user_unserialize;
! 512: }
! 513: return SUCCESS;
! 514: }
! 515: /* }}}*/
! 516:
! 517: /* {{{ function tables */
! 518: const zend_function_entry zend_funcs_aggregate[] = {
! 519: ZEND_ABSTRACT_ME(iterator, getIterator, NULL)
! 520: {NULL, NULL, NULL}
! 521: };
! 522:
! 523: const zend_function_entry zend_funcs_iterator[] = {
! 524: ZEND_ABSTRACT_ME(iterator, current, NULL)
! 525: ZEND_ABSTRACT_ME(iterator, next, NULL)
! 526: ZEND_ABSTRACT_ME(iterator, key, NULL)
! 527: ZEND_ABSTRACT_ME(iterator, valid, NULL)
! 528: ZEND_ABSTRACT_ME(iterator, rewind, NULL)
! 529: {NULL, NULL, NULL}
! 530: };
! 531:
! 532: const zend_function_entry *zend_funcs_traversable = NULL;
! 533:
! 534: ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offset, 0, 0, 1)
! 535: ZEND_ARG_INFO(0, offset)
! 536: ZEND_END_ARG_INFO()
! 537:
! 538: ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offset_get, 0, 0, 1) /* actually this should be return by ref but atm cannot be */
! 539: ZEND_ARG_INFO(0, offset)
! 540: ZEND_END_ARG_INFO()
! 541:
! 542: ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offset_value, 0, 0, 2)
! 543: ZEND_ARG_INFO(0, offset)
! 544: ZEND_ARG_INFO(0, value)
! 545: ZEND_END_ARG_INFO()
! 546:
! 547: const zend_function_entry zend_funcs_arrayaccess[] = {
! 548: ZEND_ABSTRACT_ME(arrayaccess, offsetExists, arginfo_arrayaccess_offset)
! 549: ZEND_ABSTRACT_ME(arrayaccess, offsetGet, arginfo_arrayaccess_offset_get)
! 550: ZEND_ABSTRACT_ME(arrayaccess, offsetSet, arginfo_arrayaccess_offset_value)
! 551: ZEND_ABSTRACT_ME(arrayaccess, offsetUnset, arginfo_arrayaccess_offset)
! 552: {NULL, NULL, NULL}
! 553: };
! 554:
! 555: ZEND_BEGIN_ARG_INFO(arginfo_serializable_serialize, 0)
! 556: ZEND_ARG_INFO(0, serialized)
! 557: ZEND_END_ARG_INFO()
! 558:
! 559: const zend_function_entry zend_funcs_serializable[] = {
! 560: ZEND_ABSTRACT_ME(serializable, serialize, NULL)
! 561: ZEND_FENTRY(unserialize, NULL, arginfo_serializable_serialize, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT|ZEND_ACC_CTOR)
! 562: {NULL, NULL, NULL}
! 563: };
! 564: /* }}} */
! 565:
! 566: #define REGISTER_ITERATOR_INTERFACE(class_name, class_name_str) \
! 567: {\
! 568: zend_class_entry ce;\
! 569: INIT_CLASS_ENTRY(ce, # class_name_str, zend_funcs_ ## class_name) \
! 570: zend_ce_ ## class_name = zend_register_internal_interface(&ce TSRMLS_CC);\
! 571: zend_ce_ ## class_name->interface_gets_implemented = zend_implement_ ## class_name;\
! 572: }
! 573:
! 574: #define REGISTER_ITERATOR_IMPLEMENT(class_name, interface_name) \
! 575: zend_class_implements(zend_ce_ ## class_name TSRMLS_CC, 1, zend_ce_ ## interface_name)
! 576:
! 577: /* {{{ zend_register_interfaces */
! 578: ZEND_API void zend_register_interfaces(TSRMLS_D)
! 579: {
! 580: REGISTER_ITERATOR_INTERFACE(traversable, Traversable);
! 581:
! 582: REGISTER_ITERATOR_INTERFACE(aggregate, IteratorAggregate);
! 583: REGISTER_ITERATOR_IMPLEMENT(aggregate, traversable);
! 584:
! 585: REGISTER_ITERATOR_INTERFACE(iterator, Iterator);
! 586: REGISTER_ITERATOR_IMPLEMENT(iterator, traversable);
! 587:
! 588: REGISTER_ITERATOR_INTERFACE(arrayaccess, ArrayAccess);
! 589:
! 590: REGISTER_ITERATOR_INTERFACE(serializable, Serializable)
! 591: }
! 592: /* }}} */
! 593:
! 594: /*
! 595: * Local variables:
! 596: * tab-width: 4
! 597: * c-basic-offset: 4
! 598: * indent-tabs-mode: t
! 599: * End:
! 600: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>