File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / Zend / zend_interfaces.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 20:04:03 2014 UTC (10 years, 4 months ago) by misho
Branches: php, MAIN
CVS tags: v5_4_29, HEAD
php 5.4.29

    1: /*
    2:    +----------------------------------------------------------------------+
    3:    | Zend Engine                                                          |
    4:    +----------------------------------------------------------------------+
    5:    | Copyright (c) 1998-2014 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,v 1.1.1.4 2014/06/15 20:04:03 misho Exp $ */
   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, const 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_invalidate_current */
  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 && !EG(exception)) {
  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>