diff options
Diffstat (limited to 'ext/spl')
118 files changed, 4788 insertions, 4759 deletions
diff --git a/ext/spl/config.m4 b/ext/spl/config.m4 index a0f0d1a06d..2f77946ce5 100755 --- a/ext/spl/config.m4 +++ b/ext/spl/config.m4 @@ -1,27 +1,7 @@ dnl $Id$ dnl config.m4 for extension SPL - AC_MSG_CHECKING(whether zend_object_value is packed) - old_CPPFLAGS=$CPPFLAGS - CPPFLAGS="$INCLUDES -I$abs_srcdir $CPPFLAGS" - AC_TRY_RUN([ -#include "Zend/zend_types.h" -int main(int argc, char **argv) { - return ((sizeof(zend_object_handle) + sizeof(zend_object_handlers*)) == sizeof(zend_object_value)) ? 0 : 1; -} - ], [ - ac_result=1 - AC_MSG_RESULT(yes) - ],[ - ac_result=0 - AC_MSG_RESULT(no) - ], [ - ac_result=0 - AC_MSG_RESULT(no) - ]) - CPPFLAGS=$old_CPPFLAGS - AC_DEFINE_UNQUOTED(HAVE_PACKED_OBJECT_VALUE, $ac_result, [Whether struct _zend_object_value is packed]) AC_DEFINE(HAVE_SPL, 1, [Whether you want SPL (Standard PHP Library) support]) - PHP_NEW_EXTENSION(spl, php_spl.c spl_functions.c spl_engine.c spl_iterators.c spl_array.c spl_directory.c spl_exceptions.c spl_observer.c spl_dllist.c spl_heap.c spl_fixedarray.c, no) + PHP_NEW_EXTENSION(spl, php_spl.c spl_functions.c spl_engine.c spl_iterators.c spl_array.c spl_directory.c spl_exceptions.c spl_observer.c spl_dllist.c spl_heap.c spl_fixedarray.c, no,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) PHP_INSTALL_HEADERS([ext/spl], [php_spl.h spl_array.h spl_directory.h spl_engine.h spl_exceptions.h spl_functions.h spl_iterators.h spl_observer.h spl_dllist.h spl_heap.h spl_fixedarray.h]) PHP_ADD_EXTENSION_DEP(spl, pcre, true) diff --git a/ext/spl/config.w32 b/ext/spl/config.w32 index 77cbd20346..56c466c220 100644 --- a/ext/spl/config.w32 +++ b/ext/spl/config.w32 @@ -1,7 +1,7 @@ // $Id$ // vim:ft=javascript -EXTENSION("spl", "php_spl.c spl_functions.c spl_engine.c spl_iterators.c spl_array.c spl_directory.c spl_exceptions.c spl_observer.c spl_dllist.c spl_heap.c spl_fixedarray.c", false /*never shared */); +EXTENSION("spl", "php_spl.c spl_functions.c spl_engine.c spl_iterators.c spl_array.c spl_directory.c spl_exceptions.c spl_observer.c spl_dllist.c spl_heap.c spl_fixedarray.c", false /*never shared */, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); AC_DEFINE('HAVE_SPL', 1); PHP_SPL="yes"; PHP_INSTALL_HEADERS("ext/spl", "php_spl.h spl_array.h spl_directory.h spl_engine.h spl_exceptions.h spl_functions.h spl_iterators.h spl_observer.h spl_dllist.h spl_heap.h spl_fixedarray.h"); diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c index 0f302787be..57e43d4fae 100644 --- a/ext/spl/php_spl.c +++ b/ext/spl/php_spl.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -56,35 +56,30 @@ ZEND_DECLARE_MODULE_GLOBALS(spl) static PHP_GINIT_FUNCTION(spl) { spl_globals->autoload_extensions = NULL; - spl_globals->autoload_extensions_len = 0; spl_globals->autoload_functions = NULL; spl_globals->autoload_running = 0; } /* }}} */ -static zend_class_entry * spl_find_ce_by_name(char *name, int len, zend_bool autoload TSRMLS_DC) +static zend_class_entry * spl_find_ce_by_name(zend_string *name, zend_bool autoload) { - zend_class_entry **ce; - int found; + zend_class_entry *ce; if (!autoload) { - char *lc_name; - ALLOCA_FLAG(use_heap) - - lc_name = do_alloca(len + 1, use_heap); - zend_str_tolower_copy(lc_name, name, len); + zend_string *lc_name = zend_string_alloc(ZSTR_LEN(name), 0); + zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(name), ZSTR_LEN(name)); - found = zend_hash_find(EG(class_table), lc_name, len +1, (void **) &ce); - free_alloca(lc_name, use_heap); + ce = zend_hash_find_ptr(EG(class_table), lc_name); + zend_string_free(lc_name); } else { - found = zend_lookup_class(name, len, &ce TSRMLS_CC); + ce = zend_lookup_class(name); } - if (found != SUCCESS) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Class %s does not exist%s", name, autoload ? " and could not be loaded" : ""); + if (ce == NULL) { + php_error_docref(NULL, E_WARNING, "Class %s does not exist%s", ZSTR_VAL(name), autoload ? " and could not be loaded" : ""); return NULL; } - - return *ce; + + return ce; } /* {{{ proto array class_parents(object instance [, boolean autoload = true]) @@ -95,27 +90,27 @@ PHP_FUNCTION(class_parents) zend_class_entry *parent_class, *ce; zend_bool autoload = 1; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &obj, &autoload) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|b", &obj, &autoload) == FAILURE) { RETURN_FALSE; } - + if (Z_TYPE_P(obj) != IS_OBJECT && Z_TYPE_P(obj) != IS_STRING) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "object or string expected"); + php_error_docref(NULL, E_WARNING, "object or string expected"); RETURN_FALSE; } - + if (Z_TYPE_P(obj) == IS_STRING) { - if (NULL == (ce = spl_find_ce_by_name(Z_STRVAL_P(obj), Z_STRLEN_P(obj), autoload TSRMLS_CC))) { + if (NULL == (ce = spl_find_ce_by_name(Z_STR_P(obj), autoload))) { RETURN_FALSE; } } else { ce = Z_OBJCE_P(obj); } - + array_init(return_value); parent_class = ce->parent; while (parent_class) { - spl_add_class_name(return_value, parent_class, 0, 0 TSRMLS_CC); + spl_add_class_name(return_value, parent_class, 0, 0); parent_class = parent_class->parent; } } @@ -128,25 +123,25 @@ PHP_FUNCTION(class_implements) zval *obj; zend_bool autoload = 1; zend_class_entry *ce; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &obj, &autoload) == FAILURE) { + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|b", &obj, &autoload) == FAILURE) { RETURN_FALSE; } if (Z_TYPE_P(obj) != IS_OBJECT && Z_TYPE_P(obj) != IS_STRING) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "object or string expected"); + php_error_docref(NULL, E_WARNING, "object or string expected"); RETURN_FALSE; } - + if (Z_TYPE_P(obj) == IS_STRING) { - if (NULL == (ce = spl_find_ce_by_name(Z_STRVAL_P(obj), Z_STRLEN_P(obj), autoload TSRMLS_CC))) { + if (NULL == (ce = spl_find_ce_by_name(Z_STR_P(obj), autoload))) { RETURN_FALSE; } } else { ce = Z_OBJCE_P(obj); } - + array_init(return_value); - spl_add_interfaces(return_value, ce, 1, ZEND_ACC_INTERFACE TSRMLS_CC); + spl_add_interfaces(return_value, ce, 1, ZEND_ACC_INTERFACE); } /* }}} */ @@ -157,30 +152,30 @@ PHP_FUNCTION(class_uses) zval *obj; zend_bool autoload = 1; zend_class_entry *ce; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &obj, &autoload) == FAILURE) { + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|b", &obj, &autoload) == FAILURE) { RETURN_FALSE; } if (Z_TYPE_P(obj) != IS_OBJECT && Z_TYPE_P(obj) != IS_STRING) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "object or string expected"); + php_error_docref(NULL, E_WARNING, "object or string expected"); RETURN_FALSE; } - + if (Z_TYPE_P(obj) == IS_STRING) { - if (NULL == (ce = spl_find_ce_by_name(Z_STRVAL_P(obj), Z_STRLEN_P(obj), autoload TSRMLS_CC))) { + if (NULL == (ce = spl_find_ce_by_name(Z_STR_P(obj), autoload))) { RETURN_FALSE; } } else { ce = Z_OBJCE_P(obj); } - + array_init(return_value); - spl_add_traits(return_value, ce, 1, ZEND_ACC_TRAIT TSRMLS_CC); + spl_add_traits(return_value, ce, 1, ZEND_ACC_TRAIT); } /* }}} */ #define SPL_ADD_CLASS(class_name, z_list, sub, allow, ce_flags) \ - spl_add_classes(spl_ce_ ## class_name, z_list, sub, allow, ce_flags TSRMLS_CC) + spl_add_classes(spl_ce_ ## class_name, z_list, sub, allow, ce_flags) #define SPL_LIST_CLASSES(z_list, sub, allow, ce_flags) \ SPL_ADD_CLASS(AppendIterator, z_list, sub, allow, ce_flags); \ @@ -245,66 +240,63 @@ PHP_FUNCTION(class_uses) PHP_FUNCTION(spl_classes) { array_init(return_value); - + SPL_LIST_CLASSES(return_value, 0, 0, 0) } /* }}} */ -static int spl_autoload(const char *class_name, const char * lc_name, int class_name_len, const char * file_extension TSRMLS_DC) /* {{{ */ +static int spl_autoload(zend_string *class_name, zend_string *lc_name, const char *ext, int ext_len) /* {{{ */ { char *class_file; int class_file_len; - int dummy = 1; + zval dummy; zend_file_handle file_handle; zend_op_array *new_op_array; - zval *result = NULL; + zval result; int ret; - class_file_len = spprintf(&class_file, 0, "%s%s", lc_name, file_extension); + class_file_len = (int)spprintf(&class_file, 0, "%s%.*s", ZSTR_VAL(lc_name), ext_len, ext); #if DEFAULT_SLASH != '\\' { char *ptr = class_file; char *end = ptr + class_file_len; - + while ((ptr = memchr(ptr, '\\', (end - ptr))) != NULL) { *ptr = DEFAULT_SLASH; } } #endif - ret = php_stream_open_for_zend_ex(class_file, &file_handle, USE_PATH|STREAM_OPEN_FOR_INCLUDE TSRMLS_CC); + ret = php_stream_open_for_zend_ex(class_file, &file_handle, USE_PATH|STREAM_OPEN_FOR_INCLUDE); if (ret == SUCCESS) { + zend_string *opened_path; if (!file_handle.opened_path) { - file_handle.opened_path = estrndup(class_file, class_file_len); + file_handle.opened_path = zend_string_init(class_file, class_file_len, 0); } - if (zend_hash_add(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1, (void *)&dummy, sizeof(int), NULL)==SUCCESS) { - new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE TSRMLS_CC); - zend_destroy_file_handle(&file_handle TSRMLS_CC); + opened_path = zend_string_copy(file_handle.opened_path); + ZVAL_NULL(&dummy); + if (zend_hash_add(&EG(included_files), opened_path, &dummy)) { + new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE); + zend_destroy_file_handle(&file_handle); } else { new_op_array = NULL; - zend_file_handle_dtor(&file_handle TSRMLS_CC); + zend_file_handle_dtor(&file_handle); } + zend_string_release(opened_path); if (new_op_array) { - EG(return_value_ptr_ptr) = &result; - EG(active_op_array) = new_op_array; - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); - } + ZVAL_UNDEF(&result); + zend_execute(new_op_array, &result); - zend_execute(new_op_array TSRMLS_CC); - - destroy_op_array(new_op_array TSRMLS_CC); + destroy_op_array(new_op_array); efree(new_op_array); if (!EG(exception)) { - if (EG(return_value_ptr_ptr)) { - zval_ptr_dtor(EG(return_value_ptr_ptr)); - } + zval_ptr_dtor(&result); } efree(class_file); - return zend_hash_exists(EG(class_table), (char*)lc_name, class_name_len+1); + return zend_hash_exists(EG(class_table), lc_name); } } efree(class_file); @@ -315,53 +307,56 @@ static int spl_autoload(const char *class_name, const char * lc_name, int class_ Default implementation for __autoload() */ PHP_FUNCTION(spl_autoload) { - char *class_name, *lc_name, *file_exts = SPL_G(autoload_extensions); - int class_name_len, file_exts_len = SPL_G(autoload_extensions_len), found = 0; - char *copy, *pos1, *pos2; - zval **original_return_value = EG(return_value_ptr_ptr); - zend_op **original_opline_ptr = EG(opline_ptr); - zend_op_array *original_active_op_array = EG(active_op_array); - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &class_name, &class_name_len, &file_exts, &file_exts_len) == FAILURE) { + int found = 0, pos_len, pos1_len; + char *pos, *pos1; + zend_string *class_name, *lc_name, *file_exts = SPL_G(autoload_extensions); + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|S", &class_name, &file_exts) == FAILURE) { RETURN_FALSE; } if (file_exts == NULL) { /* autoload_extensions is not initialized, set to defaults */ - copy = pos1 = estrndup(SPL_DEFAULT_FILE_EXTENSIONS, sizeof(SPL_DEFAULT_FILE_EXTENSIONS)-1); + pos = SPL_DEFAULT_FILE_EXTENSIONS; + pos_len = sizeof(SPL_DEFAULT_FILE_EXTENSIONS) - 1; } else { - copy = pos1 = estrndup(file_exts, file_exts_len); - } - lc_name = zend_str_tolower_dup(class_name, class_name_len); - while(pos1 && *pos1 && !EG(exception)) { - EG(return_value_ptr_ptr) = original_return_value; - EG(opline_ptr) = original_opline_ptr; - EG(active_op_array) = original_active_op_array; - pos2 = strchr(pos1, ','); - if (pos2) *pos2 = '\0'; - if (spl_autoload(class_name, lc_name, class_name_len, pos1 TSRMLS_CC)) { + pos = ZSTR_VAL(file_exts); + pos_len = (int)ZSTR_LEN(file_exts); + } + + lc_name = zend_string_alloc(ZSTR_LEN(class_name), 0); + zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(class_name), ZSTR_LEN(class_name)); + while (pos && *pos && !EG(exception)) { + pos1 = strchr(pos, ','); + if (pos1) { + pos1_len = (int)(pos1 - pos); + } else { + pos1_len = pos_len; + } + if (spl_autoload(class_name, lc_name, pos, pos1_len)) { found = 1; break; /* loaded */ } - pos1 = pos2 ? pos2 + 1 : NULL; + pos = pos1 ? pos1 + 1 : NULL; + pos_len = pos1? pos_len - pos1_len - 1 : 0; } - efree(lc_name); - if (copy) { - efree(copy); - } - - EG(return_value_ptr_ptr) = original_return_value; - EG(opline_ptr) = original_opline_ptr; - EG(active_op_array) = original_active_op_array; + zend_string_free(lc_name); if (!found && !SPL_G(autoload_running)) { /* For internal errors, we generate E_ERROR, for direct calls an exception is thrown. * The "scope" is determined by an opcode, if it is ZEND_FETCH_CLASS we know function was called indirectly by * the Zend engine. */ - if (EG(opline_ptr) && active_opline->opcode != ZEND_FETCH_CLASS) { - zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Class %s could not be loaded", class_name); + zend_execute_data *ex = EX(prev_execute_data); + + while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) { + ex = ex->prev_execute_data; + } + if (ex && + ex->opline->opcode != ZEND_FETCH_CLASS && + ex->opline->opcode != ZEND_NEW) { + zend_throw_exception_ex(spl_ce_LogicException, 0, "Class %s could not be loaded", ZSTR_VAL(class_name)); } else { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "Class %s could not be loaded", class_name); + php_error_docref(NULL, E_ERROR, "Class %s could not be loaded", ZSTR_VAL(class_name)); } } } /* }}} */ @@ -370,42 +365,43 @@ PHP_FUNCTION(spl_autoload) Register and return default file extensions for spl_autoload */ PHP_FUNCTION(spl_autoload_extensions) { - char *file_exts = NULL; - int file_exts_len; + zend_string *file_exts = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &file_exts, &file_exts_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S", &file_exts) == FAILURE) { return; } if (file_exts) { if (SPL_G(autoload_extensions)) { - efree(SPL_G(autoload_extensions)); + zend_string_release(SPL_G(autoload_extensions)); } - SPL_G(autoload_extensions) = estrndup(file_exts, file_exts_len); - SPL_G(autoload_extensions_len) = file_exts_len; + SPL_G(autoload_extensions) = zend_string_copy(file_exts); } if (SPL_G(autoload_extensions) == NULL) { - RETURN_STRINGL(SPL_DEFAULT_FILE_EXTENSIONS, sizeof(SPL_DEFAULT_FILE_EXTENSIONS) - 1, 1); + RETURN_STRINGL(SPL_DEFAULT_FILE_EXTENSIONS, sizeof(SPL_DEFAULT_FILE_EXTENSIONS) - 1); } else { - RETURN_STRINGL(SPL_G(autoload_extensions), SPL_G(autoload_extensions_len), 1); + zend_string_addref(SPL_G(autoload_extensions)); + RETURN_STR(SPL_G(autoload_extensions)); } } /* }}} */ typedef struct { zend_function *func_ptr; - zval *obj; - zval *closure; + zval obj; + zval closure; zend_class_entry *ce; } autoload_func_info; -static void autoload_func_info_dtor(autoload_func_info *alfi) +static void autoload_func_info_dtor(zval *element) { - if (alfi->obj) { + autoload_func_info *alfi = (autoload_func_info*)Z_PTR_P(element); + if (!Z_ISUNDEF(alfi->obj)) { zval_ptr_dtor(&alfi->obj); } - if (alfi->closure) { + if (!Z_ISUNDEF(alfi->closure)) { zval_ptr_dtor(&alfi->closure); } + efree(alfi); } /* {{{ proto void spl_autoload_call(string class_name) @@ -413,39 +409,36 @@ static void autoload_func_info_dtor(autoload_func_info *alfi) PHP_FUNCTION(spl_autoload_call) { zval *class_name, *retval = NULL; - int class_name_len; - char *func_name, *lc_name; - uint func_name_len; - ulong dummy; - HashPosition function_pos; + zend_string *lc_name, *func_name; autoload_func_info *alfi; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &class_name) == FAILURE || Z_TYPE_P(class_name) != IS_STRING) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &class_name) == FAILURE || Z_TYPE_P(class_name) != IS_STRING) { return; } if (SPL_G(autoload_functions)) { + HashPosition pos; + zend_ulong num_idx; int l_autoload_running = SPL_G(autoload_running); SPL_G(autoload_running) = 1; - class_name_len = Z_STRLEN_P(class_name); - lc_name = zend_str_tolower_dup(Z_STRVAL_P(class_name), class_name_len); - zend_hash_internal_pointer_reset_ex(SPL_G(autoload_functions), &function_pos); - while(zend_hash_has_more_elements_ex(SPL_G(autoload_functions), &function_pos) == SUCCESS) { - zend_hash_get_current_key_ex(SPL_G(autoload_functions), &func_name, &func_name_len, &dummy, 0, &function_pos); - zend_hash_get_current_data_ex(SPL_G(autoload_functions), (void **) &alfi, &function_pos); - zend_call_method(alfi->obj ? &alfi->obj : NULL, alfi->ce, &alfi->func_ptr, func_name, func_name_len, &retval, 1, class_name, NULL TSRMLS_CC); - zend_exception_save(TSRMLS_C); + lc_name = zend_string_alloc(Z_STRLEN_P(class_name), 0); + zend_str_tolower_copy(ZSTR_VAL(lc_name), Z_STRVAL_P(class_name), Z_STRLEN_P(class_name)); + zend_hash_internal_pointer_reset_ex(SPL_G(autoload_functions), &pos); + while (zend_hash_get_current_key_ex(SPL_G(autoload_functions), &func_name, &num_idx, &pos) == HASH_KEY_IS_STRING) { + alfi = zend_hash_get_current_data_ptr_ex(SPL_G(autoload_functions), &pos); + zend_call_method(Z_ISUNDEF(alfi->obj)? NULL : &alfi->obj, alfi->ce, &alfi->func_ptr, ZSTR_VAL(func_name), ZSTR_LEN(func_name), retval, 1, class_name, NULL); + zend_exception_save(); if (retval) { - zval_ptr_dtor(&retval); + zval_ptr_dtor(retval); retval = NULL; } - if (zend_hash_exists(EG(class_table), lc_name, class_name_len + 1)) { + if (zend_hash_exists(EG(class_table), lc_name)) { break; } - zend_hash_move_forward_ex(SPL_G(autoload_functions), &function_pos); + zend_hash_move_forward_ex(SPL_G(autoload_functions), &pos); } - zend_exception_restore(TSRMLS_C); - efree(lc_name); + zend_exception_restore(); + zend_string_free(lc_name); SPL_G(autoload_running) = l_autoload_running; } else { /* do not use or overwrite &EG(autoload_func) here */ @@ -453,157 +446,154 @@ PHP_FUNCTION(spl_autoload_call) } } /* }}} */ -#define HT_MOVE_TAIL_TO_HEAD(ht) \ - (ht)->pListTail->pListNext = (ht)->pListHead; \ - (ht)->pListHead = (ht)->pListTail; \ - (ht)->pListTail = (ht)->pListHead->pListLast; \ - (ht)->pListHead->pListNext->pListLast = (ht)->pListHead;\ - (ht)->pListTail->pListNext = NULL; \ - (ht)->pListHead->pListLast = NULL; +#define HT_MOVE_TAIL_TO_HEAD(ht) \ + do { \ + Bucket tmp = (ht)->arData[(ht)->nNumUsed-1]; \ + memmove((ht)->arData + 1, (ht)->arData, \ + sizeof(Bucket) * ((ht)->nNumUsed - 1)); \ + (ht)->arData[0] = tmp; \ + zend_hash_rehash(ht); \ + } while (0) -/* {{{ proto bool spl_autoload_register([mixed autoload_function = "spl_autoload" [, throw = true [, prepend]]]) +/* {{{ proto bool spl_autoload_register([mixed autoload_function [, bool throw [, bool prepend]]]) Register given function as __autoload() implementation */ PHP_FUNCTION(spl_autoload_register) { - char *func_name, *error = NULL; - int func_name_len; - char *lc_name = NULL; + zend_string *func_name; + char *error = NULL; + zend_string *lc_name; zval *zcallable = NULL; zend_bool do_throw = 1; zend_bool prepend = 0; zend_function *spl_func_ptr; autoload_func_info alfi; - zval *obj_ptr; + zend_object *obj_ptr; zend_fcall_info_cache fcc; - if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "|zbb", &zcallable, &do_throw, &prepend) == FAILURE) { + if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "|zbb", &zcallable, &do_throw, &prepend) == FAILURE) { return; } if (ZEND_NUM_ARGS()) { - if (Z_TYPE_P(zcallable) == IS_STRING) { - if (Z_STRLEN_P(zcallable) == sizeof("spl_autoload_call") - 1) { - if (!zend_binary_strcasecmp(Z_STRVAL_P(zcallable), sizeof("spl_autoload_call"), "spl_autoload_call", sizeof("spl_autoload_call"))) { - if (do_throw) { - zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Function spl_autoload_call() cannot be registered"); - } - RETURN_FALSE; - } - } - } - - if (!zend_is_callable_ex(zcallable, NULL, IS_CALLABLE_STRICT, &func_name, &func_name_len, &fcc, &error TSRMLS_CC)) { + if (!zend_is_callable_ex(zcallable, NULL, IS_CALLABLE_STRICT, &func_name, &fcc, &error)) { alfi.ce = fcc.calling_scope; alfi.func_ptr = fcc.function_handler; - obj_ptr = fcc.object_ptr; + obj_ptr = fcc.object; if (Z_TYPE_P(zcallable) == IS_ARRAY) { if (!obj_ptr && alfi.func_ptr && !(alfi.func_ptr->common.fn_flags & ZEND_ACC_STATIC)) { if (do_throw) { - zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Passed array specifies a non static method but no object (%s)", error); + zend_throw_exception_ex(spl_ce_LogicException, 0, "Passed array specifies a non static method but no object (%s)", error); } if (error) { efree(error); } - efree(func_name); + zend_string_release(func_name); RETURN_FALSE; - } - else if (do_throw) { - zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Passed array does not specify %s %smethod (%s)", alfi.func_ptr ? "a callable" : "an existing", !obj_ptr ? "static " : "", error); + } else if (do_throw) { + zend_throw_exception_ex(spl_ce_LogicException, 0, "Passed array does not specify %s %smethod (%s)", alfi.func_ptr ? "a callable" : "an existing", !obj_ptr ? "static " : "", error); } if (error) { efree(error); } - efree(func_name); + zend_string_release(func_name); RETURN_FALSE; } else if (Z_TYPE_P(zcallable) == IS_STRING) { if (do_throw) { - zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Function '%s' not %s (%s)", func_name, alfi.func_ptr ? "callable" : "found", error); + zend_throw_exception_ex(spl_ce_LogicException, 0, "Function '%s' not %s (%s)", ZSTR_VAL(func_name), alfi.func_ptr ? "callable" : "found", error); } if (error) { efree(error); } - efree(func_name); + zend_string_release(func_name); RETURN_FALSE; } else { if (do_throw) { - zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Illegal value passed (%s)", error); + zend_throw_exception_ex(spl_ce_LogicException, 0, "Illegal value passed (%s)", error); } if (error) { efree(error); } - efree(func_name); + zend_string_release(func_name); RETURN_FALSE; } + } else if (fcc.function_handler->type == ZEND_INTERNAL_FUNCTION && + fcc.function_handler->internal_function.handler == zif_spl_autoload_call) { + if (do_throw) { + zend_throw_exception_ex(spl_ce_LogicException, 0, "Function spl_autoload_call() cannot be registered"); + } + if (error) { + efree(error); + } + zend_string_release(func_name); + RETURN_FALSE; } - alfi.closure = NULL; alfi.ce = fcc.calling_scope; alfi.func_ptr = fcc.function_handler; - obj_ptr = fcc.object_ptr; + obj_ptr = fcc.object; if (error) { efree(error); } - - lc_name = safe_emalloc(func_name_len, 1, sizeof(long) + 1); - zend_str_tolower_copy(lc_name, func_name, func_name_len); - efree(func_name); if (Z_TYPE_P(zcallable) == IS_OBJECT) { - alfi.closure = zcallable; - Z_ADDREF_P(zcallable); - - lc_name = erealloc(lc_name, func_name_len + 2 + sizeof(zend_object_handle)); - memcpy(lc_name + func_name_len, &Z_OBJ_HANDLE_P(zcallable), - sizeof(zend_object_handle)); - func_name_len += sizeof(zend_object_handle); - lc_name[func_name_len] = '\0'; + ZVAL_COPY(&alfi.closure, zcallable); + + lc_name = zend_string_alloc(ZSTR_LEN(func_name) + sizeof(uint32_t), 0); + zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(func_name), ZSTR_LEN(func_name)); + memcpy(ZSTR_VAL(lc_name) + ZSTR_LEN(func_name), &Z_OBJ_HANDLE_P(zcallable), sizeof(uint32_t)); + ZSTR_VAL(lc_name)[ZSTR_LEN(lc_name)] = '\0'; + } else { + ZVAL_UNDEF(&alfi.closure); + lc_name = zend_string_alloc(ZSTR_LEN(func_name), 0); + zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(func_name), ZSTR_LEN(func_name)); } + zend_string_release(func_name); - if (SPL_G(autoload_functions) && zend_hash_exists(SPL_G(autoload_functions), (char*)lc_name, func_name_len+1)) { - if (alfi.closure) { - Z_DELREF_P(zcallable); + if (SPL_G(autoload_functions) && zend_hash_exists(SPL_G(autoload_functions), lc_name)) { + if (!Z_ISUNDEF(alfi.closure)) { + Z_DELREF_P(&alfi.closure); } goto skip; } if (obj_ptr && !(alfi.func_ptr->common.fn_flags & ZEND_ACC_STATIC)) { /* add object id to the hash to ensure uniqueness, for more reference look at bug #40091 */ - lc_name = erealloc(lc_name, func_name_len + 2 + sizeof(zend_object_handle)); - memcpy(lc_name + func_name_len, &Z_OBJ_HANDLE_P(obj_ptr), sizeof(zend_object_handle)); - func_name_len += sizeof(zend_object_handle); - lc_name[func_name_len] = '\0'; - alfi.obj = obj_ptr; - Z_ADDREF_P(alfi.obj); + lc_name = zend_string_extend(lc_name, ZSTR_LEN(lc_name) + sizeof(uint32_t), 0); + memcpy(ZSTR_VAL(lc_name) + ZSTR_LEN(lc_name) - sizeof(uint32_t), &obj_ptr->handle, sizeof(uint32_t)); + ZSTR_VAL(lc_name)[ZSTR_LEN(lc_name)] = '\0'; + ZVAL_OBJ(&alfi.obj, obj_ptr); + Z_ADDREF(alfi.obj); } else { - alfi.obj = NULL; + ZVAL_UNDEF(&alfi.obj); } if (!SPL_G(autoload_functions)) { ALLOC_HASHTABLE(SPL_G(autoload_functions)); - zend_hash_init(SPL_G(autoload_functions), 1, NULL, (dtor_func_t) autoload_func_info_dtor, 0); + zend_hash_init(SPL_G(autoload_functions), 1, NULL, autoload_func_info_dtor, 0); } - zend_hash_find(EG(function_table), "spl_autoload", sizeof("spl_autoload"), (void **) &spl_func_ptr); + spl_func_ptr = zend_hash_str_find_ptr(EG(function_table), "spl_autoload", sizeof("spl_autoload") - 1); if (EG(autoload_func) == spl_func_ptr) { /* registered already, so we insert that first */ autoload_func_info spl_alfi; spl_alfi.func_ptr = spl_func_ptr; - spl_alfi.obj = NULL; + ZVAL_UNDEF(&spl_alfi.obj); + ZVAL_UNDEF(&spl_alfi.closure); spl_alfi.ce = NULL; - spl_alfi.closure = NULL; - zend_hash_add(SPL_G(autoload_functions), "spl_autoload", sizeof("spl_autoload"), &spl_alfi, sizeof(autoload_func_info), NULL); + zend_hash_str_add_mem(SPL_G(autoload_functions), "spl_autoload", sizeof("spl_autoload") - 1, + &spl_alfi, sizeof(autoload_func_info)); if (prepend && SPL_G(autoload_functions)->nNumOfElements > 1) { /* Move the newly created element to the head of the hashtable */ HT_MOVE_TAIL_TO_HEAD(SPL_G(autoload_functions)); } } - if (zend_hash_add(SPL_G(autoload_functions), lc_name, func_name_len+1, &alfi.func_ptr, sizeof(autoload_func_info), NULL) == FAILURE) { + if (zend_hash_add_mem(SPL_G(autoload_functions), lc_name, &alfi, sizeof(autoload_func_info)) == NULL) { if (obj_ptr && !(alfi.func_ptr->common.fn_flags & ZEND_ACC_STATIC)) { - Z_DELREF_P(alfi.obj); - } - if (alfi.closure) { - Z_DELREF_P(alfi.closure); + Z_DELREF(alfi.obj); + } + if (!Z_ISUNDEF(alfi.closure)) { + Z_DELREF(alfi.closure); } } if (prepend && SPL_G(autoload_functions)->nNumOfElements > 1) { @@ -611,14 +601,15 @@ PHP_FUNCTION(spl_autoload_register) HT_MOVE_TAIL_TO_HEAD(SPL_G(autoload_functions)); } skip: - efree(lc_name); + zend_string_release(lc_name); } if (SPL_G(autoload_functions)) { - zend_hash_find(EG(function_table), "spl_autoload_call", sizeof("spl_autoload_call"), (void **) &EG(autoload_func)); + EG(autoload_func) = zend_hash_str_find_ptr(EG(function_table), "spl_autoload_call", sizeof("spl_autoload_call") - 1); } else { - zend_hash_find(EG(function_table), "spl_autoload", sizeof("spl_autoload"), (void **) &EG(autoload_func)); + EG(autoload_func) = zend_hash_str_find_ptr(EG(function_table), "spl_autoload", sizeof("spl_autoload") - 1); } + RETURN_TRUE; } /* }}} */ @@ -626,48 +617,47 @@ skip: Unregister given function as __autoload() implementation */ PHP_FUNCTION(spl_autoload_unregister) { - char *func_name, *error = NULL; - int func_name_len; - char *lc_name = NULL; + zend_string *func_name = NULL; + char *error = NULL; + zend_string *lc_name; zval *zcallable; int success = FAILURE; zend_function *spl_func_ptr; - zval *obj_ptr; + zend_object *obj_ptr; zend_fcall_info_cache fcc; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zcallable) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zcallable) == FAILURE) { return; } - if (!zend_is_callable_ex(zcallable, NULL, IS_CALLABLE_CHECK_SYNTAX_ONLY, &func_name, &func_name_len, &fcc, &error TSRMLS_CC)) { - zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Unable to unregister invalid function (%s)", error); + if (!zend_is_callable_ex(zcallable, NULL, IS_CALLABLE_CHECK_SYNTAX_ONLY, &func_name, &fcc, &error)) { + zend_throw_exception_ex(spl_ce_LogicException, 0, "Unable to unregister invalid function (%s)", error); if (error) { efree(error); } if (func_name) { - efree(func_name); + zend_string_release(func_name); } RETURN_FALSE; } - obj_ptr = fcc.object_ptr; + obj_ptr = fcc.object; if (error) { efree(error); } - lc_name = safe_emalloc(func_name_len, 1, sizeof(long) + 1); - zend_str_tolower_copy(lc_name, func_name, func_name_len); - efree(func_name); - if (Z_TYPE_P(zcallable) == IS_OBJECT) { - lc_name = erealloc(lc_name, func_name_len + 2 + sizeof(zend_object_handle)); - memcpy(lc_name + func_name_len, &Z_OBJ_HANDLE_P(zcallable), - sizeof(zend_object_handle)); - func_name_len += sizeof(zend_object_handle); - lc_name[func_name_len] = '\0'; + lc_name = zend_string_alloc(ZSTR_LEN(func_name) + sizeof(uint32_t), 0); + zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(func_name), ZSTR_LEN(func_name)); + memcpy(ZSTR_VAL(lc_name) + ZSTR_LEN(func_name), &Z_OBJ_HANDLE_P(zcallable), sizeof(uint32_t)); + ZSTR_VAL(lc_name)[ZSTR_LEN(lc_name)] = '\0'; + } else { + lc_name = zend_string_alloc(ZSTR_LEN(func_name), 0); + zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(func_name), ZSTR_LEN(func_name)); } + zend_string_release(func_name); if (SPL_G(autoload_functions)) { - if (func_name_len == sizeof("spl_autoload_call")-1 && !strcmp(lc_name, "spl_autoload_call")) { + if (ZSTR_LEN(lc_name) == sizeof("spl_autoload_call") - 1 && !strcmp(ZSTR_VAL(lc_name), "spl_autoload_call")) { /* remove all */ if (!SPL_G(autoload_running)) { zend_hash_destroy(SPL_G(autoload_functions)); @@ -680,18 +670,17 @@ PHP_FUNCTION(spl_autoload_unregister) success = SUCCESS; } else { /* remove specific */ - success = zend_hash_del(SPL_G(autoload_functions), lc_name, func_name_len+1); + success = zend_hash_del(SPL_G(autoload_functions), lc_name); if (success != SUCCESS && obj_ptr) { - lc_name = erealloc(lc_name, func_name_len + 2 + sizeof(zend_object_handle)); - memcpy(lc_name + func_name_len, &Z_OBJ_HANDLE_P(obj_ptr), sizeof(zend_object_handle)); - func_name_len += sizeof(zend_object_handle); - lc_name[func_name_len] = '\0'; - success = zend_hash_del(SPL_G(autoload_functions), lc_name, func_name_len+1); + lc_name = zend_string_extend(lc_name, ZSTR_LEN(lc_name) + sizeof(uint32_t), 0); + memcpy(ZSTR_VAL(lc_name) + ZSTR_LEN(lc_name) - sizeof(uint32_t), &obj_ptr->handle, sizeof(uint32_t)); + ZSTR_VAL(lc_name)[ZSTR_LEN(lc_name)] = '\0'; + success = zend_hash_del(SPL_G(autoload_functions), lc_name); } } - } else if (func_name_len == sizeof("spl_autoload")-1 && !strcmp(lc_name, "spl_autoload")) { + } else if (ZSTR_LEN(lc_name) == sizeof("spl_autoload")-1 && !strcmp(ZSTR_VAL(lc_name), "spl_autoload")) { /* register single spl_autoload() */ - zend_hash_find(EG(function_table), "spl_autoload", sizeof("spl_autoload"), (void **) &spl_func_ptr); + spl_func_ptr = zend_hash_str_find_ptr(EG(function_table), "spl_autoload", sizeof("spl_autoload") - 1); if (EG(autoload_func) == spl_func_ptr) { success = SUCCESS; @@ -699,7 +688,7 @@ PHP_FUNCTION(spl_autoload_unregister) } } - efree(lc_name); + zend_string_release(lc_name); RETURN_BOOL(success == SUCCESS); } /* }}} */ @@ -708,64 +697,55 @@ PHP_FUNCTION(spl_autoload_unregister) PHP_FUNCTION(spl_autoload_functions) { zend_function *fptr; - HashPosition function_pos; autoload_func_info *alfi; if (zend_parse_parameters_none() == FAILURE) { return; } - + if (!EG(autoload_func)) { - if (zend_hash_find(EG(function_table), ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME), (void **) &fptr) == SUCCESS) { + if ((fptr = zend_hash_str_find_ptr(EG(function_table), ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1))) { array_init(return_value); - add_next_index_stringl(return_value, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)-1, 1); + add_next_index_stringl(return_value, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)-1); return; } RETURN_FALSE; } - zend_hash_find(EG(function_table), "spl_autoload_call", sizeof("spl_autoload_call"), (void **) &fptr); + fptr = zend_hash_str_find_ptr(EG(function_table), "spl_autoload_call", sizeof("spl_autoload_call") - 1); if (EG(autoload_func) == fptr) { + zend_string *key; array_init(return_value); - zend_hash_internal_pointer_reset_ex(SPL_G(autoload_functions), &function_pos); - while(zend_hash_has_more_elements_ex(SPL_G(autoload_functions), &function_pos) == SUCCESS) { - zend_hash_get_current_data_ex(SPL_G(autoload_functions), (void **) &alfi, &function_pos); - if (alfi->closure) { - Z_ADDREF_P(alfi->closure); - add_next_index_zval(return_value, alfi->closure); + ZEND_HASH_FOREACH_STR_KEY_PTR(SPL_G(autoload_functions), key, alfi) { + if (!Z_ISUNDEF(alfi->closure)) { + Z_ADDREF(alfi->closure); + add_next_index_zval(return_value, &alfi->closure); } else if (alfi->func_ptr->common.scope) { - zval *tmp; - MAKE_STD_ZVAL(tmp); - array_init(tmp); + zval tmp; - if (alfi->obj) { - Z_ADDREF_P(alfi->obj); - add_next_index_zval(tmp, alfi->obj); + array_init(&tmp); + if (!Z_ISUNDEF(alfi->obj)) { + Z_ADDREF(alfi->obj); + add_next_index_zval(&tmp, &alfi->obj); } else { - add_next_index_string(tmp, alfi->ce->name, 1); + add_next_index_str(&tmp, zend_string_copy(alfi->ce->name)); } - add_next_index_string(tmp, alfi->func_ptr->common.function_name, 1); - add_next_index_zval(return_value, tmp); + add_next_index_str(&tmp, zend_string_copy(alfi->func_ptr->common.function_name)); + add_next_index_zval(return_value, &tmp); } else { - if (strncmp(alfi->func_ptr->common.function_name, "__lambda_func", sizeof("__lambda_func") - 1)) { - add_next_index_string(return_value, alfi->func_ptr->common.function_name, 1); + if (strncmp(ZSTR_VAL(alfi->func_ptr->common.function_name), "__lambda_func", sizeof("__lambda_func") - 1)) { + add_next_index_str(return_value, zend_string_copy(alfi->func_ptr->common.function_name)); } else { - char *key; - uint len; - long dummy; - zend_hash_get_current_key_ex(SPL_G(autoload_functions), &key, &len, &dummy, 0, &function_pos); - add_next_index_stringl(return_value, key, len - 1, 1); + add_next_index_str(return_value, zend_string_copy(key)); } } - - zend_hash_move_forward_ex(SPL_G(autoload_functions), &function_pos); - } + } ZEND_HASH_FOREACH_END(); return; } array_init(return_value); - add_next_index_string(return_value, EG(autoload_func)->common.function_name, 1); + add_next_index_str(return_value, zend_string_copy(EG(autoload_func)->common.function_name)); } /* }}} */ /* {{{ proto string spl_object_hash(object obj) @@ -773,49 +753,41 @@ PHP_FUNCTION(spl_autoload_functions) PHP_FUNCTION(spl_object_hash) { zval *obj; - char* hash; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &obj) == FAILURE) { return; } - - hash = emalloc(33); - php_spl_object_hash(obj, hash TSRMLS_CC); - - RETVAL_STRING(hash, 0); + + RETURN_NEW_STR(php_spl_object_hash(obj)); } /* }}} */ -PHPAPI void php_spl_object_hash(zval *obj, char *result TSRMLS_DC) /* {{{*/ +PHPAPI zend_string *php_spl_object_hash(zval *obj) /* {{{*/ { intptr_t hash_handle, hash_handlers; - char *hex; if (!SPL_G(hash_mask_init)) { if (!BG(mt_rand_is_seeded)) { - php_mt_srand(GENERATE_SEED() TSRMLS_CC); + php_mt_srand((uint32_t)GENERATE_SEED()); } - SPL_G(hash_mask_handle) = (intptr_t)(php_mt_rand(TSRMLS_C) >> 1); - SPL_G(hash_mask_handlers) = (intptr_t)(php_mt_rand(TSRMLS_C) >> 1); + SPL_G(hash_mask_handle) = (intptr_t)(php_mt_rand() >> 1); + SPL_G(hash_mask_handlers) = (intptr_t)(php_mt_rand() >> 1); SPL_G(hash_mask_init) = 1; } hash_handle = SPL_G(hash_mask_handle)^(intptr_t)Z_OBJ_HANDLE_P(obj); hash_handlers = SPL_G(hash_mask_handlers)^(intptr_t)Z_OBJ_HT_P(obj); - spprintf(&hex, 32, "%016lx%016lx", hash_handle, hash_handlers); - - strlcpy(result, hex, 33); - efree(hex); + return strpprintf(32, "%016lx%016lx", hash_handle, hash_handlers); } /* }}} */ -int spl_build_class_list_string(zval **entry, char **list TSRMLS_DC) /* {{{ */ +int spl_build_class_list_string(zval *entry, char **list) /* {{{ */ { char *res; - - spprintf(&res, 0, "%s, %s", *list, Z_STRVAL_PP(entry)); + + spprintf(&res, 0, "%s, %s", *list, Z_STRVAL_P(entry)); efree(*list); *list = res; return ZEND_HASH_APPLY_KEEP; @@ -831,20 +803,18 @@ PHP_MINFO_FUNCTION(spl) php_info_print_table_start(); php_info_print_table_header(2, "SPL support", "enabled"); - INIT_PZVAL(&list); array_init(&list); SPL_LIST_CLASSES(&list, 0, 1, ZEND_ACC_INTERFACE) strg = estrdup(""); - zend_hash_apply_with_argument(Z_ARRVAL_P(&list), (apply_func_arg_t)spl_build_class_list_string, &strg TSRMLS_CC); + zend_hash_apply_with_argument(Z_ARRVAL_P(&list), (apply_func_arg_t)spl_build_class_list_string, &strg); zval_dtor(&list); php_info_print_table_row(2, "Interfaces", strg + 2); efree(strg); - INIT_PZVAL(&list); array_init(&list); SPL_LIST_CLASSES(&list, 0, -1, ZEND_ACC_INTERFACE) strg = estrdup(""); - zend_hash_apply_with_argument(Z_ARRVAL_P(&list), (apply_func_arg_t)spl_build_class_list_string, &strg TSRMLS_CC); + zend_hash_apply_with_argument(Z_ARRVAL_P(&list), (apply_func_arg_t)spl_build_class_list_string, &strg); zval_dtor(&list); php_info_print_table_row(2, "Classes", strg + 2); efree(strg); @@ -962,7 +932,6 @@ PHP_MINIT_FUNCTION(spl) PHP_RINIT_FUNCTION(spl) /* {{{ */ { SPL_G(autoload_extensions) = NULL; - SPL_G(autoload_extensions_len) = 0; SPL_G(autoload_functions) = NULL; SPL_G(hash_mask_init) = 0; return SUCCESS; @@ -971,9 +940,8 @@ PHP_RINIT_FUNCTION(spl) /* {{{ */ PHP_RSHUTDOWN_FUNCTION(spl) /* {{{ */ { if (SPL_G(autoload_extensions)) { - efree(SPL_G(autoload_extensions)); + zend_string_release(SPL_G(autoload_extensions)); SPL_G(autoload_extensions) = NULL; - SPL_G(autoload_extensions_len) = 0; } if (SPL_G(autoload_functions)) { zend_hash_destroy(SPL_G(autoload_functions)); @@ -997,7 +965,7 @@ zend_module_entry spl_module_entry = { PHP_RINIT(spl), PHP_RSHUTDOWN(spl), PHP_MINFO(spl), - "0.2", + PHP_SPL_VERSION, PHP_MODULE_GLOBALS(spl), PHP_GINIT(spl), NULL, diff --git a/ext/spl/php_spl.h b/ext/spl/php_spl.h index b4e3211304..d1e5d805a9 100644 --- a/ext/spl/php_spl.h +++ b/ext/spl/php_spl.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -22,6 +22,8 @@ #include "php.h" #include <stdarg.h> +#define PHP_SPL_VERSION PHP_VERSION + #if 0 #define SPL_DEBUG(x) x #else @@ -58,29 +60,23 @@ PHP_MINFO_FUNCTION(spl); ZEND_BEGIN_MODULE_GLOBALS(spl) - char * autoload_extensions; - HashTable * autoload_functions; - int autoload_running; - int autoload_extensions_len; + zend_string *autoload_extensions; + HashTable *autoload_functions; intptr_t hash_mask_handle; intptr_t hash_mask_handlers; int hash_mask_init; + int autoload_running; ZEND_END_MODULE_GLOBALS(spl) -#ifdef ZTS -# define SPL_G(v) TSRMG(spl_globals_id, zend_spl_globals *, v) -extern int spl_globals_id; -#else -# define SPL_G(v) (spl_globals.v) -extern zend_spl_globals spl_globals; -#endif +ZEND_EXTERN_MODULE_GLOBALS(spl); +#define SPL_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(spl, v) PHP_FUNCTION(spl_classes); PHP_FUNCTION(class_parents); PHP_FUNCTION(class_implements); PHP_FUNCTION(class_uses); -PHPAPI void php_spl_object_hash(zval *obj, char* md5str TSRMLS_DC); +PHPAPI zend_string *php_spl_object_hash(zval *obj); #endif /* PHP_SPL_H */ diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 78bb33dda4..1f4cad1f15 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -26,7 +26,7 @@ #include "php_ini.h" #include "ext/standard/info.h" #include "ext/standard/php_var.h" -#include "ext/standard/php_smart_str.h" +#include "zend_smart_str.h" #include "zend_interfaces.h" #include "zend_exceptions.h" @@ -52,211 +52,180 @@ PHPAPI zend_class_entry *spl_ce_RecursiveArrayIterator; #define SPL_ARRAY_OVERLOADED_KEY 0x00040000 #define SPL_ARRAY_OVERLOADED_CURRENT 0x00080000 #define SPL_ARRAY_OVERLOADED_NEXT 0x00100000 -#define SPL_ARRAY_IS_REF 0x01000000 -#define SPL_ARRAY_IS_SELF 0x02000000 -#define SPL_ARRAY_USE_OTHER 0x04000000 +#define SPL_ARRAY_IS_SELF 0x01000000 +#define SPL_ARRAY_USE_OTHER 0x02000000 #define SPL_ARRAY_INT_MASK 0xFFFF0000 -#define SPL_ARRAY_CLONE_MASK 0x0300FFFF +#define SPL_ARRAY_CLONE_MASK 0x0100FFFF #define SPL_ARRAY_METHOD_NO_ARG 0 #define SPL_ARRAY_METHOD_USE_ARG 1 #define SPL_ARRAY_METHOD_MAY_USER_ARG 2 typedef struct _spl_array_object { - zend_object std; - zval *array; - zval *retval; - HashPosition pos; - ulong pos_h; + zval array; + uint32_t ht_iter; int ar_flags; - int is_self; + unsigned char nApplyCount; zend_function *fptr_offset_get; zend_function *fptr_offset_set; zend_function *fptr_offset_has; zend_function *fptr_offset_del; zend_function *fptr_count; zend_class_entry* ce_get_iterator; - HashTable *debug_info; - unsigned char nApplyCount; + zend_object std; } spl_array_object; -static inline HashTable *spl_array_get_hash_table(spl_array_object* intern, int check_std_props TSRMLS_DC) { /* {{{ */ - if ((intern->ar_flags & SPL_ARRAY_IS_SELF) != 0) { - if (!intern->std.properties) { - rebuild_object_properties(&intern->std); - } - return intern->std.properties; - } else if ((intern->ar_flags & SPL_ARRAY_USE_OTHER) && (check_std_props == 0 || (intern->ar_flags & SPL_ARRAY_STD_PROP_LIST) == 0) && Z_TYPE_P(intern->array) == IS_OBJECT) { - spl_array_object *other = (spl_array_object*)zend_object_store_get_object(intern->array TSRMLS_CC); - return spl_array_get_hash_table(other, check_std_props TSRMLS_CC); - } else if ((intern->ar_flags & ((check_std_props ? SPL_ARRAY_STD_PROP_LIST : 0) | SPL_ARRAY_IS_SELF)) != 0) { +static inline spl_array_object *spl_array_from_obj(zend_object *obj) /* {{{ */ { + return (spl_array_object*)((char*)(obj) - XtOffsetOf(spl_array_object, std)); +} +/* }}} */ + +#define Z_SPLARRAY_P(zv) spl_array_from_obj(Z_OBJ_P((zv))) + +static inline HashTable *spl_array_get_hash_table(spl_array_object* intern, int check_std_props) { /* {{{ */ + if (intern->ar_flags & SPL_ARRAY_IS_SELF + || (check_std_props && (intern->ar_flags & SPL_ARRAY_STD_PROP_LIST)) + ) { if (!intern->std.properties) { rebuild_object_properties(&intern->std); } return intern->std.properties; + } else if (intern->ar_flags & SPL_ARRAY_USE_OTHER) { + spl_array_object *other = Z_SPLARRAY_P(&intern->array); + return spl_array_get_hash_table(other, check_std_props); } else { - return HASH_OF(intern->array); + return HASH_OF(&intern->array); } } /* }}} */ -static void spl_array_rewind(spl_array_object *intern TSRMLS_DC); - -static void spl_array_update_pos(spl_array_object* intern) /* {{{ */ +static inline zend_bool spl_array_is_object(spl_array_object *intern) /* {{{ */ { - Bucket *pos = intern->pos; - if (pos != NULL) { - intern->pos_h = pos->h; + while (intern->ar_flags & SPL_ARRAY_USE_OTHER) { + intern = Z_SPLARRAY_P(&intern->array); } -} /* }}} */ + return (intern->ar_flags & SPL_ARRAY_IS_SELF) || Z_TYPE(intern->array) == IS_OBJECT; +} +/* }}} */ -static void spl_array_set_pos(spl_array_object* intern, HashPosition pos) /* {{{ */ -{ - intern->pos = pos; - spl_array_update_pos(intern); -} /* }}} */ +static int spl_array_skip_protected(spl_array_object *intern, HashTable *aht); -SPL_API int spl_hash_verify_pos_ex(spl_array_object * intern, HashTable * ht TSRMLS_DC) /* {{{ */ +static zend_never_inline void spl_array_create_ht_iter(HashTable *ht, spl_array_object* intern) /* {{{ */ { - Bucket *p; - -/* IS_CONSISTENT(ht);*/ - -/* HASH_PROTECT_RECURSION(ht);*/ - p = ht->arBuckets[intern->pos_h & ht->nTableMask]; - while (p != NULL) { - if (p == intern->pos) { - return SUCCESS; - } - p = p->pNext; - } -/* HASH_UNPROTECT_RECURSION(ht); */ - spl_array_rewind(intern TSRMLS_CC); - return FAILURE; - -} /* }}} */ + intern->ht_iter = zend_hash_iterator_add(ht, ht->nInternalPointer); + zend_hash_internal_pointer_reset_ex(ht, &EG(ht_iterators)[intern->ht_iter].pos); + spl_array_skip_protected(intern, ht); +} +/* }}} */ -SPL_API int spl_hash_verify_pos(spl_array_object * intern TSRMLS_DC) /* {{{ */ +static zend_always_inline uint32_t *spl_array_get_pos_ptr(HashTable *ht, spl_array_object* intern) /* {{{ */ { - HashTable *ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); - return spl_hash_verify_pos_ex(intern, ht TSRMLS_CC); + if (UNEXPECTED(intern->ht_iter == (uint32_t)-1)) { + spl_array_create_ht_iter(ht, intern); + } + return &EG(ht_iterators)[intern->ht_iter].pos; } /* }}} */ /* {{{ spl_array_object_free_storage */ -static void spl_array_object_free_storage(void *object TSRMLS_DC) +static void spl_array_object_free_storage(zend_object *object) { - spl_array_object *intern = (spl_array_object *)object; + spl_array_object *intern = spl_array_from_obj(object); + + if (intern->ht_iter != (uint32_t) -1) { + zend_hash_iterator_del(intern->ht_iter); + } - zend_object_std_dtor(&intern->std TSRMLS_CC); + zend_object_std_dtor(&intern->std); zval_ptr_dtor(&intern->array); - zval_ptr_dtor(&intern->retval); - - if (intern->debug_info != NULL) { - zend_hash_destroy(intern->debug_info); - efree(intern->debug_info); - } - - efree(object); } /* }}} */ -zend_object_iterator *spl_array_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC); +zend_object_iterator *spl_array_get_iterator(zend_class_entry *ce, zval *object, int by_ref); /* {{{ spl_array_object_new_ex */ -static zend_object_value spl_array_object_new_ex(zend_class_entry *class_type, spl_array_object **obj, zval *orig, int clone_orig TSRMLS_DC) +static zend_object *spl_array_object_new_ex(zend_class_entry *class_type, zval *orig, int clone_orig) { - zend_object_value retval = {0}; spl_array_object *intern; - zval *tmp; - zend_class_entry * parent = class_type; + zend_class_entry *parent = class_type; int inherited = 0; - intern = emalloc(sizeof(spl_array_object)); - memset(intern, 0, sizeof(spl_array_object)); - *obj = intern; - ALLOC_INIT_ZVAL(intern->retval); + intern = ecalloc(1, sizeof(spl_array_object) + zend_object_properties_size(parent)); - zend_object_std_init(&intern->std, class_type TSRMLS_CC); + zend_object_std_init(&intern->std, class_type); object_properties_init(&intern->std, class_type); intern->ar_flags = 0; - intern->debug_info = NULL; intern->ce_get_iterator = spl_ce_ArrayIterator; if (orig) { - spl_array_object *other = (spl_array_object*)zend_object_store_get_object(orig TSRMLS_CC); + spl_array_object *other = Z_SPLARRAY_P(orig); intern->ar_flags &= ~ SPL_ARRAY_CLONE_MASK; intern->ar_flags |= (other->ar_flags & SPL_ARRAY_CLONE_MASK); intern->ce_get_iterator = other->ce_get_iterator; if (clone_orig) { - intern->array = other->array; - if (Z_OBJ_HT_P(orig) == &spl_handler_ArrayObject) { - MAKE_STD_ZVAL(intern->array); - array_init(intern->array); - zend_hash_copy(HASH_OF(intern->array), HASH_OF(other->array), (copy_ctor_func_t) zval_add_ref, &tmp, sizeof(zval*)); - } - if (Z_OBJ_HT_P(orig) == &spl_handler_ArrayIterator) { - Z_ADDREF_P(other->array); + if (other->ar_flags & SPL_ARRAY_IS_SELF) { + ZVAL_UNDEF(&intern->array); + } else if (Z_OBJ_HT_P(orig) == &spl_handler_ArrayObject) { + ZVAL_ARR(&intern->array, zend_array_dup(HASH_OF(&other->array))); + } else { + ZEND_ASSERT(Z_OBJ_HT_P(orig) == &spl_handler_ArrayIterator); + ZVAL_COPY(&intern->array, &other->array); } } else { - intern->array = orig; - Z_ADDREF_P(intern->array); - intern->ar_flags |= SPL_ARRAY_IS_REF | SPL_ARRAY_USE_OTHER; + ZVAL_COPY(&intern->array, orig); + intern->ar_flags |= SPL_ARRAY_USE_OTHER; } } else { - MAKE_STD_ZVAL(intern->array); - array_init(intern->array); - intern->ar_flags &= ~SPL_ARRAY_IS_REF; + array_init(&intern->array); } - retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_array_object_free_storage, NULL TSRMLS_CC); while (parent) { if (parent == spl_ce_ArrayIterator || parent == spl_ce_RecursiveArrayIterator) { - retval.handlers = &spl_handler_ArrayIterator; + intern->std.handlers = &spl_handler_ArrayIterator; class_type->get_iterator = spl_array_get_iterator; break; } else if (parent == spl_ce_ArrayObject) { - retval.handlers = &spl_handler_ArrayObject; + intern->std.handlers = &spl_handler_ArrayObject; break; } parent = parent->parent; inherited = 1; } if (!parent) { /* this must never happen */ - php_error_docref(NULL TSRMLS_CC, E_COMPILE_ERROR, "Internal compiler error, Class is not child of ArrayObject or ArrayIterator"); + php_error_docref(NULL, E_COMPILE_ERROR, "Internal compiler error, Class is not child of ArrayObject or ArrayIterator"); } if (inherited) { - zend_hash_find(&class_type->function_table, "offsetget", sizeof("offsetget"), (void **) &intern->fptr_offset_get); + intern->fptr_offset_get = zend_hash_str_find_ptr(&class_type->function_table, "offsetget", sizeof("offsetget") - 1); if (intern->fptr_offset_get->common.scope == parent) { intern->fptr_offset_get = NULL; } - zend_hash_find(&class_type->function_table, "offsetset", sizeof("offsetset"), (void **) &intern->fptr_offset_set); + intern->fptr_offset_set = zend_hash_str_find_ptr(&class_type->function_table, "offsetset", sizeof("offsetset") - 1); if (intern->fptr_offset_set->common.scope == parent) { intern->fptr_offset_set = NULL; } - zend_hash_find(&class_type->function_table, "offsetexists", sizeof("offsetexists"), (void **) &intern->fptr_offset_has); + intern->fptr_offset_has = zend_hash_str_find_ptr(&class_type->function_table, "offsetexists", sizeof("offsetexists") - 1); if (intern->fptr_offset_has->common.scope == parent) { intern->fptr_offset_has = NULL; } - zend_hash_find(&class_type->function_table, "offsetunset", sizeof("offsetunset"), (void **) &intern->fptr_offset_del); + intern->fptr_offset_del = zend_hash_str_find_ptr(&class_type->function_table, "offsetunset", sizeof("offsetunset") - 1); if (intern->fptr_offset_del->common.scope == parent) { intern->fptr_offset_del = NULL; } - zend_hash_find(&class_type->function_table, "count", sizeof("count"), (void **) &intern->fptr_count); + intern->fptr_count = zend_hash_str_find_ptr(&class_type->function_table, "count", sizeof("count") - 1); if (intern->fptr_count->common.scope == parent) { intern->fptr_count = NULL; } } /* Cache iterator functions if ArrayIterator or derived. Check current's */ /* cache since only current is always required */ - if (retval.handlers == &spl_handler_ArrayIterator) { + if (intern->std.handlers == &spl_handler_ArrayIterator) { if (!class_type->iterator_funcs.zf_current) { - zend_hash_find(&class_type->function_table, "rewind", sizeof("rewind"), (void **) &class_type->iterator_funcs.zf_rewind); - zend_hash_find(&class_type->function_table, "valid", sizeof("valid"), (void **) &class_type->iterator_funcs.zf_valid); - zend_hash_find(&class_type->function_table, "key", sizeof("key"), (void **) &class_type->iterator_funcs.zf_key); - zend_hash_find(&class_type->function_table, "current", sizeof("current"), (void **) &class_type->iterator_funcs.zf_current); - zend_hash_find(&class_type->function_table, "next", sizeof("next"), (void **) &class_type->iterator_funcs.zf_next); + class_type->iterator_funcs.zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1); + class_type->iterator_funcs.zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1); + class_type->iterator_funcs.zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1); + class_type->iterator_funcs.zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1); + class_type->iterator_funcs.zf_next = zend_hash_str_find_ptr(&class_type->function_table, "next", sizeof("next") - 1); } if (inherited) { if (class_type->iterator_funcs.zf_rewind->common.scope != parent) intern->ar_flags |= SPL_ARRAY_OVERLOADED_REWIND; @@ -267,367 +236,394 @@ static zend_object_value spl_array_object_new_ex(zend_class_entry *class_type, s } } - spl_array_rewind(intern TSRMLS_CC); - return retval; + intern->ht_iter = (uint32_t)-1; + return &intern->std; } /* }}} */ /* {{{ spl_array_object_new */ -static zend_object_value spl_array_object_new(zend_class_entry *class_type TSRMLS_DC) +static zend_object *spl_array_object_new(zend_class_entry *class_type) { - spl_array_object *tmp; - return spl_array_object_new_ex(class_type, &tmp, NULL, 0 TSRMLS_CC); + return spl_array_object_new_ex(class_type, NULL, 0); } /* }}} */ /* {{{ spl_array_object_clone */ -static zend_object_value spl_array_object_clone(zval *zobject TSRMLS_DC) +static zend_object *spl_array_object_clone(zval *zobject) { - zend_object_value new_obj_val; zend_object *old_object; zend_object *new_object; - zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); - spl_array_object *intern; - old_object = zend_objects_get_address(zobject TSRMLS_CC); - new_obj_val = spl_array_object_new_ex(old_object->ce, &intern, zobject, 1 TSRMLS_CC); - new_object = &intern->std; + old_object = Z_OBJ_P(zobject); + new_object = spl_array_object_new_ex(old_object->ce, zobject, 1); - zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC); + zend_objects_clone_members(new_object, old_object); - return new_obj_val; + return new_object; } /* }}} */ -static zval **spl_array_get_dimension_ptr_ptr(int check_inherited, zval *object, zval *offset, int type TSRMLS_DC) /* {{{ */ +static zval *spl_array_get_dimension_ptr(int check_inherited, zval *object, zval *offset, int type) /* {{{ */ { - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); - zval **retval; - char *key; - uint len; - long index; - HashTable *ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); + zval *retval; + zend_long index; + zend_string *offset_key; + spl_array_object *intern = Z_SPLARRAY_P(object); + HashTable *ht = spl_array_get_hash_table(intern, 0); - if (!offset) { - return &EG(uninitialized_zval_ptr); + if (!offset || Z_ISUNDEF_P(offset)) { + return &EG(uninitialized_zval); } - if ((type == BP_VAR_W || type == BP_VAR_RW) && (ht->nApplyCount > 0)) { + if ((type == BP_VAR_W || type == BP_VAR_RW) && (ht->u.v.nApplyCount > 0)) { zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); - return &EG(error_zval_ptr);; + return &EG(error_zval); } +try_again: switch (Z_TYPE_P(offset)) { + case IS_NULL: + offset_key = ZSTR_EMPTY_ALLOC(); + goto fetch_dim_string; case IS_STRING: - key = Z_STRVAL_P(offset); - len = Z_STRLEN_P(offset) + 1; -string_offest: - if (zend_symtable_find(ht, key, len, (void **) &retval) == FAILURE) { + offset_key = Z_STR_P(offset); +fetch_dim_string: + retval = zend_symtable_find(ht, offset_key); + if (retval) { + if (Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + switch (type) { + case BP_VAR_R: + zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(offset_key)); + case BP_VAR_UNSET: + case BP_VAR_IS: + retval = &EG(uninitialized_zval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined index: %s", ZSTR_VAL(offset_key)); + case BP_VAR_W: { + ZVAL_NULL(retval); + } + } + } + } + } else { switch (type) { case BP_VAR_R: - zend_error(E_NOTICE, "Undefined index: %s", key); + zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(offset_key)); case BP_VAR_UNSET: case BP_VAR_IS: - retval = &EG(uninitialized_zval_ptr); + retval = &EG(uninitialized_zval); break; case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined index: %s", key); + zend_error(E_NOTICE,"Undefined index: %s", ZSTR_VAL(offset_key)); case BP_VAR_W: { - zval *value; - ALLOC_INIT_ZVAL(value); - zend_symtable_update(ht, key, len, (void**)&value, sizeof(void*), (void **)&retval); + zval value; + ZVAL_NULL(&value); + retval = zend_symtable_update(ht, offset_key, &value); } } } return retval; - case IS_NULL: - key = ""; - len = 1; - goto string_offest; case IS_RESOURCE: - zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_LVAL_P(offset), Z_LVAL_P(offset)); + zend_error(E_NOTICE, "Resource ID#%pd used as offset, casting to integer (%pd)", Z_RES_P(offset)->handle, Z_RES_P(offset)->handle); + index = Z_RES_P(offset)->handle; + goto num_index; case IS_DOUBLE: - case IS_BOOL: + index = (zend_long)Z_DVAL_P(offset); + goto num_index; + case IS_FALSE: + index = 0; + goto num_index; + case IS_TRUE: + index = 1; + goto num_index; case IS_LONG: - if (offset->type == IS_DOUBLE) { - index = (long)Z_DVAL_P(offset); - } else { - index = Z_LVAL_P(offset); - } - if (zend_hash_index_find(ht, index, (void **) &retval) == FAILURE) { + index = Z_LVAL_P(offset); +num_index: + if ((retval = zend_hash_index_find(ht, index)) == NULL) { switch (type) { case BP_VAR_R: - zend_error(E_NOTICE, "Undefined offset: %ld", index); + zend_error(E_NOTICE, "Undefined offset: %pd", index); case BP_VAR_UNSET: case BP_VAR_IS: - retval = &EG(uninitialized_zval_ptr); + retval = &EG(uninitialized_zval); break; case BP_VAR_RW: - zend_error(E_NOTICE, "Undefined offset: %ld", index); + zend_error(E_NOTICE, "Undefined offset: %pd", index); case BP_VAR_W: { - zval *value; - ALLOC_INIT_ZVAL(value); - zend_hash_index_update(ht, index, (void**)&value, sizeof(void*), (void **)&retval); + zval value; + ZVAL_UNDEF(&value); + retval = zend_hash_index_update(ht, index, &value); } } } return retval; + case IS_REFERENCE: + ZVAL_DEREF(offset); + goto try_again; default: zend_error(E_WARNING, "Illegal offset type"); return (type == BP_VAR_W || type == BP_VAR_RW) ? - &EG(error_zval_ptr) : &EG(uninitialized_zval_ptr); + &EG(error_zval) : &EG(uninitialized_zval); } } /* }}} */ -static zval *spl_array_read_dimension_ex(int check_inherited, zval *object, zval *offset, int type TSRMLS_DC) /* {{{ */ +static zval *spl_array_read_dimension_ex(int check_inherited, zval *object, zval *offset, int type, zval *rv) /* {{{ */ { - zval **ret; + zval *ret; if (check_inherited) { - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); + spl_array_object *intern = Z_SPLARRAY_P(object); if (intern->fptr_offset_get) { - zval *rv; + zval tmp; if (!offset) { - ALLOC_INIT_ZVAL(offset); + ZVAL_UNDEF(&tmp); + offset = &tmp; } else { SEPARATE_ARG_IF_REF(offset); } - zend_call_method_with_1_params(&object, Z_OBJCE_P(object), &intern->fptr_offset_get, "offsetGet", &rv, offset); - zval_ptr_dtor(&offset); - if (rv) { - zval_ptr_dtor(&intern->retval); - MAKE_STD_ZVAL(intern->retval); - ZVAL_ZVAL(intern->retval, rv, 1, 1); - return intern->retval; + zend_call_method_with_1_params(object, Z_OBJCE_P(object), &intern->fptr_offset_get, "offsetGet", rv, offset); + zval_ptr_dtor(offset); + + if (!Z_ISUNDEF_P(rv)) { + return rv; } - return EG(uninitialized_zval_ptr); + return &EG(uninitialized_zval); } } - ret = spl_array_get_dimension_ptr_ptr(check_inherited, object, offset, type TSRMLS_CC); + ret = spl_array_get_dimension_ptr(check_inherited, object, offset, type); /* When in a write context, * ZE has to be fooled into thinking this is in a reference set - * by separating (if necessary) and returning as an is_ref=1 zval (even if refcount == 1) */ - if ((type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) && !Z_ISREF_PP(ret) && ret != &EG(uninitialized_zval_ptr)) { - if (Z_REFCOUNT_PP(ret) > 1) { - zval *newval; - - /* Separate */ - MAKE_STD_ZVAL(newval); - *newval = **ret; - zval_copy_ctor(newval); - Z_SET_REFCOUNT_P(newval, 1); - - /* Replace */ - Z_DELREF_PP(ret); - *ret = newval; - } + * by separating (if necessary) and returning as IS_REFERENCE (with refcount == 1) + */ - Z_SET_ISREF_PP(ret); + if ((type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) && + !Z_ISREF_P(ret) && + EXPECTED(ret != &EG(uninitialized_zval))) { + ZVAL_NEW_REF(ret, ret); } - return *ret; + return ret; } /* }}} */ -static zval *spl_array_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) /* {{{ */ +static zval *spl_array_read_dimension(zval *object, zval *offset, int type, zval *rv) /* {{{ */ { - return spl_array_read_dimension_ex(1, object, offset, type TSRMLS_CC); + return spl_array_read_dimension_ex(1, object, offset, type, rv); } /* }}} */ -static void spl_array_write_dimension_ex(int check_inherited, zval *object, zval *offset, zval *value TSRMLS_DC) /* {{{ */ +static void spl_array_write_dimension_ex(int check_inherited, zval *object, zval *offset, zval *value) /* {{{ */ { - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); - long index; + spl_array_object *intern = Z_SPLARRAY_P(object); + zend_long index; HashTable *ht; if (check_inherited && intern->fptr_offset_set) { + zval tmp; + if (!offset) { - ALLOC_INIT_ZVAL(offset); + ZVAL_NULL(&tmp); + offset = &tmp; } else { SEPARATE_ARG_IF_REF(offset); } - zend_call_method_with_2_params(&object, Z_OBJCE_P(object), &intern->fptr_offset_set, "offsetSet", NULL, offset, value); - zval_ptr_dtor(&offset); + zend_call_method_with_2_params(object, Z_OBJCE_P(object), &intern->fptr_offset_set, "offsetSet", NULL, offset, value); + zval_ptr_dtor(offset); return; } if (!offset) { - ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); - if (ht->nApplyCount > 0) { + ht = spl_array_get_hash_table(intern, 0); + if (ht->u.v.nApplyCount > 0) { zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); return; } - Z_ADDREF_P(value); - zend_hash_next_index_insert(ht, (void**)&value, sizeof(void*), NULL); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zend_hash_next_index_insert(ht, value); return; } - switch(Z_TYPE_P(offset)) { - case IS_STRING: - ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); - if (ht->nApplyCount > 0) { - zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); - return; - } + + if (Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); - zend_symtable_update(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void**)&value, sizeof(void*), NULL); - return; - case IS_DOUBLE: - case IS_RESOURCE: - case IS_BOOL: - case IS_LONG: - ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); - if (ht->nApplyCount > 0) { - zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); + } + +try_again: + switch (Z_TYPE_P(offset)) { + case IS_STRING: + ht = spl_array_get_hash_table(intern, 0); + if (ht->u.v.nApplyCount > 0) { + zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); + return; + } + zend_symtable_update_ind(ht, Z_STR_P(offset), value); return; - } - if (offset->type == IS_DOUBLE) { - index = (long)Z_DVAL_P(offset); - } else { + case IS_DOUBLE: + index = (zend_long)Z_DVAL_P(offset); + goto num_index; + case IS_RESOURCE: + index = Z_RES_HANDLE_P(offset); + goto num_index; + case IS_FALSE: + index = 0; + goto num_index; + case IS_TRUE: + index = 1; + goto num_index; + case IS_LONG: index = Z_LVAL_P(offset); - } - Z_ADDREF_P(value); - zend_hash_index_update(ht, index, (void**)&value, sizeof(void*), NULL); - return; - case IS_NULL: - ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); - if (ht->nApplyCount > 0) { - zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); +num_index: + ht = spl_array_get_hash_table(intern, 0); + if (ht->u.v.nApplyCount > 0) { + zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); + return; + } + zend_hash_index_update(ht, index, value); + return; + case IS_NULL: + ht = spl_array_get_hash_table(intern, 0); + if (ht->u.v.nApplyCount > 0) { + zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); + return; + } + zend_hash_next_index_insert(ht, value); + return; + case IS_REFERENCE: + ZVAL_DEREF(offset); + goto try_again; + default: + zend_error(E_WARNING, "Illegal offset type"); return; - } - Z_ADDREF_P(value); - zend_hash_next_index_insert(ht, (void**)&value, sizeof(void*), NULL); - return; - default: - zend_error(E_WARNING, "Illegal offset type"); - return; } } /* }}} */ -static void spl_array_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC) /* {{{ */ +static void spl_array_write_dimension(zval *object, zval *offset, zval *value) /* {{{ */ { - spl_array_write_dimension_ex(1, object, offset, value TSRMLS_CC); + spl_array_write_dimension_ex(1, object, offset, value); } /* }}} */ -static void spl_array_unset_dimension_ex(int check_inherited, zval *object, zval *offset TSRMLS_DC) /* {{{ */ +static void spl_array_unset_dimension_ex(int check_inherited, zval *object, zval *offset) /* {{{ */ { - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); - long index; + zend_long index; HashTable *ht; + spl_array_object *intern = Z_SPLARRAY_P(object); if (check_inherited && intern->fptr_offset_del) { SEPARATE_ARG_IF_REF(offset); - zend_call_method_with_1_params(&object, Z_OBJCE_P(object), &intern->fptr_offset_del, "offsetUnset", NULL, offset); - zval_ptr_dtor(&offset); + zend_call_method_with_1_params(object, Z_OBJCE_P(object), &intern->fptr_offset_del, "offsetUnset", NULL, offset); + zval_ptr_dtor(offset); return; } - switch(Z_TYPE_P(offset)) { +try_again: + switch (Z_TYPE_P(offset)) { case IS_STRING: - ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); - if (ht->nApplyCount > 0) { + ht = spl_array_get_hash_table(intern, 0); + if (ht->u.v.nApplyCount > 0) { zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); return; } if (ht == &EG(symbol_table)) { - if (zend_delete_global_variable(Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC)) { + if (zend_delete_global_variable(Z_STR_P(offset))) { zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset)); } } else { - if (zend_symtable_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1) == FAILURE) { - zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset)); - } else { - spl_array_object *obj = intern; - - while (1) { - if ((obj->ar_flags & SPL_ARRAY_IS_SELF) != 0) { - break; - } else if (Z_TYPE_P(obj->array) == IS_OBJECT) { - if ((obj->ar_flags & SPL_ARRAY_USE_OTHER) == 0) { - obj = (spl_array_object*)zend_object_store_get_object(obj->array TSRMLS_CC); - break; - } else { - obj = (spl_array_object*)zend_object_store_get_object(obj->array TSRMLS_CC); - } - } else { - obj = NULL; - break; - } - } - if (obj) { - zend_property_info *property_info = zend_get_property_info(obj->std.ce, offset, 1 TSRMLS_CC); + zval *data = zend_symtable_find(ht, Z_STR_P(offset)); - if (property_info && - (property_info->flags & ZEND_ACC_STATIC) == 0 && - property_info->offset >= 0) { - obj->std.properties_table[property_info->offset] = NULL; + if (data) { + if (Z_TYPE_P(data) == IS_INDIRECT) { + data = Z_INDIRECT_P(data); + if (Z_TYPE_P(data) == IS_UNDEF) { + zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset)); + } else { + zval_ptr_dtor(data); + ZVAL_UNDEF(data); + ht->u.v.flags |= HASH_FLAG_HAS_EMPTY_IND; + zend_hash_move_forward_ex(ht, spl_array_get_pos_ptr(ht, intern)); + if (spl_array_is_object(intern)) { + spl_array_skip_protected(intern, ht); + } } + } else if (zend_symtable_del(ht, Z_STR_P(offset)) == FAILURE) { + zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset)); } + } else { + zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset)); } } break; case IS_DOUBLE: + index = (zend_long)Z_DVAL_P(offset); + goto num_index; case IS_RESOURCE: - case IS_BOOL: + index = Z_RES_HANDLE_P(offset); + goto num_index; + case IS_FALSE: + index = 0; + goto num_index; + case IS_TRUE: + index = 1; + goto num_index; case IS_LONG: - if (offset->type == IS_DOUBLE) { - index = (long)Z_DVAL_P(offset); - } else { - index = Z_LVAL_P(offset); - } - ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); - if (ht->nApplyCount > 0) { + index = Z_LVAL_P(offset); +num_index: + ht = spl_array_get_hash_table(intern, 0); + if (ht->u.v.nApplyCount > 0) { zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); return; } if (zend_hash_index_del(ht, index) == FAILURE) { - zend_error(E_NOTICE,"Undefined offset: %ld", Z_LVAL_P(offset)); + zend_error(E_NOTICE,"Undefined offset: %pd", index); } break; + case IS_REFERENCE: + ZVAL_DEREF(offset); + goto try_again; default: zend_error(E_WARNING, "Illegal offset type"); return; } - spl_hash_verify_pos(intern TSRMLS_CC); /* call rewind on FAILURE */ } /* }}} */ -static void spl_array_unset_dimension(zval *object, zval *offset TSRMLS_DC) /* {{{ */ +static void spl_array_unset_dimension(zval *object, zval *offset) /* {{{ */ { - spl_array_unset_dimension_ex(1, object, offset TSRMLS_CC); + spl_array_unset_dimension_ex(1, object, offset); } /* }}} */ -static int spl_array_has_dimension_ex(int check_inherited, zval *object, zval *offset, int check_empty TSRMLS_DC) /* {{{ */ +static int spl_array_has_dimension_ex(int check_inherited, zval *object, zval *offset, int check_empty) /* {{{ */ { - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); - long index; - zval *rv, *value = NULL, **tmp; + spl_array_object *intern = Z_SPLARRAY_P(object); + zend_long index; + zval rv, *value = NULL, *tmp; if (check_inherited && intern->fptr_offset_has) { - zval *offset_tmp = offset; - SEPARATE_ARG_IF_REF(offset_tmp); - zend_call_method_with_1_params(&object, Z_OBJCE_P(object), &intern->fptr_offset_has, "offsetExists", &rv, offset_tmp); - zval_ptr_dtor(&offset_tmp); + SEPARATE_ARG_IF_REF(offset); + zend_call_method_with_1_params(object, Z_OBJCE_P(object), &intern->fptr_offset_has, "offsetExists", &rv, offset); + zval_ptr_dtor(offset); - if (rv && zend_is_true(rv)) { + if (!Z_ISUNDEF(rv) && zend_is_true(&rv)) { zval_ptr_dtor(&rv); if (check_empty != 1) { return 1; } else if (intern->fptr_offset_get) { - value = spl_array_read_dimension_ex(1, object, offset, BP_VAR_R TSRMLS_CC); + value = spl_array_read_dimension_ex(1, object, offset, BP_VAR_R, &rv); } } else { - if (rv) { - zval_ptr_dtor(&rv); - } + zval_ptr_dtor(&rv); return 0; } } if (!value) { - HashTable *ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); + HashTable *ht = spl_array_get_hash_table(intern, 0); - switch(Z_TYPE_P(offset)) { - case IS_STRING: - if (zend_symtable_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **) &tmp) != FAILURE) { +try_again: + switch (Z_TYPE_P(offset)) { + case IS_STRING: + if ((tmp = zend_symtable_find(ht, Z_STR_P(offset))) != NULL) { if (check_empty == 2) { return 1; } @@ -637,15 +633,21 @@ static int spl_array_has_dimension_ex(int check_inherited, zval *object, zval *o break; case IS_DOUBLE: + index = (zend_long)Z_DVAL_P(offset); + goto num_index; case IS_RESOURCE: - case IS_BOOL: + index = Z_RES_HANDLE_P(offset); + goto num_index; + case IS_FALSE: + index = 0; + goto num_index; + case IS_TRUE: + index = 1; + goto num_index; case IS_LONG: - if (offset->type == IS_DOUBLE) { - index = (long)Z_DVAL_P(offset); - } else { - index = Z_LVAL_P(offset); - } - if (zend_hash_index_find(ht, index, (void **)&tmp) != FAILURE) { + index = Z_LVAL_P(offset); +num_index: + if ((tmp = zend_hash_index_find(ht, index)) != NULL) { if (check_empty == 2) { return 1; } @@ -653,37 +655,40 @@ static int spl_array_has_dimension_ex(int check_inherited, zval *object, zval *o return 0; } break; - + case IS_REFERENCE: + ZVAL_DEREF(offset); + goto try_again; default: zend_error(E_WARNING, "Illegal offset type"); return 0; } if (check_empty && check_inherited && intern->fptr_offset_get) { - value = spl_array_read_dimension_ex(1, object, offset, BP_VAR_R TSRMLS_CC); + value = spl_array_read_dimension_ex(1, object, offset, BP_VAR_R, &rv); } else { - value = *tmp; + value = tmp; } } - return check_empty ? zend_is_true(value) : Z_TYPE_P(value) != IS_NULL; + { + zend_bool result = check_empty ? zend_is_true(value) : Z_TYPE_P(value) != IS_NULL; + if (value == &rv) { + zval_ptr_dtor(&rv); + } + return result; + } } /* }}} */ -static int spl_array_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC) /* {{{ */ +static int spl_array_has_dimension(zval *object, zval *offset, int check_empty) /* {{{ */ { - return spl_array_has_dimension_ex(1, object, offset, check_empty TSRMLS_CC); + return spl_array_has_dimension_ex(1, object, offset, check_empty); } /* }}} */ /* {{{ spl_array_object_verify_pos_ex */ -static inline int spl_array_object_verify_pos_ex(spl_array_object *object, HashTable *ht, const char *msg_prefix TSRMLS_DC) +static inline int spl_array_object_verify_pos_ex(spl_array_object *object, HashTable *ht, const char *msg_prefix) { if (!ht) { - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%sArray was modified outside object and is no longer an array", msg_prefix); - return FAILURE; - } - - if (object->pos && (object->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(object, ht TSRMLS_CC) == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%sArray was modified outside object and internal position is no longer valid", msg_prefix); + php_error_docref(NULL, E_NOTICE, "%sArray was modified outside object and is no longer an array", msg_prefix); return FAILURE; } @@ -691,9 +696,9 @@ static inline int spl_array_object_verify_pos_ex(spl_array_object *object, HashT } /* }}} */ /* {{{ spl_array_object_verify_pos */ -static inline int spl_array_object_verify_pos(spl_array_object *object, HashTable *ht TSRMLS_DC) +static inline int spl_array_object_verify_pos(spl_array_object *object, HashTable *ht) { - return spl_array_object_verify_pos_ex(object, ht, "" TSRMLS_CC); + return spl_array_object_verify_pos_ex(object, ht, ""); } /* }}} */ /* {{{ proto bool ArrayObject::offsetExists(mixed $index) @@ -702,10 +707,10 @@ static inline int spl_array_object_verify_pos(spl_array_object *object, HashTabl SPL_METHOD(Array, offsetExists) { zval *index; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &index) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &index) == FAILURE) { return; } - RETURN_BOOL(spl_array_has_dimension_ex(0, getThis(), index, 2 TSRMLS_CC)); + RETURN_BOOL(spl_array_has_dimension_ex(0, getThis(), index, 2)); } /* }}} */ /* {{{ proto mixed ArrayObject::offsetGet(mixed $index) @@ -713,12 +718,15 @@ SPL_METHOD(Array, offsetExists) Returns the value at the specified $index. */ SPL_METHOD(Array, offsetGet) { - zval *index, *value; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &index) == FAILURE) { + zval *value, *index; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &index) == FAILURE) { return; } - value = spl_array_read_dimension_ex(0, getThis(), index, BP_VAR_R TSRMLS_CC); - RETURN_ZVAL(value, 1, 0); + value = spl_array_read_dimension_ex(0, getThis(), index, BP_VAR_R, return_value); + if (value != return_value) { + ZVAL_DEREF(value); + ZVAL_COPY(return_value, value); + } } /* }}} */ /* {{{ proto void ArrayObject::offsetSet(mixed $index, mixed $newval) @@ -727,31 +735,28 @@ SPL_METHOD(Array, offsetGet) SPL_METHOD(Array, offsetSet) { zval *index, *value; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &index, &value) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &index, &value) == FAILURE) { return; } - spl_array_write_dimension_ex(0, getThis(), index, value TSRMLS_CC); + spl_array_write_dimension_ex(0, getThis(), index, value); } /* }}} */ -void spl_array_iterator_append(zval *object, zval *append_value TSRMLS_DC) /* {{{ */ +void spl_array_iterator_append(zval *object, zval *append_value) /* {{{ */ { - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); - HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); + spl_array_object *intern = Z_SPLARRAY_P(object); + HashTable *aht = spl_array_get_hash_table(intern, 0); if (!aht) { - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array"); + php_error_docref(NULL, E_NOTICE, "Array was modified outside object and is no longer an array"); return; } - if (Z_TYPE_P(intern->array) == IS_OBJECT) { - php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Cannot append properties to objects, use %s::offsetSet() instead", Z_OBJCE_P(object)->name); + if (spl_array_is_object(intern)) { + php_error_docref(NULL, E_RECOVERABLE_ERROR, "Cannot append properties to objects, use %s::offsetSet() instead", ZSTR_VAL(Z_OBJCE_P(object)->name)); return; } - spl_array_write_dimension(object, NULL, append_value TSRMLS_CC); - if (!intern->pos) { - spl_array_set_pos(intern, aht->pListTail); - } + spl_array_write_dimension(object, NULL, append_value); } /* }}} */ /* {{{ proto void ArrayObject::append(mixed $newval) @@ -761,10 +766,10 @@ SPL_METHOD(Array, append) { zval *value; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &value) == FAILURE) { return; } - spl_array_iterator_append(getThis(), value TSRMLS_CC); + spl_array_iterator_append(getThis(), value); } /* }}} */ /* {{{ proto void ArrayObject::offsetUnset(mixed $index) @@ -773,10 +778,10 @@ SPL_METHOD(Array, append) SPL_METHOD(Array, offsetUnset) { zval *index; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &index) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &index) == FAILURE) { return; } - spl_array_unset_dimension_ex(0, getThis(), index TSRMLS_CC); + spl_array_unset_dimension_ex(0, getThis(), index); } /* }}} */ /* {{{ proto array ArrayObject::getArrayCopy() @@ -784,380 +789,355 @@ SPL_METHOD(Array, offsetUnset) Return a copy of the contained array */ SPL_METHOD(Array, getArrayCopy) { - zval *object = getThis(), *tmp; - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); + zval *object = getThis(); + spl_array_object *intern = Z_SPLARRAY_P(object); - array_init(return_value); - zend_hash_copy(HASH_OF(return_value), spl_array_get_hash_table(intern, 0 TSRMLS_CC), (copy_ctor_func_t) zval_add_ref, &tmp, sizeof(zval*)); + RETURN_ARR(zend_array_dup(spl_array_get_hash_table(intern, 0))); } /* }}} */ -static HashTable *spl_array_get_properties(zval *object TSRMLS_DC) /* {{{ */ +static HashTable *spl_array_get_properties(zval *object) /* {{{ */ { - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); + spl_array_object *intern = Z_SPLARRAY_P(object); HashTable *result; if (intern->nApplyCount > 1) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "Nesting level too deep - recursive dependency?"); + php_error_docref(NULL, E_ERROR, "Nesting level too deep - recursive dependency?"); } intern->nApplyCount++; - result = spl_array_get_hash_table(intern, 1 TSRMLS_CC); + result = spl_array_get_hash_table(intern, 1); intern->nApplyCount--; return result; } /* }}} */ -static HashTable* spl_array_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{ */ +static HashTable* spl_array_get_debug_info(zval *obj, int *is_temp) /* {{{ */ { - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(obj TSRMLS_CC); - zval *tmp, *storage; - int name_len; - char *zname; + zval *storage; + zend_string *zname; zend_class_entry *base; - - *is_temp = 0; + spl_array_object *intern = Z_SPLARRAY_P(obj); if (!intern->std.properties) { rebuild_object_properties(&intern->std); } - if (HASH_OF(intern->array) == intern->std.properties) { + if (intern->ar_flags & SPL_ARRAY_IS_SELF) { + *is_temp = 0; return intern->std.properties; } else { - if (intern->debug_info == NULL) { - ALLOC_HASHTABLE(intern->debug_info); - ZEND_INIT_SYMTABLE_EX(intern->debug_info, zend_hash_num_elements(intern->std.properties) + 1, 0); - } + HashTable *debug_info; + *is_temp = 1; - if (intern->debug_info->nApplyCount == 0) { - zend_hash_clean(intern->debug_info); - zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); + ALLOC_HASHTABLE(debug_info); + ZEND_INIT_SYMTABLE_EX(debug_info, zend_hash_num_elements(intern->std.properties) + 1, 0); + zend_hash_copy(debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref); - storage = intern->array; - zval_add_ref(&storage); + storage = &intern->array; + Z_TRY_ADDREF_P(storage); - base = (Z_OBJ_HT_P(obj) == &spl_handler_ArrayIterator) ? spl_ce_ArrayIterator : spl_ce_ArrayObject; - zname = spl_gen_private_prop_name(base, "storage", sizeof("storage")-1, &name_len TSRMLS_CC); - zend_symtable_update(intern->debug_info, zname, name_len+1, &storage, sizeof(zval *), NULL); - efree(zname); - } + base = Z_OBJ_HT_P(obj) == &spl_handler_ArrayIterator + ? spl_ce_ArrayIterator : spl_ce_ArrayObject; + zname = spl_gen_private_prop_name(base, "storage", sizeof("storage")-1); + zend_symtable_update(debug_info, zname, storage); + zend_string_release(zname); - return intern->debug_info; + return debug_info; } } /* }}} */ -static zval *spl_array_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */ +static HashTable *spl_array_get_gc(zval *obj, zval **gc_data, int *gc_data_count) /* {{{ */ { - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); + spl_array_object *intern = Z_SPLARRAY_P(obj); + *gc_data = &intern->array; + *gc_data_count = 1; + return zend_std_get_properties(obj); +} +/* }}} */ + +static zval *spl_array_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv) /* {{{ */ +{ + spl_array_object *intern = Z_SPLARRAY_P(object); if ((intern->ar_flags & SPL_ARRAY_ARRAY_AS_PROPS) != 0 - && !std_object_handlers.has_property(object, member, 2, key TSRMLS_CC)) { - return spl_array_read_dimension(object, member, type TSRMLS_CC); + && !std_object_handlers.has_property(object, member, 2, NULL)) { + return spl_array_read_dimension(object, member, type, rv); } - return std_object_handlers.read_property(object, member, type, key TSRMLS_CC); + return std_object_handlers.read_property(object, member, type, cache_slot, rv); } /* }}} */ -static void spl_array_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC) /* {{{ */ +static void spl_array_write_property(zval *object, zval *member, zval *value, void **cache_slot) /* {{{ */ { - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); + spl_array_object *intern = Z_SPLARRAY_P(object); if ((intern->ar_flags & SPL_ARRAY_ARRAY_AS_PROPS) != 0 - && !std_object_handlers.has_property(object, member, 2, key TSRMLS_CC)) { - spl_array_write_dimension(object, member, value TSRMLS_CC); + && !std_object_handlers.has_property(object, member, 2, NULL)) { + spl_array_write_dimension(object, member, value); return; } - std_object_handlers.write_property(object, member, value, key TSRMLS_CC); + std_object_handlers.write_property(object, member, value, cache_slot); } /* }}} */ -static zval **spl_array_get_property_ptr_ptr(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */ +static zval *spl_array_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot) /* {{{ */ { - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); + spl_array_object *intern = Z_SPLARRAY_P(object); if ((intern->ar_flags & SPL_ARRAY_ARRAY_AS_PROPS) != 0 - && !std_object_handlers.has_property(object, member, 2, key TSRMLS_CC)) { - return spl_array_get_dimension_ptr_ptr(1, object, member, type TSRMLS_CC); + && !std_object_handlers.has_property(object, member, 2, NULL)) { + return spl_array_get_dimension_ptr(1, object, member, type); } - return std_object_handlers.get_property_ptr_ptr(object, member, type, key TSRMLS_CC); + return std_object_handlers.get_property_ptr_ptr(object, member, type, cache_slot); } /* }}} */ -static int spl_array_has_property(zval *object, zval *member, int has_set_exists, const zend_literal *key TSRMLS_DC) /* {{{ */ +static int spl_array_has_property(zval *object, zval *member, int has_set_exists, void **cache_slot) /* {{{ */ { - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); + spl_array_object *intern = Z_SPLARRAY_P(object); if ((intern->ar_flags & SPL_ARRAY_ARRAY_AS_PROPS) != 0 - && !std_object_handlers.has_property(object, member, 2, key TSRMLS_CC)) { - return spl_array_has_dimension(object, member, has_set_exists TSRMLS_CC); + && !std_object_handlers.has_property(object, member, 2, NULL)) { + return spl_array_has_dimension(object, member, has_set_exists); } - return std_object_handlers.has_property(object, member, has_set_exists, key TSRMLS_CC); + return std_object_handlers.has_property(object, member, has_set_exists, cache_slot); } /* }}} */ -static void spl_array_unset_property(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */ +static void spl_array_unset_property(zval *object, zval *member, void **cache_slot) /* {{{ */ { - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); + spl_array_object *intern = Z_SPLARRAY_P(object); if ((intern->ar_flags & SPL_ARRAY_ARRAY_AS_PROPS) != 0 - && !std_object_handlers.has_property(object, member, 2, key TSRMLS_CC)) { - spl_array_unset_dimension(object, member TSRMLS_CC); - spl_array_rewind(intern TSRMLS_CC); /* because deletion might invalidate position */ + && !std_object_handlers.has_property(object, member, 2, NULL)) { + spl_array_unset_dimension(object, member); return; } - std_object_handlers.unset_property(object, member, key TSRMLS_CC); + std_object_handlers.unset_property(object, member, cache_slot); } /* }}} */ -static int spl_array_compare_objects(zval *o1, zval *o2 TSRMLS_DC) /* {{{ */ +static int spl_array_compare_objects(zval *o1, zval *o2) /* {{{ */ { HashTable *ht1, *ht2; spl_array_object *intern1, *intern2; int result = 0; - zval temp_zv; - intern1 = (spl_array_object*)zend_object_store_get_object(o1 TSRMLS_CC); - intern2 = (spl_array_object*)zend_object_store_get_object(o2 TSRMLS_CC); - ht1 = spl_array_get_hash_table(intern1, 0 TSRMLS_CC); - ht2 = spl_array_get_hash_table(intern2, 0 TSRMLS_CC); + intern1 = Z_SPLARRAY_P(o1); + intern2 = Z_SPLARRAY_P(o2); + ht1 = spl_array_get_hash_table(intern1, 0); + ht2 = spl_array_get_hash_table(intern2, 0); - zend_compare_symbol_tables(&temp_zv, ht1, ht2 TSRMLS_CC); - result = (int)Z_LVAL(temp_zv); + result = zend_compare_symbol_tables(ht1, ht2); /* if we just compared std.properties, don't do it again */ if (result == 0 && !(ht1 == intern1->std.properties && ht2 == intern2->std.properties)) { - result = std_object_handlers.compare_objects(o1, o2 TSRMLS_CC); + result = std_object_handlers.compare_objects(o1, o2); } return result; } /* }}} */ -static int spl_array_skip_protected(spl_array_object *intern, HashTable *aht TSRMLS_DC) /* {{{ */ +static int spl_array_skip_protected(spl_array_object *intern, HashTable *aht) /* {{{ */ { - char *string_key; - uint string_length; - ulong num_key; + zend_string *string_key; + zend_ulong num_key; + zval *data; + + if (spl_array_is_object(intern)) { + uint32_t *pos_ptr = spl_array_get_pos_ptr(aht, intern); - if (Z_TYPE_P(intern->array) == IS_OBJECT) { do { - if (zend_hash_get_current_key_ex(aht, &string_key, &string_length, &num_key, 0, &intern->pos) == HASH_KEY_IS_STRING) { - /* zend_hash_get_current_key_ex() should never set - * string_length to 0 when returning HASH_KEY_IS_STRING, but we - * may as well be defensive and consider that successful. - * Beyond that, we're looking for protected keys (which will - * have a null byte at string_key[0]), but want to avoid - * skipping completely empty keys (which will also have the - * null byte, but a string_length of 1). */ - if (!string_length || string_key[0] || string_length == 1) { + if (zend_hash_get_current_key_ex(aht, &string_key, &num_key, pos_ptr) == HASH_KEY_IS_STRING) { + data = zend_hash_get_current_data_ex(aht, pos_ptr); + if (data && Z_TYPE_P(data) == IS_INDIRECT && + Z_TYPE_P(data = Z_INDIRECT_P(data)) == IS_UNDEF) { + /* skip */ + } else if (!ZSTR_LEN(string_key) || ZSTR_VAL(string_key)[0]) { return SUCCESS; } } else { return SUCCESS; } - if (zend_hash_has_more_elements_ex(aht, &intern->pos) != SUCCESS) { + if (zend_hash_has_more_elements_ex(aht, pos_ptr) != SUCCESS) { return FAILURE; } - zend_hash_move_forward_ex(aht, &intern->pos); - spl_array_update_pos(intern); + zend_hash_move_forward_ex(aht, pos_ptr); } while (1); } return FAILURE; } /* }}} */ -static int spl_array_next_no_verify(spl_array_object *intern, HashTable *aht TSRMLS_DC) /* {{{ */ +static int spl_array_next_ex(spl_array_object *intern, HashTable *aht) /* {{{ */ { - zend_hash_move_forward_ex(aht, &intern->pos); - spl_array_update_pos(intern); - if (Z_TYPE_P(intern->array) == IS_OBJECT) { - return spl_array_skip_protected(intern, aht TSRMLS_CC); - } else { - return zend_hash_has_more_elements_ex(aht, &intern->pos); - } -} /* }}} */ + uint32_t *pos_ptr = spl_array_get_pos_ptr(aht, intern); -static int spl_array_next_ex(spl_array_object *intern, HashTable *aht TSRMLS_DC) /* {{{ */ -{ - if ((intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(intern, aht TSRMLS_CC) == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid"); - return FAILURE; + zend_hash_move_forward_ex(aht, pos_ptr); + if (spl_array_is_object(intern)) { + return spl_array_skip_protected(intern, aht); + } else { + return zend_hash_has_more_elements_ex(aht, pos_ptr); } - - return spl_array_next_no_verify(intern, aht TSRMLS_CC); } /* }}} */ -static int spl_array_next(spl_array_object *intern TSRMLS_DC) /* {{{ */ +static int spl_array_next(spl_array_object *intern) /* {{{ */ { - HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); + HashTable *aht = spl_array_get_hash_table(intern, 0); - return spl_array_next_ex(intern, aht TSRMLS_CC); + return spl_array_next_ex(intern, aht); } /* }}} */ -/* define an overloaded iterator structure */ -typedef struct { - zend_user_iterator intern; - spl_array_object *object; -} spl_array_it; - -static void spl_array_it_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ +static void spl_array_it_dtor(zend_object_iterator *iter) /* {{{ */ { - spl_array_it *iterator = (spl_array_it *)iter; - - zend_user_it_invalidate_current(iter TSRMLS_CC); - zval_ptr_dtor((zval**)&iterator->intern.it.data); - - efree(iterator); + zend_user_it_invalidate_current(iter); + zval_ptr_dtor(&iter->data); } /* }}} */ -static int spl_array_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ +static int spl_array_it_valid(zend_object_iterator *iter) /* {{{ */ { - spl_array_it *iterator = (spl_array_it *)iter; - spl_array_object *object = iterator->object; - HashTable *aht = spl_array_get_hash_table(object, 0 TSRMLS_CC); + spl_array_object *object = Z_SPLARRAY_P(&iter->data); + HashTable *aht = spl_array_get_hash_table(object, 0); if (object->ar_flags & SPL_ARRAY_OVERLOADED_VALID) { - return zend_user_it_valid(iter TSRMLS_CC); + return zend_user_it_valid(iter); } else { - if (spl_array_object_verify_pos_ex(object, aht, "ArrayIterator::valid(): " TSRMLS_CC) == FAILURE) { + if (spl_array_object_verify_pos_ex(object, aht, "ArrayIterator::valid(): ") == FAILURE) { return FAILURE; } - return zend_hash_has_more_elements_ex(aht, &object->pos); + return zend_hash_has_more_elements_ex(aht, spl_array_get_pos_ptr(aht, object)); } } /* }}} */ -static void spl_array_it_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */ +static zval *spl_array_it_get_current_data(zend_object_iterator *iter) /* {{{ */ { - spl_array_it *iterator = (spl_array_it *)iter; - spl_array_object *object = iterator->object; - HashTable *aht = spl_array_get_hash_table(object, 0 TSRMLS_CC); + spl_array_object *object = Z_SPLARRAY_P(&iter->data); + HashTable *aht = spl_array_get_hash_table(object, 0); if (object->ar_flags & SPL_ARRAY_OVERLOADED_CURRENT) { - zend_user_it_get_current_data(iter, data TSRMLS_CC); + return zend_user_it_get_current_data(iter); } else { - if (zend_hash_get_current_data_ex(aht, (void**)data, &object->pos) == FAILURE) { - *data = NULL; + zval *data = zend_hash_get_current_data_ex(aht, spl_array_get_pos_ptr(aht, object)); + if (Z_TYPE_P(data) == IS_INDIRECT) { + data = Z_INDIRECT_P(data); } + return data; } } /* }}} */ -static void spl_array_it_get_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) /* {{{ */ +static void spl_array_it_get_current_key(zend_object_iterator *iter, zval *key) /* {{{ */ { - spl_array_it *iterator = (spl_array_it *)iter; - spl_array_object *object = iterator->object; - HashTable *aht = spl_array_get_hash_table(object, 0 TSRMLS_CC); + spl_array_object *object = Z_SPLARRAY_P(&iter->data); + HashTable *aht = spl_array_get_hash_table(object, 0); if (object->ar_flags & SPL_ARRAY_OVERLOADED_KEY) { - zend_user_it_get_current_key(iter, key TSRMLS_CC); + zend_user_it_get_current_key(iter, key); } else { - if (spl_array_object_verify_pos_ex(object, aht, "ArrayIterator::current(): " TSRMLS_CC) == FAILURE) { + if (spl_array_object_verify_pos_ex(object, aht, "ArrayIterator::current(): ") == FAILURE) { ZVAL_NULL(key); } else { - zend_hash_get_current_key_zval_ex(aht, key, &object->pos); + zend_hash_get_current_key_zval_ex(aht, key, spl_array_get_pos_ptr(aht, object)); } } } /* }}} */ -static void spl_array_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ +static void spl_array_it_move_forward(zend_object_iterator *iter) /* {{{ */ { - spl_array_it *iterator = (spl_array_it *)iter; - spl_array_object *object = iterator->object; - HashTable *aht = spl_array_get_hash_table(object, 0 TSRMLS_CC); + spl_array_object *object = Z_SPLARRAY_P(&iter->data); + HashTable *aht = spl_array_get_hash_table(object, 0); if (object->ar_flags & SPL_ARRAY_OVERLOADED_NEXT) { - zend_user_it_move_forward(iter TSRMLS_CC); + zend_user_it_move_forward(iter); } else { - zend_user_it_invalidate_current(iter TSRMLS_CC); + zend_user_it_invalidate_current(iter); if (!aht) { - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::current(): Array was modified outside object and is no longer an array"); + php_error_docref(NULL, E_NOTICE, "ArrayIterator::current(): Array was modified outside object and is no longer an array"); return; } - if ((object->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(object, aht TSRMLS_CC) == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::next(): Array was modified outside object and internal position is no longer valid"); - } else { - spl_array_next_no_verify(object, aht TSRMLS_CC); - } + spl_array_next_ex(object, aht); } } /* }}} */ -static void spl_array_rewind_ex(spl_array_object *intern, HashTable *aht TSRMLS_DC) /* {{{ */ +static void spl_array_rewind(spl_array_object *intern) /* {{{ */ { - - zend_hash_internal_pointer_reset_ex(aht, &intern->pos); - spl_array_update_pos(intern); - spl_array_skip_protected(intern, aht TSRMLS_CC); - -} /* }}} */ - -static void spl_array_rewind(spl_array_object *intern TSRMLS_DC) /* {{{ */ -{ - HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); + HashTable *aht = spl_array_get_hash_table(intern, 0); if (!aht) { - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::rewind(): Array was modified outside object and is no longer an array"); + php_error_docref(NULL, E_NOTICE, "ArrayIterator::rewind(): Array was modified outside object and is no longer an array"); return; } - spl_array_rewind_ex(intern, aht TSRMLS_CC); + if (intern->ht_iter == (uint32_t)-1) { + spl_array_get_pos_ptr(aht, intern); + } else { + zend_hash_internal_pointer_reset_ex(aht, spl_array_get_pos_ptr(aht, intern)); + spl_array_skip_protected(intern, aht); + } } /* }}} */ -static void spl_array_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ +static void spl_array_it_rewind(zend_object_iterator *iter) /* {{{ */ { - spl_array_it *iterator = (spl_array_it *)iter; - spl_array_object *object = iterator->object; + spl_array_object *object = Z_SPLARRAY_P(&iter->data); if (object->ar_flags & SPL_ARRAY_OVERLOADED_REWIND) { - zend_user_it_rewind(iter TSRMLS_CC); + zend_user_it_rewind(iter); } else { - zend_user_it_invalidate_current(iter TSRMLS_CC); - spl_array_rewind(object TSRMLS_CC); + zend_user_it_invalidate_current(iter); + spl_array_rewind(object); } } /* }}} */ /* {{{ spl_array_set_array */ -static void spl_array_set_array(zval *object, spl_array_object *intern, zval **array, long ar_flags, int just_array TSRMLS_DC) { - - if (Z_TYPE_PP(array) == IS_ARRAY) { - SEPARATE_ZVAL_IF_NOT_REF(array); +static void spl_array_set_array(zval *object, spl_array_object *intern, zval *array, zend_long ar_flags, int just_array) { + if (Z_TYPE_P(array) != IS_OBJECT && Z_TYPE_P(array) != IS_ARRAY) { + zend_throw_exception(spl_ce_InvalidArgumentException, "Passed variable is not an array or object, using empty array instead", 0); + return; } - if (Z_TYPE_PP(array) == IS_OBJECT && (Z_OBJ_HT_PP(array) == &spl_handler_ArrayObject || Z_OBJ_HT_PP(array) == &spl_handler_ArrayIterator)) { - zval_ptr_dtor(&intern->array); - if (just_array) { - spl_array_object *other = (spl_array_object*)zend_object_store_get_object(*array TSRMLS_CC); - ar_flags = other->ar_flags & ~SPL_ARRAY_INT_MASK; - } - ar_flags |= SPL_ARRAY_USE_OTHER; - intern->array = *array; - } else { - if (Z_TYPE_PP(array) != IS_OBJECT && Z_TYPE_PP(array) != IS_ARRAY) { - zend_throw_exception(spl_ce_InvalidArgumentException, "Passed variable is not an array or object, using empty array instead", 0 TSRMLS_CC); - return; - } - zval_ptr_dtor(&intern->array); - intern->array = *array; - } - if (object == *array) { - intern->ar_flags |= SPL_ARRAY_IS_SELF; - intern->ar_flags &= ~SPL_ARRAY_USE_OTHER; + zval_ptr_dtor(&intern->array); + + if (Z_TYPE_P(array) == IS_ARRAY) { + //??? TODO: try to avoid array duplication + ZVAL_DUP(&intern->array, array); } else { - intern->ar_flags &= ~SPL_ARRAY_IS_SELF; - } - intern->ar_flags |= ar_flags; - Z_ADDREF_P(intern->array); - if (Z_TYPE_PP(array) == IS_OBJECT) { - zend_object_get_properties_t handler = Z_OBJ_HANDLER_PP(array, get_properties); - if ((handler != std_object_handlers.get_properties && handler != spl_array_get_properties) - || !spl_array_get_hash_table(intern, 0 TSRMLS_CC)) { - zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Overloaded object of type %s is not compatible with %s", Z_OBJCE_PP(array)->name, intern->std.ce->name); + if (Z_OBJ_HT_P(array) == &spl_handler_ArrayObject || Z_OBJ_HT_P(array) == &spl_handler_ArrayIterator) { + if (just_array) { + spl_array_object *other = Z_SPLARRAY_P(array); + ar_flags = other->ar_flags & ~SPL_ARRAY_INT_MASK; + } + if (Z_OBJ_P(object) == Z_OBJ_P(array)) { + ar_flags |= SPL_ARRAY_IS_SELF; + ZVAL_UNDEF(&intern->array); + } else { + ar_flags |= SPL_ARRAY_USE_OTHER; + ZVAL_COPY(&intern->array, array); + } + } else { + zend_object_get_properties_t handler = Z_OBJ_HANDLER_P(array, get_properties); + if (handler != std_object_handlers.get_properties + || !spl_array_get_hash_table(intern, 0)) { + ZVAL_UNDEF(&intern->array); + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "Overloaded object of type %s is not compatible with %s", Z_OBJCE_P(array)->name, intern->std.ce->name); + } + //??? TODO: try to avoid array duplication + if (Z_OBJ_P(array)->properties && GC_REFCOUNT(Z_OBJ_P(array)->properties) > 1) { + if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array)->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(Z_OBJ_P(array)->properties)--; + } + Z_OBJ_P(array)->properties = zend_array_dup(Z_OBJ_P(array)->properties); + } + ZVAL_COPY(&intern->array, array); } } - spl_array_rewind(intern TSRMLS_CC); + intern->ar_flags &= ~SPL_ARRAY_IS_SELF & ~SPL_ARRAY_USE_OTHER; + intern->ar_flags |= ar_flags; + intern->ht_iter = (uint32_t)-1; } /* }}} */ @@ -1171,63 +1151,56 @@ zend_object_iterator_funcs spl_array_it_funcs = { spl_array_it_rewind }; -zend_object_iterator *spl_array_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */ +zend_object_iterator *spl_array_get_iterator(zend_class_entry *ce, zval *object, int by_ref) /* {{{ */ { - spl_array_it *iterator; - spl_array_object *array_object = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); + zend_user_iterator *iterator; + spl_array_object *array_object = Z_SPLARRAY_P(object); if (by_ref && (array_object->ar_flags & SPL_ARRAY_OVERLOADED_CURRENT)) { zend_error(E_ERROR, "An iterator cannot be used with foreach by reference"); } - iterator = emalloc(sizeof(spl_array_it)); + iterator = emalloc(sizeof(zend_user_iterator)); + + zend_iterator_init(&iterator->it); - Z_ADDREF_P(object); - iterator->intern.it.data = (void*)object; - iterator->intern.it.funcs = &spl_array_it_funcs; - iterator->intern.ce = ce; - iterator->intern.value = NULL; - iterator->object = array_object; + ZVAL_COPY(&iterator->it.data, object); + iterator->it.funcs = &spl_array_it_funcs; + iterator->ce = ce; + ZVAL_UNDEF(&iterator->value); - return (zend_object_iterator*)iterator; + return &iterator->it; } /* }}} */ -/* {{{ proto void ArrayObject::__construct(array|object ar = array() [, int flags = 0 [, string iterator_class = "ArrayIterator"]]) - proto void ArrayIterator::__construct(array|object ar = array() [, int flags = 0]) +/* {{{ proto void ArrayObject::__construct([array|object ar = array() [, int flags = 0 [, string iterator_class = "ArrayIterator"]]]) + proto void ArrayIterator::__construct([array|object ar = array() [, int flags = 0]]) Constructs a new array iterator from a path. */ SPL_METHOD(Array, __construct) { zval *object = getThis(); spl_array_object *intern; - zval **array; - long ar_flags = 0; + zval *array; + zend_long ar_flags = 0; zend_class_entry *ce_get_iterator = spl_ce_Iterator; - zend_error_handling error_handling; if (ZEND_NUM_ARGS() == 0) { return; /* nothing to do */ } - zend_replace_error_handling(EH_THROW, spl_ce_InvalidArgumentException, &error_handling TSRMLS_CC); - - intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|lC", &array, &ar_flags, &ce_get_iterator) == FAILURE) { - zend_restore_error_handling(&error_handling TSRMLS_CC); + if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "z|lC", &array, &ar_flags, &ce_get_iterator) == FAILURE) { return; } + intern = Z_SPLARRAY_P(object); + if (ZEND_NUM_ARGS() > 2) { intern->ce_get_iterator = ce_get_iterator; } ar_flags &= ~SPL_ARRAY_INT_MASK; - spl_array_set_array(object, intern, array, ar_flags, ZEND_NUM_ARGS() == 1 TSRMLS_CC); - - zend_restore_error_handling(&error_handling TSRMLS_CC); - + spl_array_set_array(object, intern, array, ar_flags, ZEND_NUM_ARGS() == 1); } /* }}} */ @@ -1236,12 +1209,18 @@ SPL_METHOD(Array, __construct) SPL_METHOD(Array, setIteratorClass) { zval *object = getThis(); - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); + spl_array_object *intern = Z_SPLARRAY_P(object); zend_class_entry * ce_get_iterator = spl_ce_Iterator; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "C", &ce_get_iterator) == FAILURE) { +#ifndef FAST_ZPP + if (zend_parse_parameters(ZEND_NUM_ARGS(), "C", &ce_get_iterator) == FAILURE) { return; } +#else + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_CLASS(ce_get_iterator) + ZEND_PARSE_PARAMETERS_END(); +#endif intern->ce_get_iterator = ce_get_iterator; } @@ -1252,13 +1231,14 @@ SPL_METHOD(Array, setIteratorClass) SPL_METHOD(Array, getIteratorClass) { zval *object = getThis(); - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); + spl_array_object *intern = Z_SPLARRAY_P(object); if (zend_parse_parameters_none() == FAILURE) { return; } - RETURN_STRING(intern->ce_get_iterator->name, 1); + zend_string_addref(intern->ce_get_iterator->name); + RETURN_STR(intern->ce_get_iterator->name); } /* }}} */ @@ -1267,7 +1247,7 @@ SPL_METHOD(Array, getIteratorClass) SPL_METHOD(Array, getFlags) { zval *object = getThis(); - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); + spl_array_object *intern = Z_SPLARRAY_P(object); if (zend_parse_parameters_none() == FAILURE) { return; @@ -1282,10 +1262,10 @@ SPL_METHOD(Array, getFlags) SPL_METHOD(Array, setFlags) { zval *object = getThis(); - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); - long ar_flags = 0; + spl_array_object *intern = Z_SPLARRAY_P(object); + zend_long ar_flags = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &ar_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &ar_flags) == FAILURE) { return; } @@ -1297,18 +1277,15 @@ SPL_METHOD(Array, setFlags) Replace the referenced array or object with a new one and return the old one (right now copy - to be changed) */ SPL_METHOD(Array, exchangeArray) { - zval *object = getThis(), *tmp, **array; - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); - - array_init(return_value); - zend_hash_copy(HASH_OF(return_value), spl_array_get_hash_table(intern, 0 TSRMLS_CC), (copy_ctor_func_t) zval_add_ref, &tmp, sizeof(zval*)); + zval *object = getThis(), *array; + spl_array_object *intern = Z_SPLARRAY_P(object); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &array) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &array) == FAILURE) { return; } - spl_array_set_array(object, intern, array, 0L, 1 TSRMLS_CC); - + RETVAL_ARR(zend_array_dup(spl_array_get_hash_table(intern, 0))); + spl_array_set_array(object, intern, array, 0L, 1); } /* }}} */ @@ -1317,23 +1294,19 @@ SPL_METHOD(Array, exchangeArray) SPL_METHOD(Array, getIterator) { zval *object = getThis(); - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); - spl_array_object *iterator; - HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); + spl_array_object *intern = Z_SPLARRAY_P(object); + HashTable *aht = spl_array_get_hash_table(intern, 0); if (zend_parse_parameters_none() == FAILURE) { return; } if (!aht) { - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array"); + php_error_docref(NULL, E_NOTICE, "Array was modified outside object and is no longer an array"); return; } - return_value->type = IS_OBJECT; - return_value->value.obj = spl_array_object_new_ex(intern->ce_get_iterator, &iterator, object, 0 TSRMLS_CC); - Z_SET_REFCOUNT_P(return_value, 1); - Z_SET_ISREF_P(return_value); + ZVAL_OBJ(return_value, spl_array_object_new_ex(intern->ce_get_iterator, object, 0)); } /* }}} */ @@ -1342,13 +1315,13 @@ SPL_METHOD(Array, getIterator) SPL_METHOD(Array, rewind) { zval *object = getThis(); - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); + spl_array_object *intern = Z_SPLARRAY_P(object); if (zend_parse_parameters_none() == FAILURE) { return; } - spl_array_rewind(intern TSRMLS_CC); + spl_array_rewind(intern); } /* }}} */ @@ -1356,57 +1329,58 @@ SPL_METHOD(Array, rewind) Seek to position. */ SPL_METHOD(Array, seek) { - long opos, position; + zend_long opos, position; zval *object = getThis(); - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); - HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); + spl_array_object *intern = Z_SPLARRAY_P(object); + HashTable *aht = spl_array_get_hash_table(intern, 0); int result; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &position) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &position) == FAILURE) { return; } if (!aht) { - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array"); + php_error_docref(NULL, E_NOTICE, "Array was modified outside object and is no longer an array"); return; } opos = position; if (position >= 0) { /* negative values are not supported */ - spl_array_rewind(intern TSRMLS_CC); + spl_array_rewind(intern); result = SUCCESS; - while (position-- > 0 && (result = spl_array_next(intern TSRMLS_CC)) == SUCCESS); + while (position-- > 0 && (result = spl_array_next(intern)) == SUCCESS); - if (result == SUCCESS && zend_hash_has_more_elements_ex(aht, &intern->pos) == SUCCESS) { + if (result == SUCCESS && zend_hash_has_more_elements_ex(aht, spl_array_get_pos_ptr(aht, intern)) == SUCCESS) { return; /* ok */ } } - zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0 TSRMLS_CC, "Seek position %ld is out of range", opos); + zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0, "Seek position %pd is out of range", opos); } /* }}} */ -int static spl_array_object_count_elements_helper(spl_array_object *intern, long *count TSRMLS_DC) /* {{{ */ +int static spl_array_object_count_elements_helper(spl_array_object *intern, zend_long *count) /* {{{ */ { - HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); - HashPosition pos; + HashTable *aht = spl_array_get_hash_table(intern, 0); + HashPosition pos, *pos_ptr; if (!aht) { - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array"); + php_error_docref(NULL, E_NOTICE, "Array was modified outside object and is no longer an array"); *count = 0; return FAILURE; } - if (Z_TYPE_P(intern->array) == IS_OBJECT) { + if (spl_array_is_object(intern)) { /* We need to store the 'pos' since we'll modify it in the functions * we're going to call and which do not support 'pos' as parameter. */ - pos = intern->pos; + pos_ptr = spl_array_get_pos_ptr(aht, intern); + pos = *pos_ptr; *count = 0; - spl_array_rewind(intern TSRMLS_CC); - while(intern->pos && spl_array_next(intern TSRMLS_CC) == SUCCESS) { + spl_array_rewind(intern); + while (*pos_ptr != HT_INVALID_IDX && spl_array_next(intern) == SUCCESS) { (*count)++; } - spl_array_set_pos(intern, pos); + *pos_ptr = pos; return SUCCESS; } else { *count = zend_hash_num_elements(aht); @@ -1414,25 +1388,22 @@ int static spl_array_object_count_elements_helper(spl_array_object *intern, long } } /* }}} */ -int spl_array_object_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */ +int spl_array_object_count_elements(zval *object, zend_long *count) /* {{{ */ { - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); + spl_array_object *intern = Z_SPLARRAY_P(object); if (intern->fptr_count) { - zval *rv; - zend_call_method_with_0_params(&object, intern->std.ce, &intern->fptr_count, "count", &rv); - if (rv) { - zval_ptr_dtor(&intern->retval); - MAKE_STD_ZVAL(intern->retval); - ZVAL_ZVAL(intern->retval, rv, 1, 1); - convert_to_long(intern->retval); - *count = (long) Z_LVAL_P(intern->retval); + zval rv; + zend_call_method_with_0_params(object, intern->std.ce, &intern->fptr_count, "count", &rv); + if (Z_TYPE(rv) != IS_UNDEF) { + *count = zval_get_long(&rv); + zval_ptr_dtor(&rv); return SUCCESS; } *count = 0; return FAILURE; } - return spl_array_object_count_elements_helper(intern, count TSRMLS_CC); + return spl_array_object_count_elements_helper(intern, count); } /* }}} */ /* {{{ proto int ArrayObject::count() @@ -1440,59 +1411,65 @@ int spl_array_object_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ Return the number of elements in the Iterator. */ SPL_METHOD(Array, count) { - long count; - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + zend_long count; + spl_array_object *intern = Z_SPLARRAY_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; } - spl_array_object_count_elements_helper(intern, &count TSRMLS_CC); + spl_array_object_count_elements_helper(intern, &count); RETURN_LONG(count); } /* }}} */ static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, int fname_len, int use_arg) /* {{{ */ { - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); - zval *tmp, *arg = NULL; - zval *retval_ptr = NULL; + spl_array_object *intern = Z_SPLARRAY_P(getThis()); + HashTable *aht = spl_array_get_hash_table(intern, 0); + zval function_name, params[2], *arg = NULL; + uint32_t old_refcount; + + ZVAL_STRINGL(&function_name, fname, fname_len); - MAKE_STD_ZVAL(tmp); - Z_TYPE_P(tmp) = IS_ARRAY; - Z_ARRVAL_P(tmp) = aht; + /* A tricky way to pass "aht" by reference, reset refcount */ + //??? It may be not safe, if user comparison handler accesses "aht" + old_refcount = GC_REFCOUNT(aht); + GC_REFCOUNT(aht) = 1; + ZVAL_NEW_EMPTY_REF(¶ms[0]); + ZVAL_ARR(Z_REFVAL(params[0]), aht); if (!use_arg) { - aht->nApplyCount++; - zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, 1, tmp, NULL TSRMLS_CC); - aht->nApplyCount--; + aht->u.v.nApplyCount++; + call_user_function_ex(EG(function_table), NULL, &function_name, return_value, 1, params, 1, NULL); + aht->u.v.nApplyCount--; } else if (use_arg == SPL_ARRAY_METHOD_MAY_USER_ARG) { - if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "|z", &arg) == FAILURE) { - Z_TYPE_P(tmp) = IS_NULL; - zval_ptr_dtor(&tmp); - zend_throw_exception(spl_ce_BadMethodCallException, "Function expects one argument at most", 0 TSRMLS_CC); - return; + if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "|z", &arg) == FAILURE) { + zend_throw_exception(spl_ce_BadMethodCallException, "Function expects one argument at most", 0); + goto exit; } - aht->nApplyCount++; - zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, arg? 2 : 1, tmp, arg TSRMLS_CC); - aht->nApplyCount--; + if (arg) { + ZVAL_COPY_VALUE(¶ms[1], arg); + } + aht->u.v.nApplyCount++; + call_user_function_ex(EG(function_table), NULL, &function_name, return_value, arg ? 2 : 1, params, 1, NULL); + aht->u.v.nApplyCount--; } else { - if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg) == FAILURE) { - Z_TYPE_P(tmp) = IS_NULL; - zval_ptr_dtor(&tmp); - zend_throw_exception(spl_ce_BadMethodCallException, "Function expects exactly one argument", 0 TSRMLS_CC); - return; + if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "z", &arg) == FAILURE) { + zend_throw_exception(spl_ce_BadMethodCallException, "Function expects exactly one argument", 0); + goto exit; } - aht->nApplyCount++; - zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, 2, tmp, arg TSRMLS_CC); - aht->nApplyCount--; - } - Z_TYPE_P(tmp) = IS_NULL; /* we want to destroy the zval, not the hashtable */ - zval_ptr_dtor(&tmp); - if (retval_ptr) { - COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr); + ZVAL_COPY_VALUE(¶ms[1], arg); + aht->u.v.nApplyCount++; + call_user_function_ex(EG(function_table), NULL, &function_name, return_value, 2, params, 1, NULL); + aht->u.v.nApplyCount--; } + +exit: + /* A tricky way to pass "aht" by reference, copy back and cleanup */ + GC_REFCOUNT(aht) = old_refcount; + efree(Z_REF(params[0])); + zend_string_free(Z_STR(function_name)); } /* }}} */ #define SPL_ARRAY_METHOD(cname, fname, use_arg) \ @@ -1536,22 +1513,29 @@ SPL_ARRAY_METHOD(Array, natcasesort, SPL_ARRAY_METHOD_NO_ARG) /* }}} */ SPL_METHOD(Array, current) { zval *object = getThis(); - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); - zval **entry; - HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); + spl_array_object *intern = Z_SPLARRAY_P(object); + zval *entry; + HashTable *aht = spl_array_get_hash_table(intern, 0); if (zend_parse_parameters_none() == FAILURE) { return; } - if (spl_array_object_verify_pos(intern, aht TSRMLS_CC) == FAILURE) { + if (spl_array_object_verify_pos(intern, aht) == FAILURE) { return; } - if (zend_hash_get_current_data_ex(aht, (void **) &entry, &intern->pos) == FAILURE) { + if ((entry = zend_hash_get_current_data_ex(aht, spl_array_get_pos_ptr(aht, intern))) == NULL) { return; } - RETVAL_ZVAL(*entry, 1, 0); + if (Z_TYPE_P(entry) == IS_INDIRECT) { + entry = Z_INDIRECT_P(entry); + if (Z_TYPE_P(entry) == IS_UNDEF) { + return; + } + } + ZVAL_DEREF(entry); + ZVAL_COPY(return_value, entry); } /* }}} */ @@ -1563,19 +1547,19 @@ SPL_METHOD(Array, key) return; } - spl_array_iterator_key(getThis(), return_value TSRMLS_CC); + spl_array_iterator_key(getThis(), return_value); } /* }}} */ -void spl_array_iterator_key(zval *object, zval *return_value TSRMLS_DC) /* {{{ */ +void spl_array_iterator_key(zval *object, zval *return_value) /* {{{ */ { - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); - HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); + spl_array_object *intern = Z_SPLARRAY_P(object); + HashTable *aht = spl_array_get_hash_table(intern, 0); - if (spl_array_object_verify_pos(intern, aht TSRMLS_CC) == FAILURE) { + if (spl_array_object_verify_pos(intern, aht) == FAILURE) { return; } - zend_hash_get_current_key_zval_ex(aht, return_value, &intern->pos); + zend_hash_get_current_key_zval_ex(aht, return_value, spl_array_get_pos_ptr(aht, intern)); } /* }}} */ @@ -1584,18 +1568,18 @@ void spl_array_iterator_key(zval *object, zval *return_value TSRMLS_DC) /* {{{ * SPL_METHOD(Array, next) { zval *object = getThis(); - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); - HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); + spl_array_object *intern = Z_SPLARRAY_P(object); + HashTable *aht = spl_array_get_hash_table(intern, 0); if (zend_parse_parameters_none() == FAILURE) { return; } - if (spl_array_object_verify_pos(intern, aht TSRMLS_CC) == FAILURE) { + if (spl_array_object_verify_pos(intern, aht) == FAILURE) { return; } - spl_array_next_no_verify(intern, aht TSRMLS_CC); + spl_array_next_ex(intern, aht); } /* }}} */ @@ -1604,17 +1588,17 @@ SPL_METHOD(Array, next) SPL_METHOD(Array, valid) { zval *object = getThis(); - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); - HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); + spl_array_object *intern = Z_SPLARRAY_P(object); + HashTable *aht = spl_array_get_hash_table(intern, 0); if (zend_parse_parameters_none() == FAILURE) { return; } - if (spl_array_object_verify_pos(intern, aht TSRMLS_CC) == FAILURE) { + if (spl_array_object_verify_pos(intern, aht) == FAILURE) { RETURN_FALSE; } else { - RETURN_BOOL(zend_hash_has_more_elements_ex(aht, &intern->pos) == SUCCESS); + RETURN_BOOL(zend_hash_has_more_elements_ex(aht, spl_array_get_pos_ptr(aht, intern)) == SUCCESS); } } /* }}} */ @@ -1623,23 +1607,23 @@ SPL_METHOD(Array, valid) Check whether current element has children (e.g. is an array) */ SPL_METHOD(Array, hasChildren) { - zval *object = getThis(), **entry; - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); - HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); + zval *object = getThis(), *entry; + spl_array_object *intern = Z_SPLARRAY_P(object); + HashTable *aht = spl_array_get_hash_table(intern, 0); if (zend_parse_parameters_none() == FAILURE) { return; } - if (spl_array_object_verify_pos(intern, aht TSRMLS_CC) == FAILURE) { + if (spl_array_object_verify_pos(intern, aht) == FAILURE) { RETURN_FALSE; } - if (zend_hash_get_current_data_ex(aht, (void **) &entry, &intern->pos) == FAILURE) { + if ((entry = zend_hash_get_current_data_ex(aht, spl_array_get_pos_ptr(aht, intern))) == NULL) { RETURN_FALSE; } - RETURN_BOOL(Z_TYPE_PP(entry) == IS_ARRAY || (Z_TYPE_PP(entry) == IS_OBJECT && (intern->ar_flags & SPL_ARRAY_CHILD_ARRAYS_ONLY) == 0)); + RETURN_BOOL(Z_TYPE_P(entry) == IS_ARRAY || (Z_TYPE_P(entry) == IS_OBJECT && (intern->ar_flags & SPL_ARRAY_CHILD_ARRAYS_ONLY) == 0)); } /* }}} */ @@ -1647,35 +1631,35 @@ SPL_METHOD(Array, hasChildren) Create a sub iterator for the current element (same class as $this) */ SPL_METHOD(Array, getChildren) { - zval *object = getThis(), **entry, *flags; - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); - HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); + zval *object = getThis(), *entry, flags; + spl_array_object *intern = Z_SPLARRAY_P(object); + HashTable *aht = spl_array_get_hash_table(intern, 0); if (zend_parse_parameters_none() == FAILURE) { return; } - if (spl_array_object_verify_pos(intern, aht TSRMLS_CC) == FAILURE) { + if (spl_array_object_verify_pos(intern, aht) == FAILURE) { return; } - if (zend_hash_get_current_data_ex(aht, (void **) &entry, &intern->pos) == FAILURE) { + if ((entry = zend_hash_get_current_data_ex(aht, spl_array_get_pos_ptr(aht, intern))) == NULL) { return; } - if (Z_TYPE_PP(entry) == IS_OBJECT) { + if (Z_TYPE_P(entry) == IS_OBJECT) { if ((intern->ar_flags & SPL_ARRAY_CHILD_ARRAYS_ONLY) != 0) { return; } - if (instanceof_function(Z_OBJCE_PP(entry), Z_OBJCE_P(getThis()) TSRMLS_CC)) { - RETURN_ZVAL(*entry, 1, 0); + if (instanceof_function(Z_OBJCE_P(entry), Z_OBJCE_P(getThis()))) { + ZVAL_OBJ(return_value, Z_OBJ_P(entry)); + Z_ADDREF_P(return_value); + return; } } - MAKE_STD_ZVAL(flags); - ZVAL_LONG(flags, SPL_ARRAY_USE_OTHER | intern->ar_flags); - spl_instantiate_arg_ex2(Z_OBJCE_P(getThis()), &return_value, 0, *entry, flags TSRMLS_CC); - zval_ptr_dtor(&flags); + ZVAL_LONG(&flags, intern->ar_flags); + spl_instantiate_arg_ex2(Z_OBJCE_P(getThis()), return_value, entry, &flags); } /* }}} */ @@ -1684,53 +1668,49 @@ SPL_METHOD(Array, getChildren) SPL_METHOD(Array, serialize) { zval *object = getThis(); - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); - HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); - zval members, *pmembers; + spl_array_object *intern = Z_SPLARRAY_P(object); + HashTable *aht = spl_array_get_hash_table(intern, 0); + zval members, flags; php_serialize_data_t var_hash; smart_str buf = {0}; - zval *flags; if (zend_parse_parameters_none() == FAILURE) { return; } if (!aht) { - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array"); + php_error_docref(NULL, E_NOTICE, "Array was modified outside object and is no longer an array"); return; } PHP_VAR_SERIALIZE_INIT(var_hash); - MAKE_STD_ZVAL(flags); - ZVAL_LONG(flags, (intern->ar_flags & SPL_ARRAY_CLONE_MASK)); + ZVAL_LONG(&flags, (intern->ar_flags & SPL_ARRAY_CLONE_MASK)); /* storage */ smart_str_appendl(&buf, "x:", 2); - php_var_serialize(&buf, &flags, &var_hash TSRMLS_CC); - zval_ptr_dtor(&flags); + php_var_serialize(&buf, &flags, &var_hash); if (!(intern->ar_flags & SPL_ARRAY_IS_SELF)) { - php_var_serialize(&buf, &intern->array, &var_hash TSRMLS_CC); + php_var_serialize(&buf, &intern->array, &var_hash); smart_str_appendc(&buf, ';'); } /* members */ smart_str_appendl(&buf, "m:", 2); - INIT_PZVAL(&members); if (!intern->std.properties) { rebuild_object_properties(&intern->std); } - Z_ARRVAL(members) = intern->std.properties; - Z_TYPE(members) = IS_ARRAY; - pmembers = &members; - php_var_serialize(&buf, &pmembers, &var_hash TSRMLS_CC); /* finishes the string */ + + ZVAL_ARR(&members, intern->std.properties); + + php_var_serialize(&buf, &members, &var_hash); /* finishes the string */ /* done */ PHP_VAR_SERIALIZE_DESTROY(var_hash); - if (buf.c) { - RETURN_STRINGL(buf.c, buf.len, 0); + if (buf.s) { + RETURN_NEW_STR(buf.s); } RETURN_NULL(); @@ -1741,17 +1721,17 @@ SPL_METHOD(Array, serialize) */ SPL_METHOD(Array, unserialize) { - spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_array_object *intern = Z_SPLARRAY_P(getThis()); char *buf; - int buf_len; + size_t buf_len; const unsigned char *p, *s; php_unserialize_data_t var_hash; - zval *pmembers, *pflags = NULL; + zval *members, *zflags; HashTable *aht; - long flags; + zend_long flags; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &buf, &buf_len) == FAILURE) { return; } @@ -1759,8 +1739,8 @@ SPL_METHOD(Array, unserialize) return; } - aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); - if (aht->nApplyCount > 0) { + aht = spl_array_get_hash_table(intern, 0); + if (aht->u.v.nApplyCount > 0) { zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); return; } @@ -1774,16 +1754,15 @@ SPL_METHOD(Array, unserialize) } ++p; - ALLOC_INIT_ZVAL(pflags); - if (!php_var_unserialize(&pflags, &p, s + buf_len, &var_hash TSRMLS_CC) || Z_TYPE_P(pflags) != IS_LONG) { + zflags = var_tmp_var(&var_hash); + if (!php_var_unserialize(zflags, &p, s + buf_len, &var_hash) || Z_TYPE_P(zflags) != IS_LONG) { goto outexcept; } - var_push_dtor(&var_hash, &pflags); --p; /* for ';' */ - flags = Z_LVAL_P(pflags); + flags = Z_LVAL_P(zflags); /* flags needs to be verified and we also need to verify whether the next - * thing we get is ';'. After that we require an 'm' or somethign else + * thing we get is ';'. After that we require an 'm' or something else * where 'm' stands for members and anything else should be an array. If * neither 'a' or 'm' follows we have an error. */ @@ -1799,8 +1778,7 @@ SPL_METHOD(Array, unserialize) intern->ar_flags &= ~SPL_ARRAY_CLONE_MASK; intern->ar_flags |= flags & SPL_ARRAY_CLONE_MASK; zval_ptr_dtor(&intern->array); - ALLOC_INIT_ZVAL(intern->array); - if (!php_var_unserialize(&intern->array, &p, s + buf_len, &var_hash TSRMLS_CC)) { + if (!php_var_unserialize(&intern->array, &p, s + buf_len, &var_hash)) { goto outexcept; } var_push_dtor(&var_hash, &intern->array); @@ -1816,34 +1794,21 @@ SPL_METHOD(Array, unserialize) } ++p; - ALLOC_INIT_ZVAL(pmembers); - if (!php_var_unserialize(&pmembers, &p, s + buf_len, &var_hash TSRMLS_CC) || Z_TYPE_P(pmembers) != IS_ARRAY) { - zval_ptr_dtor(&pmembers); + members = var_tmp_var(&var_hash); + if (!php_var_unserialize(members, &p, s + buf_len, &var_hash) || Z_TYPE_P(members) != IS_ARRAY) { goto outexcept; } - var_push_dtor(&var_hash, &pmembers); /* copy members */ - if (!intern->std.properties) { - rebuild_object_properties(&intern->std); - } - zend_hash_copy(intern->std.properties, Z_ARRVAL_P(pmembers), (copy_ctor_func_t) zval_add_ref, (void *) NULL, sizeof(zval *)); - zval_ptr_dtor(&pmembers); + object_properties_load(&intern->std, Z_ARRVAL_P(members)); /* done reading $serialized */ - PHP_VAR_UNSERIALIZE_DESTROY(var_hash); - if (pflags) { - zval_ptr_dtor(&pflags); - } return; outexcept: PHP_VAR_UNSERIALIZE_DESTROY(var_hash); - if (pflags) { - zval_ptr_dtor(&pflags); - } - zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Error at offset %ld of %d bytes", (long)((char*)p - buf), buf_len); + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Error at offset %pd of %d bytes", (zend_long)((char*)p - buf), buf_len); return; } /* }}} */ @@ -1851,6 +1816,8 @@ outexcept: /* {{{ arginfo and function table */ ZEND_BEGIN_ARG_INFO_EX(arginfo_array___construct, 0, 0, 0) ZEND_ARG_INFO(0, array) + ZEND_ARG_INFO(0, ar_flags) + ZEND_ARG_INFO(0, iterator_class) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_array_offsetGet, 0, 0, 1) @@ -1966,6 +1933,8 @@ PHP_MINIT_FUNCTION(spl_array) REGISTER_SPL_IMPLEMENTS(ArrayObject, Countable); memcpy(&spl_handler_ArrayObject, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + spl_handler_ArrayObject.offset = XtOffsetOf(spl_array_object, std); + spl_handler_ArrayObject.clone_obj = spl_array_object_clone; spl_handler_ArrayObject.read_dimension = spl_array_read_dimension; spl_handler_ArrayObject.write_dimension = spl_array_write_dimension; @@ -1975,6 +1944,7 @@ PHP_MINIT_FUNCTION(spl_array) spl_handler_ArrayObject.get_properties = spl_array_get_properties; spl_handler_ArrayObject.get_debug_info = spl_array_get_debug_info; + spl_handler_ArrayObject.get_gc = spl_array_get_gc; spl_handler_ArrayObject.read_property = spl_array_read_property; spl_handler_ArrayObject.write_property = spl_array_write_property; spl_handler_ArrayObject.get_property_ptr_ptr = spl_array_get_property_ptr_ptr; @@ -1982,6 +1952,8 @@ PHP_MINIT_FUNCTION(spl_array) spl_handler_ArrayObject.unset_property = spl_array_unset_property; spl_handler_ArrayObject.compare_objects = spl_array_compare_objects; + spl_handler_ArrayObject.dtor_obj = zend_objects_destroy_object; + spl_handler_ArrayObject.free_obj = spl_array_object_free_storage; REGISTER_SPL_STD_CLASS_EX(ArrayIterator, spl_array_object_new, spl_funcs_ArrayIterator); REGISTER_SPL_IMPLEMENTS(ArrayIterator, Iterator); diff --git a/ext/spl/spl_array.h b/ext/spl/spl_array.h index ae43437cf0..5de3c963cc 100644 --- a/ext/spl/spl_array.h +++ b/ext/spl/spl_array.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -31,8 +31,8 @@ extern PHPAPI zend_class_entry *spl_ce_RecursiveArrayIterator; PHP_MINIT_FUNCTION(spl_array); -extern void spl_array_iterator_append(zval *object, zval *append_value TSRMLS_DC); -extern void spl_array_iterator_key(zval *object, zval *return_value TSRMLS_DC); +extern void spl_array_iterator_append(zval *object, zval *append_value); +extern void spl_array_iterator_key(zval *object, zval *return_value); #endif /* SPL_ARRAY_H */ diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index e60078a539..b0ee3bc7a3 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -60,28 +60,28 @@ PHPAPI zend_class_entry *spl_ce_GlobIterator; PHPAPI zend_class_entry *spl_ce_SplFileObject; PHPAPI zend_class_entry *spl_ce_SplTempFileObject; -static void spl_filesystem_file_free_line(spl_filesystem_object *intern TSRMLS_DC) /* {{{ */ +static void spl_filesystem_file_free_line(spl_filesystem_object *intern) /* {{{ */ { if (intern->u.file.current_line) { efree(intern->u.file.current_line); intern->u.file.current_line = NULL; } - if (intern->u.file.current_zval) { + if (!Z_ISUNDEF(intern->u.file.current_zval)) { zval_ptr_dtor(&intern->u.file.current_zval); - intern->u.file.current_zval = NULL; + ZVAL_UNDEF(&intern->u.file.current_zval); } } /* }}} */ -static void spl_filesystem_object_free_storage(void *object TSRMLS_DC) /* {{{ */ +static void spl_filesystem_object_free_storage(zend_object *object) /* {{{ */ { - spl_filesystem_object *intern = (spl_filesystem_object*)object; + spl_filesystem_object *intern = spl_filesystem_from_obj(object); if (intern->oth_handler && intern->oth_handler->dtor) { - intern->oth_handler->dtor(intern TSRMLS_CC); + intern->oth_handler->dtor(intern); } - - zend_object_std_dtor(&intern->std TSRMLS_CC); - + + zend_object_std_dtor(&intern->std); + if (intern->_path) { efree(intern->_path); } @@ -98,17 +98,19 @@ static void spl_filesystem_object_free_storage(void *object TSRMLS_DC) /* {{{ */ } if (intern->u.dir.sub_path) { efree(intern->u.dir.sub_path); - } + } break; case SPL_FS_FILE: if (intern->u.file.stream) { + /* if (intern->u.file.zcontext) { -/* zend_list_delref(Z_RESVAL_P(intern->zcontext));*/ + zend_list_delref(Z_RESVAL_P(intern->zcontext)); } + */ if (!intern->u.file.stream->is_persistent) { - php_stream_free(intern->u.file.stream, PHP_STREAM_FREE_CLOSE); + php_stream_close(intern->u.file.stream); } else { - php_stream_free(intern->u.file.stream, PHP_STREAM_FREE_CLOSE_PERSISTENT); + php_stream_pclose(intern->u.file.stream); } if (intern->u.file.open_mode) { efree(intern->u.file.open_mode); @@ -117,73 +119,57 @@ static void spl_filesystem_object_free_storage(void *object TSRMLS_DC) /* {{{ */ efree(intern->orig_path); } } - spl_filesystem_file_free_line(intern TSRMLS_CC); + spl_filesystem_file_free_line(intern); break; } - - { - zend_object_iterator *iterator; - iterator = (zend_object_iterator*) - spl_filesystem_object_to_iterator(intern); - if (iterator->data != NULL) { - iterator->data = NULL; - iterator->funcs->dtor(iterator TSRMLS_CC); - } - } - efree(object); } /* }}} */ /* {{{ spl_ce_dir_object_new */ -/* creates the object by - - allocating memory +/* creates the object by + - allocating memory - initializing the object members - storing the object - setting it's handlers - called from + called from - clone - new */ -static zend_object_value spl_filesystem_object_new_ex(zend_class_entry *class_type, spl_filesystem_object **obj TSRMLS_DC) +static zend_object *spl_filesystem_object_new_ex(zend_class_entry *class_type) { - zend_object_value retval; spl_filesystem_object *intern; - intern = emalloc(sizeof(spl_filesystem_object)); - memset(intern, 0, sizeof(spl_filesystem_object)); + intern = ecalloc(1, sizeof(spl_filesystem_object) + zend_object_properties_size(class_type)); /* intern->type = SPL_FS_INFO; done by set 0 */ intern->file_class = spl_ce_SplFileObject; intern->info_class = spl_ce_SplFileInfo; - if (obj) *obj = intern; - zend_object_std_init(&intern->std, class_type TSRMLS_CC); + zend_object_std_init(&intern->std, class_type); object_properties_init(&intern->std, class_type); + intern->std.handlers = &spl_filesystem_object_handlers; - retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_filesystem_object_free_storage, NULL TSRMLS_CC); - retval.handlers = &spl_filesystem_object_handlers; - return retval; + return &intern->std; } /* }}} */ /* {{{ spl_filesystem_object_new */ /* See spl_filesystem_object_new_ex */ -static zend_object_value spl_filesystem_object_new(zend_class_entry *class_type TSRMLS_DC) +static zend_object *spl_filesystem_object_new(zend_class_entry *class_type) { - return spl_filesystem_object_new_ex(class_type, NULL TSRMLS_CC); + return spl_filesystem_object_new_ex(class_type); } /* }}} */ -/* {{{ spl_filesystem_object_new_ex */ -static zend_object_value spl_filesystem_object_new_check(zend_class_entry *class_type TSRMLS_DC) +/* {{{ spl_filesystem_object_new_check */ +static zend_object *spl_filesystem_object_new_check(zend_class_entry *class_type) { - zend_object_value ret = spl_filesystem_object_new_ex(class_type, NULL TSRMLS_CC); - ret.handlers = &spl_filesystem_object_check_handlers; - return ret; + spl_filesystem_object *ret = spl_filesystem_from_obj(spl_filesystem_object_new_ex(class_type)); + ret->std.handlers = &spl_filesystem_object_check_handlers; + return &ret->std; } /* }}} */ - -PHPAPI char* spl_filesystem_object_get_path(spl_filesystem_object *intern, int *len TSRMLS_DC) /* {{{ */ +PHPAPI char* spl_filesystem_object_get_path(spl_filesystem_object *intern, size_t *len) /* {{{ */ { #ifdef HAVE_GLOB if (intern->type == SPL_FS_DIR) { @@ -198,7 +184,7 @@ PHPAPI char* spl_filesystem_object_get_path(spl_filesystem_object *intern, int * return intern->_path; } /* }}} */ -static inline void spl_filesystem_object_get_file_name(spl_filesystem_object *intern TSRMLS_DC) /* {{{ */ +static inline void spl_filesystem_object_get_file_name(spl_filesystem_object *intern) /* {{{ */ { char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH; @@ -206,21 +192,21 @@ static inline void spl_filesystem_object_get_file_name(spl_filesystem_object *in case SPL_FS_INFO: case SPL_FS_FILE: if (!intern->file_name) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "Object not initialized"); + php_error_docref(NULL, E_ERROR, "Object not initialized"); } break; case SPL_FS_DIR: if (intern->file_name) { efree(intern->file_name); } - intern->file_name_len = spprintf(&intern->file_name, 0, "%s%c%s", - spl_filesystem_object_get_path(intern, NULL TSRMLS_CC), + intern->file_name_len = (int)spprintf(&intern->file_name, 0, "%s%c%s", + spl_filesystem_object_get_path(intern, NULL), slash, intern->u.dir.entry.d_name); break; } } /* }}} */ -static int spl_filesystem_dir_read(spl_filesystem_object *intern TSRMLS_DC) /* {{{ */ +static int spl_filesystem_dir_read(spl_filesystem_object *intern) /* {{{ */ { if (!intern->u.dir.dirp || !php_stream_readdir(intern->u.dir.dirp, &intern->u.dir.entry)) { intern->u.dir.entry.d_name[0] = '\0'; @@ -241,12 +227,12 @@ static inline int spl_filesystem_is_dot(const char * d_name) /* {{{ */ /* {{{ spl_filesystem_dir_open */ /* open a directory resource */ -static void spl_filesystem_dir_open(spl_filesystem_object* intern, char *path TSRMLS_DC) +static void spl_filesystem_dir_open(spl_filesystem_object* intern, char *path) { int skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS); intern->type = SPL_FS_DIR; - intern->_path_len = strlen(path); + intern->_path_len = (int)strlen(path); intern->u.dir.dirp = php_stream_opendir(path, REPORT_ERRORS, FG(default_context)); if (intern->_path_len > 1 && IS_SLASH_AT(path, intern->_path_len-1)) { @@ -260,28 +246,28 @@ static void spl_filesystem_dir_open(spl_filesystem_object* intern, char *path TS intern->u.dir.entry.d_name[0] = '\0'; if (!EG(exception)) { /* open failed w/out notice (turned to exception due to EH_THROW) */ - zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 - TSRMLS_CC, "Failed to open directory \"%s\"", path); + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, + "Failed to open directory \"%s\"", path); } } else { do { - spl_filesystem_dir_read(intern TSRMLS_CC); + spl_filesystem_dir_read(intern); } while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name)); } } /* }}} */ -static int spl_filesystem_file_open(spl_filesystem_object *intern, int use_include_path, int silent TSRMLS_DC) /* {{{ */ +static int spl_filesystem_file_open(spl_filesystem_object *intern, int use_include_path, int silent) /* {{{ */ { - zval tmp; + zval tmp; intern->type = SPL_FS_FILE; - php_stat(intern->file_name, intern->file_name_len, FS_IS_DIR, &tmp TSRMLS_CC); - if (Z_LVAL(tmp)) { + php_stat(intern->file_name, intern->file_name_len, FS_IS_DIR, &tmp); + if (Z_TYPE(tmp) == IS_TRUE) { intern->u.file.open_mode = NULL; intern->file_name = NULL; - zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Cannot use SplFileObject with directories"); + zend_throw_exception_ex(spl_ce_LogicException, 0, "Cannot use SplFileObject with directories"); return FAILURE; } @@ -290,16 +276,19 @@ static int spl_filesystem_file_open(spl_filesystem_object *intern, int use_inclu if (!intern->file_name_len || !intern->u.file.stream) { if (!EG(exception)) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot open file '%s'", intern->file_name_len ? intern->file_name : ""); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot open file '%s'", intern->file_name_len ? intern->file_name : ""); } intern->file_name = NULL; /* until here it is not a copy */ intern->u.file.open_mode = NULL; return FAILURE; } + /* if (intern->u.file.zcontext) { - zend_list_addref(Z_RESVAL_P(intern->u.file.zcontext)); + //zend_list_addref(Z_RES_VAL(intern->u.file.zcontext)); + Z_ADDREF_P(intern->u.file.zcontext); } + */ if (intern->file_name_len > 1 && IS_SLASH_AT(intern->file_name, intern->file_name_len-1)) { intern->file_name_len--; @@ -311,93 +300,92 @@ static int spl_filesystem_file_open(spl_filesystem_object *intern, int use_inclu intern->u.file.open_mode = estrndup(intern->u.file.open_mode, intern->u.file.open_mode_len); /* avoid reference counting in debug mode, thus do it manually */ - ZVAL_RESOURCE(&intern->u.file.zresource, php_stream_get_resource_id(intern->u.file.stream)); + ZVAL_RES(&intern->u.file.zresource, intern->u.file.stream->res); + /*!!! TODO: maybe bug? Z_SET_REFCOUNT(intern->u.file.zresource, 1); - + */ + intern->u.file.delimiter = ','; intern->u.file.enclosure = '"'; intern->u.file.escape = '\\'; - zend_hash_find(&intern->std.ce->function_table, "getcurrentline", sizeof("getcurrentline"), (void **) &intern->u.file.func_getCurr); + intern->u.file.func_getCurr = zend_hash_str_find_ptr(&intern->std.ce->function_table, "getcurrentline", sizeof("getcurrentline") - 1); return SUCCESS; } /* }}} */ /* {{{ spl_filesystem_object_clone */ -/* Local zend_object_value creation (on stack) - Load the 'other' object +/* Local zend_object creation (on stack) + Load the 'other' object Create a new empty object (See spl_filesystem_object_new_ex) Open the directory Clone other members (properties) */ -static zend_object_value spl_filesystem_object_clone(zval *zobject TSRMLS_DC) +static zend_object *spl_filesystem_object_clone(zval *zobject) { - zend_object_value new_obj_val; zend_object *old_object; zend_object *new_object; - zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); spl_filesystem_object *intern; spl_filesystem_object *source; int index, skip_dots; - old_object = zend_objects_get_address(zobject TSRMLS_CC); - source = (spl_filesystem_object*)old_object; - - new_obj_val = spl_filesystem_object_new_ex(old_object->ce, &intern TSRMLS_CC); - new_object = &intern->std; + old_object = Z_OBJ_P(zobject); + source = spl_filesystem_from_obj(old_object); + new_object = spl_filesystem_object_new_ex(old_object->ce); + intern = spl_filesystem_from_obj(new_object); intern->flags = source->flags; switch (source->type) { - case SPL_FS_INFO: - intern->_path_len = source->_path_len; - intern->_path = estrndup(source->_path, source->_path_len); - intern->file_name_len = source->file_name_len; - intern->file_name = estrndup(source->file_name, intern->file_name_len); - break; - case SPL_FS_DIR: - spl_filesystem_dir_open(intern, source->_path TSRMLS_CC); - /* read until we hit the position in which we were before */ - skip_dots = SPL_HAS_FLAG(source->flags, SPL_FILE_DIR_SKIPDOTS); - for(index = 0; index < source->u.dir.index; ++index) { - do { - spl_filesystem_dir_read(intern TSRMLS_CC); - } while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name)); - } - intern->u.dir.index = index; - break; - case SPL_FS_FILE: - php_error_docref(NULL TSRMLS_CC, E_ERROR, "An object of class %s cannot be cloned", old_object->ce->name); - break; + case SPL_FS_INFO: + intern->_path_len = source->_path_len; + intern->_path = estrndup(source->_path, source->_path_len); + intern->file_name_len = source->file_name_len; + intern->file_name = estrndup(source->file_name, intern->file_name_len); + break; + case SPL_FS_DIR: + spl_filesystem_dir_open(intern, source->_path); + /* read until we hit the position in which we were before */ + skip_dots = SPL_HAS_FLAG(source->flags, SPL_FILE_DIR_SKIPDOTS); + for(index = 0; index < source->u.dir.index; ++index) { + do { + spl_filesystem_dir_read(intern); + } while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name)); + } + intern->u.dir.index = index; + break; + case SPL_FS_FILE: + php_error_docref(NULL, E_ERROR, "An object of class %s cannot be cloned", ZSTR_VAL(old_object->ce->name)); + break; } - + intern->file_class = source->file_class; intern->info_class = source->info_class; intern->oth = source->oth; intern->oth_handler = source->oth_handler; - zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC); + zend_objects_clone_members(new_object, old_object); if (intern->oth_handler && intern->oth_handler->clone) { - intern->oth_handler->clone(source, intern TSRMLS_CC); + intern->oth_handler->clone(source, intern); } - return new_obj_val; + return new_object; } /* }}} */ -void spl_filesystem_info_set_filename(spl_filesystem_object *intern, char *path, int len, int use_copy TSRMLS_DC) /* {{{ */ +void spl_filesystem_info_set_filename(spl_filesystem_object *intern, char *path, size_t len, size_t use_copy) /* {{{ */ { char *p1, *p2; - + if (intern->file_name) { efree(intern->file_name); } intern->file_name = use_copy ? estrndup(path, len) : path; - intern->file_name_len = len; + intern->file_name_len = (int)len; - while(IS_SLASH_AT(intern->file_name, intern->file_name_len-1) && intern->file_name_len > 1) { + while (intern->file_name_len > 1 && IS_SLASH_AT(intern->file_name, intern->file_name_len-1)) { intern->file_name[intern->file_name_len-1] = 0; intern->file_name_len--; } @@ -409,26 +397,26 @@ void spl_filesystem_info_set_filename(spl_filesystem_object *intern, char *path, p2 = 0; #endif if (p1 || p2) { - intern->_path_len = (p1 > p2 ? p1 : p2) - intern->file_name; + intern->_path_len = (int)((p1 > p2 ? p1 : p2) - intern->file_name); } else { intern->_path_len = 0; } - + if (intern->_path) { efree(intern->_path); } intern->_path = estrndup(path, intern->_path_len); } /* }}} */ -static spl_filesystem_object * spl_filesystem_object_create_info(spl_filesystem_object *source, char *file_path, int file_path_len, int use_copy, zend_class_entry *ce, zval *return_value TSRMLS_DC) /* {{{ */ +static spl_filesystem_object *spl_filesystem_object_create_info(spl_filesystem_object *source, char *file_path, int file_path_len, int use_copy, zend_class_entry *ce, zval *return_value) /* {{{ */ { spl_filesystem_object *intern; - zval *arg1; + zval arg1; zend_error_handling error_handling; if (!file_path || !file_path_len) { #if defined(PHP_WIN32) - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot create SplFileInfo for empty path"); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot create SplFileInfo for empty path"); if (file_path && !use_copy) { efree(file_path); } @@ -442,123 +430,124 @@ static spl_filesystem_object * spl_filesystem_object_create_info(spl_filesystem_ return NULL; } - zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling TSRMLS_CC); + zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling); ce = ce ? ce : source->info_class; - zend_update_class_constants(ce TSRMLS_CC); + zend_update_class_constants(ce); - return_value->value.obj = spl_filesystem_object_new_ex(ce, &intern TSRMLS_CC); - Z_TYPE_P(return_value) = IS_OBJECT; + intern = spl_filesystem_from_obj(spl_filesystem_object_new_ex(ce)); + ZVAL_OBJ(return_value, &intern->std); if (ce->constructor->common.scope != spl_ce_SplFileInfo) { - MAKE_STD_ZVAL(arg1); - ZVAL_STRINGL(arg1, file_path, file_path_len, use_copy); - zend_call_method_with_1_params(&return_value, ce, &ce->constructor, "__construct", NULL, arg1); + ZVAL_STRINGL(&arg1, file_path, file_path_len); + zend_call_method_with_1_params(return_value, ce, &ce->constructor, "__construct", NULL, &arg1); zval_ptr_dtor(&arg1); } else { - spl_filesystem_info_set_filename(intern, file_path, file_path_len, use_copy TSRMLS_CC); + spl_filesystem_info_set_filename(intern, file_path, file_path_len, use_copy); } - - zend_restore_error_handling(&error_handling TSRMLS_CC); + + zend_restore_error_handling(&error_handling); return intern; } /* }}} */ -static spl_filesystem_object * spl_filesystem_object_create_type(int ht, spl_filesystem_object *source, int type, zend_class_entry *ce, zval *return_value TSRMLS_DC) /* {{{ */ +static spl_filesystem_object *spl_filesystem_object_create_type(int ht, spl_filesystem_object *source, int type, zend_class_entry *ce, zval *return_value) /* {{{ */ { spl_filesystem_object *intern; zend_bool use_include_path = 0; - zval *arg1, *arg2; + zval arg1, arg2; zend_error_handling error_handling; - zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling TSRMLS_CC); + zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling); switch (source->type) { - case SPL_FS_INFO: - case SPL_FS_FILE: - break; - case SPL_FS_DIR: - if (!source->u.dir.entry.d_name[0]) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Could not open file"); - zend_restore_error_handling(&error_handling TSRMLS_CC); - return NULL; - } + case SPL_FS_INFO: + case SPL_FS_FILE: + break; + case SPL_FS_DIR: + if (!source->u.dir.entry.d_name[0]) { + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Could not open file"); + zend_restore_error_handling(&error_handling); + return NULL; + } } switch (type) { - case SPL_FS_INFO: - ce = ce ? ce : source->info_class; + case SPL_FS_INFO: + ce = ce ? ce : source->info_class; - zend_update_class_constants(ce TSRMLS_CC); + if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) { + break; + } - return_value->value.obj = spl_filesystem_object_new_ex(ce, &intern TSRMLS_CC); - Z_TYPE_P(return_value) = IS_OBJECT; + intern = spl_filesystem_from_obj(spl_filesystem_object_new_ex(ce)); + ZVAL_OBJ(return_value, &intern->std); - spl_filesystem_object_get_file_name(source TSRMLS_CC); - if (ce->constructor->common.scope != spl_ce_SplFileInfo) { - MAKE_STD_ZVAL(arg1); - ZVAL_STRINGL(arg1, source->file_name, source->file_name_len, 1); - zend_call_method_with_1_params(&return_value, ce, &ce->constructor, "__construct", NULL, arg1); - zval_ptr_dtor(&arg1); - } else { - intern->file_name = estrndup(source->file_name, source->file_name_len); - intern->file_name_len = source->file_name_len; - intern->_path = spl_filesystem_object_get_path(source, &intern->_path_len TSRMLS_CC); - intern->_path = estrndup(intern->_path, intern->_path_len); - } - break; - case SPL_FS_FILE: - ce = ce ? ce : source->file_class; - - zend_update_class_constants(ce TSRMLS_CC); - - return_value->value.obj = spl_filesystem_object_new_ex(ce, &intern TSRMLS_CC); - Z_TYPE_P(return_value) = IS_OBJECT; - - spl_filesystem_object_get_file_name(source TSRMLS_CC); - - if (ce->constructor->common.scope != spl_ce_SplFileObject) { - MAKE_STD_ZVAL(arg1); - MAKE_STD_ZVAL(arg2); - ZVAL_STRINGL(arg1, source->file_name, source->file_name_len, 1); - ZVAL_STRINGL(arg2, "r", 1, 1); - zend_call_method_with_2_params(&return_value, ce, &ce->constructor, "__construct", NULL, arg1, arg2); - zval_ptr_dtor(&arg1); - zval_ptr_dtor(&arg2); - } else { - intern->file_name = source->file_name; - intern->file_name_len = source->file_name_len; - intern->_path = spl_filesystem_object_get_path(source, &intern->_path_len TSRMLS_CC); - intern->_path = estrndup(intern->_path, intern->_path_len); - - intern->u.file.open_mode = "r"; - intern->u.file.open_mode_len = 1; - - if (ht && zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sbr", - &intern->u.file.open_mode, &intern->u.file.open_mode_len, - &use_include_path, &intern->u.file.zcontext) == FAILURE) { - zend_restore_error_handling(&error_handling TSRMLS_CC); - intern->u.file.open_mode = NULL; - intern->file_name = NULL; - zval_dtor(return_value); - Z_TYPE_P(return_value) = IS_NULL; - return NULL; + spl_filesystem_object_get_file_name(source); + if (ce->constructor->common.scope != spl_ce_SplFileInfo) { + ZVAL_STRINGL(&arg1, source->file_name, source->file_name_len); + zend_call_method_with_1_params(return_value, ce, &ce->constructor, "__construct", NULL, &arg1); + zval_ptr_dtor(&arg1); + } else { + intern->file_name = estrndup(source->file_name, source->file_name_len); + intern->file_name_len = source->file_name_len; + intern->_path = spl_filesystem_object_get_path(source, &intern->_path_len); + intern->_path = estrndup(intern->_path, intern->_path_len); } - - if (spl_filesystem_file_open(intern, use_include_path, 0 TSRMLS_CC) == FAILURE) { - zend_restore_error_handling(&error_handling TSRMLS_CC); - zval_dtor(return_value); - Z_TYPE_P(return_value) = IS_NULL; - return NULL; + break; + case SPL_FS_FILE: + ce = ce ? ce : source->file_class; + + if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) { + break; } - } - break; - case SPL_FS_DIR: - zend_restore_error_handling(&error_handling TSRMLS_CC); - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Operation not supported"); - return NULL; + + intern = spl_filesystem_from_obj(spl_filesystem_object_new_ex(ce)); + + ZVAL_OBJ(return_value, &intern->std); + + spl_filesystem_object_get_file_name(source); + + if (ce->constructor->common.scope != spl_ce_SplFileObject) { + ZVAL_STRINGL(&arg1, source->file_name, source->file_name_len); + ZVAL_STRINGL(&arg2, "r", 1); + zend_call_method_with_2_params(return_value, ce, &ce->constructor, "__construct", NULL, &arg1, &arg2); + zval_ptr_dtor(&arg1); + zval_ptr_dtor(&arg2); + } else { + intern->file_name = source->file_name; + intern->file_name_len = source->file_name_len; + intern->_path = spl_filesystem_object_get_path(source, &intern->_path_len); + intern->_path = estrndup(intern->_path, intern->_path_len); + + intern->u.file.open_mode = "r"; + intern->u.file.open_mode_len = 1; + + if (ht && zend_parse_parameters(ht, "|sbr", + &intern->u.file.open_mode, &intern->u.file.open_mode_len, + &use_include_path, &intern->u.file.zcontext) == FAILURE) { + zend_restore_error_handling(&error_handling); + intern->u.file.open_mode = NULL; + intern->file_name = NULL; + zval_ptr_dtor(return_value); + ZVAL_NULL(return_value); + return NULL; + } + + if (spl_filesystem_file_open(intern, use_include_path, 0) == FAILURE) { + zend_restore_error_handling(&error_handling); + zval_ptr_dtor(return_value); + ZVAL_NULL(return_value); + return NULL; + } + } + break; + case SPL_FS_DIR: + zend_restore_error_handling(&error_handling); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Operation not supported"); + return NULL; } - zend_restore_error_handling(&error_handling TSRMLS_CC); + zend_restore_error_handling(&error_handling); return NULL; } /* }}} */ @@ -568,31 +557,32 @@ static int spl_filesystem_is_invalid_or_dot(const char * d_name) /* {{{ */ } /* }}} */ -static char *spl_filesystem_object_get_pathname(spl_filesystem_object *intern, int *len TSRMLS_DC) { /* {{{ */ +static char *spl_filesystem_object_get_pathname(spl_filesystem_object *intern, size_t *len) { /* {{{ */ switch (intern->type) { - case SPL_FS_INFO: - case SPL_FS_FILE: - *len = intern->file_name_len; - return intern->file_name; - case SPL_FS_DIR: - if (intern->u.dir.entry.d_name[0]) { - spl_filesystem_object_get_file_name(intern TSRMLS_CC); + case SPL_FS_INFO: + case SPL_FS_FILE: *len = intern->file_name_len; return intern->file_name; - } + case SPL_FS_DIR: + if (intern->u.dir.entry.d_name[0]) { + spl_filesystem_object_get_file_name(intern); + *len = intern->file_name_len; + return intern->file_name; + } } *len = 0; return NULL; } /* }}} */ -static HashTable* spl_filesystem_object_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{ */ +static HashTable *spl_filesystem_object_get_debug_info(zval *object, int *is_temp) /* {{{ */ { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(obj TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(object); + zval tmp; HashTable *rv; - zval *tmp, zrv; - char *pnstr, *path; - int pnlen, path_len; + zend_string *pnstr; + char *path; + size_t path_len; char stmp[2]; *is_temp = 1; @@ -601,100 +591,103 @@ static HashTable* spl_filesystem_object_get_debug_info(zval *obj, int *is_temp T rebuild_object_properties(&intern->std); } - ALLOC_HASHTABLE(rv); - ZEND_INIT_SYMTABLE_EX(rv, zend_hash_num_elements(intern->std.properties) + 3, 0); - - INIT_PZVAL(&zrv); - Z_ARRVAL(zrv) = rv; - - zend_hash_copy(rv, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); + rv = zend_array_dup(intern->std.properties); - pnstr = spl_gen_private_prop_name(spl_ce_SplFileInfo, "pathName", sizeof("pathName")-1, &pnlen TSRMLS_CC); - path = spl_filesystem_object_get_pathname(intern, &path_len TSRMLS_CC); - add_assoc_stringl_ex(&zrv, pnstr, pnlen+1, path, path_len, 1); - efree(pnstr); + pnstr = spl_gen_private_prop_name(spl_ce_SplFileInfo, "pathName", sizeof("pathName")-1); + path = spl_filesystem_object_get_pathname(intern, &path_len); + ZVAL_STRINGL(&tmp, path, path_len); + zend_symtable_update(rv, pnstr, &tmp); + zend_string_release(pnstr); if (intern->file_name) { - pnstr = spl_gen_private_prop_name(spl_ce_SplFileInfo, "fileName", sizeof("fileName")-1, &pnlen TSRMLS_CC); - spl_filesystem_object_get_path(intern, &path_len TSRMLS_CC); - + pnstr = spl_gen_private_prop_name(spl_ce_SplFileInfo, "fileName", sizeof("fileName")-1); + spl_filesystem_object_get_path(intern, &path_len); + if (path_len && path_len < intern->file_name_len) { - add_assoc_stringl_ex(&zrv, pnstr, pnlen+1, intern->file_name + path_len + 1, intern->file_name_len - (path_len + 1), 1); + ZVAL_STRINGL(&tmp, intern->file_name + path_len + 1, intern->file_name_len - (path_len + 1)); } else { - add_assoc_stringl_ex(&zrv, pnstr, pnlen+1, intern->file_name, intern->file_name_len, 1); + ZVAL_STRINGL(&tmp, intern->file_name, intern->file_name_len); } - efree(pnstr); + zend_symtable_update(rv, pnstr, &tmp); + zend_string_release(pnstr); } if (intern->type == SPL_FS_DIR) { #ifdef HAVE_GLOB - pnstr = spl_gen_private_prop_name(spl_ce_DirectoryIterator, "glob", sizeof("glob")-1, &pnlen TSRMLS_CC); + pnstr = spl_gen_private_prop_name(spl_ce_DirectoryIterator, "glob", sizeof("glob")-1); if (php_stream_is(intern->u.dir.dirp ,&php_glob_stream_ops)) { - add_assoc_stringl_ex(&zrv, pnstr, pnlen+1, intern->_path, intern->_path_len, 1); + ZVAL_STRINGL(&tmp, intern->_path, intern->_path_len); } else { - add_assoc_bool_ex(&zrv, pnstr, pnlen+1, 0); + ZVAL_FALSE(&tmp); } - efree(pnstr); + zend_symtable_update(rv, pnstr, &tmp); + zend_string_release(pnstr); #endif - pnstr = spl_gen_private_prop_name(spl_ce_RecursiveDirectoryIterator, "subPathName", sizeof("subPathName")-1, &pnlen TSRMLS_CC); + pnstr = spl_gen_private_prop_name(spl_ce_RecursiveDirectoryIterator, "subPathName", sizeof("subPathName")-1); if (intern->u.dir.sub_path) { - add_assoc_stringl_ex(&zrv, pnstr, pnlen+1, intern->u.dir.sub_path, intern->u.dir.sub_path_len, 1); + ZVAL_STRINGL(&tmp, intern->u.dir.sub_path, intern->u.dir.sub_path_len); } else { - add_assoc_stringl_ex(&zrv, pnstr, pnlen+1, "", 0, 1); + ZVAL_EMPTY_STRING(&tmp); } - efree(pnstr); + zend_symtable_update(rv, pnstr, &tmp); + zend_string_release(pnstr); } if (intern->type == SPL_FS_FILE) { - pnstr = spl_gen_private_prop_name(spl_ce_SplFileObject, "openMode", sizeof("openMode")-1, &pnlen TSRMLS_CC); - add_assoc_stringl_ex(&zrv, pnstr, pnlen+1, intern->u.file.open_mode, intern->u.file.open_mode_len, 1); - efree(pnstr); + pnstr = spl_gen_private_prop_name(spl_ce_SplFileObject, "openMode", sizeof("openMode")-1); + ZVAL_STRINGL(&tmp, intern->u.file.open_mode, intern->u.file.open_mode_len); + zend_symtable_update(rv, pnstr, &tmp); + zend_string_release(pnstr); stmp[1] = '\0'; stmp[0] = intern->u.file.delimiter; - pnstr = spl_gen_private_prop_name(spl_ce_SplFileObject, "delimiter", sizeof("delimiter")-1, &pnlen TSRMLS_CC); - add_assoc_stringl_ex(&zrv, pnstr, pnlen+1, stmp, 1, 1); - efree(pnstr); + pnstr = spl_gen_private_prop_name(spl_ce_SplFileObject, "delimiter", sizeof("delimiter")-1); + ZVAL_STRINGL(&tmp, stmp, 1); + zend_symtable_update(rv, pnstr, &tmp); + zend_string_release(pnstr); stmp[0] = intern->u.file.enclosure; - pnstr = spl_gen_private_prop_name(spl_ce_SplFileObject, "enclosure", sizeof("enclosure")-1, &pnlen TSRMLS_CC); - add_assoc_stringl_ex(&zrv, pnstr, pnlen+1, stmp, 1, 1); - efree(pnstr); + pnstr = spl_gen_private_prop_name(spl_ce_SplFileObject, "enclosure", sizeof("enclosure")-1); + ZVAL_STRINGL(&tmp, stmp, 1); + zend_symtable_update(rv, pnstr, &tmp); + zend_string_release(pnstr); } return rv; } /* }}} */ -zend_function *spl_filesystem_object_get_method_check(zval **object_ptr, char *method, int method_len, const struct _zend_literal *key TSRMLS_DC) /* {{{ */ +zend_function *spl_filesystem_object_get_method_check(zend_object **object, zend_string *method, const zval *key) /* {{{ */ { - spl_filesystem_object *fsobj = zend_object_store_get_object(*object_ptr TSRMLS_CC); - + spl_filesystem_object *fsobj = spl_filesystem_from_obj(*object); + if (fsobj->u.dir.entry.d_name[0] == '\0' && fsobj->orig_path == NULL) { - method = "_bad_state_ex"; - method_len = sizeof("_bad_state_ex") - 1; - key = NULL; + zend_function *func; + zend_string *tmp = zend_string_init("_bad_state_ex", sizeof("_bad_state_ex") - 1, 0); + func = zend_get_std_object_handlers()->get_method(object, tmp, NULL); + zend_string_release(tmp); + return func; } - - return zend_get_std_object_handlers()->get_method(object_ptr, method, method_len, key TSRMLS_CC); + + return zend_get_std_object_handlers()->get_method(object, method, key); } /* }}} */ #define DIT_CTOR_FLAGS 0x00000001 #define DIT_CTOR_GLOB 0x00000002 -void spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAMETERS, long ctor_flags) /* {{{ */ +void spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAMETERS, zend_long ctor_flags) /* {{{ */ { spl_filesystem_object *intern; char *path; - int parsed, len; - long flags; + size_t parsed, len; + zend_long flags; zend_error_handling error_handling; - zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling TSRMLS_CC); + zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling); if (SPL_HAS_FLAG(ctor_flags, DIT_CTOR_FLAGS)) { flags = SPL_FILE_DIR_KEY_AS_PATHNAME|SPL_FILE_DIR_CURRENT_AS_FILEINFO; - parsed = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &path, &len, &flags); + parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &path, &len, &flags); } else { flags = SPL_FILE_DIR_KEY_AS_PATHNAME|SPL_FILE_DIR_CURRENT_AS_SELF; - parsed = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &path, &len); + parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "s", &path, &len); } if (SPL_HAS_FLAG(ctor_flags, SPL_FILE_DIR_SKIPDOTS)) { flags |= SPL_FILE_DIR_SKIPDOTS; @@ -703,38 +696,38 @@ void spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAMETERS, long ctor_fla flags |= SPL_FILE_DIR_UNIXPATHS; } if (parsed == FAILURE) { - zend_restore_error_handling(&error_handling TSRMLS_CC); + zend_restore_error_handling(&error_handling); return; } if (!len) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Directory name must not be empty."); - zend_restore_error_handling(&error_handling TSRMLS_CC); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Directory name must not be empty."); + zend_restore_error_handling(&error_handling); return; } - intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_SPLFILESYSTEM_P(getThis()); if (intern->_path) { /* object is alreay initialized */ - zend_restore_error_handling(&error_handling TSRMLS_CC); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Directory object is already initialized"); + zend_restore_error_handling(&error_handling); + php_error_docref(NULL, E_WARNING, "Directory object is already initialized"); return; } intern->flags = flags; #ifdef HAVE_GLOB if (SPL_HAS_FLAG(ctor_flags, DIT_CTOR_GLOB) && strstr(path, "glob://") != path) { spprintf(&path, 0, "glob://%s", path); - spl_filesystem_dir_open(intern, path TSRMLS_CC); + spl_filesystem_dir_open(intern, path); efree(path); } else #endif { - spl_filesystem_dir_open(intern, path TSRMLS_CC); + spl_filesystem_dir_open(intern, path); } - intern->u.dir.is_recursive = instanceof_function(intern->std.ce, spl_ce_RecursiveDirectoryIterator TSRMLS_CC) ? 1 : 0; + intern->u.dir.is_recursive = instanceof_function(intern->std.ce, spl_ce_RecursiveDirectoryIterator) ? 1 : 0; - zend_restore_error_handling(&error_handling TSRMLS_CC); + zend_restore_error_handling(&error_handling); } /* }}} */ @@ -750,8 +743,8 @@ SPL_METHOD(DirectoryIterator, __construct) Rewind dir back to the start */ SPL_METHOD(DirectoryIterator, rewind) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -760,7 +753,7 @@ SPL_METHOD(DirectoryIterator, rewind) if (intern->u.dir.dirp) { php_stream_rewinddir(intern->u.dir.dirp); } - spl_filesystem_dir_read(intern TSRMLS_CC); + spl_filesystem_dir_read(intern); } /* }}} */ @@ -768,8 +761,8 @@ SPL_METHOD(DirectoryIterator, rewind) Return current dir entry */ SPL_METHOD(DirectoryIterator, key) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -789,7 +782,8 @@ SPL_METHOD(DirectoryIterator, current) if (zend_parse_parameters_none() == FAILURE) { return; } - RETURN_ZVAL(getThis(), 1, 0); + ZVAL_OBJ(return_value, Z_OBJ_P(getThis())); + Z_ADDREF_P(return_value); } /* }}} */ @@ -797,16 +791,16 @@ SPL_METHOD(DirectoryIterator, current) Move to next entry */ SPL_METHOD(DirectoryIterator, next) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); int skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS); - + if (zend_parse_parameters_none() == FAILURE) { return; } intern->u.dir.index++; do { - spl_filesystem_dir_read(intern TSRMLS_CC); + spl_filesystem_dir_read(intern); } while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name)); if (intern->file_name) { efree(intern->file_name); @@ -819,39 +813,31 @@ SPL_METHOD(DirectoryIterator, next) Seek to the given position */ SPL_METHOD(DirectoryIterator, seek) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - zval *retval = NULL; - long pos; + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + zval retval; + zend_long pos; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &pos) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &pos) == FAILURE) { return; } if (intern->u.dir.index > pos) { /* we first rewind */ - zend_call_method_with_0_params(&this_ptr, Z_OBJCE_P(getThis()), &intern->u.dir.func_rewind, "rewind", &retval); - if (retval) { - zval_ptr_dtor(&retval); - retval = NULL; - } + zend_call_method_with_0_params(&EX(This), Z_OBJCE(EX(This)), &intern->u.dir.func_rewind, "rewind", NULL); } while (intern->u.dir.index < pos) { int valid = 0; - zend_call_method_with_0_params(&this_ptr, Z_OBJCE_P(getThis()), &intern->u.dir.func_valid, "valid", &retval); - if (retval) { - valid = zend_is_true(retval); + zend_call_method_with_0_params(&EX(This), Z_OBJCE(EX(This)), &intern->u.dir.func_valid, "valid", &retval); + if (!Z_ISUNDEF(retval)) { + valid = zend_is_true(&retval); zval_ptr_dtor(&retval); - retval = NULL; } if (!valid) { zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0 TSRMLS_CC, "Seek position %ld is out of range", pos); return; } - zend_call_method_with_0_params(&this_ptr, Z_OBJCE_P(getThis()), &intern->u.dir.func_next, "next", &retval); - if (retval) { - zval_ptr_dtor(&retval); - } + zend_call_method_with_0_params(&EX(This), Z_OBJCE(EX(This)), &intern->u.dir.func_next, "next", NULL); } } /* }}} */ @@ -859,8 +845,8 @@ SPL_METHOD(DirectoryIterator, seek) Check whether dir contains more entries */ SPL_METHOD(DirectoryIterator, valid) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -873,16 +859,16 @@ SPL_METHOD(DirectoryIterator, valid) Return the path */ SPL_METHOD(SplFileInfo, getPath) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); char *path; - int path_len; - + size_t path_len; + if (zend_parse_parameters_none() == FAILURE) { return; } - path = spl_filesystem_object_get_path(intern, &path_len TSRMLS_CC); - RETURN_STRINGL(path, path_len, 1); + path = spl_filesystem_object_get_path(intern, &path_len); + RETURN_STRINGL(path, path_len); } /* }}} */ @@ -890,19 +876,19 @@ SPL_METHOD(SplFileInfo, getPath) Return filename only */ SPL_METHOD(SplFileInfo, getFilename) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - int path_len; - + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + size_t path_len; + if (zend_parse_parameters_none() == FAILURE) { return; } - spl_filesystem_object_get_path(intern, &path_len TSRMLS_CC); - + spl_filesystem_object_get_path(intern, &path_len); + if (path_len && path_len < intern->file_name_len) { - RETURN_STRINGL(intern->file_name + path_len + 1, intern->file_name_len - (path_len + 1), 1); + RETURN_STRINGL(intern->file_name + path_len + 1, intern->file_name_len - (path_len + 1)); } else { - RETURN_STRINGL(intern->file_name, intern->file_name_len, 1); + RETURN_STRINGL(intern->file_name, intern->file_name_len); } } /* }}} */ @@ -911,13 +897,13 @@ SPL_METHOD(SplFileInfo, getFilename) Return filename of current dir entry */ SPL_METHOD(DirectoryIterator, getFilename) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } - RETURN_STRING(intern->u.dir.entry.d_name, 1); + RETURN_STRING(intern->u.dir.entry.d_name); } /* }}} */ @@ -925,17 +911,19 @@ SPL_METHOD(DirectoryIterator, getFilename) Returns file extension component of path */ SPL_METHOD(SplFileInfo, getExtension) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); char *fname = NULL; const char *p; size_t flen; - int path_len, idx; + size_t path_len; + int idx; + zend_string *ret; if (zend_parse_parameters_none() == FAILURE) { return; } - spl_filesystem_object_get_path(intern, &path_len TSRMLS_CC); + spl_filesystem_object_get_path(intern, &path_len); if (path_len && path_len < intern->file_name_len) { fname = intern->file_name + path_len + 1; @@ -945,18 +933,16 @@ SPL_METHOD(SplFileInfo, getExtension) flen = intern->file_name_len; } - php_basename(fname, flen, NULL, 0, &fname, &flen TSRMLS_CC); + ret = php_basename(fname, flen, NULL, 0); - p = zend_memrchr(fname, '.', flen); + p = zend_memrchr(ZSTR_VAL(ret), '.', ZSTR_LEN(ret)); if (p) { - idx = p - fname; - RETVAL_STRINGL(fname + idx + 1, flen - idx - 1, 1); - efree(fname); + idx = (int)(p - ZSTR_VAL(ret)); + RETVAL_STRINGL(ZSTR_VAL(ret) + idx + 1, ZSTR_LEN(ret) - idx - 1); + zend_string_release(ret); return; } else { - if (fname) { - efree(fname); - } + zend_string_release(ret); RETURN_EMPTY_STRING(); } } @@ -966,47 +952,43 @@ SPL_METHOD(SplFileInfo, getExtension) Returns the file extension component of path */ SPL_METHOD(DirectoryIterator, getExtension) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - char *fname = NULL; + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); const char *p; - size_t flen; int idx; + zend_string *fname; if (zend_parse_parameters_none() == FAILURE) { return; } - php_basename(intern->u.dir.entry.d_name, strlen(intern->u.dir.entry.d_name), NULL, 0, &fname, &flen TSRMLS_CC); + fname = php_basename(intern->u.dir.entry.d_name, strlen(intern->u.dir.entry.d_name), NULL, 0); - p = zend_memrchr(fname, '.', flen); + p = zend_memrchr(ZSTR_VAL(fname), '.', ZSTR_LEN(fname)); if (p) { - idx = p - fname; - RETVAL_STRINGL(fname + idx + 1, flen - idx - 1, 1); - efree(fname); - return; + idx = (int)(p - ZSTR_VAL(fname)); + RETVAL_STRINGL(ZSTR_VAL(fname) + idx + 1, ZSTR_LEN(fname) - idx - 1); + zend_string_release(fname); } else { - if (fname) { - efree(fname); - } + zend_string_release(fname); RETURN_EMPTY_STRING(); } } /* }}} */ -/* {{{ proto string SplFileInfo::getBasename([string $suffix]) U +/* {{{ proto string SplFileInfo::getBasename([string $suffix]) Returns filename component of path */ SPL_METHOD(SplFileInfo, getBasename) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); char *fname, *suffix = 0; size_t flen; - int slen = 0, path_len; + size_t slen = 0, path_len; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &suffix, &slen) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &suffix, &slen) == FAILURE) { return; } - spl_filesystem_object_get_path(intern, &path_len TSRMLS_CC); + spl_filesystem_object_get_path(intern, &path_len); if (path_len && path_len < intern->file_name_len) { fname = intern->file_name + path_len + 1; @@ -1016,28 +998,26 @@ SPL_METHOD(SplFileInfo, getBasename) flen = intern->file_name_len; } - php_basename(fname, flen, suffix, slen, &fname, &flen TSRMLS_CC); - - RETURN_STRINGL(fname, flen, 0); + RETURN_STR(php_basename(fname, flen, suffix, slen)); } -/* }}}*/ +/* }}}*/ -/* {{{ proto string DirectoryIterator::getBasename([string $suffix]) U +/* {{{ proto string DirectoryIterator::getBasename([string $suffix]) Returns filename component of current dir entry */ SPL_METHOD(DirectoryIterator, getBasename) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - char *suffix = 0, *fname; - int slen = 0; - size_t flen; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &suffix, &slen) == FAILURE) { + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + char *suffix = 0; + size_t slen = 0; + zend_string *fname; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &suffix, &slen) == FAILURE) { return; } - php_basename(intern->u.dir.entry.d_name, strlen(intern->u.dir.entry.d_name), suffix, slen, &fname, &flen TSRMLS_CC); + fname = php_basename(intern->u.dir.entry.d_name, strlen(intern->u.dir.entry.d_name), suffix, slen); - RETURN_STRINGL(fname, flen, 0); + RETVAL_STR(fname); } /* }}} */ @@ -1045,16 +1025,16 @@ SPL_METHOD(DirectoryIterator, getBasename) Return path and filename */ SPL_METHOD(SplFileInfo, getPathname) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); char *path; - int path_len; + size_t path_len; if (zend_parse_parameters_none() == FAILURE) { return; } - path = spl_filesystem_object_get_pathname(intern, &path_len TSRMLS_CC); + path = spl_filesystem_object_get_pathname(intern, &path_len); if (path != NULL) { - RETURN_STRINGL(path, path_len, 1); + RETURN_STRINGL(path, path_len); } else { RETURN_FALSE; } @@ -1065,17 +1045,17 @@ SPL_METHOD(SplFileInfo, getPathname) Return getPathname() or getFilename() depending on flags */ SPL_METHOD(FilesystemIterator, key) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } if (SPL_FILE_DIR_KEY(intern, SPL_FILE_DIR_KEY_AS_FILENAME)) { - RETURN_STRING(intern->u.dir.entry.d_name, 1); + RETURN_STRING(intern->u.dir.entry.d_name); } else { - spl_filesystem_object_get_file_name(intern TSRMLS_CC); - RETURN_STRINGL(intern->file_name, intern->file_name_len, 1); + spl_filesystem_object_get_file_name(intern); + RETURN_STRINGL(intern->file_name, intern->file_name_len); } } /* }}} */ @@ -1084,20 +1064,21 @@ SPL_METHOD(FilesystemIterator, key) Return getFilename(), getFileInfo() or $this depending on flags */ SPL_METHOD(FilesystemIterator, current) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } if (SPL_FILE_DIR_CURRENT(intern, SPL_FILE_DIR_CURRENT_AS_PATHNAME)) { - spl_filesystem_object_get_file_name(intern TSRMLS_CC); - RETURN_STRINGL(intern->file_name, intern->file_name_len, 1); + spl_filesystem_object_get_file_name(intern); + RETURN_STRINGL(intern->file_name, intern->file_name_len); } else if (SPL_FILE_DIR_CURRENT(intern, SPL_FILE_DIR_CURRENT_AS_FILEINFO)) { - spl_filesystem_object_get_file_name(intern TSRMLS_CC); - spl_filesystem_object_create_type(0, intern, SPL_FS_INFO, NULL, return_value TSRMLS_CC); + spl_filesystem_object_get_file_name(intern); + spl_filesystem_object_create_type(0, intern, SPL_FS_INFO, NULL, return_value); } else { - RETURN_ZVAL(getThis(), 1, 0); + ZVAL_OBJ(return_value, Z_OBJ_P(getThis())); + Z_ADDREF_P(return_value); /*RETURN_STRING(intern->u.dir.entry.d_name, 1);*/ } } @@ -1107,8 +1088,8 @@ SPL_METHOD(FilesystemIterator, current) Returns true if current entry is '.' or '..' */ SPL_METHOD(DirectoryIterator, isDot) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1119,33 +1100,23 @@ SPL_METHOD(DirectoryIterator, isDot) /* {{{ proto void SplFileInfo::__construct(string file_name) Cronstructs a new SplFileInfo from a path. */ -/* zend_replace_error_handling() is used to throw exceptions in case - the constructor fails. Here we use this to ensure the object - has a valid directory resource. - - When the constructor gets called the object is already created +/* When the constructor gets called the object is already created by the engine, so we must only call 'additional' initializations. */ SPL_METHOD(SplFileInfo, __construct) { spl_filesystem_object *intern; char *path; - int len; - zend_error_handling error_handling; + size_t len; - zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling TSRMLS_CC); - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &path, &len) == FAILURE) { - zend_restore_error_handling(&error_handling TSRMLS_CC); + if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "s", &path, &len) == FAILURE) { return; } - intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - - spl_filesystem_info_set_filename(intern, path, len, 1 TSRMLS_CC); + intern = Z_SPLFILESYSTEM_P(getThis()); + + spl_filesystem_info_set_filename(intern, path, len, 1); - zend_restore_error_handling(&error_handling TSRMLS_CC); - /* intern->type = SPL_FS_INFO; already set */ } /* }}} */ @@ -1154,16 +1125,16 @@ SPL_METHOD(SplFileInfo, __construct) #define FileInfoFunction(func_name, func_num) \ SPL_METHOD(SplFileInfo, func_name) \ { \ - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); \ + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); \ zend_error_handling error_handling; \ if (zend_parse_parameters_none() == FAILURE) { \ return; \ } \ \ - zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling TSRMLS_CC);\ - spl_filesystem_object_get_file_name(intern TSRMLS_CC); \ - php_stat(intern->file_name, intern->file_name_len, func_num, return_value TSRMLS_CC); \ - zend_restore_error_handling(&error_handling TSRMLS_CC); \ + zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);\ + spl_filesystem_object_get_file_name(intern); \ + php_stat(intern->file_name, intern->file_name_len, func_num, return_value); \ + zend_restore_error_handling(&error_handling); \ } /* }}} */ @@ -1242,29 +1213,29 @@ FileInfoFunction(isDir, FS_IS_DIR) FileInfoFunction(isLink, FS_IS_LINK) /* }}} */ -/* {{{ proto string SplFileInfo::getLinkTarget() U +/* {{{ proto string SplFileInfo::getLinkTarget() Return the target of a symbolic link */ SPL_METHOD(SplFileInfo, getLinkTarget) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); int ret; char buff[MAXPATHLEN]; zend_error_handling error_handling; - + if (zend_parse_parameters_none() == FAILURE) { return; } - zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling TSRMLS_CC); + zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling); #if defined(PHP_WIN32) || HAVE_SYMLINK if (intern->file_name == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty filename"); + php_error_docref(NULL, E_WARNING, "Empty filename"); RETURN_FALSE; } else if (!IS_ABSOLUTE_PATH(intern->file_name, intern->file_name_len)) { char expanded_path[MAXPATHLEN]; - if (!expand_filepath_with_mode(intern->file_name, expanded_path, NULL, 0, CWD_EXPAND TSRMLS_CC)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such file or directory"); + if (!expand_filepath_with_mode(intern->file_name, expanded_path, NULL, 0, CWD_EXPAND )) { + php_error_docref(NULL, E_WARNING, "No such file or directory"); RETURN_FALSE; } ret = php_sys_readlink(expanded_path, buff, MAXPATHLEN - 1); @@ -1276,16 +1247,16 @@ SPL_METHOD(SplFileInfo, getLinkTarget) #endif if (ret == -1) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Unable to read link %s, error: %s", intern->file_name, strerror(errno)); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Unable to read link %s, error: %s", intern->file_name, strerror(errno)); RETVAL_FALSE; } else { /* Append NULL to the end of the string */ buff[ret] = '\0'; - RETVAL_STRINGL(buff, ret, 1); + RETVAL_STRINGL(buff, ret); } - zend_restore_error_handling(&error_handling TSRMLS_CC); + zend_restore_error_handling(&error_handling); } /* }}} */ @@ -1294,24 +1265,24 @@ SPL_METHOD(SplFileInfo, getLinkTarget) Return the resolved path */ SPL_METHOD(SplFileInfo, getRealPath) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); char buff[MAXPATHLEN]; char *filename; zend_error_handling error_handling; - + if (zend_parse_parameters_none() == FAILURE) { return; } - zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling TSRMLS_CC); + zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling); if (intern->type == SPL_FS_DIR && !intern->file_name && intern->u.dir.entry.d_name[0]) { - spl_filesystem_object_get_file_name(intern TSRMLS_CC); + spl_filesystem_object_get_file_name(intern); } - + if (intern->orig_path) { filename = intern->orig_path; - } else { + } else { filename = intern->file_name; } @@ -1322,12 +1293,12 @@ SPL_METHOD(SplFileInfo, getRealPath) RETVAL_FALSE; } else #endif - RETVAL_STRING(buff, 1); + RETVAL_STRING(buff); } else { RETVAL_FALSE; } - zend_restore_error_handling(&error_handling TSRMLS_CC); + zend_restore_error_handling(&error_handling); } /* }}} */ #endif @@ -1336,9 +1307,9 @@ SPL_METHOD(SplFileInfo, getRealPath) Open the current file */ SPL_METHOD(SplFileInfo, openFile) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); - spl_filesystem_object_create_type(ht, intern, SPL_FS_FILE, NULL, return_value TSRMLS_CC); + spl_filesystem_object_create_type(ZEND_NUM_ARGS(), intern, SPL_FS_FILE, NULL, return_value); } /* }}} */ @@ -1346,17 +1317,17 @@ SPL_METHOD(SplFileInfo, openFile) Class to use in openFile() */ SPL_METHOD(SplFileInfo, setFileClass) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); zend_class_entry *ce = spl_ce_SplFileObject; zend_error_handling error_handling; - - zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling TSRMLS_CC); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &ce) == SUCCESS) { + zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling); + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C", &ce) == SUCCESS) { intern->file_class = ce; } - zend_restore_error_handling(&error_handling TSRMLS_CC); + zend_restore_error_handling(&error_handling); } /* }}} */ @@ -1364,17 +1335,17 @@ SPL_METHOD(SplFileInfo, setFileClass) Class to use in getFileInfo(), getPathInfo() */ SPL_METHOD(SplFileInfo, setInfoClass) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); zend_class_entry *ce = spl_ce_SplFileInfo; zend_error_handling error_handling; - - zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling TSRMLS_CC); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &ce) == SUCCESS) { + zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling ); + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C", &ce) == SUCCESS) { intern->info_class = ce; } - zend_restore_error_handling(&error_handling TSRMLS_CC); + zend_restore_error_handling(&error_handling); } /* }}} */ @@ -1382,17 +1353,17 @@ SPL_METHOD(SplFileInfo, setInfoClass) Get/copy file info */ SPL_METHOD(SplFileInfo, getFileInfo) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); zend_class_entry *ce = intern->info_class; zend_error_handling error_handling; - - zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling TSRMLS_CC); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &ce) == SUCCESS) { - spl_filesystem_object_create_type(ht, intern, SPL_FS_INFO, ce, return_value TSRMLS_CC); + zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling); + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C", &ce) == SUCCESS) { + spl_filesystem_object_create_type(ZEND_NUM_ARGS(), intern, SPL_FS_INFO, ce, return_value); } - zend_restore_error_handling(&error_handling TSRMLS_CC); + zend_restore_error_handling(&error_handling); } /* }}} */ @@ -1400,31 +1371,31 @@ SPL_METHOD(SplFileInfo, getFileInfo) Get/copy file info */ SPL_METHOD(SplFileInfo, getPathInfo) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); zend_class_entry *ce = intern->info_class; zend_error_handling error_handling; - - zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling TSRMLS_CC); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &ce) == SUCCESS) { - int path_len; - char *path = spl_filesystem_object_get_pathname(intern, &path_len TSRMLS_CC); + zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling); + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C", &ce) == SUCCESS) { + size_t path_len; + char *path = spl_filesystem_object_get_pathname(intern, &path_len); if (path) { char *dpath = estrndup(path, path_len); path_len = php_dirname(dpath, path_len); - spl_filesystem_object_create_info(intern, dpath, path_len, 1, ce, return_value TSRMLS_CC); + spl_filesystem_object_create_info(intern, dpath, (int)path_len, 1, ce, return_value); efree(dpath); } } - zend_restore_error_handling(&error_handling TSRMLS_CC); + zend_restore_error_handling(&error_handling); } /* }}} */ -/* {{{ */ +/* {{{ proto SplFileInfo::_bad_state_ex(void) */ SPL_METHOD(SplFileInfo, _bad_state_ex) { - zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, + zend_throw_exception_ex(spl_ce_LogicException, 0, "The parent constructor was not called: the object is in an " "invalid state "); } @@ -1442,7 +1413,7 @@ SPL_METHOD(FilesystemIterator, __construct) Rewind dir back to the start */ SPL_METHOD(FilesystemIterator, rewind) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); int skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS); if (zend_parse_parameters_none() == FAILURE) { @@ -1454,7 +1425,7 @@ SPL_METHOD(FilesystemIterator, rewind) php_stream_rewinddir(intern->u.dir.dirp); } do { - spl_filesystem_dir_read(intern TSRMLS_CC); + spl_filesystem_dir_read(intern); } while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name)); } /* }}} */ @@ -1463,8 +1434,8 @@ SPL_METHOD(FilesystemIterator, rewind) Get handling flags */ SPL_METHOD(FilesystemIterator, getFlags) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1476,10 +1447,10 @@ SPL_METHOD(FilesystemIterator, getFlags) Set handling flags */ SPL_METHOD(FilesystemIterator, setFlags) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - long flags; + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + zend_long flags; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &flags) == FAILURE) { return; } @@ -1492,22 +1463,22 @@ SPL_METHOD(FilesystemIterator, setFlags) SPL_METHOD(RecursiveDirectoryIterator, hasChildren) { zend_bool allow_links = 0; - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &allow_links) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &allow_links) == FAILURE) { return; } if (spl_filesystem_is_invalid_or_dot(intern->u.dir.entry.d_name)) { RETURN_FALSE; } else { - spl_filesystem_object_get_file_name(intern TSRMLS_CC); + spl_filesystem_object_get_file_name(intern); if (!allow_links && !(intern->flags & SPL_FILE_DIR_FOLLOW_SYMLINKS)) { - php_stat(intern->file_name, intern->file_name_len, FS_IS_LINK, return_value TSRMLS_CC); + php_stat(intern->file_name, intern->file_name_len, FS_IS_LINK, return_value); if (zend_is_true(return_value)) { RETURN_FALSE; } } - php_stat(intern->file_name, intern->file_name_len, FS_IS_DIR, return_value TSRMLS_CC); + php_stat(intern->file_name, intern->file_name_len, FS_IS_DIR, return_value); } } /* }}} */ @@ -1516,31 +1487,29 @@ SPL_METHOD(RecursiveDirectoryIterator, hasChildren) Returns an iterator for the current entry if it is a directory */ SPL_METHOD(RecursiveDirectoryIterator, getChildren) { - zval *zpath, *zflags; - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + zval zpath, zflags; + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); spl_filesystem_object *subdir; char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH; - + if (zend_parse_parameters_none() == FAILURE) { return; } - - spl_filesystem_object_get_file_name(intern TSRMLS_CC); - MAKE_STD_ZVAL(zflags); - MAKE_STD_ZVAL(zpath); - ZVAL_LONG(zflags, intern->flags); - ZVAL_STRINGL(zpath, intern->file_name, intern->file_name_len, 1); - spl_instantiate_arg_ex2(Z_OBJCE_P(getThis()), &return_value, 0, zpath, zflags TSRMLS_CC); + spl_filesystem_object_get_file_name(intern); + + ZVAL_LONG(&zflags, intern->flags); + ZVAL_STRINGL(&zpath, intern->file_name, intern->file_name_len); + spl_instantiate_arg_ex2(Z_OBJCE_P(getThis()), return_value, &zpath, &zflags); zval_ptr_dtor(&zpath); zval_ptr_dtor(&zflags); - subdir = (spl_filesystem_object*)zend_object_store_get_object(return_value TSRMLS_CC); + subdir = Z_SPLFILESYSTEM_P(return_value); if (subdir) { if (intern->u.dir.sub_path && intern->u.dir.sub_path[0]) { - subdir->u.dir.sub_path_len = spprintf(&subdir->u.dir.sub_path, 0, "%s%c%s", intern->u.dir.sub_path, slash, intern->u.dir.entry.d_name); + subdir->u.dir.sub_path_len = (int)spprintf(&subdir->u.dir.sub_path, 0, "%s%c%s", intern->u.dir.sub_path, slash, intern->u.dir.entry.d_name); } else { - subdir->u.dir.sub_path_len = strlen(intern->u.dir.entry.d_name); + subdir->u.dir.sub_path_len = (int)strlen(intern->u.dir.entry.d_name); subdir->u.dir.sub_path = estrndup(intern->u.dir.entry.d_name, subdir->u.dir.sub_path_len); } subdir->info_class = intern->info_class; @@ -1554,16 +1523,16 @@ SPL_METHOD(RecursiveDirectoryIterator, getChildren) Get sub path */ SPL_METHOD(RecursiveDirectoryIterator, getSubPath) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } if (intern->u.dir.sub_path) { - RETURN_STRINGL(intern->u.dir.sub_path, intern->u.dir.sub_path_len, 1); + RETURN_STRINGL(intern->u.dir.sub_path, intern->u.dir.sub_path_len); } else { - RETURN_STRINGL("", 0, 1); + RETURN_EMPTY_STRING(); } } /* }}} */ @@ -1572,20 +1541,17 @@ SPL_METHOD(RecursiveDirectoryIterator, getSubPath) Get sub path and file name */ SPL_METHOD(RecursiveDirectoryIterator, getSubPathname) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - char *sub_name; - int len; + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH; - + if (zend_parse_parameters_none() == FAILURE) { return; } if (intern->u.dir.sub_path) { - len = spprintf(&sub_name, 0, "%s%c%s", intern->u.dir.sub_path, slash, intern->u.dir.entry.d_name); - RETURN_STRINGL(sub_name, len, 0); + RETURN_NEW_STR(strpprintf(0, "%s%c%s", intern->u.dir.sub_path, slash, intern->u.dir.entry.d_name)); } else { - RETURN_STRING(intern->u.dir.entry.d_name, 1); + RETURN_STRING(intern->u.dir.entry.d_name); } } /* }}} */ @@ -1611,8 +1577,8 @@ SPL_METHOD(GlobIterator, __construct) Return the number of directories and files found by globbing */ SPL_METHOD(GlobIterator, count) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1621,19 +1587,19 @@ SPL_METHOD(GlobIterator, count) RETURN_LONG(php_glob_stream_get_count(intern->u.dir.dirp, NULL)); } else { /* should not happen */ - php_error_docref(NULL TSRMLS_CC, E_ERROR, "GlobIterator lost glob state"); + php_error_docref(NULL, E_ERROR, "GlobIterator lost glob state"); } } /* }}} */ #endif /* HAVE_GLOB */ /* {{{ forward declarations to the iterator handlers */ -static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter TSRMLS_DC); -static int spl_filesystem_dir_it_valid(zend_object_iterator *iter TSRMLS_DC); -static void spl_filesystem_dir_it_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC); -static void spl_filesystem_dir_it_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC); -static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter TSRMLS_DC); -static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter TSRMLS_DC); +static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter); +static int spl_filesystem_dir_it_valid(zend_object_iterator *iter); +static zval *spl_filesystem_dir_it_current_data(zend_object_iterator *iter); +static void spl_filesystem_dir_it_current_key(zend_object_iterator *iter, zval *key); +static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter); +static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter); /* iterator handler table */ zend_object_iterator_funcs spl_filesystem_dir_it_funcs = { @@ -1647,50 +1613,44 @@ zend_object_iterator_funcs spl_filesystem_dir_it_funcs = { /* }}} */ /* {{{ spl_ce_dir_get_iterator */ -zend_object_iterator *spl_filesystem_dir_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) +zend_object_iterator *spl_filesystem_dir_get_iterator(zend_class_entry *ce, zval *object, int by_ref) { spl_filesystem_iterator *iterator; - spl_filesystem_object *dir_object; + spl_filesystem_object *dir_object; if (by_ref) { zend_error(E_ERROR, "An iterator cannot be used with foreach by reference"); } - dir_object = (spl_filesystem_object*)zend_object_store_get_object(object TSRMLS_CC); - iterator = spl_filesystem_object_to_iterator(dir_object); + dir_object = Z_SPLFILESYSTEM_P(object); + iterator = spl_filesystem_object_to_iterator(dir_object); + ZVAL_COPY(&iterator->intern.data, object); + iterator->intern.funcs = &spl_filesystem_dir_it_funcs; + /* ->current must be initialized; rewind doesn't set it and valid + * doesn't check whether it's set */ + iterator->current = *object; - /* initialize iterator if it wasn't gotten before */ - if (iterator->intern.data == NULL) { - iterator->intern.data = object; - iterator->intern.funcs = &spl_filesystem_dir_it_funcs; - /* ->current must be initialized; rewind doesn't set it and valid - * doesn't check whether it's set */ - iterator->current = object; - } - zval_add_ref(&object); - - return (zend_object_iterator*)iterator; + return &iterator->intern; } /* }}} */ /* {{{ spl_filesystem_dir_it_dtor */ -static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter TSRMLS_DC) +static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter) { spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter; - if (iterator->intern.data) { - zval *object = iterator->intern.data; - zval_ptr_dtor(&object); + if (!Z_ISUNDEF(iterator->intern.data)) { + zval *object = &iterator->intern.data; + zval_ptr_dtor(object); } /* Otherwise we were called from the owning object free storage handler as - * it sets - * iterator->intern.data to NULL. + * it sets iterator->intern.data to IS_UNDEF. * We don't even need to destroy iterator->current as we didn't add a * reference to it in move_forward or get_iterator */ } /* }}} */ /* {{{ spl_filesystem_dir_it_valid */ -static int spl_filesystem_dir_it_valid(zend_object_iterator *iter TSRMLS_DC) +static int spl_filesystem_dir_it_valid(zend_object_iterator *iter) { spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter); @@ -1699,16 +1659,16 @@ static int spl_filesystem_dir_it_valid(zend_object_iterator *iter TSRMLS_DC) /* }}} */ /* {{{ spl_filesystem_dir_it_current_data */ -static void spl_filesystem_dir_it_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) +static zval *spl_filesystem_dir_it_current_data(zend_object_iterator *iter) { spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter; - - *data = &iterator->current; + + return &iterator->current; } /* }}} */ /* {{{ spl_filesystem_dir_it_current_key */ -static void spl_filesystem_dir_it_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) +static void spl_filesystem_dir_it_current_key(zend_object_iterator *iter, zval *key) { spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter); @@ -1717,12 +1677,12 @@ static void spl_filesystem_dir_it_current_key(zend_object_iterator *iter, zval * /* }}} */ /* {{{ spl_filesystem_dir_it_move_forward */ -static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter TSRMLS_DC) +static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter) { spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter); - + object->u.dir.index++; - spl_filesystem_dir_read(object TSRMLS_CC); + spl_filesystem_dir_read(object); if (object->file_name) { efree(object->file_name); object->file_name = NULL; @@ -1731,111 +1691,110 @@ static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter TSRMLS /* }}} */ /* {{{ spl_filesystem_dir_it_rewind */ -static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter TSRMLS_DC) +static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter) { spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter); - + object->u.dir.index = 0; if (object->u.dir.dirp) { php_stream_rewinddir(object->u.dir.dirp); } - spl_filesystem_dir_read(object TSRMLS_CC); + spl_filesystem_dir_read(object); } /* }}} */ /* {{{ spl_filesystem_tree_it_dtor */ -static void spl_filesystem_tree_it_dtor(zend_object_iterator *iter TSRMLS_DC) +static void spl_filesystem_tree_it_dtor(zend_object_iterator *iter) { spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter; - if (iterator->intern.data) { - zval *object = iterator->intern.data; - zval_ptr_dtor(&object); + if (!Z_ISUNDEF(iterator->intern.data)) { + zval *object = &iterator->intern.data; + zval_ptr_dtor(object); } else { - if (iterator->current) { + if (!Z_ISUNDEF(iterator->current)) { zval_ptr_dtor(&iterator->current); + ZVAL_UNDEF(&iterator->current); } } } /* }}} */ /* {{{ spl_filesystem_tree_it_current_data */ -static void spl_filesystem_tree_it_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) +static zval *spl_filesystem_tree_it_current_data(zend_object_iterator *iter) { spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter; spl_filesystem_object *object = spl_filesystem_iterator_to_object(iterator); if (SPL_FILE_DIR_CURRENT(object, SPL_FILE_DIR_CURRENT_AS_PATHNAME)) { - if (!iterator->current) { - ALLOC_INIT_ZVAL(iterator->current); - spl_filesystem_object_get_file_name(object TSRMLS_CC); - ZVAL_STRINGL(iterator->current, object->file_name, object->file_name_len, 1); + if (Z_ISUNDEF(iterator->current)) { + spl_filesystem_object_get_file_name(object); + ZVAL_STRINGL(&iterator->current, object->file_name, object->file_name_len); } - *data = &iterator->current; + return &iterator->current; } else if (SPL_FILE_DIR_CURRENT(object, SPL_FILE_DIR_CURRENT_AS_FILEINFO)) { - if (!iterator->current) { - ALLOC_INIT_ZVAL(iterator->current); - spl_filesystem_object_get_file_name(object TSRMLS_CC); - spl_filesystem_object_create_type(0, object, SPL_FS_INFO, NULL, iterator->current TSRMLS_CC); + if (Z_ISUNDEF(iterator->current)) { + spl_filesystem_object_get_file_name(object); + spl_filesystem_object_create_type(0, object, SPL_FS_INFO, NULL, &iterator->current); } - *data = &iterator->current; + return &iterator->current; } else { - *data = (zval**)&iterator->intern.data; + return &iterator->intern.data; } } /* }}} */ /* {{{ spl_filesystem_tree_it_current_key */ -static void spl_filesystem_tree_it_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) +static void spl_filesystem_tree_it_current_key(zend_object_iterator *iter, zval *key) { spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter); if (SPL_FILE_DIR_KEY(object, SPL_FILE_DIR_KEY_AS_FILENAME)) { - ZVAL_STRING(key, object->u.dir.entry.d_name, 1); + ZVAL_STRING(key, object->u.dir.entry.d_name); } else { - spl_filesystem_object_get_file_name(object TSRMLS_CC); - ZVAL_STRINGL(key, object->file_name, object->file_name_len, 1); + spl_filesystem_object_get_file_name(object); + ZVAL_STRINGL(key, object->file_name, object->file_name_len); } } /* }}} */ /* {{{ spl_filesystem_tree_it_move_forward */ -static void spl_filesystem_tree_it_move_forward(zend_object_iterator *iter TSRMLS_DC) +static void spl_filesystem_tree_it_move_forward(zend_object_iterator *iter) { spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter; spl_filesystem_object *object = spl_filesystem_iterator_to_object(iterator); - + object->u.dir.index++; do { - spl_filesystem_dir_read(object TSRMLS_CC); + spl_filesystem_dir_read(object); } while (spl_filesystem_is_dot(object->u.dir.entry.d_name)); if (object->file_name) { efree(object->file_name); object->file_name = NULL; } - if (iterator->current) { + if (!Z_ISUNDEF(iterator->current)) { zval_ptr_dtor(&iterator->current); - iterator->current = NULL; + ZVAL_UNDEF(&iterator->current); } } /* }}} */ /* {{{ spl_filesystem_tree_it_rewind */ -static void spl_filesystem_tree_it_rewind(zend_object_iterator *iter TSRMLS_DC) +static void spl_filesystem_tree_it_rewind(zend_object_iterator *iter) { spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter; spl_filesystem_object *object = spl_filesystem_iterator_to_object(iterator); - + object->u.dir.index = 0; if (object->u.dir.dirp) { php_stream_rewinddir(object->u.dir.dirp); } do { - spl_filesystem_dir_read(object TSRMLS_CC); + spl_filesystem_dir_read(object); } while (spl_filesystem_is_dot(object->u.dir.entry.d_name)); - if (iterator->current) { + if (!Z_ISUNDEF(iterator->current)) { zval_ptr_dtor(&iterator->current); - iterator->current = NULL; + ZVAL_UNDEF(&iterator->current); } } /* }}} */ @@ -1852,7 +1811,7 @@ zend_object_iterator_funcs spl_filesystem_tree_it_funcs = { /* }}} */ /* {{{ spl_ce_dir_get_iterator */ -zend_object_iterator *spl_filesystem_tree_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) +zend_object_iterator *spl_filesystem_tree_get_iterator(zend_class_entry *ce, zval *object, int by_ref) { spl_filesystem_iterator *iterator; spl_filesystem_object *dir_object; @@ -1860,28 +1819,24 @@ zend_object_iterator *spl_filesystem_tree_get_iterator(zend_class_entry *ce, zva if (by_ref) { zend_error(E_ERROR, "An iterator cannot be used with foreach by reference"); } - dir_object = (spl_filesystem_object*)zend_object_store_get_object(object TSRMLS_CC); - iterator = spl_filesystem_object_to_iterator(dir_object); + dir_object = Z_SPLFILESYSTEM_P(object); + iterator = spl_filesystem_object_to_iterator(dir_object); - /* initialize iterator if wasn't gotten before */ - if (iterator->intern.data == NULL) { - iterator->intern.data = object; - iterator->intern.funcs = &spl_filesystem_tree_it_funcs; - } - zval_add_ref(&object); - - return (zend_object_iterator*)iterator; + ZVAL_COPY(&iterator->intern.data, object); + iterator->intern.funcs = &spl_filesystem_tree_it_funcs; + + return &iterator->intern; } /* }}} */ /* {{{ spl_filesystem_object_cast */ -static int spl_filesystem_object_cast(zval *readobj, zval *writeobj, int type TSRMLS_DC) +static int spl_filesystem_object_cast(zval *readobj, zval *writeobj, int type) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(readobj TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(readobj); if (type == IS_STRING) { if (Z_OBJCE_P(readobj)->__tostring) { - return std_object_handlers.cast_object(readobj, writeobj, type TSRMLS_CC); + return std_object_handlers.cast_object(readobj, writeobj, type); } switch (intern->type) { @@ -1891,11 +1846,11 @@ static int spl_filesystem_object_cast(zval *readobj, zval *writeobj, int type TS zval retval; zval *retval_ptr = &retval; - ZVAL_STRINGL(retval_ptr, intern->file_name, intern->file_name_len, 1); - zval_dtor(readobj); - ZVAL_ZVAL(writeobj, retval_ptr, 0, 0); + ZVAL_STRINGL(retval_ptr, intern->file_name, intern->file_name_len); + zval_ptr_dtor(readobj); + ZVAL_COPY_VALUE(writeobj, retval_ptr); } else { - ZVAL_STRINGL(writeobj, intern->file_name, intern->file_name_len, 1); + ZVAL_STRINGL(writeobj, intern->file_name, intern->file_name_len); } return SUCCESS; case SPL_FS_DIR: @@ -1903,20 +1858,20 @@ static int spl_filesystem_object_cast(zval *readobj, zval *writeobj, int type TS zval retval; zval *retval_ptr = &retval; - ZVAL_STRING(retval_ptr, intern->u.dir.entry.d_name, 1); - zval_dtor(readobj); - ZVAL_ZVAL(writeobj, retval_ptr, 0, 0); + ZVAL_STRING(retval_ptr, intern->u.dir.entry.d_name); + zval_ptr_dtor(readobj); + ZVAL_COPY_VALUE(writeobj, retval_ptr); } else { - ZVAL_STRING(writeobj, intern->u.dir.entry.d_name, 1); + ZVAL_STRING(writeobj, intern->u.dir.entry.d_name); } return SUCCESS; } - } else if (type == IS_BOOL) { - ZVAL_BOOL(writeobj, 1); + } else if (type == _IS_BOOL) { + ZVAL_TRUE(writeobj); return SUCCESS; } if (readobj == writeobj) { - zval_dtor(readobj); + zval_ptr_dtor(readobj); } ZVAL_NULL(writeobj); return FAILURE; @@ -1925,7 +1880,7 @@ static int spl_filesystem_object_cast(zval *readobj, zval *writeobj, int type TS /* {{{ declare method parameters */ /* supply a name and default to call by parameter */ -ZEND_BEGIN_ARG_INFO(arginfo_info___construct, 0) +ZEND_BEGIN_ARG_INFO(arginfo_info___construct, 0) ZEND_ARG_INFO(0, file_name) ZEND_END_ARG_INFO() @@ -1984,11 +1939,11 @@ static const zend_function_entry spl_SplFileInfo_functions[] = { PHP_FE_END }; -ZEND_BEGIN_ARG_INFO(arginfo_dir___construct, 0) +ZEND_BEGIN_ARG_INFO(arginfo_dir___construct, 0) ZEND_ARG_INFO(0, path) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_dir_it_seek, 0) +ZEND_BEGIN_ARG_INFO(arginfo_dir_it_seek, 0) ZEND_ARG_INFO(0, position) ZEND_END_ARG_INFO(); @@ -2010,7 +1965,7 @@ static const zend_function_entry spl_DirectoryIterator_functions[] = { PHP_FE_END }; -ZEND_BEGIN_ARG_INFO_EX(arginfo_r_dir___construct, 0, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_r_dir___construct, 0, 0, 1) ZEND_ARG_INFO(0, path) ZEND_ARG_INFO(0, flags) ZEND_END_ARG_INFO() @@ -2052,17 +2007,17 @@ static const zend_function_entry spl_GlobIterator_functions[] = { #endif /* }}} */ -static int spl_filesystem_file_read(spl_filesystem_object *intern, int silent TSRMLS_DC) /* {{{ */ +static int spl_filesystem_file_read(spl_filesystem_object *intern, int silent) /* {{{ */ { char *buf; size_t line_len = 0; - long line_add = (intern->u.file.current_line || intern->u.file.current_zval) ? 1 : 0; + zend_long line_add = (intern->u.file.current_line || !Z_ISUNDEF(intern->u.file.current_zval)) ? 1 : 0; + + spl_filesystem_file_free_line(intern); - spl_filesystem_file_free_line(intern TSRMLS_CC); - if (php_stream_eof(intern->u.file.stream)) { if (!silent) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot read from file %s", intern->file_name); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot read from file %s", intern->file_name); } return FAILURE; } @@ -2087,7 +2042,7 @@ static int spl_filesystem_file_read(spl_filesystem_object *intern, int silent TS line_len = strcspn(buf, "\r\n"); buf[line_len] = '\0'; } - + intern->u.file.current_line = buf; intern->u.file.current_line_len = line_len; } @@ -2096,49 +2051,51 @@ static int spl_filesystem_file_read(spl_filesystem_object *intern, int silent TS return SUCCESS; } /* }}} */ -static int spl_filesystem_file_call(spl_filesystem_object *intern, zend_function *func_ptr, int pass_num_args, zval *return_value, zval *arg2 TSRMLS_DC) /* {{{ */ +static int spl_filesystem_file_call(spl_filesystem_object *intern, zend_function *func_ptr, int pass_num_args, zval *return_value, zval *arg2) /* {{{ */ { zend_fcall_info fci; zend_fcall_info_cache fcic; - zval z_fname; - zval * zresource_ptr = &intern->u.file.zresource, *retval = NULL; + zval *zresource_ptr = &intern->u.file.zresource, retval; int result; int num_args = pass_num_args + (arg2 ? 2 : 1); - zval ***params = (zval***)safe_emalloc(num_args, sizeof(zval**), 0); + zval *params = (zval*)safe_emalloc(num_args, sizeof(zval), 0); + + params[0] = *zresource_ptr; - params[0] = &zresource_ptr; - if (arg2) { - params[1] = &arg2; + params[1] = *arg2; } - zend_get_parameters_array_ex(pass_num_args, params+(arg2 ? 2 : 1)); + if (zend_get_parameters_array_ex(pass_num_args, params + (arg2 ? 2 : 1)) != SUCCESS) { + efree(params); + WRONG_PARAM_COUNT_WITH_RETVAL(FAILURE); + } - ZVAL_STRING(&z_fname, func_ptr->common.function_name, 0); + ZVAL_UNDEF(&retval); fci.size = sizeof(fci); fci.function_table = EG(function_table); - fci.object_ptr = NULL; - fci.function_name = &z_fname; - fci.retval_ptr_ptr = &retval; + fci.object = NULL; + fci.retval = &retval; fci.param_count = num_args; fci.params = params; fci.no_separation = 1; fci.symbol_table = NULL; + ZVAL_STR(&fci.function_name, func_ptr->common.function_name); fcic.initialized = 1; fcic.function_handler = func_ptr; fcic.calling_scope = NULL; fcic.called_scope = NULL; - fcic.object_ptr = NULL; + fcic.object = NULL; - result = zend_call_function(&fci, &fcic TSRMLS_CC); - - if (result == FAILURE || retval == NULL) { + result = zend_call_function(&fci, &fcic); + + if (result == FAILURE || Z_ISUNDEF(retval)) { RETVAL_FALSE; } else { - ZVAL_ZVAL(return_value, retval, 1, 1); + ZVAL_ZVAL(return_value, &retval, 0, 0); } efree(params); @@ -2148,73 +2105,75 @@ static int spl_filesystem_file_call(spl_filesystem_object *intern, zend_function #define FileFunctionCall(func_name, pass_num_args, arg2) /* {{{ */ \ { \ zend_function *func_ptr; \ - int ret; \ - ret = zend_hash_find(EG(function_table), #func_name, sizeof(#func_name), (void **) &func_ptr); \ - if (ret != SUCCESS) { \ - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Internal error, function '%s' not found. Please report", #func_name); \ + func_ptr = (zend_function *)zend_hash_str_find_ptr(EG(function_table), #func_name, sizeof(#func_name) - 1); \ + if (func_ptr == NULL) { \ + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Internal error, function '%s' not found. Please report", #func_name); \ return; \ } \ - spl_filesystem_file_call(intern, func_ptr, pass_num_args, return_value, arg2 TSRMLS_CC); \ + spl_filesystem_file_call(intern, func_ptr, pass_num_args, return_value, arg2); \ } /* }}} */ -static int spl_filesystem_file_read_csv(spl_filesystem_object *intern, char delimiter, char enclosure, char escape, zval *return_value TSRMLS_DC) /* {{{ */ +static int spl_filesystem_file_read_csv(spl_filesystem_object *intern, char delimiter, char enclosure, char escape, zval *return_value) /* {{{ */ { int ret = SUCCESS; - + zval *value; + do { - ret = spl_filesystem_file_read(intern, 1 TSRMLS_CC); + ret = spl_filesystem_file_read(intern, 1); } while (ret == SUCCESS && !intern->u.file.current_line_len && SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_SKIP_EMPTY)); - + if (ret == SUCCESS) { size_t buf_len = intern->u.file.current_line_len; char *buf = estrndup(intern->u.file.current_line, buf_len); - if (intern->u.file.current_zval) { + if (!Z_ISUNDEF(intern->u.file.current_zval)) { zval_ptr_dtor(&intern->u.file.current_zval); + ZVAL_UNDEF(&intern->u.file.current_zval); } - ALLOC_INIT_ZVAL(intern->u.file.current_zval); - php_fgetcsv(intern->u.file.stream, delimiter, enclosure, escape, buf_len, buf, intern->u.file.current_zval TSRMLS_CC); + php_fgetcsv(intern->u.file.stream, delimiter, enclosure, escape, buf_len, buf, &intern->u.file.current_zval); if (return_value) { - if (Z_TYPE_P(return_value) != IS_NULL) { - zval_dtor(return_value); - ZVAL_NULL(return_value); - } - ZVAL_ZVAL(return_value, intern->u.file.current_zval, 1, 0); + zval_ptr_dtor(return_value); + value = &intern->u.file.current_zval; + ZVAL_DEREF(value); + ZVAL_COPY(return_value, value); } } return ret; } /* }}} */ -static int spl_filesystem_file_read_line_ex(zval * this_ptr, spl_filesystem_object *intern, int silent TSRMLS_DC) /* {{{ */ +static int spl_filesystem_file_read_line_ex(zval * this_ptr, spl_filesystem_object *intern, int silent) /* {{{ */ { - zval *retval = NULL; + zval retval; /* 1) use fgetcsv? 2) overloaded call the function, 3) do it directly */ if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV) || intern->u.file.func_getCurr->common.scope != spl_ce_SplFileObject) { if (php_stream_eof(intern->u.file.stream)) { if (!silent) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot read from file %s", intern->file_name); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot read from file %s", intern->file_name); } return FAILURE; } if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV)) { - return spl_filesystem_file_read_csv(intern, intern->u.file.delimiter, intern->u.file.enclosure, intern->u.file.escape, NULL TSRMLS_CC); + return spl_filesystem_file_read_csv(intern, intern->u.file.delimiter, intern->u.file.enclosure, intern->u.file.escape, NULL); } else { - zend_call_method_with_0_params(&this_ptr, Z_OBJCE_P(getThis()), &intern->u.file.func_getCurr, "getCurrentLine", &retval); + zend_execute_data *execute_data = EG(current_execute_data); + zend_call_method_with_0_params(this_ptr, Z_OBJCE(EX(This)), &intern->u.file.func_getCurr, "getCurrentLine", &retval); } - if (retval) { - if (intern->u.file.current_line || intern->u.file.current_zval) { + if (!Z_ISUNDEF(retval)) { + if (intern->u.file.current_line || !Z_ISUNDEF(intern->u.file.current_zval)) { intern->u.file.current_line_num++; } - spl_filesystem_file_free_line(intern TSRMLS_CC); - if (Z_TYPE_P(retval) == IS_STRING) { - intern->u.file.current_line = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval)); - intern->u.file.current_line_len = Z_STRLEN_P(retval); + spl_filesystem_file_free_line(intern); + if (Z_TYPE(retval) == IS_STRING) { + intern->u.file.current_line = estrndup(Z_STRVAL(retval), Z_STRLEN(retval)); + intern->u.file.current_line_len = Z_STRLEN(retval); } else { - MAKE_STD_ZVAL(intern->u.file.current_zval); - ZVAL_ZVAL(intern->u.file.current_zval, retval, 1, 0); + zval *value = &retval; + + ZVAL_DEREF(value); + ZVAL_COPY(&intern->u.file.current_zval, value); } zval_ptr_dtor(&retval); return SUCCESS; @@ -2222,30 +2181,35 @@ static int spl_filesystem_file_read_line_ex(zval * this_ptr, spl_filesystem_obje return FAILURE; } } else { - return spl_filesystem_file_read(intern, silent TSRMLS_CC); + return spl_filesystem_file_read(intern, silent); } } /* }}} */ -static int spl_filesystem_file_is_empty_line(spl_filesystem_object *intern TSRMLS_DC) /* {{{ */ +static int spl_filesystem_file_is_empty_line(spl_filesystem_object *intern) /* {{{ */ { if (intern->u.file.current_line) { return intern->u.file.current_line_len == 0; - } else if (intern->u.file.current_zval) { - switch(Z_TYPE_P(intern->u.file.current_zval)) { - case IS_STRING: - return Z_STRLEN_P(intern->u.file.current_zval) == 0; - case IS_ARRAY: - if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV) - && zend_hash_num_elements(Z_ARRVAL_P(intern->u.file.current_zval)) == 1) { - zval ** first = Z_ARRVAL_P(intern->u.file.current_zval)->pListHead->pData; - - return Z_TYPE_PP(first) == IS_STRING && Z_STRLEN_PP(first) == 0; - } - return zend_hash_num_elements(Z_ARRVAL_P(intern->u.file.current_zval)) == 0; - case IS_NULL: - return 1; - default: - return 0; + } else if (!Z_ISUNDEF(intern->u.file.current_zval)) { + switch(Z_TYPE(intern->u.file.current_zval)) { + case IS_STRING: + return Z_STRLEN(intern->u.file.current_zval) == 0; + case IS_ARRAY: + if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV) + && zend_hash_num_elements(Z_ARRVAL(intern->u.file.current_zval)) == 1) { + uint idx = 0; + zval *first; + + while (Z_ISUNDEF(Z_ARRVAL(intern->u.file.current_zval)->arData[idx].val)) { + idx++; + } + first = &Z_ARRVAL(intern->u.file.current_zval)->arData[idx].val; + return Z_TYPE_P(first) == IS_STRING && Z_STRLEN_P(first) == 0; + } + return zend_hash_num_elements(Z_ARRVAL(intern->u.file.current_zval)) == 0; + case IS_NULL: + return 1; + default: + return 0; } } else { return 1; @@ -2253,33 +2217,33 @@ static int spl_filesystem_file_is_empty_line(spl_filesystem_object *intern TSRML } /* }}} */ -static int spl_filesystem_file_read_line(zval * this_ptr, spl_filesystem_object *intern, int silent TSRMLS_DC) /* {{{ */ +static int spl_filesystem_file_read_line(zval * this_ptr, spl_filesystem_object *intern, int silent) /* {{{ */ { - int ret = spl_filesystem_file_read_line_ex(this_ptr, intern, silent TSRMLS_CC); + int ret = spl_filesystem_file_read_line_ex(this_ptr, intern, silent); - while (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_SKIP_EMPTY) && ret == SUCCESS && spl_filesystem_file_is_empty_line(intern TSRMLS_CC)) { - spl_filesystem_file_free_line(intern TSRMLS_CC); - ret = spl_filesystem_file_read_line_ex(this_ptr, intern, silent TSRMLS_CC); + while (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_SKIP_EMPTY) && ret == SUCCESS && spl_filesystem_file_is_empty_line(intern)) { + spl_filesystem_file_free_line(intern); + ret = spl_filesystem_file_read_line_ex(this_ptr, intern, silent); } - + return ret; } /* }}} */ -static void spl_filesystem_file_rewind(zval * this_ptr, spl_filesystem_object *intern TSRMLS_DC) /* {{{ */ +static void spl_filesystem_file_rewind(zval * this_ptr, spl_filesystem_object *intern) /* {{{ */ { if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized"); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); return; } if (-1 == php_stream_rewind(intern->u.file.stream)) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot rewind file %s", intern->file_name); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot rewind file %s", intern->file_name); } else { - spl_filesystem_file_free_line(intern TSRMLS_CC); + spl_filesystem_file_free_line(intern); intern->u.file.current_line_num = 0; } if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) { - spl_filesystem_file_read_line(this_ptr, intern, 1 TSRMLS_CC); + spl_filesystem_file_read_line(this_ptr, intern, 1); } } /* }}} */ @@ -2287,34 +2251,33 @@ static void spl_filesystem_file_rewind(zval * this_ptr, spl_filesystem_object *i Construct a new file object */ SPL_METHOD(SplFileObject, __construct) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); zend_bool use_include_path = 0; char *p1, *p2; char *tmp_path; - int tmp_path_len; + size_t tmp_path_len; zend_error_handling error_handling; - zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling TSRMLS_CC); - intern->u.file.open_mode = NULL; intern->u.file.open_mode_len = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sbr!", + if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "p|sbr!", &intern->file_name, &intern->file_name_len, - &intern->u.file.open_mode, &intern->u.file.open_mode_len, - &use_include_path, &intern->u.file.zcontext) == FAILURE) { + &intern->u.file.open_mode, &intern->u.file.open_mode_len, + &use_include_path, &intern->u.file.zcontext) == FAILURE) { intern->u.file.open_mode = NULL; intern->file_name = NULL; - zend_restore_error_handling(&error_handling TSRMLS_CC); return; } - + if (intern->u.file.open_mode == NULL) { intern->u.file.open_mode = "r"; intern->u.file.open_mode_len = 1; } - if (spl_filesystem_file_open(intern, use_include_path, 0 TSRMLS_CC) == SUCCESS) { + zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling); + + if (spl_filesystem_file_open(intern, use_include_path, 0) == SUCCESS) { tmp_path_len = strlen(intern->u.file.stream->orig_path); if (tmp_path_len > 1 && IS_SLASH_AT(intern->u.file.stream->orig_path, tmp_path_len-1)) { @@ -2330,7 +2293,7 @@ SPL_METHOD(SplFileObject, __construct) p2 = 0; #endif if (p1 || p2) { - intern->_path_len = (p1 > p2 ? p1 : p2) - tmp_path; + intern->_path_len = (int)((p1 > p2 ? p1 : p2) - tmp_path); } else { intern->_path_len = 0; } @@ -2340,7 +2303,7 @@ SPL_METHOD(SplFileObject, __construct) intern->_path = estrndup(intern->u.file.stream->orig_path, intern->_path_len); } - zend_restore_error_handling(&error_handling TSRMLS_CC); + zend_restore_error_handling(&error_handling); } /* }}} */ @@ -2348,15 +2311,12 @@ SPL_METHOD(SplFileObject, __construct) Construct a new temp file object */ SPL_METHOD(SplTempFileObject, __construct) { - long max_memory = PHP_STREAM_MAX_MEM; + zend_long max_memory = PHP_STREAM_MAX_MEM; char tmp_fname[48]; - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); zend_error_handling error_handling; - zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling TSRMLS_CC); - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &max_memory) == FAILURE) { - zend_restore_error_handling(&error_handling TSRMLS_CC); + if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "|l", &max_memory) == FAILURE) { return; } @@ -2364,7 +2324,7 @@ SPL_METHOD(SplTempFileObject, __construct) intern->file_name = "php://memory"; intern->file_name_len = 12; } else if (ZEND_NUM_ARGS()) { - intern->file_name_len = slprintf(tmp_fname, sizeof(tmp_fname), "php://temp/maxmemory:%ld", max_memory); + intern->file_name_len = slprintf(tmp_fname, sizeof(tmp_fname), "php://temp/maxmemory:%pd", max_memory); intern->file_name = tmp_fname; } else { intern->file_name = "php://temp"; @@ -2372,40 +2332,40 @@ SPL_METHOD(SplTempFileObject, __construct) } intern->u.file.open_mode = "wb"; intern->u.file.open_mode_len = 1; - intern->u.file.zcontext = NULL; - - if (spl_filesystem_file_open(intern, 0, 0 TSRMLS_CC) == SUCCESS) { + + zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling); + if (spl_filesystem_file_open(intern, 0, 0) == SUCCESS) { intern->_path_len = 0; intern->_path = estrndup("", 0); } - zend_restore_error_handling(&error_handling TSRMLS_CC); + zend_restore_error_handling(&error_handling); } /* }}} */ /* {{{ proto void SplFileObject::rewind() Rewind the file and read the first line */ SPL_METHOD(SplFileObject, rewind) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } - spl_filesystem_file_rewind(getThis(), intern TSRMLS_CC); + spl_filesystem_file_rewind(getThis(), intern); } /* }}} */ /* {{{ proto void SplFileObject::eof() Return whether end of file is reached */ SPL_METHOD(SplFileObject, eof) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized"); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); return; } @@ -2416,14 +2376,14 @@ SPL_METHOD(SplFileObject, eof) Return !eof() */ SPL_METHOD(SplFileObject, valid) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) { - RETURN_BOOL(intern->u.file.current_line || intern->u.file.current_zval); + RETURN_BOOL(intern->u.file.current_line || !Z_ISUNDEF(intern->u.file.current_zval)); } else { if(!intern->u.file.stream) { RETURN_FALSE; @@ -2436,45 +2396,49 @@ SPL_METHOD(SplFileObject, valid) Rturn next line from file */ SPL_METHOD(SplFileObject, fgets) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized"); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); return; } - if (spl_filesystem_file_read(intern, 0 TSRMLS_CC) == FAILURE) { + if (spl_filesystem_file_read(intern, 0) == FAILURE) { RETURN_FALSE; } - RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len, 1); + RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len); } /* }}} */ /* {{{ proto string SplFileObject::current() Return current line from file */ SPL_METHOD(SplFileObject, current) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized"); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); return; } - if (!intern->u.file.current_line && !intern->u.file.current_zval) { - spl_filesystem_file_read_line(getThis(), intern, 1 TSRMLS_CC); + if (!intern->u.file.current_line && Z_ISUNDEF(intern->u.file.current_zval)) { + spl_filesystem_file_read_line(getThis(), intern, 1); } - if (intern->u.file.current_line && (!SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV) || !intern->u.file.current_zval)) { - RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len, 1); - } else if (intern->u.file.current_zval) { - RETURN_ZVAL(intern->u.file.current_zval, 1, 0); + if (intern->u.file.current_line && (!SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV) || Z_ISUNDEF(intern->u.file.current_zval))) { + RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len); + } else if (!Z_ISUNDEF(intern->u.file.current_zval)) { + zval *value = &intern->u.file.current_zval; + + ZVAL_DEREF(value); + ZVAL_COPY(return_value, value); + return; } RETURN_FALSE; } /* }}} */ @@ -2483,15 +2447,15 @@ SPL_METHOD(SplFileObject, current) Return line number */ SPL_METHOD(SplFileObject, key) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } /* Do not read the next line to support correct counting with fgetc() if (!intern->current_line) { - spl_filesystem_file_read_line(getThis(), intern, 1 TSRMLS_CC); + spl_filesystem_file_read_line(getThis(), intern, 1); } */ RETURN_LONG(intern->u.file.current_line_num); } /* }}} */ @@ -2500,15 +2464,15 @@ SPL_METHOD(SplFileObject, key) Read next line */ SPL_METHOD(SplFileObject, next) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } - spl_filesystem_file_free_line(intern TSRMLS_CC); + spl_filesystem_file_free_line(intern); if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) { - spl_filesystem_file_read_line(getThis(), intern, 1 TSRMLS_CC); + spl_filesystem_file_read_line(getThis(), intern, 1); } intern->u.file.current_line_num++; } /* }}} */ @@ -2517,9 +2481,9 @@ SPL_METHOD(SplFileObject, next) Set file handling flags */ SPL_METHOD(SplFileObject, setFlags) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &intern->flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &intern->flags) == FAILURE) { return; } } /* }}} */ @@ -2528,7 +2492,7 @@ SPL_METHOD(SplFileObject, setFlags) Get file handling flags */ SPL_METHOD(SplFileObject, getFlags) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; @@ -2541,19 +2505,19 @@ SPL_METHOD(SplFileObject, getFlags) Set maximum line length */ SPL_METHOD(SplFileObject, setMaxLineLen) { - long max_len; + zend_long max_len; - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &max_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &max_len) == FAILURE) { return; } if (max_len < 0) { - zend_throw_exception_ex(spl_ce_DomainException, 0 TSRMLS_CC, "Maximum line length must be greater than or equal zero"); + zend_throw_exception_ex(spl_ce_DomainException, 0, "Maximum line length must be greater than or equal zero"); return; } - + intern->u.file.max_line_len = max_len; } /* }}} */ @@ -2561,13 +2525,13 @@ SPL_METHOD(SplFileObject, setMaxLineLen) Get maximum line length */ SPL_METHOD(SplFileObject, getMaxLineLen) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } - RETURN_LONG((long)intern->u.file.max_line_len); + RETURN_LONG((zend_long)intern->u.file.max_line_len); } /* }}} */ /* {{{ proto bool SplFileObject::hasChildren() @@ -2577,7 +2541,7 @@ SPL_METHOD(SplFileObject, hasChildren) if (zend_parse_parameters_none() == FAILURE) { return; } - + RETURN_FALSE; } /* }}} */ @@ -2595,7 +2559,7 @@ SPL_METHOD(SplFileObject, getChildren) #define FileFunction(func_name) \ SPL_METHOD(SplFileObject, func_name) \ { \ - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); \ + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); \ FileFunctionCall(func_name, ZEND_NUM_ARGS(), NULL); \ } /* }}} */ @@ -2604,15 +2568,15 @@ SPL_METHOD(SplFileObject, func_name) \ Return current line as csv */ SPL_METHOD(SplFileObject, fgetcsv) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); char delimiter = intern->u.file.delimiter, enclosure = intern->u.file.enclosure, escape = intern->u.file.escape; char *delim = NULL, *enclo = NULL, *esc = NULL; - int d_len = 0, e_len = 0, esc_len = 0; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sss", &delim, &d_len, &enclo, &e_len, &esc, &esc_len) == SUCCESS) { + size_t d_len = 0, e_len = 0, esc_len = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|sss", &delim, &d_len, &enclo, &e_len, &esc, &esc_len) == SUCCESS) { if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized"); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); return; } @@ -2620,21 +2584,21 @@ SPL_METHOD(SplFileObject, fgetcsv) { case 3: if (esc_len != 1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "escape must be a character"); + php_error_docref(NULL, E_WARNING, "escape must be a character"); RETURN_FALSE; } escape = esc[0]; /* no break */ case 2: if (e_len != 1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "enclosure must be a character"); + php_error_docref(NULL, E_WARNING, "enclosure must be a character"); RETURN_FALSE; } enclosure = enclo[0]; /* no break */ case 1: if (d_len != 1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "delimiter must be a character"); + php_error_docref(NULL, E_WARNING, "delimiter must be a character"); RETURN_FALSE; } delimiter = delim[0]; @@ -2642,7 +2606,7 @@ SPL_METHOD(SplFileObject, fgetcsv) case 0: break; } - spl_filesystem_file_read_csv(intern, delimiter, enclosure, escape, return_value TSRMLS_CC); + spl_filesystem_file_read_csv(intern, delimiter, enclosure, escape, return_value); } } /* }}} */ @@ -2651,32 +2615,33 @@ SPL_METHOD(SplFileObject, fgetcsv) Output a field array as a CSV line */ SPL_METHOD(SplFileObject, fputcsv) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); char delimiter = intern->u.file.delimiter, enclosure = intern->u.file.enclosure, escape = intern->u.file.escape; char *delim = NULL, *enclo = NULL, *esc = NULL; - int d_len = 0, e_len = 0, esc_len = 0, ret; + size_t d_len = 0, e_len = 0, esc_len = 0; + zend_long ret; zval *fields = NULL; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|sss", &fields, &delim, &d_len, &enclo, &e_len, &esc, &esc_len) == SUCCESS) { + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|sss", &fields, &delim, &d_len, &enclo, &e_len, &esc, &esc_len) == SUCCESS) { switch(ZEND_NUM_ARGS()) { case 4: if (esc_len != 1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "escape must be a character"); + php_error_docref(NULL, E_WARNING, "escape must be a character"); RETURN_FALSE; } escape = esc[0]; /* no break */ case 3: if (e_len != 1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "enclosure must be a character"); + php_error_docref(NULL, E_WARNING, "enclosure must be a character"); RETURN_FALSE; } enclosure = enclo[0]; /* no break */ case 2: if (d_len != 1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "delimiter must be a character"); + php_error_docref(NULL, E_WARNING, "delimiter must be a character"); RETURN_FALSE; } delimiter = delim[0]; @@ -2685,41 +2650,41 @@ SPL_METHOD(SplFileObject, fputcsv) case 0: break; } - ret = php_fputcsv(intern->u.file.stream, fields, delimiter, enclosure, escape TSRMLS_CC); + ret = php_fputcsv(intern->u.file.stream, fields, delimiter, enclosure, escape); RETURN_LONG(ret); } } /* }}} */ -/* {{{ proto void SplFileObject::setCsvControl([string delimiter = ',' [, string enclosure = '"' [, string escape = '\\']]]) +/* {{{ proto void SplFileObject::setCsvControl([string delimiter [, string enclosure [, string escape ]]]) Set the delimiter and enclosure character used in fgetcsv */ SPL_METHOD(SplFileObject, setCsvControl) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); char delimiter = ',', enclosure = '"', escape='\\'; char *delim = NULL, *enclo = NULL, *esc = NULL; - int d_len = 0, e_len = 0, esc_len = 0; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sss", &delim, &d_len, &enclo, &e_len, &esc, &esc_len) == SUCCESS) { + size_t d_len = 0, e_len = 0, esc_len = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|sss", &delim, &d_len, &enclo, &e_len, &esc, &esc_len) == SUCCESS) { switch(ZEND_NUM_ARGS()) { case 3: if (esc_len != 1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "escape must be a character"); + php_error_docref(NULL, E_WARNING, "escape must be a character"); RETURN_FALSE; } escape = esc[0]; /* no break */ case 2: if (e_len != 1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "enclosure must be a character"); + php_error_docref(NULL, E_WARNING, "enclosure must be a character"); RETURN_FALSE; } enclosure = enclo[0]; /* no break */ case 1: if (d_len != 1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "delimiter must be a character"); + php_error_docref(NULL, E_WARNING, "delimiter must be a character"); RETURN_FALSE; } delimiter = delim[0]; @@ -2738,18 +2703,18 @@ SPL_METHOD(SplFileObject, setCsvControl) Get the delimiter and enclosure character used in fgetcsv */ SPL_METHOD(SplFileObject, getCsvControl) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); char delimiter[2], enclosure[2]; array_init(return_value); - + delimiter[0] = intern->u.file.delimiter; delimiter[1] = '\0'; enclosure[0] = intern->u.file.enclosure; enclosure[1] = '\0'; - add_next_index_string(return_value, delimiter, 1); - add_next_index_string(return_value, enclosure, 1); + add_next_index_string(return_value, delimiter); + add_next_index_string(return_value, enclosure); } /* }}} */ @@ -2762,10 +2727,10 @@ FileFunction(flock) Flush the file */ SPL_METHOD(SplFileObject, fflush) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized"); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); return; } @@ -2776,11 +2741,11 @@ SPL_METHOD(SplFileObject, fflush) Return current file position */ SPL_METHOD(SplFileObject, ftell) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - long ret; + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + zend_long ret; if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized"); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); return; } @@ -2797,36 +2762,36 @@ SPL_METHOD(SplFileObject, ftell) Return current file position */ SPL_METHOD(SplFileObject, fseek) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - long pos, whence = SEEK_SET; + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + zend_long pos, whence = SEEK_SET; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &pos, &whence) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &pos, &whence) == FAILURE) { return; } if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized"); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); return; } - spl_filesystem_file_free_line(intern TSRMLS_CC); - RETURN_LONG(php_stream_seek(intern->u.file.stream, pos, whence)); + spl_filesystem_file_free_line(intern); + RETURN_LONG(php_stream_seek(intern->u.file.stream, pos, (int)whence)); } /* }}} */ /* {{{ proto int SplFileObject::fgetc() Get a character form the file */ SPL_METHOD(SplFileObject, fgetc) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); char buf[2]; int result; if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized"); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); return; } - spl_filesystem_file_free_line(intern TSRMLS_CC); + spl_filesystem_file_free_line(intern); result = php_stream_getc(intern->u.file.stream); @@ -2839,7 +2804,7 @@ SPL_METHOD(SplFileObject, fgetc) buf[0] = result; buf[1] = '\0'; - RETURN_STRINGL(buf, 1, 1); + RETURN_STRINGL(buf, 1); } } /* }}} */ @@ -2847,37 +2812,34 @@ SPL_METHOD(SplFileObject, fgetc) Get a line from file pointer and strip HTML tags */ SPL_METHOD(SplFileObject, fgetss) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - zval *arg2 = NULL; - MAKE_STD_ZVAL(arg2); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + zval arg2; if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized"); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); return; } if (intern->u.file.max_line_len > 0) { - ZVAL_LONG(arg2, intern->u.file.max_line_len); + ZVAL_LONG(&arg2, intern->u.file.max_line_len); } else { - ZVAL_LONG(arg2, 1024); + ZVAL_LONG(&arg2, 1024); } - spl_filesystem_file_free_line(intern TSRMLS_CC); + spl_filesystem_file_free_line(intern); intern->u.file.current_line_num++; - FileFunctionCall(fgetss, ZEND_NUM_ARGS(), arg2); - - zval_ptr_dtor(&arg2); + FileFunctionCall(fgetss, ZEND_NUM_ARGS(), &arg2); } /* }}} */ /* {{{ proto int SplFileObject::fpassthru() Output all remaining data from a file pointer */ SPL_METHOD(SplFileObject, fpassthru) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized"); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); return; } @@ -2888,14 +2850,14 @@ SPL_METHOD(SplFileObject, fpassthru) Implements a mostly ANSI compatible fscanf() */ SPL_METHOD(SplFileObject, fscanf) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized"); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); return; } - spl_filesystem_file_free_line(intern TSRMLS_CC); + spl_filesystem_file_free_line(intern); intern->u.file.current_line_num++; FileFunctionCall(fscanf, ZEND_NUM_ARGS(), NULL); @@ -2906,22 +2868,27 @@ SPL_METHOD(SplFileObject, fscanf) Binary-safe file write */ SPL_METHOD(SplFileObject, fwrite) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); char *str; - int str_len; - long length = 0; + size_t str_len; + zend_long length = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &str, &str_len, &length) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &str, &str_len, &length) == FAILURE) { return; } if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized"); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); return; } if (ZEND_NUM_ARGS() > 1) { - str_len = MAX(0, MIN(length, str_len)); + if (length >= 0) { + str_len = MAX(0, MIN((size_t)length, str_len)); + } else { + /* Negative length given, nothing to write */ + str_len = 0; + } } if (!str_len) { RETURN_LONG(0); @@ -2932,29 +2899,28 @@ SPL_METHOD(SplFileObject, fwrite) SPL_METHOD(SplFileObject, fread) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - long length = 0; + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + zend_long length = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &length) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &length) == FAILURE) { return; } if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized"); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); return; } if (length <= 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0"); + php_error_docref(NULL, E_WARNING, "Length parameter must be greater than 0"); RETURN_FALSE; } - Z_STRVAL_P(return_value) = emalloc(length + 1); + ZVAL_NEW_STR(return_value, zend_string_alloc(length, 0)); Z_STRLEN_P(return_value) = php_stream_read(intern->u.file.stream, Z_STRVAL_P(return_value), length); /* needed because recv/read/gzread doesnt put a null at the end*/ Z_STRVAL_P(return_value)[Z_STRLEN_P(return_value)] = 0; - Z_TYPE_P(return_value) = IS_STRING; } /* {{{ proto bool SplFileObject::fstat() @@ -2966,23 +2932,23 @@ FileFunction(fstat) Truncate file to 'size' length */ SPL_METHOD(SplFileObject, ftruncate) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - long size; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &size) == FAILURE) { + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + zend_long size; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &size) == FAILURE) { return; } if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized"); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); return; } if (!php_stream_truncate_supported(intern->u.file.stream)) { - zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Can't truncate file %s", intern->file_name); + zend_throw_exception_ex(spl_ce_LogicException, 0, "Can't truncate file %s", intern->file_name); RETURN_FALSE; } - + RETURN_BOOL(0 == php_stream_truncate_set_size(intern->u.file.stream, size)); } /* }}} */ @@ -2990,26 +2956,26 @@ SPL_METHOD(SplFileObject, ftruncate) Seek to specified line */ SPL_METHOD(SplFileObject, seek) { - spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - long line_pos; + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); + zend_long line_pos; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &line_pos) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &line_pos) == FAILURE) { return; } if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Object not initialized"); + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); return; } if (line_pos < 0) { - zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Can't seek file %s to negative line %ld", intern->file_name, line_pos); - RETURN_FALSE; + zend_throw_exception_ex(spl_ce_LogicException, 0, "Can't seek file %s to negative line %pd", intern->file_name, line_pos); + RETURN_FALSE; } - spl_filesystem_file_rewind(getThis(), intern TSRMLS_CC); - + spl_filesystem_file_rewind(getThis(), intern); + while(intern->u.file.current_line_num < line_pos) { - if (spl_filesystem_file_read_line(getThis(), intern, 1 TSRMLS_CC) == FAILURE) { + if (spl_filesystem_file_read_line(getThis(), intern, 1) == FAILURE) { break; } } @@ -3044,26 +3010,26 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fputcsv, 0, 0, 1) ZEND_ARG_INFO(0, escape) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_flock, 0, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_flock, 0, 0, 1) ZEND_ARG_INFO(0, operation) ZEND_ARG_INFO(1, wouldblock) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fseek, 0, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fseek, 0, 0, 1) ZEND_ARG_INFO(0, pos) ZEND_ARG_INFO(0, whence) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fgetss, 0, 0, 0) +ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fgetss, 0, 0, 0) ZEND_ARG_INFO(0, allowable_tags) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fscanf, 0, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fscanf, 0, 0, 1) ZEND_ARG_INFO(0, format) ZEND_ARG_VARIADIC_INFO(1, vars) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fwrite, 0, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fwrite, 0, 0, 1) ZEND_ARG_INFO(0, str) ZEND_ARG_INFO(0, length) ZEND_END_ARG_INFO() @@ -3072,11 +3038,11 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fread, 0, 0, 1) ZEND_ARG_INFO(0, length) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_ftruncate, 0, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_ftruncate, 0, 0, 1) ZEND_ARG_INFO(0, size) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_seek, 0, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_seek, 0, 0, 1) ZEND_ARG_INFO(0, line_pos) ZEND_END_ARG_INFO() @@ -3134,14 +3100,18 @@ PHP_MINIT_FUNCTION(spl_directory) { REGISTER_SPL_STD_CLASS_EX(SplFileInfo, spl_filesystem_object_new, spl_SplFileInfo_functions); memcpy(&spl_filesystem_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - spl_filesystem_object_handlers.clone_obj = spl_filesystem_object_clone; - spl_filesystem_object_handlers.cast_object = spl_filesystem_object_cast; + spl_filesystem_object_handlers.offset = XtOffsetOf(spl_filesystem_object, std); + spl_filesystem_object_handlers.clone_obj = spl_filesystem_object_clone; + spl_filesystem_object_handlers.cast_object = spl_filesystem_object_cast; spl_filesystem_object_handlers.get_debug_info = spl_filesystem_object_get_debug_info; + spl_filesystem_object_handlers.dtor_obj = zend_objects_destroy_object; + spl_filesystem_object_handlers.free_obj = spl_filesystem_object_free_storage; spl_ce_SplFileInfo->serialize = zend_class_serialize_deny; spl_ce_SplFileInfo->unserialize = zend_class_unserialize_deny; + REGISTER_SPL_SUB_CLASS_EX(DirectoryIterator, SplFileInfo, spl_filesystem_object_new, spl_DirectoryIterator_functions); - zend_class_implements(spl_ce_DirectoryIterator TSRMLS_CC, 1, zend_ce_iterator); + zend_class_implements(spl_ce_DirectoryIterator, 1, zend_ce_iterator); REGISTER_SPL_IMPLEMENTS(DirectoryIterator, SeekableIterator); spl_ce_DirectoryIterator->get_iterator = spl_filesystem_dir_get_iterator; @@ -3165,7 +3135,7 @@ PHP_MINIT_FUNCTION(spl_directory) REGISTER_SPL_SUB_CLASS_EX(RecursiveDirectoryIterator, FilesystemIterator, spl_filesystem_object_new, spl_RecursiveDirectoryIterator_functions); REGISTER_SPL_IMPLEMENTS(RecursiveDirectoryIterator, RecursiveIterator); - + memcpy(&spl_filesystem_object_check_handlers, &spl_filesystem_object_handlers, sizeof(zend_object_handlers)); spl_filesystem_object_check_handlers.get_method = spl_filesystem_object_get_method_check; @@ -3182,7 +3152,7 @@ PHP_MINIT_FUNCTION(spl_directory) REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "READ_AHEAD", SPL_FILE_OBJECT_READ_AHEAD); REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "SKIP_EMPTY", SPL_FILE_OBJECT_SKIP_EMPTY); REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "READ_CSV", SPL_FILE_OBJECT_READ_CSV); - + REGISTER_SPL_SUB_CLASS_EX(SplTempFileObject, SplFileObject, spl_filesystem_object_new_check, spl_SplTempFileObject_functions); return SUCCESS; } diff --git a/ext/spl/spl_directory.h b/ext/spl/spl_directory.h index 06272ac629..2f7a323ea6 100644 --- a/ext/spl/spl_directory.h +++ b/ext/spl/spl_directory.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -42,10 +42,10 @@ typedef enum { typedef struct _spl_filesystem_object spl_filesystem_object; -typedef void (*spl_foreign_dtor_t)(spl_filesystem_object *object TSRMLS_DC); -typedef void (*spl_foreign_clone_t)(spl_filesystem_object *src, spl_filesystem_object *dst TSRMLS_DC); +typedef void (*spl_foreign_dtor_t)(spl_filesystem_object *object); +typedef void (*spl_foreign_clone_t)(spl_filesystem_object *src, spl_filesystem_object *dst); -PHPAPI char* spl_filesystem_object_get_path(spl_filesystem_object *intern, int *len TSRMLS_DC); +PHPAPI char* spl_filesystem_object_get_path(spl_filesystem_object *intern, size_t *len); typedef struct _spl_other_handler { spl_foreign_dtor_t dtor; @@ -55,21 +55,20 @@ typedef struct _spl_other_handler { /* define an overloaded iterator structure */ typedef struct { zend_object_iterator intern; - zval *current; - spl_filesystem_object *object; + zval current; + void *object; } spl_filesystem_iterator; struct _spl_filesystem_object { - zend_object std; void *oth; spl_other_handler *oth_handler; char *_path; - int _path_len; + size_t _path_len; char *orig_path; char *file_name; - int file_name_len; + size_t file_name_len; SPL_FS_OBJ_TYPE type; - long flags; + zend_long flags; zend_class_entry *file_class; zend_class_entry *info_class; union { @@ -77,7 +76,7 @@ struct _spl_filesystem_object { php_stream *dirp; php_stream_dirent entry; char *sub_path; - int sub_path_len; + size_t sub_path_len; int index; int is_recursive; zend_function *func_rewind; @@ -89,12 +88,12 @@ struct _spl_filesystem_object { php_stream_context *context; zval *zcontext; char *open_mode; - int open_mode_len; - zval *current_zval; + size_t open_mode_len; + zval current_zval; char *current_line; size_t current_line_len; size_t max_line_len; - long current_line_num; + zend_long current_line_num; zval zresource; zend_function *func_getCurr; char delimiter; @@ -102,17 +101,29 @@ struct _spl_filesystem_object { char escape; } file; } u; - spl_filesystem_iterator it; + zend_object std; }; +static inline spl_filesystem_object *spl_filesystem_from_obj(zend_object *obj) /* {{{ */ { + return (spl_filesystem_object*)((char*)(obj) - XtOffsetOf(spl_filesystem_object, std)); +} +/* }}} */ + +#define Z_SPLFILESYSTEM_P(zv) spl_filesystem_from_obj(Z_OBJ_P((zv))) + static inline spl_filesystem_iterator* spl_filesystem_object_to_iterator(spl_filesystem_object *obj) { - return &obj->it; + spl_filesystem_iterator *it; + + it = ecalloc(1, sizeof(spl_filesystem_iterator)); + it->object = (void *)obj; + zend_iterator_init(&it->intern); + return it; } static inline spl_filesystem_object* spl_filesystem_iterator_to_object(spl_filesystem_iterator *it) { - return (spl_filesystem_object*)((char*)it - XtOffsetOf(spl_filesystem_object, it)); + return (spl_filesystem_object*)it->object; } #define SPL_FILE_OBJECT_DROP_NEW_LINE 0x00000001 /* drop new lines */ diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c index 987fff987a..4eed914aeb 100644 --- a/ext/spl/spl_dllist.c +++ b/ext/spl/spl_dllist.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -29,7 +29,7 @@ #include "php_spl.h" #include "ext/standard/info.h" #include "ext/standard/php_var.h" -#include "ext/standard/php_smart_str.h" +#include "zend_smart_str.h" #include "spl_functions.h" #include "spl_engine.h" #include "spl_iterators.h" @@ -65,11 +65,11 @@ typedef struct _spl_ptr_llist_element { struct _spl_ptr_llist_element *prev; struct _spl_ptr_llist_element *next; int rc; - void *data; + zval data; } spl_ptr_llist_element; -typedef void (*spl_ptr_llist_dtor_func)(spl_ptr_llist_element * TSRMLS_DC); -typedef void (*spl_ptr_llist_ctor_func)(spl_ptr_llist_element * TSRMLS_DC); +typedef void (*spl_ptr_llist_dtor_func)(spl_ptr_llist_element *); +typedef void (*spl_ptr_llist_ctor_func)(spl_ptr_llist_element *); typedef struct _spl_ptr_llist { spl_ptr_llist_element *head; @@ -83,11 +83,9 @@ typedef struct _spl_dllist_object spl_dllist_object; typedef struct _spl_dllist_it spl_dllist_it; struct _spl_dllist_object { - zend_object std; spl_ptr_llist *llist; int traverse_position; spl_ptr_llist_element *traverse_pointer; - zval *retval; int flags; zend_function *fptr_offset_get; zend_function *fptr_offset_set; @@ -95,28 +93,39 @@ struct _spl_dllist_object { zend_function *fptr_offset_del; zend_function *fptr_count; zend_class_entry *ce_get_iterator; - HashTable *debug_info; + zval *gc_data; + int gc_data_count; + zend_object std; }; /* define an overloaded iterator structure */ struct _spl_dllist_it { zend_user_iterator intern; - int traverse_position; spl_ptr_llist_element *traverse_pointer; + int traverse_position; int flags; - spl_dllist_object *object; }; +static inline spl_dllist_object *spl_dllist_from_obj(zend_object *obj) /* {{{ */ { + return (spl_dllist_object*)((char*)(obj) - XtOffsetOf(spl_dllist_object, std)); +} +/* }}} */ + +#define Z_SPLDLLIST_P(zv) spl_dllist_from_obj(Z_OBJ_P((zv))) + /* {{{ spl_ptr_llist */ -static void spl_ptr_llist_zval_dtor(spl_ptr_llist_element *elem TSRMLS_DC) { /* {{{ */ - if (elem->data) { - zval_ptr_dtor((zval **)&elem->data); +static void spl_ptr_llist_zval_dtor(spl_ptr_llist_element *elem) { /* {{{ */ + if (!Z_ISUNDEF(elem->data)) { + zval_ptr_dtor(&elem->data); + ZVAL_UNDEF(&elem->data); } } /* }}} */ -static void spl_ptr_llist_zval_ctor(spl_ptr_llist_element *elem TSRMLS_DC) { /* {{{ */ - Z_ADDREF_P((zval *)elem->data); +static void spl_ptr_llist_zval_ctor(spl_ptr_llist_element *elem) { /* {{{ */ + if (Z_REFCOUNTED(elem->data)) { + Z_ADDREF(elem->data); + } } /* }}} */ @@ -134,13 +143,13 @@ static spl_ptr_llist *spl_ptr_llist_init(spl_ptr_llist_ctor_func ctor, spl_ptr_l } /* }}} */ -static long spl_ptr_llist_count(spl_ptr_llist *llist) /* {{{ */ +static zend_long spl_ptr_llist_count(spl_ptr_llist *llist) /* {{{ */ { - return (long)llist->count; + return (zend_long)llist->count; } /* }}} */ -static void spl_ptr_llist_destroy(spl_ptr_llist *llist TSRMLS_DC) /* {{{ */ +static void spl_ptr_llist_destroy(spl_ptr_llist *llist) /* {{{ */ { spl_ptr_llist_element *current = llist->head, *next; spl_ptr_llist_dtor_func dtor = llist->dtor; @@ -148,7 +157,7 @@ static void spl_ptr_llist_destroy(spl_ptr_llist *llist TSRMLS_DC) /* {{{ */ while (current) { next = current->next; if(current && dtor) { - dtor(current TSRMLS_CC); + dtor(current); } SPL_LLIST_DELREF(current); current = next; @@ -158,7 +167,7 @@ static void spl_ptr_llist_destroy(spl_ptr_llist *llist TSRMLS_DC) /* {{{ */ } /* }}} */ -static spl_ptr_llist_element *spl_ptr_llist_offset(spl_ptr_llist *llist, long offset, int backward) /* {{{ */ +static spl_ptr_llist_element *spl_ptr_llist_offset(spl_ptr_llist *llist, zend_long offset, int backward) /* {{{ */ { spl_ptr_llist_element *current; @@ -183,14 +192,14 @@ static spl_ptr_llist_element *spl_ptr_llist_offset(spl_ptr_llist *llist, long of } /* }}} */ -static void spl_ptr_llist_unshift(spl_ptr_llist *llist, void *data TSRMLS_DC) /* {{{ */ +static void spl_ptr_llist_unshift(spl_ptr_llist *llist, zval *data) /* {{{ */ { spl_ptr_llist_element *elem = emalloc(sizeof(spl_ptr_llist_element)); - elem->data = data; elem->rc = 1; elem->prev = NULL; elem->next = llist->head; + ZVAL_COPY_VALUE(&elem->data, data); if (llist->head) { llist->head->prev = elem; @@ -202,19 +211,19 @@ static void spl_ptr_llist_unshift(spl_ptr_llist *llist, void *data TSRMLS_DC) /* llist->count++; if (llist->ctor) { - llist->ctor(elem TSRMLS_CC); + llist->ctor(elem); } } /* }}} */ -static void spl_ptr_llist_push(spl_ptr_llist *llist, void *data TSRMLS_DC) /* {{{ */ +static void spl_ptr_llist_push(spl_ptr_llist *llist, zval *data) /* {{{ */ { spl_ptr_llist_element *elem = emalloc(sizeof(spl_ptr_llist_element)); - elem->data = data; elem->rc = 1; elem->prev = llist->tail; elem->next = NULL; + ZVAL_COPY_VALUE(&elem->data, data); if (llist->tail) { llist->tail->next = elem; @@ -226,18 +235,18 @@ static void spl_ptr_llist_push(spl_ptr_llist *llist, void *data TSRMLS_DC) /* {{ llist->count++; if (llist->ctor) { - llist->ctor(elem TSRMLS_CC); + llist->ctor(elem); } } /* }}} */ -static void *spl_ptr_llist_pop(spl_ptr_llist *llist TSRMLS_DC) /* {{{ */ +static void spl_ptr_llist_pop(spl_ptr_llist *llist, zval *ret) /* {{{ */ { - void *data; spl_ptr_llist_element *tail = llist->tail; if (tail == NULL) { - return NULL; + ZVAL_UNDEF(ret); + return; } if (tail->prev) { @@ -248,51 +257,49 @@ static void *spl_ptr_llist_pop(spl_ptr_llist *llist TSRMLS_DC) /* {{{ */ llist->tail = tail->prev; llist->count--; - data = tail->data; + ZVAL_COPY(ret, &tail->data); if (llist->dtor) { - llist->dtor(tail TSRMLS_CC); + llist->dtor(tail); } - tail->data = NULL; + ZVAL_UNDEF(&tail->data); SPL_LLIST_DELREF(tail); - - return data; } /* }}} */ -static void *spl_ptr_llist_last(spl_ptr_llist *llist) /* {{{ */ +static zval *spl_ptr_llist_last(spl_ptr_llist *llist) /* {{{ */ { spl_ptr_llist_element *tail = llist->tail; if (tail == NULL) { return NULL; } else { - return tail->data; + return &tail->data; } } /* }}} */ -static void *spl_ptr_llist_first(spl_ptr_llist *llist) /* {{{ */ +static zval *spl_ptr_llist_first(spl_ptr_llist *llist) /* {{{ */ { spl_ptr_llist_element *head = llist->head; if (head == NULL) { return NULL; } else { - return head->data; + return &head->data; } } /* }}} */ -static void *spl_ptr_llist_shift(spl_ptr_llist *llist TSRMLS_DC) /* {{{ */ +static void spl_ptr_llist_shift(spl_ptr_llist *llist, zval *ret) /* {{{ */ { - void *data; spl_ptr_llist_element *head = llist->head; if (head == NULL) { - return NULL; + ZVAL_UNDEF(ret); + return; } if (head->next) { @@ -303,32 +310,32 @@ static void *spl_ptr_llist_shift(spl_ptr_llist *llist TSRMLS_DC) /* {{{ */ llist->head = head->next; llist->count--; - data = head->data; + ZVAL_COPY(ret, &head->data); if (llist->dtor) { - llist->dtor(head TSRMLS_CC); + llist->dtor(head); } - head->data = NULL; + ZVAL_UNDEF(&head->data); SPL_LLIST_DELREF(head); - - return data; } /* }}} */ -static void spl_ptr_llist_copy(spl_ptr_llist *from, spl_ptr_llist *to TSRMLS_DC) /* {{{ */ +static void spl_ptr_llist_copy(spl_ptr_llist *from, spl_ptr_llist *to) /* {{{ */ { - spl_ptr_llist_element *current = from->head, *next; - spl_ptr_llist_ctor_func ctor = from->ctor; + spl_ptr_llist_element *current = from->head, *next; +//??? spl_ptr_llist_ctor_func ctor = from->ctor; while (current) { next = current->next; + /*??? FIXME if (ctor) { - ctor(current TSRMLS_CC); + ctor(current); } + */ - spl_ptr_llist_push(to, current->data TSRMLS_CC); + spl_ptr_llist_push(to, ¤t->data); current = next; } @@ -337,58 +344,50 @@ static void spl_ptr_llist_copy(spl_ptr_llist *from, spl_ptr_llist *to TSRMLS_DC) /* }}} */ -static void spl_dllist_object_free_storage(void *object TSRMLS_DC) /* {{{ */ +static void spl_dllist_object_free_storage(zend_object *object) /* {{{ */ { - spl_dllist_object *intern = (spl_dllist_object *)object; - zval *tmp = NULL; + spl_dllist_object *intern = spl_dllist_from_obj(object); + zval tmp; - zend_object_std_dtor(&intern->std TSRMLS_CC); + zend_object_std_dtor(&intern->std); - while(intern->llist->count > 0) { - tmp = (zval *)spl_ptr_llist_pop(intern->llist TSRMLS_CC); + while (intern->llist->count > 0) { + spl_ptr_llist_pop(intern->llist, &tmp); zval_ptr_dtor(&tmp); } - spl_ptr_llist_destroy(intern->llist TSRMLS_CC); - SPL_LLIST_CHECK_DELREF(intern->traverse_pointer); - zval_ptr_dtor(&intern->retval); - - if (intern->debug_info != NULL) { - zend_hash_destroy(intern->debug_info); - efree(intern->debug_info); - } + if (intern->gc_data != NULL) { + efree(intern->gc_data); + }; - efree(object); + spl_ptr_llist_destroy(intern->llist); + SPL_LLIST_CHECK_DELREF(intern->traverse_pointer); } /* }}} */ -zend_object_iterator *spl_dllist_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC); +zend_object_iterator *spl_dllist_get_iterator(zend_class_entry *ce, zval *object, int by_ref); -static zend_object_value spl_dllist_object_new_ex(zend_class_entry *class_type, spl_dllist_object **obj, zval *orig, int clone_orig TSRMLS_DC) /* {{{ */ +static zend_object *spl_dllist_object_new_ex(zend_class_entry *class_type, zval *orig, int clone_orig) /* {{{ */ { - zend_object_value retval = {0}; spl_dllist_object *intern; zend_class_entry *parent = class_type; int inherited = 0; - intern = ecalloc(1, sizeof(spl_dllist_object)); - *obj = intern; - ALLOC_INIT_ZVAL(intern->retval); + intern = ecalloc(1, sizeof(spl_dllist_object) + zend_object_properties_size(parent)); - zend_object_std_init(&intern->std, class_type TSRMLS_CC); + zend_object_std_init(&intern->std, class_type); object_properties_init(&intern->std, class_type); intern->flags = 0; intern->traverse_position = 0; - intern->debug_info = NULL; if (orig) { - spl_dllist_object *other = (spl_dllist_object*)zend_object_store_get_object(orig TSRMLS_CC); + spl_dllist_object *other = Z_SPLDLLIST_P(orig); intern->ce_get_iterator = other->ce_get_iterator; if (clone_orig) { intern->llist = (spl_ptr_llist *)spl_ptr_llist_init(other->llist->ctor, other->llist->dtor); - spl_ptr_llist_copy(other->llist, intern->llist TSRMLS_CC); + spl_ptr_llist_copy(other->llist, intern->llist); intern->traverse_pointer = intern->llist->head; SPL_LLIST_CHECK_ADDREF(intern->traverse_pointer); } else { @@ -407,14 +406,14 @@ static zend_object_value spl_dllist_object_new_ex(zend_class_entry *class_type, while (parent) { if (parent == spl_ce_SplStack) { intern->flags |= (SPL_DLLIST_IT_FIX | SPL_DLLIST_IT_LIFO); - retval.handlers = &spl_handler_SplDoublyLinkedList; + intern->std.handlers = &spl_handler_SplDoublyLinkedList; } else if (parent == spl_ce_SplQueue) { intern->flags |= SPL_DLLIST_IT_FIX; - retval.handlers = &spl_handler_SplDoublyLinkedList; + intern->std.handlers = &spl_handler_SplDoublyLinkedList; } if (parent == spl_ce_SplDoublyLinkedList) { - retval.handlers = &spl_handler_SplDoublyLinkedList; + intern->std.handlers = &spl_handler_SplDoublyLinkedList; break; } @@ -422,76 +421,66 @@ static zend_object_value spl_dllist_object_new_ex(zend_class_entry *class_type, inherited = 1; } - retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, spl_dllist_object_free_storage, NULL TSRMLS_CC); - if (!parent) { /* this must never happen */ - php_error_docref(NULL TSRMLS_CC, E_COMPILE_ERROR, "Internal compiler error, Class is not child of SplDoublyLinkedList"); + php_error_docref(NULL, E_COMPILE_ERROR, "Internal compiler error, Class is not child of SplDoublyLinkedList"); } if (inherited) { - zend_hash_find(&class_type->function_table, "offsetget", sizeof("offsetget"), (void **) &intern->fptr_offset_get); + intern->fptr_offset_get = zend_hash_str_find_ptr(&class_type->function_table, "offsetget", sizeof("offsetget") - 1); if (intern->fptr_offset_get->common.scope == parent) { intern->fptr_offset_get = NULL; } - zend_hash_find(&class_type->function_table, "offsetset", sizeof("offsetset"), (void **) &intern->fptr_offset_set); + intern->fptr_offset_set = zend_hash_str_find_ptr(&class_type->function_table, "offsetset", sizeof("offsetset") - 1); if (intern->fptr_offset_set->common.scope == parent) { intern->fptr_offset_set = NULL; } - zend_hash_find(&class_type->function_table, "offsetexists", sizeof("offsetexists"), (void **) &intern->fptr_offset_has); + intern->fptr_offset_has = zend_hash_str_find_ptr(&class_type->function_table, "offsetexists", sizeof("offsetexists") - 1); if (intern->fptr_offset_has->common.scope == parent) { intern->fptr_offset_has = NULL; } - zend_hash_find(&class_type->function_table, "offsetunset", sizeof("offsetunset"), (void **) &intern->fptr_offset_del); + intern->fptr_offset_del = zend_hash_str_find_ptr(&class_type->function_table, "offsetunset", sizeof("offsetunset") - 1); if (intern->fptr_offset_del->common.scope == parent) { intern->fptr_offset_del = NULL; } - zend_hash_find(&class_type->function_table, "count", sizeof("count"), (void **) &intern->fptr_count); + intern->fptr_count = zend_hash_str_find_ptr(&class_type->function_table, "count", sizeof("count") - 1); if (intern->fptr_count->common.scope == parent) { intern->fptr_count = NULL; } } - return retval; + return &intern->std; } /* }}} */ -static zend_object_value spl_dllist_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */ +static zend_object *spl_dllist_object_new(zend_class_entry *class_type) /* {{{ */ { - spl_dllist_object *tmp; - return spl_dllist_object_new_ex(class_type, &tmp, NULL, 0 TSRMLS_CC); + return spl_dllist_object_new_ex(class_type, NULL, 0); } /* }}} */ -static zend_object_value spl_dllist_object_clone(zval *zobject TSRMLS_DC) /* {{{ */ +static zend_object *spl_dllist_object_clone(zval *zobject) /* {{{ */ { - zend_object_value new_obj_val; zend_object *old_object; zend_object *new_object; - zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); - spl_dllist_object *intern; - old_object = zend_objects_get_address(zobject TSRMLS_CC); - new_obj_val = spl_dllist_object_new_ex(old_object->ce, &intern, zobject, 1 TSRMLS_CC); - new_object = &intern->std; + old_object = Z_OBJ_P(zobject); + new_object = spl_dllist_object_new_ex(old_object->ce, zobject, 1); - zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC); + zend_objects_clone_members(new_object, old_object); - return new_obj_val; + return new_object; } /* }}} */ -static int spl_dllist_object_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */ +static int spl_dllist_object_count_elements(zval *object, zend_long *count) /* {{{ */ { - spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(object TSRMLS_CC); + spl_dllist_object *intern = Z_SPLDLLIST_P(object); if (intern->fptr_count) { - zval *rv; - zend_call_method_with_0_params(&object, intern->std.ce, &intern->fptr_count, "count", &rv); - if (rv) { - zval_ptr_dtor(&intern->retval); - MAKE_STD_ZVAL(intern->retval); - ZVAL_ZVAL(intern->retval, rv, 1, 1); - convert_to_long(intern->retval); - *count = (long) Z_LVAL_P(intern->retval); + zval rv; + zend_call_method_with_0_params(object, intern->std.ce, &intern->fptr_count, "count", &rv); + if (!Z_ISUNDEF(rv)) { + *count = zval_get_long(&rv); + zval_ptr_dtor(&rv); return SUCCESS; } *count = 0; @@ -503,144 +492,150 @@ static int spl_dllist_object_count_elements(zval *object, long *count TSRMLS_DC) } /* }}} */ -static HashTable* spl_dllist_object_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{{ */ +static HashTable* spl_dllist_object_get_debug_info(zval *obj, int *is_temp) /* {{{{ */ { - spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(obj TSRMLS_CC); + spl_dllist_object *intern = Z_SPLDLLIST_P(obj); spl_ptr_llist_element *current = intern->llist->head, *next; - zval *tmp, zrv, *dllist_array; - char *pnstr; - int pnlen; + zval tmp, dllist_array; + zend_string *pnstr; int i = 0; + HashTable *debug_info; + *is_temp = 1; - *is_temp = 0; - - if (intern->debug_info == NULL) { - ALLOC_HASHTABLE(intern->debug_info); - zend_hash_init(intern->debug_info, 1, NULL, ZVAL_PTR_DTOR, 0); + if (!intern->std.properties) { + rebuild_object_properties(&intern->std); } - if (intern->debug_info->nApplyCount == 0) { - INIT_PZVAL(&zrv); - Z_ARRVAL(zrv) = intern->debug_info; + ALLOC_HASHTABLE(debug_info); + zend_hash_init(debug_info, 1, NULL, ZVAL_PTR_DTOR, 0); + zend_hash_copy(debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref); + + pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "flags", sizeof("flags")-1); + ZVAL_LONG(&tmp, intern->flags); + zend_hash_add(debug_info, pnstr, &tmp); + zend_string_release(pnstr); + + array_init(&dllist_array); + + while (current) { + next = current->next; - if (!intern->std.properties) { - rebuild_object_properties(&intern->std); + add_index_zval(&dllist_array, i, ¤t->data); + if (Z_REFCOUNTED(current->data)) { + Z_ADDREF(current->data); } - zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); + i++; - pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "flags", sizeof("flags")-1, &pnlen TSRMLS_CC); - add_assoc_long_ex(&zrv, pnstr, pnlen+1, intern->flags); - efree(pnstr); + current = next; + } - ALLOC_INIT_ZVAL(dllist_array); - array_init(dllist_array); + pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "dllist", sizeof("dllist")-1); + zend_hash_add(debug_info, pnstr, &dllist_array); + zend_string_release(pnstr); - while (current) { - next = current->next; + return debug_info; +} +/* }}}} */ - add_index_zval(dllist_array, i, (zval *)current->data); - Z_ADDREF_P(current->data); - i++; +static HashTable *spl_dllist_object_get_gc(zval *obj, zval **gc_data, int *gc_data_count) /* {{{ */ +{ + spl_dllist_object *intern = Z_SPLDLLIST_P(obj); + spl_ptr_llist_element *current = intern->llist->head; + int i = 0; - current = next; - } + if (intern->gc_data_count < intern->llist->count) { + intern->gc_data_count = intern->llist->count; + intern->gc_data = safe_erealloc(intern->gc_data, intern->gc_data_count, sizeof(zval), 0); + } - pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "dllist", sizeof("dllist")-1, &pnlen TSRMLS_CC); - add_assoc_zval_ex(&zrv, pnstr, pnlen+1, dllist_array); - efree(pnstr); + while (current) { + ZVAL_COPY_VALUE(&intern->gc_data[i++], ¤t->data); + current = current->next; } - return intern->debug_info; + *gc_data = intern->gc_data; + *gc_data_count = i; + return zend_std_get_properties(obj); } -/* }}}} */ +/* }}} */ -/* {{{ proto bool SplDoublyLinkedList::push(mixed $value) U +/* {{{ proto bool SplDoublyLinkedList::push(mixed value) Push $value on the SplDoublyLinkedList */ SPL_METHOD(SplDoublyLinkedList, push) { zval *value; spl_dllist_object *intern; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &value) == FAILURE) { return; } - SEPARATE_ARG_IF_REF(value); - - intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - spl_ptr_llist_push(intern->llist, value TSRMLS_CC); + intern = Z_SPLDLLIST_P(getThis()); + spl_ptr_llist_push(intern->llist, value); RETURN_TRUE; } /* }}} */ -/* {{{ proto bool SplDoublyLinkedList::unshift(mixed $value) U +/* {{{ proto bool SplDoublyLinkedList::unshift(mixed value) Unshift $value on the SplDoublyLinkedList */ SPL_METHOD(SplDoublyLinkedList, unshift) { zval *value; spl_dllist_object *intern; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &value) == FAILURE) { return; } - SEPARATE_ARG_IF_REF(value); - - intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - spl_ptr_llist_unshift(intern->llist, value TSRMLS_CC); + intern = Z_SPLDLLIST_P(getThis()); + spl_ptr_llist_unshift(intern->llist, value); RETURN_TRUE; } /* }}} */ -/* {{{ proto mixed SplDoublyLinkedList::pop() U +/* {{{ proto mixed SplDoublyLinkedList::pop() Pop an element out of the SplDoublyLinkedList */ SPL_METHOD(SplDoublyLinkedList, pop) { - zval *value; spl_dllist_object *intern; if (zend_parse_parameters_none() == FAILURE) { return; } - intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - value = (zval *)spl_ptr_llist_pop(intern->llist TSRMLS_CC); + intern = Z_SPLDLLIST_P(getThis()); + spl_ptr_llist_pop(intern->llist, return_value); - if (value == NULL) { - zend_throw_exception(spl_ce_RuntimeException, "Can't pop from an empty datastructure", 0 TSRMLS_CC); - return; + if (Z_ISUNDEF_P(return_value)) { + zend_throw_exception(spl_ce_RuntimeException, "Can't pop from an empty datastructure", 0); + RETURN_NULL(); } - - RETURN_ZVAL(value, 1, 1); } /* }}} */ -/* {{{ proto mixed SplDoublyLinkedList::shift() U +/* {{{ proto mixed SplDoublyLinkedList::shift() Shift an element out of the SplDoublyLinkedList */ SPL_METHOD(SplDoublyLinkedList, shift) { - zval *value; spl_dllist_object *intern; if (zend_parse_parameters_none() == FAILURE) { return; } - intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - value = (zval *)spl_ptr_llist_shift(intern->llist TSRMLS_CC); + intern = Z_SPLDLLIST_P(getThis()); + spl_ptr_llist_shift(intern->llist, return_value); - if (value == NULL) { - zend_throw_exception(spl_ce_RuntimeException, "Can't shift from an empty datastructure", 0 TSRMLS_CC); - return; + if (Z_ISUNDEF_P(return_value)) { + zend_throw_exception(spl_ce_RuntimeException, "Can't shift from an empty datastructure", 0); + RETURN_NULL(); } - - RETURN_ZVAL(value, 1, 1); } /* }}} */ -/* {{{ proto mixed SplDoublyLinkedList::top() U +/* {{{ proto mixed SplDoublyLinkedList::top() Peek at the top element of the SplDoublyLinkedList */ SPL_METHOD(SplDoublyLinkedList, top) { @@ -651,19 +646,20 @@ SPL_METHOD(SplDoublyLinkedList, top) return; } - intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - value = (zval *)spl_ptr_llist_last(intern->llist); + intern = Z_SPLDLLIST_P(getThis()); + value = spl_ptr_llist_last(intern->llist); - if (value == NULL) { - zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty datastructure", 0 TSRMLS_CC); + if (value == NULL || Z_ISUNDEF_P(value)) { + zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty datastructure", 0); return; } - RETURN_ZVAL(value, 1, 0); + ZVAL_DEREF(value); + ZVAL_COPY(return_value, value); } /* }}} */ -/* {{{ proto mixed SplDoublyLinkedList::bottom() U +/* {{{ proto mixed SplDoublyLinkedList::bottom() Peek at the bottom element of the SplDoublyLinkedList */ SPL_METHOD(SplDoublyLinkedList, bottom) { @@ -674,24 +670,25 @@ SPL_METHOD(SplDoublyLinkedList, bottom) return; } - intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - value = (zval *)spl_ptr_llist_first(intern->llist); + intern = Z_SPLDLLIST_P(getThis()); + value = spl_ptr_llist_first(intern->llist); - if (value == NULL) { - zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty datastructure", 0 TSRMLS_CC); + if (value == NULL || Z_ISUNDEF_P(value)) { + zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty datastructure", 0); return; } - RETURN_ZVAL(value, 1, 0); + ZVAL_DEREF(value); + ZVAL_COPY(return_value, value); } /* }}} */ -/* {{{ proto int SplDoublyLinkedList::count() U +/* {{{ proto int SplDoublyLinkedList::count() Return the number of elements in the datastructure. */ SPL_METHOD(SplDoublyLinkedList, count) { - long count; - spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + zend_long count; + spl_dllist_object *intern = Z_SPLDLLIST_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; @@ -702,37 +699,37 @@ SPL_METHOD(SplDoublyLinkedList, count) } /* }}} */ -/* {{{ proto int SplDoublyLinkedList::isEmpty() U +/* {{{ proto int SplDoublyLinkedList::isEmpty() Return true if the SplDoublyLinkedList is empty. */ SPL_METHOD(SplDoublyLinkedList, isEmpty) { - long count; + zend_long count; if (zend_parse_parameters_none() == FAILURE) { return; } - spl_dllist_object_count_elements(getThis(), &count TSRMLS_CC); - RETURN_BOOL(count==0); + spl_dllist_object_count_elements(getThis(), &count); + RETURN_BOOL(count == 0); } /* }}} */ -/* {{{ proto int SplDoublyLinkedList::setIteratorMode($flags) U +/* {{{ proto int SplDoublyLinkedList::setIteratorMode(int flags) Set the mode of iteration */ SPL_METHOD(SplDoublyLinkedList, setIteratorMode) { - long value; + zend_long value; spl_dllist_object *intern; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &value) == FAILURE) { return; } - intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_SPLDLLIST_P(getThis()); if (intern->flags & SPL_DLLIST_IT_FIX && (intern->flags & SPL_DLLIST_IT_LIFO) != (value & SPL_DLLIST_IT_LIFO)) { - zend_throw_exception(spl_ce_RuntimeException, "Iterators' LIFO/FIFO modes for SplStack/SplQueue objects are frozen", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_RuntimeException, "Iterators' LIFO/FIFO modes for SplStack/SplQueue objects are frozen", 0); return; } @@ -742,7 +739,7 @@ SPL_METHOD(SplDoublyLinkedList, setIteratorMode) } /* }}} */ -/* {{{ proto int SplDoublyLinkedList::getIteratorMode() U +/* {{{ proto int SplDoublyLinkedList::getIteratorMode() Return the mode of iteration */ SPL_METHOD(SplDoublyLinkedList, getIteratorMode) { @@ -752,89 +749,89 @@ SPL_METHOD(SplDoublyLinkedList, getIteratorMode) return; } - intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_SPLDLLIST_P(getThis()); RETURN_LONG(intern->flags); } /* }}} */ -/* {{{ proto bool SplDoublyLinkedList::offsetExists(mixed $index) U +/* {{{ proto bool SplDoublyLinkedList::offsetExists(mixed index) Returns whether the requested $index exists. */ SPL_METHOD(SplDoublyLinkedList, offsetExists) { zval *zindex; spl_dllist_object *intern; - long index; + zend_long index; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zindex) == FAILURE) { return; } - intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - index = spl_offset_convert_to_long(zindex TSRMLS_CC); + intern = Z_SPLDLLIST_P(getThis()); + index = spl_offset_convert_to_long(zindex); RETURN_BOOL(index >= 0 && index < intern->llist->count); } /* }}} */ -/* {{{ proto mixed SplDoublyLinkedList::offsetGet(mixed $index) U +/* {{{ proto mixed SplDoublyLinkedList::offsetGet(mixed index) Returns the value at the specified $index. */ SPL_METHOD(SplDoublyLinkedList, offsetGet) { - zval *zindex, *value; - long index; + zval *zindex; + zend_long index; spl_dllist_object *intern; spl_ptr_llist_element *element; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zindex) == FAILURE) { return; } - intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - index = spl_offset_convert_to_long(zindex TSRMLS_CC); + intern = Z_SPLDLLIST_P(getThis()); + index = spl_offset_convert_to_long(zindex); if (index < 0 || index >= intern->llist->count) { - zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0); return; } element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO); if (element != NULL) { - value = (zval *)element->data; - RETURN_ZVAL(value, 1, 0); + zval *value = &element->data; + + ZVAL_DEREF(value); + ZVAL_COPY(return_value, value); } else { - zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid", 0 TSRMLS_CC); - return; + zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid", 0); } } /* }}} */ -/* {{{ proto void SplDoublyLinkedList::offsetSet(mixed $index, mixed $newval) U +/* {{{ proto void SplDoublyLinkedList::offsetSet(mixed index, mixed newval) Sets the value at the specified $index to $newval. */ SPL_METHOD(SplDoublyLinkedList, offsetSet) { zval *zindex, *value; spl_dllist_object *intern; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &zindex, &value) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &zindex, &value) == FAILURE) { return; } - SEPARATE_ARG_IF_REF(value); - intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_SPLDLLIST_P(getThis()); if (Z_TYPE_P(zindex) == IS_NULL) { /* $obj[] = ... */ - spl_ptr_llist_push(intern->llist, value TSRMLS_CC); + spl_ptr_llist_push(intern->llist, value); } else { /* $obj[$foo] = ... */ - long index; + zend_long index; spl_ptr_llist_element *element; - index = spl_offset_convert_to_long(zindex TSRMLS_CC); + index = spl_offset_convert_to_long(zindex); if (index < 0 || index >= intern->llist->count) { - zval_ptr_dtor(&value); - zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0 TSRMLS_CC); + zval_ptr_dtor(value); + zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0); return; } @@ -843,46 +840,46 @@ SPL_METHOD(SplDoublyLinkedList, offsetSet) if (element != NULL) { /* call dtor on the old element as in spl_ptr_llist_pop */ if (intern->llist->dtor) { - intern->llist->dtor(element TSRMLS_CC); + intern->llist->dtor(element); } /* the element is replaced, delref the old one as in * SplDoublyLinkedList::pop() */ - zval_ptr_dtor((zval **)&element->data); - element->data = value; + zval_ptr_dtor(&element->data); + ZVAL_COPY_VALUE(&element->data, value); /* new element, call ctor as in spl_ptr_llist_push */ if (intern->llist->ctor) { - intern->llist->ctor(element TSRMLS_CC); + intern->llist->ctor(element); } } else { - zval_ptr_dtor(&value); - zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid", 0 TSRMLS_CC); + zval_ptr_dtor(value); + zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid", 0); return; } } } /* }}} */ -/* {{{ proto void SplDoublyLinkedList::offsetUnset(mixed $index) U +/* {{{ proto void SplDoublyLinkedList::offsetUnset(mixed index) Unsets the value at the specified $index. */ SPL_METHOD(SplDoublyLinkedList, offsetUnset) { zval *zindex; - long index; + zend_long index; spl_dllist_object *intern; spl_ptr_llist_element *element; spl_ptr_llist *llist; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zindex) == FAILURE) { return; } - intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - index = spl_offset_convert_to_long(zindex TSRMLS_CC); + intern = Z_SPLDLLIST_P(getThis()); + index = spl_offset_convert_to_long(zindex); llist = intern->llist; if (index < 0 || index >= intern->llist->count) { - zend_throw_exception(spl_ce_OutOfRangeException, "Offset out of range", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_OutOfRangeException, "Offset out of range", 0); return; } @@ -911,38 +908,35 @@ SPL_METHOD(SplDoublyLinkedList, offsetUnset) llist->count--; if(llist->dtor) { - llist->dtor(element TSRMLS_CC); + llist->dtor(element); } if (intern->traverse_pointer == element) { SPL_LLIST_DELREF(element); intern->traverse_pointer = NULL; } - - zval_ptr_dtor((zval **)&element->data); - element->data = NULL; + zval_ptr_dtor(&element->data); + ZVAL_UNDEF(&element->data); SPL_LLIST_DELREF(element); } else { - zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid", 0); return; } } /* }}} */ -static void spl_dllist_it_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ +static void spl_dllist_it_dtor(zend_object_iterator *iter) /* {{{ */ { spl_dllist_it *iterator = (spl_dllist_it *)iter; SPL_LLIST_CHECK_DELREF(iterator->traverse_pointer); - zend_user_it_invalidate_current(iter TSRMLS_CC); - zval_ptr_dtor((zval**)&iterator->intern.it.data); - - efree(iterator); + zend_user_it_invalidate_current(iter); + zval_ptr_dtor(&iterator->intern.it.data); } /* }}} */ -static void spl_dllist_it_helper_rewind(spl_ptr_llist_element **traverse_pointer_ptr, int *traverse_position_ptr, spl_ptr_llist *llist, int flags TSRMLS_DC) /* {{{ */ +static void spl_dllist_it_helper_rewind(spl_ptr_llist_element **traverse_pointer_ptr, int *traverse_position_ptr, spl_ptr_llist *llist, int flags) /* {{{ */ { SPL_LLIST_CHECK_DELREF(*traverse_pointer_ptr); @@ -958,7 +952,7 @@ static void spl_dllist_it_helper_rewind(spl_ptr_llist_element **traverse_pointer } /* }}} */ -static void spl_dllist_it_helper_move_forward(spl_ptr_llist_element **traverse_pointer_ptr, int *traverse_position_ptr, spl_ptr_llist *llist, int flags TSRMLS_DC) /* {{{ */ +static void spl_dllist_it_helper_move_forward(spl_ptr_llist_element **traverse_pointer_ptr, int *traverse_position_ptr, spl_ptr_llist *llist, int flags) /* {{{ */ { if (*traverse_pointer_ptr) { spl_ptr_llist_element *old = *traverse_pointer_ptr; @@ -968,21 +962,19 @@ static void spl_dllist_it_helper_move_forward(spl_ptr_llist_element **traverse_p (*traverse_position_ptr)--; if (flags & SPL_DLLIST_IT_DELETE) { - zval *prev = (zval *)spl_ptr_llist_pop(llist TSRMLS_CC); + zval prev; + spl_ptr_llist_pop(llist, &prev); - if (prev) { - zval_ptr_dtor((zval **)&prev); - } + zval_ptr_dtor(&prev); } } else { *traverse_pointer_ptr = old->next; if (flags & SPL_DLLIST_IT_DELETE) { - zval *prev = (zval *)spl_ptr_llist_shift(llist TSRMLS_CC); + zval prev; + spl_ptr_llist_shift(llist, &prev); - if (prev) { - zval_ptr_dtor((zval **)&prev); - } + zval_ptr_dtor(&prev); } else { (*traverse_position_ptr)++; } @@ -994,17 +986,17 @@ static void spl_dllist_it_helper_move_forward(spl_ptr_llist_element **traverse_p } /* }}} */ -static void spl_dllist_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ +static void spl_dllist_it_rewind(zend_object_iterator *iter) /* {{{ */ { - spl_dllist_it *iterator = (spl_dllist_it *)iter; - spl_dllist_object *object = iterator->object; - spl_ptr_llist *llist = object->llist; + spl_dllist_it *iterator = (spl_dllist_it *)iter; + spl_dllist_object *object = Z_SPLDLLIST_P(&iter->data); + spl_ptr_llist *llist = object->llist; - spl_dllist_it_helper_rewind(&iterator->traverse_pointer, &iterator->traverse_position, llist, object->flags TSRMLS_CC); + spl_dllist_it_helper_rewind(&iterator->traverse_pointer, &iterator->traverse_position, llist, object->flags); } /* }}} */ -static int spl_dllist_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ +static int spl_dllist_it_valid(zend_object_iterator *iter) /* {{{ */ { spl_dllist_it *iterator = (spl_dllist_it *)iter; spl_ptr_llist_element *element = iterator->traverse_pointer; @@ -1013,20 +1005,20 @@ static int spl_dllist_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ } /* }}} */ -static void spl_dllist_it_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */ +static zval *spl_dllist_it_get_current_data(zend_object_iterator *iter) /* {{{ */ { spl_dllist_it *iterator = (spl_dllist_it *)iter; spl_ptr_llist_element *element = iterator->traverse_pointer; - if (element == NULL || element->data == NULL) { - *data = NULL; - } else { - *data = (zval **)&element->data; + if (element == NULL || Z_ISUNDEF(element->data)) { + return NULL; } + + return &element->data; } /* }}} */ -static void spl_dllist_it_get_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) /* {{{ */ +static void spl_dllist_it_get_current_key(zend_object_iterator *iter, zval *key) /* {{{ */ { spl_dllist_it *iterator = (spl_dllist_it *)iter; @@ -1034,22 +1026,22 @@ static void spl_dllist_it_get_current_key(zend_object_iterator *iter, zval *key } /* }}} */ -static void spl_dllist_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ +static void spl_dllist_it_move_forward(zend_object_iterator *iter) /* {{{ */ { - spl_dllist_it *iterator = (spl_dllist_it *)iter; - spl_dllist_object *object = iterator->object; + spl_dllist_it *iterator = (spl_dllist_it *)iter; + spl_dllist_object *object = Z_SPLDLLIST_P(&iter->data); - zend_user_it_invalidate_current(iter TSRMLS_CC); + zend_user_it_invalidate_current(iter); - spl_dllist_it_helper_move_forward(&iterator->traverse_pointer, &iterator->traverse_position, object->llist, object->flags TSRMLS_CC); + spl_dllist_it_helper_move_forward(&iterator->traverse_pointer, &iterator->traverse_position, object->llist, object->flags); } /* }}} */ -/* {{{ proto int SplDoublyLinkedList::key() U +/* {{{ proto int SplDoublyLinkedList::key() Return current array key */ SPL_METHOD(SplDoublyLinkedList, key) { - spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_dllist_object *intern = Z_SPLDLLIST_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; @@ -1059,39 +1051,39 @@ SPL_METHOD(SplDoublyLinkedList, key) } /* }}} */ -/* {{{ proto void SplDoublyLinkedList::prev() U +/* {{{ proto void SplDoublyLinkedList::prev() Move to next entry */ SPL_METHOD(SplDoublyLinkedList, prev) { - spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_dllist_object *intern = Z_SPLDLLIST_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; } - spl_dllist_it_helper_move_forward(&intern->traverse_pointer, &intern->traverse_position, intern->llist, intern->flags ^ SPL_DLLIST_IT_LIFO TSRMLS_CC); + spl_dllist_it_helper_move_forward(&intern->traverse_pointer, &intern->traverse_position, intern->llist, intern->flags ^ SPL_DLLIST_IT_LIFO); } /* }}} */ -/* {{{ proto void SplDoublyLinkedList::next() U +/* {{{ proto void SplDoublyLinkedList::next() Move to next entry */ SPL_METHOD(SplDoublyLinkedList, next) { - spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_dllist_object *intern = Z_SPLDLLIST_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; } - spl_dllist_it_helper_move_forward(&intern->traverse_pointer, &intern->traverse_position, intern->llist, intern->flags TSRMLS_CC); + spl_dllist_it_helper_move_forward(&intern->traverse_pointer, &intern->traverse_position, intern->llist, intern->flags); } /* }}} */ -/* {{{ proto bool SplDoublyLinkedList::valid() U +/* {{{ proto bool SplDoublyLinkedList::valid() Check whether the datastructure contains more entries */ SPL_METHOD(SplDoublyLinkedList, valid) { - spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_dllist_object *intern = Z_SPLDLLIST_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; @@ -1101,47 +1093,50 @@ SPL_METHOD(SplDoublyLinkedList, valid) } /* }}} */ -/* {{{ proto void SplDoublyLinkedList::rewind() U +/* {{{ proto void SplDoublyLinkedList::rewind() Rewind the datastructure back to the start */ SPL_METHOD(SplDoublyLinkedList, rewind) { - spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_dllist_object *intern = Z_SPLDLLIST_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; } - spl_dllist_it_helper_rewind(&intern->traverse_pointer, &intern->traverse_position, intern->llist, intern->flags TSRMLS_CC); + spl_dllist_it_helper_rewind(&intern->traverse_pointer, &intern->traverse_position, intern->llist, intern->flags); } /* }}} */ -/* {{{ proto mixed|NULL SplDoublyLinkedList::current() U +/* {{{ proto mixed|NULL SplDoublyLinkedList::current() Return current datastructure entry */ SPL_METHOD(SplDoublyLinkedList, current) { - spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_dllist_object *intern = Z_SPLDLLIST_P(getThis()); spl_ptr_llist_element *element = intern->traverse_pointer; if (zend_parse_parameters_none() == FAILURE) { return; } - if (element == NULL || element->data == NULL) { + if (element == NULL || Z_ISUNDEF(element->data)) { RETURN_NULL(); } else { - zval *data = (zval *)element->data; - RETURN_ZVAL(data, 1, 0); + zval *value = &element->data; + + ZVAL_DEREF(value); + ZVAL_COPY(return_value, value); } } /* }}} */ + /* {{{ proto string SplDoublyLinkedList::serialize() Serializes storage */ SPL_METHOD(SplDoublyLinkedList, serialize) { - spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_dllist_object *intern = Z_SPLDLLIST_P(getThis()); smart_str buf = {0}; spl_ptr_llist_element *current = intern->llist->head, *next; - zval *flags; + zval flags; php_serialize_data_t var_hash; if (zend_parse_parameters_none() == FAILURE) { @@ -1151,9 +1146,8 @@ SPL_METHOD(SplDoublyLinkedList, serialize) PHP_VAR_SERIALIZE_INIT(var_hash); /* flags */ - MAKE_STD_ZVAL(flags); - ZVAL_LONG(flags, intern->flags); - php_var_serialize(&buf, &flags, &var_hash TSRMLS_CC); + ZVAL_LONG(&flags, intern->flags); + php_var_serialize(&buf, &flags, &var_hash); zval_ptr_dtor(&flags); /* elements */ @@ -1161,7 +1155,7 @@ SPL_METHOD(SplDoublyLinkedList, serialize) smart_str_appendc(&buf, ':'); next = current->next; - php_var_serialize(&buf, (zval **)¤t->data, &var_hash TSRMLS_CC); + php_var_serialize(&buf, ¤t->data, &var_hash); current = next; } @@ -1171,8 +1165,8 @@ SPL_METHOD(SplDoublyLinkedList, serialize) /* done */ PHP_VAR_SERIALIZE_DESTROY(var_hash); - if (buf.c) { - RETURN_STRINGL(buf.c, buf.len, 0); + if (buf.s) { + RETURN_NEW_STR(buf.s); } else { RETURN_NULL(); } @@ -1183,14 +1177,14 @@ SPL_METHOD(SplDoublyLinkedList, serialize) Unserializes storage */ SPL_METHOD(SplDoublyLinkedList, unserialize) { - spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - zval *flags, *elem; + spl_dllist_object *intern = Z_SPLDLLIST_P(getThis()); + zval *flags, *elem; char *buf; - int buf_len; + size_t buf_len; const unsigned char *p, *s; php_unserialize_data_t var_hash; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &buf, &buf_len) == FAILURE) { return; } @@ -1202,26 +1196,23 @@ SPL_METHOD(SplDoublyLinkedList, unserialize) PHP_VAR_UNSERIALIZE_INIT(var_hash); /* flags */ - ALLOC_INIT_ZVAL(flags); - if (!php_var_unserialize(&flags, &p, s + buf_len, &var_hash TSRMLS_CC) || Z_TYPE_P(flags) != IS_LONG) { - zval_ptr_dtor(&flags); + flags = var_tmp_var(&var_hash); + if (!php_var_unserialize(flags, &p, s + buf_len, &var_hash) || Z_TYPE_P(flags) != IS_LONG) { goto error; } - var_push_dtor(&var_hash, &flags); - intern->flags = Z_LVAL_P(flags); - zval_ptr_dtor(&flags); + + intern->flags = (int)Z_LVAL_P(flags); /* elements */ while(*p == ':') { ++p; - ALLOC_INIT_ZVAL(elem); - if (!php_var_unserialize(&elem, &p, s + buf_len, &var_hash TSRMLS_CC)) { - zval_ptr_dtor(&elem); + elem = var_tmp_var(&var_hash); + if (!php_var_unserialize(elem, &p, s + buf_len, &var_hash)) { goto error; } - var_push_dtor(&var_hash, &elem); + var_push_dtor(&var_hash, elem); - spl_ptr_llist_push(intern->llist, elem TSRMLS_CC); + spl_ptr_llist_push(intern->llist, elem); } if (*p != '\0') { @@ -1233,36 +1224,38 @@ SPL_METHOD(SplDoublyLinkedList, unserialize) error: PHP_VAR_UNSERIALIZE_DESTROY(var_hash); - zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Error at offset %ld of %d bytes", (long)((char*)p - buf), buf_len); + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Error at offset %pd of %d bytes", (zend_long)((char*)p - buf), buf_len); return; } /* }}} */ -/* {{{ proto void SplDoublyLinkedList::add(mixed $index, mixed $newval) U +/* {{{ proto void SplDoublyLinkedList::add(mixed index, mixed newval) Inserts a new entry before the specified $index consisting of $newval. */ SPL_METHOD(SplDoublyLinkedList, add) { zval *zindex, *value; spl_dllist_object *intern; spl_ptr_llist_element *element; - long index; + zend_long index; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &zindex, &value) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &zindex, &value) == FAILURE) { return; } - intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - index = spl_offset_convert_to_long(zindex TSRMLS_CC); + intern = Z_SPLDLLIST_P(getThis()); + index = spl_offset_convert_to_long(zindex); if (index < 0 || index > intern->llist->count) { - zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0); return; } - Z_ADDREF_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } if (index == intern->llist->count) { /* If index is the last entry+1 then we do a push because we're not inserting before any entry */ - spl_ptr_llist_push(intern->llist, value TSRMLS_CC); + spl_ptr_llist_push(intern->llist, value); } else { /* Create the new element we want to insert */ spl_ptr_llist_element *elem = emalloc(sizeof(spl_ptr_llist_element)); @@ -1270,7 +1263,7 @@ SPL_METHOD(SplDoublyLinkedList, add) /* Get the element we want to insert before */ element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO); - elem->data = value; + ZVAL_COPY_VALUE(&elem->data, value); elem->rc = 1; /* connect to the neighbours */ elem->next = element; @@ -1287,13 +1280,12 @@ SPL_METHOD(SplDoublyLinkedList, add) intern->llist->count++; if (intern->llist->ctor) { - intern->llist->ctor(elem TSRMLS_CC); + intern->llist->ctor(elem); } } } /* }}} */ - -/* iterator handler table */ +/* {{{ iterator handler table */ zend_object_iterator_funcs spl_dllist_it_funcs = { spl_dllist_it_dtor, spl_dllist_it_valid, @@ -1301,34 +1293,33 @@ zend_object_iterator_funcs spl_dllist_it_funcs = { spl_dllist_it_get_current_key, spl_dllist_it_move_forward, spl_dllist_it_rewind -}; +}; /* }}} */ -zend_object_iterator *spl_dllist_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */ +zend_object_iterator *spl_dllist_get_iterator(zend_class_entry *ce, zval *object, int by_ref) /* {{{ */ { - spl_dllist_it *iterator; - spl_dllist_object *dllist_object = (spl_dllist_object*)zend_object_store_get_object(object TSRMLS_CC); + spl_dllist_it *iterator; + spl_dllist_object *dllist_object = Z_SPLDLLIST_P(object); if (by_ref) { - zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0); return NULL; } - Z_ADDREF_P(object); + iterator = emalloc(sizeof(spl_dllist_it)); + + zend_iterator_init((zend_object_iterator*)iterator); - iterator = emalloc(sizeof(spl_dllist_it)); - iterator->intern.it.data = (void*)object; + ZVAL_COPY(&iterator->intern.it.data, object); iterator->intern.it.funcs = &spl_dllist_it_funcs; iterator->intern.ce = ce; - iterator->intern.value = NULL; iterator->traverse_position = dllist_object->traverse_position; iterator->traverse_pointer = dllist_object->traverse_pointer; iterator->flags = dllist_object->flags & SPL_DLLIST_IT_MASK; - iterator->object = dllist_object; + ZVAL_UNDEF(&iterator->intern.value); SPL_LLIST_CHECK_ADDREF(iterator->traverse_pointer); - - return (zend_object_iterator*)iterator; + return &iterator->intern.it; } /* }}} */ @@ -1402,9 +1393,13 @@ PHP_MINIT_FUNCTION(spl_dllist) /* {{{ */ REGISTER_SPL_STD_CLASS_EX(SplDoublyLinkedList, spl_dllist_object_new, spl_funcs_SplDoublyLinkedList); memcpy(&spl_handler_SplDoublyLinkedList, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - spl_handler_SplDoublyLinkedList.clone_obj = spl_dllist_object_clone; + spl_handler_SplDoublyLinkedList.offset = XtOffsetOf(spl_dllist_object, std); + spl_handler_SplDoublyLinkedList.clone_obj = spl_dllist_object_clone; spl_handler_SplDoublyLinkedList.count_elements = spl_dllist_object_count_elements; spl_handler_SplDoublyLinkedList.get_debug_info = spl_dllist_object_get_debug_info; + spl_handler_SplDoublyLinkedList.get_gc = spl_dllist_object_get_gc; + spl_handler_SplDoublyLinkedList.dtor_obj = zend_objects_destroy_object; + spl_handler_SplDoublyLinkedList.free_obj = spl_dllist_object_free_storage; REGISTER_SPL_CLASS_CONST_LONG(SplDoublyLinkedList, "IT_MODE_LIFO", SPL_DLLIST_IT_LIFO); REGISTER_SPL_CLASS_CONST_LONG(SplDoublyLinkedList, "IT_MODE_FIFO", 0); @@ -1427,6 +1422,7 @@ PHP_MINIT_FUNCTION(spl_dllist) /* {{{ */ return SUCCESS; } /* }}} */ + /* * Local variables: * tab-width: 4 diff --git a/ext/spl/spl_dllist.h b/ext/spl/spl_dllist.h index d916618b6a..6aff0bef19 100644 --- a/ext/spl/spl_dllist.h +++ b/ext/spl/spl_dllist.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/spl/spl_engine.c b/ext/spl/spl_engine.c index e4a6354a1b..7df2ff036e 100644 --- a/ext/spl/spl_engine.c +++ b/ext/spl/spl_engine.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -32,32 +32,39 @@ #include "spl_array.h" /* {{{ spl_instantiate */ -PHPAPI void spl_instantiate(zend_class_entry *pce, zval **object, int alloc TSRMLS_DC) +PHPAPI void spl_instantiate(zend_class_entry *pce, zval *object) { - if (alloc) { - ALLOC_ZVAL(*object); - } - object_init_ex(*object, pce); - Z_SET_REFCOUNT_PP(object, 1); - Z_SET_ISREF_PP(object); /* check if this can be hold always */ + object_init_ex(object, pce); } /* }}} */ -PHPAPI long spl_offset_convert_to_long(zval *offset TSRMLS_DC) /* {{{ */ +PHPAPI zend_long spl_offset_convert_to_long(zval *offset) /* {{{ */ { + zend_ulong idx; + +try_again: switch (Z_TYPE_P(offset)) { case IS_STRING: - ZEND_HANDLE_NUMERIC(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, idx); + if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), idx)) { + return idx; + } break; case IS_DOUBLE: - return (long)Z_DVAL_P(offset); - case IS_RESOURCE: - case IS_BOOL: + return (zend_long)Z_DVAL_P(offset); case IS_LONG: return Z_LVAL_P(offset); + case IS_FALSE: + return 0; + case IS_TRUE: + return 1; + case IS_REFERENCE: + offset = Z_REFVAL_P(offset); + goto try_again; + case IS_RESOURCE: + return Z_RES_HANDLE_P(offset); } return -1; -} +} /* }}} */ /* diff --git a/ext/spl/spl_engine.h b/ext/spl/spl_engine.h index 8d9af82623..c5f0927953 100644 --- a/ext/spl/spl_engine.h +++ b/ext/spl/spl_engine.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -25,49 +25,48 @@ #include "php_spl.h" #include "zend_interfaces.h" -PHPAPI void spl_instantiate(zend_class_entry *pce, zval **object, int alloc TSRMLS_DC); +PHPAPI void spl_instantiate(zend_class_entry *pce, zval *object); -PHPAPI long spl_offset_convert_to_long(zval *offset TSRMLS_DC); +PHPAPI zend_long spl_offset_convert_to_long(zval *offset); /* {{{ spl_instantiate_arg_ex1 */ -static inline int spl_instantiate_arg_ex1(zend_class_entry *pce, zval **retval, int alloc, zval *arg1 TSRMLS_DC) +static inline int spl_instantiate_arg_ex1(zend_class_entry *pce, zval *retval, zval *arg1) { - spl_instantiate(pce, retval, alloc TSRMLS_CC); - - zend_call_method(retval, pce, &pce->constructor, pce->constructor->common.function_name, strlen(pce->constructor->common.function_name), NULL, 1, arg1, NULL TSRMLS_CC); + zend_function *func = pce->constructor; + spl_instantiate(pce, retval); + + zend_call_method(retval, pce, &func, ZSTR_VAL(func->common.function_name), ZSTR_LEN(func->common.function_name), NULL, 1, arg1, NULL); return 0; } /* }}} */ /* {{{ spl_instantiate_arg_ex2 */ -static inline int spl_instantiate_arg_ex2(zend_class_entry *pce, zval **retval, int alloc, zval *arg1, zval *arg2 TSRMLS_DC) +static inline int spl_instantiate_arg_ex2(zend_class_entry *pce, zval *retval, zval *arg1, zval *arg2) { - spl_instantiate(pce, retval, alloc TSRMLS_CC); - - zend_call_method(retval, pce, &pce->constructor, pce->constructor->common.function_name, strlen(pce->constructor->common.function_name), NULL, 2, arg1, arg2 TSRMLS_CC); + zend_function *func = pce->constructor; + spl_instantiate(pce, retval); + + zend_call_method(retval, pce, &func, ZSTR_VAL(func->common.function_name), ZSTR_LEN(func->common.function_name), NULL, 2, arg1, arg2); return 0; } /* }}} */ /* {{{ spl_instantiate_arg_n */ -static inline void spl_instantiate_arg_n(zend_class_entry *pce, zval **retval, int argc, zval ***argv TSRMLS_DC) +static inline void spl_instantiate_arg_n(zend_class_entry *pce, zval *retval, int argc, zval *argv) { zend_function *func = pce->constructor; zend_fcall_info fci; zend_fcall_info_cache fcc; - zval *dummy; - zval z_name; - - spl_instantiate(pce, retval, 0 TSRMLS_CC); + zval dummy; - ZVAL_STRING(&z_name, func->common.function_name, 0); + spl_instantiate(pce, retval); fci.size = sizeof(zend_fcall_info); fci.function_table = &pce->function_table; - fci.function_name = &z_name; - fci.object_ptr = *retval; + ZVAL_STR(&fci.function_name, func->common.function_name); + fci.object = Z_OBJ_P(retval); fci.symbol_table = NULL; - fci.retval_ptr_ptr = &dummy; + fci.retval = &dummy; fci.param_count = argc; fci.params = argv; fci.no_separation = 1; @@ -76,11 +75,9 @@ static inline void spl_instantiate_arg_n(zend_class_entry *pce, zval **retval, i fcc.function_handler = func; fcc.calling_scope = EG(scope); fcc.called_scope = pce; - fcc.object_ptr = *retval; - - zend_call_function(&fci, &fcc TSRMLS_CC); + fcc.object = Z_OBJ_P(retval); - zval_ptr_dtor(&dummy); + zend_call_function(&fci, &fcc); } /* }}} */ diff --git a/ext/spl/spl_exceptions.c b/ext/spl/spl_exceptions.c index bb9627729b..a5f15a54a2 100644 --- a/ext/spl/spl_exceptions.c +++ b/ext/spl/spl_exceptions.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -47,7 +47,7 @@ PHPAPI zend_class_entry *spl_ce_RangeException; PHPAPI zend_class_entry *spl_ce_UnderflowException; PHPAPI zend_class_entry *spl_ce_UnexpectedValueException; -#define spl_ce_Exception zend_exception_get_default(TSRMLS_C) +#define spl_ce_Exception zend_ce_exception /* {{{ PHP_MINIT_FUNCTION(spl_exceptions) */ PHP_MINIT_FUNCTION(spl_exceptions) diff --git a/ext/spl/spl_exceptions.h b/ext/spl/spl_exceptions.h index f64f6c54d0..3f0da34196 100644 --- a/ext/spl/spl_exceptions.h +++ b/ext/spl/spl_exceptions.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index 8ce2ac5de9..9bbda05829 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -43,15 +43,13 @@ ZEND_GET_MODULE(spl_fixedarray) #endif typedef struct _spl_fixedarray { /* {{{ */ - long size; - zval **elements; + zend_long size; + zval *elements; } spl_fixedarray; /* }}} */ typedef struct _spl_fixedarray_object { /* {{{ */ - zend_object std; - spl_fixedarray *array; - zval *retval; + spl_fixedarray *array; zend_function *fptr_offset_get; zend_function *fptr_offset_set; zend_function *fptr_offset_has; @@ -60,12 +58,12 @@ typedef struct _spl_fixedarray_object { /* {{{ */ int current; int flags; zend_class_entry *ce_get_iterator; + zend_object std; } spl_fixedarray_object; /* }}} */ typedef struct _spl_fixedarray_it { /* {{{ */ zend_user_iterator intern; - spl_fixedarray_object *object; } spl_fixedarray_it; /* }}} */ @@ -75,11 +73,18 @@ typedef struct _spl_fixedarray_it { /* {{{ */ #define SPL_FIXEDARRAY_OVERLOADED_CURRENT 0x0008 #define SPL_FIXEDARRAY_OVERLOADED_NEXT 0x0010 -static void spl_fixedarray_init(spl_fixedarray *array, long size TSRMLS_DC) /* {{{ */ +static inline spl_fixedarray_object *spl_fixed_array_from_obj(zend_object *obj) /* {{{ */ { + return (spl_fixedarray_object*)((char*)(obj) - XtOffsetOf(spl_fixedarray_object, std)); +} +/* }}} */ + +#define Z_SPLFIXEDARRAY_P(zv) spl_fixed_array_from_obj(Z_OBJ_P((zv))) + +static void spl_fixedarray_init(spl_fixedarray *array, zend_long size) /* {{{ */ { if (size > 0) { array->size = 0; /* reset size in case ecalloc() fails */ - array->elements = ecalloc(size, sizeof(zval *)); + array->elements = ecalloc(size, sizeof(zval)); array->size = size; } else { array->elements = NULL; @@ -88,7 +93,7 @@ static void spl_fixedarray_init(spl_fixedarray *array, long size TSRMLS_DC) /* { } /* }}} */ -static void spl_fixedarray_resize(spl_fixedarray *array, long size TSRMLS_DC) /* {{{ */ +static void spl_fixedarray_resize(spl_fixedarray *array, zend_long size) /* {{{ */ { if (size == array->size) { /* nothing to do */ @@ -97,18 +102,16 @@ static void spl_fixedarray_resize(spl_fixedarray *array, long size TSRMLS_DC) /* /* first initialization */ if (array->size == 0) { - spl_fixedarray_init(array, size TSRMLS_CC); + spl_fixedarray_init(array, size); return; } /* clearing the array */ if (size == 0) { - long i; + zend_long i; for (i = 0; i < array->size; i++) { - if (array->elements[i]) { - zval_ptr_dtor(&(array->elements[i])); - } + zval_ptr_dtor(&(array->elements[i])); } if (array->elements) { @@ -116,45 +119,38 @@ static void spl_fixedarray_resize(spl_fixedarray *array, long size TSRMLS_DC) /* array->elements = NULL; } } else if (size > array->size) { - array->elements = safe_erealloc(array->elements, size, sizeof(zval *), 0); - memset(array->elements + array->size, '\0', sizeof(zval *) * (size - array->size)); + array->elements = safe_erealloc(array->elements, size, sizeof(zval), 0); + memset(array->elements + array->size, '\0', sizeof(zval) * (size - array->size)); } else { /* size < array->size */ - long i; + zend_long i; for (i = size; i < array->size; i++) { - if (array->elements[i]) { - zval_ptr_dtor(&(array->elements[i])); - } + zval_ptr_dtor(&(array->elements[i])); } - array->elements = erealloc(array->elements, sizeof(zval *) * size); + array->elements = erealloc(array->elements, sizeof(zval) * size); } array->size = size; } /* }}} */ -static void spl_fixedarray_copy(spl_fixedarray *to, spl_fixedarray *from TSRMLS_DC) /* {{{ */ +static void spl_fixedarray_copy(spl_fixedarray *to, spl_fixedarray *from) /* {{{ */ { int i; for (i = 0; i < from->size; i++) { - if (from->elements[i]) { - Z_ADDREF_P(from->elements[i]); - to->elements[i] = from->elements[i]; - } else { - to->elements[i] = NULL; - } + ZVAL_COPY(&to->elements[i], &from->elements[i]); } } /* }}} */ -static HashTable* spl_fixedarray_object_get_gc(zval *obj, zval ***table, int *n TSRMLS_DC) /* {{{{ */ +static HashTable* spl_fixedarray_object_get_gc(zval *obj, zval **table, int *n) /* {{{{ */ { - spl_fixedarray_object *intern = (spl_fixedarray_object*)zend_object_store_get_object(obj TSRMLS_CC); - HashTable *ht = zend_std_get_properties(obj TSRMLS_CC); + spl_fixedarray_object *intern = Z_SPLFIXEDARRAY_P(obj); + HashTable *ht = zend_std_get_properties(obj); if (intern->array) { *table = intern->array->elements; - *n = intern->array->size; + *n = (int)intern->array->size; } else { *table = NULL; *n = 0; @@ -164,22 +160,23 @@ static HashTable* spl_fixedarray_object_get_gc(zval *obj, zval ***table, int *n } /* }}}} */ -static HashTable* spl_fixedarray_object_get_properties(zval *obj TSRMLS_DC) /* {{{{ */ +static HashTable* spl_fixedarray_object_get_properties(zval *obj) /* {{{{ */ { - spl_fixedarray_object *intern = (spl_fixedarray_object*)zend_object_store_get_object(obj TSRMLS_CC); - HashTable *ht = zend_std_get_properties(obj TSRMLS_CC); - int i = 0; + spl_fixedarray_object *intern = Z_SPLFIXEDARRAY_P(obj); + HashTable *ht = zend_std_get_properties(obj); + zend_long i = 0; if (intern->array) { - int j = zend_hash_num_elements(ht); + zend_long j = zend_hash_num_elements(ht); for (i = 0; i < intern->array->size; i++) { - if (intern->array->elements[i]) { - zend_hash_index_update(ht, i, (void *)&intern->array->elements[i], sizeof(zval *), NULL); - Z_ADDREF_P(intern->array->elements[i]); + if (!Z_ISUNDEF(intern->array->elements[i])) { + zend_hash_index_update(ht, i, &intern->array->elements[i]); + if (Z_REFCOUNTED(intern->array->elements[i])){ + Z_ADDREF(intern->array->elements[i]); + } } else { - zend_hash_index_update(ht, i, (void *)&EG(uninitialized_zval_ptr), sizeof(zval *), NULL); - Z_ADDREF_P(EG(uninitialized_zval_ptr)); + zend_hash_index_update(ht, i, &EG(uninitialized_zval)); } } if (j > intern->array->size) { @@ -193,16 +190,14 @@ static HashTable* spl_fixedarray_object_get_properties(zval *obj TSRMLS_DC) /* { } /* }}}} */ -static void spl_fixedarray_object_free_storage(void *object TSRMLS_DC) /* {{{ */ +static void spl_fixedarray_object_free_storage(zend_object *object) /* {{{ */ { - spl_fixedarray_object *intern = (spl_fixedarray_object *)object; - long i; + spl_fixedarray_object *intern = spl_fixed_array_from_obj(object); + zend_long i; if (intern->array) { for (i = 0; i < intern->array->size; i++) { - if (intern->array->elements[i]) { - zval_ptr_dtor(&(intern->array->elements[i])); - } + zval_ptr_dtor(&(intern->array->elements[i])); } if (intern->array->size > 0 && intern->array->elements) { @@ -211,48 +206,42 @@ static void spl_fixedarray_object_free_storage(void *object TSRMLS_DC) /* {{{ */ efree(intern->array); } - zend_object_std_dtor(&intern->std TSRMLS_CC); - zval_ptr_dtor(&intern->retval); - - efree(object); + zend_object_std_dtor(&intern->std); } /* }}} */ -zend_object_iterator *spl_fixedarray_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC); +zend_object_iterator *spl_fixedarray_get_iterator(zend_class_entry *ce, zval *object, int by_ref); -static zend_object_value spl_fixedarray_object_new_ex(zend_class_entry *class_type, spl_fixedarray_object **obj, zval *orig, int clone_orig TSRMLS_DC) /* {{{ */ +static zend_object *spl_fixedarray_object_new_ex(zend_class_entry *class_type, zval *orig, int clone_orig) /* {{{ */ { - zend_object_value retval; spl_fixedarray_object *intern; zend_class_entry *parent = class_type; int inherited = 0; - intern = ecalloc(1, sizeof(spl_fixedarray_object)); - *obj = intern; - ALLOC_INIT_ZVAL(intern->retval); + intern = ecalloc(1, sizeof(spl_fixedarray_object) + zend_object_properties_size(parent)); - zend_object_std_init(&intern->std, class_type TSRMLS_CC); + zend_object_std_init(&intern->std, class_type); object_properties_init(&intern->std, class_type); intern->current = 0; intern->flags = 0; if (orig && clone_orig) { - spl_fixedarray_object *other = (spl_fixedarray_object*)zend_object_store_get_object(orig TSRMLS_CC); + spl_fixedarray_object *other = Z_SPLFIXEDARRAY_P(orig); intern->ce_get_iterator = other->ce_get_iterator; if (!other->array) { /* leave a empty object, will be dtor later by CLONE handler */ - zend_throw_exception(spl_ce_RuntimeException, "The instance wasn't initialized properly", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_RuntimeException, "The instance wasn't initialized properly", 0); } else { intern->array = emalloc(sizeof(spl_fixedarray)); - spl_fixedarray_init(intern->array, other->array->size TSRMLS_CC); - spl_fixedarray_copy(intern->array, other->array TSRMLS_CC); + spl_fixedarray_init(intern->array, other->array->size); + spl_fixedarray_copy(intern->array, other->array); } } while (parent) { if (parent == spl_ce_SplFixedArray) { - retval.handlers = &spl_handler_SplFixedArray; + intern->std.handlers = &spl_handler_SplFixedArray; class_type->get_iterator = spl_fixedarray_get_iterator; break; } @@ -261,107 +250,101 @@ static zend_object_value spl_fixedarray_object_new_ex(zend_class_entry *class_ty inherited = 1; } - retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, spl_fixedarray_object_free_storage, NULL TSRMLS_CC); - if (!parent) { /* this must never happen */ - php_error_docref(NULL TSRMLS_CC, E_COMPILE_ERROR, "Internal compiler error, Class is not child of SplFixedArray"); + php_error_docref(NULL, E_COMPILE_ERROR, "Internal compiler error, Class is not child of SplFixedArray"); } + if (!class_type->iterator_funcs.zf_current) { - zend_hash_find(&class_type->function_table, "rewind", sizeof("rewind"), (void **) &class_type->iterator_funcs.zf_rewind); - zend_hash_find(&class_type->function_table, "valid", sizeof("valid"), (void **) &class_type->iterator_funcs.zf_valid); - zend_hash_find(&class_type->function_table, "key", sizeof("key"), (void **) &class_type->iterator_funcs.zf_key); - zend_hash_find(&class_type->function_table, "current", sizeof("current"), (void **) &class_type->iterator_funcs.zf_current); - zend_hash_find(&class_type->function_table, "next", sizeof("next"), (void **) &class_type->iterator_funcs.zf_next); + class_type->iterator_funcs.zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1); + class_type->iterator_funcs.zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1); + class_type->iterator_funcs.zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1); + class_type->iterator_funcs.zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1); + class_type->iterator_funcs.zf_next = zend_hash_str_find_ptr(&class_type->function_table, "next", sizeof("next") - 1); } if (inherited) { - if (class_type->iterator_funcs.zf_rewind->common.scope != parent) { + if (class_type->iterator_funcs.zf_rewind->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_REWIND; } - if (class_type->iterator_funcs.zf_valid->common.scope != parent) { + if (class_type->iterator_funcs.zf_valid->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_VALID; } - if (class_type->iterator_funcs.zf_key->common.scope != parent) { + if (class_type->iterator_funcs.zf_key->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_KEY; } - if (class_type->iterator_funcs.zf_current->common.scope != parent) { + if (class_type->iterator_funcs.zf_current->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_CURRENT; } - if (class_type->iterator_funcs.zf_next->common.scope != parent) { + if (class_type->iterator_funcs.zf_next->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_NEXT; } - zend_hash_find(&class_type->function_table, "offsetget", sizeof("offsetget"), (void **) &intern->fptr_offset_get); + intern->fptr_offset_get = zend_hash_str_find_ptr(&class_type->function_table, "offsetget", sizeof("offsetget") - 1); if (intern->fptr_offset_get->common.scope == parent) { intern->fptr_offset_get = NULL; } - zend_hash_find(&class_type->function_table, "offsetset", sizeof("offsetset"), (void **) &intern->fptr_offset_set); + intern->fptr_offset_set = zend_hash_str_find_ptr(&class_type->function_table, "offsetset", sizeof("offsetset") - 1); if (intern->fptr_offset_set->common.scope == parent) { intern->fptr_offset_set = NULL; } - zend_hash_find(&class_type->function_table, "offsetexists", sizeof("offsetexists"), (void **) &intern->fptr_offset_has); + intern->fptr_offset_has = zend_hash_str_find_ptr(&class_type->function_table, "offsetexists", sizeof("offsetexists") - 1); if (intern->fptr_offset_has->common.scope == parent) { intern->fptr_offset_has = NULL; } - zend_hash_find(&class_type->function_table, "offsetunset", sizeof("offsetunset"), (void **) &intern->fptr_offset_del); + intern->fptr_offset_del = zend_hash_str_find_ptr(&class_type->function_table, "offsetunset", sizeof("offsetunset") - 1); if (intern->fptr_offset_del->common.scope == parent) { intern->fptr_offset_del = NULL; } - zend_hash_find(&class_type->function_table, "count", sizeof("count"), (void **) &intern->fptr_count); + intern->fptr_count = zend_hash_str_find_ptr(&class_type->function_table, "count", sizeof("count") - 1); if (intern->fptr_count->common.scope == parent) { intern->fptr_count = NULL; } } - return retval; + return &intern->std; } /* }}} */ -static zend_object_value spl_fixedarray_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */ +static zend_object *spl_fixedarray_new(zend_class_entry *class_type) /* {{{ */ { - spl_fixedarray_object *tmp; - return spl_fixedarray_object_new_ex(class_type, &tmp, NULL, 0 TSRMLS_CC); + return spl_fixedarray_object_new_ex(class_type, NULL, 0); } /* }}} */ -static zend_object_value spl_fixedarray_object_clone(zval *zobject TSRMLS_DC) /* {{{ */ +static zend_object *spl_fixedarray_object_clone(zval *zobject) /* {{{ */ { - zend_object_value new_obj_val; - zend_object *old_object; - zend_object *new_object; - zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); - spl_fixedarray_object *intern; + zend_object *old_object; + zend_object *new_object; - old_object = zend_objects_get_address(zobject TSRMLS_CC); - new_obj_val = spl_fixedarray_object_new_ex(old_object->ce, &intern, zobject, 1 TSRMLS_CC); - new_object = &intern->std; + old_object = Z_OBJ_P(zobject); + new_object = spl_fixedarray_object_new_ex(old_object->ce, zobject, 1); - zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC); + zend_objects_clone_members(new_object, old_object); - return new_obj_val; + return new_object; } /* }}} */ -static inline zval **spl_fixedarray_object_read_dimension_helper(spl_fixedarray_object *intern, zval *offset TSRMLS_DC) /* {{{ */ +static inline zval *spl_fixedarray_object_read_dimension_helper(spl_fixedarray_object *intern, zval *offset) /* {{{ */ { - long index; + zend_long index; - /* we have to return NULL on error here to avoid memleak because of + /* we have to return NULL on error here to avoid memleak because of * ZE duplicating uninitialized_zval_ptr */ if (!offset) { - zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0); return NULL; } if (Z_TYPE_P(offset) != IS_LONG) { - index = spl_offset_convert_to_long(offset TSRMLS_CC); + index = spl_offset_convert_to_long(offset); } else { index = Z_LVAL_P(offset); } - + if (index < 0 || intern->array == NULL || index >= intern->array->size) { - zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0); return NULL; - } else if(!intern->array->elements[index]) { + } else if (Z_ISUNDEF(intern->array->elements[index])) { return NULL; } else { return &intern->array->elements[index]; @@ -369,149 +352,142 @@ static inline zval **spl_fixedarray_object_read_dimension_helper(spl_fixedarray_ } /* }}} */ -static zval *spl_fixedarray_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) /* {{{ */ +static zval *spl_fixedarray_object_read_dimension(zval *object, zval *offset, int type, zval *rv) /* {{{ */ { spl_fixedarray_object *intern; - zval **retval; - intern = (spl_fixedarray_object *)zend_object_store_get_object(object TSRMLS_CC); + intern = Z_SPLFIXEDARRAY_P(object); if (intern->fptr_offset_get) { - zval *rv; + zval tmp; if (!offset) { - ALLOC_INIT_ZVAL(offset); + ZVAL_UNDEF(&tmp); + offset = &tmp; } else { SEPARATE_ARG_IF_REF(offset); } - zend_call_method_with_1_params(&object, intern->std.ce, &intern->fptr_offset_get, "offsetGet", &rv, offset); - zval_ptr_dtor(&offset); - if (rv) { - zval_ptr_dtor(&intern->retval); - MAKE_STD_ZVAL(intern->retval); - ZVAL_ZVAL(intern->retval, rv, 1, 1); - return intern->retval; + zend_call_method_with_1_params(object, intern->std.ce, &intern->fptr_offset_get, "offsetGet", rv, offset); + zval_ptr_dtor(offset); + if (!Z_ISUNDEF_P(rv)) { + return rv; } - return EG(uninitialized_zval_ptr); + return &EG(uninitialized_zval); } - retval = spl_fixedarray_object_read_dimension_helper(intern, offset TSRMLS_CC); - if (retval) { - return *retval; - } - return NULL; + return spl_fixedarray_object_read_dimension_helper(intern, offset); } /* }}} */ -static inline void spl_fixedarray_object_write_dimension_helper(spl_fixedarray_object *intern, zval *offset, zval *value TSRMLS_DC) /* {{{ */ +static inline void spl_fixedarray_object_write_dimension_helper(spl_fixedarray_object *intern, zval *offset, zval *value) /* {{{ */ { - long index; + zend_long index; if (!offset) { /* '$array[] = value' syntax is not supported */ - zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0); return; } if (Z_TYPE_P(offset) != IS_LONG) { - index = spl_offset_convert_to_long(offset TSRMLS_CC); + index = spl_offset_convert_to_long(offset); } else { index = Z_LVAL_P(offset); } if (index < 0 || intern->array == NULL || index >= intern->array->size) { - zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0); return; } else { - if (intern->array->elements[index]) { + if (!Z_ISUNDEF(intern->array->elements[index])) { zval_ptr_dtor(&(intern->array->elements[index])); } - SEPARATE_ARG_IF_REF(value); - intern->array->elements[index] = value; + ZVAL_DEREF(value); + ZVAL_COPY(&intern->array->elements[index], value); } } /* }}} */ -static void spl_fixedarray_object_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC) /* {{{ */ +static void spl_fixedarray_object_write_dimension(zval *object, zval *offset, zval *value) /* {{{ */ { spl_fixedarray_object *intern; - intern = (spl_fixedarray_object *)zend_object_store_get_object(object TSRMLS_CC); + intern = Z_SPLFIXEDARRAY_P(object); if (intern->fptr_offset_set) { + zval tmp; if (!offset) { - ALLOC_INIT_ZVAL(offset); + ZVAL_NULL(&tmp); + offset = &tmp; } else { SEPARATE_ARG_IF_REF(offset); } SEPARATE_ARG_IF_REF(value); - zend_call_method_with_2_params(&object, intern->std.ce, &intern->fptr_offset_set, "offsetSet", NULL, offset, value); - zval_ptr_dtor(&value); - zval_ptr_dtor(&offset); + zend_call_method_with_2_params(object, intern->std.ce, &intern->fptr_offset_set, "offsetSet", NULL, offset, value); + zval_ptr_dtor(value); + zval_ptr_dtor(offset); return; } - spl_fixedarray_object_write_dimension_helper(intern, offset, value TSRMLS_CC); + spl_fixedarray_object_write_dimension_helper(intern, offset, value); } /* }}} */ -static inline void spl_fixedarray_object_unset_dimension_helper(spl_fixedarray_object *intern, zval *offset TSRMLS_DC) /* {{{ */ +static inline void spl_fixedarray_object_unset_dimension_helper(spl_fixedarray_object *intern, zval *offset) /* {{{ */ { - long index; - + zend_long index; + if (Z_TYPE_P(offset) != IS_LONG) { - index = spl_offset_convert_to_long(offset TSRMLS_CC); + index = spl_offset_convert_to_long(offset); } else { index = Z_LVAL_P(offset); } - + if (index < 0 || intern->array == NULL || index >= intern->array->size) { - zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0); return; } else { - if (intern->array->elements[index]) { - zval_ptr_dtor(&(intern->array->elements[index])); - } - intern->array->elements[index] = NULL; + zval_ptr_dtor(&(intern->array->elements[index])); + ZVAL_UNDEF(&intern->array->elements[index]); } } /* }}} */ -static void spl_fixedarray_object_unset_dimension(zval *object, zval *offset TSRMLS_DC) /* {{{ */ +static void spl_fixedarray_object_unset_dimension(zval *object, zval *offset) /* {{{ */ { spl_fixedarray_object *intern; - intern = (spl_fixedarray_object *)zend_object_store_get_object(object TSRMLS_CC); + intern = Z_SPLFIXEDARRAY_P(object); if (intern->fptr_offset_del) { SEPARATE_ARG_IF_REF(offset); - zend_call_method_with_1_params(&object, intern->std.ce, &intern->fptr_offset_del, "offsetUnset", NULL, offset); - zval_ptr_dtor(&offset); + zend_call_method_with_1_params(object, intern->std.ce, &intern->fptr_offset_del, "offsetUnset", NULL, offset); + zval_ptr_dtor(offset); return; } - spl_fixedarray_object_unset_dimension_helper(intern, offset TSRMLS_CC); + spl_fixedarray_object_unset_dimension_helper(intern, offset); } /* }}} */ -static inline int spl_fixedarray_object_has_dimension_helper(spl_fixedarray_object *intern, zval *offset, int check_empty TSRMLS_DC) /* {{{ */ +static inline int spl_fixedarray_object_has_dimension_helper(spl_fixedarray_object *intern, zval *offset, int check_empty) /* {{{ */ { - long index; + zend_long index; int retval; - + if (Z_TYPE_P(offset) != IS_LONG) { - index = spl_offset_convert_to_long(offset TSRMLS_CC); + index = spl_offset_convert_to_long(offset); } else { index = Z_LVAL_P(offset); } - + if (index < 0 || intern->array == NULL || index >= intern->array->size) { retval = 0; } else { - if (!intern->array->elements[index]) { + if (Z_ISUNDEF(intern->array->elements[index])) { retval = 0; } else if (check_empty) { - if (zend_is_true(intern->array->elements[index])) { + if (zend_is_true(&intern->array->elements[index])) { retval = 1; } else { retval = 0; @@ -525,44 +501,40 @@ static inline int spl_fixedarray_object_has_dimension_helper(spl_fixedarray_obje } /* }}} */ -static int spl_fixedarray_object_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC) /* {{{ */ +static int spl_fixedarray_object_has_dimension(zval *object, zval *offset, int check_empty) /* {{{ */ { spl_fixedarray_object *intern; - intern = (spl_fixedarray_object *)zend_object_store_get_object(object TSRMLS_CC); + intern = Z_SPLFIXEDARRAY_P(object); if (intern->fptr_offset_get) { - zval *rv; + zval rv; SEPARATE_ARG_IF_REF(offset); - zend_call_method_with_1_params(&object, intern->std.ce, &intern->fptr_offset_has, "offsetExists", &rv, offset); - zval_ptr_dtor(&offset); - if (rv) { - zval_ptr_dtor(&intern->retval); - MAKE_STD_ZVAL(intern->retval); - ZVAL_ZVAL(intern->retval, rv, 1, 1); - return zend_is_true(intern->retval); + zend_call_method_with_1_params(object, intern->std.ce, &intern->fptr_offset_has, "offsetExists", &rv, offset); + zval_ptr_dtor(offset); + if (!Z_ISUNDEF(rv)) { + zend_bool result = zend_is_true(&rv); + zval_ptr_dtor(&rv); + return result; } return 0; } - return spl_fixedarray_object_has_dimension_helper(intern, offset, check_empty TSRMLS_CC); + return spl_fixedarray_object_has_dimension_helper(intern, offset, check_empty); } /* }}} */ -static int spl_fixedarray_object_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */ +static int spl_fixedarray_object_count_elements(zval *object, zend_long *count) /* {{{ */ { spl_fixedarray_object *intern; - - intern = (spl_fixedarray_object *)zend_object_store_get_object(object TSRMLS_CC); + + intern = Z_SPLFIXEDARRAY_P(object); if (intern->fptr_count) { - zval *rv; - zend_call_method_with_0_params(&object, intern->std.ce, &intern->fptr_count, "count", &rv); - if (rv) { - zval_ptr_dtor(&intern->retval); - MAKE_STD_ZVAL(intern->retval); - ZVAL_ZVAL(intern->retval, rv, 1, 1); - convert_to_long(intern->retval); - *count = (long) Z_LVAL_P(intern->retval); + zval rv; + zend_call_method_with_0_params(object, intern->std.ce, &intern->fptr_count, "count", &rv); + if (!Z_ISUNDEF(rv)) { + *count = zval_get_long(&rv); + zval_ptr_dtor(&rv); return SUCCESS; } } else if (intern->array) { @@ -581,18 +553,18 @@ SPL_METHOD(SplFixedArray, __construct) { zval *object = getThis(); spl_fixedarray_object *intern; - long size = 0; + zend_long size = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &size) == FAILURE) { + if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "|l", &size) == FAILURE) { return; } if (size < 0) { - zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "array size cannot be less than zero"); + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "array size cannot be less than zero"); return; } - intern = (spl_fixedarray_object *)zend_object_store_get_object(object TSRMLS_CC); + intern = Z_SPLFIXEDARRAY_P(object); if (intern->array) { /* called __construct() twice, bail out */ @@ -600,7 +572,7 @@ SPL_METHOD(SplFixedArray, __construct) } intern->array = emalloc(sizeof(spl_fixedarray)); - spl_fixedarray_init(intern->array, size TSRMLS_CC); + spl_fixedarray_init(intern->array, size); } /* }}} */ @@ -608,10 +580,9 @@ SPL_METHOD(SplFixedArray, __construct) */ SPL_METHOD(SplFixedArray, __wakeup) { - spl_fixedarray_object *intern = (spl_fixedarray_object *) zend_object_store_get_object(getThis() TSRMLS_CC); - HashPosition ptr; - HashTable *intern_ht = zend_std_get_properties(getThis() TSRMLS_CC); - zval **data; + spl_fixedarray_object *intern = Z_SPLFIXEDARRAY_P(getThis()); + HashTable *intern_ht = zend_std_get_properties(getThis()); + zval *data; if (zend_parse_parameters_none() == FAILURE) { return; @@ -622,12 +593,15 @@ SPL_METHOD(SplFixedArray, __wakeup) int size = zend_hash_num_elements(intern_ht); intern->array = emalloc(sizeof(spl_fixedarray)); - spl_fixedarray_init(intern->array, size TSRMLS_CC); + spl_fixedarray_init(intern->array, size); - for (zend_hash_internal_pointer_reset_ex(intern_ht, &ptr); zend_hash_get_current_data_ex(intern_ht, (void **) &data, &ptr) == SUCCESS; zend_hash_move_forward_ex(intern_ht, &ptr)) { - Z_ADDREF_PP(data); - intern->array->elements[index++] = *data; - } + ZEND_HASH_FOREACH_VAL(intern_ht, data) { + if (Z_REFCOUNTED_P(data)) { + Z_ADDREF_P(data); + } + ZVAL_COPY_VALUE(&intern->array->elements[index], data); + index++; + } ZEND_HASH_FOREACH_END(); /* Remove the unserialised properties, since we now have the elements * within the spl_fixedarray_object structure. */ @@ -647,7 +621,7 @@ SPL_METHOD(SplFixedArray, count) return; } - intern = (spl_fixedarray_object *)zend_object_store_get_object(object TSRMLS_CC); + intern = Z_SPLFIXEDARRAY_P(object); if (intern->array) { RETURN_LONG(intern->array->size); } @@ -665,18 +639,19 @@ SPL_METHOD(SplFixedArray, toArray) return; } - intern = (spl_fixedarray_object *)zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_SPLFIXEDARRAY_P(getThis()); array_init(return_value); if (intern->array) { int i = 0; for (; i < intern->array->size; i++) { - if (intern->array->elements[i]) { - zend_hash_index_update(Z_ARRVAL_P(return_value), i, (void *)&intern->array->elements[i], sizeof(zval *), NULL); - Z_ADDREF_P(intern->array->elements[i]); + if (!Z_ISUNDEF(intern->array->elements[i])) { + zend_hash_index_update(Z_ARRVAL_P(return_value), i, &intern->array->elements[i]); + if (Z_REFCOUNTED(intern->array->elements[i])) { + Z_ADDREF(intern->array->elements[i]); + } } else { - zend_hash_index_update(Z_ARRVAL_P(return_value), i, (void *)&EG(uninitialized_zval_ptr), sizeof(zval *), NULL); - Z_ADDREF_P(EG(uninitialized_zval_ptr)); + zend_hash_index_update(Z_ARRVAL_P(return_value), i, &EG(uninitialized_zval)); } } } @@ -693,79 +668,62 @@ SPL_METHOD(SplFixedArray, fromArray) int num; zend_bool save_indexes = 1; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &data, &save_indexes) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|b", &data, &save_indexes) == FAILURE) { return; } - array = ecalloc(1, sizeof(*array)); + array = ecalloc(1, sizeof(spl_fixedarray)); num = zend_hash_num_elements(Z_ARRVAL_P(data)); - + if (num > 0 && save_indexes) { - zval **element, *value; - char *str_index; - ulong num_index, max_index = 0; - long tmp; - - for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(data)); - zend_hash_get_current_data(Z_ARRVAL_P(data), (void **) &element) == SUCCESS; - zend_hash_move_forward(Z_ARRVAL_P(data)) - ) { - if (zend_hash_get_current_key(Z_ARRVAL_P(data), &str_index, &num_index, 0) != HASH_KEY_IS_LONG || (long)num_index < 0) { + zval *element; + zend_string *str_index; + zend_ulong num_index, max_index = 0; + zend_long tmp; + + ZEND_HASH_FOREACH_KEY(Z_ARRVAL_P(data), num_index, str_index) { + if (str_index != NULL || (zend_long)num_index < 0) { efree(array); - zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "array must contain only positive integer keys"); + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "array must contain only positive integer keys"); return; } if (num_index > max_index) { max_index = num_index; } - } + } ZEND_HASH_FOREACH_END(); tmp = max_index + 1; if (tmp <= 0) { efree(array); - zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "integer overflow detected"); + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "integer overflow detected"); return; } - spl_fixedarray_init(array, tmp TSRMLS_CC); - - for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(data)); - zend_hash_get_current_data(Z_ARRVAL_P(data), (void **) &element) == SUCCESS; - zend_hash_move_forward(Z_ARRVAL_P(data)) - ) { - - zend_hash_get_current_key(Z_ARRVAL_P(data), &str_index, &num_index, 0); - value = *element; - - SEPARATE_ARG_IF_REF(value); - array->elements[num_index] = value; - } + spl_fixedarray_init(array, tmp); + + ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(data), num_index, str_index, element) { + ZVAL_DEREF(element); + ZVAL_COPY(&array->elements[num_index], element); + } ZEND_HASH_FOREACH_END(); } else if (num > 0 && !save_indexes) { - zval **element, *value; - long i = 0; - - spl_fixedarray_init(array, num TSRMLS_CC); - - for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(data)); - zend_hash_get_current_data(Z_ARRVAL_P(data), (void **) &element) == SUCCESS; - zend_hash_move_forward(Z_ARRVAL_P(data)) - ) { - - value = *element; - - SEPARATE_ARG_IF_REF(value); - array->elements[i] = value; + zval *element; + zend_long i = 0; + + spl_fixedarray_init(array, num); + + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(data), element) { + ZVAL_DEREF(element); + ZVAL_COPY(&array->elements[i], element); i++; - } + } ZEND_HASH_FOREACH_END(); } else { - spl_fixedarray_init(array, 0 TSRMLS_CC); + spl_fixedarray_init(array, 0); } object_init_ex(return_value, spl_ce_SplFixedArray); - Z_TYPE_P(return_value) = IS_OBJECT; - intern = (spl_fixedarray_object *)zend_object_store_get_object(return_value TSRMLS_CC); + intern = Z_SPLFIXEDARRAY_P(return_value); intern->array = array; } /* }}} */ @@ -781,7 +739,7 @@ SPL_METHOD(SplFixedArray, getSize) return; } - intern = (spl_fixedarray_object *)zend_object_store_get_object(object TSRMLS_CC); + intern = Z_SPLFIXEDARRAY_P(object); if (intern->array) { RETURN_LONG(intern->array->size); } @@ -795,129 +753,127 @@ SPL_METHOD(SplFixedArray, setSize) { zval *object = getThis(); spl_fixedarray_object *intern; - long size; + zend_long size; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &size) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &size) == FAILURE) { return; } if (size < 0) { - zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "array size cannot be less than zero"); + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "array size cannot be less than zero"); return; } - intern = (spl_fixedarray_object *)zend_object_store_get_object(object TSRMLS_CC); + intern = Z_SPLFIXEDARRAY_P(object); if (!intern->array) { intern->array = ecalloc(1, sizeof(spl_fixedarray)); } - spl_fixedarray_resize(intern->array, size TSRMLS_CC); + spl_fixedarray_resize(intern->array, size); RETURN_TRUE; } /* }}} */ -/* {{{ proto bool SplFixedArray::offsetExists(mixed $index) U +/* {{{ proto bool SplFixedArray::offsetExists(mixed $index) Returns whether the requested $index exists. */ SPL_METHOD(SplFixedArray, offsetExists) { zval *zindex; spl_fixedarray_object *intern; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zindex) == FAILURE) { return; } - intern = (spl_fixedarray_object *)zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_SPLFIXEDARRAY_P(getThis()); - RETURN_BOOL(spl_fixedarray_object_has_dimension_helper(intern, zindex, 0 TSRMLS_CC)); + RETURN_BOOL(spl_fixedarray_object_has_dimension_helper(intern, zindex, 0)); } /* }}} */ -/* {{{ proto mixed SplFixedArray::offsetGet(mixed $index) U +/* {{{ proto mixed SplFixedArray::offsetGet(mixed $index) Returns the value at the specified $index. */ SPL_METHOD(SplFixedArray, offsetGet) { - zval *zindex, **value_pp; + zval *zindex, *value; spl_fixedarray_object *intern; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zindex) == FAILURE) { return; } - intern = (spl_fixedarray_object *)zend_object_store_get_object(getThis() TSRMLS_CC); - value_pp = spl_fixedarray_object_read_dimension_helper(intern, zindex TSRMLS_CC); + intern = Z_SPLFIXEDARRAY_P(getThis()); + value = spl_fixedarray_object_read_dimension_helper(intern, zindex); - if (value_pp) { - RETURN_ZVAL(*value_pp, 1, 0); + if (value) { + ZVAL_DEREF(value); + ZVAL_COPY(return_value, value); + } else { + RETURN_NULL(); } - RETURN_NULL(); } /* }}} */ -/* {{{ proto void SplFixedArray::offsetSet(mixed $index, mixed $newval) U +/* {{{ proto void SplFixedArray::offsetSet(mixed $index, mixed $newval) Sets the value at the specified $index to $newval. */ SPL_METHOD(SplFixedArray, offsetSet) { zval *zindex, *value; spl_fixedarray_object *intern; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &zindex, &value) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &zindex, &value) == FAILURE) { return; } - intern = (spl_fixedarray_object *)zend_object_store_get_object(getThis() TSRMLS_CC); - spl_fixedarray_object_write_dimension_helper(intern, zindex, value TSRMLS_CC); + intern = Z_SPLFIXEDARRAY_P(getThis()); + spl_fixedarray_object_write_dimension_helper(intern, zindex, value); } /* }}} */ -/* {{{ proto void SplFixedArray::offsetUnset(mixed $index) U +/* {{{ proto void SplFixedArray::offsetUnset(mixed $index) Unsets the value at the specified $index. */ SPL_METHOD(SplFixedArray, offsetUnset) { zval *zindex; spl_fixedarray_object *intern; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zindex) == FAILURE) { return; } - intern = (spl_fixedarray_object *)zend_object_store_get_object(getThis() TSRMLS_CC); - spl_fixedarray_object_unset_dimension_helper(intern, zindex TSRMLS_CC); + intern = Z_SPLFIXEDARRAY_P(getThis()); + spl_fixedarray_object_unset_dimension_helper(intern, zindex); } /* }}} */ -static void spl_fixedarray_it_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ +static void spl_fixedarray_it_dtor(zend_object_iterator *iter) /* {{{ */ { spl_fixedarray_it *iterator = (spl_fixedarray_it *)iter; - zend_user_it_invalidate_current(iter TSRMLS_CC); - zval_ptr_dtor((zval**)&iterator->intern.it.data); - - efree(iterator); + zend_user_it_invalidate_current(iter); + zval_ptr_dtor(&iterator->intern.it.data); } /* }}} */ -static void spl_fixedarray_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ +static void spl_fixedarray_it_rewind(zend_object_iterator *iter) /* {{{ */ { - spl_fixedarray_it *iterator = (spl_fixedarray_it *)iter; - spl_fixedarray_object *intern = iterator->object; + spl_fixedarray_object *object = Z_SPLFIXEDARRAY_P(&iter->data); - if (intern->flags & SPL_FIXEDARRAY_OVERLOADED_REWIND) { - zend_user_it_rewind(iter TSRMLS_CC); + if (object->flags & SPL_FIXEDARRAY_OVERLOADED_REWIND) { + zend_user_it_rewind(iter); } else { - iterator->object->current = 0; + object->current = 0; } } /* }}} */ -static int spl_fixedarray_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ +static int spl_fixedarray_it_valid(zend_object_iterator *iter) /* {{{ */ { - spl_fixedarray_it *iterator = (spl_fixedarray_it *)iter; - spl_fixedarray_object *intern = iterator->object; + spl_fixedarray_object *object = Z_SPLFIXEDARRAY_P(&iter->data); - if (intern->flags & SPL_FIXEDARRAY_OVERLOADED_VALID) { - return zend_user_it_valid(iter TSRMLS_CC); + if (object->flags & SPL_FIXEDARRAY_OVERLOADED_VALID) { + return zend_user_it_valid(iter); } - if (iterator->object->current >= 0 && iterator->object->array && iterator->object->current < iterator->object->array->size) { + if (object->current >= 0 && object->array && object->current < object->array->size) { return SUCCESS; } @@ -925,62 +881,60 @@ static int spl_fixedarray_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ } /* }}} */ -static void spl_fixedarray_it_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */ +static zval *spl_fixedarray_it_get_current_data(zend_object_iterator *iter) /* {{{ */ { - zval *zindex; - spl_fixedarray_it *iterator = (spl_fixedarray_it *)iter; - spl_fixedarray_object *intern = iterator->object; + zval zindex; + spl_fixedarray_object *object = Z_SPLFIXEDARRAY_P(&iter->data); - if (intern->flags & SPL_FIXEDARRAY_OVERLOADED_CURRENT) { - zend_user_it_get_current_data(iter, data TSRMLS_CC); + if (object->flags & SPL_FIXEDARRAY_OVERLOADED_CURRENT) { + return zend_user_it_get_current_data(iter); } else { - ALLOC_INIT_ZVAL(zindex); - ZVAL_LONG(zindex, iterator->object->current); - - *data = spl_fixedarray_object_read_dimension_helper(intern, zindex TSRMLS_CC); + zval *data; - if (*data == NULL) { - *data = &EG(uninitialized_zval_ptr); - } + ZVAL_LONG(&zindex, object->current); + data = spl_fixedarray_object_read_dimension_helper(object, &zindex); zval_ptr_dtor(&zindex); + + if (data == NULL) { + data = &EG(uninitialized_zval); + } + return data; } } /* }}} */ -static void spl_fixedarray_it_get_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) /* {{{ */ +static void spl_fixedarray_it_get_current_key(zend_object_iterator *iter, zval *key) /* {{{ */ { - spl_fixedarray_it *iterator = (spl_fixedarray_it *)iter; - spl_fixedarray_object *intern = iterator->object; + spl_fixedarray_object *object = Z_SPLFIXEDARRAY_P(&iter->data); - if (intern->flags & SPL_FIXEDARRAY_OVERLOADED_KEY) { - zend_user_it_get_current_key(iter, key TSRMLS_CC); + if (object->flags & SPL_FIXEDARRAY_OVERLOADED_KEY) { + zend_user_it_get_current_key(iter, key); } else { - ZVAL_LONG(key, iterator->object->current); + ZVAL_LONG(key, object->current); } } /* }}} */ -static void spl_fixedarray_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ +static void spl_fixedarray_it_move_forward(zend_object_iterator *iter) /* {{{ */ { - spl_fixedarray_it *iterator = (spl_fixedarray_it *)iter; - spl_fixedarray_object *intern = iterator->object; + spl_fixedarray_object *object = Z_SPLFIXEDARRAY_P(&iter->data); - if (intern->flags & SPL_FIXEDARRAY_OVERLOADED_NEXT) { - zend_user_it_move_forward(iter TSRMLS_CC); + if (object->flags & SPL_FIXEDARRAY_OVERLOADED_NEXT) { + zend_user_it_move_forward(iter); } else { - zend_user_it_invalidate_current(iter TSRMLS_CC); - iterator->object->current++; + zend_user_it_invalidate_current(iter); + object->current++; } } /* }}} */ -/* {{{ proto int SplFixedArray::key() U +/* {{{ proto int SplFixedArray::key() Return current array key */ SPL_METHOD(SplFixedArray, key) { - spl_fixedarray_object *intern = (spl_fixedarray_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_fixedarray_object *intern = Z_SPLFIXEDARRAY_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -989,12 +943,12 @@ SPL_METHOD(SplFixedArray, key) } /* }}} */ -/* {{{ proto void SplFixedArray::next() U +/* {{{ proto void SplFixedArray::next() Move to next entry */ SPL_METHOD(SplFixedArray, next) { - spl_fixedarray_object *intern = (spl_fixedarray_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_fixedarray_object *intern = Z_SPLFIXEDARRAY_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1003,12 +957,12 @@ SPL_METHOD(SplFixedArray, next) } /* }}} */ -/* {{{ proto bool SplFixedArray::valid() U +/* {{{ proto bool SplFixedArray::valid() Check whether the datastructure contains more entries */ SPL_METHOD(SplFixedArray, valid) { - spl_fixedarray_object *intern = (spl_fixedarray_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_fixedarray_object *intern = Z_SPLFIXEDARRAY_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1017,12 +971,12 @@ SPL_METHOD(SplFixedArray, valid) } /* }}} */ -/* {{{ proto void SplFixedArray::rewind() U +/* {{{ proto void SplFixedArray::rewind() Rewind the datastructure back to the start */ SPL_METHOD(SplFixedArray, rewind) { - spl_fixedarray_object *intern = (spl_fixedarray_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_fixedarray_object *intern = Z_SPLFIXEDARRAY_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1031,28 +985,29 @@ SPL_METHOD(SplFixedArray, rewind) } /* }}} */ -/* {{{ proto mixed|NULL SplFixedArray::current() U +/* {{{ proto mixed|NULL SplFixedArray::current() Return current datastructure entry */ SPL_METHOD(SplFixedArray, current) { - zval *zindex, **value_pp; - spl_fixedarray_object *intern = (spl_fixedarray_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + zval zindex, *value; + spl_fixedarray_object *intern = Z_SPLFIXEDARRAY_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } - ALLOC_INIT_ZVAL(zindex); - ZVAL_LONG(zindex, intern->current); + ZVAL_LONG(&zindex, intern->current); - value_pp = spl_fixedarray_object_read_dimension_helper(intern, zindex TSRMLS_CC); + value = spl_fixedarray_object_read_dimension_helper(intern, &zindex); zval_ptr_dtor(&zindex); - if (value_pp) { - RETURN_ZVAL(*value_pp, 1, 0); + if (value) { + ZVAL_DEREF(value); + ZVAL_COPY(return_value, value); + } else { + RETURN_NULL(); } - RETURN_NULL(); } /* }}} */ @@ -1066,26 +1021,25 @@ zend_object_iterator_funcs spl_fixedarray_it_funcs = { spl_fixedarray_it_rewind }; -zend_object_iterator *spl_fixedarray_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */ +zend_object_iterator *spl_fixedarray_get_iterator(zend_class_entry *ce, zval *object, int by_ref) /* {{{ */ { - spl_fixedarray_it *iterator; - spl_fixedarray_object *fixedarray_object = (spl_fixedarray_object*)zend_object_store_get_object(object TSRMLS_CC); + spl_fixedarray_it *iterator; if (by_ref) { - zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0); return NULL; } - Z_ADDREF_P(object); + iterator = emalloc(sizeof(spl_fixedarray_it)); + + zend_iterator_init((zend_object_iterator*)iterator); - iterator = emalloc(sizeof(spl_fixedarray_it)); - iterator->intern.it.data = (void*)object; - iterator->intern.it.funcs = &spl_fixedarray_it_funcs; - iterator->intern.ce = ce; - iterator->intern.value = NULL; - iterator->object = fixedarray_object; + ZVAL_COPY(&iterator->intern.it.data, object); + iterator->intern.it.funcs = &spl_fixedarray_it_funcs; + iterator->intern.ce = ce; + ZVAL_UNDEF(&iterator->intern.value); - return (zend_object_iterator*)iterator; + return &iterator->intern.it; } /* }}} */ @@ -1141,6 +1095,7 @@ PHP_MINIT_FUNCTION(spl_fixedarray) REGISTER_SPL_STD_CLASS_EX(SplFixedArray, spl_fixedarray_new, spl_funcs_SplFixedArray); memcpy(&spl_handler_SplFixedArray, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + spl_handler_SplFixedArray.offset = XtOffsetOf(spl_fixedarray_object, std); spl_handler_SplFixedArray.clone_obj = spl_fixedarray_object_clone; spl_handler_SplFixedArray.read_dimension = spl_fixedarray_object_read_dimension; spl_handler_SplFixedArray.write_dimension = spl_fixedarray_object_write_dimension; @@ -1149,6 +1104,8 @@ PHP_MINIT_FUNCTION(spl_fixedarray) spl_handler_SplFixedArray.count_elements = spl_fixedarray_object_count_elements; spl_handler_SplFixedArray.get_properties = spl_fixedarray_object_get_properties; spl_handler_SplFixedArray.get_gc = spl_fixedarray_object_get_gc; + spl_handler_SplFixedArray.dtor_obj = zend_objects_destroy_object; + spl_handler_SplFixedArray.free_obj = spl_fixedarray_object_free_storage; REGISTER_SPL_IMPLEMENTS(SplFixedArray, Iterator); REGISTER_SPL_IMPLEMENTS(SplFixedArray, ArrayAccess); diff --git a/ext/spl/spl_fixedarray.h b/ext/spl/spl_fixedarray.h index 8b655b72b6..0ea8b5c4f8 100644 --- a/ext/spl/spl_fixedarray.h +++ b/ext/spl/spl_fixedarray.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/spl/spl_functions.c b/ext/spl/spl_functions.c index 77e407b9ad..4b5a4cc9e7 100644 --- a/ext/spl/spl_functions.c +++ b/ext/spl/spl_functions.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -28,22 +28,22 @@ #include "php_spl.h" /* {{{ spl_register_interface */ -void spl_register_interface(zend_class_entry ** ppce, char * class_name, const zend_function_entry * functions TSRMLS_DC) +void spl_register_interface(zend_class_entry ** ppce, char * class_name, const zend_function_entry * functions) { zend_class_entry ce; - + INIT_CLASS_ENTRY_EX(ce, class_name, strlen(class_name), functions); - *ppce = zend_register_internal_interface(&ce TSRMLS_CC); + *ppce = zend_register_internal_interface(&ce); } /* }}} */ /* {{{ spl_register_std_class */ -PHPAPI void spl_register_std_class(zend_class_entry ** ppce, char * class_name, void * obj_ctor, const zend_function_entry * function_list TSRMLS_DC) +PHPAPI void spl_register_std_class(zend_class_entry ** ppce, char * class_name, void * obj_ctor, const zend_function_entry * function_list) { zend_class_entry ce; - + INIT_CLASS_ENTRY_EX(ce, class_name, strlen(class_name), function_list); - *ppce = zend_register_internal_class(&ce TSRMLS_CC); + *ppce = zend_register_internal_class(&ce); /* entries changed by initialize */ if (obj_ctor) { @@ -53,12 +53,12 @@ PHPAPI void spl_register_std_class(zend_class_entry ** ppce, char * class_name, /* }}} */ /* {{{ spl_register_sub_class */ -PHPAPI void spl_register_sub_class(zend_class_entry ** ppce, zend_class_entry * parent_ce, char * class_name, void *obj_ctor, const zend_function_entry * function_list TSRMLS_DC) +PHPAPI void spl_register_sub_class(zend_class_entry ** ppce, zend_class_entry * parent_ce, char * class_name, void *obj_ctor, const zend_function_entry * function_list) { zend_class_entry ce; - + INIT_CLASS_ENTRY_EX(ce, class_name, strlen(class_name), function_list); - *ppce = zend_register_internal_class_ex(&ce, parent_ce, NULL TSRMLS_CC); + *ppce = zend_register_internal_class_ex(&ce, parent_ce); /* entries changed by initialize */ if (obj_ctor) { @@ -70,76 +70,71 @@ PHPAPI void spl_register_sub_class(zend_class_entry ** ppce, zend_class_entry * /* }}} */ /* {{{ spl_register_property */ -void spl_register_property( zend_class_entry * class_entry, char *prop_name, int prop_name_len, int prop_flags TSRMLS_DC) +void spl_register_property( zend_class_entry * class_entry, char *prop_name, int prop_name_len, int prop_flags) { - zend_declare_property_null(class_entry, prop_name, prop_name_len, prop_flags TSRMLS_CC); + zend_declare_property_null(class_entry, prop_name, prop_name_len, prop_flags); } /* }}} */ /* {{{ spl_add_class_name */ -void spl_add_class_name(zval *list, zend_class_entry * pce, int allow, int ce_flags TSRMLS_DC) +void spl_add_class_name(zval *list, zend_class_entry *pce, int allow, int ce_flags) { if (!allow || (allow > 0 && pce->ce_flags & ce_flags) || (allow < 0 && !(pce->ce_flags & ce_flags))) { - size_t len = pce->name_length; zval *tmp; - if (zend_hash_find(Z_ARRVAL_P(list), pce->name, len+1, (void*)&tmp) == FAILURE) { - MAKE_STD_ZVAL(tmp); - ZVAL_STRINGL(tmp, pce->name, pce->name_length, 1); - zend_hash_add(Z_ARRVAL_P(list), pce->name, len+1, &tmp, sizeof(zval *), NULL); + if ((tmp = zend_hash_find(Z_ARRVAL_P(list), pce->name)) == NULL) { + zval t; + ZVAL_STR_COPY(&t, pce->name); + zend_hash_add(Z_ARRVAL_P(list), pce->name, &t); } } } /* }}} */ /* {{{ spl_add_interfaces */ -void spl_add_interfaces(zval *list, zend_class_entry * pce, int allow, int ce_flags TSRMLS_DC) +void spl_add_interfaces(zval *list, zend_class_entry * pce, int allow, int ce_flags) { - zend_uint num_interfaces; + uint32_t num_interfaces; for (num_interfaces = 0; num_interfaces < pce->num_interfaces; num_interfaces++) { - spl_add_class_name(list, pce->interfaces[num_interfaces], allow, ce_flags TSRMLS_CC); + spl_add_class_name(list, pce->interfaces[num_interfaces], allow, ce_flags); } } /* }}} */ /* {{{ spl_add_traits */ -void spl_add_traits(zval *list, zend_class_entry * pce, int allow, int ce_flags TSRMLS_DC) +void spl_add_traits(zval *list, zend_class_entry * pce, int allow, int ce_flags) { - zend_uint num_traits; - + uint32_t num_traits; + for (num_traits = 0; num_traits < pce->num_traits; num_traits++) { - spl_add_class_name(list, pce->traits[num_traits], allow, ce_flags TSRMLS_CC); + spl_add_class_name(list, pce->traits[num_traits], allow, ce_flags); } } /* }}} */ /* {{{ spl_add_classes */ -int spl_add_classes(zend_class_entry *pce, zval *list, int sub, int allow, int ce_flags TSRMLS_DC) +int spl_add_classes(zend_class_entry *pce, zval *list, int sub, int allow, int ce_flags) { if (!pce) { return 0; } - spl_add_class_name(list, pce, allow, ce_flags TSRMLS_CC); + spl_add_class_name(list, pce, allow, ce_flags); if (sub) { - spl_add_interfaces(list, pce, allow, ce_flags TSRMLS_CC); + spl_add_interfaces(list, pce, allow, ce_flags); while (pce->parent) { pce = pce->parent; - spl_add_classes(pce, list, sub, allow, ce_flags TSRMLS_CC); + spl_add_classes(pce, list, sub, allow, ce_flags); } } return 0; } /* }}} */ -char * spl_gen_private_prop_name(zend_class_entry *ce, char *prop_name, int prop_len, int *name_len TSRMLS_DC) /* {{{ */ +zend_string * spl_gen_private_prop_name(zend_class_entry *ce, char *prop_name, int prop_len) /* {{{ */ { - char *rv; - - zend_mangle_property_name(&rv, name_len, ce->name, ce->name_length, prop_name, prop_len, 0); - - return rv; + return zend_mangle_property_name(ZSTR_VAL(ce->name), ZSTR_LEN(ce->name), prop_name, prop_len, 0); } /* }}} */ diff --git a/ext/spl/spl_functions.h b/ext/spl/spl_functions.h index 3e759cd20f..0611cab2b8 100644 --- a/ext/spl/spl_functions.h +++ b/ext/spl/spl_functions.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -23,54 +23,54 @@ #include "php.h" -typedef zend_object_value (*create_object_func_t)(zend_class_entry *class_type TSRMLS_DC); +typedef zend_object* (*create_object_func_t)(zend_class_entry *class_type); #define REGISTER_SPL_STD_CLASS(class_name, obj_ctor) \ - spl_register_std_class(&spl_ce_ ## class_name, # class_name, obj_ctor, NULL TSRMLS_CC); + spl_register_std_class(&spl_ce_ ## class_name, # class_name, obj_ctor, NULL); #define REGISTER_SPL_STD_CLASS_EX(class_name, obj_ctor, funcs) \ - spl_register_std_class(&spl_ce_ ## class_name, # class_name, obj_ctor, funcs TSRMLS_CC); + spl_register_std_class(&spl_ce_ ## class_name, # class_name, obj_ctor, funcs); #define REGISTER_SPL_SUB_CLASS_EX(class_name, parent_class_name, obj_ctor, funcs) \ - spl_register_sub_class(&spl_ce_ ## class_name, spl_ce_ ## parent_class_name, # class_name, obj_ctor, funcs TSRMLS_CC); + spl_register_sub_class(&spl_ce_ ## class_name, spl_ce_ ## parent_class_name, # class_name, obj_ctor, funcs); #define REGISTER_SPL_INTERFACE(class_name) \ - spl_register_interface(&spl_ce_ ## class_name, # class_name, spl_funcs_ ## class_name TSRMLS_CC); + spl_register_interface(&spl_ce_ ## class_name, # class_name, spl_funcs_ ## class_name); #define REGISTER_SPL_IMPLEMENTS(class_name, interface_name) \ - zend_class_implements(spl_ce_ ## class_name TSRMLS_CC, 1, spl_ce_ ## interface_name); + zend_class_implements(spl_ce_ ## class_name, 1, spl_ce_ ## interface_name); #define REGISTER_SPL_ITERATOR(class_name) \ - zend_class_implements(spl_ce_ ## class_name TSRMLS_CC, 1, zend_ce_iterator); + zend_class_implements(spl_ce_ ## class_name, 1, zend_ce_iterator); #define REGISTER_SPL_PROPERTY(class_name, prop_name, prop_flags) \ - spl_register_property(spl_ce_ ## class_name, prop_name, sizeof(prop_name)-1, prop_flags TSRMLS_CC); + spl_register_property(spl_ce_ ## class_name, prop_name, sizeof(prop_name)-1, prop_flags); #define REGISTER_SPL_CLASS_CONST_LONG(class_name, const_name, value) \ - zend_declare_class_constant_long(spl_ce_ ## class_name, const_name, sizeof(const_name)-1, (long)value TSRMLS_CC); + zend_declare_class_constant_long(spl_ce_ ## class_name, const_name, sizeof(const_name)-1, (zend_long)value); -void spl_register_std_class(zend_class_entry ** ppce, char * class_name, create_object_func_t ctor, const zend_function_entry * function_list TSRMLS_DC); -void spl_register_sub_class(zend_class_entry ** ppce, zend_class_entry * parent_ce, char * class_name, create_object_func_t ctor, const zend_function_entry * function_list TSRMLS_DC); -void spl_register_interface(zend_class_entry ** ppce, char * class_name, const zend_function_entry *functions TSRMLS_DC); +void spl_register_std_class(zend_class_entry ** ppce, char * class_name, create_object_func_t ctor, const zend_function_entry * function_list); +void spl_register_sub_class(zend_class_entry ** ppce, zend_class_entry * parent_ce, char * class_name, create_object_func_t ctor, const zend_function_entry * function_list); +void spl_register_interface(zend_class_entry ** ppce, char * class_name, const zend_function_entry *functions); -void spl_register_property( zend_class_entry * class_entry, char *prop_name, int prop_name_len, int prop_flags TSRMLS_DC); +void spl_register_property( zend_class_entry * class_entry, char *prop_name, int prop_name_len, int prop_flags); /* sub: whether to allow subclasses/interfaces allow = 0: allow all classes and interfaces allow > 0: allow all that match and mask ce_flags allow < 0: disallow all that match and mask ce_flags */ -void spl_add_class_name(zval * list, zend_class_entry * pce, int allow, int ce_flags TSRMLS_DC); -void spl_add_interfaces(zval * list, zend_class_entry * pce, int allow, int ce_flags TSRMLS_DC); -void spl_add_traits(zval * list, zend_class_entry * pce, int allow, int ce_flags TSRMLS_DC); -int spl_add_classes(zend_class_entry *pce, zval *list, int sub, int allow, int ce_flags TSRMLS_DC); +void spl_add_class_name(zval * list, zend_class_entry * pce, int allow, int ce_flags); +void spl_add_interfaces(zval * list, zend_class_entry * pce, int allow, int ce_flags); +void spl_add_traits(zval * list, zend_class_entry * pce, int allow, int ce_flags); +int spl_add_classes(zend_class_entry *pce, zval *list, int sub, int allow, int ce_flags); /* caller must efree(return) */ -char * spl_gen_private_prop_name(zend_class_entry *ce, char *prop_name, int prop_len, int *name_len TSRMLS_DC); +zend_string *spl_gen_private_prop_name(zend_class_entry *ce, char *prop_name, int prop_len); #define SPL_ME(class_name, function_name, arg_info, flags) \ PHP_ME( spl_ ## class_name, function_name, arg_info, flags) - + #define SPL_ABSTRACT_ME(class_name, function_name, arg_info) \ ZEND_ABSTRACT_ME( spl_ ## class_name, function_name, arg_info) diff --git a/ext/spl/spl_heap.c b/ext/spl/spl_heap.c index bac9828033..2e014a1863 100644 --- a/ext/spl/spl_heap.c +++ b/ext/spl/spl_heap.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -49,14 +49,13 @@ PHPAPI zend_class_entry *spl_ce_SplMaxHeap; PHPAPI zend_class_entry *spl_ce_SplMinHeap; PHPAPI zend_class_entry *spl_ce_SplPriorityQueue; -typedef void *spl_ptr_heap_element; -typedef void (*spl_ptr_heap_dtor_func)(spl_ptr_heap_element TSRMLS_DC); -typedef void (*spl_ptr_heap_ctor_func)(spl_ptr_heap_element TSRMLS_DC); -typedef int (*spl_ptr_heap_cmp_func)(spl_ptr_heap_element, spl_ptr_heap_element, void* TSRMLS_DC); +typedef void (*spl_ptr_heap_dtor_func)(zval *); +typedef void (*spl_ptr_heap_ctor_func)(zval *); +typedef int (*spl_ptr_heap_cmp_func)(zval *, zval *, zval *); typedef struct _spl_ptr_heap { - spl_ptr_heap_element *elements; + zval *elements; spl_ptr_heap_ctor_func ctor; spl_ptr_heap_dtor_func dtor; spl_ptr_heap_cmp_func cmp; @@ -69,68 +68,70 @@ typedef struct _spl_heap_object spl_heap_object; typedef struct _spl_heap_it spl_heap_it; struct _spl_heap_object { - zend_object std; spl_ptr_heap *heap; - zval *retval; int flags; zend_class_entry *ce_get_iterator; zend_function *fptr_cmp; zend_function *fptr_count; - HashTable *debug_info; + zend_object std; }; /* define an overloaded iterator structure */ struct _spl_heap_it { zend_user_iterator intern; int flags; - spl_heap_object *object; }; -/* {{{ spl_ptr_heap */ -static void spl_ptr_heap_zval_dtor(spl_ptr_heap_element elem TSRMLS_DC) { /* {{{ */ - if (elem) { - zval_ptr_dtor((zval **)&elem); - } +static inline spl_heap_object *spl_heap_from_obj(zend_object *obj) /* {{{ */ { + return (spl_heap_object*)((char*)(obj) - XtOffsetOf(spl_heap_object, std)); } /* }}} */ -static void spl_ptr_heap_zval_ctor(spl_ptr_heap_element elem TSRMLS_DC) { /* {{{ */ - Z_ADDREF_P((zval *)elem); +#define Z_SPLHEAP_P(zv) spl_heap_from_obj(Z_OBJ_P((zv))) + +static void spl_ptr_heap_zval_dtor(zval *elem) { /* {{{ */ + if (!Z_ISUNDEF_P(elem)) { + zval_ptr_dtor(elem); + } } /* }}} */ -static int spl_ptr_heap_cmp_cb_helper(zval *object, spl_heap_object *heap_object, zval *a, zval *b, long *result TSRMLS_DC) { /* {{{ */ - zval *result_p = NULL; +static void spl_ptr_heap_zval_ctor(zval *elem) { /* {{{ */ + if (Z_REFCOUNTED_P(elem)) { + Z_ADDREF_P(elem); + } +} +/* }}} */ - zend_call_method_with_2_params(&object, heap_object->std.ce, &heap_object->fptr_cmp, "compare", &result_p, a, b); +static int spl_ptr_heap_cmp_cb_helper(zval *object, spl_heap_object *heap_object, zval *a, zval *b, zend_long *result) { /* {{{ */ + zval zresult; - if (EG(exception)) { - return FAILURE; - } + zend_call_method_with_2_params(object, heap_object->std.ce, &heap_object->fptr_cmp, "compare", &zresult, a, b); - convert_to_long(result_p); - *result = Z_LVAL_P(result_p); + if (EG(exception)) { + return FAILURE; + } - zval_ptr_dtor(&result_p); + *result = zval_get_long(&zresult); + zval_ptr_dtor(&zresult); - return SUCCESS; + return SUCCESS; } /* }}} */ -static zval **spl_pqueue_extract_helper(zval **value, int flags) /* {{{ */ +static zval *spl_pqueue_extract_helper(zval *value, int flags) /* {{{ */ { if ((flags & SPL_PQUEUE_EXTR_BOTH) == SPL_PQUEUE_EXTR_BOTH) { return value; } else if ((flags & SPL_PQUEUE_EXTR_BOTH) > 0) { - if ((flags & SPL_PQUEUE_EXTR_DATA) == SPL_PQUEUE_EXTR_DATA) { - zval **data; - if (zend_hash_find(Z_ARRVAL_PP(value), "data", sizeof("data"), (void **) &data) == SUCCESS) { + zval *data; + if ((data = zend_hash_str_find(Z_ARRVAL_P(value), "data", sizeof("data") - 1)) != NULL) { return data; } } else { - zval **priority; - if (zend_hash_find(Z_ARRVAL_PP(value), "priority", sizeof("priority"), (void **) &priority) == SUCCESS) { + zval *priority; + if ((priority = zend_hash_str_find(Z_ARRVAL_P(value), "priority", sizeof("priority") - 1)) != NULL) { return priority; } } @@ -140,7 +141,7 @@ static zval **spl_pqueue_extract_helper(zval **value, int flags) /* {{{ */ } /* }}} */ -static int spl_ptr_heap_zval_max_cmp(spl_ptr_heap_element a, spl_ptr_heap_element b, void* object TSRMLS_DC) { /* {{{ */ +static int spl_ptr_heap_zval_max_cmp(zval *a, zval *b, zval *object) { /* {{{ */ zval result; if (EG(exception)) { @@ -148,24 +149,23 @@ static int spl_ptr_heap_zval_max_cmp(spl_ptr_heap_element a, spl_ptr_heap_elemen } if (object) { - spl_heap_object *heap_object = (spl_heap_object*)zend_object_store_get_object((zval *)object TSRMLS_CC); + spl_heap_object *heap_object = Z_SPLHEAP_P(object); if (heap_object->fptr_cmp) { - long lval = 0; - if (spl_ptr_heap_cmp_cb_helper((zval *)object, heap_object, (zval *)a, (zval *)b, &lval TSRMLS_CC) == FAILURE) { + zend_long lval = 0; + if (spl_ptr_heap_cmp_cb_helper(object, heap_object, a, b, &lval) == FAILURE) { /* exception or call failure */ return 0; } - return lval; + return lval > 0 ? 1 : (lval < 0 ? -1 : 0); } } - INIT_ZVAL(result); - compare_function(&result, (zval *)a, (zval *)b TSRMLS_CC); - return Z_LVAL(result); + compare_function(&result, a, b); + return (int)Z_LVAL(result); } /* }}} */ -static int spl_ptr_heap_zval_min_cmp(spl_ptr_heap_element a, spl_ptr_heap_element b, void* object TSRMLS_DC) { /* {{{ */ +static int spl_ptr_heap_zval_min_cmp(zval *a, zval *b, zval *object) { /* {{{ */ zval result; if (EG(exception)) { @@ -173,51 +173,50 @@ static int spl_ptr_heap_zval_min_cmp(spl_ptr_heap_element a, spl_ptr_heap_elemen } if (object) { - spl_heap_object *heap_object = (spl_heap_object*)zend_object_store_get_object((zval *)object TSRMLS_CC); + spl_heap_object *heap_object = Z_SPLHEAP_P(object); if (heap_object->fptr_cmp) { - long lval = 0; - if (spl_ptr_heap_cmp_cb_helper((zval *)object, heap_object, (zval *)a, (zval *)b, &lval TSRMLS_CC) == FAILURE) { + zend_long lval = 0; + if (spl_ptr_heap_cmp_cb_helper(object, heap_object, a, b, &lval) == FAILURE) { /* exception or call failure */ return 0; } - return lval; + return lval > 0 ? 1 : (lval < 0 ? -1 : 0); } } - INIT_ZVAL(result); - compare_function(&result, (zval *)b, (zval *)a TSRMLS_CC); - return Z_LVAL(result); + compare_function(&result, b, a); + return (int)Z_LVAL(result); } /* }}} */ -static int spl_ptr_pqueue_zval_cmp(spl_ptr_heap_element a, spl_ptr_heap_element b, void* object TSRMLS_DC) { /* {{{ */ +static int spl_ptr_pqueue_zval_cmp(zval *a, zval *b, zval *object) { /* {{{ */ zval result; - zval **a_priority_pp = spl_pqueue_extract_helper((zval **)&a, SPL_PQUEUE_EXTR_PRIORITY); - zval **b_priority_pp = spl_pqueue_extract_helper((zval **)&b, SPL_PQUEUE_EXTR_PRIORITY); + zval *a_priority_p = spl_pqueue_extract_helper(a, SPL_PQUEUE_EXTR_PRIORITY); + zval *b_priority_p = spl_pqueue_extract_helper(b, SPL_PQUEUE_EXTR_PRIORITY); - if ((!a_priority_pp) || (!b_priority_pp)) { + if ((!a_priority_p) || (!b_priority_p)) { zend_error(E_RECOVERABLE_ERROR, "Unable to extract from the PriorityQueue node"); return 0; } + if (EG(exception)) { return 0; } if (object) { - spl_heap_object *heap_object = (spl_heap_object*)zend_object_store_get_object(object TSRMLS_CC); + spl_heap_object *heap_object = Z_SPLHEAP_P(object); if (heap_object->fptr_cmp) { - long lval = 0; - if (spl_ptr_heap_cmp_cb_helper((zval *)object, heap_object, *a_priority_pp, *b_priority_pp, &lval TSRMLS_CC) == FAILURE) { + zend_long lval = 0; + if (spl_ptr_heap_cmp_cb_helper((zval *)object, heap_object, a_priority_p, b_priority_p, &lval) == FAILURE) { /* exception or call failure */ return 0; } - return lval; + return lval > 0 ? 1 : (lval < 0 ? -1 : 0); } } - INIT_ZVAL(result); - compare_function(&result, *a_priority_pp, *b_priority_pp TSRMLS_CC); - return Z_LVAL(result); + compare_function(&result, a_priority_p, b_priority_p); + return (int)Z_LVAL(result); } /* }}} */ @@ -228,7 +227,7 @@ static spl_ptr_heap *spl_ptr_heap_init(spl_ptr_heap_cmp_func cmp, spl_ptr_heap_c heap->dtor = dtor; heap->ctor = ctor; heap->cmp = cmp; - heap->elements = safe_emalloc(sizeof(spl_ptr_heap_element), PTR_HEAP_BLOCK_SIZE, 0); + heap->elements = ecalloc(PTR_HEAP_BLOCK_SIZE, sizeof(zval)); heap->max_size = PTR_HEAP_BLOCK_SIZE; heap->count = 0; heap->flags = 0; @@ -237,19 +236,18 @@ static spl_ptr_heap *spl_ptr_heap_init(spl_ptr_heap_cmp_func cmp, spl_ptr_heap_c } /* }}} */ -static void spl_ptr_heap_insert(spl_ptr_heap *heap, spl_ptr_heap_element elem, void *cmp_userdata TSRMLS_DC) { /* {{{ */ +static void spl_ptr_heap_insert(spl_ptr_heap *heap, zval *elem, void *cmp_userdata) { /* {{{ */ int i; if (heap->count+1 > heap->max_size) { /* we need to allocate more memory */ - heap->elements = (void **) safe_erealloc(heap->elements, sizeof(spl_ptr_heap_element), (heap->max_size), (sizeof(spl_ptr_heap_element) * (heap->max_size))); + heap->elements = erealloc(heap->elements, heap->max_size * 2 * sizeof(zval)); + memset(heap->elements + heap->max_size, 0, heap->max_size * sizeof(zval)); heap->max_size *= 2; } - heap->ctor(elem TSRMLS_CC); - /* sifting up */ - for(i = heap->count; i > 0 && heap->cmp(heap->elements[(i-1)/2], elem, cmp_userdata TSRMLS_CC) < 0; i = (i-1)/2) { + for (i = heap->count; i > 0 && heap->cmp(&heap->elements[(i-1)/2], elem, cmp_userdata) < 0; i = (i-1)/2) { heap->elements[i] = heap->elements[(i-1)/2]; } heap->count++; @@ -259,43 +257,41 @@ static void spl_ptr_heap_insert(spl_ptr_heap *heap, spl_ptr_heap_element elem, v heap->flags |= SPL_HEAP_CORRUPTED; } - heap->elements[i] = elem; - + ZVAL_COPY_VALUE(&heap->elements[i], elem); } /* }}} */ -static spl_ptr_heap_element spl_ptr_heap_top(spl_ptr_heap *heap) { /* {{{ */ +static zval *spl_ptr_heap_top(spl_ptr_heap *heap) { /* {{{ */ if (heap->count == 0) { return NULL; } - return heap->elements[0]; + return Z_ISUNDEF(heap->elements[0])? NULL : &heap->elements[0]; } /* }}} */ -static spl_ptr_heap_element spl_ptr_heap_delete_top(spl_ptr_heap *heap, void *cmp_userdata TSRMLS_DC) { /* {{{ */ +static void spl_ptr_heap_delete_top(spl_ptr_heap *heap, zval *elem, void *cmp_userdata) { /* {{{ */ int i, j; const int limit = (heap->count-1)/2; - spl_ptr_heap_element top; - spl_ptr_heap_element bottom; + zval *bottom; if (heap->count == 0) { - return NULL; + ZVAL_UNDEF(elem); + return; } - top = heap->elements[0]; - bottom = heap->elements[--heap->count]; + ZVAL_COPY_VALUE(elem, &heap->elements[0]); + bottom = &heap->elements[--heap->count]; - for( i = 0; i < limit; i = j) - { + for (i = 0; i < limit; i = j) { /* Find smaller child */ - j = i*2+1; - if(j != heap->count && heap->cmp(heap->elements[j+1], heap->elements[j], cmp_userdata TSRMLS_CC) > 0) { + j = i * 2 + 1; + if(j != heap->count && heap->cmp(&heap->elements[j+1], &heap->elements[j], cmp_userdata) > 0) { j++; /* next child is bigger */ } /* swap elements between two levels */ - if(heap->cmp(bottom, heap->elements[j], cmp_userdata TSRMLS_CC) < 0) { + if(heap->cmp(bottom, &heap->elements[j], cmp_userdata) < 0) { heap->elements[i] = heap->elements[j]; } else { break; @@ -307,13 +303,11 @@ static spl_ptr_heap_element spl_ptr_heap_delete_top(spl_ptr_heap *heap, void *cm heap->flags |= SPL_HEAP_CORRUPTED; } - heap->elements[i] = bottom; - heap->dtor(top TSRMLS_CC); - return top; + ZVAL_COPY_VALUE(&heap->elements[i], bottom); } /* }}} */ -static spl_ptr_heap *spl_ptr_heap_clone(spl_ptr_heap *from TSRMLS_DC) { /* {{{ */ +static spl_ptr_heap *spl_ptr_heap_clone(spl_ptr_heap *from) { /* {{{ */ int i; spl_ptr_heap *heap = emalloc(sizeof(spl_ptr_heap)); @@ -325,22 +319,22 @@ static spl_ptr_heap *spl_ptr_heap_clone(spl_ptr_heap *from TSRMLS_DC) { /* {{{ * heap->count = from->count; heap->flags = from->flags; - heap->elements = safe_emalloc(sizeof(spl_ptr_heap_element),from->max_size,0); - memcpy(heap->elements, from->elements, sizeof(spl_ptr_heap_element)*from->max_size); + heap->elements = safe_emalloc(sizeof(zval), from->max_size, 0); + memcpy(heap->elements, from->elements, sizeof(zval)*from->max_size); for (i=0; i < heap->count; ++i) { - heap->ctor(heap->elements[i] TSRMLS_CC); + heap->ctor(&heap->elements[i]); } return heap; } /* }}} */ -static void spl_ptr_heap_destroy(spl_ptr_heap *heap TSRMLS_DC) { /* {{{ */ +static void spl_ptr_heap_destroy(spl_ptr_heap *heap) { /* {{{ */ int i; for (i=0; i < heap->count; ++i) { - heap->dtor(heap->elements[i] TSRMLS_CC); + heap->dtor(&heap->elements[i]); } efree(heap->elements); @@ -352,66 +346,39 @@ static int spl_ptr_heap_count(spl_ptr_heap *heap) { /* {{{ */ return heap->count; } /* }}} */ -/* }}} */ -zend_object_iterator *spl_heap_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC); +zend_object_iterator *spl_heap_get_iterator(zend_class_entry *ce, zval *object, int by_ref); -static void spl_heap_object_free_storage(void *object TSRMLS_DC) /* {{{ */ +static void spl_heap_object_free_storage(zend_object *object) /* {{{ */ { - int i; - spl_heap_object *intern = (spl_heap_object *)object; - - zend_object_std_dtor(&intern->std TSRMLS_CC); - - for (i = 0; i < intern->heap->count; ++i) { - if (intern->heap->elements[i]) { - zval_ptr_dtor((zval **)&intern->heap->elements[i]); - } - } - - spl_ptr_heap_destroy(intern->heap TSRMLS_CC); + spl_heap_object *intern = spl_heap_from_obj(object); - zval_ptr_dtor(&intern->retval); + zend_object_std_dtor(&intern->std); - if (intern->debug_info != NULL) { - zend_hash_destroy(intern->debug_info); - efree(intern->debug_info); - } - - efree(object); + spl_ptr_heap_destroy(intern->heap); } /* }}} */ -static zend_object_value spl_heap_object_new_ex(zend_class_entry *class_type, spl_heap_object **obj, zval *orig, int clone_orig TSRMLS_DC) /* {{{ */ +static zend_object *spl_heap_object_new_ex(zend_class_entry *class_type, zval *orig, int clone_orig) /* {{{ */ { - zend_object_value retval; spl_heap_object *intern; zend_class_entry *parent = class_type; int inherited = 0; - intern = ecalloc(1, sizeof(spl_heap_object)); - *obj = intern; - ALLOC_INIT_ZVAL(intern->retval); + intern = ecalloc(1, sizeof(spl_heap_object) + zend_object_properties_size(parent)); - zend_object_std_init(&intern->std, class_type TSRMLS_CC); + zend_object_std_init(&intern->std, class_type); object_properties_init(&intern->std, class_type); intern->flags = 0; intern->fptr_cmp = NULL; - intern->debug_info = NULL; if (orig) { - spl_heap_object *other = (spl_heap_object*)zend_object_store_get_object(orig TSRMLS_CC); + spl_heap_object *other = Z_SPLHEAP_P(orig); intern->ce_get_iterator = other->ce_get_iterator; if (clone_orig) { - int i; - intern->heap = spl_ptr_heap_clone(other->heap TSRMLS_CC); - for (i = 0; i < intern->heap->count; ++i) { - if (intern->heap->elements[i]) { - Z_ADDREF_P((zval *)intern->heap->elements[i]); - } - } + intern->heap = spl_ptr_heap_clone(other->heap); } else { intern->heap = other->heap; } @@ -421,13 +388,13 @@ static zend_object_value spl_heap_object_new_ex(zend_class_entry *class_type, sp intern->heap = spl_ptr_heap_init(spl_ptr_heap_zval_max_cmp, spl_ptr_heap_zval_ctor, spl_ptr_heap_zval_dtor); } - retval.handlers = &spl_handler_SplHeap; + intern->std.handlers = &spl_handler_SplHeap; while (parent) { if (parent == spl_ce_SplPriorityQueue) { intern->heap->cmp = spl_ptr_pqueue_zval_cmp; - intern->flags = SPL_PQUEUE_EXTR_DATA; - retval.handlers = &spl_handler_SplPriorityQueue; + intern->flags = SPL_PQUEUE_EXTR_DATA; + intern->std.handlers = &spl_handler_SplPriorityQueue; break; } @@ -449,144 +416,139 @@ static zend_object_value spl_heap_object_new_ex(zend_class_entry *class_type, sp inherited = 1; } - retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, spl_heap_object_free_storage, NULL TSRMLS_CC); - if (!parent) { /* this must never happen */ - php_error_docref(NULL TSRMLS_CC, E_COMPILE_ERROR, "Internal compiler error, Class is not child of SplHeap"); + php_error_docref(NULL, E_COMPILE_ERROR, "Internal compiler error, Class is not child of SplHeap"); } if (inherited) { - zend_hash_find(&class_type->function_table, "compare", sizeof("compare"), (void **) &intern->fptr_cmp); + intern->fptr_cmp = zend_hash_str_find_ptr(&class_type->function_table, "compare", sizeof("compare") - 1); if (intern->fptr_cmp->common.scope == parent) { intern->fptr_cmp = NULL; } - zend_hash_find(&class_type->function_table, "count", sizeof("count"), (void **) &intern->fptr_count); + intern->fptr_count = zend_hash_str_find_ptr(&class_type->function_table, "count", sizeof("count") - 1); if (intern->fptr_count->common.scope == parent) { intern->fptr_count = NULL; } } - return retval; + return &intern->std; } /* }}} */ -static zend_object_value spl_heap_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */ +static zend_object *spl_heap_object_new(zend_class_entry *class_type) /* {{{ */ { - spl_heap_object *tmp; - return spl_heap_object_new_ex(class_type, &tmp, NULL, 0 TSRMLS_CC); + return spl_heap_object_new_ex(class_type, NULL, 0); } /* }}} */ -static zend_object_value spl_heap_object_clone(zval *zobject TSRMLS_DC) /* {{{ */ +static zend_object *spl_heap_object_clone(zval *zobject) /* {{{ */ { - zend_object_value new_obj_val; zend_object *old_object; zend_object *new_object; - zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); - spl_heap_object *intern; - old_object = zend_objects_get_address(zobject TSRMLS_CC); - new_obj_val = spl_heap_object_new_ex(old_object->ce, &intern, zobject, 1 TSRMLS_CC); - new_object = &intern->std; + old_object = Z_OBJ_P(zobject); + new_object = spl_heap_object_new_ex(old_object->ce, zobject, 1); - zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC); + zend_objects_clone_members(new_object, old_object); - return new_obj_val; + return new_object; } /* }}} */ -static int spl_heap_object_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */ +static int spl_heap_object_count_elements(zval *object, zend_long *count) /* {{{ */ { - spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(object TSRMLS_CC); + spl_heap_object *intern = Z_SPLHEAP_P(object); if (intern->fptr_count) { - zval *rv; - zend_call_method_with_0_params(&object, intern->std.ce, &intern->fptr_count, "count", &rv); - if (rv) { - zval_ptr_dtor(&intern->retval); - MAKE_STD_ZVAL(intern->retval); - ZVAL_ZVAL(intern->retval, rv, 1, 1); - convert_to_long(intern->retval); - *count = (long) Z_LVAL_P(intern->retval); + zval rv; + zend_call_method_with_0_params(object, intern->std.ce, &intern->fptr_count, "count", &rv); + if (!Z_ISUNDEF(rv)) { + *count = zval_get_long(&rv); + zval_ptr_dtor(&rv); return SUCCESS; } *count = 0; return FAILURE; } - + *count = spl_ptr_heap_count(intern->heap); return SUCCESS; -} +} /* }}} */ -static HashTable* spl_heap_object_get_debug_info_helper(zend_class_entry *ce, zval *obj, int *is_temp TSRMLS_DC) { /* {{{ */ - spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(obj TSRMLS_CC); - zval *tmp, zrv, *heap_array; - char *pnstr; - int pnlen; +static HashTable* spl_heap_object_get_debug_info_helper(zend_class_entry *ce, zval *obj, int *is_temp) { /* {{{ */ + spl_heap_object *intern = Z_SPLHEAP_P(obj); + zval tmp, heap_array; + zend_string *pnstr; + HashTable *debug_info; int i; - *is_temp = 0; + *is_temp = 1; if (!intern->std.properties) { rebuild_object_properties(&intern->std); } - if (intern->debug_info == NULL) { - ALLOC_HASHTABLE(intern->debug_info); - ZEND_INIT_SYMTABLE_EX(intern->debug_info, zend_hash_num_elements(intern->std.properties) + 1, 0); - } + ALLOC_HASHTABLE(debug_info); + ZEND_INIT_SYMTABLE_EX(debug_info, zend_hash_num_elements(intern->std.properties) + 1, 0); + zend_hash_copy(debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref); - if (intern->debug_info->nApplyCount == 0) { - INIT_PZVAL(&zrv); - Z_ARRVAL(zrv) = intern->debug_info; + pnstr = spl_gen_private_prop_name(ce, "flags", sizeof("flags")-1); + ZVAL_LONG(&tmp, intern->flags); + zend_hash_update(debug_info, pnstr, &tmp); + zend_string_release(pnstr); - zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); + pnstr = spl_gen_private_prop_name(ce, "isCorrupted", sizeof("isCorrupted")-1); + ZVAL_BOOL(&tmp, intern->heap->flags&SPL_HEAP_CORRUPTED); + zend_hash_update(debug_info, pnstr, &tmp); + zend_string_release(pnstr); - pnstr = spl_gen_private_prop_name(ce, "flags", sizeof("flags")-1, &pnlen TSRMLS_CC); - add_assoc_long_ex(&zrv, pnstr, pnlen+1, intern->flags); - efree(pnstr); + array_init(&heap_array); - pnstr = spl_gen_private_prop_name(ce, "isCorrupted", sizeof("isCorrupted")-1, &pnlen TSRMLS_CC); - add_assoc_bool_ex(&zrv, pnstr, pnlen+1, intern->heap->flags&SPL_HEAP_CORRUPTED); - efree(pnstr); + for (i = 0; i < intern->heap->count; ++i) { + add_index_zval(&heap_array, i, &intern->heap->elements[i]); + if (Z_REFCOUNTED(intern->heap->elements[i])) { + Z_ADDREF(intern->heap->elements[i]); + } + } - ALLOC_INIT_ZVAL(heap_array); - array_init(heap_array); + pnstr = spl_gen_private_prop_name(ce, "heap", sizeof("heap")-1); + zend_hash_update(debug_info, pnstr, &heap_array); + zend_string_release(pnstr); - for (i = 0; i < intern->heap->count; ++i) { - add_index_zval(heap_array, i, (zval *)intern->heap->elements[i]); - Z_ADDREF_P(intern->heap->elements[i]); - } + return debug_info; +} +/* }}} */ - pnstr = spl_gen_private_prop_name(ce, "heap", sizeof("heap")-1, &pnlen TSRMLS_CC); - add_assoc_zval_ex(&zrv, pnstr, pnlen+1, heap_array); - efree(pnstr); - } +static HashTable *spl_heap_object_get_gc(zval *obj, zval **gc_data, int *gc_data_count) /* {{{ */ +{ + spl_heap_object *intern = Z_SPLHEAP_P(obj); + *gc_data = intern->heap->elements; + *gc_data_count = intern->heap->count; - return intern->debug_info; + return std_object_handlers.get_properties(obj); } /* }}} */ -static HashTable* spl_heap_object_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{ */ +static HashTable* spl_heap_object_get_debug_info(zval *obj, int *is_temp) /* {{{ */ { - return spl_heap_object_get_debug_info_helper(spl_ce_SplHeap, obj, is_temp TSRMLS_CC); + return spl_heap_object_get_debug_info_helper(spl_ce_SplHeap, obj, is_temp); } /* }}} */ -static HashTable* spl_pqueue_object_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{ */ +static HashTable* spl_pqueue_object_get_debug_info(zval *obj, int *is_temp) /* {{{ */ { - return spl_heap_object_get_debug_info_helper(spl_ce_SplPriorityQueue, obj, is_temp TSRMLS_CC); + return spl_heap_object_get_debug_info_helper(spl_ce_SplPriorityQueue, obj, is_temp); } /* }}} */ -/* {{{ proto int SplHeap::count() U +/* {{{ proto int SplHeap::count() Return the number of elements in the heap. */ SPL_METHOD(SplHeap, count) { - long count; - spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + zend_long count; + spl_heap_object *intern = Z_SPLHEAP_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; @@ -597,199 +559,191 @@ SPL_METHOD(SplHeap, count) } /* }}} */ -/* {{{ proto int SplHeap::isEmpty() U +/* {{{ proto int SplHeap::isEmpty() Return true if the heap is empty. */ SPL_METHOD(SplHeap, isEmpty) { - spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_heap_object *intern = Z_SPLHEAP_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; } - RETURN_BOOL(spl_ptr_heap_count(intern->heap)==0); + RETURN_BOOL(spl_ptr_heap_count(intern->heap) == 0); } /* }}} */ -/* {{{ proto bool SplHeap::insert(mixed $value) U +/* {{{ proto bool SplHeap::insert(mixed value) Push $value on the heap */ SPL_METHOD(SplHeap, insert) { zval *value; spl_heap_object *intern; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &value) == FAILURE) { return; } - intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_SPLHEAP_P(getThis()); if (intern->heap->flags & SPL_HEAP_CORRUPTED) { - zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0); return; } - SEPARATE_ARG_IF_REF(value); - - spl_ptr_heap_insert(intern->heap, value, getThis() TSRMLS_CC); + if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value); + spl_ptr_heap_insert(intern->heap, value, getThis()); RETURN_TRUE; -} +} /* }}} */ -/* {{{ proto mixed SplHeap::extract() U +/* {{{ proto mixed SplHeap::extract() extract the element out of the top of the heap */ SPL_METHOD(SplHeap, extract) { - zval *value; spl_heap_object *intern; if (zend_parse_parameters_none() == FAILURE) { return; } - intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_SPLHEAP_P(getThis()); if (intern->heap->flags & SPL_HEAP_CORRUPTED) { - zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0); return; } - value = (zval *)spl_ptr_heap_delete_top(intern->heap, getThis() TSRMLS_CC); + spl_ptr_heap_delete_top(intern->heap, return_value, getThis()); - if (!value) { - zend_throw_exception(spl_ce_RuntimeException, "Can't extract from an empty heap", 0 TSRMLS_CC); + if (Z_ISUNDEF_P(return_value)) { + zend_throw_exception(spl_ce_RuntimeException, "Can't extract from an empty heap", 0); return; } - - RETURN_ZVAL(value, 1, 1); -} +} /* }}} */ -/* {{{ proto bool SplPriorityQueue::insert(mixed $value, mixed $priority) U +/* {{{ proto bool SplPriorityQueue::insert(mixed value, mixed priority) Push $value with the priority $priodiry on the priorityqueue */ SPL_METHOD(SplPriorityQueue, insert) { - zval *data, *priority, *elem; + zval *data, *priority, elem; spl_heap_object *intern; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &data, &priority) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &data, &priority) == FAILURE) { return; } - intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_SPLHEAP_P(getThis()); if (intern->heap->flags & SPL_HEAP_CORRUPTED) { - zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0); return; } - SEPARATE_ARG_IF_REF(data); - SEPARATE_ARG_IF_REF(priority); + if (Z_REFCOUNTED_P(data)) Z_ADDREF_P(data); + if (Z_REFCOUNTED_P(priority)) Z_ADDREF_P(priority); - ALLOC_INIT_ZVAL(elem); + array_init(&elem); + add_assoc_zval_ex(&elem, "data", sizeof("data") - 1, data); + add_assoc_zval_ex(&elem, "priority", sizeof("priority") - 1, priority); - array_init(elem); - add_assoc_zval_ex(elem, "data", sizeof("data"), data); - add_assoc_zval_ex(elem, "priority", sizeof("priority"), priority); - - spl_ptr_heap_insert(intern->heap, elem, getThis() TSRMLS_CC); + spl_ptr_heap_insert(intern->heap, &elem, getThis()); RETURN_TRUE; -} +} /* }}} */ -/* {{{ proto mixed SplPriorityQueue::extract() U +/* {{{ proto mixed SplPriorityQueue::extract() extract the element out of the top of the priority queue */ SPL_METHOD(SplPriorityQueue, extract) { - zval *value, *value_out, **value_out_pp; + zval value, *value_out; spl_heap_object *intern; if (zend_parse_parameters_none() == FAILURE) { return; } - intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_SPLHEAP_P(getThis()); if (intern->heap->flags & SPL_HEAP_CORRUPTED) { - zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0); return; } - value = (zval *)spl_ptr_heap_delete_top(intern->heap, getThis() TSRMLS_CC); + spl_ptr_heap_delete_top(intern->heap, &value, getThis()); - if (!value) { - zend_throw_exception(spl_ce_RuntimeException, "Can't extract from an empty heap", 0 TSRMLS_CC); + if (Z_ISUNDEF(value)) { + zend_throw_exception(spl_ce_RuntimeException, "Can't extract from an empty heap", 0); return; } - value_out_pp = spl_pqueue_extract_helper(&value, intern->flags); - + value_out = spl_pqueue_extract_helper(&value, intern->flags); - if (!value_out_pp) { + if (!value_out) { zend_error(E_RECOVERABLE_ERROR, "Unable to extract from the PriorityQueue node"); zval_ptr_dtor(&value); return; } - value_out = *value_out_pp; - - Z_ADDREF_P(value_out); + ZVAL_DEREF(value_out); + ZVAL_COPY(return_value, value_out); zval_ptr_dtor(&value); - - RETURN_ZVAL(value_out, 1, 1); -} +} /* }}} */ -/* {{{ proto mixed SplPriorityQueue::top() U +/* {{{ proto mixed SplPriorityQueue::top() Peek at the top element of the priority queue */ SPL_METHOD(SplPriorityQueue, top) { - zval *value, **value_out; + zval *value, *value_out; spl_heap_object *intern; if (zend_parse_parameters_none() == FAILURE) { return; } - intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_SPLHEAP_P(getThis()); if (intern->heap->flags & SPL_HEAP_CORRUPTED) { - zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0); return; } - value = (zval *)spl_ptr_heap_top(intern->heap); + value = spl_ptr_heap_top(intern->heap); if (!value) { - zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty heap", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty heap", 0); return; } - value_out = spl_pqueue_extract_helper(&value, intern->flags); + value_out = spl_pqueue_extract_helper(value, intern->flags); if (!value_out) { zend_error(E_RECOVERABLE_ERROR, "Unable to extract from the PriorityQueue node"); return; } - RETURN_ZVAL(*value_out, 1, 0); + ZVAL_DEREF(value_out); + ZVAL_COPY(return_value, value_out); } /* }}} */ -/* {{{ proto int SplPriorityQueue::setIteratorMode($flags) U + +/* {{{ proto int SplPriorityQueue::setExtractFlags(int flags) Set the flags of extraction*/ SPL_METHOD(SplPriorityQueue, setExtractFlags) { - long value; + zend_long value; spl_heap_object *intern; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &value) == FAILURE) { return; } - intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_SPLHEAP_P(getThis()); intern->flags = value & SPL_PQUEUE_EXTR_MASK; @@ -797,7 +751,23 @@ SPL_METHOD(SplPriorityQueue, setExtractFlags) } /* }}} */ -/* {{{ proto int SplHeap::recoverFromCorruption() U +/* {{{ proto int SplPriorityQueue::getExtractFlags() + Get the flags of extraction*/ +SPL_METHOD(SplPriorityQueue, getExtractFlags) +{ + spl_heap_object *intern; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + intern = Z_SPLHEAP_P(getThis()); + + RETURN_LONG(intern->flags); +} +/* }}} */ + +/* {{{ proto int SplHeap::recoverFromCorruption() Recover from a corrupted state*/ SPL_METHOD(SplHeap, recoverFromCorruption) { @@ -807,7 +777,7 @@ SPL_METHOD(SplHeap, recoverFromCorruption) return; } - intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_SPLHEAP_P(getThis()); intern->heap->flags = intern->heap->flags & ~SPL_HEAP_CORRUPTED; @@ -815,21 +785,37 @@ SPL_METHOD(SplHeap, recoverFromCorruption) } /* }}} */ -/* {{{ proto bool SplPriorityQueue::compare(mixed $a, mixed $b) U +/* {{{ proto int SplHeap::isCorrupted() + Tells if the heap is in a corrupted state*/ +SPL_METHOD(SplHeap, isCorrupted) +{ + spl_heap_object *intern; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + intern = Z_SPLHEAP_P(getThis()); + + RETURN_BOOL(intern->heap->flags & SPL_HEAP_CORRUPTED); +} +/* }}} */ + +/* {{{ proto bool SplPriorityQueue::compare(mixed $a, mixed $b) compare the priorities */ SPL_METHOD(SplPriorityQueue, compare) { zval *a, *b; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a, &b) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &a, &b) == FAILURE) { return; } - RETURN_LONG(spl_ptr_heap_zval_max_cmp(a, b, NULL TSRMLS_CC)); -} + RETURN_LONG(spl_ptr_heap_zval_max_cmp(a, b, NULL)); +} /* }}} */ -/* {{{ proto mixed SplHeap::top() U +/* {{{ proto mixed SplHeap::top() Peek at the top element of the heap */ SPL_METHOD(SplHeap, top) { @@ -840,182 +826,176 @@ SPL_METHOD(SplHeap, top) return; } - intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_SPLHEAP_P(getThis()); if (intern->heap->flags & SPL_HEAP_CORRUPTED) { - zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0); return; } - value = (zval *)spl_ptr_heap_top(intern->heap); + value = spl_ptr_heap_top(intern->heap); if (!value) { - zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty heap", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty heap", 0); return; } - RETURN_ZVAL(value, 1, 0); + ZVAL_DEREF(value); + ZVAL_COPY(return_value, value); } /* }}} */ -/* {{{ proto bool SplMinHeap::compare(mixed $a, mixed $b) U +/* {{{ proto bool SplMinHeap::compare(mixed $a, mixed $b) compare the values */ SPL_METHOD(SplMinHeap, compare) { zval *a, *b; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a, &b) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &a, &b) == FAILURE) { return; } - RETURN_LONG(spl_ptr_heap_zval_min_cmp(a, b, NULL TSRMLS_CC)); -} + RETURN_LONG(spl_ptr_heap_zval_min_cmp(a, b, NULL)); +} /* }}} */ -/* {{{ proto bool SplMaxHeap::compare(mixed $a, mixed $b) U +/* {{{ proto bool SplMaxHeap::compare(mixed $a, mixed $b) compare the values */ SPL_METHOD(SplMaxHeap, compare) { zval *a, *b; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a, &b) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &a, &b) == FAILURE) { return; } - RETURN_LONG(spl_ptr_heap_zval_max_cmp(a, b, NULL TSRMLS_CC)); -} + RETURN_LONG(spl_ptr_heap_zval_max_cmp(a, b, NULL)); +} /* }}} */ -static void spl_heap_it_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ +static void spl_heap_it_dtor(zend_object_iterator *iter) /* {{{ */ { spl_heap_it *iterator = (spl_heap_it *)iter; - zend_user_it_invalidate_current(iter TSRMLS_CC); - zval_ptr_dtor((zval**)&iterator->intern.it.data); - - efree(iterator); + zend_user_it_invalidate_current(iter); + zval_ptr_dtor(&iterator->intern.it.data); } /* }}} */ -static void spl_heap_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ +static void spl_heap_it_rewind(zend_object_iterator *iter) /* {{{ */ { /* do nothing, the iterator always points to the top element */ } /* }}} */ -static int spl_heap_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ +static int spl_heap_it_valid(zend_object_iterator *iter) /* {{{ */ { - spl_heap_it *iterator = (spl_heap_it *)iter; - - return (iterator->object->heap->count != 0 ? SUCCESS : FAILURE); + return ((Z_SPLHEAP_P(&iter->data))->heap->count != 0 ? SUCCESS : FAILURE); } /* }}} */ -static void spl_heap_it_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */ +static zval *spl_heap_it_get_current_data(zend_object_iterator *iter) /* {{{ */ { - spl_heap_it *iterator = (spl_heap_it *)iter; - zval **element = (zval **)&iterator->object->heap->elements[0]; + spl_heap_object *object = Z_SPLHEAP_P(&iter->data); + zval *element = &object->heap->elements[0]; - if (iterator->object->heap->flags & SPL_HEAP_CORRUPTED) { - zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC); - return; + if (object->heap->flags & SPL_HEAP_CORRUPTED) { + zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0); + return NULL; } - if (iterator->object->heap->count == 0 || !*element) { - *data = NULL; + if (object->heap->count == 0 || Z_ISUNDEF_P(element)) { + return NULL; } else { - *data = element; + return element; } } /* }}} */ -static void spl_pqueue_it_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */ +static zval *spl_pqueue_it_get_current_data(zend_object_iterator *iter) /* {{{ */ { - spl_heap_it *iterator = (spl_heap_it *)iter; - zval **element = (zval **)&iterator->object->heap->elements[0]; + spl_heap_object *object = Z_SPLHEAP_P(&iter->data); + zval *element = &object->heap->elements[0]; - if (iterator->object->heap->flags & SPL_HEAP_CORRUPTED) { - zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC); - return; + if (object->heap->flags & SPL_HEAP_CORRUPTED) { + zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0); + return NULL; } - if (iterator->object->heap->count == 0 || !*element) { - *data = NULL; + if (object->heap->count == 0 || Z_ISUNDEF_P(element)) { + return NULL; } else { - *data = spl_pqueue_extract_helper(element, iterator->object->flags); - if (!*data) { + zval *data = spl_pqueue_extract_helper(element, object->flags); + if (!data) { zend_error(E_RECOVERABLE_ERROR, "Unable to extract from the PriorityQueue node"); } + return data; } } /* }}} */ -static void spl_heap_it_get_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) /* {{{ */ +static void spl_heap_it_get_current_key(zend_object_iterator *iter, zval *key) /* {{{ */ { - spl_heap_it *iterator = (spl_heap_it *)iter; + spl_heap_object *object = Z_SPLHEAP_P(&iter->data); - ZVAL_LONG(key, iterator->object->heap->count - 1); + ZVAL_LONG(key, object->heap->count - 1); } /* }}} */ -static void spl_heap_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ +static void spl_heap_it_move_forward(zend_object_iterator *iter) /* {{{ */ { - zval *object = (zval*)((zend_user_iterator *)iter)->it.data; - spl_heap_it *iterator = (spl_heap_it *)iter; - spl_ptr_heap_element elem; + spl_heap_object *object = Z_SPLHEAP_P(&iter->data); + zval elem; - if (iterator->object->heap->flags & SPL_HEAP_CORRUPTED) { - zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0 TSRMLS_CC); + if (object->heap->flags & SPL_HEAP_CORRUPTED) { + zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0); return; } - elem = spl_ptr_heap_delete_top(iterator->object->heap, object TSRMLS_CC); + spl_ptr_heap_delete_top(object->heap, &elem, &iter->data); - if (elem != NULL) { - zval_ptr_dtor((zval **)&elem); - } + zval_ptr_dtor(&elem); - zend_user_it_invalidate_current(iter TSRMLS_CC); + zend_user_it_invalidate_current(iter); } /* }}} */ -/* {{{ proto int SplHeap::key() U +/* {{{ proto int SplHeap::key() Return current array key */ SPL_METHOD(SplHeap, key) { - spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_heap_object *intern = Z_SPLHEAP_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; - } - + } + RETURN_LONG(intern->heap->count - 1); } /* }}} */ -/* {{{ proto void SplHeap::next() U +/* {{{ proto void SplHeap::next() Move to next entry */ SPL_METHOD(SplHeap, next) { - spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - spl_ptr_heap_element elem = spl_ptr_heap_delete_top(intern->heap, getThis() TSRMLS_CC); - + spl_heap_object *intern = Z_SPLHEAP_P(getThis()); + zval elem; + spl_ptr_heap_delete_top(intern->heap, &elem, getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } - if (elem != NULL) { - zval_ptr_dtor((zval **)&elem); - } + zval_ptr_dtor(&elem); } /* }}} */ -/* {{{ proto bool SplHeap::valid() U +/* {{{ proto bool SplHeap::valid() Check whether the datastructure contains more entries */ SPL_METHOD(SplHeap, valid) { - spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_heap_object *intern = Z_SPLHEAP_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1024,7 +1004,7 @@ SPL_METHOD(SplHeap, valid) } /* }}} */ -/* {{{ proto void SplHeap::rewind() U +/* {{{ proto void SplHeap::rewind() Rewind the datastructure back to the start */ SPL_METHOD(SplHeap, rewind) { @@ -1035,47 +1015,49 @@ SPL_METHOD(SplHeap, rewind) } /* }}} */ -/* {{{ proto mixed|NULL SplHeap::current() U +/* {{{ proto mixed|NULL SplHeap::current() Return current datastructure entry */ SPL_METHOD(SplHeap, current) { - spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - zval *element = (zval *)intern->heap->elements[0]; - + spl_heap_object *intern = Z_SPLHEAP_P(getThis()); + zval *element = &intern->heap->elements[0]; + if (zend_parse_parameters_none() == FAILURE) { return; } - if (!intern->heap->count || !element) { + if (!intern->heap->count || Z_ISUNDEF_P(element)) { RETURN_NULL(); } else { - RETURN_ZVAL(element, 1, 0); + ZVAL_DEREF(element); + ZVAL_COPY(return_value, element); } } /* }}} */ -/* {{{ proto mixed|NULL SplPriorityQueue::current() U +/* {{{ proto mixed|NULL SplPriorityQueue::current() Return current datastructure entry */ SPL_METHOD(SplPriorityQueue, current) { - spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - zval **element = (zval **)&intern->heap->elements[0]; - + spl_heap_object *intern = Z_SPLHEAP_P(getThis()); + zval *element = &intern->heap->elements[0]; + if (zend_parse_parameters_none() == FAILURE) { return; } - if (!intern->heap->count || !*element) { + if (!intern->heap->count || Z_ISUNDEF_P(element)) { RETURN_NULL(); } else { - zval **data = spl_pqueue_extract_helper(element, intern->flags); + zval *data = spl_pqueue_extract_helper(element, intern->flags); if (!data) { zend_error(E_RECOVERABLE_ERROR, "Unable to extract from the PriorityQueue node"); RETURN_NULL(); } - RETURN_ZVAL(*data, 1, 0); + ZVAL_DEREF(data); + ZVAL_COPY(return_value, data); } } /* }}} */ @@ -1099,51 +1081,52 @@ zend_object_iterator_funcs spl_pqueue_it_funcs = { spl_heap_it_rewind }; -zend_object_iterator *spl_heap_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */ +zend_object_iterator *spl_heap_get_iterator(zend_class_entry *ce, zval *object, int by_ref) /* {{{ */ { spl_heap_it *iterator; - spl_heap_object *heap_object = (spl_heap_object*)zend_object_store_get_object(object TSRMLS_CC); + spl_heap_object *heap_object = Z_SPLHEAP_P(object); if (by_ref) { - zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0); return NULL; } - Z_ADDREF_P(object); + iterator = emalloc(sizeof(spl_heap_it)); - iterator = emalloc(sizeof(spl_heap_it)); - iterator->intern.it.data = (void*)object; + zend_iterator_init(&iterator->intern.it); + + ZVAL_COPY(&iterator->intern.it.data, object); iterator->intern.it.funcs = &spl_heap_it_funcs; iterator->intern.ce = ce; - iterator->intern.value = NULL; iterator->flags = heap_object->flags; - iterator->object = heap_object; + ZVAL_UNDEF(&iterator->intern.value); - return (zend_object_iterator*)iterator; + return &iterator->intern.it; } /* }}} */ -zend_object_iterator *spl_pqueue_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */ +zend_object_iterator *spl_pqueue_get_iterator(zend_class_entry *ce, zval *object, int by_ref) /* {{{ */ { spl_heap_it *iterator; - spl_heap_object *heap_object = (spl_heap_object*)zend_object_store_get_object(object TSRMLS_CC); + spl_heap_object *heap_object = Z_SPLHEAP_P(object); if (by_ref) { - zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0); return NULL; } - Z_ADDREF_P(object); + iterator = emalloc(sizeof(spl_heap_it)); + + zend_iterator_init((zend_object_iterator*)iterator); - iterator = emalloc(sizeof(spl_heap_it)); - iterator->intern.it.data = (void*)object; + ZVAL_COPY(&iterator->intern.it.data, object); iterator->intern.it.funcs = &spl_pqueue_it_funcs; iterator->intern.ce = ce; - iterator->intern.value = NULL; iterator->flags = heap_object->flags; - iterator->object = heap_object; - return (zend_object_iterator*)iterator; + ZVAL_UNDEF(&iterator->intern.value); + + return &iterator->intern.it; } /* }}} */ @@ -1181,6 +1164,7 @@ static const zend_function_entry spl_funcs_SplPriorityQueue[] = { SPL_ME(SplPriorityQueue, compare, arginfo_heap_compare, ZEND_ACC_PUBLIC) SPL_ME(SplPriorityQueue, insert, arginfo_pqueue_insert, ZEND_ACC_PUBLIC) SPL_ME(SplPriorityQueue, setExtractFlags, arginfo_pqueue_setflags, ZEND_ACC_PUBLIC) + SPL_ME(SplPriorityQueue, getExtractFlags, arginfo_splheap_void, ZEND_ACC_PUBLIC) SPL_ME(SplPriorityQueue, top, arginfo_splheap_void, ZEND_ACC_PUBLIC) SPL_ME(SplPriorityQueue, extract, arginfo_splheap_void, ZEND_ACC_PUBLIC) SPL_ME(SplHeap, count, arginfo_splheap_void, ZEND_ACC_PUBLIC) @@ -1191,6 +1175,7 @@ static const zend_function_entry spl_funcs_SplPriorityQueue[] = { SPL_ME(SplHeap, next, arginfo_splheap_void, ZEND_ACC_PUBLIC) SPL_ME(SplHeap, valid, arginfo_splheap_void, ZEND_ACC_PUBLIC) SPL_ME(SplHeap, recoverFromCorruption, arginfo_splheap_void, ZEND_ACC_PUBLIC) + SPL_ME(SplHeap, isCorrupted, arginfo_splheap_void, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} }; @@ -1206,6 +1191,7 @@ static const zend_function_entry spl_funcs_SplHeap[] = { SPL_ME(SplHeap, next, arginfo_splheap_void, ZEND_ACC_PUBLIC) SPL_ME(SplHeap, valid, arginfo_splheap_void, ZEND_ACC_PUBLIC) SPL_ME(SplHeap, recoverFromCorruption, arginfo_splheap_void, ZEND_ACC_PUBLIC) + SPL_ME(SplHeap, isCorrupted, arginfo_splheap_void, ZEND_ACC_PUBLIC) ZEND_FENTRY(compare, NULL, NULL, ZEND_ACC_PROTECTED|ZEND_ACC_ABSTRACT) {NULL, NULL, NULL} }; @@ -1216,9 +1202,13 @@ PHP_MINIT_FUNCTION(spl_heap) /* {{{ */ REGISTER_SPL_STD_CLASS_EX(SplHeap, spl_heap_object_new, spl_funcs_SplHeap); memcpy(&spl_handler_SplHeap, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + spl_handler_SplHeap.offset = XtOffsetOf(spl_heap_object, std); spl_handler_SplHeap.clone_obj = spl_heap_object_clone; spl_handler_SplHeap.count_elements = spl_heap_object_count_elements; spl_handler_SplHeap.get_debug_info = spl_heap_object_get_debug_info; + spl_handler_SplHeap.get_gc = spl_heap_object_get_gc; + spl_handler_SplHeap.dtor_obj = zend_objects_destroy_object; + spl_handler_SplHeap.free_obj = spl_heap_object_free_storage; REGISTER_SPL_IMPLEMENTS(SplHeap, Iterator); REGISTER_SPL_IMPLEMENTS(SplHeap, Countable); @@ -1234,9 +1224,13 @@ PHP_MINIT_FUNCTION(spl_heap) /* {{{ */ REGISTER_SPL_STD_CLASS_EX(SplPriorityQueue, spl_heap_object_new, spl_funcs_SplPriorityQueue); memcpy(&spl_handler_SplPriorityQueue, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + spl_handler_SplPriorityQueue.offset = XtOffsetOf(spl_heap_object, std); spl_handler_SplPriorityQueue.clone_obj = spl_heap_object_clone; spl_handler_SplPriorityQueue.count_elements = spl_heap_object_count_elements; spl_handler_SplPriorityQueue.get_debug_info = spl_pqueue_object_get_debug_info; + spl_handler_SplPriorityQueue.get_gc = spl_heap_object_get_gc; + spl_handler_SplPriorityQueue.dtor_obj = zend_objects_destroy_object; + spl_handler_SplPriorityQueue.free_obj = spl_heap_object_free_storage; REGISTER_SPL_IMPLEMENTS(SplPriorityQueue, Iterator); REGISTER_SPL_IMPLEMENTS(SplPriorityQueue, Countable); diff --git a/ext/spl/spl_heap.h b/ext/spl/spl_heap.h index 4416a978c6..99bf19f278 100644 --- a/ext/spl/spl_heap.h +++ b/ext/spl/spl_heap.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index c6181d922d..8ff3427011 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -35,7 +35,7 @@ #include "spl_directory.h" #include "spl_array.h" #include "spl_exceptions.h" -#include "ext/standard/php_smart_str.h" +#include "zend_smart_str.h" #ifdef accept #undef accept @@ -95,13 +95,12 @@ typedef enum { typedef struct _spl_sub_iterator { zend_object_iterator *iterator; - zval *zobject; + zval zobject; zend_class_entry *ce; RecursiveIteratorState state; } spl_sub_iterator; typedef struct _spl_recursive_it_object { - zend_object std; spl_sub_iterator *iterators; int level; RecursiveIteratorMode mode; @@ -118,59 +117,75 @@ typedef struct _spl_recursive_it_object { zend_class_entry *ce; smart_str prefix[6]; smart_str postfix[1]; + zend_object std; } spl_recursive_it_object; typedef struct _spl_recursive_it_iterator { zend_object_iterator intern; - zval *zobject; } spl_recursive_it_iterator; static zend_object_handlers spl_handlers_rec_it_it; static zend_object_handlers spl_handlers_dual_it; -#define SPL_FETCH_AND_CHECK_DUAL_IT(var, objzval) \ +static inline spl_recursive_it_object *spl_recursive_it_from_obj(zend_object *obj) /* {{{ */ { + return (spl_recursive_it_object*)((char*)(obj) - XtOffsetOf(spl_recursive_it_object, std)); +} +/* }}} */ + +#define Z_SPLRECURSIVE_IT_P(zv) spl_recursive_it_from_obj(Z_OBJ_P((zv))) + +#define SPL_FETCH_AND_CHECK_DUAL_IT(var, objzval) \ + do { \ + spl_dual_it_object *it = Z_SPLDUAL_IT_P(objzval); \ + if (it->dit_type == DIT_Unknown) { \ + zend_throw_exception_ex(spl_ce_LogicException, 0, \ + "The object is in an invalid state as the parent constructor was not called"); \ + return; \ + } \ + (var) = it; \ + } while (0) + +#define SPL_FETCH_SUB_ELEMENT(var, object, element) \ do { \ - spl_dual_it_object *it = zend_object_store_get_object((objzval) TSRMLS_CC); \ - if (it->dit_type == DIT_Unknown) { \ - zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, \ + if(!(object)->iterators) { \ + zend_throw_exception_ex(spl_ce_LogicException, 0, \ "The object is in an invalid state as the parent constructor was not called"); \ return; \ } \ - (var) = it; \ + (var) = (object)->iterators[(object)->level].element; \ } while (0) -#define SPL_FETCH_SUB_ELEMENT(var, object, element) \ +#define SPL_FETCH_SUB_ELEMENT_ADDR(var, object, element) \ do { \ if(!(object)->iterators) { \ - zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, \ + zend_throw_exception_ex(spl_ce_LogicException, 0, \ "The object is in an invalid state as the parent constructor was not called"); \ return; \ } \ - (var) = (object)->iterators[(object)->level].element; \ + (var) = &(object)->iterators[(object)->level].element; \ } while (0) #define SPL_FETCH_SUB_ITERATOR(var, object) SPL_FETCH_SUB_ELEMENT(var, object, iterator) -static void spl_recursive_it_dtor(zend_object_iterator *_iter TSRMLS_DC) +static void spl_recursive_it_dtor(zend_object_iterator *_iter) { spl_recursive_it_iterator *iter = (spl_recursive_it_iterator*)_iter; - spl_recursive_it_object *object = (spl_recursive_it_object*)_iter->data; + spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(&iter->intern.data); zend_object_iterator *sub_iter; while (object->level > 0) { sub_iter = object->iterators[object->level].iterator; - sub_iter->funcs->dtor(sub_iter TSRMLS_CC); + zend_iterator_dtor(sub_iter); zval_ptr_dtor(&object->iterators[object->level--].zobject); } object->iterators = erealloc(object->iterators, sizeof(spl_sub_iterator)); object->level = 0; - zval_ptr_dtor(&iter->zobject); - efree(iter); + zval_ptr_dtor(&iter->intern.data); } -static int spl_recursive_it_valid_ex(spl_recursive_it_object *object, zval *zthis TSRMLS_DC) +static int spl_recursive_it_valid_ex(spl_recursive_it_object *object, zval *zthis) { zend_object_iterator *sub_iter; int level = object->level; @@ -180,51 +195,49 @@ static int spl_recursive_it_valid_ex(spl_recursive_it_object *object, zval *zthi } while (level >=0) { sub_iter = object->iterators[level].iterator; - if (sub_iter->funcs->valid(sub_iter TSRMLS_CC) == SUCCESS) { + if (sub_iter->funcs->valid(sub_iter) == SUCCESS) { return SUCCESS; } level--; } if (object->endIteration && object->in_iteration) { - zend_call_method_with_0_params(&zthis, object->ce, &object->endIteration, "endIteration", NULL); + zend_call_method_with_0_params(zthis, object->ce, &object->endIteration, "endIteration", NULL); } object->in_iteration = 0; return FAILURE; } -static int spl_recursive_it_valid(zend_object_iterator *iter TSRMLS_DC) +static int spl_recursive_it_valid(zend_object_iterator *iter) { - spl_recursive_it_object *object = (spl_recursive_it_object*)iter->data; - - return spl_recursive_it_valid_ex(object, ((spl_recursive_it_iterator*)iter)->zobject TSRMLS_CC); + return spl_recursive_it_valid_ex(Z_SPLRECURSIVE_IT_P(&iter->data), &iter->data); } -static void spl_recursive_it_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) +static zval *spl_recursive_it_get_current_data(zend_object_iterator *iter) { - spl_recursive_it_object *object = (spl_recursive_it_object*)iter->data; - zend_object_iterator *sub_iter = object->iterators[object->level].iterator; - - sub_iter->funcs->get_current_data(sub_iter, data TSRMLS_CC); + spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(&iter->data); + zend_object_iterator *sub_iter = object->iterators[object->level].iterator; + + return sub_iter->funcs->get_current_data(sub_iter); } -static void spl_recursive_it_get_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC) +static void spl_recursive_it_get_current_key(zend_object_iterator *iter, zval *key) { - spl_recursive_it_object *object = (spl_recursive_it_object*)iter->data; - zend_object_iterator *sub_iter = object->iterators[object->level].iterator; + spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(&iter->data); + zend_object_iterator *sub_iter = object->iterators[object->level].iterator; if (sub_iter->funcs->get_current_key) { - sub_iter->funcs->get_current_key(sub_iter, key TSRMLS_CC); + sub_iter->funcs->get_current_key(sub_iter, key); } else { ZVAL_LONG(key, iter->index); } } -static void spl_recursive_it_move_forward_ex(spl_recursive_it_object *object, zval *zthis TSRMLS_DC) +static void spl_recursive_it_move_forward_ex(spl_recursive_it_object *object, zval *zthis) { zend_object_iterator *iterator; zval *zobject; zend_class_entry *ce; - zval *retval, *child; + zval retval, child; zend_object_iterator *sub_iter; int has_children; @@ -235,39 +248,39 @@ next_step: iterator = object->iterators[object->level].iterator; switch (object->iterators[object->level].state) { case RS_NEXT: - iterator->funcs->move_forward(iterator TSRMLS_CC); + iterator->funcs->move_forward(iterator); if (EG(exception)) { if (!(object->flags & RIT_CATCH_GET_CHILD)) { return; } else { - zend_clear_exception(TSRMLS_C); + zend_clear_exception(); } } /* fall through */ case RS_START: - if (iterator->funcs->valid(iterator TSRMLS_CC) == FAILURE) { + if (iterator->funcs->valid(iterator) == FAILURE) { break; } - object->iterators[object->level].state = RS_TEST; + object->iterators[object->level].state = RS_TEST; /* break; */ case RS_TEST: ce = object->iterators[object->level].ce; - zobject = object->iterators[object->level].zobject; + zobject = &object->iterators[object->level].zobject; if (object->callHasChildren) { - zend_call_method_with_0_params(&zthis, object->ce, &object->callHasChildren, "callHasChildren", &retval); + zend_call_method_with_0_params(zthis, object->ce, &object->callHasChildren, "callHasChildren", &retval); } else { - zend_call_method_with_0_params(&zobject, ce, NULL, "haschildren", &retval); + zend_call_method_with_0_params(zobject, ce, NULL, "haschildren", &retval); } if (EG(exception)) { if (!(object->flags & RIT_CATCH_GET_CHILD)) { object->iterators[object->level].state = RS_NEXT; return; } else { - zend_clear_exception(TSRMLS_C); + zend_clear_exception(); } } - if (retval) { - has_children = zend_is_true(retval); + if (Z_TYPE(retval) != IS_UNDEF) { + has_children = zend_is_true(&retval); zval_ptr_dtor(&retval); if (has_children) { if (object->max_depth == -1 || object->max_depth > object->level) { @@ -291,20 +304,20 @@ next_step: } } if (object->nextElement) { - zend_call_method_with_0_params(&zthis, object->ce, &object->nextElement, "nextelement", NULL); + zend_call_method_with_0_params(zthis, object->ce, &object->nextElement, "nextelement", NULL); } object->iterators[object->level].state = RS_NEXT; if (EG(exception)) { if (!(object->flags & RIT_CATCH_GET_CHILD)) { return; } else { - zend_clear_exception(TSRMLS_C); + zend_clear_exception(); } } return /* self */; case RS_SELF: if (object->nextElement && (object->mode == RIT_SELF_FIRST || object->mode == RIT_CHILD_FIRST)) { - zend_call_method_with_0_params(&zthis, object->ce, &object->nextElement, "nextelement", NULL); + zend_call_method_with_0_params(zthis, object->ce, &object->nextElement, "nextelement", NULL); } if (object->mode == RIT_SELF_FIRST) { object->iterators[object->level].state = RS_CHILD; @@ -314,55 +327,52 @@ next_step: return /* self */; case RS_CHILD: ce = object->iterators[object->level].ce; - zobject = object->iterators[object->level].zobject; + zobject = &object->iterators[object->level].zobject; if (object->callGetChildren) { - zend_call_method_with_0_params(&zthis, object->ce, &object->callGetChildren, "callGetChildren", &child); + zend_call_method_with_0_params(zthis, object->ce, &object->callGetChildren, "callGetChildren", &child); } else { - zend_call_method_with_0_params(&zobject, ce, NULL, "getchildren", &child); + zend_call_method_with_0_params(zobject, ce, NULL, "getchildren", &child); } if (EG(exception)) { if (!(object->flags & RIT_CATCH_GET_CHILD)) { return; } else { - zend_clear_exception(TSRMLS_C); - if (child) { - zval_ptr_dtor(&child); - } + zend_clear_exception(); + zval_ptr_dtor(&child); object->iterators[object->level].state = RS_NEXT; goto next_step; } } - ce = child && Z_TYPE_P(child) == IS_OBJECT ? Z_OBJCE_P(child) : NULL; - if (!ce || !instanceof_function(ce, spl_ce_RecursiveIterator TSRMLS_CC)) { - if (child) { - zval_ptr_dtor(&child); - } - zend_throw_exception(spl_ce_UnexpectedValueException, "Objects returned by RecursiveIterator::getChildren() must implement RecursiveIterator", 0 TSRMLS_CC); + if (Z_TYPE(child) == IS_UNDEF || Z_TYPE(child) != IS_OBJECT || + !((ce = Z_OBJCE(child)) && instanceof_function(ce, spl_ce_RecursiveIterator))) { + zval_ptr_dtor(&child); + zend_throw_exception(spl_ce_UnexpectedValueException, "Objects returned by RecursiveIterator::getChildren() must implement RecursiveIterator", 0); return; } + if (object->mode == RIT_CHILD_FIRST) { object->iterators[object->level].state = RS_SELF; } else { object->iterators[object->level].state = RS_NEXT; } object->iterators = erealloc(object->iterators, sizeof(spl_sub_iterator) * (++object->level+1)); - sub_iter = ce->get_iterator(ce, child, 0 TSRMLS_CC); + sub_iter = ce->get_iterator(ce, &child, 0); + ZVAL_COPY_VALUE(&object->iterators[object->level].zobject, &child); object->iterators[object->level].iterator = sub_iter; - object->iterators[object->level].zobject = child; object->iterators[object->level].ce = ce; object->iterators[object->level].state = RS_START; if (sub_iter->funcs->rewind) { - sub_iter->funcs->rewind(sub_iter TSRMLS_CC); + sub_iter->funcs->rewind(sub_iter); } if (object->beginChildren) { - zend_call_method_with_0_params(&zthis, object->ce, &object->beginChildren, "beginchildren", NULL); + zend_call_method_with_0_params(zthis, object->ce, &object->beginChildren, "beginchildren", NULL); if (EG(exception)) { if (!(object->flags & RIT_CATCH_GET_CHILD)) { return; } else { - zend_clear_exception(TSRMLS_C); + zend_clear_exception(); } } } @@ -371,17 +381,17 @@ next_step: /* no more elements */ if (object->level > 0) { if (object->endChildren) { - zend_call_method_with_0_params(&zthis, object->ce, &object->endChildren, "endchildren", NULL); + zend_call_method_with_0_params(zthis, object->ce, &object->endChildren, "endchildren", NULL); if (EG(exception)) { if (!(object->flags & RIT_CATCH_GET_CHILD)) { return; } else { - zend_clear_exception(TSRMLS_C); + zend_clear_exception(); } } } if (object->level > 0) { - iterator->funcs->dtor(iterator TSRMLS_CC); + zend_iterator_dtor(iterator); zval_ptr_dtor(&object->iterators[object->level].zobject); object->level--; } @@ -391,62 +401,62 @@ next_step: } } -static void spl_recursive_it_rewind_ex(spl_recursive_it_object *object, zval *zthis TSRMLS_DC) +static void spl_recursive_it_rewind_ex(spl_recursive_it_object *object, zval *zthis) { - zend_object_iterator *sub_iter; - + zend_object_iterator *sub_iter; + SPL_FETCH_SUB_ITERATOR(sub_iter, object); while (object->level) { sub_iter = object->iterators[object->level].iterator; - sub_iter->funcs->dtor(sub_iter TSRMLS_CC); + zend_iterator_dtor(sub_iter); zval_ptr_dtor(&object->iterators[object->level--].zobject); if (!EG(exception) && (!object->endChildren || object->endChildren->common.scope != spl_ce_RecursiveIteratorIterator)) { - zend_call_method_with_0_params(&zthis, object->ce, &object->endChildren, "endchildren", NULL); + zend_call_method_with_0_params(zthis, object->ce, &object->endChildren, "endchildren", NULL); } } object->iterators = erealloc(object->iterators, sizeof(spl_sub_iterator)); object->iterators[0].state = RS_START; sub_iter = object->iterators[0].iterator; if (sub_iter->funcs->rewind) { - sub_iter->funcs->rewind(sub_iter TSRMLS_CC); + sub_iter->funcs->rewind(sub_iter); } if (!EG(exception) && object->beginIteration && !object->in_iteration) { - zend_call_method_with_0_params(&zthis, object->ce, &object->beginIteration, "beginIteration", NULL); + zend_call_method_with_0_params(zthis, object->ce, &object->beginIteration, "beginIteration", NULL); } object->in_iteration = 1; - spl_recursive_it_move_forward_ex(object, zthis TSRMLS_CC); + spl_recursive_it_move_forward_ex(object, zthis); } -static void spl_recursive_it_move_forward(zend_object_iterator *iter TSRMLS_DC) +static void spl_recursive_it_move_forward(zend_object_iterator *iter) { - spl_recursive_it_move_forward_ex((spl_recursive_it_object*)iter->data, ((spl_recursive_it_iterator*)iter)->zobject TSRMLS_CC); + spl_recursive_it_move_forward_ex(Z_SPLRECURSIVE_IT_P(&iter->data), &iter->data); } -static void spl_recursive_it_rewind(zend_object_iterator *iter TSRMLS_DC) +static void spl_recursive_it_rewind(zend_object_iterator *iter) { - spl_recursive_it_rewind_ex((spl_recursive_it_object*)iter->data, ((spl_recursive_it_iterator*)iter)->zobject TSRMLS_CC); + spl_recursive_it_rewind_ex(Z_SPLRECURSIVE_IT_P(&iter->data), &iter->data); } -static zend_object_iterator *spl_recursive_it_get_iterator(zend_class_entry *ce, zval *zobject, int by_ref TSRMLS_DC) +static zend_object_iterator *spl_recursive_it_get_iterator(zend_class_entry *ce, zval *zobject, int by_ref) { spl_recursive_it_iterator *iterator; - spl_recursive_it_object *object; + spl_recursive_it_object *object; if (by_ref) { zend_error(E_ERROR, "An iterator cannot be used with foreach by reference"); } iterator = emalloc(sizeof(spl_recursive_it_iterator)); - object = (spl_recursive_it_object*)zend_object_store_get_object(zobject TSRMLS_CC); + object = Z_SPLRECURSIVE_IT_P(zobject); if (object->iterators == NULL) { zend_error(E_ERROR, "The object to be iterated is in an invalid state: " "the parent constructor has not been called"); } - Z_ADDREF_P(zobject); - iterator->intern.data = (void*)object; + zend_iterator_init((zend_object_iterator*)iterator); + + ZVAL_COPY(&iterator->intern.data, zobject); iterator->intern.funcs = ce->iterator_funcs.funcs; - iterator->zobject = zobject; return (zend_object_iterator*)iterator; } @@ -461,43 +471,40 @@ zend_object_iterator_funcs spl_recursive_it_iterator_funcs = { static void spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *ce_base, zend_class_entry *ce_inner, recursive_it_it_type rit_type) { - zval *object = getThis(); - spl_recursive_it_object *intern; - zval *iterator; - zend_class_entry *ce_iterator; - long mode, flags; - int inc_refcount = 1; - zend_error_handling error_handling; + zval *object = getThis(); + spl_recursive_it_object *intern; + zval *iterator; + zend_class_entry *ce_iterator; + zend_long mode, flags; + zend_error_handling error_handling; + zval caching_it, aggregate_retval; - zend_replace_error_handling(EH_THROW, spl_ce_InvalidArgumentException, &error_handling TSRMLS_CC); + zend_replace_error_handling(EH_THROW, spl_ce_InvalidArgumentException, &error_handling); - switch(rit_type) { + switch (rit_type) { case RIT_RecursiveTreeIterator: { - - zval *caching_it, *caching_it_flags, *user_caching_it_flags = NULL; + zval caching_it_flags, *user_caching_it_flags = NULL; mode = RIT_SELF_FIRST; flags = RTIT_BYPASS_KEY; - if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "o|lzl", &iterator, &flags, &user_caching_it_flags, &mode) == SUCCESS) { - if (instanceof_function(Z_OBJCE_P(iterator), zend_ce_aggregate TSRMLS_CC)) { - zval *aggregate = iterator; - zend_call_method_with_0_params(&aggregate, Z_OBJCE_P(aggregate), &Z_OBJCE_P(aggregate)->iterator_funcs.zf_new_iterator, "getiterator", &iterator); - inc_refcount = 0; + if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "o|lzl", &iterator, &flags, &user_caching_it_flags, &mode) == SUCCESS) { + if (instanceof_function(Z_OBJCE_P(iterator), zend_ce_aggregate)) { + zend_call_method_with_0_params(iterator, Z_OBJCE_P(iterator), &Z_OBJCE_P(iterator)->iterator_funcs.zf_new_iterator, "getiterator", &aggregate_retval); + iterator = &aggregate_retval; + } else { + Z_ADDREF_P(iterator); } - MAKE_STD_ZVAL(caching_it_flags); if (user_caching_it_flags) { - ZVAL_ZVAL(caching_it_flags, user_caching_it_flags, 1, 0); + ZVAL_COPY(&caching_it_flags, user_caching_it_flags); } else { - ZVAL_LONG(caching_it_flags, CIT_CATCH_GET_CHILD); + ZVAL_LONG(&caching_it_flags, CIT_CATCH_GET_CHILD); } - spl_instantiate_arg_ex2(spl_ce_RecursiveCachingIterator, &caching_it, 1, iterator, caching_it_flags TSRMLS_CC); + spl_instantiate_arg_ex2(spl_ce_RecursiveCachingIterator, &caching_it, iterator, &caching_it_flags); zval_ptr_dtor(&caching_it_flags); - if (inc_refcount == 0 && iterator) { - zval_ptr_dtor(&iterator); - } - iterator = caching_it; - inc_refcount = 0; + + zval_ptr_dtor(iterator); + iterator = &caching_it; } else { iterator = NULL; } @@ -508,11 +515,12 @@ static void spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_cla mode = RIT_LEAVES_ONLY; flags = 0; - if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "o|ll", &iterator, &mode, &flags) == SUCCESS) { - if (instanceof_function(Z_OBJCE_P(iterator), zend_ce_aggregate TSRMLS_CC)) { - zval *aggregate = iterator; - zend_call_method_with_0_params(&aggregate, Z_OBJCE_P(aggregate), &Z_OBJCE_P(aggregate)->iterator_funcs.zf_new_iterator, "getiterator", &iterator); - inc_refcount = 0; + if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "o|ll", &iterator, &mode, &flags) == SUCCESS) { + if (instanceof_function(Z_OBJCE_P(iterator), zend_ce_aggregate)) { + zend_call_method_with_0_params(iterator, Z_OBJCE_P(iterator), &Z_OBJCE_P(iterator)->iterator_funcs.zf_new_iterator, "getiterator", &aggregate_retval); + iterator = &aggregate_retval; + } else { + Z_ADDREF_P(iterator); } } else { iterator = NULL; @@ -520,69 +528,67 @@ static void spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_cla break; } } - if (!iterator || !instanceof_function(Z_OBJCE_P(iterator), spl_ce_RecursiveIterator TSRMLS_CC)) { - if (iterator && !inc_refcount) { - zval_ptr_dtor(&iterator); + if (!iterator || !instanceof_function(Z_OBJCE_P(iterator), spl_ce_RecursiveIterator)) { + if (iterator) { + zval_ptr_dtor(iterator); } - zend_throw_exception(spl_ce_InvalidArgumentException, "An instance of RecursiveIterator or IteratorAggregate creating it is required", 0 TSRMLS_CC); - zend_restore_error_handling(&error_handling TSRMLS_CC); + zend_throw_exception(spl_ce_InvalidArgumentException, "An instance of RecursiveIterator or IteratorAggregate creating it is required", 0); + zend_restore_error_handling(&error_handling); return; } - intern = (spl_recursive_it_object*)zend_object_store_get_object(object TSRMLS_CC); + intern = Z_SPLRECURSIVE_IT_P(object); intern->iterators = emalloc(sizeof(spl_sub_iterator)); intern->level = 0; intern->mode = mode; - intern->flags = flags; + intern->flags = (int)flags; intern->max_depth = -1; intern->in_iteration = 0; intern->ce = Z_OBJCE_P(object); - zend_hash_find(&intern->ce->function_table, "beginiteration", sizeof("beginiteration"), (void **) &intern->beginIteration); + intern->beginIteration = zend_hash_str_find_ptr(&intern->ce->function_table, "beginiteration", sizeof("beginiteration") - 1); if (intern->beginIteration->common.scope == ce_base) { intern->beginIteration = NULL; } - zend_hash_find(&intern->ce->function_table, "enditeration", sizeof("enditeration"), (void **) &intern->endIteration); + intern->endIteration = zend_hash_str_find_ptr(&intern->ce->function_table, "enditeration", sizeof("enditeration") - 1); if (intern->endIteration->common.scope == ce_base) { intern->endIteration = NULL; } - zend_hash_find(&intern->ce->function_table, "callhaschildren", sizeof("callHasChildren"), (void **) &intern->callHasChildren); + intern->callHasChildren = zend_hash_str_find_ptr(&intern->ce->function_table, "callhaschildren", sizeof("callHasChildren") - 1); if (intern->callHasChildren->common.scope == ce_base) { intern->callHasChildren = NULL; } - zend_hash_find(&intern->ce->function_table, "callgetchildren", sizeof("callGetChildren"), (void **) &intern->callGetChildren); + intern->callGetChildren = zend_hash_str_find_ptr(&intern->ce->function_table, "callgetchildren", sizeof("callGetChildren") - 1); if (intern->callGetChildren->common.scope == ce_base) { intern->callGetChildren = NULL; } - zend_hash_find(&intern->ce->function_table, "beginchildren", sizeof("beginchildren"), (void **) &intern->beginChildren); + intern->beginChildren = zend_hash_str_find_ptr(&intern->ce->function_table, "beginchildren", sizeof("beginchildren") - 1); if (intern->beginChildren->common.scope == ce_base) { intern->beginChildren = NULL; } - zend_hash_find(&intern->ce->function_table, "endchildren", sizeof("endchildren"), (void **) &intern->endChildren); + intern->endChildren = zend_hash_str_find_ptr(&intern->ce->function_table, "endchildren", sizeof("endchildren") - 1); if (intern->endChildren->common.scope == ce_base) { intern->endChildren = NULL; } - zend_hash_find(&intern->ce->function_table, "nextelement", sizeof("nextElement"), (void **) &intern->nextElement); + intern->nextElement = zend_hash_str_find_ptr(&intern->ce->function_table, "nextelement", sizeof("nextElement") - 1); if (intern->nextElement->common.scope == ce_base) { intern->nextElement = NULL; } + ce_iterator = Z_OBJCE_P(iterator); /* respect inheritance, don't use spl_ce_RecursiveIterator */ - intern->iterators[0].iterator = ce_iterator->get_iterator(ce_iterator, iterator, 0 TSRMLS_CC); - if (inc_refcount) { - Z_ADDREF_P(iterator); - } - intern->iterators[0].zobject = iterator; + intern->iterators[0].iterator = ce_iterator->get_iterator(ce_iterator, iterator, 0); + ZVAL_COPY_VALUE(&intern->iterators[0].zobject, iterator); intern->iterators[0].ce = ce_iterator; intern->iterators[0].state = RS_START; - zend_restore_error_handling(&error_handling TSRMLS_CC); + zend_restore_error_handling(&error_handling); if (EG(exception)) { zend_object_iterator *sub_iter; while (intern->level >= 0) { sub_iter = intern->iterators[intern->level].iterator; - sub_iter->funcs->dtor(sub_iter TSRMLS_CC); + zend_iterator_dtor(sub_iter); zval_ptr_dtor(&intern->iterators[intern->level--].zobject); } efree(intern->iterators); @@ -601,33 +607,33 @@ SPL_METHOD(RecursiveIteratorIterator, __construct) Rewind the iterator to the first element of the top level inner iterator. */ SPL_METHOD(RecursiveIteratorIterator, rewind) { - spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } - spl_recursive_it_rewind_ex(object, getThis() TSRMLS_CC); + spl_recursive_it_rewind_ex(object, getThis()); } /* }}} */ /* {{{ proto bool RecursiveIteratorIterator::valid() Check whether the current position is valid */ SPL_METHOD(RecursiveIteratorIterator, valid) { - spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; } - RETURN_BOOL(spl_recursive_it_valid_ex(object, getThis() TSRMLS_CC) == SUCCESS); + RETURN_BOOL(spl_recursive_it_valid_ex(object, getThis()) == SUCCESS); } /* }}} */ /* {{{ proto mixed RecursiveIteratorIterator::key() Access the current key */ SPL_METHOD(RecursiveIteratorIterator, key) { - spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis()); zend_object_iterator *iterator; if (zend_parse_parameters_none() == FAILURE) { @@ -637,7 +643,7 @@ SPL_METHOD(RecursiveIteratorIterator, key) SPL_FETCH_SUB_ITERATOR(iterator, object); if (iterator->funcs->get_current_key) { - iterator->funcs->get_current_key(iterator, return_value TSRMLS_CC); + iterator->funcs->get_current_key(iterator, return_value); } else { RETURN_NULL(); } @@ -647,19 +653,20 @@ SPL_METHOD(RecursiveIteratorIterator, key) Access the current element value */ SPL_METHOD(RecursiveIteratorIterator, current) { - spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis()); zend_object_iterator *iterator; - zval **data; - + zval *data; + if (zend_parse_parameters_none() == FAILURE) { return; } SPL_FETCH_SUB_ITERATOR(iterator, object); - iterator->funcs->get_current_data(iterator, &data TSRMLS_CC); - if (data && *data) { - RETURN_ZVAL(*data, 1, 0); + data = iterator->funcs->get_current_data(iterator); + if (data) { + ZVAL_DEREF(data); + ZVAL_COPY(return_value, data); } } /* }}} */ @@ -667,25 +674,25 @@ SPL_METHOD(RecursiveIteratorIterator, current) Move forward to the next element */ SPL_METHOD(RecursiveIteratorIterator, next) { - spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } - spl_recursive_it_move_forward_ex(object, getThis() TSRMLS_CC); + spl_recursive_it_move_forward_ex(object, getThis()); } /* }}} */ /* {{{ proto int RecursiveIteratorIterator::getDepth() Get the current depth of the recursive iteration */ SPL_METHOD(RecursiveIteratorIterator, getDepth) { - spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis()); + if (zend_parse_parameters_none() == FAILURE) { return; } - + RETURN_LONG(object->level); } /* }}} */ @@ -693,11 +700,11 @@ SPL_METHOD(RecursiveIteratorIterator, getDepth) The current active sub iterator or the iterator at specified level */ SPL_METHOD(RecursiveIteratorIterator, getSubIterator) { - spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - long level = object->level; - zval *zobject; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &level) == FAILURE) { + spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis()); + zend_long level = object->level; + zval *value; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &level) == FAILURE) { return; } if (level < 0 || level > object->level) { @@ -705,28 +712,31 @@ SPL_METHOD(RecursiveIteratorIterator, getSubIterator) } if(!object->iterators) { - zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, + zend_throw_exception_ex(spl_ce_LogicException, 0, "The object is in an invalid state as the parent constructor was not called"); return; } - RETURN_ZVAL(object->iterators[level].zobject, 1, 0); + value = &object->iterators[level].zobject; + ZVAL_DEREF(value); + ZVAL_COPY(return_value, value); } /* }}} */ /* {{{ proto RecursiveIterator RecursiveIteratorIterator::getInnerIterator() The current active sub iterator */ SPL_METHOD(RecursiveIteratorIterator, getInnerIterator) { - spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis()); zval *zobject; - + if (zend_parse_parameters_none() == FAILURE) { return; } - SPL_FETCH_SUB_ELEMENT(zobject, object, zobject); + SPL_FETCH_SUB_ELEMENT_ADDR(zobject, object, zobject); - RETURN_ZVAL(zobject, 1, 0); + ZVAL_DEREF(zobject); + ZVAL_COPY(return_value, zobject); } /* }}} */ /* {{{ proto RecursiveIterator RecursiveIteratorIterator::beginIteration() @@ -753,10 +763,10 @@ SPL_METHOD(RecursiveIteratorIterator, endIteration) Called for each element to test whether it has children */ SPL_METHOD(RecursiveIteratorIterator, callHasChildren) { - spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis()); zend_class_entry *ce; - zval *retval, *zobject; - + zval *zobject; + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -767,14 +777,12 @@ SPL_METHOD(RecursiveIteratorIterator, callHasChildren) SPL_FETCH_SUB_ELEMENT(ce, object, ce); - zobject = object->iterators[object->level].zobject; - if (!zobject) { + zobject = &object->iterators[object->level].zobject; + if (Z_TYPE_P(zobject) == IS_UNDEF) { RETURN_FALSE; } else { - zend_call_method_with_0_params(&zobject, ce, NULL, "haschildren", &retval); - if (retval) { - RETURN_ZVAL(retval, 0, 1); - } else { + zend_call_method_with_0_params(zobject, ce, NULL, "haschildren", return_value); + if (Z_TYPE_P(return_value) == IS_UNDEF) { RETURN_FALSE; } } @@ -784,23 +792,23 @@ SPL_METHOD(RecursiveIteratorIterator, callHasChildren) Return children of current element */ SPL_METHOD(RecursiveIteratorIterator, callGetChildren) { - spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis()); zend_class_entry *ce; - zval *retval, *zobject; - + zval *zobject; + if (zend_parse_parameters_none() == FAILURE) { return; } SPL_FETCH_SUB_ELEMENT(ce, object, ce); - zobject = object->iterators[object->level].zobject; - if (!zobject) { + zobject = &object->iterators[object->level].zobject; + if (Z_TYPE_P(zobject) == IS_UNDEF) { return; } else { - zend_call_method_with_0_params(&zobject, ce, NULL, "getchildren", &retval); - if (retval) { - RETURN_ZVAL(retval, 0, 1); + zend_call_method_with_0_params(zobject, ce, NULL, "getchildren", return_value); + if (Z_TYPE_P(return_value) == IS_UNDEF) { + RETURN_NULL(); } } } /* }}} */ @@ -839,29 +847,32 @@ SPL_METHOD(RecursiveIteratorIterator, nextElement) Set the maximum allowed depth (or any depth if pmax_depth = -1] */ SPL_METHOD(RecursiveIteratorIterator, setMaxDepth) { - spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - long max_depth = -1; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &max_depth) == FAILURE) { + spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis()); + zend_long max_depth = -1; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &max_depth) == FAILURE) { return; } if (max_depth < -1) { - zend_throw_exception(spl_ce_OutOfRangeException, "Parameter max_depth must be >= -1", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_OutOfRangeException, "Parameter max_depth must be >= -1", 0); return; + } else if (max_depth > INT_MAX) { + max_depth = INT_MAX; } - object->max_depth = max_depth; + + object->max_depth = (int)max_depth; } /* }}} */ /* {{{ proto int|false RecursiveIteratorIterator::getMaxDepth() Return the maximum accepted depth or false if any depth is allowed */ SPL_METHOD(RecursiveIteratorIterator, getMaxDepth) { - spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; } - + if (object->max_depth == -1) { RETURN_FALSE; } else { @@ -869,45 +880,45 @@ SPL_METHOD(RecursiveIteratorIterator, getMaxDepth) } } /* }}} */ -static union _zend_function *spl_recursive_it_get_method(zval **object_ptr, char *method, int method_len, const zend_literal *key TSRMLS_DC) +static union _zend_function *spl_recursive_it_get_method(zend_object **zobject, zend_string *method, const zval *key) { union _zend_function *function_handler; - spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(*object_ptr TSRMLS_CC); - long level = object->level; + spl_recursive_it_object *object = spl_recursive_it_from_obj(*zobject); + zend_long level = object->level; zval *zobj; if (!object->iterators) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "The %s instance wasn't initialized properly", Z_OBJCE_PP(object_ptr)->name); + php_error_docref(NULL, E_ERROR, "The %s instance wasn't initialized properly", ZSTR_VAL((*zobject)->ce->name)); } - zobj = object->iterators[level].zobject; + zobj = &object->iterators[level].zobject; - function_handler = std_object_handlers.get_method(object_ptr, method, method_len, key TSRMLS_CC); + function_handler = std_object_handlers.get_method(zobject, method, key); if (!function_handler) { - if (zend_hash_find(&Z_OBJCE_P(zobj)->function_table, method, method_len+1, (void **) &function_handler) == FAILURE) { + if ((function_handler = zend_hash_find_ptr(&Z_OBJCE_P(zobj)->function_table, method)) == NULL) { if (Z_OBJ_HT_P(zobj)->get_method) { - *object_ptr = zobj; - function_handler = Z_OBJ_HT_P(*object_ptr)->get_method(object_ptr, method, method_len, key TSRMLS_CC); + *zobject = Z_OBJ_P(zobj); + function_handler = (*zobject)->handlers->get_method(zobject, method, key); } } else { - *object_ptr = zobj; + *zobject = Z_OBJ_P(zobj); } } return function_handler; } /* {{{ spl_RecursiveIteratorIterator_dtor */ -static void spl_RecursiveIteratorIterator_dtor(zend_object *_object, zend_object_handle handle TSRMLS_DC) +static void spl_RecursiveIteratorIterator_dtor(zend_object *_object) { - spl_recursive_it_object *object = (spl_recursive_it_object *)_object; - zend_object_iterator *sub_iter; + spl_recursive_it_object *object = spl_recursive_it_from_obj(_object); + zend_object_iterator *sub_iter; /* call standard dtor */ - zend_objects_destroy_object(_object, handle TSRMLS_CC); + zend_objects_destroy_object(_object); if (object->iterators) { while (object->level >= 0) { sub_iter = object->iterators[object->level].iterator; - sub_iter->funcs->dtor(sub_iter TSRMLS_CC); + zend_iterator_dtor(sub_iter); zval_ptr_dtor(&object->iterators[object->level--].zobject); } efree(object->iterators); @@ -917,11 +928,16 @@ static void spl_RecursiveIteratorIterator_dtor(zend_object *_object, zend_object /* }}} */ /* {{{ spl_RecursiveIteratorIterator_free_storage */ -static void spl_RecursiveIteratorIterator_free_storage(void *_object TSRMLS_DC) +static void spl_RecursiveIteratorIterator_free_storage(zend_object *_object) { - spl_recursive_it_object *object = (spl_recursive_it_object *)_object; + spl_recursive_it_object *object = spl_recursive_it_from_obj(_object); + + if (object->iterators) { + efree(object->iterators); + object->iterators = NULL; + } - zend_object_std_dtor(&object->std TSRMLS_CC); + zend_object_std_dtor(&object->std); smart_str_free(&object->prefix[0]); smart_str_free(&object->prefix[1]); smart_str_free(&object->prefix[2]); @@ -930,19 +946,15 @@ static void spl_RecursiveIteratorIterator_free_storage(void *_object TSRMLS_DC) smart_str_free(&object->prefix[5]); smart_str_free(&object->postfix[0]); - - efree(object); } /* }}} */ /* {{{ spl_RecursiveIteratorIterator_new_ex */ -static zend_object_value spl_RecursiveIteratorIterator_new_ex(zend_class_entry *class_type, int init_prefix TSRMLS_DC) +static zend_object *spl_RecursiveIteratorIterator_new_ex(zend_class_entry *class_type, int init_prefix) { - zend_object_value retval; spl_recursive_it_object *intern; - intern = emalloc(sizeof(spl_recursive_it_object)); - memset(intern, 0, sizeof(spl_recursive_it_object)); + intern = ecalloc(1, sizeof(spl_recursive_it_object) + zend_object_properties_size(class_type)); if (init_prefix) { smart_str_appendl(&intern->prefix[0], "", 0); @@ -955,30 +967,29 @@ static zend_object_value spl_RecursiveIteratorIterator_new_ex(zend_class_entry * smart_str_appendl(&intern->postfix[0], "", 0); } - zend_object_std_init(&intern->std, class_type TSRMLS_CC); + zend_object_std_init(&intern->std, class_type); object_properties_init(&intern->std, class_type); - retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)spl_RecursiveIteratorIterator_dtor, (zend_objects_free_object_storage_t) spl_RecursiveIteratorIterator_free_storage, NULL TSRMLS_CC); - retval.handlers = &spl_handlers_rec_it_it; - return retval; + intern->std.handlers = &spl_handlers_rec_it_it; + return &intern->std; } /* }}} */ /* {{{ spl_RecursiveIteratorIterator_new */ -static zend_object_value spl_RecursiveIteratorIterator_new(zend_class_entry *class_type TSRMLS_DC) +static zend_object *spl_RecursiveIteratorIterator_new(zend_class_entry *class_type) { - return spl_RecursiveIteratorIterator_new_ex(class_type, 0 TSRMLS_CC); + return spl_RecursiveIteratorIterator_new_ex(class_type, 0); } /* }}} */ /* {{{ spl_RecursiveTreeIterator_new */ -static zend_object_value spl_RecursiveTreeIterator_new(zend_class_entry *class_type TSRMLS_DC) +static zend_object *spl_RecursiveTreeIterator_new(zend_class_entry *class_type) { - return spl_RecursiveIteratorIterator_new_ex(class_type, 1 TSRMLS_CC); + return spl_RecursiveIteratorIterator_new_ex(class_type, 1); } /* }}} */ -ZEND_BEGIN_ARG_INFO_EX(arginfo_recursive_it___construct, 0, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_recursive_it___construct, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, iterator, Traversable, 0) ZEND_ARG_INFO(0, mode) ZEND_ARG_INFO(0, flags) @@ -1014,65 +1025,68 @@ static const zend_function_entry spl_funcs_RecursiveIteratorIterator[] = { PHP_FE_END }; -static void spl_recursive_tree_iterator_get_prefix(spl_recursive_it_object *object, zval *return_value TSRMLS_DC) +static void spl_recursive_tree_iterator_get_prefix(spl_recursive_it_object *object, zval *return_value) { smart_str str = {0}; - zval *has_next; + zval has_next; int level; - smart_str_appendl(&str, object->prefix[0].c, object->prefix[0].len); - + smart_str_appendl(&str, ZSTR_VAL(object->prefix[0].s), ZSTR_LEN(object->prefix[0].s)); + for (level = 0; level < object->level; ++level) { zend_call_method_with_0_params(&object->iterators[level].zobject, object->iterators[level].ce, NULL, "hasnext", &has_next); - if (has_next) { - if (Z_LVAL_P(has_next)) { - smart_str_appendl(&str, object->prefix[1].c, object->prefix[1].len); + if (Z_TYPE(has_next) != IS_UNDEF) { + if (Z_TYPE(has_next) == IS_TRUE) { + smart_str_appendl(&str, ZSTR_VAL(object->prefix[1].s), ZSTR_LEN(object->prefix[1].s)); } else { - smart_str_appendl(&str, object->prefix[2].c, object->prefix[2].len); + smart_str_appendl(&str, ZSTR_VAL(object->prefix[2].s), ZSTR_LEN(object->prefix[2].s)); } zval_ptr_dtor(&has_next); } } zend_call_method_with_0_params(&object->iterators[level].zobject, object->iterators[level].ce, NULL, "hasnext", &has_next); - if (has_next) { - if (Z_LVAL_P(has_next)) { - smart_str_appendl(&str, object->prefix[3].c, object->prefix[3].len); + if (Z_TYPE(has_next) != IS_UNDEF) { + if (Z_TYPE(has_next) == IS_TRUE) { + smart_str_appendl(&str, ZSTR_VAL(object->prefix[3].s), ZSTR_LEN(object->prefix[3].s)); } else { - smart_str_appendl(&str, object->prefix[4].c, object->prefix[4].len); + smart_str_appendl(&str, ZSTR_VAL(object->prefix[4].s), ZSTR_LEN(object->prefix[4].s)); } zval_ptr_dtor(&has_next); } - smart_str_appendl(&str, object->prefix[5].c, object->prefix[5].len); + smart_str_appendl(&str, ZSTR_VAL(object->prefix[5].s), ZSTR_LEN(object->prefix[5].s)); smart_str_0(&str); - RETVAL_STRINGL(str.c, str.len, 0); + RETURN_NEW_STR(str.s); } -static void spl_recursive_tree_iterator_get_entry(spl_recursive_it_object * object, zval * return_value TSRMLS_DC) +static void spl_recursive_tree_iterator_get_entry(spl_recursive_it_object *object, zval *return_value) { zend_object_iterator *iterator = object->iterators[object->level].iterator; - zval **data; + zval *data; zend_error_handling error_handling; - iterator->funcs->get_current_data(iterator, &data TSRMLS_CC); + data = iterator->funcs->get_current_data(iterator); - zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling TSRMLS_CC); - if (data && *data) { - RETVAL_ZVAL(*data, 1, 0); - if (Z_TYPE_P(return_value) == IS_ARRAY) { - zval_dtor(return_value); - ZVAL_STRINGL(return_value, "Array", sizeof("Array")-1, 1); + /* Replace exception handling so the catchable fatal error that is thrown when a class + * without __toString is converted to string is converted into an exception. */ + zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling); + if (data) { + ZVAL_DEREF(data); + if (Z_TYPE_P(data) == IS_ARRAY) { + ZVAL_STRINGL(return_value, "Array", sizeof("Array")-1); } else { + ZVAL_COPY(return_value, data); convert_to_string(return_value); } } - zend_restore_error_handling(&error_handling TSRMLS_CC); + zend_restore_error_handling(&error_handling); } -static void spl_recursive_tree_iterator_get_postfix(spl_recursive_it_object * object, zval * return_value TSRMLS_DC) +static void spl_recursive_tree_iterator_get_postfix(spl_recursive_it_object *object, zval *return_value) { - RETVAL_STRINGL(object->postfix[0].c, object->postfix[0].len, 1); + RETVAL_STR(object->postfix[0].s); + Z_ADDREF_P(return_value); } /* {{{ proto void RecursiveTreeIterator::__construct(RecursiveIterator|IteratorAggregate it [, int flags = RTIT_BYPASS_KEY [, int cit_flags = CIT_CATCH_GET_CHILD [, mode = RIT_SELF_FIRST ]]]) throws InvalidArgumentException @@ -1086,19 +1100,20 @@ SPL_METHOD(RecursiveTreeIterator, __construct) Sets prefix parts as used in getPrefix() */ SPL_METHOD(RecursiveTreeIterator, setPrefixPart) { - spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - long part; + zend_long part; char* prefix; - int prefix_len; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &part, &prefix, &prefix_len) == FAILURE) { + size_t prefix_len; + spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis()); + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "ls", &part, &prefix, &prefix_len) == FAILURE) { return; } + if (0 > part || part > 5) { - zend_throw_exception_ex(spl_ce_OutOfRangeException, 0 TSRMLS_CC, "Use RecursiveTreeIterator::PREFIX_* constant"); + zend_throw_exception_ex(spl_ce_OutOfRangeException, 0, "Use RecursiveTreeIterator::PREFIX_* constant"); return; } - + smart_str_free(&object->prefix[part]); smart_str_appendl(&object->prefix[part], prefix, prefix_len); } /* }}} */ @@ -1107,30 +1122,30 @@ SPL_METHOD(RecursiveTreeIterator, setPrefixPart) Returns the string to place in front of current element */ SPL_METHOD(RecursiveTreeIterator, getPrefix) { - spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; } if(!object->iterators) { - zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, + zend_throw_exception_ex(spl_ce_LogicException, 0, "The object is in an invalid state as the parent constructor was not called"); return; - } - - spl_recursive_tree_iterator_get_prefix(object, return_value TSRMLS_CC); + } + + spl_recursive_tree_iterator_get_prefix(object, return_value); } /* }}} */ /* {{{ proto void RecursiveTreeIterator::setPostfix(string prefix) Sets postfix as used in getPostfix() */ SPL_METHOD(RecursiveTreeIterator, setPostfix) { - spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis()); char* postfix; - int postfix_len; + size_t postfix_len; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &postfix, &postfix_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &postfix, &postfix_len) == FAILURE) { return; } @@ -1142,86 +1157,87 @@ SPL_METHOD(RecursiveTreeIterator, setPostfix) Returns the string presentation built for current element */ SPL_METHOD(RecursiveTreeIterator, getEntry) { - spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; } if(!object->iterators) { - zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, + zend_throw_exception_ex(spl_ce_LogicException, 0, "The object is in an invalid state as the parent constructor was not called"); return; } - - spl_recursive_tree_iterator_get_entry(object, return_value TSRMLS_CC); + + spl_recursive_tree_iterator_get_entry(object, return_value); } /* }}} */ /* {{{ proto string RecursiveTreeIterator::getPostfix() Returns the string to place after the current element */ SPL_METHOD(RecursiveTreeIterator, getPostfix) { - spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; } if(!object->iterators) { - zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, + zend_throw_exception_ex(spl_ce_LogicException, 0, "The object is in an invalid state as the parent constructor was not called"); return; } - - spl_recursive_tree_iterator_get_postfix(object, return_value TSRMLS_CC); + + spl_recursive_tree_iterator_get_postfix(object, return_value); } /* }}} */ /* {{{ proto mixed RecursiveTreeIterator::current() Returns the current element prefixed and postfixed */ SPL_METHOD(RecursiveTreeIterator, current) { - spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis()); zval prefix, entry, postfix; - char *str, *ptr; - size_t str_len; - + char *ptr; + zend_string *str; + if (zend_parse_parameters_none() == FAILURE) { return; } if(!object->iterators) { - zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, + zend_throw_exception_ex(spl_ce_LogicException, 0, "The object is in an invalid state as the parent constructor was not called"); return; - } + } if (object->flags & RTIT_BYPASS_CURRENT) { - zend_object_iterator *iterator; - zval **data; + zend_object_iterator *iterator = object->iterators[object->level].iterator; + zval *data; SPL_FETCH_SUB_ITERATOR(iterator, object); - iterator->funcs->get_current_data(iterator, &data TSRMLS_CC); - if (data && *data) { - RETURN_ZVAL(*data, 1, 0); + data = iterator->funcs->get_current_data(iterator); + if (data) { + ZVAL_DEREF(data); + ZVAL_COPY(return_value, data); + return; } else { RETURN_NULL(); } } - INIT_ZVAL(prefix); - INIT_ZVAL(entry); - spl_recursive_tree_iterator_get_prefix(object, &prefix TSRMLS_CC); - spl_recursive_tree_iterator_get_entry(object, &entry TSRMLS_CC); + ZVAL_NULL(&prefix); + ZVAL_NULL(&entry); + spl_recursive_tree_iterator_get_prefix(object, &prefix); + spl_recursive_tree_iterator_get_entry(object, &entry); if (Z_TYPE(entry) != IS_STRING) { - zval_dtor(&prefix); - zval_dtor(&entry); + zval_ptr_dtor(&prefix); + zval_ptr_dtor(&entry); RETURN_NULL(); } - spl_recursive_tree_iterator_get_postfix(object, &postfix TSRMLS_CC); + spl_recursive_tree_iterator_get_postfix(object, &postfix); - str_len = Z_STRLEN(prefix) + Z_STRLEN(entry) + Z_STRLEN(postfix); - str = (char *) emalloc(str_len + 1U); - ptr = str; + str = zend_string_alloc(Z_STRLEN(prefix) + Z_STRLEN(entry) + Z_STRLEN(postfix), 0); + ptr = ZSTR_VAL(str); memcpy(ptr, Z_STRVAL(prefix), Z_STRLEN(prefix)); ptr += Z_STRLEN(prefix); @@ -1231,23 +1247,23 @@ SPL_METHOD(RecursiveTreeIterator, current) ptr += Z_STRLEN(postfix); *ptr = 0; - zval_dtor(&prefix); - zval_dtor(&entry); - zval_dtor(&postfix); + zval_ptr_dtor(&prefix); + zval_ptr_dtor(&entry); + zval_ptr_dtor(&postfix); - RETURN_STRINGL(str, str_len, 0); + RETURN_NEW_STR(str); } /* }}} */ /* {{{ proto mixed RecursiveTreeIterator::key() Returns the current key prefixed and postfixed */ SPL_METHOD(RecursiveTreeIterator, key) { - spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(getThis()); zend_object_iterator *iterator; zval prefix, key, postfix, key_copy; - char *str, *ptr; - size_t str_len; - + char *ptr; + zend_string *str; + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1255,32 +1271,27 @@ SPL_METHOD(RecursiveTreeIterator, key) SPL_FETCH_SUB_ITERATOR(iterator, object); if (iterator->funcs->get_current_key) { - iterator->funcs->get_current_key(iterator, &key TSRMLS_CC); + iterator->funcs->get_current_key(iterator, &key); } else { ZVAL_NULL(&key); } if (object->flags & RTIT_BYPASS_KEY) { - zval *key_ptr = &key; - RETVAL_ZVAL(key_ptr, 1, 0); - zval_dtor(&key); + RETVAL_ZVAL(&key, 1, 1); return; } if (Z_TYPE(key) != IS_STRING) { - int use_copy; - zend_make_printable_zval(&key, &key_copy, &use_copy); - if (use_copy) { + if (zend_make_printable_zval(&key, &key_copy)) { key = key_copy; } } - spl_recursive_tree_iterator_get_prefix(object, &prefix TSRMLS_CC); - spl_recursive_tree_iterator_get_postfix(object, &postfix TSRMLS_CC); + spl_recursive_tree_iterator_get_prefix(object, &prefix); + spl_recursive_tree_iterator_get_postfix(object, &postfix); - str_len = Z_STRLEN(prefix) + Z_STRLEN(key) + Z_STRLEN(postfix); - str = (char *) emalloc(str_len + 1U); - ptr = str; + str = zend_string_alloc(Z_STRLEN(prefix) + Z_STRLEN(key) + Z_STRLEN(postfix), 0); + ptr = ZSTR_VAL(str); memcpy(ptr, Z_STRVAL(prefix), Z_STRLEN(prefix)); ptr += Z_STRLEN(prefix); @@ -1290,14 +1301,14 @@ SPL_METHOD(RecursiveTreeIterator, key) ptr += Z_STRLEN(postfix); *ptr = 0; - zval_dtor(&prefix); - zval_dtor(&key); - zval_dtor(&postfix); + zval_ptr_dtor(&prefix); + zval_ptr_dtor(&key); + zval_ptr_dtor(&postfix); - RETVAL_STRINGL(str, str_len, 0); + RETURN_NEW_STR(str); } /* }}} */ -ZEND_BEGIN_ARG_INFO_EX(arginfo_recursive_tree_it___construct, 0, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_recursive_tree_it___construct, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, iterator, Traversable, 0) ZEND_ARG_INFO(0, flags) ZEND_ARG_INFO(0, caching_it_flags) @@ -1332,7 +1343,7 @@ static const zend_function_entry spl_funcs_RecursiveTreeIterator[] = { }; #if MBO_0 -static int spl_dual_it_gets_implemented(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC) +static int spl_dual_it_gets_implemented(zend_class_entry *interface, zend_class_entry *class_type) { class_type->iterator_funcs.zf_valid = NULL; class_type->iterator_funcs.zf_current = NULL; @@ -1347,22 +1358,22 @@ static int spl_dual_it_gets_implemented(zend_class_entry *interface, zend_class_ } #endif -static union _zend_function *spl_dual_it_get_method(zval **object_ptr, char *method, int method_len, const zend_literal *key TSRMLS_DC) +static union _zend_function *spl_dual_it_get_method(zend_object **object, zend_string *method, const zval *key) { union _zend_function *function_handler; spl_dual_it_object *intern; - intern = (spl_dual_it_object*)zend_object_store_get_object(*object_ptr TSRMLS_CC); + intern = spl_dual_it_from_obj(*object); - function_handler = std_object_handlers.get_method(object_ptr, method, method_len, key TSRMLS_CC); + function_handler = std_object_handlers.get_method(object, method, key); if (!function_handler && intern->inner.ce) { - if (zend_hash_find(&intern->inner.ce->function_table, method, method_len+1, (void **) &function_handler) == FAILURE) { - if (Z_OBJ_HT_P(intern->inner.zobject)->get_method) { - *object_ptr = intern->inner.zobject; - function_handler = Z_OBJ_HT_P(*object_ptr)->get_method(object_ptr, method, method_len, key TSRMLS_CC); + if ((function_handler = zend_hash_find_ptr(&intern->inner.ce->function_table, method)) == NULL) { + if (Z_OBJ_HT(intern->inner.zobject)->get_method) { + *object = Z_OBJ(intern->inner.zobject); + function_handler = (*object)->handlers->get_method(object, method, key); } } else { - *object_ptr = intern->inner.zobject; + *object = Z_OBJ(intern->inner.zobject); } } return function_handler; @@ -1372,23 +1383,23 @@ static union _zend_function *spl_dual_it_get_method(zval **object_ptr, char *met int spl_dual_it_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS) { zval ***func_params, func; - zval *retval_ptr; + zval retval; int arg_count; int current = 0; int success; void **p; spl_dual_it_object *intern; - intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_SPLDUAL_IT_P(getThis()); ZVAL_STRING(&func, method, 0); - if (!zend_is_callable(&func, 0, &method TSRMLS_CC)) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "Method %s::%s() does not exist", intern->inner.ce->name, method); + if (!zend_is_callable(&func, 0, &method)) { + php_error_docref(NULL, E_ERROR, "Method %s::%s() does not exist", intern->inner.ce->name, method); return FAILURE; } p = EG(argument_stack).top_element-2; - arg_count = (ulong) *p; + arg_count = (zend_ulong) *p; func_params = safe_emalloc(sizeof(zval **), arg_count, 0); @@ -1399,135 +1410,120 @@ int spl_dual_it_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS) } arg_count = current; /* restore */ - if (call_user_function_ex(EG(function_table), NULL, &func, &retval_ptr, arg_count, func_params, 0, NULL TSRMLS_CC) == SUCCESS && retval_ptr) { - RETURN_ZVAL(retval_ptr, 0, 1); - + if (call_user_function_ex(EG(function_table), NULL, &func, &retval, arg_count, func_params, 0, NULL) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { + RETURN_ZVAL(&retval, 0, 0); + success = SUCCESS; } else { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to call %s::%s()", intern->inner.ce->name, method); + php_error_docref(NULL, E_ERROR, "Unable to call %s::%s()", intern->inner.ce->name, method); success = FAILURE; } - efree(func_params); + efree(func_params); return success; } #endif #define SPL_CHECK_CTOR(intern, classname) \ if (intern->dit_type == DIT_Unknown) { \ - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Classes derived from %s must call %s::__construct()", \ - (spl_ce_##classname)->name, (spl_ce_##classname)->name); \ + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Classes derived from %s must call %s::__construct()", \ + ZSTR_VAL((spl_ce_##classname)->name), ZSTR_VAL((spl_ce_##classname)->name)); \ return; \ } #define APPENDIT_CHECK_CTOR(intern) SPL_CHECK_CTOR(intern, AppendIterator) -static inline int spl_dual_it_fetch(spl_dual_it_object *intern, int check_more TSRMLS_DC); +static inline int spl_dual_it_fetch(spl_dual_it_object *intern, int check_more); -static inline int spl_cit_check_flags(int flags) +static inline int spl_cit_check_flags(zend_long flags) { - int cnt = 0; + zend_long cnt = 0; cnt += (flags & CIT_CALL_TOSTRING) ? 1 : 0; cnt += (flags & CIT_TOSTRING_USE_KEY) ? 1 : 0; cnt += (flags & CIT_TOSTRING_USE_CURRENT) ? 1 : 0; cnt += (flags & CIT_TOSTRING_USE_INNER) ? 1 : 0; - + return cnt <= 1 ? SUCCESS : FAILURE; } static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *ce_base, zend_class_entry *ce_inner, dual_it_type dit_type) { - zval *zobject, *retval; + zval *zobject, retval; spl_dual_it_object *intern; zend_class_entry *ce = NULL; int inc_refcount = 1; zend_error_handling error_handling; - intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + intern = Z_SPLDUAL_IT_P(getThis()); + if (intern->dit_type != DIT_Unknown) { - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "%s::getIterator() must be called exactly once per instance", ce_base->name); + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s::getIterator() must be called exactly once per instance", ZSTR_VAL(ce_base->name)); return NULL; } - zend_replace_error_handling(EH_THROW, spl_ce_InvalidArgumentException, &error_handling TSRMLS_CC); - intern->dit_type = dit_type; switch (dit_type) { case DIT_LimitIterator: { intern->u.limit.offset = 0; /* start at beginning */ intern->u.limit.count = -1; /* get all */ - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|ll", &zobject, ce_inner, &intern->u.limit.offset, &intern->u.limit.count) == FAILURE) { - zend_restore_error_handling(&error_handling TSRMLS_CC); + if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "O|ll", &zobject, ce_inner, &intern->u.limit.offset, &intern->u.limit.count) == FAILURE) { return NULL; } if (intern->u.limit.offset < 0) { - zend_throw_exception(spl_ce_OutOfRangeException, "Parameter offset must be >= 0", 0 TSRMLS_CC); - zend_restore_error_handling(&error_handling TSRMLS_CC); + zend_throw_exception(spl_ce_OutOfRangeException, "Parameter offset must be >= 0", 0); return NULL; } if (intern->u.limit.count < 0 && intern->u.limit.count != -1) { - zend_throw_exception(spl_ce_OutOfRangeException, "Parameter count must either be -1 or a value greater than or equal 0", 0 TSRMLS_CC); - zend_restore_error_handling(&error_handling TSRMLS_CC); + zend_throw_exception(spl_ce_OutOfRangeException, "Parameter count must either be -1 or a value greater than or equal 0", 0); return NULL; } break; } case DIT_CachingIterator: case DIT_RecursiveCachingIterator: { - long flags = CIT_CALL_TOSTRING; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|l", &zobject, ce_inner, &flags) == FAILURE) { - zend_restore_error_handling(&error_handling TSRMLS_CC); + zend_long flags = CIT_CALL_TOSTRING; + if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "O|l", &zobject, ce_inner, &flags) == FAILURE) { return NULL; } if (spl_cit_check_flags(flags) != SUCCESS) { - zend_throw_exception(spl_ce_InvalidArgumentException, "Flags must contain only one of CALL_TOSTRING, TOSTRING_USE_KEY, TOSTRING_USE_CURRENT, TOSTRING_USE_INNER", 0 TSRMLS_CC); - zend_restore_error_handling(&error_handling TSRMLS_CC); + zend_throw_exception(spl_ce_InvalidArgumentException, "Flags must contain only one of CALL_TOSTRING, TOSTRING_USE_KEY, TOSTRING_USE_CURRENT, TOSTRING_USE_INNER", 0); return NULL; } intern->u.caching.flags |= flags & CIT_PUBLIC; - MAKE_STD_ZVAL(intern->u.caching.zcache); - array_init(intern->u.caching.zcache); + array_init(&intern->u.caching.zcache); break; } case DIT_IteratorIterator: { - zend_class_entry **pce_cast; - char * class_name = NULL; - int class_name_len = 0; + zend_class_entry *ce_cast; + zend_string *class_name; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|s", &zobject, ce_inner, &class_name, &class_name_len) == FAILURE) { - zend_restore_error_handling(&error_handling TSRMLS_CC); + if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "O|S", &zobject, ce_inner, &class_name) == FAILURE) { return NULL; } ce = Z_OBJCE_P(zobject); - if (!instanceof_function(ce, zend_ce_iterator TSRMLS_CC)) { + if (!instanceof_function(ce, zend_ce_iterator)) { if (ZEND_NUM_ARGS() > 1) { - if (zend_lookup_class(class_name, class_name_len, &pce_cast TSRMLS_CC) == FAILURE - || !instanceof_function(ce, *pce_cast TSRMLS_CC) - || !(*pce_cast)->get_iterator + if (!(ce_cast = zend_lookup_class(class_name)) + || !instanceof_function(ce, ce_cast) + || !ce_cast->get_iterator ) { - zend_throw_exception(spl_ce_LogicException, "Class to downcast to not found or not base class or does not implement Traversable", 0 TSRMLS_CC); - zend_restore_error_handling(&error_handling TSRMLS_CC); + zend_throw_exception(spl_ce_LogicException, "Class to downcast to not found or not base class or does not implement Traversable", 0); return NULL; } - ce = *pce_cast; + ce = ce_cast; } - if (instanceof_function(ce, zend_ce_aggregate TSRMLS_CC)) { - zend_call_method_with_0_params(&zobject, ce, &ce->iterator_funcs.zf_new_iterator, "getiterator", &retval); + if (instanceof_function(ce, zend_ce_aggregate)) { + zend_call_method_with_0_params(zobject, ce, &ce->iterator_funcs.zf_new_iterator, "getiterator", &retval); if (EG(exception)) { - if (retval) { - zval_ptr_dtor(&retval); - } - zend_restore_error_handling(&error_handling TSRMLS_CC); + zval_ptr_dtor(&retval); return NULL; } - if (!retval || Z_TYPE_P(retval) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(retval), zend_ce_traversable TSRMLS_CC)) { - zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "%s::getIterator() must return an object that implements Traversable", ce->name); - zend_restore_error_handling(&error_handling TSRMLS_CC); + if (Z_TYPE(retval) != IS_OBJECT || !instanceof_function(Z_OBJCE(retval), zend_ce_traversable)) { + zend_throw_exception_ex(spl_ce_LogicException, 0, "%s::getIterator() must return an object that implements Traversable", ZSTR_VAL(ce->name)); return NULL; } - zobject = retval; + zobject = &retval; ce = Z_OBJCE_P(zobject); inc_refcount = 0; } @@ -1535,37 +1531,37 @@ static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, z break; } case DIT_AppendIterator: - spl_instantiate(spl_ce_ArrayIterator, &intern->u.append.zarrayit, 1 TSRMLS_CC); + zend_replace_error_handling(EH_THROW, spl_ce_InvalidArgumentException, &error_handling); + spl_instantiate(spl_ce_ArrayIterator, &intern->u.append.zarrayit); zend_call_method_with_0_params(&intern->u.append.zarrayit, spl_ce_ArrayIterator, &spl_ce_ArrayIterator->constructor, "__construct", NULL); - intern->u.append.iterator = spl_ce_ArrayIterator->get_iterator(spl_ce_ArrayIterator, intern->u.append.zarrayit, 0 TSRMLS_CC); - zend_restore_error_handling(&error_handling TSRMLS_CC); + intern->u.append.iterator = spl_ce_ArrayIterator->get_iterator(spl_ce_ArrayIterator, &intern->u.append.zarrayit, 0); + zend_restore_error_handling(&error_handling); return intern; #if HAVE_PCRE || HAVE_BUNDLED_PCRE case DIT_RegexIterator: case DIT_RecursiveRegexIterator: { - char *regex; - int regex_len; - long mode = REGIT_MODE_MATCH; + zend_string *regex; + zend_long mode = REGIT_MODE_MATCH; intern->u.regex.use_flags = ZEND_NUM_ARGS() >= 5; intern->u.regex.flags = 0; intern->u.regex.preg_flags = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|lll", &zobject, ce_inner, ®ex, ®ex_len, &mode, &intern->u.regex.flags, &intern->u.regex.preg_flags) == FAILURE) { - zend_restore_error_handling(&error_handling TSRMLS_CC); + if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "OS|lll", &zobject, ce_inner, ®ex, &mode, &intern->u.regex.flags, &intern->u.regex.preg_flags) == FAILURE) { return NULL; } if (mode < 0 || mode >= REGIT_MODE_MAX) { - zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Illegal mode %ld", mode); - zend_restore_error_handling(&error_handling TSRMLS_CC); + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "Illegal mode %pd", mode); return NULL; } intern->u.regex.mode = mode; - intern->u.regex.regex = estrndup(regex, regex_len); - intern->u.regex.regex_len = regex_len; - intern->u.regex.pce = pcre_get_compiled_regex_cache(regex, regex_len TSRMLS_CC); + intern->u.regex.regex = zend_string_copy(regex); + + zend_replace_error_handling(EH_THROW, spl_ce_InvalidArgumentException, &error_handling); + intern->u.regex.pce = pcre_get_compiled_regex_cache(regex); + zend_restore_error_handling(&error_handling); + if (intern->u.regex.pce == NULL) { /* pcre_get_compiled_regex_cache has already sent error */ - zend_restore_error_handling(&error_handling TSRMLS_CC); return NULL; } intern->u.regex.pce->refcount++; @@ -1575,56 +1571,54 @@ static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, z case DIT_CallbackFilterIterator: case DIT_RecursiveCallbackFilterIterator: { _spl_cbfilter_it_intern *cfi = emalloc(sizeof(*cfi)); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Of", &zobject, ce_inner, &cfi->fci, &cfi->fcc) == FAILURE) { - zend_restore_error_handling(&error_handling TSRMLS_CC); + cfi->fci.object = NULL; + if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "Of", &zobject, ce_inner, &cfi->fci, &cfi->fcc) == FAILURE) { efree(cfi); return NULL; } - if (cfi->fci.function_name) { - Z_ADDREF_P(cfi->fci.function_name); - } - if (cfi->fci.object_ptr) { - Z_ADDREF_P(cfi->fci.object_ptr); + if (Z_REFCOUNTED_P(&cfi->fci.function_name)) { + Z_ADDREF(cfi->fci.function_name); } + cfi->object = cfi->fcc.object; + if (cfi->object) GC_REFCOUNT(cfi->object)++; intern->u.cbfilter = cfi; break; } default: - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zobject, ce_inner) == FAILURE) { - zend_restore_error_handling(&error_handling TSRMLS_CC); + if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "O", &zobject, ce_inner) == FAILURE) { return NULL; } break; } - zend_restore_error_handling(&error_handling TSRMLS_CC); - if (inc_refcount) { - Z_ADDREF_P(zobject); + ZVAL_COPY(&intern->inner.zobject, zobject); + } else { + ZVAL_COPY_VALUE(&intern->inner.zobject, zobject); } - intern->inner.zobject = zobject; + intern->inner.ce = dit_type == DIT_IteratorIterator ? ce : Z_OBJCE_P(zobject); - intern->inner.object = zend_object_store_get_object(zobject TSRMLS_CC); - intern->inner.iterator = intern->inner.ce->get_iterator(intern->inner.ce, zobject, 0 TSRMLS_CC); + intern->inner.object = Z_OBJ_P(zobject); + intern->inner.iterator = intern->inner.ce->get_iterator(intern->inner.ce, zobject, 0); return intern; } -/* {{{ proto void FilterIterator::__construct(Iterator it) +/* {{{ proto void FilterIterator::__construct(Iterator it) Create an Iterator from another iterator */ SPL_METHOD(FilterIterator, __construct) { spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_FilterIterator, zend_ce_iterator, DIT_FilterIterator); } /* }}} */ -/* {{{ proto void CallbackFilterIterator::__construct(Iterator it, callback) +/* {{{ proto void CallbackFilterIterator::__construct(Iterator it, callback func) Create an Iterator from another iterator */ SPL_METHOD(CallbackFilterIterator, __construct) { spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_CallbackFilterIterator, zend_ce_iterator, DIT_CallbackFilterIterator); } /* }}} */ -/* {{{ proto Iterator FilterIterator::getInnerIterator() +/* {{{ proto Iterator FilterIterator::getInnerIterator() proto Iterator CachingIterator::getInnerIterator() proto Iterator LimitIterator::getInnerIterator() proto Iterator ParentIterator::getInnerIterator() @@ -1632,105 +1626,106 @@ SPL_METHOD(CallbackFilterIterator, __construct) SPL_METHOD(dual_it, getInnerIterator) { spl_dual_it_object *intern; - + if (zend_parse_parameters_none() == FAILURE) { return; } - + SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - if (intern->inner.zobject) { - RETVAL_ZVAL(intern->inner.zobject, 1, 0); + if (!Z_ISUNDEF(intern->inner.zobject)) { + zval *value = &intern->inner.zobject; + + ZVAL_DEREF(value); + ZVAL_COPY(return_value, value); } else { RETURN_NULL(); } } /* }}} */ -static inline void spl_dual_it_require(spl_dual_it_object *intern TSRMLS_DC) +static inline void spl_dual_it_require(spl_dual_it_object *intern) { if (!intern->inner.iterator) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "The inner constructor wasn't initialized with an iterator instance"); + php_error_docref(NULL, E_ERROR, "The inner constructor wasn't initialized with an iterator instance"); } } -static inline void spl_dual_it_free(spl_dual_it_object *intern TSRMLS_DC) +static inline void spl_dual_it_free(spl_dual_it_object *intern) { if (intern->inner.iterator && intern->inner.iterator->funcs->invalidate_current) { - intern->inner.iterator->funcs->invalidate_current(intern->inner.iterator TSRMLS_CC); + intern->inner.iterator->funcs->invalidate_current(intern->inner.iterator); } - if (intern->current.data) { + if (Z_TYPE(intern->current.data) != IS_UNDEF) { zval_ptr_dtor(&intern->current.data); - intern->current.data = NULL; + ZVAL_UNDEF(&intern->current.data); } - if (intern->current.key) { + if (Z_TYPE(intern->current.key) != IS_UNDEF) { zval_ptr_dtor(&intern->current.key); - intern->current.key = NULL; + ZVAL_UNDEF(&intern->current.key); } if (intern->dit_type == DIT_CachingIterator || intern->dit_type == DIT_RecursiveCachingIterator) { - if (intern->u.caching.zstr) { + if (Z_TYPE(intern->u.caching.zstr) != IS_UNDEF) { zval_ptr_dtor(&intern->u.caching.zstr); - intern->u.caching.zstr = NULL; + ZVAL_UNDEF(&intern->u.caching.zstr); } - if (intern->u.caching.zchildren) { + if (Z_TYPE(intern->u.caching.zchildren) != IS_UNDEF) { zval_ptr_dtor(&intern->u.caching.zchildren); - intern->u.caching.zchildren = NULL; + ZVAL_UNDEF(&intern->u.caching.zchildren); } } } -static inline void spl_dual_it_rewind(spl_dual_it_object *intern TSRMLS_DC) +static inline void spl_dual_it_rewind(spl_dual_it_object *intern) { - spl_dual_it_free(intern TSRMLS_CC); + spl_dual_it_free(intern); intern->current.pos = 0; if (intern->inner.iterator->funcs->rewind) { - intern->inner.iterator->funcs->rewind(intern->inner.iterator TSRMLS_CC); + intern->inner.iterator->funcs->rewind(intern->inner.iterator); } } -static inline int spl_dual_it_valid(spl_dual_it_object *intern TSRMLS_DC) +static inline int spl_dual_it_valid(spl_dual_it_object *intern) { if (!intern->inner.iterator) { return FAILURE; } /* FAILURE / SUCCESS */ - return intern->inner.iterator->funcs->valid(intern->inner.iterator TSRMLS_CC); + return intern->inner.iterator->funcs->valid(intern->inner.iterator); } -static inline int spl_dual_it_fetch(spl_dual_it_object *intern, int check_more TSRMLS_DC) +static inline int spl_dual_it_fetch(spl_dual_it_object *intern, int check_more) { - zval **data; + zval *data; - spl_dual_it_free(intern TSRMLS_CC); - if (!check_more || spl_dual_it_valid(intern TSRMLS_CC) == SUCCESS) { - intern->inner.iterator->funcs->get_current_data(intern->inner.iterator, &data TSRMLS_CC); - if (data && *data) { - intern->current.data = *data; - Z_ADDREF_P(intern->current.data); + spl_dual_it_free(intern); + if (!check_more || spl_dual_it_valid(intern) == SUCCESS) { + data = intern->inner.iterator->funcs->get_current_data(intern->inner.iterator); + if (data) { + ZVAL_COPY(&intern->current.data, data); } - MAKE_STD_ZVAL(intern->current.key); if (intern->inner.iterator->funcs->get_current_key) { - intern->inner.iterator->funcs->get_current_key(intern->inner.iterator, intern->current.key TSRMLS_CC); + intern->inner.iterator->funcs->get_current_key(intern->inner.iterator, &intern->current.key); if (EG(exception)) { zval_ptr_dtor(&intern->current.key); - intern->current.key = NULL; + ZVAL_UNDEF(&intern->current.key); } } else { - ZVAL_LONG(intern->current.key, intern->current.pos); + ZVAL_LONG(&intern->current.key, intern->current.pos); } return EG(exception) ? FAILURE : SUCCESS; } return FAILURE; } -static inline void spl_dual_it_next(spl_dual_it_object *intern, int do_free TSRMLS_DC) +static inline void spl_dual_it_next(spl_dual_it_object *intern, int do_free) { if (do_free) { - spl_dual_it_free(intern TSRMLS_CC); + spl_dual_it_free(intern); } else { - spl_dual_it_require(intern TSRMLS_CC); + spl_dual_it_require(intern); } - intern->inner.iterator->funcs->move_forward(intern->inner.iterator TSRMLS_CC); + intern->inner.iterator->funcs->move_forward(intern->inner.iterator); intern->current.pos++; } @@ -1741,15 +1736,15 @@ static inline void spl_dual_it_next(spl_dual_it_object *intern, int do_free TSRM SPL_METHOD(dual_it, rewind) { spl_dual_it_object *intern; - + if (zend_parse_parameters_none() == FAILURE) { return; } - + SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - - spl_dual_it_rewind(intern TSRMLS_CC); - spl_dual_it_fetch(intern, 1 TSRMLS_CC); + + spl_dual_it_rewind(intern); + spl_dual_it_fetch(intern, 1); } /* }}} */ /* {{{ proto bool FilterIterator::valid() @@ -1764,10 +1759,10 @@ SPL_METHOD(dual_it, valid) if (zend_parse_parameters_none() == FAILURE) { return; } - + SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - RETURN_BOOL(intern->current.data); + RETURN_BOOL(Z_TYPE(intern->current.data) != IS_UNDEF); } /* }}} */ /* {{{ proto mixed FilterIterator::key() @@ -1785,13 +1780,17 @@ SPL_METHOD(dual_it, key) if (zend_parse_parameters_none() == FAILURE) { return; } - + SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - if (intern->current.key) { - RETURN_ZVAL(intern->current.key, 1, 0); + if (Z_TYPE(intern->current.key) != IS_UNDEF) { + zval *value = &intern->current.key; + + ZVAL_DEREF(value); + ZVAL_COPY(return_value, value); + } else { + RETURN_NULL(); } - RETURN_NULL(); } /* }}} */ /* {{{ proto mixed FilterIterator::current() @@ -1805,15 +1804,18 @@ SPL_METHOD(dual_it, key) SPL_METHOD(dual_it, current) { spl_dual_it_object *intern; - + if (zend_parse_parameters_none() == FAILURE) { return; } SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - if (intern->current.data) { - RETVAL_ZVAL(intern->current.data, 1, 0); + if (Z_TYPE(intern->current.data) != IS_UNDEF) { + zval *value = &intern->current.data; + + ZVAL_DEREF(value); + ZVAL_COPY(return_value, value); } else { RETURN_NULL(); } @@ -1826,25 +1828,25 @@ SPL_METHOD(dual_it, current) SPL_METHOD(dual_it, next) { spl_dual_it_object *intern; - + if (zend_parse_parameters_none() == FAILURE) { return; } SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - spl_dual_it_next(intern, 1 TSRMLS_CC); - spl_dual_it_fetch(intern, 1 TSRMLS_CC); + spl_dual_it_next(intern, 1); + spl_dual_it_fetch(intern, 1); } /* }}} */ -static inline void spl_filter_it_fetch(zval *zthis, spl_dual_it_object *intern TSRMLS_DC) +static inline void spl_filter_it_fetch(zval *zthis, spl_dual_it_object *intern) { - zval *retval; + zval retval; - while (spl_dual_it_fetch(intern, 1 TSRMLS_CC) == SUCCESS) { - zend_call_method_with_0_params(&zthis, intern->std.ce, NULL, "accept", &retval); - if (retval) { - if (zend_is_true(retval)) { + while (spl_dual_it_fetch(intern, 1) == SUCCESS) { + zend_call_method_with_0_params(zthis, intern->std.ce, NULL, "accept", &retval); + if (Z_TYPE(retval) != IS_UNDEF) { + if (zend_is_true(&retval)) { zval_ptr_dtor(&retval); return; } @@ -1853,21 +1855,21 @@ static inline void spl_filter_it_fetch(zval *zthis, spl_dual_it_object *intern T if (EG(exception)) { return; } - intern->inner.iterator->funcs->move_forward(intern->inner.iterator TSRMLS_CC); + intern->inner.iterator->funcs->move_forward(intern->inner.iterator); } - spl_dual_it_free(intern TSRMLS_CC); + spl_dual_it_free(intern); } -static inline void spl_filter_it_rewind(zval *zthis, spl_dual_it_object *intern TSRMLS_DC) +static inline void spl_filter_it_rewind(zval *zthis, spl_dual_it_object *intern) { - spl_dual_it_rewind(intern TSRMLS_CC); - spl_filter_it_fetch(zthis, intern TSRMLS_CC); + spl_dual_it_rewind(intern); + spl_filter_it_fetch(zthis, intern); } -static inline void spl_filter_it_next(zval *zthis, spl_dual_it_object *intern TSRMLS_DC) +static inline void spl_filter_it_next(zval *zthis, spl_dual_it_object *intern) { - spl_dual_it_next(intern, 1 TSRMLS_CC); - spl_filter_it_fetch(zthis, intern TSRMLS_CC); + spl_dual_it_next(intern, 1); + spl_filter_it_fetch(zthis, intern); } /* {{{ proto void FilterIterator::rewind() @@ -1875,13 +1877,13 @@ static inline void spl_filter_it_next(zval *zthis, spl_dual_it_object *intern TS SPL_METHOD(FilterIterator, rewind) { spl_dual_it_object *intern; - + if (zend_parse_parameters_none() == FAILURE) { return; } SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - spl_filter_it_rewind(getThis(), intern TSRMLS_CC); + spl_filter_it_rewind(getThis(), intern); } /* }}} */ /* {{{ proto void FilterIterator::next() @@ -1889,16 +1891,16 @@ SPL_METHOD(FilterIterator, rewind) SPL_METHOD(FilterIterator, next) { spl_dual_it_object *intern; - + if (zend_parse_parameters_none() == FAILURE) { return; } SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - spl_filter_it_next(getThis(), intern TSRMLS_CC); + spl_filter_it_next(getThis(), intern); } /* }}} */ -/* {{{ proto void RecursiveCallbackFilterIterator::__construct(RecursiveIterator it, callback) +/* {{{ proto void RecursiveCallbackFilterIterator::__construct(RecursiveIterator it, callback func) Create a RecursiveCallbackFilterIterator from a RecursiveIterator */ SPL_METHOD(RecursiveCallbackFilterIterator, __construct) { @@ -1918,8 +1920,8 @@ SPL_METHOD(RecursiveFilterIterator, __construct) SPL_METHOD(RecursiveFilterIterator, hasChildren) { spl_dual_it_object *intern; - zval *retval; - + zval retval; + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1927,8 +1929,8 @@ SPL_METHOD(RecursiveFilterIterator, hasChildren) SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "haschildren", &retval); - if (retval) { - RETURN_ZVAL(retval, 0, 1); + if (Z_TYPE(retval) != IS_UNDEF) { + RETURN_ZVAL(&retval, 0, 1); } else { RETURN_FALSE; } @@ -1939,8 +1941,8 @@ SPL_METHOD(RecursiveFilterIterator, hasChildren) SPL_METHOD(RecursiveFilterIterator, getChildren) { spl_dual_it_object *intern; - zval *retval; - + zval retval; + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1948,12 +1950,10 @@ SPL_METHOD(RecursiveFilterIterator, getChildren) SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &retval); - if (!EG(exception) && retval) { - spl_instantiate_arg_ex1(Z_OBJCE_P(getThis()), &return_value, 0, retval TSRMLS_CC); - } - if (retval) { - zval_ptr_dtor(&retval); + if (!EG(exception) && Z_TYPE(retval) != IS_UNDEF) { + spl_instantiate_arg_ex1(Z_OBJCE_P(getThis()), return_value, &retval); } + zval_ptr_dtor(&retval); } /* }}} */ /* {{{ proto RecursiveCallbackFilterIterator RecursiveCallbackFilterIterator::getChildren() @@ -1961,8 +1961,8 @@ SPL_METHOD(RecursiveFilterIterator, getChildren) SPL_METHOD(RecursiveCallbackFilterIterator, getChildren) { spl_dual_it_object *intern; - zval *retval; - + zval retval; + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1970,12 +1970,10 @@ SPL_METHOD(RecursiveCallbackFilterIterator, getChildren) SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &retval); - if (!EG(exception) && retval) { - spl_instantiate_arg_ex2(Z_OBJCE_P(getThis()), &return_value, 0, retval, intern->u.cbfilter->fci.function_name TSRMLS_CC); - } - if (retval) { - zval_ptr_dtor(&retval); + if (!EG(exception) && Z_TYPE(retval) != IS_UNDEF) { + spl_instantiate_arg_ex2(Z_OBJCE_P(getThis()), return_value, &retval, &intern->u.cbfilter->fci.function_name); } + zval_ptr_dtor(&retval); } /* }}} */ /* {{{ proto void ParentIterator::__construct(RecursiveIterator it) Create a ParentIterator from a RecursiveIterator */ @@ -1985,7 +1983,7 @@ SPL_METHOD(ParentIterator, __construct) } /* }}} */ #if HAVE_PCRE || HAVE_BUNDLED_PCRE -/* {{{ proto void RegexIterator::__construct(Iterator it, string regex [, int mode [, int flags [, int preg_flags]]]) +/* {{{ proto void RegexIterator::__construct(Iterator it, string regex [, int mode [, int flags [, int preg_flags]]]) Create an RegexIterator from another iterator and a regular expression */ SPL_METHOD(RegexIterator, __construct) { @@ -1996,37 +1994,37 @@ SPL_METHOD(RegexIterator, __construct) Calls the callback with the current value, the current key and the inner iterator as arguments */ SPL_METHOD(CallbackFilterIterator, accept) { - spl_dual_it_object *intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_dual_it_object *intern = Z_SPLDUAL_IT_P(getThis()); zend_fcall_info *fci = &intern->u.cbfilter->fci; zend_fcall_info_cache *fcc = &intern->u.cbfilter->fcc; - zval **params[3]; - zval *result; + zval params[3]; + zval result; if (zend_parse_parameters_none() == FAILURE) { return; } - if (intern->current.data == NULL || intern->current.key == NULL) { + if (Z_TYPE(intern->current.data) == IS_UNDEF || Z_TYPE(intern->current.key) == IS_UNDEF) { RETURN_FALSE; } - params[0] = &intern->current.data; - params[1] = &intern->current.key; - params[2] = &intern->inner.zobject; + ZVAL_COPY_VALUE(¶ms[0], &intern->current.data); + ZVAL_COPY_VALUE(¶ms[1], &intern->current.key); + ZVAL_COPY_VALUE(¶ms[2], &intern->inner.zobject); - fci->retval_ptr_ptr = &result; + fci->retval = &result; fci->param_count = 3; fci->params = params; fci->no_separation = 0; - if (zend_call_function(fci, fcc TSRMLS_CC) != SUCCESS || !result) { + if (zend_call_function(fci, fcc) != SUCCESS || Z_TYPE(result) == IS_UNDEF) { RETURN_FALSE; } if (EG(exception)) { return; } - RETURN_ZVAL(result, 1, 1); + RETURN_ZVAL(&result, 1, 1); } /* }}} */ @@ -2035,116 +2033,98 @@ SPL_METHOD(CallbackFilterIterator, accept) SPL_METHOD(RegexIterator, accept) { spl_dual_it_object *intern; - char *subject, *result; - int subject_len, use_copy, count = 0, result_len; - zval *subject_ptr, subject_copy, zcount, *replacement, tmp_replacement; - + zend_string *result, *subject; + int count = 0; + zval zcount, *replacement, tmp_replacement, rv; + if (zend_parse_parameters_none() == FAILURE) { return; } - + SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - - if (intern->current.data == NULL) { + + if (Z_TYPE(intern->current.data) == IS_UNDEF) { RETURN_FALSE; - } else if (Z_TYPE_P(intern->current.data) == IS_ARRAY) { + } else if (Z_TYPE(intern->current.data) == IS_ARRAY) { RETURN_FALSE; } if (intern->u.regex.flags & REGIT_USE_KEY) { - subject_ptr = intern->current.key; - } else { - subject_ptr = intern->current.data; - } - - zend_make_printable_zval(subject_ptr, &subject_copy, &use_copy); - if (use_copy) { - subject = Z_STRVAL(subject_copy); - subject_len = Z_STRLEN(subject_copy); + subject = zval_get_string(&intern->current.key); } else { - subject = Z_STRVAL_P(subject_ptr); - subject_len = Z_STRLEN_P(subject_ptr); + subject = zval_get_string(&intern->current.data); } switch (intern->u.regex.mode) { - case REGIT_MODE_MAX: /* won't happen but makes compiler happy */ - case REGIT_MODE_MATCH: - count = pcre_exec(intern->u.regex.pce->re, intern->u.regex.pce->extra, subject, subject_len, 0, 0, NULL, 0); - RETVAL_BOOL(count >= 0); - break; - - case REGIT_MODE_ALL_MATCHES: - case REGIT_MODE_GET_MATCH: - if (!use_copy) { - subject = estrndup(subject, subject_len); - use_copy = 1; - } - zval_ptr_dtor(&intern->current.data); - ALLOC_INIT_ZVAL(intern->current.data); - php_pcre_match_impl(intern->u.regex.pce, subject, subject_len, &zcount, - intern->current.data, intern->u.regex.mode == REGIT_MODE_ALL_MATCHES, intern->u.regex.use_flags, intern->u.regex.preg_flags, 0 TSRMLS_CC); - RETVAL_BOOL(Z_LVAL(zcount) > 0); - break; - - case REGIT_MODE_SPLIT: - if (!use_copy) { - subject = estrndup(subject, subject_len); - use_copy = 1; - } - zval_ptr_dtor(&intern->current.data); - ALLOC_INIT_ZVAL(intern->current.data); - php_pcre_split_impl(intern->u.regex.pce, subject, subject_len, intern->current.data, -1, intern->u.regex.preg_flags TSRMLS_CC); - count = zend_hash_num_elements(Z_ARRVAL_P(intern->current.data)); - RETVAL_BOOL(count > 1); - break; - - case REGIT_MODE_REPLACE: - replacement = zend_read_property(intern->std.ce, getThis(), "replacement", sizeof("replacement")-1, 1 TSRMLS_CC); - if (Z_TYPE_P(replacement) != IS_STRING) { - tmp_replacement = *replacement; - zval_copy_ctor(&tmp_replacement); - convert_to_string(&tmp_replacement); - replacement = &tmp_replacement; - } - result = php_pcre_replace_impl(intern->u.regex.pce, subject, subject_len, replacement, 0, &result_len, -1, &count TSRMLS_CC); - - if (intern->u.regex.flags & REGIT_USE_KEY) { - zval_ptr_dtor(&intern->current.key); - MAKE_STD_ZVAL(intern->current.key); - ZVAL_STRINGL(intern->current.key, result, result_len, 0); - } else { + case REGIT_MODE_MAX: /* won't happen but makes compiler happy */ + case REGIT_MODE_MATCH: +#ifdef PCRE_EXTRA_MARK + if (intern->u.regex.pce->extra) { + intern->u.regex.pce->extra->flags &= ~PCRE_EXTRA_MARK; + } +#endif + count = pcre_exec(intern->u.regex.pce->re, intern->u.regex.pce->extra, ZSTR_VAL(subject), ZSTR_LEN(subject), 0, 0, NULL, 0); + RETVAL_BOOL(count >= 0); + break; + + case REGIT_MODE_ALL_MATCHES: + case REGIT_MODE_GET_MATCH: zval_ptr_dtor(&intern->current.data); - MAKE_STD_ZVAL(intern->current.data); - ZVAL_STRINGL(intern->current.data, result, result_len, 0); - } + ZVAL_UNDEF(&intern->current.data); + php_pcre_match_impl(intern->u.regex.pce, ZSTR_VAL(subject), ZSTR_LEN(subject), &zcount, + &intern->current.data, intern->u.regex.mode == REGIT_MODE_ALL_MATCHES, intern->u.regex.use_flags, intern->u.regex.preg_flags, 0); + RETVAL_BOOL(Z_LVAL(zcount) > 0); + break; - if (replacement == &tmp_replacement) { - zval_dtor(replacement); - } - RETVAL_BOOL(count > 0); - } + case REGIT_MODE_SPLIT: + zval_ptr_dtor(&intern->current.data); + ZVAL_UNDEF(&intern->current.data); + php_pcre_split_impl(intern->u.regex.pce, ZSTR_VAL(subject), ZSTR_LEN(subject), &intern->current.data, -1, intern->u.regex.preg_flags); + count = zend_hash_num_elements(Z_ARRVAL(intern->current.data)); + RETVAL_BOOL(count > 1); + break; - if (intern->u.regex.flags & REGIT_INVERTED) { - RETVAL_BOOL(! Z_LVAL_P(return_value)); + case REGIT_MODE_REPLACE: + replacement = zend_read_property(intern->std.ce, getThis(), "replacement", sizeof("replacement")-1, 1, &rv); + if (Z_TYPE_P(replacement) != IS_STRING) { + ZVAL_COPY(&tmp_replacement, replacement); + convert_to_string(&tmp_replacement); + replacement = &tmp_replacement; + } + result = php_pcre_replace_impl(intern->u.regex.pce, subject, ZSTR_VAL(subject), ZSTR_LEN(subject), replacement, 0, -1, &count); + + if (intern->u.regex.flags & REGIT_USE_KEY) { + zval_ptr_dtor(&intern->current.key); + ZVAL_STR(&intern->current.key, result); + } else { + zval_ptr_dtor(&intern->current.data); + ZVAL_STR(&intern->current.data, result); + } + + if (replacement == &tmp_replacement) { + zval_ptr_dtor(replacement); + } + RETVAL_BOOL(count > 0); } - if (use_copy) { - str_efree(subject); + if (intern->u.regex.flags & REGIT_INVERTED) { + RETVAL_BOOL(Z_TYPE_P(return_value) != IS_TRUE); } + zend_string_release(subject); } /* }}} */ /* {{{ proto string RegexIterator::getRegex() Returns current regular expression */ SPL_METHOD(RegexIterator, getRegex) { - spl_dual_it_object *intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_dual_it_object *intern = Z_SPLDUAL_IT_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; } - RETURN_STRINGL(intern->u.regex.regex, intern->u.regex.regex_len, 1); + RETURN_STR_COPY(intern->u.regex.regex); } /* }}} */ /* {{{ proto bool RegexIterator::getMode() @@ -2156,9 +2136,9 @@ SPL_METHOD(RegexIterator, getMode) if (zend_parse_parameters_none() == FAILURE) { return; } - + SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - + RETURN_LONG(intern->u.regex.mode); } /* }}} */ @@ -2167,17 +2147,17 @@ SPL_METHOD(RegexIterator, getMode) SPL_METHOD(RegexIterator, setMode) { spl_dual_it_object *intern; - long mode; + zend_long mode; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &mode) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &mode) == FAILURE) { return; } if (mode < 0 || mode >= REGIT_MODE_MAX) { - zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Illegal mode %ld", mode); + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "Illegal mode %pd", mode); return;/* NULL */ } - + SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); intern->u.regex.mode = mode; @@ -2192,9 +2172,9 @@ SPL_METHOD(RegexIterator, getFlags) if (zend_parse_parameters_none() == FAILURE) { return; } - + SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - + RETURN_LONG(intern->u.regex.flags); } /* }}} */ @@ -2203,12 +2183,12 @@ SPL_METHOD(RegexIterator, getFlags) SPL_METHOD(RegexIterator, setFlags) { spl_dual_it_object *intern; - long flags; + zend_long flags; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &flags) == FAILURE) { return; } - + SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); intern->u.regex.flags = flags; @@ -2219,11 +2199,11 @@ SPL_METHOD(RegexIterator, setFlags) SPL_METHOD(RegexIterator, getPregFlags) { spl_dual_it_object *intern; - + if (zend_parse_parameters_none() == FAILURE) { return; } - + SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); if (intern->u.regex.use_flags) { @@ -2238,19 +2218,19 @@ SPL_METHOD(RegexIterator, getPregFlags) SPL_METHOD(RegexIterator, setPregFlags) { spl_dual_it_object *intern; - long preg_flags; + zend_long preg_flags; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &preg_flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &preg_flags) == FAILURE) { return; } - + SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); intern->u.regex.preg_flags = preg_flags; intern->u.regex.use_flags = 1; } /* }}} */ -/* {{{ proto void RecursiveRegexIterator::__construct(RecursiveIterator it, string regex [, int mode [, int flags [, int preg_flags]]]) +/* {{{ proto void RecursiveRegexIterator::__construct(RecursiveIterator it, string regex [, int mode [, int flags [, int preg_flags]]]) Create an RecursiveRegexIterator from another recursive iterator and a regular expression */ SPL_METHOD(RecursiveRegexIterator, __construct) { @@ -2262,8 +2242,8 @@ SPL_METHOD(RecursiveRegexIterator, __construct) SPL_METHOD(RecursiveRegexIterator, getChildren) { spl_dual_it_object *intern; - zval *retval; - + zval retval; + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -2272,43 +2252,25 @@ SPL_METHOD(RecursiveRegexIterator, getChildren) zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &retval); if (!EG(exception)) { - zval **args[5], *object, *regex, *mode, *flags, *preg_flags; - - MAKE_STD_ZVAL(object); - MAKE_STD_ZVAL(regex); - MAKE_STD_ZVAL(mode); - MAKE_STD_ZVAL(flags); - MAKE_STD_ZVAL(preg_flags); - - MAKE_COPY_ZVAL(&retval, object); - ZVAL_STRING(regex, intern->u.regex.regex, 1); - ZVAL_LONG(mode, intern->u.regex.mode); - ZVAL_LONG(flags, intern->u.regex.flags); - ZVAL_LONG(preg_flags, intern->u.regex.preg_flags); - - args[0] = &object; - args[1] = ®ex; - args[2] = &mode; - args[3] = &flags; - args[4] = &preg_flags; - - spl_instantiate_arg_n(Z_OBJCE_P(getThis()), &return_value, 5, args TSRMLS_CC); - - zval_ptr_dtor(&object); - zval_ptr_dtor(®ex); - zval_ptr_dtor(&mode); - zval_ptr_dtor(&flags); - zval_ptr_dtor(&preg_flags); - } - if (retval) { - zval_ptr_dtor(&retval); + zval args[5]; + + ZVAL_COPY(&args[0], &retval); + ZVAL_STR_COPY(&args[1], intern->u.regex.regex); + ZVAL_LONG(&args[2], intern->u.regex.mode); + ZVAL_LONG(&args[3], intern->u.regex.flags); + ZVAL_LONG(&args[4], intern->u.regex.preg_flags); + + spl_instantiate_arg_n(Z_OBJCE_P(getThis()), return_value, 5, args); + + zval_ptr_dtor(&args[0]); + zval_ptr_dtor(&args[1]); } + zval_ptr_dtor(&retval); } /* }}} */ SPL_METHOD(RecursiveRegexIterator, accept) { spl_dual_it_object *intern; - zval *rv; if (zend_parse_parameters_none() == FAILURE) { return; @@ -2316,57 +2278,52 @@ SPL_METHOD(RecursiveRegexIterator, accept) SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - if (intern->current.data == NULL) { + if (Z_TYPE(intern->current.data) == IS_UNDEF) { RETURN_FALSE; - } else if (Z_TYPE_P(intern->current.data) == IS_ARRAY) { - RETURN_BOOL(zend_hash_num_elements(Z_ARRVAL_P(intern->current.data)) > 0); + } else if (Z_TYPE(intern->current.data) == IS_ARRAY) { + RETURN_BOOL(zend_hash_num_elements(Z_ARRVAL(intern->current.data)) > 0); } - zend_call_method_with_0_params(&(getThis()), spl_ce_RegexIterator, NULL, "accept", &rv); - - RETURN_ZVAL(rv, 1, 1); + zend_call_method_with_0_params(getThis(), spl_ce_RegexIterator, NULL, "accept", return_value); } #endif /* {{{ spl_dual_it_dtor */ -static void spl_dual_it_dtor(zend_object *_object, zend_object_handle handle TSRMLS_DC) +static void spl_dual_it_dtor(zend_object *_object) { - spl_dual_it_object *object = (spl_dual_it_object *)_object; + spl_dual_it_object *object = spl_dual_it_from_obj(_object); /* call standard dtor */ - zend_objects_destroy_object(_object, handle TSRMLS_CC); + zend_objects_destroy_object(_object); - spl_dual_it_free(object TSRMLS_CC); + spl_dual_it_free(object); if (object->inner.iterator) { - object->inner.iterator->funcs->dtor(object->inner.iterator TSRMLS_CC); + zend_iterator_dtor(object->inner.iterator); } } /* }}} */ /* {{{ spl_dual_it_free_storage */ -static void spl_dual_it_free_storage(void *_object TSRMLS_DC) +static void spl_dual_it_free_storage(zend_object *_object) { - spl_dual_it_object *object = (spl_dual_it_object *)_object; + spl_dual_it_object *object = spl_dual_it_from_obj(_object); - if (object->inner.zobject) { + if (!Z_ISUNDEF(object->inner.zobject)) { zval_ptr_dtor(&object->inner.zobject); } - + if (object->dit_type == DIT_AppendIterator) { - object->u.append.iterator->funcs->dtor(object->u.append.iterator TSRMLS_CC); - if (object->u.append.zarrayit) { + zend_iterator_dtor(object->u.append.iterator); + if (Z_TYPE(object->u.append.zarrayit) != IS_UNDEF) { zval_ptr_dtor(&object->u.append.zarrayit); } } if (object->dit_type == DIT_CachingIterator || object->dit_type == DIT_RecursiveCachingIterator) { - if (object->u.caching.zcache) { - zval_ptr_dtor(&object->u.caching.zcache); - object->u.caching.zcache = NULL; - } + zval_ptr_dtor(&object->u.caching.zcache); } #if HAVE_PCRE || HAVE_BUNDLED_PCRE @@ -2375,49 +2332,44 @@ static void spl_dual_it_free_storage(void *_object TSRMLS_DC) object->u.regex.pce->refcount--; } if (object->u.regex.regex) { - efree(object->u.regex.regex); + zend_string_release(object->u.regex.regex); } } #endif if (object->dit_type == DIT_CallbackFilterIterator || object->dit_type == DIT_RecursiveCallbackFilterIterator) { if (object->u.cbfilter) { - if (object->u.cbfilter->fci.function_name) { - zval_ptr_dtor(&object->u.cbfilter->fci.function_name); + _spl_cbfilter_it_intern *cbfilter = object->u.cbfilter; + object->u.cbfilter = NULL; + zval_ptr_dtor(&cbfilter->fci.function_name); + if (cbfilter->fci.object) { + OBJ_RELEASE(cbfilter->fci.object); } - if (object->u.cbfilter->fci.object_ptr) { - zval_ptr_dtor(&object->u.cbfilter->fci.object_ptr); - } - efree(object->u.cbfilter); + efree(cbfilter); } } - zend_object_std_dtor(&object->std TSRMLS_CC); - - efree(object); + zend_object_std_dtor(&object->std); } /* }}} */ /* {{{ spl_dual_it_new */ -static zend_object_value spl_dual_it_new(zend_class_entry *class_type TSRMLS_DC) +static zend_object *spl_dual_it_new(zend_class_entry *class_type) { - zend_object_value retval; spl_dual_it_object *intern; - intern = emalloc(sizeof(spl_dual_it_object)); - memset(intern, 0, sizeof(spl_dual_it_object)); + intern = ecalloc(1, sizeof(spl_dual_it_object) + zend_object_properties_size(class_type)); intern->dit_type = DIT_Unknown; - zend_object_std_init(&intern->std, class_type TSRMLS_CC); + zend_object_std_init(&intern->std, class_type); object_properties_init(&intern->std, class_type); - retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)spl_dual_it_dtor, (zend_objects_free_object_storage_t) spl_dual_it_free_storage, NULL TSRMLS_CC); - retval.handlers = &spl_handlers_dual_it; - return retval; + intern->std.handlers = &spl_handlers_dual_it; + return &intern->std; } /* }}} */ -ZEND_BEGIN_ARG_INFO(arginfo_filter_it___construct, 0) +ZEND_BEGIN_ARG_INFO(arginfo_filter_it___construct, 0) ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0) ZEND_END_ARG_INFO(); @@ -2433,7 +2385,7 @@ static const zend_function_entry spl_funcs_FilterIterator[] = { PHP_FE_END }; -ZEND_BEGIN_ARG_INFO(arginfo_callback_filter_it___construct, 0) +ZEND_BEGIN_ARG_INFO(arginfo_callback_filter_it___construct, 0) ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0) ZEND_ARG_INFO(0, callback) ZEND_END_ARG_INFO(); @@ -2444,7 +2396,7 @@ static const zend_function_entry spl_funcs_CallbackFilterIterator[] = { PHP_FE_END }; -ZEND_BEGIN_ARG_INFO(arginfo_recursive_callback_filter_it___construct, 0) +ZEND_BEGIN_ARG_INFO(arginfo_recursive_callback_filter_it___construct, 0) ZEND_ARG_OBJ_INFO(0, iterator, RecursiveIterator, 0) ZEND_ARG_INFO(0, callback) ZEND_END_ARG_INFO(); @@ -2456,7 +2408,7 @@ static const zend_function_entry spl_funcs_RecursiveCallbackFilterIterator[] = { PHP_FE_END }; -ZEND_BEGIN_ARG_INFO(arginfo_parent_it___construct, 0) +ZEND_BEGIN_ARG_INFO(arginfo_parent_it___construct, 0) ZEND_ARG_OBJ_INFO(0, iterator, RecursiveIterator, 0) ZEND_END_ARG_INFO(); @@ -2474,7 +2426,7 @@ static const zend_function_entry spl_funcs_ParentIterator[] = { }; #if HAVE_PCRE || HAVE_BUNDLED_PCRE -ZEND_BEGIN_ARG_INFO_EX(arginfo_regex_it___construct, 0, 0, 2) +ZEND_BEGIN_ARG_INFO_EX(arginfo_regex_it___construct, 0, 0, 2) ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0) ZEND_ARG_INFO(0, regex) ZEND_ARG_INFO(0, mode) @@ -2482,15 +2434,15 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_regex_it___construct, 0, 0, 2) ZEND_ARG_INFO(0, preg_flags) ZEND_END_ARG_INFO(); -ZEND_BEGIN_ARG_INFO_EX(arginfo_regex_it_set_mode, 0, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_regex_it_set_mode, 0, 0, 1) ZEND_ARG_INFO(0, mode) ZEND_END_ARG_INFO(); -ZEND_BEGIN_ARG_INFO_EX(arginfo_regex_it_set_flags, 0, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_regex_it_set_flags, 0, 0, 1) ZEND_ARG_INFO(0, flags) ZEND_END_ARG_INFO(); -ZEND_BEGIN_ARG_INFO_EX(arginfo_regex_it_set_preg_flags, 0, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_regex_it_set_preg_flags, 0, 0, 1) ZEND_ARG_INFO(0, preg_flags) ZEND_END_ARG_INFO(); @@ -2507,7 +2459,7 @@ static const zend_function_entry spl_funcs_RegexIterator[] = { PHP_FE_END }; -ZEND_BEGIN_ARG_INFO_EX(arginfo_rec_regex_it___construct, 0, 0, 2) +ZEND_BEGIN_ARG_INFO_EX(arginfo_rec_regex_it___construct, 0, 0, 2) ZEND_ARG_OBJ_INFO(0, iterator, RecursiveIterator, 0) ZEND_ARG_INFO(0, regex) ZEND_ARG_INFO(0, mode) @@ -2524,52 +2476,51 @@ static const zend_function_entry spl_funcs_RecursiveRegexIterator[] = { }; #endif -static inline int spl_limit_it_valid(spl_dual_it_object *intern TSRMLS_DC) +static inline int spl_limit_it_valid(spl_dual_it_object *intern) { /* FAILURE / SUCCESS */ if (intern->u.limit.count != -1 && intern->current.pos >= intern->u.limit.offset + intern->u.limit.count) { return FAILURE; } else { - return spl_dual_it_valid(intern TSRMLS_CC); + return spl_dual_it_valid(intern); } } -static inline void spl_limit_it_seek(spl_dual_it_object *intern, long pos TSRMLS_DC) +static inline void spl_limit_it_seek(spl_dual_it_object *intern, zend_long pos) { - zval *zpos; + zval zpos; - spl_dual_it_free(intern TSRMLS_CC); + spl_dual_it_free(intern); if (pos < intern->u.limit.offset) { - zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0 TSRMLS_CC, "Cannot seek to %ld which is below the offset %ld", pos, intern->u.limit.offset); + zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0, "Cannot seek to %pd which is below the offset %pd", pos, intern->u.limit.offset); return; } if (pos >= intern->u.limit.offset + intern->u.limit.count && intern->u.limit.count != -1) { - zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0 TSRMLS_CC, "Cannot seek to %ld which is behind offset %ld plus count %ld", pos, intern->u.limit.offset, intern->u.limit.count); + zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0, "Cannot seek to %pd which is behind offset %pd plus count %pd", pos, intern->u.limit.offset, intern->u.limit.count); return; } - if (pos != intern->current.pos && instanceof_function(intern->inner.ce, spl_ce_SeekableIterator TSRMLS_CC)) { - MAKE_STD_ZVAL(zpos); - ZVAL_LONG(zpos, pos); - spl_dual_it_free(intern TSRMLS_CC); - zend_call_method_with_1_params(&intern->inner.zobject, intern->inner.ce, NULL, "seek", NULL, zpos); + if (pos != intern->current.pos && instanceof_function(intern->inner.ce, spl_ce_SeekableIterator)) { + ZVAL_LONG(&zpos, pos); + spl_dual_it_free(intern); + zend_call_method_with_1_params(&intern->inner.zobject, intern->inner.ce, NULL, "seek", NULL, &zpos); zval_ptr_dtor(&zpos); if (!EG(exception)) { intern->current.pos = pos; - if (spl_limit_it_valid(intern TSRMLS_CC) == SUCCESS) { - spl_dual_it_fetch(intern, 0 TSRMLS_CC); + if (spl_limit_it_valid(intern) == SUCCESS) { + spl_dual_it_fetch(intern, 0); } } } else { /* emulate the forward seek, by next() calls */ /* a back ward seek is done by a previous rewind() */ if (pos < intern->current.pos) { - spl_dual_it_rewind(intern TSRMLS_CC); + spl_dual_it_rewind(intern); } - while (pos > intern->current.pos && spl_dual_it_valid(intern TSRMLS_CC) == SUCCESS) { - spl_dual_it_next(intern, 1 TSRMLS_CC); + while (pos > intern->current.pos && spl_dual_it_valid(intern) == SUCCESS) { + spl_dual_it_next(intern, 1); } - if (spl_dual_it_valid(intern TSRMLS_CC) == SUCCESS) { - spl_dual_it_fetch(intern, 1 TSRMLS_CC); + if (spl_dual_it_valid(intern) == SUCCESS) { + spl_dual_it_fetch(intern, 1); } } } @@ -2581,15 +2532,15 @@ SPL_METHOD(LimitIterator, __construct) spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_LimitIterator, zend_ce_iterator, DIT_LimitIterator); } /* }}} */ -/* {{{ proto void LimitIterator::rewind() +/* {{{ proto void LimitIterator::rewind() Rewind the iterator to the specified starting offset */ SPL_METHOD(LimitIterator, rewind) { spl_dual_it_object *intern; SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - spl_dual_it_rewind(intern TSRMLS_CC); - spl_limit_it_seek(intern, intern->u.limit.offset TSRMLS_CC); + spl_dual_it_rewind(intern); + spl_limit_it_seek(intern, intern->u.limit.offset); } /* }}} */ /* {{{ proto bool LimitIterator::valid() @@ -2600,8 +2551,8 @@ SPL_METHOD(LimitIterator, valid) SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); -/* RETURN_BOOL(spl_limit_it_valid(intern TSRMLS_CC) == SUCCESS);*/ - RETURN_BOOL((intern->u.limit.count == -1 || intern->current.pos < intern->u.limit.offset + intern->u.limit.count) && intern->current.data); +/* RETURN_BOOL(spl_limit_it_valid(intern) == SUCCESS);*/ + RETURN_BOOL((intern->u.limit.count == -1 || intern->current.pos < intern->u.limit.offset + intern->u.limit.count) && Z_TYPE(intern->current.data) != IS_UNDEF); } /* }}} */ /* {{{ proto void LimitIterator::next() @@ -2612,9 +2563,9 @@ SPL_METHOD(LimitIterator, next) SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - spl_dual_it_next(intern, 1 TSRMLS_CC); + spl_dual_it_next(intern, 1); if (intern->u.limit.count == -1 || intern->current.pos < intern->u.limit.offset + intern->u.limit.count) { - spl_dual_it_fetch(intern, 1 TSRMLS_CC); + spl_dual_it_fetch(intern, 1); } } /* }}} */ @@ -2623,14 +2574,14 @@ SPL_METHOD(LimitIterator, next) SPL_METHOD(LimitIterator, seek) { spl_dual_it_object *intern; - long pos; + zend_long pos; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &pos) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &pos) == FAILURE) { return; } SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - spl_limit_it_seek(intern, pos TSRMLS_CC); + spl_limit_it_seek(intern, pos); RETURN_LONG(intern->current.pos); } /* }}} */ @@ -2643,7 +2594,7 @@ SPL_METHOD(LimitIterator, getPosition) RETURN_LONG(intern->current.pos); } /* }}} */ -ZEND_BEGIN_ARG_INFO(arginfo_seekable_it_seek, 0) +ZEND_BEGIN_ARG_INFO(arginfo_seekable_it_seek, 0) ZEND_ARG_INFO(0, position) ZEND_END_ARG_INFO(); @@ -2652,13 +2603,13 @@ static const zend_function_entry spl_funcs_SeekableIterator[] = { PHP_FE_END }; -ZEND_BEGIN_ARG_INFO_EX(arginfo_limit_it___construct, 0, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_limit_it___construct, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0) ZEND_ARG_INFO(0, offset) ZEND_ARG_INFO(0, count) ZEND_END_ARG_INFO(); -ZEND_BEGIN_ARG_INFO(arginfo_limit_it_seek, 0) +ZEND_BEGIN_ARG_INFO(arginfo_limit_it_seek, 0) ZEND_ARG_INFO(0, position) ZEND_END_ARG_INFO(); @@ -2675,69 +2626,62 @@ static const zend_function_entry spl_funcs_LimitIterator[] = { PHP_FE_END }; -static inline int spl_caching_it_valid(spl_dual_it_object *intern TSRMLS_DC) +static inline int spl_caching_it_valid(spl_dual_it_object *intern) { return intern->u.caching.flags & CIT_VALID ? SUCCESS : FAILURE; } -static inline int spl_caching_it_has_next(spl_dual_it_object *intern TSRMLS_DC) +static inline int spl_caching_it_has_next(spl_dual_it_object *intern) { - return spl_dual_it_valid(intern TSRMLS_CC); + return spl_dual_it_valid(intern); } -static inline void spl_caching_it_next(spl_dual_it_object *intern TSRMLS_DC) +static inline void spl_caching_it_next(spl_dual_it_object *intern) { - if (spl_dual_it_fetch(intern, 1 TSRMLS_CC) == SUCCESS) { + if (spl_dual_it_fetch(intern, 1) == SUCCESS) { intern->u.caching.flags |= CIT_VALID; /* Full cache ? */ if (intern->u.caching.flags & CIT_FULL_CACHE) { - zval *zcacheval; - zval *key = intern->current.key; - - MAKE_STD_ZVAL(zcacheval); - ZVAL_ZVAL(zcacheval, intern->current.data, 1, 0); - - array_set_zval_key(HASH_OF(intern->u.caching.zcache), key, zcacheval); + zval *key = &intern->current.key; + zval *data = &intern->current.data; - zval_ptr_dtor(&zcacheval); + ZVAL_DEREF(data); + Z_TRY_ADDREF_P(data); + array_set_zval_key(Z_ARRVAL(intern->u.caching.zcache), key, data); + zval_ptr_dtor(data); } /* Recursion ? */ if (intern->dit_type == DIT_RecursiveCachingIterator) { - zval *retval, *zchildren, zflags; + zval retval, zchildren, zflags; zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "haschildren", &retval); if (EG(exception)) { - if (retval) { - zval_ptr_dtor(&retval); - } + zval_ptr_dtor(&retval); if (intern->u.caching.flags & CIT_CATCH_GET_CHILD) { - zend_clear_exception(TSRMLS_C); + zend_clear_exception(); } else { return; } } else { - if (zend_is_true(retval)) { + if (zend_is_true(&retval)) { zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &zchildren); if (EG(exception)) { - if (zchildren) { - zval_ptr_dtor(&zchildren); - } + zval_ptr_dtor(&zchildren); if (intern->u.caching.flags & CIT_CATCH_GET_CHILD) { - zend_clear_exception(TSRMLS_C); + zend_clear_exception(); } else { zval_ptr_dtor(&retval); return; } } else { - INIT_PZVAL(&zflags); ZVAL_LONG(&zflags, intern->u.caching.flags & CIT_PUBLIC); - spl_instantiate_arg_ex2(spl_ce_RecursiveCachingIterator, &intern->u.caching.zchildren, 1, zchildren, &zflags TSRMLS_CC); + spl_instantiate_arg_ex2(spl_ce_RecursiveCachingIterator, &intern->u.caching.zchildren, &zchildren, &zflags); zval_ptr_dtor(&zchildren); } } zval_ptr_dtor(&retval); if (EG(exception)) { if (intern->u.caching.flags & CIT_CATCH_GET_CHILD) { - zend_clear_exception(TSRMLS_C); + zend_clear_exception(); } else { return; } @@ -2747,34 +2691,29 @@ static inline void spl_caching_it_next(spl_dual_it_object *intern TSRMLS_DC) if (intern->u.caching.flags & (CIT_TOSTRING_USE_INNER|CIT_CALL_TOSTRING)) { int use_copy; zval expr_copy; - ALLOC_ZVAL(intern->u.caching.zstr); if (intern->u.caching.flags & CIT_TOSTRING_USE_INNER) { - *intern->u.caching.zstr = *intern->inner.zobject; + ZVAL_COPY_VALUE(&intern->u.caching.zstr, &intern->inner.zobject); } else { - *intern->u.caching.zstr = *intern->current.data; + ZVAL_COPY_VALUE(&intern->u.caching.zstr, &intern->current.data); } - zend_make_printable_zval(intern->u.caching.zstr, &expr_copy, &use_copy); + use_copy = zend_make_printable_zval(&intern->u.caching.zstr, &expr_copy); if (use_copy) { - *intern->u.caching.zstr = expr_copy; - INIT_PZVAL(intern->u.caching.zstr); - zval_copy_ctor(intern->u.caching.zstr); - zval_dtor(&expr_copy); - } else { - INIT_PZVAL(intern->u.caching.zstr); - zval_copy_ctor(intern->u.caching.zstr); + ZVAL_COPY_VALUE(&intern->u.caching.zstr, &expr_copy); + } else if (Z_REFCOUNTED(intern->u.caching.zstr)) { + Z_ADDREF(intern->u.caching.zstr); } } - spl_dual_it_next(intern, 0 TSRMLS_CC); + spl_dual_it_next(intern, 0); } else { intern->u.caching.flags &= ~CIT_VALID; } } -static inline void spl_caching_it_rewind(spl_dual_it_object *intern TSRMLS_DC) +static inline void spl_caching_it_rewind(spl_dual_it_object *intern) { - spl_dual_it_rewind(intern TSRMLS_CC); - zend_hash_clean(HASH_OF(intern->u.caching.zcache)); - spl_caching_it_next(intern TSRMLS_CC); + spl_dual_it_rewind(intern); + zend_hash_clean(Z_ARRVAL(intern->u.caching.zcache)); + spl_caching_it_next(intern); } /* {{{ proto void CachingIterator::__construct(Iterator it [, flags = CIT_CALL_TOSTRING]) @@ -2789,14 +2728,14 @@ SPL_METHOD(CachingIterator, __construct) SPL_METHOD(CachingIterator, rewind) { spl_dual_it_object *intern; - + if (zend_parse_parameters_none() == FAILURE) { return; } SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - spl_caching_it_rewind(intern TSRMLS_CC); + spl_caching_it_rewind(intern); } /* }}} */ /* {{{ proto bool CachingIterator::valid() @@ -2804,14 +2743,14 @@ SPL_METHOD(CachingIterator, rewind) SPL_METHOD(CachingIterator, valid) { spl_dual_it_object *intern; - + if (zend_parse_parameters_none() == FAILURE) { return; } SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - RETURN_BOOL(spl_caching_it_valid(intern TSRMLS_CC) == SUCCESS); + RETURN_BOOL(spl_caching_it_valid(intern) == SUCCESS); } /* }}} */ /* {{{ proto void CachingIterator::next() @@ -2819,14 +2758,14 @@ SPL_METHOD(CachingIterator, valid) SPL_METHOD(CachingIterator, next) { spl_dual_it_object *intern; - + if (zend_parse_parameters_none() == FAILURE) { return; } SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - spl_caching_it_next(intern TSRMLS_CC); + spl_caching_it_next(intern); } /* }}} */ /* {{{ proto bool CachingIterator::hasNext() @@ -2834,14 +2773,14 @@ SPL_METHOD(CachingIterator, next) SPL_METHOD(CachingIterator, hasNext) { spl_dual_it_object *intern; - + if (zend_parse_parameters_none() == FAILURE) { return; } SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - RETURN_BOOL(spl_caching_it_has_next(intern TSRMLS_CC) == SUCCESS); + RETURN_BOOL(spl_caching_it_has_next(intern) == SUCCESS); } /* }}} */ /* {{{ proto string CachingIterator::__toString() @@ -2853,20 +2792,20 @@ SPL_METHOD(CachingIterator, __toString) SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); if (!(intern->u.caching.flags & (CIT_CALL_TOSTRING|CIT_TOSTRING_USE_KEY|CIT_TOSTRING_USE_CURRENT|CIT_TOSTRING_USE_INNER))) { - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "%s does not fetch string value (see CachingIterator::__construct)", Z_OBJCE_P(getThis())->name); + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s does not fetch string value (see CachingIterator::__construct)", ZSTR_VAL(Z_OBJCE_P(getThis())->name)); return; } if (intern->u.caching.flags & CIT_TOSTRING_USE_KEY) { - MAKE_COPY_ZVAL(&intern->current.key, return_value); + ZVAL_COPY(return_value, &intern->current.key); convert_to_string(return_value); return; } else if (intern->u.caching.flags & CIT_TOSTRING_USE_CURRENT) { - MAKE_COPY_ZVAL(&intern->current.data, return_value); + ZVAL_COPY(return_value, &intern->current.data); convert_to_string(return_value); return; } - if (intern->u.caching.zstr) { - RETURN_STRINGL(Z_STRVAL_P(intern->u.caching.zstr), Z_STRLEN_P(intern->u.caching.zstr), 1); + if (Z_TYPE(intern->u.caching.zstr) == IS_STRING) { + RETURN_STR_COPY(Z_STR_P(&intern->u.caching.zstr)); } else { RETURN_NULL(); } @@ -2877,23 +2816,24 @@ SPL_METHOD(CachingIterator, __toString) SPL_METHOD(CachingIterator, offsetSet) { spl_dual_it_object *intern; - char *arKey; - uint nKeyLength; + zend_string *key; zval *value; SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); if (!(intern->u.caching.flags & CIT_FULL_CACHE)) { - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "%s does not use a full cache (see CachingIterator::__construct)", Z_OBJCE_P(getThis())->name); + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s does not use a full cache (see CachingIterator::__construct)", ZSTR_VAL(Z_OBJCE_P(getThis())->name)); return; } - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &arKey, &nKeyLength, &value) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz", &key, &value) == FAILURE) { return; } - Z_ADDREF_P(value); - zend_symtable_update(HASH_OF(intern->u.caching.zcache), arKey, nKeyLength+1, &value, sizeof(value), NULL); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zend_symtable_update(Z_ARRVAL(intern->u.caching.zcache), key, value); } /* }}} */ @@ -2902,27 +2842,27 @@ SPL_METHOD(CachingIterator, offsetSet) SPL_METHOD(CachingIterator, offsetGet) { spl_dual_it_object *intern; - char *arKey; - uint nKeyLength; - zval **value; + zend_string *key; + zval *value; SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); if (!(intern->u.caching.flags & CIT_FULL_CACHE)) { - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "%s does not use a full cache (see CachingIterator::__construct)", Z_OBJCE_P(getThis())->name); + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s does not use a full cache (see CachingIterator::__construct)", ZSTR_VAL(Z_OBJCE_P(getThis())->name)); return; } - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arKey, &nKeyLength) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &key) == FAILURE) { return; } - if (zend_symtable_find(HASH_OF(intern->u.caching.zcache), arKey, nKeyLength+1, (void**)&value) == FAILURE) { - zend_error(E_NOTICE, "Undefined index: %s", arKey); + if ((value = zend_symtable_find(Z_ARRVAL(intern->u.caching.zcache), key)) == NULL) { + zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(key)); return; } - - RETURN_ZVAL(*value, 1, 0); + + ZVAL_DEREF(value); + ZVAL_COPY(return_value, value); } /* }}} */ @@ -2931,21 +2871,20 @@ SPL_METHOD(CachingIterator, offsetGet) SPL_METHOD(CachingIterator, offsetUnset) { spl_dual_it_object *intern; - char *arKey; - uint nKeyLength; + zend_string *key; SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); if (!(intern->u.caching.flags & CIT_FULL_CACHE)) { - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "%s does not use a full cache (see CachingIterator::__construct)", Z_OBJCE_P(getThis())->name); + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s does not use a full cache (see CachingIterator::__construct)", ZSTR_VAL(Z_OBJCE_P(getThis())->name)); return; } - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arKey, &nKeyLength) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &key) == FAILURE) { return; } - zend_symtable_del(HASH_OF(intern->u.caching.zcache), arKey, nKeyLength+1); + zend_symtable_del(Z_ARRVAL(intern->u.caching.zcache), key); } /* }}} */ @@ -2954,21 +2893,20 @@ SPL_METHOD(CachingIterator, offsetUnset) SPL_METHOD(CachingIterator, offsetExists) { spl_dual_it_object *intern; - char *arKey; - uint nKeyLength; - + zend_string *key; + SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); if (!(intern->u.caching.flags & CIT_FULL_CACHE)) { - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "%s does not use a full cache (see CachingIterator::__construct)", Z_OBJCE_P(getThis())->name); + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s does not use a full cache (see CachingIterator::__construct)", ZSTR_VAL(Z_OBJCE_P(getThis())->name)); return; } - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arKey, &nKeyLength) == FAILURE) { + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &key) == FAILURE) { return; } - RETURN_BOOL(zend_symtable_exists(HASH_OF(intern->u.caching.zcache), arKey, nKeyLength+1)); + RETURN_BOOL(zend_symtable_exists(Z_ARRVAL(intern->u.caching.zcache), key)); } /* }}} */ @@ -2977,19 +2915,19 @@ SPL_METHOD(CachingIterator, offsetExists) SPL_METHOD(CachingIterator, getCache) { spl_dual_it_object *intern; - + if (zend_parse_parameters_none() == FAILURE) { return; } - + SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); if (!(intern->u.caching.flags & CIT_FULL_CACHE)) { - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "%v does not use a full cache (see CachingIterator::__construct)", Z_OBJCE_P(getThis())->name); + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%v does not use a full cache (see CachingIterator::__construct)", ZSTR_VAL(Z_OBJCE_P(getThis())->name)); return; } - RETURN_ZVAL(intern->u.caching.zcache, 1, 0); + ZVAL_COPY(return_value, &intern->u.caching.zcache); } /* }}} */ @@ -3002,7 +2940,7 @@ SPL_METHOD(CachingIterator, getFlags) if (zend_parse_parameters_none() == FAILURE) { return; } - + SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); RETURN_LONG(intern->u.caching.flags); @@ -3014,29 +2952,29 @@ SPL_METHOD(CachingIterator, getFlags) SPL_METHOD(CachingIterator, setFlags) { spl_dual_it_object *intern; - long flags; + zend_long flags; SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &flags) == FAILURE) { return; } if (spl_cit_check_flags(flags) != SUCCESS) { - zend_throw_exception(spl_ce_InvalidArgumentException , "Flags must contain only one of CALL_TOSTRING, TOSTRING_USE_KEY, TOSTRING_USE_CURRENT, TOSTRING_USE_INNER", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_InvalidArgumentException , "Flags must contain only one of CALL_TOSTRING, TOSTRING_USE_KEY, TOSTRING_USE_CURRENT, TOSTRING_USE_INNER", 0); return; } if ((intern->u.caching.flags & CIT_CALL_TOSTRING) != 0 && (flags & CIT_CALL_TOSTRING) == 0) { - zend_throw_exception(spl_ce_InvalidArgumentException, "Unsetting flag CALL_TO_STRING is not possible", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_InvalidArgumentException, "Unsetting flag CALL_TO_STRING is not possible", 0); return; } if ((intern->u.caching.flags & CIT_TOSTRING_USE_INNER) != 0 && (flags & CIT_TOSTRING_USE_INNER) == 0) { - zend_throw_exception(spl_ce_InvalidArgumentException, "Unsetting flag TOSTRING_USE_INNER is not possible", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_InvalidArgumentException, "Unsetting flag TOSTRING_USE_INNER is not possible", 0); return; } if ((flags & CIT_FULL_CACHE) != 0 && (intern->u.caching.flags & CIT_FULL_CACHE) == 0) { /* clear on (re)enable */ - zend_hash_clean(HASH_OF(intern->u.caching.zcache)); + zend_hash_clean(Z_ARRVAL(intern->u.caching.zcache)); } intern->u.caching.flags = (intern->u.caching.flags & ~CIT_PUBLIC) | (flags & CIT_PUBLIC); } @@ -3051,24 +2989,24 @@ SPL_METHOD(CachingIterator, count) if (zend_parse_parameters_none() == FAILURE) { return; } - + SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); if (!(intern->u.caching.flags & CIT_FULL_CACHE)) { - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "%v does not use a full cache (see CachingIterator::__construct)", Z_OBJCE_P(getThis())->name); + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%v does not use a full cache (see CachingIterator::__construct)", ZSTR_VAL(Z_OBJCE_P(getThis())->name)); return; } - RETURN_LONG(zend_hash_num_elements(HASH_OF(intern->u.caching.zcache))); + RETURN_LONG(zend_hash_num_elements(Z_ARRVAL(intern->u.caching.zcache))); } /* }}} */ -ZEND_BEGIN_ARG_INFO_EX(arginfo_caching_it___construct, 0, 0, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_caching_it___construct, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0) ZEND_ARG_INFO(0, flags) ZEND_END_ARG_INFO(); -ZEND_BEGIN_ARG_INFO(arginfo_caching_it_setFlags, 0) +ZEND_BEGIN_ARG_INFO(arginfo_caching_it_setFlags, 0) ZEND_ARG_INFO(0, flags) ZEND_END_ARG_INFO(); @@ -3118,10 +3056,10 @@ SPL_METHOD(RecursiveCachingIterator, hasChildren) if (zend_parse_parameters_none() == FAILURE) { return; } - + SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - RETURN_BOOL(intern->u.caching.zchildren); + RETURN_BOOL(Z_TYPE(intern->u.caching.zchildren) != IS_UNDEF); } /* }}} */ /* {{{ proto RecursiveCachingIterator RecursiveCachingIterator::getChildren() @@ -3129,21 +3067,24 @@ SPL_METHOD(RecursiveCachingIterator, hasChildren) SPL_METHOD(RecursiveCachingIterator, getChildren) { spl_dual_it_object *intern; - + if (zend_parse_parameters_none() == FAILURE) { return; } SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - if (intern->u.caching.zchildren) { - RETURN_ZVAL(intern->u.caching.zchildren, 1, 0); + if (Z_TYPE(intern->u.caching.zchildren) != IS_UNDEF) { + zval *value = &intern->u.caching.zchildren; + + ZVAL_DEREF(value); + ZVAL_COPY(return_value, value); } else { RETURN_NULL(); } } /* }}} */ -ZEND_BEGIN_ARG_INFO_EX(arginfo_caching_rec_it___construct, 0, ZEND_RETURN_VALUE, 1) +ZEND_BEGIN_ARG_INFO_EX(arginfo_caching_rec_it___construct, 0, ZEND_RETURN_VALUE, 1) ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0) ZEND_ARG_INFO(0, flags) ZEND_END_ARG_INFO(); @@ -3162,7 +3103,7 @@ SPL_METHOD(IteratorIterator, __construct) spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_IteratorIterator, zend_ce_traversable, DIT_IteratorIterator); } /* }}} */ -ZEND_BEGIN_ARG_INFO(arginfo_iterator_it___construct, 0) +ZEND_BEGIN_ARG_INFO(arginfo_iterator_it___construct, 0) ZEND_ARG_OBJ_INFO(0, iterator, Traversable, 0) ZEND_END_ARG_INFO(); @@ -3199,13 +3140,13 @@ SPL_METHOD(NoRewindIterator, rewind) SPL_METHOD(NoRewindIterator, valid) { spl_dual_it_object *intern; - + if (zend_parse_parameters_none() == FAILURE) { return; } SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - RETURN_BOOL(intern->inner.iterator->funcs->valid(intern->inner.iterator TSRMLS_CC) == SUCCESS); + RETURN_BOOL(intern->inner.iterator->funcs->valid(intern->inner.iterator) == SUCCESS); } /* }}} */ /* {{{ proto mixed NoRewindIterator::key() @@ -3213,7 +3154,7 @@ SPL_METHOD(NoRewindIterator, valid) SPL_METHOD(NoRewindIterator, key) { spl_dual_it_object *intern; - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -3221,7 +3162,7 @@ SPL_METHOD(NoRewindIterator, key) SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); if (intern->inner.iterator->funcs->get_current_key) { - intern->inner.iterator->funcs->get_current_key(intern->inner.iterator, return_value TSRMLS_CC); + intern->inner.iterator->funcs->get_current_key(intern->inner.iterator, return_value); } else { RETURN_NULL(); } @@ -3232,16 +3173,17 @@ SPL_METHOD(NoRewindIterator, key) SPL_METHOD(NoRewindIterator, current) { spl_dual_it_object *intern; - zval **data; - + zval *data; + if (zend_parse_parameters_none() == FAILURE) { return; } SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - intern->inner.iterator->funcs->get_current_data(intern->inner.iterator, &data TSRMLS_CC); - if (data && *data) { - RETURN_ZVAL(*data, 1, 0); + data = intern->inner.iterator->funcs->get_current_data(intern->inner.iterator); + if (data) { + ZVAL_DEREF(data); + ZVAL_COPY(return_value, data); } } /* }}} */ @@ -3250,16 +3192,16 @@ SPL_METHOD(NoRewindIterator, current) SPL_METHOD(NoRewindIterator, next) { spl_dual_it_object *intern; - + if (zend_parse_parameters_none() == FAILURE) { return; } SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - intern->inner.iterator->funcs->move_forward(intern->inner.iterator TSRMLS_CC); + intern->inner.iterator->funcs->move_forward(intern->inner.iterator); } /* }}} */ -ZEND_BEGIN_ARG_INFO(arginfo_norewind_it___construct, 0) +ZEND_BEGIN_ARG_INFO(arginfo_norewind_it___construct, 0) ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0) ZEND_END_ARG_INFO(); @@ -3286,20 +3228,20 @@ SPL_METHOD(InfiniteIterator, __construct) SPL_METHOD(InfiniteIterator, next) { spl_dual_it_object *intern; - + if (zend_parse_parameters_none() == FAILURE) { return; } SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - spl_dual_it_next(intern, 1 TSRMLS_CC); - if (spl_dual_it_valid(intern TSRMLS_CC) == SUCCESS) { - spl_dual_it_fetch(intern, 0 TSRMLS_CC); + spl_dual_it_next(intern, 1); + if (spl_dual_it_valid(intern) == SUCCESS) { + spl_dual_it_fetch(intern, 0); } else { - spl_dual_it_rewind(intern TSRMLS_CC); - if (spl_dual_it_valid(intern TSRMLS_CC) == SUCCESS) { - spl_dual_it_fetch(intern, 0 TSRMLS_CC); + spl_dual_it_rewind(intern); + if (spl_dual_it_valid(intern) == SUCCESS) { + spl_dual_it_fetch(intern, 0); } } } /* }}} */ @@ -3336,7 +3278,7 @@ SPL_METHOD(EmptyIterator, key) if (zend_parse_parameters_none() == FAILURE) { return; } - zend_throw_exception(spl_ce_BadMethodCallException, "Accessing the key of an EmptyIterator", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_BadMethodCallException, "Accessing the key of an EmptyIterator", 0); } /* }}} */ /* {{{ proto void EmptyIterator::current() @@ -3346,7 +3288,7 @@ SPL_METHOD(EmptyIterator, current) if (zend_parse_parameters_none() == FAILURE) { return; } - zend_throw_exception(spl_ce_BadMethodCallException, "Accessing the value of an EmptyIterator", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_BadMethodCallException, "Accessing the value of an EmptyIterator", 0); } /* }}} */ /* {{{ proto void EmptyIterator::next() @@ -3367,53 +3309,50 @@ static const zend_function_entry spl_funcs_EmptyIterator[] = { PHP_FE_END }; -int spl_append_it_next_iterator(spl_dual_it_object *intern TSRMLS_DC) /* {{{*/ +int spl_append_it_next_iterator(spl_dual_it_object *intern) /* {{{*/ { - spl_dual_it_free(intern TSRMLS_CC); + spl_dual_it_free(intern); - if (intern->inner.zobject) { + if (!Z_ISUNDEF(intern->inner.zobject)) { zval_ptr_dtor(&intern->inner.zobject); - intern->inner.zobject = NULL; + ZVAL_UNDEF(&intern->inner.zobject); intern->inner.ce = NULL; - intern->inner.object = NULL; if (intern->inner.iterator) { - intern->inner.iterator->funcs->dtor(intern->inner.iterator TSRMLS_CC); + zend_iterator_dtor(intern->inner.iterator); intern->inner.iterator = NULL; } } - if (intern->u.append.iterator->funcs->valid(intern->u.append.iterator TSRMLS_CC) == SUCCESS) { - zval **it; + if (intern->u.append.iterator->funcs->valid(intern->u.append.iterator) == SUCCESS) { + zval *it; - intern->u.append.iterator->funcs->get_current_data(intern->u.append.iterator, &it TSRMLS_CC); - Z_ADDREF_PP(it); - intern->inner.zobject = *it; - intern->inner.ce = Z_OBJCE_PP(it); - intern->inner.object = zend_object_store_get_object(*it TSRMLS_CC); - intern->inner.iterator = intern->inner.ce->get_iterator(intern->inner.ce, *it, 0 TSRMLS_CC); - spl_dual_it_rewind(intern TSRMLS_CC); + it = intern->u.append.iterator->funcs->get_current_data(intern->u.append.iterator); + ZVAL_COPY(&intern->inner.zobject, it); + intern->inner.ce = Z_OBJCE_P(it); + intern->inner.iterator = intern->inner.ce->get_iterator(intern->inner.ce, it, 0); + spl_dual_it_rewind(intern); return SUCCESS; } else { return FAILURE; } } /* }}} */ -void spl_append_it_fetch(spl_dual_it_object *intern TSRMLS_DC) /* {{{*/ +void spl_append_it_fetch(spl_dual_it_object *intern) /* {{{*/ { - while (spl_dual_it_valid(intern TSRMLS_CC) != SUCCESS) { - intern->u.append.iterator->funcs->move_forward(intern->u.append.iterator TSRMLS_CC); - if (spl_append_it_next_iterator(intern TSRMLS_CC) != SUCCESS) { + while (spl_dual_it_valid(intern) != SUCCESS) { + intern->u.append.iterator->funcs->move_forward(intern->u.append.iterator); + if (spl_append_it_next_iterator(intern) != SUCCESS) { return; } } - spl_dual_it_fetch(intern, 0 TSRMLS_CC); + spl_dual_it_fetch(intern, 0); } /* }}} */ -void spl_append_it_next(spl_dual_it_object *intern TSRMLS_DC) /* {{{ */ +void spl_append_it_next(spl_dual_it_object *intern) /* {{{ */ { - if (spl_dual_it_valid(intern TSRMLS_CC) == SUCCESS) { - spl_dual_it_next(intern, 1 TSRMLS_CC); + if (spl_dual_it_valid(intern) == SUCCESS) { + spl_dual_it_next(intern, 1); } - spl_append_it_fetch(intern TSRMLS_CC); + spl_append_it_fetch(intern); } /* }}} */ /* {{{ proto void AppendIterator::__construct() @@ -3432,19 +3371,19 @@ SPL_METHOD(AppendIterator, append) SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "O", &it, zend_ce_iterator) == FAILURE) { + if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "O", &it, zend_ce_iterator) == FAILURE) { return; } - spl_array_iterator_append(intern->u.append.zarrayit, it TSRMLS_CC); + spl_array_iterator_append(&intern->u.append.zarrayit, it); - if (!intern->inner.iterator || spl_dual_it_valid(intern TSRMLS_CC) != SUCCESS) { - if (intern->u.append.iterator->funcs->valid(intern->u.append.iterator TSRMLS_CC) != SUCCESS) { - intern->u.append.iterator->funcs->rewind(intern->u.append.iterator TSRMLS_CC); + if (!intern->inner.iterator || spl_dual_it_valid(intern) != SUCCESS) { + if (intern->u.append.iterator->funcs->valid(intern->u.append.iterator) != SUCCESS) { + intern->u.append.iterator->funcs->rewind(intern->u.append.iterator); } do { - spl_append_it_next_iterator(intern TSRMLS_CC); - } while (intern->inner.zobject != it); - spl_append_it_fetch(intern TSRMLS_CC); + spl_append_it_next_iterator(intern); + } while (Z_OBJ(intern->inner.zobject) != Z_OBJ_P(it)); + spl_append_it_fetch(intern); } } /* }}} */ @@ -3453,16 +3392,16 @@ SPL_METHOD(AppendIterator, append) SPL_METHOD(AppendIterator, rewind) { spl_dual_it_object *intern; - + if (zend_parse_parameters_none() == FAILURE) { return; } SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - - intern->u.append.iterator->funcs->rewind(intern->u.append.iterator TSRMLS_CC); - if (spl_append_it_next_iterator(intern TSRMLS_CC) == SUCCESS) { - spl_append_it_fetch(intern TSRMLS_CC); + + intern->u.append.iterator->funcs->rewind(intern->u.append.iterator); + if (spl_append_it_next_iterator(intern) == SUCCESS) { + spl_append_it_fetch(intern); } } /* }}} */ @@ -3475,10 +3414,10 @@ SPL_METHOD(AppendIterator, valid) if (zend_parse_parameters_none() == FAILURE) { return; } - + SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - RETURN_BOOL(intern->current.data); + RETURN_BOOL(Z_TYPE(intern->current.data) != IS_UNDEF); } /* }}} */ /* {{{ proto void AppendIterator::next() @@ -3486,14 +3425,14 @@ SPL_METHOD(AppendIterator, valid) SPL_METHOD(AppendIterator, next) { spl_dual_it_object *intern; - + if (zend_parse_parameters_none() == FAILURE) { return; } SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - - spl_append_it_next(intern TSRMLS_CC); + + spl_append_it_next(intern); } /* }}} */ /* {{{ proto int AppendIterator::getIteratorIndex() @@ -3501,7 +3440,7 @@ SPL_METHOD(AppendIterator, next) SPL_METHOD(AppendIterator, getIteratorIndex) { spl_dual_it_object *intern; - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -3509,7 +3448,7 @@ SPL_METHOD(AppendIterator, getIteratorIndex) SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); APPENDIT_CHECK_CTOR(intern); - spl_array_iterator_key(intern->u.append.zarrayit, return_value TSRMLS_CC); + spl_array_iterator_key(&intern->u.append.zarrayit, return_value); } /* }}} */ /* {{{ proto ArrayIterator AppendIterator::getArrayIterator() @@ -3517,17 +3456,20 @@ SPL_METHOD(AppendIterator, getIteratorIndex) SPL_METHOD(AppendIterator, getArrayIterator) { spl_dual_it_object *intern; - + zval *value; + if (zend_parse_parameters_none() == FAILURE) { return; } SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); - RETURN_ZVAL(intern->u.append.zarrayit, 1, 0); + value = &intern->u.append.zarrayit; + ZVAL_DEREF(value); + ZVAL_COPY(return_value, value); } /* }}} */ -ZEND_BEGIN_ARG_INFO(arginfo_append_it_append, 0) +ZEND_BEGIN_ARG_INFO(arginfo_append_it_append, 0) ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0) ZEND_END_ARG_INFO(); @@ -3545,12 +3487,12 @@ static const zend_function_entry spl_funcs_AppendIterator[] = { PHP_FE_END }; -PHPAPI int spl_iterator_apply(zval *obj, spl_iterator_apply_func_t apply_func, void *puser TSRMLS_DC) +PHPAPI int spl_iterator_apply(zval *obj, spl_iterator_apply_func_t apply_func, void *puser) { zend_object_iterator *iter; zend_class_entry *ce = Z_OBJCE_P(obj); - iter = ce->get_iterator(ce, obj, 0 TSRMLS_CC); + iter = ce->get_iterator(ce, obj, 0); if (EG(exception)) { goto done; @@ -3558,21 +3500,21 @@ PHPAPI int spl_iterator_apply(zval *obj, spl_iterator_apply_func_t apply_func, v iter->index = 0; if (iter->funcs->rewind) { - iter->funcs->rewind(iter TSRMLS_CC); + iter->funcs->rewind(iter); if (EG(exception)) { goto done; } } - while (iter->funcs->valid(iter TSRMLS_CC) == SUCCESS) { + while (iter->funcs->valid(iter) == SUCCESS) { if (EG(exception)) { goto done; } - if (apply_func(iter, puser TSRMLS_CC) == ZEND_HASH_APPLY_STOP || EG(exception)) { + if (apply_func(iter, puser) == ZEND_HASH_APPLY_STOP || EG(exception)) { goto done; } iter->index++; - iter->funcs->move_forward(iter TSRMLS_CC); + iter->funcs->move_forward(iter); if (EG(exception)) { goto done; } @@ -3580,94 +3522,96 @@ PHPAPI int spl_iterator_apply(zval *obj, spl_iterator_apply_func_t apply_func, v done: if (iter) { - iter->funcs->dtor(iter TSRMLS_CC); + zend_iterator_dtor(iter); } return EG(exception) ? FAILURE : SUCCESS; } /* }}} */ -static int spl_iterator_to_array_apply(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{ */ +static int spl_iterator_to_array_apply(zend_object_iterator *iter, void *puser) /* {{{ */ { - zval **data, *return_value = (zval*)puser; + zval *data, *return_value = (zval*)puser; - iter->funcs->get_current_data(iter, &data TSRMLS_CC); + data = iter->funcs->get_current_data(iter); if (EG(exception)) { return ZEND_HASH_APPLY_STOP; } - if (data == NULL || *data == NULL) { + if (data == NULL) { return ZEND_HASH_APPLY_STOP; } if (iter->funcs->get_current_key) { zval key; - iter->funcs->get_current_key(iter, &key TSRMLS_CC); + iter->funcs->get_current_key(iter, &key); if (EG(exception)) { return ZEND_HASH_APPLY_STOP; } - array_set_zval_key(Z_ARRVAL_P(return_value), &key, *data); - zval_dtor(&key); + array_set_zval_key(Z_ARRVAL_P(return_value), &key, data); + zval_ptr_dtor(&key); } else { - Z_ADDREF_PP(data); - add_next_index_zval(return_value, *data); + Z_TRY_ADDREF_P(data); + add_next_index_zval(return_value, data); } return ZEND_HASH_APPLY_KEEP; } /* }}} */ -static int spl_iterator_to_values_apply(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{ */ +static int spl_iterator_to_values_apply(zend_object_iterator *iter, void *puser) /* {{{ */ { - zval **data, *return_value = (zval*)puser; + zval *data, *return_value = (zval*)puser; - iter->funcs->get_current_data(iter, &data TSRMLS_CC); + data = iter->funcs->get_current_data(iter); if (EG(exception)) { return ZEND_HASH_APPLY_STOP; } - if (data == NULL || *data == NULL) { + if (data == NULL) { return ZEND_HASH_APPLY_STOP; } - Z_ADDREF_PP(data); - add_next_index_zval(return_value, *data); + if (Z_REFCOUNTED_P(data)) { + Z_ADDREF_P(data); + } + add_next_index_zval(return_value, data); return ZEND_HASH_APPLY_KEEP; } /* }}} */ -/* {{{ proto array iterator_to_array(Traversable it [, bool use_keys = true]) +/* {{{ proto array iterator_to_array(Traversable it [, bool use_keys = true]) Copy the iterator into an array */ PHP_FUNCTION(iterator_to_array) { zval *obj; zend_bool use_keys = 1; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|b", &obj, zend_ce_traversable, &use_keys) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|b", &obj, zend_ce_traversable, &use_keys) == FAILURE) { RETURN_FALSE; } array_init(return_value); - if (spl_iterator_apply(obj, use_keys ? spl_iterator_to_array_apply : spl_iterator_to_values_apply, (void*)return_value TSRMLS_CC) != SUCCESS) { - zval_dtor(return_value); + if (spl_iterator_apply(obj, use_keys ? spl_iterator_to_array_apply : spl_iterator_to_values_apply, (void*)return_value) != SUCCESS) { + zval_ptr_dtor(return_value); RETURN_NULL(); } } /* }}} */ -static int spl_iterator_count_apply(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{ */ +static int spl_iterator_count_apply(zend_object_iterator *iter, void *puser) /* {{{ */ { - (*(long*)puser)++; + (*(zend_long*)puser)++; return ZEND_HASH_APPLY_KEEP; } /* }}} */ -/* {{{ proto int iterator_count(Traversable it) +/* {{{ proto int iterator_count(Traversable it) Count the elements in an iterator */ PHP_FUNCTION(iterator_count) { zval *obj; - long count = 0; + zend_long count = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &obj, zend_ce_traversable) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &obj, zend_ce_traversable) == FAILURE) { RETURN_FALSE; } - - if (spl_iterator_apply(obj, spl_iterator_count_apply, (void*)&count TSRMLS_CC) == SUCCESS) { + + if (spl_iterator_apply(obj, spl_iterator_count_apply, (void*)&count) == SUCCESS) { RETURN_LONG(count); } } @@ -3676,21 +3620,21 @@ PHP_FUNCTION(iterator_count) typedef struct { zval *obj; zval *args; - long count; + zend_long count; zend_fcall_info fci; zend_fcall_info_cache fcc; } spl_iterator_apply_info; -static int spl_iterator_func_apply(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{ */ +static int spl_iterator_func_apply(zend_object_iterator *iter, void *puser) /* {{{ */ { - zval *retval; + zval retval; spl_iterator_apply_info *apply_info = (spl_iterator_apply_info*)puser; int result; apply_info->count++; - zend_fcall_info_call(&apply_info->fci, &apply_info->fcc, &retval, NULL TSRMLS_CC); - if (retval) { - result = zend_is_true(retval) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_STOP; + zend_fcall_info_call(&apply_info->fci, &apply_info->fcc, &retval, NULL); + if (Z_TYPE(retval) != IS_UNDEF) { + result = zend_is_true(&retval) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_STOP; zval_ptr_dtor(&retval); } else { result = ZEND_HASH_APPLY_STOP; @@ -3706,18 +3650,18 @@ PHP_FUNCTION(iterator_apply) spl_iterator_apply_info apply_info; apply_info.args = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Of|a!", &apply_info.obj, zend_ce_traversable, &apply_info.fci, &apply_info.fcc, &apply_info.args) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Of|a!", &apply_info.obj, zend_ce_traversable, &apply_info.fci, &apply_info.fcc, &apply_info.args) == FAILURE) { return; } apply_info.count = 0; - zend_fcall_info_args(&apply_info.fci, apply_info.args TSRMLS_CC); - if (spl_iterator_apply(apply_info.obj, spl_iterator_func_apply, (void*)&apply_info TSRMLS_CC) == SUCCESS) { + zend_fcall_info_args(&apply_info.fci, apply_info.args); + if (spl_iterator_apply(apply_info.obj, spl_iterator_func_apply, (void*)&apply_info) == SUCCESS) { RETVAL_LONG(apply_info.count); } else { RETVAL_FALSE; } - zend_fcall_info_args(&apply_info.fci, NULL TSRMLS_CC); + zend_fcall_info_args(&apply_info.fci, NULL); } /* }}} */ @@ -3742,14 +3686,20 @@ PHP_MINIT_FUNCTION(spl_iterators) REGISTER_SPL_ITERATOR(RecursiveIteratorIterator); memcpy(&spl_handlers_rec_it_it, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + spl_handlers_rec_it_it.offset = XtOffsetOf(spl_recursive_it_object, std); spl_handlers_rec_it_it.get_method = spl_recursive_it_get_method; spl_handlers_rec_it_it.clone_obj = NULL; + spl_handlers_rec_it_it.dtor_obj = spl_RecursiveIteratorIterator_dtor; + spl_handlers_rec_it_it.free_obj = spl_RecursiveIteratorIterator_free_storage; memcpy(&spl_handlers_dual_it, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + spl_handlers_dual_it.offset = XtOffsetOf(spl_dual_it_object, std); spl_handlers_dual_it.get_method = spl_dual_it_get_method; /*spl_handlers_dual_it.call_method = spl_dual_it_call_method;*/ spl_handlers_dual_it.clone_obj = NULL; - + spl_handlers_dual_it.dtor_obj = spl_dual_it_dtor; + spl_handlers_dual_it.free_obj = spl_dual_it_free_storage; + spl_ce_RecursiveIteratorIterator->get_iterator = spl_recursive_it_get_iterator; spl_ce_RecursiveIteratorIterator->iterator_funcs.funcs = &spl_recursive_it_iterator_funcs; @@ -3789,16 +3739,16 @@ PHP_MINIT_FUNCTION(spl_iterators) REGISTER_SPL_IMPLEMENTS(CachingIterator, ArrayAccess); REGISTER_SPL_IMPLEMENTS(CachingIterator, Countable); - REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "CALL_TOSTRING", CIT_CALL_TOSTRING); - REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "CATCH_GET_CHILD", CIT_CATCH_GET_CHILD); + REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "CALL_TOSTRING", CIT_CALL_TOSTRING); + REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "CATCH_GET_CHILD", CIT_CATCH_GET_CHILD); REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "TOSTRING_USE_KEY", CIT_TOSTRING_USE_KEY); REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "TOSTRING_USE_CURRENT", CIT_TOSTRING_USE_CURRENT); REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "TOSTRING_USE_INNER", CIT_TOSTRING_USE_INNER); - REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "FULL_CACHE", CIT_FULL_CACHE); + REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "FULL_CACHE", CIT_FULL_CACHE); REGISTER_SPL_SUB_CLASS_EX(RecursiveCachingIterator, CachingIterator, spl_dual_it_new, spl_funcs_RecursiveCachingIterator); REGISTER_SPL_IMPLEMENTS(RecursiveCachingIterator, RecursiveIterator); - + REGISTER_SPL_SUB_CLASS_EX(NoRewindIterator, IteratorIterator, spl_dual_it_new, spl_funcs_NoRewindIterator); REGISTER_SPL_SUB_CLASS_EX(AppendIterator, IteratorIterator, spl_dual_it_new, spl_funcs_AppendIterator); diff --git a/ext/spl/spl_iterators.h b/ext/spl/spl_iterators.h index e19823297f..f128015111 100644 --- a/ext/spl/spl_iterators.h +++ b/ext/spl/spl_iterators.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -121,55 +121,61 @@ typedef enum { typedef struct _spl_cbfilter_it_intern { zend_fcall_info fci; zend_fcall_info_cache fcc; + zend_object *object; } _spl_cbfilter_it_intern; typedef struct _spl_dual_it_object { - zend_object std; struct { - zval *zobject; + zval zobject; zend_class_entry *ce; zend_object *object; zend_object_iterator *iterator; } inner; struct { - zval *data; - zval *key; - int pos; + zval data; + zval key; + zend_long pos; } current; dual_it_type dit_type; union { struct { - long offset; - long count; + zend_long offset; + zend_long count; } limit; struct { - long flags; /* CIT_* */ - zval *zstr; - zval *zchildren; - zval *zcache; + zend_long flags; /* CIT_* */ + zval zstr; + zval zchildren; + zval zcache; } caching; struct { - zval *zarrayit; + zval zarrayit; zend_object_iterator *iterator; } append; #if HAVE_PCRE || HAVE_BUNDLED_PCRE struct { - int use_flags; - long flags; - regex_mode mode; - long preg_flags; + zend_long flags; + zend_long preg_flags; pcre_cache_entry *pce; - char *regex; - uint regex_len; + zend_string *regex; + regex_mode mode; + int use_flags; } regex; #endif _spl_cbfilter_it_intern *cbfilter; } u; + zend_object std; } spl_dual_it_object; -typedef int (*spl_iterator_apply_func_t)(zend_object_iterator *iter, void *puser TSRMLS_DC); +static inline spl_dual_it_object *spl_dual_it_from_obj(zend_object *obj) /* {{{ */ { + return (spl_dual_it_object*)((char*)(obj) - XtOffsetOf(spl_dual_it_object, std)); +} /* }}} */ + +#define Z_SPLDUAL_IT_P(zv) spl_dual_it_from_obj(Z_OBJ_P((zv))) + +typedef int (*spl_iterator_apply_func_t)(zend_object_iterator *iter, void *puser); -PHPAPI int spl_iterator_apply(zval *obj, spl_iterator_apply_func_t apply_func, void *puser TSRMLS_DC); +PHPAPI int spl_iterator_apply(zval *obj, spl_iterator_apply_func_t apply_func, void *puser); #endif /* SPL_ITERATORS_H */ diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index 08cf66a67b..154a3c08d5 100644 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -28,7 +28,7 @@ #include "ext/standard/info.h" #include "ext/standard/php_array.h" #include "ext/standard/php_var.h" -#include "ext/standard/php_smart_str.h" +#include "zend_smart_str.h" #include "zend_interfaces.h" #include "zend_exceptions.h" @@ -80,61 +80,52 @@ PHPAPI zend_class_entry *spl_ce_MultipleIterator; PHPAPI zend_object_handlers spl_handler_SplObjectStorage; typedef struct _spl_SplObjectStorage { /* {{{ */ - zend_object std; HashTable storage; - long index; + zend_long index; HashPosition pos; - long flags; + zend_long flags; zend_function *fptr_get_hash; - HashTable *debug_info; - zval **gcdata; - long gcdata_num; + zval *gcdata; + size_t gcdata_num; + zend_object std; } spl_SplObjectStorage; /* }}} */ -/* {{{ storage is an assoc aray of [zend_object_value]=>[zval *obj, zval *inf] */ +/* {{{ storage is an assoc aray of [zend_object*]=>[zval *obj, zval *inf] */ typedef struct _spl_SplObjectStorageElement { - zval* obj; - zval* inf; + zval obj; + zval inf; } spl_SplObjectStorageElement; /* }}} */ -void spl_SplOjectStorage_free_storage(void *object TSRMLS_DC) /* {{{ */ +static inline spl_SplObjectStorage *spl_object_storage_from_obj(zend_object *obj) /* {{{ */ { + return (spl_SplObjectStorage*)((char*)(obj) - XtOffsetOf(spl_SplObjectStorage, std)); +} +/* }}} */ + +#define Z_SPLOBJSTORAGE_P(zv) spl_object_storage_from_obj(Z_OBJ_P((zv))) + +void spl_SplObjectStorage_free_storage(zend_object *object) /* {{{ */ { - spl_SplObjectStorage *intern = (spl_SplObjectStorage *)object; + spl_SplObjectStorage *intern = spl_object_storage_from_obj(object); - zend_object_std_dtor(&intern->std TSRMLS_CC); + zend_object_std_dtor(&intern->std); zend_hash_destroy(&intern->storage); - if (intern->debug_info != NULL) { - zend_hash_destroy(intern->debug_info); - efree(intern->debug_info); - } - if (intern->gcdata != NULL) { efree(intern->gcdata); } - efree(object); } /* }}} */ -static char *spl_object_storage_get_hash(spl_SplObjectStorage *intern, zval *this, zval *obj, int *hash_len_ptr TSRMLS_DC) { +static zend_string *spl_object_storage_get_hash(spl_SplObjectStorage *intern, zval *this, zval *obj) { if (intern->fptr_get_hash) { - zval *rv; - zend_call_method_with_1_params(&this, intern->std.ce, &intern->fptr_get_hash, "getHash", &rv, obj); - if (rv) { - if (Z_TYPE_P(rv) == IS_STRING) { - int hash_len = Z_STRLEN_P(rv); - char *hash = emalloc((hash_len+1)*sizeof(char)); - strncpy(hash, Z_STRVAL_P(rv), hash_len); - hash[hash_len] = 0; - - zval_ptr_dtor(&rv); - if (hash_len_ptr) { - *hash_len_ptr = hash_len; - } - return hash; + zval rv; + zend_call_method_with_1_params(this, intern->std.ce, &intern->fptr_get_hash, "getHash", &rv, obj); + if (!Z_ISUNDEF(rv)) { + if (Z_TYPE(rv) == IS_STRING) { + return Z_STR(rv); } else { - zend_throw_exception(spl_ce_RuntimeException, "Hash needs to be a string", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_RuntimeException, "Hash needs to be a string", 0); zval_ptr_dtor(&rv); return NULL; @@ -143,147 +134,111 @@ static char *spl_object_storage_get_hash(spl_SplObjectStorage *intern, zval *thi return NULL; } } else { - int hash_len = sizeof(zend_object_value); - -#if HAVE_PACKED_OBJECT_VALUE - - if (hash_len_ptr) { - *hash_len_ptr = hash_len; - } - - return (char*)&Z_OBJVAL_P(obj); -#else - char *hash = emalloc(hash_len + 1); - - zend_object_value zvalue; - memset(&zvalue, 0, sizeof(zend_object_value)); - zvalue.handle = Z_OBJ_HANDLE_P(obj); - zvalue.handlers = Z_OBJ_HT_P(obj); - - memcpy(hash, (char *)&zvalue, hash_len); - hash[hash_len] = 0; - - if (hash_len_ptr) { - *hash_len_ptr = hash_len; - } - + zend_string *hash = zend_string_alloc(sizeof(zend_object*), 0); + memcpy(ZSTR_VAL(hash), (void*)&Z_OBJ_P(obj), sizeof(zend_object*)); + ZSTR_VAL(hash)[ZSTR_LEN(hash)] = '\0'; return hash; -#endif } } -static void spl_object_storage_free_hash(spl_SplObjectStorage *intern, char *hash) { - if (intern->fptr_get_hash) { - efree(hash); - } else { -#if HAVE_PACKED_OBJECT_VALUE - /* Nothing to do */ -#else - efree(hash); -#endif - } +static void spl_object_storage_free_hash(spl_SplObjectStorage *intern, zend_string *hash) { + zend_string_release(hash); } -static void spl_object_storage_dtor(spl_SplObjectStorageElement *element) /* {{{ */ +static void spl_object_storage_dtor(zval *element) /* {{{ */ { - zval_ptr_dtor(&element->obj); - zval_ptr_dtor(&element->inf); + spl_SplObjectStorageElement *el = Z_PTR_P(element); + zval_ptr_dtor(&el->obj); + zval_ptr_dtor(&el->inf); + efree(el); } /* }}} */ -spl_SplObjectStorageElement* spl_object_storage_get(spl_SplObjectStorage *intern, char *hash, int hash_len TSRMLS_DC) /* {{{ */ +spl_SplObjectStorageElement* spl_object_storage_get(spl_SplObjectStorage *intern, zend_string *hash) /* {{{ */ { - spl_SplObjectStorageElement *element; - if (zend_hash_find(&intern->storage, hash, hash_len, (void**)&element) == SUCCESS) { - return element; - } else { - return NULL; - } + return (spl_SplObjectStorageElement*)zend_hash_find_ptr(&intern->storage, hash); } /* }}} */ -void spl_object_storage_attach(spl_SplObjectStorage *intern, zval *this, zval *obj, zval *inf TSRMLS_DC) /* {{{ */ +spl_SplObjectStorageElement *spl_object_storage_attach(spl_SplObjectStorage *intern, zval *this, zval *obj, zval *inf) /* {{{ */ { spl_SplObjectStorageElement *pelement, element; + zend_string *hash = spl_object_storage_get_hash(intern, this, obj); - int hash_len; - char *hash = spl_object_storage_get_hash(intern, this, obj, &hash_len TSRMLS_CC); if (!hash) { - return; + return NULL; } - pelement = spl_object_storage_get(intern, hash, hash_len TSRMLS_CC); + pelement = spl_object_storage_get(intern, hash); - if (inf) { - Z_ADDREF_P(inf); - } else { - ALLOC_INIT_ZVAL(inf); - } if (pelement) { zval_ptr_dtor(&pelement->inf); - pelement->inf = inf; + if (inf) { + ZVAL_COPY(&pelement->inf, inf); + } else { + ZVAL_NULL(&pelement->inf); + } spl_object_storage_free_hash(intern, hash); - return; + return pelement; + } + + ZVAL_COPY(&element.obj, obj); + if (inf) { + ZVAL_COPY(&element.inf, inf); + } else { + ZVAL_NULL(&element.inf); } - Z_ADDREF_P(obj); - element.obj = obj; - element.inf = inf; - zend_hash_update(&intern->storage, hash, hash_len, &element, sizeof(spl_SplObjectStorageElement), NULL); + pelement = zend_hash_update_mem(&intern->storage, hash, &element, sizeof(spl_SplObjectStorageElement)); spl_object_storage_free_hash(intern, hash); + return pelement; } /* }}} */ -int spl_object_storage_detach(spl_SplObjectStorage *intern, zval *this, zval *obj TSRMLS_DC) /* {{{ */ +int spl_object_storage_detach(spl_SplObjectStorage *intern, zval *this, zval *obj) /* {{{ */ { - int hash_len, ret = FAILURE; - char *hash = spl_object_storage_get_hash(intern, this, obj, &hash_len TSRMLS_CC); + int ret = FAILURE; + zend_string *hash = spl_object_storage_get_hash(intern, this, obj); if (!hash) { return ret; } - ret = zend_hash_del(&intern->storage, hash, hash_len); + ret = zend_hash_del(&intern->storage, hash); spl_object_storage_free_hash(intern, hash); return ret; } /* }}}*/ -void spl_object_storage_addall(spl_SplObjectStorage *intern, zval *this, spl_SplObjectStorage *other TSRMLS_DC) { /* {{{ */ - HashPosition pos; +void spl_object_storage_addall(spl_SplObjectStorage *intern, zval *this, spl_SplObjectStorage *other) { /* {{{ */ spl_SplObjectStorageElement *element; - zend_hash_internal_pointer_reset_ex(&other->storage, &pos); - while (zend_hash_get_current_data_ex(&other->storage, (void **)&element, &pos) == SUCCESS) { - spl_object_storage_attach(intern, this, element->obj, element->inf TSRMLS_CC); - zend_hash_move_forward_ex(&other->storage, &pos); - } + ZEND_HASH_FOREACH_PTR(&other->storage, element) { + spl_object_storage_attach(intern, this, &element->obj, &element->inf); + } ZEND_HASH_FOREACH_END(); - zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); intern->index = 0; } /* }}} */ -static zend_object_value spl_object_storage_new_ex(zend_class_entry *class_type, spl_SplObjectStorage **obj, zval *orig TSRMLS_DC) /* {{{ */ +static zend_object *spl_object_storage_new_ex(zend_class_entry *class_type, zval *orig) /* {{{ */ { - zend_object_value retval; spl_SplObjectStorage *intern; - zend_class_entry *parent = class_type; + zend_class_entry *parent = class_type; - intern = emalloc(sizeof(spl_SplObjectStorage)); - memset(intern, 0, sizeof(spl_SplObjectStorage)); - *obj = intern; + intern = emalloc(sizeof(spl_SplObjectStorage) + zend_object_properties_size(parent)); + memset(intern, 0, sizeof(spl_SplObjectStorage) - sizeof(zval)); + intern->pos = HT_INVALID_IDX; - zend_object_std_init(&intern->std, class_type TSRMLS_CC); + zend_object_std_init(&intern->std, class_type); object_properties_init(&intern->std, class_type); - zend_hash_init(&intern->storage, 0, NULL, (void (*)(void *))spl_object_storage_dtor, 0); + zend_hash_init(&intern->storage, 0, NULL, spl_object_storage_dtor, 0); - retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_SplOjectStorage_free_storage, NULL TSRMLS_CC); - retval.handlers = &spl_handler_SplObjectStorage; + intern->std.handlers = &spl_handler_SplObjectStorage; if (orig) { - spl_SplObjectStorage *other = (spl_SplObjectStorage*)zend_object_store_get_object(orig TSRMLS_CC); - spl_object_storage_addall(intern, orig, other TSRMLS_CC); + spl_SplObjectStorage *other = Z_SPLOBJSTORAGE_P(orig); + spl_object_storage_addall(intern, orig, other); } while (parent) { if (parent == spl_ce_SplObjectStorage) { if (class_type != spl_ce_SplObjectStorage) { - zend_hash_find(&class_type->function_table, "gethash", sizeof("gethash"), (void **) &intern->fptr_get_hash); + intern->fptr_get_hash = zend_hash_str_find_ptr(&class_type->function_table, "gethash", sizeof("gethash") - 1); if (intern->fptr_get_hash->common.scope == spl_ce_SplObjectStorage) { intern->fptr_get_hash = NULL; } @@ -294,225 +249,208 @@ static zend_object_value spl_object_storage_new_ex(zend_class_entry *class_type, parent = parent->parent; } - return retval; + return &intern->std; } /* }}} */ /* {{{ spl_object_storage_clone */ -static zend_object_value spl_object_storage_clone(zval *zobject TSRMLS_DC) +static zend_object *spl_object_storage_clone(zval *zobject) { - zend_object_value new_obj_val; zend_object *old_object; zend_object *new_object; - zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); - spl_SplObjectStorage *intern; - old_object = zend_objects_get_address(zobject TSRMLS_CC); - new_obj_val = spl_object_storage_new_ex(old_object->ce, &intern, zobject TSRMLS_CC); - new_object = &intern->std; + old_object = Z_OBJ_P(zobject); + new_object = spl_object_storage_new_ex(old_object->ce, zobject); - zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC); + zend_objects_clone_members(new_object, old_object); - return new_obj_val; + return new_object; } /* }}} */ -static HashTable* spl_object_storage_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{ */ +static HashTable* spl_object_storage_debug_info(zval *obj, int *is_temp) /* {{{ */ { - spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(obj TSRMLS_CC); + spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(obj); spl_SplObjectStorageElement *element; HashTable *props; - HashPosition pos; - zval *tmp, *storage; - char md5str[33]; - int name_len; - char *zname; + zval tmp, storage; + zend_string *md5str; + zend_string *zname; + HashTable *debug_info; - *is_temp = 0; + *is_temp = 1; props = Z_OBJPROP_P(obj); - if (intern->debug_info == NULL) { - ALLOC_HASHTABLE(intern->debug_info); - ZEND_INIT_SYMTABLE_EX(intern->debug_info, zend_hash_num_elements(props) + 1, 0); - } - - if (intern->debug_info->nApplyCount == 0) { - zend_hash_copy(intern->debug_info, props, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); - - MAKE_STD_ZVAL(storage); - array_init(storage); - - zend_hash_internal_pointer_reset_ex(&intern->storage, &pos); - while (zend_hash_get_current_data_ex(&intern->storage, (void **)&element, &pos) == SUCCESS) { - php_spl_object_hash(element->obj, md5str TSRMLS_CC); - MAKE_STD_ZVAL(tmp); - array_init(tmp); - /* Incrementing the refcount of obj and inf would confuse the garbage collector. - * Prefer to null the destructor */ - Z_ARRVAL_P(tmp)->pDestructor = NULL; - add_assoc_zval_ex(tmp, "obj", sizeof("obj"), element->obj); - add_assoc_zval_ex(tmp, "inf", sizeof("inf"), element->inf); - add_assoc_zval_ex(storage, md5str, 33, tmp); - zend_hash_move_forward_ex(&intern->storage, &pos); - } - - zname = spl_gen_private_prop_name(spl_ce_SplObjectStorage, "storage", sizeof("storage")-1, &name_len TSRMLS_CC); - zend_symtable_update(intern->debug_info, zname, name_len+1, &storage, sizeof(zval *), NULL); - efree(zname); - } - - return intern->debug_info; + ALLOC_HASHTABLE(debug_info); + ZEND_INIT_SYMTABLE_EX(debug_info, zend_hash_num_elements(props) + 1, 0); + zend_hash_copy(debug_info, props, (copy_ctor_func_t)zval_add_ref); + + array_init(&storage); + + ZEND_HASH_FOREACH_PTR(&intern->storage, element) { + md5str = php_spl_object_hash(&element->obj); + array_init(&tmp); + /* Incrementing the refcount of obj and inf would confuse the garbage collector. + * Prefer to null the destructor */ + Z_ARRVAL_P(&tmp)->pDestructor = NULL; + add_assoc_zval_ex(&tmp, "obj", sizeof("obj") - 1, &element->obj); + add_assoc_zval_ex(&tmp, "inf", sizeof("inf") - 1, &element->inf); + zend_hash_update(Z_ARRVAL(storage), md5str, &tmp); + zend_string_release(md5str); + } ZEND_HASH_FOREACH_END(); + + zname = spl_gen_private_prop_name(spl_ce_SplObjectStorage, "storage", sizeof("storage")-1); + zend_symtable_update(debug_info, zname, &storage); + zend_string_release(zname); + + return debug_info; } /* }}} */ /* overriden for garbage collection */ -static HashTable *spl_object_storage_get_gc(zval *obj, zval ***table, int *n TSRMLS_DC) /* {{{ */ +static HashTable *spl_object_storage_get_gc(zval *obj, zval **table, int *n) /* {{{ */ { - long i = 0; - spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(obj TSRMLS_CC); + int i = 0; + spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(obj); spl_SplObjectStorageElement *element; - HashPosition pos; if (intern->storage.nNumOfElements * 2 > intern->gcdata_num) { intern->gcdata_num = intern->storage.nNumOfElements * 2; - intern->gcdata = (zval**)erealloc(intern->gcdata, sizeof(zval*) * intern->gcdata_num); + intern->gcdata = (zval*)erealloc(intern->gcdata, sizeof(zval) * intern->gcdata_num); } - zend_hash_internal_pointer_reset_ex(&intern->storage, &pos); - while (zend_hash_get_current_data_ex(&intern->storage, (void **)&element, &pos) == SUCCESS) { - intern->gcdata[i++] = element->obj; - intern->gcdata[i++] = element->inf; - zend_hash_move_forward_ex(&intern->storage, &pos); - } + ZEND_HASH_FOREACH_PTR(&intern->storage, element) { + ZVAL_COPY_VALUE(&intern->gcdata[i++], &element->obj); + ZVAL_COPY_VALUE(&intern->gcdata[i++], &element->inf); + } ZEND_HASH_FOREACH_END(); *table = intern->gcdata; *n = i; - return std_object_handlers.get_properties(obj TSRMLS_CC); + return std_object_handlers.get_properties(obj); } /* }}} */ -static int spl_object_storage_compare_info(spl_SplObjectStorageElement *e1, spl_SplObjectStorageElement *e2 TSRMLS_DC) /* {{{ */ +static int spl_object_storage_compare_info(zval *e1, zval *e2) /* {{{ */ { + spl_SplObjectStorageElement *s1 = (spl_SplObjectStorageElement*)Z_PTR_P(e1); + spl_SplObjectStorageElement *s2 = (spl_SplObjectStorageElement*)Z_PTR_P(e2); zval result; - if (compare_function(&result, e1->inf, e2->inf TSRMLS_CC) == FAILURE) { + if (compare_function(&result, &s1->inf, &s2->inf) == FAILURE) { return 1; } - return Z_LVAL(result); + return Z_LVAL(result) > 0 ? 1 : (Z_LVAL(result) < 0 ? -1 : 0); } /* }}} */ -static int spl_object_storage_compare_objects(zval *o1, zval *o2 TSRMLS_DC) /* {{{ */ +static int spl_object_storage_compare_objects(zval *o1, zval *o2) /* {{{ */ { - zend_object *zo1 = (zend_object *)zend_object_store_get_object(o1 TSRMLS_CC); - zend_object *zo2 = (zend_object *)zend_object_store_get_object(o2 TSRMLS_CC); + zend_object *zo1 = (zend_object *)Z_OBJ_P(o1); + zend_object *zo2 = (zend_object *)Z_OBJ_P(o2); if (zo1->ce != spl_ce_SplObjectStorage || zo2->ce != spl_ce_SplObjectStorage) { return 1; } - return zend_hash_compare(&((spl_SplObjectStorage *)zo1)->storage, &((spl_SplObjectStorage *)zo2)->storage, (compare_func_t) spl_object_storage_compare_info, 0 TSRMLS_CC); + return zend_hash_compare(&(Z_SPLOBJSTORAGE_P(o1))->storage, &(Z_SPLOBJSTORAGE_P(o2))->storage, (compare_func_t)spl_object_storage_compare_info, 0); } /* }}} */ /* {{{ spl_array_object_new */ -static zend_object_value spl_SplObjectStorage_new(zend_class_entry *class_type TSRMLS_DC) +static zend_object *spl_SplObjectStorage_new(zend_class_entry *class_type) { - spl_SplObjectStorage *tmp; - return spl_object_storage_new_ex(class_type, &tmp, NULL TSRMLS_CC); + return spl_object_storage_new_ex(class_type, NULL); } /* }}} */ -int spl_object_storage_contains(spl_SplObjectStorage *intern, zval *this, zval *obj TSRMLS_DC) /* {{{ */ +int spl_object_storage_contains(spl_SplObjectStorage *intern, zval *this, zval *obj) /* {{{ */ { - int hash_len, found; - char *hash = spl_object_storage_get_hash(intern, this, obj, &hash_len TSRMLS_CC); + int found; + zend_string *hash = spl_object_storage_get_hash(intern, this, obj); if (!hash) { return 0; } - found = zend_hash_exists(&intern->storage, hash, hash_len); + found = zend_hash_exists(&intern->storage, hash); spl_object_storage_free_hash(intern, hash); return found; } /* }}} */ -/* {{{ proto void SplObjectStorage::attach($obj, $inf = NULL) +/* {{{ proto void SplObjectStorage::attach(object obj, mixed inf = NULL) Attaches an object to the storage if not yet contained */ SPL_METHOD(SplObjectStorage, attach) { zval *obj, *inf = NULL; - spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(getThis()); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o|z!", &obj, &inf) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "o|z!", &obj, &inf) == FAILURE) { return; } - spl_object_storage_attach(intern, getThis(), obj, inf TSRMLS_CC); + spl_object_storage_attach(intern, getThis(), obj, inf); } /* }}} */ -/* {{{ proto void SplObjectStorage::detach($obj) +/* {{{ proto void SplObjectStorage::detach(object obj) Detaches an object from the storage */ SPL_METHOD(SplObjectStorage, detach) { zval *obj; - spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(getThis()); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &obj) == FAILURE) { return; } - spl_object_storage_detach(intern, getThis(), obj TSRMLS_CC); + spl_object_storage_detach(intern, getThis(), obj); zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); intern->index = 0; } /* }}} */ -/* {{{ proto string SplObjectStorage::getHash($object) +/* {{{ proto string SplObjectStorage::getHash(object obj) Returns the hash of an object */ SPL_METHOD(SplObjectStorage, getHash) { zval *obj; - char *hash; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &obj) == FAILURE) { return; } - hash = emalloc(33); - php_spl_object_hash(obj, hash TSRMLS_CC); - - RETVAL_STRING(hash, 0); + RETURN_NEW_STR(php_spl_object_hash(obj)); } /* }}} */ -/* {{{ proto mixed SplObjectStorage::offsetGet($object) +/* {{{ proto mixed SplObjectStorage::offsetGet(object obj) Returns associated information for a stored object */ SPL_METHOD(SplObjectStorage, offsetGet) { zval *obj; spl_SplObjectStorageElement *element; - spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); - char *hash; - int hash_len; + spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(getThis()); + zend_string *hash; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &obj) == FAILURE) { return; } - hash = spl_object_storage_get_hash(intern, getThis(), obj, &hash_len TSRMLS_CC); + hash = spl_object_storage_get_hash(intern, getThis(), obj); if (!hash) { return; } - element = spl_object_storage_get(intern, hash, hash_len TSRMLS_CC); + element = spl_object_storage_get(intern, hash); spl_object_storage_free_hash(intern, hash); if (!element) { - zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Object not found"); + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Object not found"); } else { - RETURN_ZVAL(element->inf,1, 0); + zval *value = &element->inf; + + ZVAL_DEREF(value); + ZVAL_COPY(return_value, value); } } /* }}} */ @@ -521,16 +459,16 @@ SPL_METHOD(SplObjectStorage, offsetGet) SPL_METHOD(SplObjectStorage, addAll) { zval *obj; - spl_SplObjectStorage *intern = (spl_SplObjectStorage *)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(getThis()); spl_SplObjectStorage *other; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &obj, spl_ce_SplObjectStorage) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &obj, spl_ce_SplObjectStorage) == FAILURE) { return; } - other = (spl_SplObjectStorage *)zend_object_store_get_object(obj TSRMLS_CC); + other = Z_SPLOBJSTORAGE_P(obj); - spl_object_storage_addall(intern, getThis(), other TSRMLS_CC); + spl_object_storage_addall(intern, getThis(), other); RETURN_LONG(zend_hash_num_elements(&intern->storage)); } /* }}} */ @@ -540,19 +478,19 @@ SPL_METHOD(SplObjectStorage, addAll) SPL_METHOD(SplObjectStorage, removeAll) { zval *obj; - spl_SplObjectStorage *intern = (spl_SplObjectStorage *)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(getThis()); spl_SplObjectStorage *other; spl_SplObjectStorageElement *element; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &obj, spl_ce_SplObjectStorage) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &obj, spl_ce_SplObjectStorage) == FAILURE) { return; } - other = (spl_SplObjectStorage *)zend_object_store_get_object(obj TSRMLS_CC); + other = Z_SPLOBJSTORAGE_P(obj); zend_hash_internal_pointer_reset(&other->storage); - while (zend_hash_get_current_data(&other->storage, (void **)&element) == SUCCESS) { - if (spl_object_storage_detach(intern, getThis(), element->obj TSRMLS_CC) == FAILURE) { + while ((element = zend_hash_get_current_data_ptr(&other->storage)) != NULL) { + if (spl_object_storage_detach(intern, getThis(), &element->obj) == FAILURE) { zend_hash_move_forward(&other->storage); } } @@ -568,23 +506,21 @@ SPL_METHOD(SplObjectStorage, removeAll) SPL_METHOD(SplObjectStorage, removeAllExcept) { zval *obj; - spl_SplObjectStorage *intern = (spl_SplObjectStorage *)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(getThis()); spl_SplObjectStorage *other; spl_SplObjectStorageElement *element; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &obj, spl_ce_SplObjectStorage) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &obj, spl_ce_SplObjectStorage) == FAILURE) { return; } - other = (spl_SplObjectStorage *)zend_object_store_get_object(obj TSRMLS_CC); + other = Z_SPLOBJSTORAGE_P(obj); - zend_hash_internal_pointer_reset(&intern->storage); - while (zend_hash_get_current_data(&intern->storage, (void **)&element) == SUCCESS) { - if (!spl_object_storage_contains(other, getThis(), element->obj TSRMLS_CC)) { - spl_object_storage_detach(intern, getThis(), element->obj TSRMLS_CC); + ZEND_HASH_FOREACH_PTR(&intern->storage, element) { + if (!spl_object_storage_contains(other, getThis(), &element->obj)) { + spl_object_storage_detach(intern, getThis(), &element->obj); } - zend_hash_move_forward(&intern->storage); - } + } ZEND_HASH_FOREACH_END(); zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); intern->index = 0; @@ -593,40 +529,37 @@ SPL_METHOD(SplObjectStorage, removeAllExcept) } /* }}} */ -/* {{{ proto bool SplObjectStorage::contains($obj) +/* {{{ proto bool SplObjectStorage::contains(object obj) Determine whethe an object is contained in the storage */ SPL_METHOD(SplObjectStorage, contains) { zval *obj; - spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(getThis()); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &obj) == FAILURE) { return; } - RETURN_BOOL(spl_object_storage_contains(intern, getThis(), obj TSRMLS_CC)); + RETURN_BOOL(spl_object_storage_contains(intern, getThis(), obj)); } /* }}} */ /* {{{ proto int SplObjectStorage::count() Determine number of objects in storage */ SPL_METHOD(SplObjectStorage, count) { - spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); - long mode = COUNT_NORMAL; + spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(getThis()); + zend_long mode = COUNT_NORMAL; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &mode) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &mode) == FAILURE) { return; } if (mode == COUNT_RECURSIVE) { - long ret = zend_hash_num_elements(&intern->storage); - HashPosition position; + zend_long ret = zend_hash_num_elements(&intern->storage); zval *element; - for (zend_hash_internal_pointer_reset_ex(&intern->storage, &position); - zend_hash_get_current_data_ex(&intern->storage, (void**) &element, &position) == SUCCESS; - zend_hash_move_forward_ex(&intern->storage, &position)) { - ret += php_count_recursive(element, mode TSRMLS_CC); - } + ZEND_HASH_FOREACH_VAL(&intern->storage, element) { + ret += php_count_recursive(element, mode); + } ZEND_HASH_FOREACH_END(); RETURN_LONG(ret); return; @@ -639,7 +572,7 @@ SPL_METHOD(SplObjectStorage, count) Rewind to first position */ SPL_METHOD(SplObjectStorage, rewind) { - spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; @@ -653,7 +586,7 @@ SPL_METHOD(SplObjectStorage, rewind) Returns whether current position is valid */ SPL_METHOD(SplObjectStorage, valid) { - spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; @@ -666,7 +599,7 @@ SPL_METHOD(SplObjectStorage, valid) Returns current key */ SPL_METHOD(SplObjectStorage, key) { - spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; @@ -680,16 +613,16 @@ SPL_METHOD(SplObjectStorage, key) SPL_METHOD(SplObjectStorage, current) { spl_SplObjectStorageElement *element; - spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; } - if (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == FAILURE) { + if ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) == NULL) { return; } - RETVAL_ZVAL(element->obj, 1, 0); + ZVAL_COPY(return_value, &element->obj); } /* }}} */ /* {{{ proto mixed SplObjectStorage::getInfo() @@ -697,16 +630,16 @@ SPL_METHOD(SplObjectStorage, current) SPL_METHOD(SplObjectStorage, getInfo) { spl_SplObjectStorageElement *element; - spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; } - if (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == FAILURE) { + if ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) == NULL) { return; } - RETVAL_ZVAL(element->inf, 1, 0); + ZVAL_COPY(return_value, &element->inf); } /* }}} */ /* {{{ proto mixed SplObjectStorage::setInfo(mixed $inf) @@ -714,26 +647,25 @@ SPL_METHOD(SplObjectStorage, getInfo) SPL_METHOD(SplObjectStorage, setInfo) { spl_SplObjectStorageElement *element; - spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(getThis()); zval *inf; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &inf) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &inf) == FAILURE) { return; } - if (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == FAILURE) { + if ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) == NULL) { return; } zval_ptr_dtor(&element->inf); - element->inf = inf; - Z_ADDREF_P(inf); + ZVAL_COPY(&element->inf, inf); } /* }}} */ /* {{{ proto void SplObjectStorage::next() Moves position forward */ SPL_METHOD(SplObjectStorage, next) { - spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; @@ -747,10 +679,10 @@ SPL_METHOD(SplObjectStorage, next) Serializes storage */ SPL_METHOD(SplObjectStorage, serialize) { - spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(getThis()); spl_SplObjectStorageElement *element; - zval members, *pmembers, *flags; + zval members, flags; HashPosition pos; php_serialize_data_t var_hash; smart_str buf = {0}; @@ -763,40 +695,37 @@ SPL_METHOD(SplObjectStorage, serialize) /* storage */ smart_str_appendl(&buf, "x:", 2); - MAKE_STD_ZVAL(flags); - ZVAL_LONG(flags, zend_hash_num_elements(&intern->storage)); - php_var_serialize(&buf, &flags, &var_hash TSRMLS_CC); + ZVAL_LONG(&flags, zend_hash_num_elements(&intern->storage)); + php_var_serialize(&buf, &flags, &var_hash); zval_ptr_dtor(&flags); zend_hash_internal_pointer_reset_ex(&intern->storage, &pos); - while(zend_hash_has_more_elements_ex(&intern->storage, &pos) == SUCCESS) { - if (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &pos) == FAILURE) { + while (zend_hash_has_more_elements_ex(&intern->storage, &pos) == SUCCESS) { + if ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &pos)) == NULL) { smart_str_free(&buf); PHP_VAR_SERIALIZE_DESTROY(var_hash); RETURN_NULL(); } - php_var_serialize(&buf, &element->obj, &var_hash TSRMLS_CC); + php_var_serialize(&buf, &element->obj, &var_hash); smart_str_appendc(&buf, ','); - php_var_serialize(&buf, &element->inf, &var_hash TSRMLS_CC); + php_var_serialize(&buf, &element->inf, &var_hash); smart_str_appendc(&buf, ';'); zend_hash_move_forward_ex(&intern->storage, &pos); } /* members */ smart_str_appendl(&buf, "m:", 2); - INIT_PZVAL(&members); - Z_ARRVAL(members) = zend_std_get_properties(getThis() TSRMLS_CC); - Z_TYPE(members) = IS_ARRAY; - pmembers = &members; - php_var_serialize(&buf, &pmembers, &var_hash TSRMLS_CC); /* finishes the string */ + ZVAL_ARR(&members, zend_array_dup(zend_std_get_properties(getThis()))); + php_var_serialize(&buf, &members, &var_hash); /* finishes the string */ + zval_ptr_dtor(&members); /* done */ PHP_VAR_SERIALIZE_DESTROY(var_hash); - if (buf.c) { - RETURN_STRINGL(buf.c, buf.len, 0); + if (buf.s) { + RETURN_NEW_STR(buf.s); } else { RETURN_NULL(); } @@ -807,16 +736,18 @@ SPL_METHOD(SplObjectStorage, serialize) Unserializes storage */ SPL_METHOD(SplObjectStorage, unserialize) { - spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(getThis()); char *buf; - int buf_len; + size_t buf_len; const unsigned char *p, *s; php_unserialize_data_t var_hash; - zval *pentry, *pmembers, *pcount = NULL, *pinf; - long count; + zval entry, inf; + zval *pcount, *pmembers; + spl_SplObjectStorageElement *element; + zend_long count; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &buf, &buf_len) == FAILURE) { return; } @@ -833,19 +764,17 @@ SPL_METHOD(SplObjectStorage, unserialize) } ++p; - ALLOC_INIT_ZVAL(pcount); - if (!php_var_unserialize(&pcount, &p, s + buf_len, &var_hash TSRMLS_CC) || Z_TYPE_P(pcount) != IS_LONG) { + pcount = var_tmp_var(&var_hash); + if (!php_var_unserialize(pcount, &p, s + buf_len, &var_hash) || Z_TYPE_P(pcount) != IS_LONG) { goto outexcept; } - var_push_dtor(&var_hash, &pcount); --p; /* for ';' */ count = Z_LVAL_P(pcount); - while(count-- > 0) { + while (count-- > 0) { spl_SplObjectStorageElement *pelement; - char *hash; - int hash_len; + zend_string *hash; if (*p != ';') { goto outexcept; @@ -854,45 +783,45 @@ SPL_METHOD(SplObjectStorage, unserialize) if(*p != 'O' && *p != 'C' && *p != 'r') { goto outexcept; } - ALLOC_INIT_ZVAL(pentry); - if (!php_var_unserialize(&pentry, &p, s + buf_len, &var_hash TSRMLS_CC)) { - zval_ptr_dtor(&pentry); + /* store reference to allow cross-references between different elements */ + if (!php_var_unserialize(&entry, &p, s + buf_len, &var_hash)) { goto outexcept; } - var_push_dtor(&var_hash, &pentry); - if(Z_TYPE_P(pentry) != IS_OBJECT) { - zval_ptr_dtor(&pentry); + if (Z_TYPE(entry) != IS_OBJECT) { + zval_ptr_dtor(&entry); goto outexcept; } - ALLOC_INIT_ZVAL(pinf); if (*p == ',') { /* new version has inf */ ++p; - if (!php_var_unserialize(&pinf, &p, s + buf_len, &var_hash TSRMLS_CC)) { - zval_ptr_dtor(&pinf); + if (!php_var_unserialize(&inf, &p, s + buf_len, &var_hash)) { + zval_ptr_dtor(&entry); goto outexcept; } - var_push_dtor(&var_hash, &pinf); + } else { + ZVAL_UNDEF(&inf); } - hash = spl_object_storage_get_hash(intern, getThis(), pentry, &hash_len TSRMLS_CC); + hash = spl_object_storage_get_hash(intern, getThis(), &entry); if (!hash) { - zval_ptr_dtor(&pentry); - zval_ptr_dtor(&pinf); + zval_ptr_dtor(&entry); + zval_ptr_dtor(&inf); goto outexcept; } - pelement = spl_object_storage_get(intern, hash, hash_len TSRMLS_CC); + pelement = spl_object_storage_get(intern, hash); spl_object_storage_free_hash(intern, hash); - if(pelement) { - if(pelement->inf) { + if (pelement) { + if (!Z_ISUNDEF(pelement->inf)) { var_push_dtor(&var_hash, &pelement->inf); } - if(pelement->obj) { + if (!Z_ISUNDEF(pelement->obj)) { var_push_dtor(&var_hash, &pelement->obj); } } - spl_object_storage_attach(intern, getThis(), pentry, pinf TSRMLS_CC); - zval_ptr_dtor(&pentry); - zval_ptr_dtor(&pinf); + element = spl_object_storage_attach(intern, getThis(), &entry, Z_ISUNDEF(inf)?NULL:&inf); + var_replace(&var_hash, &entry, &element->obj); + var_replace(&var_hash, &inf, &element->inf); + zval_ptr_dtor(&entry); + zval_ptr_dtor(&inf); } if (*p != ';') { @@ -906,33 +835,23 @@ SPL_METHOD(SplObjectStorage, unserialize) } ++p; - ALLOC_INIT_ZVAL(pmembers); - if (!php_var_unserialize(&pmembers, &p, s + buf_len, &var_hash TSRMLS_CC) || Z_TYPE_P(pmembers) != IS_ARRAY) { - zval_ptr_dtor(&pmembers); + pmembers = var_tmp_var(&var_hash); + if (!php_var_unserialize(pmembers, &p, s + buf_len, &var_hash) || Z_TYPE_P(pmembers) != IS_ARRAY) { goto outexcept; } - var_push_dtor(&var_hash, &pmembers); /* copy members */ if (!intern->std.properties) { rebuild_object_properties(&intern->std); } - zend_hash_copy(intern->std.properties, Z_ARRVAL_P(pmembers), (copy_ctor_func_t) zval_add_ref, (void *) NULL, sizeof(zval *)); - zval_ptr_dtor(&pmembers); + zend_hash_copy(intern->std.properties, Z_ARRVAL_P(pmembers), (copy_ctor_func_t) zval_add_ref); - /* done reading $serialized */ - if (pcount) { - zval_ptr_dtor(&pcount); - } PHP_VAR_UNSERIALIZE_DESTROY(var_hash); return; outexcept: - if (pcount) { - zval_ptr_dtor(&pcount); - } PHP_VAR_UNSERIALIZE_DESTROY(var_hash); - zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Error at offset %ld of %d bytes", (long)((char*)p - buf), buf_len); + zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Error at offset %pd of %d bytes", (zend_long)((char*)p - buf), buf_len); return; } /* }}} */ @@ -1009,19 +928,14 @@ typedef enum { SPL_METHOD(MultipleIterator, __construct) { spl_SplObjectStorage *intern; - long flags = MIT_NEED_ALL|MIT_KEYS_NUMERIC; - zend_error_handling error_handling; - - zend_replace_error_handling(EH_THROW, spl_ce_InvalidArgumentException, &error_handling TSRMLS_CC); + zend_long flags = MIT_NEED_ALL|MIT_KEYS_NUMERIC; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags) == FAILURE) { - zend_restore_error_handling(&error_handling TSRMLS_CC); + if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "|l", &flags) == FAILURE) { return; } - intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_SPLOBJSTORAGE_P(getThis()); intern->flags = flags; - zend_restore_error_handling(&error_handling TSRMLS_CC); } /* }}} */ @@ -1029,7 +943,7 @@ SPL_METHOD(MultipleIterator, __construct) Return current flags */ SPL_METHOD(MultipleIterator, getFlags) { - spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; @@ -1043,9 +957,9 @@ SPL_METHOD(MultipleIterator, getFlags) SPL_METHOD(MultipleIterator, setFlags) { spl_SplObjectStorage *intern; - intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_SPLOBJSTORAGE_P(getThis()); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &intern->flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &intern->flags) == FAILURE) { return; } } @@ -1058,33 +972,31 @@ SPL_METHOD(MultipleIterator, attachIterator) spl_SplObjectStorage *intern; zval *iterator = NULL, *info = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|z!", &iterator, zend_ce_iterator, &info) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|z!", &iterator, zend_ce_iterator, &info) == FAILURE) { return; } - intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_SPLOBJSTORAGE_P(getThis()); if (info != NULL) { spl_SplObjectStorageElement *element; - zval compare_result; if (Z_TYPE_P(info) != IS_LONG && Z_TYPE_P(info) != IS_STRING) { - zend_throw_exception(spl_ce_InvalidArgumentException, "Info must be NULL, integer or string", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_InvalidArgumentException, "Info must be NULL, integer or string", 0); return; } zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); - while (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == SUCCESS) { - is_identical_function(&compare_result, info, element->inf TSRMLS_CC); - if (Z_LVAL(compare_result)) { - zend_throw_exception(spl_ce_InvalidArgumentException, "Key duplication error", 0 TSRMLS_CC); + while ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) != NULL) { + if (fast_is_identical_function(info, &element->inf)) { + zend_throw_exception(spl_ce_InvalidArgumentException, "Key duplication error", 0); return; } zend_hash_move_forward_ex(&intern->storage, &intern->pos); } } - spl_object_storage_attach(intern, getThis(), iterator, info TSRMLS_CC); + spl_object_storage_attach(intern, getThis(), iterator, info); } /* }}} */ @@ -1096,16 +1008,16 @@ SPL_METHOD(MultipleIterator, rewind) spl_SplObjectStorageElement *element; zval *it; - intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_SPLOBJSTORAGE_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; } zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); - while (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == SUCCESS && !EG(exception)) { - it = element->obj; - zend_call_method_with_0_params(&it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_rewind, "rewind", NULL); + while ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) != NULL && !EG(exception)) { + it = &element->obj; + zend_call_method_with_0_params(it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_rewind, "rewind", NULL); zend_hash_move_forward_ex(&intern->storage, &intern->pos); } } @@ -1119,16 +1031,16 @@ SPL_METHOD(MultipleIterator, next) spl_SplObjectStorageElement *element; zval *it; - intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_SPLOBJSTORAGE_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; } zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); - while (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == SUCCESS && !EG(exception)) { - it = element->obj; - zend_call_method_with_0_params(&it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_next, "next", NULL); + while ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) != NULL && !EG(exception)) { + it = &element->obj; + zend_call_method_with_0_params(it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_next, "next", NULL); zend_hash_move_forward_ex(&intern->storage, &intern->pos); } } @@ -1140,10 +1052,10 @@ SPL_METHOD(MultipleIterator, valid) { spl_SplObjectStorage *intern; spl_SplObjectStorageElement *element; - zval *it, *retval = NULL; - long expect, valid; + zval *it, retval; + zend_long expect, valid; - intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_SPLOBJSTORAGE_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; @@ -1156,12 +1068,12 @@ SPL_METHOD(MultipleIterator, valid) expect = (intern->flags & MIT_NEED_ALL) ? 1 : 0; zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); - while (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == SUCCESS && !EG(exception)) { - it = element->obj; - zend_call_method_with_0_params(&it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_valid, "valid", &retval); + while ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) != NULL && !EG(exception)) { + it = &element->obj; + zend_call_method_with_0_params(it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_valid, "valid", &retval); - if (retval) { - valid = Z_LVAL_P(retval); + if (!Z_ISUNDEF(retval)) { + valid = (Z_TYPE(retval) == IS_TRUE); zval_ptr_dtor(&retval); } else { valid = 0; @@ -1178,10 +1090,10 @@ SPL_METHOD(MultipleIterator, valid) } /* }}} */ -static void spl_multiple_iterator_get_all(spl_SplObjectStorage *intern, int get_type, zval *return_value TSRMLS_DC) /* {{{ */ +static void spl_multiple_iterator_get_all(spl_SplObjectStorage *intern, int get_type, zval *return_value) /* {{{ */ { spl_SplObjectStorageElement *element; - zval *it, *retval = NULL; + zval *it, retval; int valid = 1, num_elements; num_elements = zend_hash_num_elements(&intern->storage); @@ -1192,12 +1104,12 @@ static void spl_multiple_iterator_get_all(spl_SplObjectStorage *intern, int get_ array_init_size(return_value, num_elements); zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); - while (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == SUCCESS && !EG(exception)) { - it = element->obj; - zend_call_method_with_0_params(&it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_valid, "valid", &retval); + while ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) != NULL && !EG(exception)) { + it = &element->obj; + zend_call_method_with_0_params(it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_valid, "valid", &retval); - if (retval) { - valid = Z_LVAL_P(retval); + if (!Z_ISUNDEF(retval)) { + valid = Z_TYPE(retval) == IS_TRUE; zval_ptr_dtor(&retval); } else { valid = 0; @@ -1205,40 +1117,40 @@ static void spl_multiple_iterator_get_all(spl_SplObjectStorage *intern, int get_ if (valid) { if (SPL_MULTIPLE_ITERATOR_GET_ALL_CURRENT == get_type) { - zend_call_method_with_0_params(&it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_current, "current", &retval); + zend_call_method_with_0_params(it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_current, "current", &retval); } else { - zend_call_method_with_0_params(&it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_key, "key", &retval); + zend_call_method_with_0_params(it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_key, "key", &retval); } - if (!retval) { - zend_throw_exception(spl_ce_RuntimeException, "Failed to call sub iterator method", 0 TSRMLS_CC); + if (Z_ISUNDEF(retval)) { + zend_throw_exception(spl_ce_RuntimeException, "Failed to call sub iterator method", 0); return; } } else if (intern->flags & MIT_NEED_ALL) { if (SPL_MULTIPLE_ITERATOR_GET_ALL_CURRENT == get_type) { - zend_throw_exception(spl_ce_RuntimeException, "Called current() with non valid sub iterator", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_RuntimeException, "Called current() with non valid sub iterator", 0); } else { - zend_throw_exception(spl_ce_RuntimeException, "Called key() with non valid sub iterator", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_RuntimeException, "Called key() with non valid sub iterator", 0); } return; } else { - ALLOC_INIT_ZVAL(retval); + ZVAL_NULL(&retval); } if (intern->flags & MIT_KEYS_ASSOC) { - switch (Z_TYPE_P(element->inf)) { + switch (Z_TYPE(element->inf)) { case IS_LONG: - add_index_zval(return_value, Z_LVAL_P(element->inf), retval); + add_index_zval(return_value, Z_LVAL(element->inf), &retval); break; case IS_STRING: - add_assoc_zval_ex(return_value, Z_STRVAL_P(element->inf), Z_STRLEN_P(element->inf)+1U, retval); + zend_symtable_update(Z_ARRVAL_P(return_value), Z_STR(element->inf), &retval); break; default: zval_ptr_dtor(&retval); - zend_throw_exception(spl_ce_InvalidArgumentException, "Sub-Iterator is associated with NULL", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_InvalidArgumentException, "Sub-Iterator is associated with NULL", 0); return; } } else { - add_next_index_zval(return_value, retval); + add_next_index_zval(return_value, &retval); } zend_hash_move_forward_ex(&intern->storage, &intern->pos); @@ -1251,13 +1163,13 @@ static void spl_multiple_iterator_get_all(spl_SplObjectStorage *intern, int get_ SPL_METHOD(MultipleIterator, current) { spl_SplObjectStorage *intern; - intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); + intern = Z_SPLOBJSTORAGE_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; } - spl_multiple_iterator_get_all(intern, SPL_MULTIPLE_ITERATOR_GET_ALL_CURRENT, return_value TSRMLS_CC); + spl_multiple_iterator_get_all(intern, SPL_MULTIPLE_ITERATOR_GET_ALL_CURRENT, return_value); } /* }}} */ @@ -1265,14 +1177,14 @@ SPL_METHOD(MultipleIterator, current) Return an array of all registered Iterator instances key() result */ SPL_METHOD(MultipleIterator, key) { - spl_SplObjectStorage *intern; - intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); + spl_SplObjectStorage *intern; + intern = Z_SPLOBJSTORAGE_P(getThis()); if (zend_parse_parameters_none() == FAILURE) { return; } - spl_multiple_iterator_get_all(intern, SPL_MULTIPLE_ITERATOR_GET_ALL_KEY, return_value TSRMLS_CC); + spl_multiple_iterator_get_all(intern, SPL_MULTIPLE_ITERATOR_GET_ALL_KEY, return_value); } /* }}} */ @@ -1319,10 +1231,13 @@ PHP_MINIT_FUNCTION(spl_observer) REGISTER_SPL_STD_CLASS_EX(SplObjectStorage, spl_SplObjectStorage_new, spl_funcs_SplObjectStorage); memcpy(&spl_handler_SplObjectStorage, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + spl_handler_SplObjectStorage.offset = XtOffsetOf(spl_SplObjectStorage, std); spl_handler_SplObjectStorage.get_debug_info = spl_object_storage_debug_info; spl_handler_SplObjectStorage.compare_objects = spl_object_storage_compare_objects; spl_handler_SplObjectStorage.clone_obj = spl_object_storage_clone; spl_handler_SplObjectStorage.get_gc = spl_object_storage_get_gc; + spl_handler_SplObjectStorage.dtor_obj = zend_objects_destroy_object; + spl_handler_SplObjectStorage.free_obj = spl_SplObjectStorage_free_storage; REGISTER_SPL_IMPLEMENTS(SplObjectStorage, Countable); REGISTER_SPL_IMPLEMENTS(SplObjectStorage, Iterator); diff --git a/ext/spl/spl_observer.h b/ext/spl/spl_observer.h index d6adeefb41..c5c705b2b7 100644 --- a/ext/spl/spl_observer.h +++ b/ext/spl/spl_observer.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ diff --git a/ext/spl/tests/CallbackFilterIteratorTest-002.phpt b/ext/spl/tests/CallbackFilterIteratorTest-002.phpt index cbad2e3b9c..216a40bd6a 100644 --- a/ext/spl/tests/CallbackFilterIteratorTest-002.phpt +++ b/ext/spl/tests/CallbackFilterIteratorTest-002.phpt @@ -10,25 +10,25 @@ set_error_handler(function($errno, $errstr){ try { new CallbackFilterIterator(); -} catch(InvalidArgumentException $e) { +} catch (TypeError $e) { echo $e->getMessage() . "\n"; } try { new CallbackFilterIterator(null); -} catch(InvalidArgumentException $e) { +} catch (TypeError $e) { echo $e->getMessage() . "\n"; } try { new CallbackFilterIterator(new ArrayIterator(array()), null); -} catch(InvalidArgumentException $e) { +} catch (TypeError $e) { echo $e->getMessage() . "\n"; } try { new CallbackFilterIterator(new ArrayIterator(array()), array()); -} catch(InvalidArgumentException $e) { +} catch (TypeError $e) { echo $e->getMessage() . "\n"; } @@ -44,7 +44,6 @@ try { --EXPECT-- CallbackFilterIterator::__construct() expects exactly 2 parameters, 0 given Argument 1 passed to CallbackFilterIterator::__construct() must implement interface Iterator, null given -CallbackFilterIterator::__construct() expects exactly 2 parameters, 1 given CallbackFilterIterator::__construct() expects parameter 2 to be a valid callback, no array or string given CallbackFilterIterator::__construct() expects parameter 2 to be a valid callback, array must have exactly two members some message diff --git a/ext/spl/tests/DirectoryIterator_empty_constructor.phpt b/ext/spl/tests/DirectoryIterator_empty_constructor.phpt index da5276ccdc..d0753fc33e 100644 --- a/ext/spl/tests/DirectoryIterator_empty_constructor.phpt +++ b/ext/spl/tests/DirectoryIterator_empty_constructor.phpt @@ -8,7 +8,7 @@ Havard Eide <nucleuz@gmail.com> $it = new DirectoryIterator(""); ?> --EXPECTF-- -Fatal error: Uncaught exception 'RuntimeException' with message 'Directory name must not be empty.' in %s:%d +Fatal error: Uncaught RuntimeException: Directory name must not be empty. in %s:%d Stack trace: #0 %s(%d): DirectoryIterator->__construct('') #1 {main} diff --git a/ext/spl/tests/DirectoryIterator_getInode_error.phpt b/ext/spl/tests/DirectoryIterator_getInode_error.phpt index c3641f9d89..ba9014c690 100644 --- a/ext/spl/tests/DirectoryIterator_getInode_error.phpt +++ b/ext/spl/tests/DirectoryIterator_getInode_error.phpt @@ -21,7 +21,7 @@ var_dump($fileInfo->getInode()); ?> --EXPECTF-- -Fatal error: Uncaught exception 'RuntimeException' with message 'SplFileInfo::getInode(): stat failed for %s' in %s +Fatal error: Uncaught RuntimeException: SplFileInfo::getInode(): stat failed for %s in %s Stack trace: #0 %s: SplFileInfo->getInode() #1 {main} diff --git a/ext/spl/tests/RegexIterator_with_reference_replacement.phpt b/ext/spl/tests/RegexIterator_with_reference_replacement.phpt new file mode 100644 index 0000000000..18b3ef9089 --- /dev/null +++ b/ext/spl/tests/RegexIterator_with_reference_replacement.phpt @@ -0,0 +1,19 @@ +--TEST-- +RegexIterator with $replacement being a reference +--FILE-- +<?php +$a = new ArrayIterator(array('test1', 'test2', 'test3')); +$i = new RegexIterator($a, '/^(test)(\d+)/', RegexIterator::REPLACE); +$r = '$2:$1'; +$i->replacement =& $r; +var_dump(iterator_to_array($i)); +?> +--EXPECT-- +array(3) { + [0]=> + string(6) "1:test" + [1]=> + string(6) "2:test" + [2]=> + string(6) "3:test" +} diff --git a/ext/spl/tests/SplDoublyLinkedList_offsetGet_param_array.phpt b/ext/spl/tests/SplDoublyLinkedList_offsetGet_param_array.phpt index 5df4ab59a5..b2bc444550 100644 --- a/ext/spl/tests/SplDoublyLinkedList_offsetGet_param_array.phpt +++ b/ext/spl/tests/SplDoublyLinkedList_offsetGet_param_array.phpt @@ -11,7 +11,7 @@ $get = $array->offsetGet( array( 'fail' ) ); ?> --EXPECTF-- -Fatal error: Uncaught exception 'OutOfRangeException' with message 'Offset invalid or out of range' in %s +Fatal error: Uncaught OutOfRangeException: Offset invalid or out of range in %s Stack trace: #0 %s #1 {main} diff --git a/ext/spl/tests/SplDoublyLinkedList_offsetGet_param_string.phpt b/ext/spl/tests/SplDoublyLinkedList_offsetGet_param_string.phpt index fcff762e6b..a387439d16 100644 --- a/ext/spl/tests/SplDoublyLinkedList_offsetGet_param_string.phpt +++ b/ext/spl/tests/SplDoublyLinkedList_offsetGet_param_string.phpt @@ -11,7 +11,7 @@ $get = $array->offsetGet( 'fail' ); ?> --EXPECTF-- -Fatal error: Uncaught exception 'OutOfRangeException' with message 'Offset invalid or out of range' in %s +Fatal error: Uncaught OutOfRangeException: Offset invalid or out of range in %s Stack trace: #0 %s #1 {main} diff --git a/ext/spl/tests/SplDoublyLinkedList_setIteratorMode_param_SplDoublyLinkedList.phpt b/ext/spl/tests/SplDoublyLinkedList_setIteratorMode_param_SplDoublyLinkedList.phpt index 9bf7a32007..f370159e3b 100644 --- a/ext/spl/tests/SplDoublyLinkedList_setIteratorMode_param_SplDoublyLinkedList.phpt +++ b/ext/spl/tests/SplDoublyLinkedList_setIteratorMode_param_SplDoublyLinkedList.phpt @@ -8,4 +8,4 @@ $dll = new SplDoublyLinkedList(2); $dll->setIteratorMode(new SplDoublyLinkedList(2)); ?> --EXPECTF-- -Warning: SplDoublyLinkedList::setIteratorMode() expects parameter 1 to be long, object given in %s on line %d
\ No newline at end of file +Warning: SplDoublyLinkedList::setIteratorMode() expects parameter 1 to be integer, object given in %s on line %d
\ No newline at end of file diff --git a/ext/spl/tests/SplFileInfo_getGroup_error.phpt b/ext/spl/tests/SplFileInfo_getGroup_error.phpt index f0db00d9ed..acfa6b99c5 100644 --- a/ext/spl/tests/SplFileInfo_getGroup_error.phpt +++ b/ext/spl/tests/SplFileInfo_getGroup_error.phpt @@ -21,7 +21,7 @@ var_dump($fileInfo->getGroup()); ?> --EXPECTF-- -Fatal error: Uncaught exception 'RuntimeException' with message 'SplFileInfo::getGroup(): stat failed for not_existing' in %s +Fatal error: Uncaught RuntimeException: SplFileInfo::getGroup(): stat failed for not_existing in %s Stack trace: #0 %s: SplFileInfo->getGroup() #1 {main} diff --git a/ext/spl/tests/SplFileInfo_getInode_error.phpt b/ext/spl/tests/SplFileInfo_getInode_error.phpt index bf8efae4c9..31b5382336 100644 --- a/ext/spl/tests/SplFileInfo_getInode_error.phpt +++ b/ext/spl/tests/SplFileInfo_getInode_error.phpt @@ -21,7 +21,7 @@ var_dump($fileInfo->getInode()); ?> --EXPECTF-- -Fatal error: Uncaught exception 'RuntimeException' with message 'SplFileInfo::getInode(): stat failed for not_existing' in %s +Fatal error: Uncaught RuntimeException: SplFileInfo::getInode(): stat failed for not_existing in %s Stack trace: #0 %s: SplFileInfo->getInode() #1 {main} diff --git a/ext/spl/tests/SplFileInfo_getOwner_error.phpt b/ext/spl/tests/SplFileInfo_getOwner_error.phpt index d5d46781cc..f6b4b29195 100644 --- a/ext/spl/tests/SplFileInfo_getOwner_error.phpt +++ b/ext/spl/tests/SplFileInfo_getOwner_error.phpt @@ -21,7 +21,7 @@ var_dump($fileInfo->getOwner()); ?> --EXPECTF-- -Fatal error: Uncaught exception 'RuntimeException' with message 'SplFileInfo::getOwner(): stat failed for not_existing' in %s +Fatal error: Uncaught RuntimeException: SplFileInfo::getOwner(): stat failed for not_existing in %s Stack trace: #0 %s: SplFileInfo->getOwner() #1 {main} diff --git a/ext/spl/tests/SplFileInfo_getPerms_error.phpt b/ext/spl/tests/SplFileInfo_getPerms_error.phpt index 8e05cdf8df..23b48de976 100644 --- a/ext/spl/tests/SplFileInfo_getPerms_error.phpt +++ b/ext/spl/tests/SplFileInfo_getPerms_error.phpt @@ -21,7 +21,7 @@ var_dump($fileInfo->getPerms() == 0100557); ?> --EXPECTF-- -Fatal error: Uncaught exception 'RuntimeException' with message 'SplFileInfo::getPerms(): stat failed for %s' in %s +Fatal error: Uncaught RuntimeException: SplFileInfo::getPerms(): stat failed for %s in %s Stack trace: #0 %s: SplFileInfo->getPerms() #1 {main} diff --git a/ext/spl/tests/SplFixedArray__construct_param_array.phpt b/ext/spl/tests/SplFixedArray__construct_param_array.phpt index d63d7cca54..b15579edca 100644 --- a/ext/spl/tests/SplFixedArray__construct_param_array.phpt +++ b/ext/spl/tests/SplFixedArray__construct_param_array.phpt @@ -5,8 +5,12 @@ PHPNW Test Fest 2009 - Jordan Hatch --FILE-- <?php -$array = new SplFixedArray( array("string", 1) ); +try { + $array = new SplFixedArray( array("string", 1) ); +} catch (TypeError $iae) { + echo "Ok - ".$iae->getMessage().PHP_EOL; +} ?> --EXPECTF-- -Warning: SplFixedArray::__construct() expects parameter 1 to be long, array given in %s on line %d
\ No newline at end of file +Ok - SplFixedArray::__construct() expects parameter 1 to be integer, array given diff --git a/ext/spl/tests/SplFixedArray__construct_param_string.phpt b/ext/spl/tests/SplFixedArray__construct_param_string.phpt index 3a7e734b06..d30fc691c6 100644 --- a/ext/spl/tests/SplFixedArray__construct_param_string.phpt +++ b/ext/spl/tests/SplFixedArray__construct_param_string.phpt @@ -4,9 +4,13 @@ SplFixedArray::__construct() with string passed as parameter. PHPNW Test Fest 2009 - Jordan Hatch --FILE-- <?php +try { + $array = new SplFixedArray( "string" ); +} catch (TypeError $iae) { + echo "Ok - ".$iae->getMessage().PHP_EOL; +} -$array = new SplFixedArray( "string" ); ?> --EXPECTF-- -Warning: SplFixedArray::__construct() expects parameter 1 to be long, %unicode_string_optional% given in %s on line %d +Ok - SplFixedArray::__construct() expects parameter 1 to be integer, %unicode_string_optional% given diff --git a/ext/spl/tests/SplFixedArray_construct_param_SplFixedArray.phpt b/ext/spl/tests/SplFixedArray_construct_param_SplFixedArray.phpt index 6582f847bd..4739d8c55d 100644 --- a/ext/spl/tests/SplFixedArray_construct_param_SplFixedArray.phpt +++ b/ext/spl/tests/SplFixedArray_construct_param_SplFixedArray.phpt @@ -4,10 +4,12 @@ Create an SplFixedArray using an SplFixedArray object. Philip Norton philipnorton42@gmail.com --FILE-- <?php -$array = new SplFixedArray(new SplFixedArray(3)); -var_dump($array); +try { + $array = new SplFixedArray(new SplFixedArray(3)); +} catch (TypeError $iae) { + echo "Ok - ".$iae->getMessage().PHP_EOL; +} + ?> --EXPECTF-- -Warning: SplFixedArray::__construct() expects parameter 1 to be long, object given in %s on line %d -object(SplFixedArray)#1 (0) { -}
\ No newline at end of file +Ok - SplFixedArray::__construct() expects parameter 1 to be integer, object given diff --git a/ext/spl/tests/SplFixedArray_setSize_param_array.phpt b/ext/spl/tests/SplFixedArray_setSize_param_array.phpt index 269a45de1b..ee155bb6da 100644 --- a/ext/spl/tests/SplFixedArray_setSize_param_array.phpt +++ b/ext/spl/tests/SplFixedArray_setSize_param_array.phpt @@ -9,7 +9,7 @@ $fixed_array->setSize(array()); var_dump($fixed_array); ?> --EXPECTF-- -Warning: SplFixedArray::setSize() expects parameter 1 to be long, array given in %s on line %d +Warning: SplFixedArray::setSize() expects parameter 1 to be integer, array given in %s on line %d object(SplFixedArray)#1 (2) { [0]=> NULL diff --git a/ext/spl/tests/SplHeap_with_by_reference_compare.phpt b/ext/spl/tests/SplHeap_with_by_reference_compare.phpt new file mode 100644 index 0000000000..b7b7b6d747 --- /dev/null +++ b/ext/spl/tests/SplHeap_with_by_reference_compare.phpt @@ -0,0 +1,16 @@ +--TEST-- +SplHeap using a compare function returning by-reference +--FILE-- +<?php +class Heap extends SplMinHeap { + public function &compare($a, $b) { + return $a; + } +} +$h = new Heap; +$h->insert(0); +$h->insert(0); +?> +===DONE=== +--EXPECT-- +===DONE=== diff --git a/ext/spl/tests/SplObjectStorage_addAll_invalid_parameter.phpt b/ext/spl/tests/SplObjectStorage_addAll_invalid_parameter.phpt index 62605b1dcf..c3f73c4bd1 100644 --- a/ext/spl/tests/SplObjectStorage_addAll_invalid_parameter.phpt +++ b/ext/spl/tests/SplObjectStorage_addAll_invalid_parameter.phpt @@ -35,7 +35,7 @@ NULL Warning: SplObjectStorage::addAll() expects parameter 1 to be SplObjectStorage, integer given in %s on line %d NULL -Warning: SplObjectStorage::addAll() expects parameter 1 to be SplObjectStorage, double given in %s on line %d +Warning: SplObjectStorage::addAll() expects parameter 1 to be SplObjectStorage, float given in %s on line %d NULL Warning: SplObjectStorage::addAll() expects parameter 1 to be SplObjectStorage, null given in %s on line %d diff --git a/ext/spl/tests/SplObjectStorage_contains_invalid_parameter.phpt b/ext/spl/tests/SplObjectStorage_contains_invalid_parameter.phpt index f523928702..7e065952b8 100644 --- a/ext/spl/tests/SplObjectStorage_contains_invalid_parameter.phpt +++ b/ext/spl/tests/SplObjectStorage_contains_invalid_parameter.phpt @@ -35,7 +35,7 @@ NULL Warning: SplObjectStorage::contains() expects parameter 1 to be object, integer given in %s on line %d NULL -Warning: SplObjectStorage::contains() expects parameter 1 to be object, double given in %s on line %d +Warning: SplObjectStorage::contains() expects parameter 1 to be object, float given in %s on line %d NULL Warning: SplObjectStorage::contains() expects parameter 1 to be object, null given in %s on line %d diff --git a/ext/spl/tests/SplObjectStorage_detach_invalid_parameter.phpt b/ext/spl/tests/SplObjectStorage_detach_invalid_parameter.phpt index 83b79fcbf2..0841dfc1c9 100644 --- a/ext/spl/tests/SplObjectStorage_detach_invalid_parameter.phpt +++ b/ext/spl/tests/SplObjectStorage_detach_invalid_parameter.phpt @@ -35,7 +35,7 @@ NULL Warning: SplObjectStorage::detach() expects parameter 1 to be object, integer given in %s on line %d NULL -Warning: SplObjectStorage::detach() expects parameter 1 to be object, double given in %s on line %d +Warning: SplObjectStorage::detach() expects parameter 1 to be object, float given in %s on line %d NULL Warning: SplObjectStorage::detach() expects parameter 1 to be object, null given in %s on line %d diff --git a/ext/spl/tests/SplObjectStorage_offsetGet_invalid_parameter.phpt b/ext/spl/tests/SplObjectStorage_offsetGet_invalid_parameter.phpt index 3f8bd437ec..4b495a0c44 100644 --- a/ext/spl/tests/SplObjectStorage_offsetGet_invalid_parameter.phpt +++ b/ext/spl/tests/SplObjectStorage_offsetGet_invalid_parameter.phpt @@ -37,7 +37,7 @@ NULL Warning: SplObjectStorage::offsetGet() expects parameter 1 to be object, integer given in %s on line %d NULL -Warning: SplObjectStorage::offsetGet() expects parameter 1 to be object, double given in %s on line %d +Warning: SplObjectStorage::offsetGet() expects parameter 1 to be object, float given in %s on line %d NULL Warning: SplObjectStorage::offsetGet() expects parameter 1 to be object, null given in %s on line %d diff --git a/ext/spl/tests/SplObjectStorage_removeAllExcept_invalid_parameter.phpt b/ext/spl/tests/SplObjectStorage_removeAllExcept_invalid_parameter.phpt index 62e0dde65b..8ffb0e6721 100644 --- a/ext/spl/tests/SplObjectStorage_removeAllExcept_invalid_parameter.phpt +++ b/ext/spl/tests/SplObjectStorage_removeAllExcept_invalid_parameter.phpt @@ -36,7 +36,7 @@ NULL Warning: SplObjectStorage::removeAllExcept() expects parameter 1 to be SplObjectStorage, integer given in %s on line %d NULL -Warning: SplObjectStorage::removeAllExcept() expects parameter 1 to be SplObjectStorage, double given in %s on line %d +Warning: SplObjectStorage::removeAllExcept() expects parameter 1 to be SplObjectStorage, float given in %s on line %d NULL Warning: SplObjectStorage::removeAllExcept() expects parameter 1 to be SplObjectStorage, null given in %s on line %d diff --git a/ext/spl/tests/SplObjectStorage_removeAll_invalid_parameter.phpt b/ext/spl/tests/SplObjectStorage_removeAll_invalid_parameter.phpt index ffd339869f..a0c48aac75 100644 --- a/ext/spl/tests/SplObjectStorage_removeAll_invalid_parameter.phpt +++ b/ext/spl/tests/SplObjectStorage_removeAll_invalid_parameter.phpt @@ -35,7 +35,7 @@ NULL Warning: SplObjectStorage::removeAll() expects parameter 1 to be SplObjectStorage, integer given in %s on line %d NULL -Warning: SplObjectStorage::removeAll() expects parameter 1 to be SplObjectStorage, double given in %s on line %d +Warning: SplObjectStorage::removeAll() expects parameter 1 to be SplObjectStorage, float given in %s on line %d NULL Warning: SplObjectStorage::removeAll() expects parameter 1 to be SplObjectStorage, null given in %s on line %d diff --git a/ext/spl/tests/SplTempFileObject_constructor_error.phpt b/ext/spl/tests/SplTempFileObject_constructor_error.phpt index d2717ac5ae..fe47366987 100644 --- a/ext/spl/tests/SplTempFileObject_constructor_error.phpt +++ b/ext/spl/tests/SplTempFileObject_constructor_error.phpt @@ -2,11 +2,11 @@ SPL SplTempFileObject constructor sets correct defaults when pass 0 arguments --FILE-- <?php -new SplTempFileObject('invalid'); +try { + new SplTempFileObject('invalid'); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} ?> --EXPECTF-- -Fatal error: Uncaught exception 'RuntimeException' with message 'SplTempFileObject::__construct() expects parameter 1 to be long, string given' in %s -Stack trace: -#0 %s: SplTempFileObject->__construct('invalid') -#1 {main} - thrown in %s +SplTempFileObject::__construct() expects parameter 1 to be integer, string given diff --git a/ext/spl/tests/arrayObject___construct_basic7.phpt b/ext/spl/tests/arrayObject___construct_basic7.phpt new file mode 100644 index 0000000000..2474b38ce6 --- /dev/null +++ b/ext/spl/tests/arrayObject___construct_basic7.phpt @@ -0,0 +1,34 @@ +--TEST-- +SPL: ArrayObject::__construct: Using object with shared properties +--FILE-- +<?php +$y = 2; +$x = 1; +$a = array($y, $x); +$o = (object)$a; +$ao = new ArrayObject($o); +$ao->asort(); +var_dump($a, $o, $ao); +?> +--EXPECT-- +array(2) { + [0]=> + int(2) + [1]=> + int(1) +} +object(stdClass)#1 (2) { + [1]=> + int(1) + [0]=> + int(2) +} +object(ArrayObject)#2 (1) { + ["storage":"ArrayObject":private]=> + object(stdClass)#1 (2) { + [1]=> + int(1) + [0]=> + int(2) + } +} diff --git a/ext/spl/tests/arrayObject___construct_error1.phpt b/ext/spl/tests/arrayObject___construct_error1.phpt index 21c312d2d0..f0e1107d51 100644 --- a/ext/spl/tests/arrayObject___construct_error1.phpt +++ b/ext/spl/tests/arrayObject___construct_error1.phpt @@ -7,14 +7,14 @@ $a = new stdClass; $a->p = 1; try { var_dump(new ArrayObject($a, 0, "Exception")); -} catch (InvalidArgumentException $e) { +} catch (TypeError $e) { echo $e->getMessage() . "(" . $e->getLine() . ")\n"; } echo "Non-existent class:\n"; try { var_dump(new ArrayObject(new stdClass, 0, "nonExistentClassName")); -} catch (InvalidArgumentException $e) { +} catch (TypeError $e) { echo $e->getMessage() . "(" . $e->getLine() . ")\n"; } ?> diff --git a/ext/spl/tests/arrayObject___construct_error2.phpt b/ext/spl/tests/arrayObject___construct_error2.phpt index 850a2cb3fc..35ba83d09f 100644 --- a/ext/spl/tests/arrayObject___construct_error2.phpt +++ b/ext/spl/tests/arrayObject___construct_error2.phpt @@ -13,10 +13,10 @@ Class C implements Iterator { try { var_dump(new ArrayObject(new stdClass, 0, "C", "extra")); -} catch (InvalidArgumentException $e) { +} catch (TypeError $e) { echo $e->getMessage() . "(" . $e->getLine() . ")\n"; } ?> --EXPECTF-- Too many arguments: -ArrayObject::__construct() expects at most 3 parameters, 4 given(12)
\ No newline at end of file +ArrayObject::__construct() expects at most 3 parameters, 4 given(12) diff --git a/ext/spl/tests/arrayObject_asort_basic1.phpt b/ext/spl/tests/arrayObject_asort_basic1.phpt index 53df1d502b..6a523aec66 100644 --- a/ext/spl/tests/arrayObject_asort_basic1.phpt +++ b/ext/spl/tests/arrayObject_asort_basic1.phpt @@ -36,7 +36,7 @@ object(ArrayObject)#%d (1) { } } -Warning: asort() expects parameter 2 to be long, string given in %sarrayObject_asort_basic1.php on line %d +Warning: asort() expects parameter 2 to be integer, string given in %sarrayObject_asort_basic1.php on line %d bool(false) object(ArrayObject)#%d (1) { ["storage":"ArrayObject":private]=> diff --git a/ext/spl/tests/arrayObject_exchangeArray_basic3.phpt b/ext/spl/tests/arrayObject_exchangeArray_basic3.phpt index 4045b7a946..ed2b8e89e1 100644 --- a/ext/spl/tests/arrayObject_exchangeArray_basic3.phpt +++ b/ext/spl/tests/arrayObject_exchangeArray_basic3.phpt @@ -98,9 +98,7 @@ object(C)#3 (2) { ["addedToOriginal"]=> string(17) "added To Original" } -array(2) { - ["pub1"]=> - string(7) "public1" +array(1) { ["addedToCopy"]=> string(13) "added To Copy" } diff --git a/ext/spl/tests/arrayObject_ksort_basic1.phpt b/ext/spl/tests/arrayObject_ksort_basic1.phpt index 8f37938126..1e7aa01fe8 100644 --- a/ext/spl/tests/arrayObject_ksort_basic1.phpt +++ b/ext/spl/tests/arrayObject_ksort_basic1.phpt @@ -35,7 +35,7 @@ object(ArrayObject)#%d (1) { } } -Warning: ksort() expects parameter 2 to be long, string given in %sarrayObject_ksort_basic1.php on line %d +Warning: ksort() expects parameter 2 to be integer, string given in %sarrayObject_ksort_basic1.php on line %d bool(false) object(ArrayObject)#2 (1) { ["storage":"ArrayObject":private]=> diff --git a/ext/spl/tests/arrayObject_setFlags_basic2.phpt b/ext/spl/tests/arrayObject_setFlags_basic2.phpt index 806f8129a3..6eece74cbb 100644 --- a/ext/spl/tests/arrayObject_setFlags_basic2.phpt +++ b/ext/spl/tests/arrayObject_setFlags_basic2.phpt @@ -26,4 +26,7 @@ string(6) "secret" string(6) "public" string(6) "secret" -Fatal error: Cannot access private property C::$x in %s on line 19 +Fatal error: Uncaught Error: Cannot access private property C::$x in %s:19 +Stack trace: +#0 {main} + thrown in %s on line 19 diff --git a/ext/spl/tests/arrayObject_setIteratorClass_error1.phpt b/ext/spl/tests/arrayObject_setIteratorClass_error1.phpt index 4715eea986..89efdb6a9f 100644 --- a/ext/spl/tests/arrayObject_setIteratorClass_error1.phpt +++ b/ext/spl/tests/arrayObject_setIteratorClass_error1.phpt @@ -28,7 +28,7 @@ try { foreach($ao as $key=>$value) { echo " $key=>$value\n"; } -} catch (Exception $e) { +} catch (TypeError $e) { var_dump($e->getMessage()); } @@ -37,7 +37,7 @@ try { foreach($ao as $key=>$value) { echo " $key=>$value\n"; } -} catch (Exception $e) { +} catch (TypeError $e) { var_dump($e->getMessage()); } diff --git a/ext/spl/tests/array_015.phpt b/ext/spl/tests/array_015.phpt index f0bf9f4087..cd3ce5f45a 100644 --- a/ext/spl/tests/array_015.phpt +++ b/ext/spl/tests/array_015.phpt @@ -56,9 +56,7 @@ object(ArrayObject)#%d (1) { int(5) } } - -Notice: ArrayIterator::next(): Array was modified outside object and internal position is no longer valid in %sarray_015.php on line %d -int(2) +int(3) object(ArrayObject)#%d (1) { %s"storage"%s"ArrayObject":private]=> array(4) { @@ -84,14 +82,11 @@ object(ArrayObject)#%d (1) { } } 1=>2 - -Notice: main(): ArrayIterator::next(): Array was modified outside object and internal position is no longer valid in %sarray_015.php on line %d -3=>4 - -Notice: main(): ArrayIterator::next(): Array was modified outside object and internal position is no longer valid in %sarray_015.php on line %d object(ArrayObject)#%d (1) { %s"storage"%s"ArrayObject":private]=> - array(0) { + array(1) { + [3]=> + int(4) } } ===DONE=== diff --git a/ext/spl/tests/array_022.phpt b/ext/spl/tests/array_022.phpt index 82da3bbfe3..1ce6cae4ad 100644 --- a/ext/spl/tests/array_022.phpt +++ b/ext/spl/tests/array_022.phpt @@ -50,31 +50,21 @@ object(MyArrayObject)#%d (1) { ["bar"]=> string(3) "baz" } -object(MyArrayObject)#%d (3) { +object(MyArrayObject)#%d (2) { ["bar"]=> string(3) "baz" ["baz"]=> string(3) "Foo" - ["storage":"ArrayObject":private]=> - array(1) { - ["bar"]=> - string(3) "baz" - } } ==ArrayIterator=== object(MyArrayIterator)#%d (1) { ["bar"]=> string(3) "baz" } -object(MyArrayIterator)#%d (3) { +object(MyArrayIterator)#%d (2) { ["bar"]=> string(3) "baz" ["baz"]=> string(3) "Foo" - ["storage":"ArrayIterator":private]=> - object(MyArrayIterator)#%d (1) { - ["bar"]=> - string(3) "baz" - } } ===DONE=== diff --git a/ext/spl/tests/array_028.phpt b/ext/spl/tests/array_028.phpt new file mode 100644 index 0000000000..1adcdd3f90 --- /dev/null +++ b/ext/spl/tests/array_028.phpt @@ -0,0 +1,27 @@ +--TEST-- +ArrayObject/Iterator on array with NUL bytes +--FILE-- +<?php +$array = [ + "\0foo" => "bar", +]; + +$it = new ArrayIterator($array); +foreach ($it as $v) { + var_dump($v); +} + +$obj = new ArrayObject($array); +foreach ($obj as $v) { + var_dump($v); +} + +$obj = new ArrayObject($it); +foreach ($obj as $v) { + var_dump($v); +} +?> +--EXPECT-- +string(3) "bar" +string(3) "bar" +string(3) "bar" diff --git a/ext/spl/tests/bug31346.phpt b/ext/spl/tests/bug31346.phpt index 9b5618ec0e..e3bf51f57f 100644 --- a/ext/spl/tests/bug31346.phpt +++ b/ext/spl/tests/bug31346.phpt @@ -15,5 +15,4 @@ $i->next(); ?> ===DONE=== --EXPECTF-- -Notice: ArrayIterator::next(): Array was modified outside object and internal position is no longer valid in %sbug31346.php on line %d ===DONE=== diff --git a/ext/spl/tests/bug45614.phpt b/ext/spl/tests/bug45614.phpt index 8f999348e8..9ab3186a75 100644 --- a/ext/spl/tests/bug45614.phpt +++ b/ext/spl/tests/bug45614.phpt @@ -8,6 +8,7 @@ class C { public $pub1 = 'public1'; public $pub2 = 'public2'; public $pub3 = 'public3'; + public $pub4 = 'public4'; } function showFirstTwoItems($it) { @@ -48,8 +49,8 @@ pub1 => public1 pub2 => public2 --> Invalidate current position and show the first two items: -pub1 => public1 pub3 => public3 +pub4 => public4 --> Rewind, seek and show the first two items: pub1 => public1 diff --git a/ext/spl/tests/bug48023.phpt b/ext/spl/tests/bug48023.phpt index ed0ff9e35a..9cb8dd2c1f 100644 --- a/ext/spl/tests/bug48023.phpt +++ b/ext/spl/tests/bug48023.phpt @@ -9,4 +9,7 @@ new Foo; ?> ===DONE=== --EXPECTF-- -Fatal error: Class 'Foo' not found in %s on line %d +Fatal error: Uncaught Error: Class 'Foo' not found in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/ext/spl/tests/bug49972.phpt b/ext/spl/tests/bug49972.phpt index 843c2519ba..836d399ed9 100644 --- a/ext/spl/tests/bug49972.phpt +++ b/ext/spl/tests/bug49972.phpt @@ -8,4 +8,7 @@ $iterator->undefined(); ?> --EXPECTF-- -Fatal error: Call to undefined method AppendIterator::undefined() in %s on line %d +Fatal error: Uncaught Error: Call to undefined method AppendIterator::undefined() in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/ext/spl/tests/bug52238.phpt b/ext/spl/tests/bug52238.phpt index 10da0b5fd9..667c0a497a 100644 --- a/ext/spl/tests/bug52238.phpt +++ b/ext/spl/tests/bug52238.phpt @@ -15,7 +15,7 @@ class Foo implements IteratorAggregate var_dump(iterator_to_array(new Foo)); ?> --EXPECTF-- -Fatal error: Uncaught exception 'Exception' in %s +Fatal error: Uncaught Exception in %s Stack trace: #0 %s: Foo->bar() #1 [internal function]: Foo->getIterator() diff --git a/ext/spl/tests/bug54281.phpt b/ext/spl/tests/bug54281.phpt index 9a19a59ad8..1d83699e14 100644 --- a/ext/spl/tests/bug54281.phpt +++ b/ext/spl/tests/bug54281.phpt @@ -12,7 +12,7 @@ foreach($it as $k=>$v) { } ?> --EXPECTF-- -Fatal error: Uncaught exception 'LogicException' with message 'The object is in an invalid state as the parent constructor was not called' in %s:%d +Fatal error: Uncaught LogicException: The object is in an invalid state as the parent constructor was not called in %s:%d Stack trace: #0 %s%ebug54281.php(8): RecursiveIteratorIterator->rewind() #1 {main} diff --git a/ext/spl/tests/bug54291.phpt b/ext/spl/tests/bug54291.phpt index 9314b6b9ff..c0119c4360 100644 --- a/ext/spl/tests/bug54291.phpt +++ b/ext/spl/tests/bug54291.phpt @@ -5,7 +5,7 @@ Bug #54291 (Crash iterating DirectoryIterator for dir name starting with \0) $dir = new DirectoryIterator("\x00/abc"); $dir->isFile(); --EXPECTF-- -Fatal error: Uncaught exception 'UnexpectedValueException' with message 'Failed to open directory ""' in %s:%d +Fatal error: Uncaught UnexpectedValueException: Failed to open directory "" in %s:%d Stack trace: #0 %s(%d): DirectoryIterator->__construct('\x00/abc') #1 {main} diff --git a/ext/spl/tests/bug54292.phpt b/ext/spl/tests/bug54292.phpt index d9175f7e6f..288f49a4ec 100644 --- a/ext/spl/tests/bug54292.phpt +++ b/ext/spl/tests/bug54292.phpt @@ -5,7 +5,7 @@ Bug #54292 (Wrong parameter causes crash in SplFileObject::__construct()) try { new SplFileObject('foo', array()); -} catch (Exception $e) { +} catch (TypeError $e) { var_dump($e->getMessage()); } diff --git a/ext/spl/tests/bug60201.phpt b/ext/spl/tests/bug60201.phpt index 68a5daabfd..c77988eb13 100644 --- a/ext/spl/tests/bug60201.phpt +++ b/ext/spl/tests/bug60201.phpt @@ -12,17 +12,17 @@ var_dump($params); --EXPECTF-- array(3) { [0]=> - &object(ReflectionParameter)#%d (1) { + object(ReflectionParameter)#%d (1) { ["name"]=> string(9) "delimiter" } [1]=> - &object(ReflectionParameter)#%d (1) { + object(ReflectionParameter)#%d (1) { ["name"]=> string(9) "enclosure" } [2]=> - &object(ReflectionParameter)#%d (1) { + object(ReflectionParameter)#%d (1) { ["name"]=> string(6) "escape" } diff --git a/ext/spl/tests/bug61527.phpt b/ext/spl/tests/bug61527.phpt index ab13c69547..03dbbe346b 100644 --- a/ext/spl/tests/bug61527.phpt +++ b/ext/spl/tests/bug61527.phpt @@ -67,26 +67,16 @@ var_dump($ai4->getChildren()); --EXPECTF-- NULL NULL - -Notice: ArrayIterator::next(): Array was modified outside object and internal position is no longer valid in %sbug61527.php on line %d - -Notice: ArrayIterator::key(): Array was modified outside object and internal position is no longer valid in %sbug61527.php on line %d +int(4) +int(5) NULL - -Notice: ArrayIterator::current(): Array was modified outside object and internal position is no longer valid in %sbug61527.php on line %d NULL -int(5) -int(5) NULL NULL NULL NULL NULL bool(false) - -Notice: RecursiveArrayIterator::hasChildren(): Array was modified outside object and internal position is no longer valid in %sbug61527.php on line %d bool(false) - -Notice: RecursiveArrayIterator::getChildren(): Array was modified outside object and internal position is no longer valid in %sbug61527.php on line %d NULL ==DONE== diff --git a/ext/spl/tests/bug62978.phpt b/ext/spl/tests/bug62978.phpt index 0d91609f88..5c55507ad9 100644 --- a/ext/spl/tests/bug62978.phpt +++ b/ext/spl/tests/bug62978.phpt @@ -44,7 +44,7 @@ Notice: Undefined index: epic_magic in %sbug62978.php on line %d NULL bool(false) -Strict Standards: Resource ID#%d used as offset, casting to integer (%d) in %sbug62978.php on line %d +Notice: Resource ID#%d used as offset, casting to integer (%d) in %sbug62978.php on line %d Notice: Undefined offset: %d in %sbug62978.php on line %d NULL diff --git a/ext/spl/tests/bug68479.phpt b/ext/spl/tests/bug68479.phpt index 1782a9cef2..e4e7976a9b 100644 --- a/ext/spl/tests/bug68479.phpt +++ b/ext/spl/tests/bug68479.phpt @@ -12,24 +12,24 @@ var_dump($params); --EXPECTF-- array(4) { [0]=> - &object(ReflectionParameter)#2 (1) { + object(ReflectionParameter)#2 (1) { ["name"]=> string(6) "fields" } [1]=> - &object(ReflectionParameter)#3 (1) { + object(ReflectionParameter)#3 (1) { ["name"]=> string(9) "delimiter" } [2]=> - &object(ReflectionParameter)#4 (1) { + object(ReflectionParameter)#4 (1) { ["name"]=> string(9) "enclosure" } [3]=> - &object(ReflectionParameter)#5 (1) { + object(ReflectionParameter)#5 (1) { ["name"]=> string(6) "escape" } } -===DONE===
\ No newline at end of file +===DONE=== diff --git a/ext/spl/tests/bug69335.phpt b/ext/spl/tests/bug69335.phpt new file mode 100644 index 0000000000..41f03efcb0 --- /dev/null +++ b/ext/spl/tests/bug69335.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #69335 (SplArray BC break) +--FILE-- +<?php +$a = array(1=>1, 3=>3, 5=>5, 7=>7); +$a = new ArrayObject($a); + +foreach ($a as $k => $v) { + var_dump("$k => $v"); + if ($k == 3) { + $a['a'] = "?"; + } +} +?> +--EXPECTF-- +string(6) "1 => 1" +string(6) "3 => 3" +string(6) "5 => 5" +string(6) "7 => 7" +string(6) "a => ?" diff --git a/ext/spl/tests/bug69737.phpt b/ext/spl/tests/bug69737.phpt index d954fa0830..02815c296a 100644 --- a/ext/spl/tests/bug69737.phpt +++ b/ext/spl/tests/bug69737.phpt @@ -13,4 +13,9 @@ $h->insert(6); ?> ===DONE=== --EXPECTF-- -Fatal error: Call to undefined method SplMinHeap::notexist() in %s%ebug69737.php on line %d +Fatal error: Uncaught Error: Call to undefined method SplMinHeap::notexist() in %s%ebug69737.php:%d +Stack trace: +#0 [internal function]: SplMinHeap1->compare(1, 6) +#1 %s%ebug69737.php(%d): SplHeap->insert(6) +#2 {main} + thrown in %s%ebug69737.php on line %d diff --git a/ext/spl/tests/bug69845.phpt b/ext/spl/tests/bug69845.phpt new file mode 100644 index 0000000000..db88a8e10d --- /dev/null +++ b/ext/spl/tests/bug69845.phpt @@ -0,0 +1,13 @@ +--TEST-- +Fixed bug #69845 (ArrayObject with ARRAY_AS_PROPS broken) +--FILE-- +<?php +for ($i = 0; $i<2; $i++) { + $data = new \ArrayObject(new stdClass(), ArrayObject::ARRAY_AS_PROPS); + $data->itemType = 'bulletin'; + var_dump(!is_null($data['itemType'])); +} +?> +--EXPECT-- +bool(true) +bool(true) diff --git a/ext/spl/tests/bug70053.phpt b/ext/spl/tests/bug70053.phpt new file mode 100644 index 0000000000..2cab083c37 --- /dev/null +++ b/ext/spl/tests/bug70053.phpt @@ -0,0 +1,21 @@ +--TEST-- +SPL: ArrayObject +--FILE-- +<?php + +echo "-- Two empty iterators attached with infos that are different but same array key --\n"; +$mit = new MultipleIterator(MultipleIterator::MIT_KEYS_ASSOC); +$mit ->attachIterator(new EmptyIterator(), "2"); +$mit ->attachIterator(new EmptyIterator(), 2); +var_dump($mit->countIterators()); +$mit->rewind(); +var_dump($mit->current()); + +?> +--EXPECT-- +-- Two empty iterators attached with infos that are different but same array key -- +int(2) +array(1) { + [2]=> + NULL +} diff --git a/ext/spl/tests/bug70290.phpt b/ext/spl/tests/bug70290.phpt deleted file mode 100644 index 0fd83c2d75..0000000000 --- a/ext/spl/tests/bug70290.phpt +++ /dev/null @@ -1,9 +0,0 @@ ---TEST-- -Bug #70290 (Null pointer deref (segfault) in spl_autoload via ob_start) ---INI-- -display_errors=2 ---FILE-- -<?php ob_start("spl_autoload"); ?> 1 ---EXPECT-- -Fatal error: Unknown: Class 1 - could not be loaded in Unknown on line 0 diff --git a/ext/spl/tests/bug70573.phpt b/ext/spl/tests/bug70573.phpt new file mode 100644 index 0000000000..b93e48876d --- /dev/null +++ b/ext/spl/tests/bug70573.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #70573 (Cloning SplPriorityQueue leads to memory leaks) +--FILE-- +<?php +$q1 = new SplPriorityQueue(); +$a = 1; +$q1->insert([$a], 1); +$q1->insert([$a], 2); +$q2 = clone $q1; +echo "ok\n"; +?> +--EXPECT-- +ok + + diff --git a/ext/spl/tests/bug70730.phpt b/ext/spl/tests/bug70730.phpt new file mode 100644 index 0000000000..5710c9586d --- /dev/null +++ b/ext/spl/tests/bug70730.phpt @@ -0,0 +1,44 @@ +--TEST-- +Bug #70730 (Incorrect ArrayObject serialization if unset is called in serialize()) +--FILE-- +<?php +class A extends \ArrayObject +{ + protected $foo; + + public function __construct() + { + $this->foo = 'bar'; + } + + public function serialize() + { + unset($this->foo); + $result = parent::serialize(); + $this->foo = 'bar'; + return $result; + } +} + +$a = new A(); +$a->append('item1'); +$a->append('item2'); +$a->append('item3'); +$b = new A(); +$b->unserialize($a->serialize()); +var_dump($b); +?> +--EXPECTF-- +object(A)#%d (2) { + ["foo":protected]=> + string(3) "bar" + ["storage":"ArrayObject":private]=> + array(3) { + [0]=> + string(5) "item1" + [1]=> + string(5) "item2" + [2]=> + string(5) "item3" + } +} diff --git a/ext/spl/tests/bug70853.phpt b/ext/spl/tests/bug70853.phpt new file mode 100644 index 0000000000..99530ece40 --- /dev/null +++ b/ext/spl/tests/bug70853.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #70853 (SplFixedArray throws exception when using ref variable as index) +--FILE-- +<?php + +$list = new SplFixedArray(10); +$ndx = 1; +$ndx2 =& $ndx; +$list[$ndx] = 123; // This throws an exception; +$list[$ndx2] = 123; // as does this, to. +echo 'ok'; + +?> +--EXPECT-- +ok diff --git a/ext/spl/tests/bug70868.phpt b/ext/spl/tests/bug70868.phpt new file mode 100644 index 0000000000..d3dd76354a --- /dev/null +++ b/ext/spl/tests/bug70868.phpt @@ -0,0 +1,32 @@ +--TEST-- +Bug #70868, with PCRE JIT +--INI-- +pcre.jit=1 +--SKIPIF-- +<?php if (!extension_loaded("pcre")) die("skip"); ?> +--FILE-- +<?php + +namespace X; + +$iterator = + new \RegexIterator( + new \ArrayIterator(['A.phpt', 'B.phpt', 'C.phpt']), + '/\.phpt$/' + ) +; + +foreach ($iterator as $foo) { + var_dump($foo); + preg_replace('/\.phpt$/', '', ''); +} + +echo "Done", PHP_EOL; + +?> +--EXPECTF-- + +string(6) "A.phpt" +string(6) "B.phpt" +string(6) "C.phpt" +Done diff --git a/ext/spl/tests/bug70959.phpt b/ext/spl/tests/bug70959.phpt new file mode 100644 index 0000000000..3fd500736d --- /dev/null +++ b/ext/spl/tests/bug70959.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug #70959 (ArrayObject unserialize does not restore protected fields) +--FILE-- +<?php +class testObject extends ArrayObject { + protected $test; + + public function getTest() { + return $this->test; + } + + public function setTest($test) { + $this->test = $test; + } +} + +$obj = new testObject(); +$obj->setTest('test'); +var_dump($obj->getTest()); +$obj2 = unserialize(serialize($obj)); +var_dump($obj2->getTest()); +--EXPECTF-- +string(4) "test" +string(4) "test" diff --git a/ext/spl/tests/bug71028.phpt b/ext/spl/tests/bug71028.phpt new file mode 100644 index 0000000000..b8f0cc962f --- /dev/null +++ b/ext/spl/tests/bug71028.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug #71028 (Undefined index with ArrayIterator) +--FILE-- +<?php +function cast(&$a) { + $a = (int)$a; +} + +$a = new ArrayIterator; +$a[-1] = 123; + +$b = "-1"; +cast($b); + +var_dump(isset($a[$b])); +$a[$b] = "okey"; +var_dump($a[$b]); +unset($a[$b]); +var_dump(isset($a[$b])); +?> +--EXPECT-- +bool(true) +string(4) "okey" +bool(false) diff --git a/ext/spl/tests/bug71153.phpt b/ext/spl/tests/bug71153.phpt new file mode 100644 index 0000000000..bdd940cbee --- /dev/null +++ b/ext/spl/tests/bug71153.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #71153: Performance Degradation in ArrayIterator with large arrays +--FILE-- +<?php + +$n = 200000; + +for ($i = 0; $i < $n; ++$i) { + foreach (new ArrayIterator([]) as $v) {} +} + +echo "done\n"; + +?> +--EXPECT-- +done diff --git a/ext/spl/tests/bug71202.phpt b/ext/spl/tests/bug71202.phpt new file mode 100644 index 0000000000..d26d7e1f35 --- /dev/null +++ b/ext/spl/tests/bug71202.phpt @@ -0,0 +1,38 @@ +--TEST-- +Bug #71202 (Autoload function registered by another not activated immediately) +--FILE-- +<?php + +function inner_autoload ($name){ + if ($name == 'A') { + class A { + function __construct(){ + echo "okey, "; + } + } + } else { + class B { + function __construct() { + die("error"); + } + } + } +} + +spl_autoload_register(function ($name) { + if ($name == 'A') { + spl_autoload_register("inner_autoload"); + } else { + spl_autoload_unregister("inner_autoload"); + } +}); + +$c = new A(); +try { + $c = new B(); +} catch (Error $e) { + echo "done"; +} +?> +--EXPECT-- +okey, done diff --git a/ext/spl/tests/bug71204.phpt b/ext/spl/tests/bug71204.phpt index 01a9f3bcaf..64fa13bfb1 100644 --- a/ext/spl/tests/bug71204.phpt +++ b/ext/spl/tests/bug71204.phpt @@ -13,4 +13,7 @@ spl_autoload_register(function ($name) { new A(); ?> --EXPECTF-- -Fatal error: Cannot destroy active lambda function in %sbug71204.php on line %d +Fatal error: Uncaught Error: Class 'A' not found in %sbug71204.php:%d +Stack trace: +#0 {main} + thrown in %sbug71204.php on line %d diff --git a/ext/spl/tests/fileobject_setmaxlinelen_error003.phpt b/ext/spl/tests/fileobject_setmaxlinelen_error003.phpt index 8dc50d5fc7..06451a3677 100644 --- a/ext/spl/tests/fileobject_setmaxlinelen_error003.phpt +++ b/ext/spl/tests/fileobject_setmaxlinelen_error003.phpt @@ -9,4 +9,4 @@ $s->setMaxLineLen('string'); ?> --EXPECTF-- -Warning: SplFileObject::setMaxLineLen() expects parameter 1 to be long, string given in %s on line %d +Warning: SplFileObject::setMaxLineLen() expects parameter 1 to be integer, string given in %s on line %d diff --git a/ext/spl/tests/fixedarray_002.phpt b/ext/spl/tests/fixedarray_002.phpt index 534d41f184..2521516c14 100644 --- a/ext/spl/tests/fixedarray_002.phpt +++ b/ext/spl/tests/fixedarray_002.phpt @@ -3,6 +3,9 @@ SPL: FixedArray: overloading --FILE-- <?php class A extends SplFixedArray { + public $prop1 = NULL; + public $prop2 = NULL; + public function count() { return 2; } diff --git a/ext/spl/tests/fixedarray_003.phpt b/ext/spl/tests/fixedarray_003.phpt index b6c5eb53e4..69cec7528e 100644 --- a/ext/spl/tests/fixedarray_003.phpt +++ b/ext/spl/tests/fixedarray_003.phpt @@ -3,6 +3,8 @@ SPL: FixedArray: Iterators --FILE-- <?php class A extends SplFixedArray { + public $prop1 = "dummy"; + public $prop2 = "dummy"; public function current() { echo "A::current\n"; diff --git a/ext/spl/tests/fixedarray_005.phpt b/ext/spl/tests/fixedarray_005.phpt index 9ccc693d55..cc64fd01b0 100644 --- a/ext/spl/tests/fixedarray_005.phpt +++ b/ext/spl/tests/fixedarray_005.phpt @@ -1,12 +1,30 @@ --TEST-- -SPL: FixedArray: Trying to instantiate passing object to constructor parameter +SPL: FixedArray: Invalid arguments --FILE-- <?php -$b = new stdClass; +try { + $a = new SplFixedArray(new stdClass); +} catch (TypeError $iae) { + echo "Ok - ".$iae->getMessage().PHP_EOL; +} -$a = new SplFixedArray($b); +try { + $a = new SplFixedArray('FOO'); +} catch (TypeError $iae) { + echo "Ok - ".$iae->getMessage().PHP_EOL; +} + +try { + $a = new SplFixedArray(''); +} catch (TypeError $iae) { + echo "Ok - ".$iae->getMessage().PHP_EOL; +} ?> ---EXPECTF-- -Warning: SplFixedArray::__construct() expects parameter 1 to be long, object given in %s on line %d +===DONE=== +--EXPECT-- +Ok - SplFixedArray::__construct() expects parameter 1 to be integer, object given +Ok - SplFixedArray::__construct() expects parameter 1 to be integer, string given +Ok - SplFixedArray::__construct() expects parameter 1 to be integer, string given +===DONE=== diff --git a/ext/spl/tests/fixedarray_009.phpt b/ext/spl/tests/fixedarray_009.phpt index 936d210a65..fe38883621 100644 --- a/ext/spl/tests/fixedarray_009.phpt +++ b/ext/spl/tests/fixedarray_009.phpt @@ -3,8 +3,11 @@ SPL: FixedArray: Trying to instantiate passing string to construtor parameter --FILE-- <?php -$a = new SplFixedArray('FOO'); - +try { + $a = new SplFixedArray('FOO'); +} catch (TypeError $iae) { + echo "Ok - ".$iae->getMessage().PHP_EOL; +} ?> --EXPECTF-- -Warning: SplFixedArray::__construct() expects parameter 1 to be long, string given in %s on line %d +Ok - SplFixedArray::__construct() expects parameter 1 to be integer, string given diff --git a/ext/spl/tests/fixedarray_015.phpt b/ext/spl/tests/fixedarray_015.phpt index 60fc4d12fd..b6f119ab1f 100644 --- a/ext/spl/tests/fixedarray_015.phpt +++ b/ext/spl/tests/fixedarray_015.phpt @@ -3,47 +3,14 @@ SPL: FixedArray: accessing uninitialized array --FILE-- <?php -$a = new SplFixedArray(''); - -try { - var_dump($a[1]); -} catch (Exception $e) { - echo $e->getMessage(), "\n"; -} -try { - $a[1] = 1; -} catch (Exception $e) { - echo $e->getMessage(), "\n"; -} -try { - var_dump(count($a[1])); -} catch (Exception $e) { - echo $e->getMessage(), "\n"; -} -try { - var_dump($a->getSize()); -} catch (Exception $e) { - echo $e->getMessage(), "\n"; -} -try { - foreach ($a as $v) { - } -} catch (Exception $e) { - echo $e->getMessage(), "\n"; -} try { - var_dump($a->setSize(10)); -} catch (Exception $e) { - echo $e->getMessage(), "\n"; + $a = new SplFixedArray(''); +} catch (TypeError $iae) { + echo "Ok - ".$iae->getMessage().PHP_EOL; } echo "Done\n"; ?> --EXPECTF-- -Warning: SplFixedArray::__construct() expects parameter 1 to be long, string given in %s on line %d -Index invalid or out of range -Index invalid or out of range -Index invalid or out of range -int(0) -bool(true) +Ok - SplFixedArray::__construct() expects parameter 1 to be integer, string given Done diff --git a/ext/spl/tests/heap_corruption.phpt b/ext/spl/tests/heap_corruption.phpt index 284ee1db81..5e9dec7855 100644 --- a/ext/spl/tests/heap_corruption.phpt +++ b/ext/spl/tests/heap_corruption.phpt @@ -42,6 +42,8 @@ $heap->insert(4); $heap->allow_compare = false; +var_dump($heap->isCorrupted()); + try { $heap->extract(); } @@ -56,7 +58,13 @@ catch (Exception $e) { echo "Corruption Exception: " . $e->getMessage() . PHP_EOL; } +var_dump($heap->isCorrupted()); +$heap->recoverFromCorruption(); +var_dump($heap->isCorrupted()); ?> --EXPECT-- +bool(false) Compare Exception: Compare exception -Corruption Exception: Heap is corrupted, heap properties are no longer ensured.
\ No newline at end of file +Corruption Exception: Heap is corrupted, heap properties are no longer ensured. +bool(true) +bool(false)
\ No newline at end of file diff --git a/ext/spl/tests/iterator_035.phpt b/ext/spl/tests/iterator_035.phpt index fc0271e381..307337431a 100644 --- a/ext/spl/tests/iterator_035.phpt +++ b/ext/spl/tests/iterator_035.phpt @@ -14,4 +14,7 @@ echo "Done\n"; --EXPECTF-- Notice: Indirect modification of overloaded element of ArrayIterator has no effect in %s on line %d -Fatal error: Cannot assign by reference to overloaded object in %s on line %d +Fatal error: Uncaught Error: Cannot assign by reference to overloaded object in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/ext/spl/tests/iterator_036.phpt b/ext/spl/tests/iterator_036.phpt index 9a9e66b3b3..0f668db53f 100644 --- a/ext/spl/tests/iterator_036.phpt +++ b/ext/spl/tests/iterator_036.phpt @@ -19,4 +19,4 @@ test(new CachingIterator($ar, 0)); ===DONE=== --EXPECTF-- -Fatal error: Method CachingIterator::__toString() must not throw an exception in %siterator_036.php on line %d +Fatal error: Method CachingIterator::__toString() must not throw an exception, caught BadMethodCallException: CachingIterator does not fetch string value (see CachingIterator::__construct) in %siterator_036.php on line %d diff --git a/ext/spl/tests/iterator_042.phpt b/ext/spl/tests/iterator_042.phpt index 95fea2f6b8..a344d60e33 100644 --- a/ext/spl/tests/iterator_042.phpt +++ b/ext/spl/tests/iterator_042.phpt @@ -3,7 +3,7 @@ SPL: AppendIterator and its ArrayIterator --FILE-- <?php -function test_error_handler($errno, $msg, $filename, $linenum, $vars) +function test_error_handler($errno, $msg, $filename, $linenum) { echo "Error $msg in $filename on line $linenum\n"; return true; @@ -13,7 +13,11 @@ set_error_handler('test_error_handler'); $it = new AppendIterator; -$it->append(array()); +try { + $it->append(array()); +} catch (Error $e) { + test_error_handler($e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine()); +} $it->append(new ArrayIterator(array(1))); $it->append(new ArrayIterator(array(21, 22))); @@ -83,7 +87,7 @@ object(ArrayIterator)#%d (1) { } } [2]=> - object(ArrayIterator)#5 (1) { + object(ArrayIterator)#%d (1) { %s"storage"%s"ArrayIterator":private]=> array(3) { [0]=> diff --git a/ext/spl/tests/iterator_056.phpt b/ext/spl/tests/iterator_056.phpt index 4b0e75a7d4..b5213732c3 100644 --- a/ext/spl/tests/iterator_056.phpt +++ b/ext/spl/tests/iterator_056.phpt @@ -1,19 +1,64 @@ --TEST-- -SPL: FilterIterator::__construct(void) +SPL: Calling __construct(void) on class extending SPL iterator --CREDITS-- Sebastian Schürmann --FILE-- <?php + class myFilterIterator extends FilterIterator { - function accept() { - - } + function accept() { } } + +class myCachingIterator extends CachingIterator { } + +class myRecursiveCachingIterator extends RecursiveCachingIterator { } + +class myParentIterator extends ParentIterator { } + +class myLimitIterator extends LimitIterator { } + +class myNoRewindIterator extends NoRewindIterator {} + try { $it = new myFilterIterator(); -} catch (InvalidArgumentException $e) { - echo 'InvalidArgumentException thrown'; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; } + +try { + $it = new myCachingIterator(); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +try { + $it = new myRecursiveCachingIterator(); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +try { + $it = new myParentIterator(); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +try { + $it = new myLimitIterator(); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +try { + $it = new myNoRewindIterator(); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + ?> --EXPECT-- -InvalidArgumentException thrown +FilterIterator::__construct() expects exactly 1 parameter, 0 given +CachingIterator::__construct() expects at least 1 parameter, 0 given +RecursiveCachingIterator::__construct() expects at least 1 parameter, 0 given +ParentIterator::__construct() expects exactly 1 parameter, 0 given +LimitIterator::__construct() expects at least 1 parameter, 0 given +NoRewindIterator::__construct() expects exactly 1 parameter, 0 given diff --git a/ext/spl/tests/iterator_059.phpt b/ext/spl/tests/iterator_059.phpt deleted file mode 100644 index 8c579ae43a..0000000000 --- a/ext/spl/tests/iterator_059.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -SPL: CachingIterator::__construct(void) ---CREDITS-- -Sebastian Schürmann ---FILE-- -<?php -class myCachingIterator extends CachingIterator { - -} -try { - $it = new myCachingIterator(); -} catch (InvalidArgumentException $e) { - echo 'InvalidArgumentException thrown'; -} -?> ---EXPECT-- -InvalidArgumentException thrown diff --git a/ext/spl/tests/iterator_060.phpt b/ext/spl/tests/iterator_060.phpt deleted file mode 100644 index 0c3b6c21d2..0000000000 --- a/ext/spl/tests/iterator_060.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -SPL: RecursiveCachingIterator::__construct(void) ---CREDITS-- -Sebastian Schürmann ---FILE-- -<?php -class myRecursiveCachingIterator extends RecursiveCachingIterator { - -} -try { - $it = new myRecursiveCachingIterator(); -} catch (InvalidArgumentException $e) { - echo 'InvalidArgumentException thrown'; -} -?> ---EXPECT-- -InvalidArgumentException thrown diff --git a/ext/spl/tests/iterator_061.phpt b/ext/spl/tests/iterator_061.phpt deleted file mode 100644 index 472f8da196..0000000000 --- a/ext/spl/tests/iterator_061.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -SPL: ParentIterator::__construct(void) ---CREDITS-- -Sebastian Schürmann ---FILE-- -<?php -class myParentIterator extends ParentIterator { - -} -try { - $it = new myParentIterator(); -} catch (InvalidArgumentException $e) { - echo 'InvalidArgumentException thrown'; -} -?> ---EXPECT-- -InvalidArgumentException thrown diff --git a/ext/spl/tests/iterator_063.phpt b/ext/spl/tests/iterator_063.phpt deleted file mode 100644 index 4d4112bac5..0000000000 --- a/ext/spl/tests/iterator_063.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -SPL: LimitIterator::__construct(void) ---CREDITS-- -Sebastian Schürmann ---FILE-- -<?php -class myLimitIterator extends LimitIterator { - -} -try { - $it = new myLimitIterator(); -} catch (InvalidArgumentException $e) { - echo 'InvalidArgumentException thrown'; -} -?> ---EXPECT-- -InvalidArgumentException thrown diff --git a/ext/spl/tests/iterator_064.phpt b/ext/spl/tests/iterator_064.phpt deleted file mode 100644 index 6a62e6c9c5..0000000000 --- a/ext/spl/tests/iterator_064.phpt +++ /dev/null @@ -1,15 +0,0 @@ ---TEST-- -SPL: CachingIterator::__construct(void) ---CREDITS-- -Sebastian Schürmann ---FILE-- -<?php -class myCachingIterator extends CachingIterator {} -try { - $it = new myCachingIterator(); -} catch (InvalidArgumentException $e) { - echo 'InvalidArgumentException thrown'; -} -?> ---EXPECT-- -InvalidArgumentException thrown diff --git a/ext/spl/tests/iterator_065.phpt b/ext/spl/tests/iterator_065.phpt deleted file mode 100644 index 9ea2974cd4..0000000000 --- a/ext/spl/tests/iterator_065.phpt +++ /dev/null @@ -1,15 +0,0 @@ ---TEST-- -SPL: RecursiveCachingIterator::__construct(void) ---CREDITS-- -Sebastian Schürmann ---FILE-- -<?php -class myRecursiveCachingIterator extends RecursiveCachingIterator {} -try { - $it = new myRecursiveCachingIterator(); -} catch (InvalidArgumentException $e) { - echo 'InvalidArgumentException thrown'; -} -?> ---EXPECT-- -InvalidArgumentException thrown diff --git a/ext/spl/tests/iterator_066.phpt b/ext/spl/tests/iterator_066.phpt deleted file mode 100644 index 008c47ccc5..0000000000 --- a/ext/spl/tests/iterator_066.phpt +++ /dev/null @@ -1,15 +0,0 @@ ---TEST-- -SPL: NoRewindIterator::__construct(void) ---CREDITS-- -Sebastian Schürmann ---FILE-- -<?php -class myNoRewindIterator extends NoRewindIterator {} -try { - $it = new myNoRewindIterator(); -} catch (InvalidArgumentException $e) { - echo 'InvalidArgumentException thrown'; -} -?> ---EXPECT-- -InvalidArgumentException thrown diff --git a/ext/spl/tests/iterator_count.phpt b/ext/spl/tests/iterator_count.phpt index 9aa4e1197c..c0dad0f422 100644 --- a/ext/spl/tests/iterator_count.phpt +++ b/ext/spl/tests/iterator_count.phpt @@ -23,4 +23,8 @@ Warning: iterator_count() expects exactly 1 parameter, 0 given in %s Warning: iterator_count() expects exactly 1 parameter, 2 given in %s -Catchable fatal error: Argument 1 passed to iterator_count() must implement interface Traversable, %unicode_string_optional% given %s +Fatal error: Uncaught TypeError: Argument 1 passed to iterator_count() must implement interface Traversable, string given in %s:%d +Stack trace: +#0 %s(%d): iterator_count('1') +#1 {main} + thrown in %s on line %d diff --git a/ext/spl/tests/iterator_to_array.phpt b/ext/spl/tests/iterator_to_array.phpt index 958d370cca..f36b99db23 100644 --- a/ext/spl/tests/iterator_to_array.phpt +++ b/ext/spl/tests/iterator_to_array.phpt @@ -22,4 +22,8 @@ Warning: iterator_to_array() expects at least 1 parameter, 0 given in %s Warning: iterator_to_array() expects at most 2 parameters, 3 given in %s -Catchable fatal error: Argument 1 passed to iterator_to_array() must implement interface Traversable, %unicode_string_optional% given %s +Fatal error: Uncaught TypeError: Argument 1 passed to iterator_to_array() must implement interface Traversable, string given in %s:%d +Stack trace: +#0 %s(%d): iterator_to_array('test', 'test') +#1 {main} + thrown in %s on line %d diff --git a/ext/spl/tests/recursiveIteratorIterator_beginchildren_error.phpt b/ext/spl/tests/recursiveIteratorIterator_beginchildren_error.phpt index f5430725d4..c9e21b260e 100644 --- a/ext/spl/tests/recursiveIteratorIterator_beginchildren_error.phpt +++ b/ext/spl/tests/recursiveIteratorIterator_beginchildren_error.phpt @@ -28,7 +28,7 @@ var_dump($recItIt2->next()); --EXPECTF--
NULL
-Fatal error: Uncaught exception 'Exception' in %s
+Fatal error: Uncaught Exception in %s
Stack trace:
#0 [internal function]: MyRecursiveIteratorIterator->beginchildren()
#1 %s: RecursiveIteratorIterator->next()
diff --git a/ext/spl/tests/recursiveIteratorIterator_callHasChildren_error.phpt b/ext/spl/tests/recursiveIteratorIterator_callHasChildren_error.phpt index 88f03fbd81..cbf8136ab6 100644 --- a/ext/spl/tests/recursiveIteratorIterator_callHasChildren_error.phpt +++ b/ext/spl/tests/recursiveIteratorIterator_callHasChildren_error.phpt @@ -28,7 +28,7 @@ var_dump($recItIt2->next()); --EXPECTF--
NULL
-Fatal error: Uncaught exception 'Exception' in %s
+Fatal error: Uncaught Exception in %s
Stack trace:
#0 [internal function]: MyRecursiveIteratorIterator->callHasChildren()
#1 %s: RecursiveIteratorIterator->next()
diff --git a/ext/spl/tests/recursiveIteratorIterator_endchildren_error.phpt b/ext/spl/tests/recursiveIteratorIterator_endchildren_error.phpt index e25d3edc80..82d55cf0ce 100644 --- a/ext/spl/tests/recursiveIteratorIterator_endchildren_error.phpt +++ b/ext/spl/tests/recursiveIteratorIterator_endchildren_error.phpt @@ -34,7 +34,7 @@ foreach ($recItIt2 as $val) echo "$val\n"; 1
2
-Fatal error: Uncaught exception 'Exception' in %s
+Fatal error: Uncaught Exception in %s
Stack trace:
#0 [internal function]: MyRecursiveIteratorIterator->endchildren()
#1 %s: RecursiveIteratorIterator->next()
diff --git a/ext/spl/tests/recursiveIteratorIterator_nextelement_error.phpt b/ext/spl/tests/recursiveIteratorIterator_nextelement_error.phpt index 3a91ed5b27..bb020fdff0 100644 --- a/ext/spl/tests/recursiveIteratorIterator_nextelement_error.phpt +++ b/ext/spl/tests/recursiveIteratorIterator_nextelement_error.phpt @@ -28,7 +28,7 @@ var_dump($recItIt->next()); --EXPECTF--
NULL
-Fatal error: Uncaught exception 'Exception' in %s
+Fatal error: Uncaught Exception in %s
Stack trace:
#0 [internal function]: MyRecursiveIteratorIterator->nextelement()
#1 %s: RecursiveIteratorIterator->next()
diff --git a/ext/spl/tests/recursive_tree_iterator_003.phpt b/ext/spl/tests/recursive_tree_iterator_003.phpt index 83c8553942..721b67ac02 100644 --- a/ext/spl/tests/recursive_tree_iterator_003.phpt +++ b/ext/spl/tests/recursive_tree_iterator_003.phpt @@ -1,16 +1,14 @@ --TEST-- SPL: RecursiveTreeIterator(non-traversable) ---INI-- -error_reporting=E_ALL&~E_NOTICE --FILE-- <?php try { new RecursiveTreeIterator(new ArrayIterator(array())); -} catch (InvalidArgumentException $e) { - echo "InvalidArgumentException thrown\n"; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; } ?> ===DONE=== ---EXPECTF-- -InvalidArgumentException thrown +--EXPECT-- +RecursiveCachingIterator::__construct() expects parameter 1 to be RecursiveIterator, object given ===DONE=== diff --git a/ext/spl/tests/recursive_tree_iterator_setprefixpart.phpt b/ext/spl/tests/recursive_tree_iterator_setprefixpart.phpt index 81c853f307..32bc574433 100644 --- a/ext/spl/tests/recursive_tree_iterator_setprefixpart.phpt +++ b/ext/spl/tests/recursive_tree_iterator_setprefixpart.phpt @@ -26,7 +26,7 @@ $it->setPrefixPart(1, $a); // Should throw a warning as setPrefixPart expects ar --EXPECTF-- Warning: RecursiveTreeIterator::setPrefixPart() expects exactly 2 parameters, 1 given in %s on line %d -Warning: RecursiveTreeIterator::setPrefixPart() expects parameter 1 to be long, object given in %s on line %d +Warning: RecursiveTreeIterator::setPrefixPart() expects parameter 1 to be integer, object given in %s on line %d Warning: RecursiveTreeIterator::setPrefixPart() expects parameter 2 to be %binary_string_optional%, object given in %s on line %d ===DONE=== diff --git a/ext/spl/tests/regexIterator_setMode_error.phpt b/ext/spl/tests/regexIterator_setMode_error.phpt index 52af499d7e..7062959eb1 100644 --- a/ext/spl/tests/regexIterator_setMode_error.phpt +++ b/ext/spl/tests/regexIterator_setMode_error.phpt @@ -25,4 +25,4 @@ int(0) string(14) "Illegal mode 7" int(0) -Warning: RegexIterator::setMode() expects parameter 1 to be long, string given in %s on line %d +Warning: RegexIterator::setMode() expects parameter 1 to be integer, string given in %s on line %d diff --git a/ext/spl/tests/spl_004.phpt b/ext/spl/tests/spl_004.phpt index d56f48f896..ac44b9d684 100644 --- a/ext/spl/tests/spl_004.phpt +++ b/ext/spl/tests/spl_004.phpt @@ -42,7 +42,11 @@ $it = new RecursiveIteratorIterator($it); var_dump(iterator_apply($it, 'test')); echo "===ERRORS===\n"; -var_dump(iterator_apply($it, 'test', 1)); +try { + var_dump(iterator_apply($it, 'test', 1)); +} catch (Error $e) { + my_error_handler($e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine()); +} var_dump(iterator_apply($it, 'non_existing_function')); var_dump(iterator_apply($it, 'non_existing_function', NULL, 2)); @@ -75,8 +79,6 @@ int(6) int(4) ===ERRORS=== Error: Argument 3 passed to iterator_apply() must be of the type array, integer given -Error: iterator_apply() expects parameter 3 to be array, integer given -NULL Error: iterator_apply() expects parameter 2 to be a valid callback, function 'non_existing_function' not found or invalid function name NULL Error: iterator_apply() expects at most 3 parameters, 4 given diff --git a/ext/spl/tests/spl_autoload_012.phpt b/ext/spl/tests/spl_autoload_012.phpt index e07f0e4fe5..16389fa4fa 100644 --- a/ext/spl/tests/spl_autoload_012.phpt +++ b/ext/spl/tests/spl_autoload_012.phpt @@ -49,14 +49,14 @@ first autoload_first autoload_second -Fatal error: Uncaught exception 'Exception' with message 'first' in %sspl_autoload_012.php:%d +Fatal error: Uncaught Exception: first in %sspl_autoload_012.php:%d Stack trace: #0 [internal function]: autoload_first('ThisClassDoesNo...') #1 [internal function]: spl_autoload_call('ThisClassDoesNo...') #2 %sspl_autoload_012.php(%d): class_exists('ThisClassDoesNo...') #3 {main} -Next exception 'Exception' with message 'second' in %sspl_autoload_012.php:%d +Next Exception: second in %sspl_autoload_012.php:%d Stack trace: #0 [internal function]: autoload_second('ThisClassDoesNo...') #1 [internal function]: spl_autoload_call('ThisClassDoesNo...') diff --git a/ext/spl/tests/spl_fileinfo_getextension_leadingdot.phpt b/ext/spl/tests/spl_fileinfo_getextension_leadingdot.phpt new file mode 100644 index 0000000000..7b2be18900 --- /dev/null +++ b/ext/spl/tests/spl_fileinfo_getextension_leadingdot.phpt @@ -0,0 +1,13 @@ +--TEST-- +SPL: Spl File Info test getExtension with leading dot +--FILE-- +<?php +$file = __DIR__ . '/.test'; +touch($file); +$fileInfo = new SplFileInfo($file); + +var_dump($fileInfo->getExtension()); +unlink($file); +?> +--EXPECT-- +string(4) "test" diff --git a/ext/spl/tests/spl_heap_count_basic.phpt b/ext/spl/tests/spl_heap_count_basic.phpt index 6e6baf6c9b..a14133e873 100644 --- a/ext/spl/tests/spl_heap_count_basic.phpt +++ b/ext/spl/tests/spl_heap_count_basic.phpt @@ -27,7 +27,7 @@ count($heap);// refers to MyHeap->count() method ?> --EXPECTF-- -Fatal error: Uncaught exception 'Exception' with message 'Cause count to fail' in %s +Fatal error: Uncaught Exception: Cause count to fail in %s Stack trace: #0 [internal function]: MyHeap->count() #1 %s count(Object(MyHeap)) diff --git a/ext/spl/tests/spl_iterator_iterator_constructor.phpt b/ext/spl/tests/spl_iterator_iterator_constructor.phpt index d4fdb14c13..4c3fae25a2 100644 --- a/ext/spl/tests/spl_iterator_iterator_constructor.phpt +++ b/ext/spl/tests/spl_iterator_iterator_constructor.phpt @@ -6,23 +6,19 @@ TestFest London May 2009 --FILE-- <?php - //I think this is testing line 1297 of spl_iterators.c - - $array = array(array(7,8,9),1,2,3,array(4,5,6)); +$array = array(array(7,8,9),1,2,3,array(4,5,6)); $arrayIterator = new ArrayIterator($array); try { -$test = new IteratorIterator($arrayIterator); - -$test = new IteratorIterator($arrayIterator, 1); -$test = new IteratorIterator($arrayIterator, 1, 1); -$test = new IteratorIterator($arrayIterator, 1, 1, 1); -$test = new IteratorIterator($arrayIterator, 1, 1, 1, 1); + $test = new IteratorIterator($arrayIterator); -} catch (InvalidArgumentException $e){ - print $e->getMessage() . "\n"; + $test = new IteratorIterator($arrayIterator, 1); + $test = new IteratorIterator($arrayIterator, 1, 1); + $test = new IteratorIterator($arrayIterator, 1, 1, 1); + $test = new IteratorIterator($arrayIterator, 1, 1, 1, 1); +} catch (TypeError $e){ + echo $e->getMessage() . "\n"; } - ?> ===DONE=== --EXPECTF-- diff --git a/ext/spl/tests/spl_iterator_recursive_getiterator_error.phpt b/ext/spl/tests/spl_iterator_recursive_getiterator_error.phpt index 0d45c31513..debc85e622 100644 --- a/ext/spl/tests/spl_iterator_recursive_getiterator_error.phpt +++ b/ext/spl/tests/spl_iterator_recursive_getiterator_error.phpt @@ -13,4 +13,8 @@ function p ($i) { } ?> --EXPECTF-- -Fatal error: An iterator cannot be used with foreach by reference in %s
\ No newline at end of file +Fatal error: Uncaught Error: An iterator cannot be used with foreach by reference in %s:%d +Stack trace: +#0 %s(%d): p(Object(IteratorIterator)) +#1 {main} + thrown in %s on line %d diff --git a/ext/spl/tests/spl_pq_top_basic.phpt b/ext/spl/tests/spl_pq_top_basic.phpt index dcc1cbe4c0..14e0af51cb 100644 --- a/ext/spl/tests/spl_pq_top_basic.phpt +++ b/ext/spl/tests/spl_pq_top_basic.phpt @@ -8,6 +8,8 @@ Nathaniel McHugh nat@fishtrap.co.uk $priorityQueue = new SplPriorityQueue(); +var_dump($priorityQueue->getExtractFlags()); + $priorityQueue->insert("a", 1); $priorityQueue->insert("b", 2); $priorityQueue->insert("c", 0); @@ -16,6 +18,8 @@ echo "EXTR DEFAULT",PHP_EOL; echo "value: ",$priorityQueue->top(),PHP_EOL; $priorityQueue->setExtractFlags(SplPriorityQueue::EXTR_PRIORITY); +var_dump($priorityQueue->getExtractFlags() & SplPriorityQueue::EXTR_PRIORITY); + echo "EXTR_PRIORITY",PHP_EOL; echo "priority: ",$priorityQueue->top(),PHP_EOL; @@ -28,8 +32,10 @@ $priorityQueue->setExtractFlags(SplPriorityQueue::EXTR_DATA); echo "value: ",$priorityQueue->top(),PHP_EOL; ?> --EXPECT-- +int(1) EXTR DEFAULT value: b +int(2) EXTR_PRIORITY priority: 2 EXTR_BOTH |