diff options
-rwxr-xr-x | ext/spl/README | 3 | ||||
-rwxr-xr-x | ext/spl/spl_array.c | 15 | ||||
-rwxr-xr-x | ext/spl/spl_engine.c | 222 | ||||
-rwxr-xr-x | ext/spl/spl_engine.h | 56 | ||||
-rwxr-xr-x | ext/spl/spl_foreach.c | 42 | ||||
-rwxr-xr-x | ext/spl/spl_functions.c | 6 | ||||
-rwxr-xr-x | ext/spl/tests/foreach.phpt | 65 |
7 files changed, 288 insertions, 121 deletions
diff --git a/ext/spl/README b/ext/spl/README index e4d9aaf7a2..5d12e7d42f 100755 --- a/ext/spl/README +++ b/ext/spl/README @@ -1,4 +1,3 @@ -<pre> This is an extension that aims to implement some efficient data access interfaces and classes. @@ -35,5 +34,3 @@ There is no efficient way for "lazy or just in time evaluating" so 4) should 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 diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 7c68d3c06f..186cdb78a7 100755 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -119,13 +119,10 @@ zend_object_value spl_array_writer_default_create(zend_class_entry *class_type T /* {{{ 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 @@ int spl_fetch_dimension_address(znode *result, znode *op1, znode *op2, temp_vari 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 @@ int spl_fetch_dimension_address(znode *result, znode *op1, znode *op2, temp_vari } 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 @@ int spl_fetch_dimension_address(znode *result, znode *op1, znode *op2, temp_vari } 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 @@ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_ASSIGN) 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); } diff --git a/ext/spl/spl_engine.c b/ext/spl/spl_engine.c index 04dbd75d78..aa72cfd9cd 100755 --- a/ext/spl/spl_engine.c +++ b/ext/spl/spl_engine.c @@ -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 @@ void spl_instanciate(zend_class_entry *pce, zval **object TSRMLS_DC) /* }}} */ /* {{{ 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; } @@ -243,6 +186,167 @@ int spl_implements(zval **obj, zend_class_entry *ce TSRMLS_DC) } /* }}} */ +#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; +} +/* }}} */ + /* * Local variables: * tab-width: 4 diff --git a/ext/spl/spl_engine.h b/ext/spl/spl_engine.h index db61a1982d..040862f8bf 100755 --- a/ext/spl/spl_engine.h +++ b/ext/spl/spl_engine.h @@ -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); diff --git a/ext/spl/spl_foreach.c b/ext/spl/spl_foreach.c index cbe7dfd1e2..ee77b03175 100755 --- a/ext/spl/spl_foreach.c +++ b/ext/spl/spl_foreach.c @@ -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 @@ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_RESET) 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 @@ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_RESET) 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 @@ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_FETCH) { 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_EXECUTE_HOOK_FUNCTION(ZEND_FE_FETCH) 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; diff --git a/ext/spl/spl_functions.c b/ext/spl/spl_functions.c index 1977db1ae9..e6b2573b9d 100755 --- a/ext/spl/spl_functions.c +++ b/ext/spl/spl_functions.c @@ -50,12 +50,10 @@ void spl_register_interface(zend_class_entry ** ppce, zend_namespace * namespace 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 @@ void spl_register_std_class(zend_class_entry ** ppce, zend_namespace * namespace 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; } /* }}} */ diff --git a/ext/spl/tests/foreach.phpt b/ext/spl/tests/foreach.phpt index 6803e44c27..fdef242028 100755 --- a/ext/spl/tests/foreach.phpt +++ b/ext/spl/tests/foreach.phpt @@ -21,8 +21,9 @@ class c_iter implements spl::forward_assoc { $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 @@ print "Done\n"; ?> --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
\ No newline at end of file |