cvs: spl / README spl_array.c spl_engine.c spl_engine.h spl_foreach.c spl_functions.c /tests foreach.phpt

From: Date: Sat, 24 May 2003 13:47:49 +0000
Subject: cvs: spl / README spl_array.c spl_engine.c spl_engine.h spl_foreach.c spl_functions.c /tests foreach.phpt
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-21243@lists.php.net to get a copy of this message
helly Sat May 24 09:47:49 2003 EDT Modified files: /spl README spl_array.c spl_engine.c spl_engine.h spl_foreach.c spl_functions.c /spl/tests foreach.phpt Log: Fixes and optimizations

Index: spl/README diff -u spl/README:1.1 spl/README:1.2 --- spl/README:1.1 Thu May 1 23:09:58 2003 +++ spl/README Sat May 24 09:47:49 2003 @@ -1,4 +1,3 @@ -<pre> This is an extension that aims to implement some efficient data access interfaces and classes. @@ -35,5 +34,3 @@ be the best case. And 4) also enables the foreach trick. To implement 3) and 4) with other db extensions ask me and wait for LT to pass. - -</pre> \ No newline at end of file Index: spl/spl_array.c diff -u spl/spl_array.c:1.1.1.1 spl/spl_array.c:1.2 --- spl/spl_array.c:1.1.1.1 Thu May 1 19:28:28 2003 +++ spl/spl_array.c Sat May 24 09:47:49 2003 @@ -119,13 +119,10 @@ /* {{{ spl_array_writer_default_set */ void spl_array_writer_default_set(zval *object, zval *newval, zval **retval TSRMLS_DC) { - zval *obj, *idx; spl_array_writer_object *writer; writer = (spl_array_writer_object *) zend_object_store_get_object(object TSRMLS_CC); - obj = writer->obj; - idx = writer->idx; - spl_begin_method_call_arg_ex2(&obj, "set", retval, &idx, &newval, 0, NULL TSRMLS_CC); + spl_begin_method_call_arg_ex2(&writer->obj, NULL, "set", sizeof("set")-1, retval, writer->idx, newval TSRMLS_CC); } /* }}} */ @@ -172,7 +169,7 @@ zval *exists; /*ALLOC_ZVAL(exists); not needed */ - spl_begin_method_call_arg_ex1(container_ptr, "exists", &exists, &dim, 0, NULL TSRMLS_CC); + spl_begin_method_call_arg_ex1(container_ptr, NULL, "exists", sizeof("exists")-1, &exists, dim TSRMLS_CC); if (!i_zend_is_true(exists)) { if (type == BP_VAR_R || type == BP_VAR_RW) { SEPARATE_ZVAL(&dim); @@ -191,13 +188,13 @@ } DELETE_RET_ZVAL(exists); if (type == BP_VAR_R || type == BP_VAR_IS) { - spl_begin_method_call_arg_ex1(container_ptr, "get", retval, &dim, 0, NULL TSRMLS_CC); + spl_begin_method_call_arg_ex1(container_ptr, NULL, "get", sizeof("get")-1, retval, dim TSRMLS_CC); (*retval)->refcount--; } else #ifdef SPL_ARRAY_WRITE if (spl_is_instance_of(container_ptr, spl_ce_array_access_ex TSRMLS_CC)) { /* array_access_ex instaces have their own way of creating an access_writer */ - spl_begin_method_call_arg_ex1(container_ptr, "new_writer", retval, &dim, 0, NULL TSRMLS_CC); + spl_begin_method_call_arg_ex1(container_ptr, NULL, "new_writer", sizeof("new_writer")-1, retval, dim TSRMLS_CC); T(result->u.var).var.ptr = *retval; AI_PTR_2_PTR_PTR(T(result->u.var).var); SELECTIVE_PZVAL_LOCK(*retval, result); @@ -217,7 +214,7 @@ } SELECTIVE_PZVAL_LOCK(*retval, result); #else - zend_error(E_ERROR, "SPL compiled withut array write hook"); + zend_error(E_ERROR, "SPL compiled without array write hook"); #endif FREE_OP(Ts, op2, EG(free_op2)); return 0; @@ -294,7 +291,7 @@ spl_array_writer_default_set(*writer, newval, &retval TSRMLS_CC); } else if (spl_is_instance_of(writer, spl_ce_array_writer TSRMLS_CC)) { newval = spl_get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2) TSRMLS_CC); - spl_begin_method_call_arg_ex1(writer, "set", &retval, &newval, 0, NULL TSRMLS_CC); + spl_begin_method_call_arg_ex1(writer, NULL, "set", sizeof("set")-1, &retval, newval TSRMLS_CC); } else { ZEND_EXECUTE_HOOK_ORIGINAL(ZEND_ASSIGN); } Index: spl/spl_engine.c diff -u spl/spl_engine.c:1.2 spl/spl_engine.c:1.3 --- spl/spl_engine.c:1.2 Fri May 2 11:39:12 2003 +++ spl/spl_engine.c Sat May 24 09:47:49 2003 @@ -30,57 +30,6 @@ #include "spl_functions.h" #include "spl_engine.h" -/* {{{ spl_begin_method_call_arg */ -int spl_begin_method_call_arg(zval **ce, char *function_name, zval *retval, zval *arg1 TSRMLS_DC) -{ - zval *args[1]; - zval fn_name; - - ZVAL_STRING(&fn_name, function_name, 0); - - args[0] = arg1; - return call_user_function(&Z_OBJCE_PP(ce)->function_table, ce, &fn_name, retval, 1, args TSRMLS_CC); -} -/* }}} */ - -/* {{{ spl_begin_method_call_this */ -int spl_begin_method_call_this(zval **ce, char *function_name, zval *retval TSRMLS_DC) -{ - zval fn_name; - - ZVAL_STRING(&fn_name, function_name, 0); - - return call_user_function(&Z_OBJCE_PP(ce)->function_table, ce, &fn_name, retval, 0, NULL TSRMLS_CC); -} -/* }}} */ - -/* {{{ spl_begin_method_call_arg_ex1 */ -int spl_begin_method_call_arg_ex1(zval **ce, char *function_name, zval **retval, zval **arg1, int no_separation, HashTable *symbol_table TSRMLS_DC) -{ - zval **args[1]; - zval fn_name; - - ZVAL_STRING(&fn_name, function_name, 0); - - args[0] = arg1; - return call_user_function_ex(&Z_OBJCE_PP(ce)->function_table, ce, &fn_name, retval, 1, args, no_separation, symbol_table TSRMLS_CC); -} -/* }}} */ - -/* {{{ spl_begin_method_call_arg_ex2 */ -int spl_begin_method_call_arg_ex2(zval **ce, char *function_name, zval **retval, zval **arg1, zval **arg2, int no_separation, HashTable *symbol_table TSRMLS_DC) -{ - zval **args[2]; - zval fn_name; - - ZVAL_STRING(&fn_name, function_name, 0); - - args[0] = arg1; - args[1] = arg2; - return call_user_function_ex(&Z_OBJCE_PP(ce)->function_table, ce, &fn_name, retval, 2, args, no_separation, symbol_table TSRMLS_CC); -} -/* }}} */ - /* {{{ spl_instanciate */ void spl_instanciate(zend_class_entry *pce, zval **object TSRMLS_DC) { @@ -92,21 +41,15 @@ /* }}} */ /* {{{ spl_instanciate_arg_ex2 */ -int spl_instanciate_arg_ex2(zend_class_entry *pce, zval **retval, zval **arg1, zval **arg2, int no_separation, HashTable *symbol_table TSRMLS_DC) +int spl_instanciate_arg_ex2(zend_class_entry *pce, zval **retval, zval *arg1, zval *arg2, HashTable *symbol_table TSRMLS_DC) { - zval **args[2]; - zval fn_name; zval *object; spl_instanciate(pce, &object TSRMLS_CC); retval = &EG(uninitialized_zval_ptr); - ZVAL_STRING(&fn_name, pce->constructor->common.function_name, 0); - - args[0] = arg1; - args[1] = arg2; - call_user_function_ex(&pce->function_table, &object, &fn_name, retval, 2, args, no_separation, symbol_table TSRMLS_CC); + spl_call_method(&object, NULL, pce->constructor->common.function_name, strlen(pce->constructor->common.function_name), retval, NULL TSRMLS_CC, 2, arg1, arg2); *retval = object; return 0; } @@ -240,6 +183,167 @@ } } return spl_is_instance_of(obj, ce TSRMLS_CC); +} +/* }}} */ + +#undef EX +#define EX(element) execute_data.element + +/* {{{ spl_call_method */ +int spl_call_method(zval **object_pp, zend_function **fn_proxy, char *function_name, int fname_len, zval **retval, HashTable *symbol_table TSRMLS_DC, int param_count, ...) +{ + int i; + zval **original_return_value; + HashTable *calling_symbol_table; + zend_function_state *original_function_state_ptr; + zend_op_array *original_op_array; + zend_op **original_opline_ptr; + zval *orig_free_op1, *orig_free_op2; + int (*orig_unary_op)(zval *result, zval *op1); + int (*orig_binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC); + zend_class_entry *current_scope; + zend_class_entry *calling_scope = NULL; + zval *current_this; + zend_namespace *current_namespace = EG(active_namespace); + zend_execute_data execute_data; + zend_class_entry *obj_ce; + va_list args; + + if (!object_pp || (obj_ce = spl_get_class_entry(*object_pp TSRMLS_CC)) == NULL) { + return FAILURE; + } + + /* Initialize execute_data */ + EX(fbc) = NULL; + EX(Ts) = NULL; + EX(op_array) = NULL; + EX(opline) = NULL; + + EX(object) = *object_pp; + calling_scope = Z_OBJCE_PP(object_pp); + + original_function_state_ptr = EG(function_state_ptr); + if (fn_proxy && *fn_proxy) { + EX(function_state).function = *fn_proxy; + } else { + if (zend_hash_find(&obj_ce->function_table, function_name, fname_len+1, (void **) &EX(function_state).function)==FAILURE) { + return FAILURE; + } + if (fn_proxy) { + *fn_proxy = EX(function_state).function; + } + } + + va_start(args, param_count); + for (i=0; i<param_count; i++) { + zval *arg; + zval *param; + + arg = va_arg(args, zval*); + + if (EX(function_state).function->common.arg_types + && i<EX(function_state).function->common.arg_types[0] + && EX(function_state).function->common.arg_types[i+1]==BYREF_FORCE + && !PZVAL_IS_REF(arg)) { + if (arg->refcount > 1) { + zval *new_zval; + + ALLOC_ZVAL(new_zval); + *new_zval = *arg; + zval_copy_ctor(new_zval); + new_zval->refcount = 1; + arg->refcount--; + arg = new_zval; + } + arg->refcount++; + arg->is_ref = 1; + param = arg; + } else if (arg != &EG(uninitialized_zval)) { + arg->refcount++; + param = arg; + } else { + ALLOC_ZVAL(param); + *param = *arg; + INIT_PZVAL(param); + } + zend_ptr_stack_push(&EG(argument_stack), param); + } + va_end(args); + + zend_ptr_stack_n_push(&EG(argument_stack), 2, (void *) (long) param_count, NULL); + + EG(function_state_ptr) = &EX(function_state); + + current_scope = EG(scope); + EG(scope) = calling_scope; + + current_this = EG(This); + + EG(This) = *object_pp; + + if (!PZVAL_IS_REF(EG(This))) { + EG(This)->refcount++; /* For $this pointer */ + } else { + zval *this_ptr; + + ALLOC_ZVAL(this_ptr); + *this_ptr = *EG(This); + INIT_PZVAL(this_ptr); + zval_copy_ctor(this_ptr); + EG(This) = this_ptr; + } + + EX(prev_execute_data) = EG(current_execute_data); + EG(current_execute_data) = &execute_data; + + if (EX(function_state).function->type == ZEND_USER_FUNCTION) { + calling_symbol_table = EG(active_symbol_table); + if (symbol_table) { + EG(active_symbol_table) = symbol_table; + } else { + ALLOC_HASHTABLE(EG(active_symbol_table)); + zend_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0); + } + + original_return_value = EG(return_value_ptr_ptr); + original_op_array = EG(active_op_array); + EG(return_value_ptr_ptr) = retval; + EG(active_op_array) = (zend_op_array *) EX(function_state).function; + original_opline_ptr = EG(opline_ptr); + orig_free_op1 = EG(free_op1); + orig_free_op2 = EG(free_op2); + orig_unary_op = EG(unary_op); + orig_binary_op = EG(binary_op); + zend_execute(EG(active_op_array) TSRMLS_CC); + if (!symbol_table) { + zend_hash_destroy(EG(active_symbol_table)); + FREE_HASHTABLE(EG(active_symbol_table)); + } + EG(active_symbol_table) = calling_symbol_table; + EG(active_op_array) = original_op_array; + EG(return_value_ptr_ptr)=original_return_value; + EG(opline_ptr) = original_opline_ptr; + EG(free_op1) = orig_free_op1; + EG(free_op2) = orig_free_op2; + EG(unary_op) = orig_unary_op; + EG(binary_op) = orig_binary_op; + } else { + ALLOC_INIT_ZVAL(*retval); + ((zend_internal_function *) EX(function_state).function)->handler(param_count, *retval, (object_pp?*object_pp:NULL), 1 TSRMLS_CC); + INIT_PZVAL(*retval); + } + zend_ptr_stack_clear_multiple(TSRMLS_C); + EG(function_state_ptr) = original_function_state_ptr; + EG(active_namespace) = current_namespace; + + if (EG(This)) { + zval_ptr_dtor(&EG(This)); + } + EG(scope) = current_scope; + EG(This) = current_this; + EG(current_execute_data) = EX(prev_execute_data); \ + + return SUCCESS; } /* }}} */ Index: spl/spl_engine.h diff -u spl/spl_engine.h:1.2 spl/spl_engine.h:1.3 --- spl/spl_engine.h:1.2 Fri May 2 11:39:12 2003 +++ spl/spl_engine.h Sat May 24 09:47:49 2003 @@ -36,13 +36,59 @@ int zend_do_fcall_common_helper(ZEND_OPCODE_HANDLER_ARGS); -int spl_begin_method_call_arg(zval **ce, char *function_name, zval *retval, zval *arg1 TSRMLS_DC); -int spl_begin_method_call_this(zval **ce, char *function_name, zval *retval TSRMLS_DC); -int spl_begin_method_call_arg_ex1(zval **ce, char *function_name, zval **retval, zval **arg1, int no_separation, HashTable *symbol_table TSRMLS_DC); -int spl_begin_method_call_arg_ex2(zval **ce, char *function_name, zval **retval, zval **arg1, zval **arg2, int no_separation, HashTable *symbol_table TSRMLS_DC); +int spl_call_method(zval **object_pp, zend_function **fn_proxy, char *function_name, int function_name_len, zval **retval_ptr, HashTable *symbol_table TSRMLS_DC, int param_count, ...); + +/* {{{ spl_begin_method_call_arg */ +static inline int spl_begin_method_call_arg(zval **ce, zend_function **fn_proxy, char *function_name, int fname_len, zval *retval, zval *arg1 TSRMLS_DC) +{ + zval *local_retval; + int ret = spl_call_method(ce, fn_proxy, function_name, fname_len, &local_retval, NULL TSRMLS_CC, 1, arg1); + if (local_retval) { + COPY_PZVAL_TO_ZVAL(*retval, local_retval); + } else { + INIT_ZVAL(*retval); + } + return ret; +} +/* }}} */ + +/* {{{ spl_begin_method_call_this */ +static inline int spl_begin_method_call_this(zval **ce, zend_function **fn_proxy, char *function_name, int fname_len, zval *retval TSRMLS_DC) +{ + zval *local_retval; + int ret = spl_call_method(ce, fn_proxy, function_name, fname_len, &local_retval, NULL TSRMLS_CC, 0); + if (local_retval) { + COPY_PZVAL_TO_ZVAL(*retval, local_retval); + } else { + INIT_ZVAL(*retval); + } + return ret; +} +/* }}} */ + +/* {{{ spl_begin_method_call_ex */ +static inline int spl_begin_method_call_ex(zval **ce, zend_function **fn_proxy, char *function_name, int fname_len, zval **retval TSRMLS_DC) +{ + return spl_call_method(ce, fn_proxy, function_name, fname_len, retval, NULL TSRMLS_CC, 0); +} +/* }}} */ + +/* {{{ spl_begin_method_call_arg_ex1 */ +static inline int spl_begin_method_call_arg_ex1(zval **ce, zend_function **fn_proxy, char *function_name, int fname_len, zval **retval, zval *arg1 TSRMLS_DC) +{ + return spl_call_method(ce, fn_proxy, function_name, fname_len, retval, NULL TSRMLS_CC, 1, arg1); +} +/* }}} */ + +/* {{{ spl_begin_method_call_arg_ex2 */ +static inline int spl_begin_method_call_arg_ex2(zval **ce, zend_function **fn_proxy, char *function_name, int fname_len, zval **retval, zval *arg1, zval *arg2 TSRMLS_DC) +{ + return spl_call_method(ce, fn_proxy, function_name, fname_len, retval, NULL TSRMLS_CC, 2, arg1, arg2); +} +/* }}} */ void spl_instanciate(zend_class_entry *pce, zval **object TSRMLS_DC); -int spl_instanciate_arg_ex2(zend_class_entry *pce, zval **retval, zval **arg1, zval **arg2, int no_separation, HashTable *symbol_table TSRMLS_DC); +int spl_instanciate_arg_ex2(zend_class_entry *pce, zval **retval, zval *arg1, zval *arg2, HashTable *symbol_table TSRMLS_DC); zval ** spl_get_zval_ptr_ptr(znode *node, temp_variable *Ts TSRMLS_DC); void spl_unlock_zval_ptr_ptr(znode *node, temp_variable *Ts TSRMLS_DC); Index: spl/spl_foreach.c diff -u spl/spl_foreach.c:1.3 spl/spl_foreach.c:1.4 --- spl/spl_foreach.c:1.3 Fri May 2 11:39:12 2003 +++ spl/spl_foreach.c Sat May 24 09:47:49 2003 @@ -31,6 +31,18 @@ #include "spl_engine.h" #include "spl_foreach.h" +#define ezalloc(size) \ + memset(emalloc(size), 0, size) + +typedef struct { + zend_uint index; + zend_function *f_next; + zend_function *f_rewind; + zend_function *f_more; + zend_function *f_current; + zend_function *f_key; +} spl_foreach_proxy; + /* {{{ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_RESET) */ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_RESET) { @@ -41,10 +53,10 @@ if (spl_implements(obj, spl_ce_iterator TSRMLS_CC)) { spl_unlock_zval_ptr_ptr(&EX(opline)->op1, EX(Ts) TSRMLS_CC); MAKE_STD_ZVAL(retval); - spl_begin_method_call_this(obj, "new_iterator", retval TSRMLS_CC); + spl_begin_method_call_this(obj, NULL, "new_iterator", sizeof("new_iterator")-1, retval TSRMLS_CC); EX_T(EX(opline)->result.u.var).var.ptr = retval; EX_T(EX(opline)->result.u.var).var.ptr_ptr = &EX_T(EX(opline)->result.u.var).var.ptr; - EX(opline)->op2.u.EA.type = 0; /* missuse as index */ + /* EX(opline)->result.u.EA.type = 0; */ PZVAL_LOCK(retval); @@ -54,7 +66,7 @@ EX_T(EX(opline)->result.u.var).var.ptr = *obj; EX_T(EX(opline)->result.u.var).var.ptr_ptr = &EX_T(EX(opline)->result.u.var).var.ptr; - EX(opline)->op2.u.EA.type = 0; /* missuse as index */ + /* EX(opline)->result.u.EA.type = 0; */ (*obj)->refcount++; PZVAL_LOCK(*obj); @@ -71,38 +83,43 @@ { zval **obj = spl_get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts) TSRMLS_CC); zval more, tmp, *value, *key, *result; + spl_foreach_proxy *proxy; if (spl_implements(obj, spl_ce_forward TSRMLS_CC)) { - zend_uint index = EX(opline)->op2.u.EA.type++; + proxy = (spl_foreach_proxy*)EX(opline)->op1.u.EA.type; + + if (!proxy) { + (spl_foreach_proxy*)EX(opline)->op1.u.EA.type = proxy = ezalloc(sizeof(spl_foreach_proxy)); + } spl_unlock_zval_ptr_ptr(&EX(opline)->op1, EX(Ts) TSRMLS_CC); PZVAL_LOCK(*obj); - if (index) { - spl_begin_method_call_this(obj, "next", &more TSRMLS_CC); + if (proxy->index++) { + spl_begin_method_call_this(obj, &proxy->f_next, "next", sizeof("next")-1, &tmp TSRMLS_CC); } else if (spl_implements(obj, spl_ce_sequence TSRMLS_CC)) { - spl_begin_method_call_this(obj, "rewind", &more TSRMLS_CC); + spl_begin_method_call_this(obj, &proxy->f_rewind, "rewind", sizeof("rewind")-1, &tmp TSRMLS_CC); } - spl_begin_method_call_this(obj, "has_more", &more TSRMLS_CC); + spl_begin_method_call_this(obj, &proxy->f_more, "has_more", sizeof("has_more")-1, &more TSRMLS_CC); if (zend_is_true(&more)) { result = &EX_T(EX(opline)->result.u.var).tmp_var; array_init(result); ALLOC_ZVAL(value); - spl_begin_method_call_this(obj, "current", value TSRMLS_CC); + spl_begin_method_call_this(obj, &proxy->f_current, "current", sizeof("current")-1, value TSRMLS_CC); zend_hash_index_update(result->value.ht, 0, &value, sizeof(zval *), NULL); if (spl_implements(obj, spl_ce_assoc TSRMLS_CC)) { ALLOC_ZVAL(key); - spl_begin_method_call_this(obj, "key", key TSRMLS_CC); + spl_begin_method_call_this(obj, &proxy->f_key, "key", sizeof("key")-1, key TSRMLS_CC); } else { /* If someone makes a reference to this value then there is * a real problem. And the only way to avoid it is to alloc * dealloc this temporary zval then. */ - tmp.value.lval = index; + tmp.value.lval = proxy->index; tmp.type = IS_LONG; tmp.refcount = 0; tmp.is_ref = 0; @@ -111,6 +128,9 @@ zend_hash_index_update(result->value.ht, 1, &key, sizeof(zval *), NULL); NEXT_OPCODE(); + } else { + efree(proxy); + EX(opline)->op1.u.EA.type = 0; } EX(opline) = op_array->opcodes+EX(opline)->op2.u.opline_num; return 0; Index: spl/spl_functions.c diff -u spl/spl_functions.c:1.1.1.1 spl/spl_functions.c:1.2 --- spl/spl_functions.c:1.1.1.1 Thu May 1 19:28:28 2003 +++ spl/spl_functions.c Sat May 24 09:47:49 2003 @@ -50,12 +50,10 @@ zend_class_entry ce; INIT_CLASS_ENTRY(ce, class_name, NULL); - ce.num_interfaces = 0; *ppce = zend_register_internal_ns_class(&ce, NULL, namespace_entry, NULL TSRMLS_CC); /* entries changed by initialize */ (*ppce)->ce_flags = ZEND_ACC_ABSTRACT | ZEND_ACC_INTERFACE; - (*ppce)->ns = namespace_entry; } /* }}} */ @@ -66,15 +64,11 @@ memset(&ce, 0, sizeof(zend_class_entry)); INIT_CLASS_ENTRY(ce, class_name, NULL); - - ce.num_interfaces = 0; - *ppce = zend_register_internal_ns_class(&ce, NULL, namespace_entry, NULL TSRMLS_CC); /* entries changed by initialize */ (*ppce)->ce_flags = ZEND_ACC_ABSTRACT | ZEND_ACC_INTERFACE; (*ppce)->create_object = obj_ctor; - (*ppce)->ns = namespace_entry; } /* }}} */ Index: spl/tests/foreach.phpt diff -u spl/tests/foreach.phpt:1.1.1.1 spl/tests/foreach.phpt:1.2 --- spl/tests/foreach.phpt:1.1.1.1 Thu May 1 19:28:28 2003 +++ spl/tests/foreach.phpt Sat May 24 09:47:49 2003 @@ -21,8 +21,9 @@ $this->num++; } function has_more() { - echo __CLASS__ . '::' . __FUNCTION__ . "\n"; - return $this->num < $this->obj->max; + $more = $this->num < $this->obj->max; + echo __CLASS__ . '::' . __FUNCTION__ . ' = ' .($more ? 'true' : 'false') . "\n"; + return $more; } function key() { echo __CLASS__ . '::' . __FUNCTION__ . "\n"; @@ -74,111 +75,119 @@ ?> --EXPECT-- c::new_iterator -c_iter::has_more +c_iter::has_more = true c_iter::current 0 c_iter::next -c_iter::has_more +c_iter::has_more = true c_iter::current 1 c_iter::next -c_iter::has_more +c_iter::has_more = true c_iter::current 2 c_iter::next -c_iter::has_more +c_iter::has_more = false array:0 array:1 array:2 c::new_iterator -c_iter::has_more +c_iter::has_more = true c_iter::current c_iter::key object:0 c_iter::next -c_iter::has_more +c_iter::has_more = true c_iter::current c_iter::key object:1 c_iter::next -c_iter::has_more +c_iter::has_more = true c_iter::current c_iter::key object:2 c_iter::next -c_iter::has_more +c_iter::has_more = false c::new_iterator -c_iter::has_more +c_iter::has_more = true c_iter::current c_iter::key c::new_iterator -c_iter::has_more +c_iter::has_more = true c_iter::current c_iter::key double:0:0 c_iter::next -c_iter::has_more +c_iter::has_more = true c_iter::current c_iter::key double:0:1 c_iter::next -c_iter::has_more +c_iter::has_more = true c_iter::current c_iter::key double:0:2 c_iter::next -c_iter::has_more +c_iter::has_more = false c_iter::next -c_iter::has_more +c_iter::has_more = true c_iter::current c_iter::key c::new_iterator +c_iter::has_more = true +c_iter::current +c_iter::key +double:1:0 c_iter::next -c_iter::has_more +c_iter::has_more = true c_iter::current c_iter::key double:1:1 c_iter::next -c_iter::has_more +c_iter::has_more = true c_iter::current c_iter::key double:1:2 c_iter::next -c_iter::has_more +c_iter::has_more = false c_iter::next -c_iter::has_more +c_iter::has_more = true c_iter::current c_iter::key c::new_iterator +c_iter::has_more = true +c_iter::current +c_iter::key +double:2:0 c_iter::next -c_iter::has_more +c_iter::has_more = true c_iter::current c_iter::key double:2:1 c_iter::next -c_iter::has_more +c_iter::has_more = true c_iter::current c_iter::key double:2:2 c_iter::next -c_iter::has_more +c_iter::has_more = false c_iter::next -c_iter::has_more +c_iter::has_more = false c::new_iterator -c_iter::has_more +c_iter::has_more = true c_iter::current c_iter::key object:1st=>0 c_iter::next -c_iter::has_more +c_iter::has_more = true c_iter::current c_iter::key object:2nd=>1 c_iter::next -c_iter::has_more +c_iter::has_more = true c_iter::current c_iter::key object:3rd=>2 c_iter::next -c_iter::has_more +c_iter::has_more = false Done
« previous php.cvs (#21243) next »