summaryrefslogtreecommitdiff
path: root/ext/standard/array.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/standard/array.c')
-rw-r--r--ext/standard/array.c1329
1 files changed, 1032 insertions, 297 deletions
diff --git a/ext/standard/array.c b/ext/standard/array.c
index 07db375440..3a55333a76 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -790,6 +790,7 @@ PHP_FUNCTION(count)
switch (Z_TYPE_P(array)) {
case IS_NULL:
+ php_error_docref(NULL, E_WARNING, "Parameter must be an array or an object that implements Countable");
RETURN_LONG(0);
break;
case IS_ARRAY:
@@ -812,7 +813,7 @@ PHP_FUNCTION(count)
}
}
/* if not and the object implements Countable we call its count() method */
- if (instanceof_function(Z_OBJCE_P(array), spl_ce_Countable)) {
+ if (instanceof_function(Z_OBJCE_P(array), zend_ce_countable)) {
zend_call_method_with_0_params(array, NULL, NULL, "count", &retval);
if (Z_TYPE(retval) != IS_UNDEF) {
RETVAL_LONG(zval_get_long(&retval));
@@ -820,8 +821,14 @@ PHP_FUNCTION(count)
}
return;
}
+
+ /* If There's no handler and it doesn't implement Countable then add a warning */
+ php_error_docref(NULL, E_WARNING, "Parameter must be an array or an object that implements Countable");
+ RETURN_LONG(1);
+ break;
}
default:
+ php_error_docref(NULL, E_WARNING, "Parameter must be an array or an object that implements Countable");
RETURN_LONG(1);
break;
}
@@ -832,9 +839,9 @@ static void php_natsort(INTERNAL_FUNCTION_PARAMETERS, int fold_case) /* {{{ */
{
zval *array;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/", &array) == FAILURE) {
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY_EX(array, 0, 1)
+ ZEND_PARSE_PARAMETERS_END();
if (fold_case) {
if (zend_hash_sort(Z_ARRVAL_P(array), php_array_natural_case_compare, 0) == FAILURE) {
@@ -874,9 +881,11 @@ PHP_FUNCTION(asort)
zend_long sort_type = PHP_SORT_REGULAR;
compare_func_t cmp;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|l", &array, &sort_type) == FAILURE) {
- RETURN_FALSE;
- }
+ ZEND_PARSE_PARAMETERS_START(1, 2)
+ Z_PARAM_ARRAY_EX(array, 0, 1)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_LONG(sort_type)
+ ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
cmp = php_get_data_compare_func(sort_type, 0);
@@ -895,9 +904,11 @@ PHP_FUNCTION(arsort)
zend_long sort_type = PHP_SORT_REGULAR;
compare_func_t cmp;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|l", &array, &sort_type) == FAILURE) {
- RETURN_FALSE;
- }
+ ZEND_PARSE_PARAMETERS_START(1, 2)
+ Z_PARAM_ARRAY_EX(array, 0, 1)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_LONG(sort_type)
+ ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
cmp = php_get_data_compare_func(sort_type, 1);
@@ -916,9 +927,11 @@ PHP_FUNCTION(sort)
zend_long sort_type = PHP_SORT_REGULAR;
compare_func_t cmp;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|l", &array, &sort_type) == FAILURE) {
- RETURN_FALSE;
- }
+ ZEND_PARSE_PARAMETERS_START(1, 2)
+ Z_PARAM_ARRAY_EX(array, 0, 1)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_LONG(sort_type)
+ ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
cmp = php_get_data_compare_func(sort_type, 0);
@@ -937,9 +950,11 @@ PHP_FUNCTION(rsort)
zend_long sort_type = PHP_SORT_REGULAR;
compare_func_t cmp;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|l", &array, &sort_type) == FAILURE) {
- RETURN_FALSE;
- }
+ ZEND_PARSE_PARAMETERS_START(1, 2)
+ Z_PARAM_ARRAY_EX(array, 0, 1)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_LONG(sort_type)
+ ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
cmp = php_get_data_compare_func(sort_type, 1);
@@ -1019,10 +1034,10 @@ static void php_usort(INTERNAL_FUNCTION_PARAMETERS, compare_func_t compare_func,
PHP_ARRAY_CMP_FUNC_BACKUP();
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "af", &array, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) {
- PHP_ARRAY_CMP_FUNC_RESTORE();
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(2, 2)
+ Z_PARAM_ARRAY_EX2(array, 0, 1, 0)
+ Z_PARAM_FUNC(BG(user_compare_fci), BG(user_compare_fci_cache))
+ ZEND_PARSE_PARAMETERS_END_EX( PHP_ARRAY_CMP_FUNC_RESTORE(); return );
arr = Z_ARR_P(array);
if (zend_hash_num_elements(arr) == 0) {
@@ -1267,9 +1282,9 @@ PHP_FUNCTION(min)
int argc;
zval *args = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(1, -1)
+ Z_PARAM_VARIADIC('+', args, argc)
+ ZEND_PARSE_PARAMETERS_END();
/* mixed min ( array $values ) */
if (argc == 1) {
@@ -1301,7 +1316,6 @@ PHP_FUNCTION(min)
}
}
- ZVAL_DEREF(min);
ZVAL_COPY(return_value, min);
}
}
@@ -1314,9 +1328,9 @@ PHP_FUNCTION(max)
zval *args = NULL;
int argc;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(1, -1)
+ Z_PARAM_VARIADIC('+', args, argc)
+ ZEND_PARSE_PARAMETERS_END();
/* mixed max ( array $values ) */
if (argc == 1) {
@@ -1348,7 +1362,6 @@ PHP_FUNCTION(max)
}
}
- ZVAL_DEREF(max);
ZVAL_COPY(return_value, max);
}
}
@@ -1500,7 +1513,7 @@ PHP_FUNCTION(array_walk)
Z_PARAM_ARRAY_OR_OBJECT_EX(array, 0, 1)
Z_PARAM_FUNC(BG(array_walk_fci), BG(array_walk_fci_cache))
Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL_EX(userdata, 0, 1)
+ Z_PARAM_ZVAL(userdata)
ZEND_PARSE_PARAMETERS_END_EX(
BG(array_walk_fci) = orig_array_walk_fci;
BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
@@ -1526,11 +1539,16 @@ PHP_FUNCTION(array_walk_recursive)
orig_array_walk_fci = BG(array_walk_fci);
orig_array_walk_fci_cache = BG(array_walk_fci_cache);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "A/f|z/", &array, &BG(array_walk_fci), &BG(array_walk_fci_cache), &userdata) == FAILURE) {
+ ZEND_PARSE_PARAMETERS_START(2, 3)
+ Z_PARAM_ARRAY_OR_OBJECT_EX(array, 0, 1)
+ Z_PARAM_FUNC(BG(array_walk_fci), BG(array_walk_fci_cache))
+ Z_PARAM_OPTIONAL
+ Z_PARAM_ZVAL(userdata)
+ ZEND_PARSE_PARAMETERS_END_EX(
BG(array_walk_fci) = orig_array_walk_fci;
BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
- return;
- }
+ return
+ );
php_array_walk(array, userdata, 1);
BG(array_walk_fci) = orig_array_walk_fci;
@@ -1716,148 +1734,464 @@ PHPAPI int php_prefix_varname(zval *result, zval *prefix, char *var_name, size_t
}
/* }}} */
-/* {{{ proto int extract(array var_array [, int extract_type [, string prefix]])
- Imports variables into symbol table from an array */
-PHP_FUNCTION(extract)
+static zend_long php_extract_ref_if_exists(zend_array *arr, zend_array *symbol_table) /* {{{ */
{
- zval *var_array_param, *prefix = NULL;
- zend_long extract_type = EXTR_OVERWRITE;
- zval *entry;
- zend_string *var_name;
- zend_ulong num_key;
- int var_exists, count = 0;
- int extract_refs = 0;
int exception_thrown = 0;
- zend_array *symbol_table;
- zval var_array;
-
- ZEND_PARSE_PARAMETERS_START(1, 3)
- Z_PARAM_ARRAY(var_array_param)
- Z_PARAM_OPTIONAL
- Z_PARAM_LONG(extract_type)
- Z_PARAM_ZVAL_EX(prefix, 0, 1)
- ZEND_PARSE_PARAMETERS_END();
+ zend_long count = 0;
+ zend_string *var_name;
+ zval *entry, *orig_var;
- extract_refs = (extract_type & EXTR_REFS);
- if (extract_refs) {
- SEPARATE_ZVAL(var_array_param);
- }
- extract_type &= 0xff;
+ ZEND_HASH_FOREACH_STR_KEY_VAL_IND(arr, var_name, entry) {
+ if (!var_name) {
+ continue;
+ }
+ orig_var = zend_hash_find(symbol_table, var_name);
+ if (orig_var) {
+ if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
+ orig_var = Z_INDIRECT_P(orig_var);
+ if (Z_TYPE_P(orig_var) == IS_UNDEF) {
+ continue;
+ }
+ }
+ if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) {
+ continue;
+ }
+ if (ZSTR_LEN(var_name) == sizeof("GLOBALS")-1 && !strcmp(ZSTR_VAL(var_name), "GLOBALS")) {
+ continue;
+ }
+ if (ZSTR_LEN(var_name) == sizeof("this")-1 && !strcmp(ZSTR_VAL(var_name), "this")) {
+ if (!exception_thrown) {
+ exception_thrown = 1;
+ zend_throw_error(NULL, "Cannot re-assign $this");
+ }
+ continue;
+ }
+ ZVAL_MAKE_REF(entry);
+ Z_ADDREF_P(entry);
+ zval_ptr_dtor(orig_var);
+ ZVAL_COPY_VALUE(orig_var, entry);
+ count++;
+ }
+ } ZEND_HASH_FOREACH_END();
- if (extract_type < EXTR_OVERWRITE || extract_type > EXTR_IF_EXISTS) {
- php_error_docref(NULL, E_WARNING, "Invalid extract type");
- return;
- }
+ return count;
+}
+/* }}} */
- if (extract_type > EXTR_SKIP && extract_type <= EXTR_PREFIX_IF_EXISTS && ZEND_NUM_ARGS() < 3) {
- php_error_docref(NULL, E_WARNING, "specified extract type requires the prefix parameter");
- return;
- }
+static zend_long php_extract_if_exists(zend_array *arr, zend_array *symbol_table) /* {{{ */
+{
+ int exception_thrown = 0;
+ zend_long count = 0;
+ zend_string *var_name;
+ zval *entry, *orig_var;
- if (prefix) {
- convert_to_string(prefix);
- if (Z_STRLEN_P(prefix) && !php_valid_var_name(Z_STRVAL_P(prefix), Z_STRLEN_P(prefix))) {
- php_error_docref(NULL, E_WARNING, "prefix is not a valid identifier");
- return;
+ ZEND_HASH_FOREACH_STR_KEY_VAL_IND(arr, var_name, entry) {
+ if (!var_name) {
+ continue;
}
- }
+ orig_var = zend_hash_find(symbol_table, var_name);
+ if (orig_var) {
+ if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
+ orig_var = Z_INDIRECT_P(orig_var);
+ if (Z_TYPE_P(orig_var) == IS_UNDEF) {
+ continue;
+ }
+ }
+ if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) {
+ continue;
+ }
+ if (ZSTR_LEN(var_name) == sizeof("GLOBALS")-1 && !strcmp(ZSTR_VAL(var_name), "GLOBALS")) {
+ continue;
+ }
+ if (ZSTR_LEN(var_name) == sizeof("this")-1 && !strcmp(ZSTR_VAL(var_name), "this")) {
+ if (!exception_thrown) {
+ exception_thrown = 1;
+ zend_throw_error(NULL, "Cannot re-assign $this");
+ }
+ continue;
+ }
+ ZVAL_DEREF(entry);
+ if (Z_REFCOUNTED_P(entry)) Z_ADDREF_P(entry);
+ ZVAL_DEREF(orig_var);
+ zval_ptr_dtor(orig_var);
+ ZVAL_COPY_VALUE(orig_var, entry);
+ count++;
+ }
+ } ZEND_HASH_FOREACH_END();
- if (zend_forbid_dynamic_call("extract()") == FAILURE) {
- return;
- }
+ return count;
+}
+/* }}} */
- symbol_table = zend_rebuild_symbol_table();
-#if 0
- if (!symbol_table) {
- php_error_docref(NULL, E_WARNING, "failed to build symbol table");
- return;
- }
-#endif
+static zend_long php_extract_ref_overwrite(zend_array *arr, zend_array *symbol_table) /* {{{ */
+{
+ int exception_thrown = 0;
+ zend_long count = 0;
+ zend_string *var_name;
+ zval *entry, *orig_var;
- /* The array might be stored in a local variable that will be overwritten. To avoid losing the
- * reference in that case we work on a copy. */
- ZVAL_COPY(&var_array, var_array_param);
+ ZEND_HASH_FOREACH_STR_KEY_VAL_IND(arr, var_name, entry) {
+ if (!var_name) {
+ continue;
+ }
+ if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) {
+ continue;
+ }
+ if (ZSTR_LEN(var_name) == sizeof("this")-1 && !strcmp(ZSTR_VAL(var_name), "this")) {
+ if (!exception_thrown) {
+ exception_thrown = 1;
+ zend_throw_error(NULL, "Cannot re-assign $this");
+ }
+ continue;
+ }
+ orig_var = zend_hash_find(symbol_table, var_name);
+ if (orig_var) {
+ if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
+ orig_var = Z_INDIRECT_P(orig_var);
+ }
+ if (ZSTR_LEN(var_name) == sizeof("GLOBALS")-1 && !strcmp(ZSTR_VAL(var_name), "GLOBALS")) {
+ continue;
+ }
+ ZVAL_MAKE_REF(entry);
+ Z_ADDREF_P(entry);
+ zval_ptr_dtor(orig_var);
+ ZVAL_COPY_VALUE(orig_var, entry);
+ } else {
+ ZVAL_MAKE_REF(entry);
+ Z_ADDREF_P(entry);
+ zend_hash_add_new(symbol_table, var_name, entry);
+ }
+ count++;
+ } ZEND_HASH_FOREACH_END();
- ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL(var_array), num_key, var_name, entry) {
- zval final_name;
+ return count;
+}
+/* }}} */
- ZVAL_NULL(&final_name);
- var_exists = 0;
+static zend_long php_extract_overwrite(zend_array *arr, zend_array *symbol_table) /* {{{ */
+{
+ int exception_thrown = 0;
+ zend_long count = 0;
+ zend_string *var_name;
+ zval *entry, *orig_var;
- if (var_name) {
- var_exists = zend_hash_exists_ind(symbol_table, var_name);
- } else if (extract_type == EXTR_PREFIX_ALL || extract_type == EXTR_PREFIX_INVALID) {
- zend_string *str = zend_long_to_str(num_key);
- php_prefix_varname(&final_name, prefix, ZSTR_VAL(str), ZSTR_LEN(str), 1);
- zend_string_release(str);
- } else {
+ ZEND_HASH_FOREACH_STR_KEY_VAL_IND(arr, var_name, entry) {
+ if (!var_name) {
continue;
}
+ if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) {
+ continue;
+ }
+ if (ZSTR_LEN(var_name) == sizeof("this")-1 && !strcmp(ZSTR_VAL(var_name), "this")) {
+ if (!exception_thrown) {
+ exception_thrown = 1;
+ zend_throw_error(NULL, "Cannot re-assign $this");
+ }
+ continue;
+ }
+ orig_var = zend_hash_find(symbol_table, var_name);
+ if (orig_var) {
+ if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
+ orig_var = Z_INDIRECT_P(orig_var);
+ }
+ if (ZSTR_LEN(var_name) == sizeof("GLOBALS")-1 && !strcmp(ZSTR_VAL(var_name), "GLOBALS")) {
+ continue;
+ }
+ ZVAL_DEREF(entry);
+ if (Z_REFCOUNTED_P(entry)) Z_ADDREF_P(entry);
+ ZVAL_DEREF(orig_var);
+ zval_ptr_dtor(orig_var);
+ ZVAL_COPY_VALUE(orig_var, entry);
+ } else {
+ ZVAL_DEREF(entry);
+ if (Z_REFCOUNTED_P(entry)) Z_ADDREF_P(entry);
+ zend_hash_add_new(symbol_table, var_name, entry);
+ }
+ count++;
+ } ZEND_HASH_FOREACH_END();
- switch (extract_type) {
- case EXTR_IF_EXISTS:
- if (!var_exists) break;
- /* break omitted intentionally */
+ return count;
+}
+/* }}} */
- case EXTR_OVERWRITE:
- /* GLOBALS protection */
- if (var_exists && ZSTR_LEN(var_name) == sizeof("GLOBALS")-1 && !strcmp(ZSTR_VAL(var_name), "GLOBALS")) {
- break;
- }
- ZVAL_STR_COPY(&final_name, var_name);
- break;
+static zend_long php_extract_ref_prefix_if_exists(zend_array *arr, zend_array *symbol_table, zval *prefix) /* {{{ */
+{
+ int exception_thrown = 0;
+ zend_long count = 0;
+ zend_string *var_name;
+ zval *entry, *orig_var, final_name;
- case EXTR_PREFIX_IF_EXISTS:
- if (var_exists) {
- php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1);
+ ZEND_HASH_FOREACH_STR_KEY_VAL_IND(arr, var_name, entry) {
+ if (!var_name) {
+ continue;
+ }
+ orig_var = zend_hash_find(symbol_table, var_name);
+ if (orig_var) {
+ if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
+ orig_var = Z_INDIRECT_P(orig_var);
+ if (Z_TYPE_P(orig_var) == IS_UNDEF) {
+ ZVAL_MAKE_REF(entry);
+ Z_ADDREF_P(entry);
+ ZVAL_COPY_VALUE(orig_var, entry);
+ count++;
+ continue;
}
- break;
-
- case EXTR_PREFIX_SAME:
- if (!var_exists && ZSTR_LEN(var_name) != 0) {
- ZVAL_STR_COPY(&final_name, var_name);
+ }
+ php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1);
+ if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
+ if (Z_STRLEN(final_name) == sizeof("this")-1 && !strcmp(Z_STRVAL(final_name), "this")) {
+ if (!exception_thrown) {
+ exception_thrown = 1;
+ zend_throw_error(NULL, "Cannot re-assign $this");
+ }
+ } else {
+ ZVAL_MAKE_REF(entry);
+ Z_ADDREF_P(entry);
+ if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) {
+ if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
+ orig_var = Z_INDIRECT_P(orig_var);
+ }
+ zval_ptr_dtor(orig_var);
+ ZVAL_COPY_VALUE(orig_var, entry);
+ } else {
+ zend_hash_add_new(symbol_table, Z_STR(final_name), entry);
+ }
+ count++;
}
- /* break omitted intentionally */
+ }
+ zend_string_release(Z_STR(final_name));
+ }
+ } ZEND_HASH_FOREACH_END();
- case EXTR_PREFIX_ALL:
- if (Z_TYPE(final_name) == IS_NULL && ZSTR_LEN(var_name) != 0) {
- php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1);
- }
- break;
+ return count;
+}
+/* }}} */
- case EXTR_PREFIX_INVALID:
- if (Z_TYPE(final_name) == IS_NULL) {
- if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) {
- php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1);
+static zend_long php_extract_prefix_if_exists(zend_array *arr, zend_array *symbol_table, zval *prefix) /* {{{ */
+{
+ int exception_thrown = 0;
+ zend_long count = 0;
+ zend_string *var_name;
+ zval *entry, *orig_var, final_name;
+
+ ZEND_HASH_FOREACH_STR_KEY_VAL_IND(arr, var_name, entry) {
+ if (!var_name) {
+ continue;
+ }
+ orig_var = zend_hash_find(symbol_table, var_name);
+ if (orig_var) {
+ if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
+ orig_var = Z_INDIRECT_P(orig_var);
+ if (Z_TYPE_P(orig_var) == IS_UNDEF) {
+ ZVAL_DEREF(entry);
+ if (Z_REFCOUNTED_P(entry)) Z_ADDREF_P(entry);
+ ZVAL_COPY_VALUE(orig_var, entry);
+ count++;
+ continue;
+ }
+ }
+ php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1);
+ if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
+ if (Z_STRLEN(final_name) == sizeof("this")-1 && !strcmp(Z_STRVAL(final_name), "this")) {
+ if (!exception_thrown) {
+ exception_thrown = 1;
+ zend_throw_error(NULL, "Cannot re-assign $this");
+ }
+ } else {
+ ZVAL_DEREF(entry);
+ if (Z_REFCOUNTED_P(entry)) Z_ADDREF_P(entry);
+ if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) {
+ if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
+ orig_var = Z_INDIRECT_P(orig_var);
+ }
+ ZVAL_DEREF(orig_var);
+ zval_ptr_dtor(orig_var);
+ ZVAL_COPY_VALUE(orig_var, entry);
} else {
- ZVAL_STR_COPY(&final_name, var_name);
+ zend_hash_add_new(symbol_table, Z_STR(final_name), entry);
}
+ count++;
}
- break;
+ }
+ zend_string_release(Z_STR(final_name));
+ }
+ } ZEND_HASH_FOREACH_END();
- default:
- if (!var_exists) {
- ZVAL_STR_COPY(&final_name, var_name);
+ return count;
+}
+/* }}} */
+
+static zend_long php_extract_ref_prefix_same(zend_array *arr, zend_array *symbol_table, zval *prefix) /* {{{ */
+{
+ int exception_thrown = 0;
+ zend_long count = 0;
+ zend_string *var_name;
+ zval *entry, *orig_var, final_name;
+
+ ZEND_HASH_FOREACH_STR_KEY_VAL_IND(arr, var_name, entry) {
+ if (!var_name) {
+ continue;
+ }
+ if (ZSTR_LEN(var_name) == 0) {
+ continue;
+ }
+ orig_var = zend_hash_find(symbol_table, var_name);
+ if (orig_var) {
+ if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
+ orig_var = Z_INDIRECT_P(orig_var);
+ if (Z_TYPE_P(orig_var) == IS_UNDEF) {
+ ZVAL_MAKE_REF(entry);
+ Z_ADDREF_P(entry);
+ ZVAL_COPY_VALUE(orig_var, entry);
+ count++;
+ continue;
}
- break;
+ }
+ php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1);
+ if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
+ if (Z_STRLEN(final_name) == sizeof("this")-1 && !strcmp(Z_STRVAL(final_name), "this")) {
+ if (!exception_thrown) {
+ exception_thrown = 1;
+ zend_throw_error(NULL, "Cannot re-assign $this");
+ }
+ } else {
+ ZVAL_MAKE_REF(entry);
+ Z_ADDREF_P(entry);
+ if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) {
+ if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
+ orig_var = Z_INDIRECT_P(orig_var);
+ }
+ zval_ptr_dtor(orig_var);
+ ZVAL_COPY_VALUE(orig_var, entry);
+ } else {
+ zend_hash_add_new(symbol_table, Z_STR(final_name), entry);
+ }
+ count++;
+ }
+ }
+ zend_string_release(Z_STR(final_name));
+ } else {
+ if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) {
+ continue;
+ }
+ if (ZSTR_LEN(var_name) == sizeof("this")-1 && !strcmp(ZSTR_VAL(var_name), "this")) {
+ if (!exception_thrown) {
+ exception_thrown = 1;
+ zend_throw_error(NULL, "Cannot re-assign $this");
+ }
+ continue;
+ }
+ ZVAL_MAKE_REF(entry);
+ Z_ADDREF_P(entry);
+ zend_hash_add_new(symbol_table, var_name, entry);
+ count++;
}
+ } ZEND_HASH_FOREACH_END();
- if (Z_TYPE(final_name) == IS_STRING && php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
- zval *orig_var;
+ return count;
+}
+/* }}} */
- if (Z_STRLEN(final_name) == sizeof("this")-1 && !strcmp(Z_STRVAL(final_name), "this")) {
+static zend_long php_extract_prefix_same(zend_array *arr, zend_array *symbol_table, zval *prefix) /* {{{ */
+{
+ int exception_thrown = 0;
+ zend_long count = 0;
+ zend_string *var_name;
+ zval *entry, *orig_var, final_name;
+
+ ZEND_HASH_FOREACH_STR_KEY_VAL_IND(arr, var_name, entry) {
+ if (!var_name) {
+ continue;
+ }
+ if (ZSTR_LEN(var_name) == 0) {
+ continue;
+ }
+ orig_var = zend_hash_find(symbol_table, var_name);
+ if (orig_var) {
+ if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
+ orig_var = Z_INDIRECT_P(orig_var);
+ if (Z_TYPE_P(orig_var) == IS_UNDEF) {
+ ZVAL_DEREF(entry);
+ if (Z_REFCOUNTED_P(entry)) Z_ADDREF_P(entry);
+ ZVAL_COPY_VALUE(orig_var, entry);
+ count++;
+ continue;
+ }
+ }
+ php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1);
+ if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
+ if (Z_STRLEN(final_name) == sizeof("this")-1 && !strcmp(Z_STRVAL(final_name), "this")) {
+ if (!exception_thrown) {
+ exception_thrown = 1;
+ zend_throw_error(NULL, "Cannot re-assign $this");
+ }
+ } else {
+ ZVAL_DEREF(entry);
+ if (Z_REFCOUNTED_P(entry)) Z_ADDREF_P(entry);
+ if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) {
+ if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
+ orig_var = Z_INDIRECT_P(orig_var);
+ }
+ ZVAL_DEREF(orig_var);
+ zval_ptr_dtor(orig_var);
+ ZVAL_COPY_VALUE(orig_var, entry);
+ } else {
+ zend_hash_add_new(symbol_table, Z_STR(final_name), entry);
+ }
+ count++;
+ }
+ }
+ zend_string_release(Z_STR(final_name));
+ } else {
+ if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) {
+ continue;
+ }
+ if (ZSTR_LEN(var_name) == sizeof("this")-1 && !strcmp(ZSTR_VAL(var_name), "this")) {
if (!exception_thrown) {
exception_thrown = 1;
zend_throw_error(NULL, "Cannot re-assign $this");
}
- zval_dtor(&final_name);
continue;
}
- if (extract_refs) {
+ ZVAL_DEREF(entry);
+ if (Z_REFCOUNTED_P(entry)) Z_ADDREF_P(entry);
+ zend_hash_add_new(symbol_table, var_name, entry);
+ count++;
+ }
+ } ZEND_HASH_FOREACH_END();
+
+ return count;
+}
+/* }}} */
+static zend_long php_extract_ref_prefix_all(zend_array *arr, zend_array *symbol_table, zval *prefix) /* {{{ */
+{
+ int exception_thrown = 0;
+ zend_long count = 0;
+ zend_string *var_name;
+ zend_ulong num_key;
+ zval *entry, *orig_var, final_name;
+
+ ZEND_HASH_FOREACH_KEY_VAL_IND(arr, num_key, var_name, entry) {
+ if (var_name) {
+ if (ZSTR_LEN(var_name) == 0) {
+ continue;
+ }
+ php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1);
+ } else {
+ zend_string *str = zend_long_to_str(num_key);
+ php_prefix_varname(&final_name, prefix, ZSTR_VAL(str), ZSTR_LEN(str), 1);
+ zend_string_release(str);
+ }
+ if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
+ if (Z_STRLEN(final_name) == sizeof("this")-1 && !strcmp(Z_STRVAL(final_name), "this")) {
+ if (!exception_thrown) {
+ exception_thrown = 1;
+ zend_throw_error(NULL, "Cannot re-assign $this");
+ }
+ } else {
ZVAL_MAKE_REF(entry);
Z_ADDREF_P(entry);
-
if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) {
if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
orig_var = Z_INDIRECT_P(orig_var);
@@ -1865,7 +2199,42 @@ PHP_FUNCTION(extract)
zval_ptr_dtor(orig_var);
ZVAL_COPY_VALUE(orig_var, entry);
} else {
- zend_hash_update(symbol_table, Z_STR(final_name), entry);
+ zend_hash_add_new(symbol_table, Z_STR(final_name), entry);
+ }
+ count++;
+ }
+ }
+ zend_string_release(Z_STR(final_name));
+ } ZEND_HASH_FOREACH_END();
+
+ return count;
+}
+/* }}} */
+
+static zend_long php_extract_prefix_all(zend_array *arr, zend_array *symbol_table, zval *prefix) /* {{{ */
+{
+ int exception_thrown = 0;
+ zend_long count = 0;
+ zend_string *var_name;
+ zend_ulong num_key;
+ zval *entry, *orig_var, final_name;
+
+ ZEND_HASH_FOREACH_KEY_VAL_IND(arr, num_key, var_name, entry) {
+ if (var_name) {
+ if (ZSTR_LEN(var_name) == 0) {
+ continue;
+ }
+ php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1);
+ } else {
+ zend_string *str = zend_long_to_str(num_key);
+ php_prefix_varname(&final_name, prefix, ZSTR_VAL(str), ZSTR_LEN(str), 1);
+ zend_string_release(str);
+ }
+ if (php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
+ if (Z_STRLEN(final_name) == sizeof("this")-1 && !strcmp(Z_STRVAL(final_name), "this")) {
+ if (!exception_thrown) {
+ exception_thrown = 1;
+ zend_throw_error(NULL, "Cannot re-assign $this");
}
} else {
ZVAL_DEREF(entry);
@@ -1878,14 +2247,311 @@ PHP_FUNCTION(extract)
zval_ptr_dtor(orig_var);
ZVAL_COPY_VALUE(orig_var, entry);
} else {
- zend_hash_update(symbol_table, Z_STR(final_name), entry);
+ zend_hash_add_new(symbol_table, Z_STR(final_name), entry);
+ }
+ count++;
+ }
+ }
+ zend_string_release(Z_STR(final_name));
+ } ZEND_HASH_FOREACH_END();
+
+ return count;
+}
+/* }}} */
+
+static zend_long php_extract_ref_prefix_invalid(zend_array *arr, zend_array *symbol_table, zval *prefix) /* {{{ */
+{
+ int exception_thrown = 0;
+ zend_long count = 0;
+ zend_string *var_name;
+ zend_ulong num_key;
+ zval *entry, *orig_var, final_name;
+
+ ZEND_HASH_FOREACH_KEY_VAL_IND(arr, num_key, var_name, entry) {
+ if (var_name) {
+ if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) {
+ php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1);
+ if (!php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
+ zend_string_release(Z_STR(final_name));
+ continue;
+ }
+ } else {
+ ZVAL_STR_COPY(&final_name, var_name);
+ }
+ } else {
+ zend_string *str = zend_long_to_str(num_key);
+ php_prefix_varname(&final_name, prefix, ZSTR_VAL(str), ZSTR_LEN(str), 1);
+ zend_string_release(str);
+ if (!php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
+ zend_string_release(Z_STR(final_name));
+ continue;
+ }
+ }
+ if (Z_STRLEN(final_name) == sizeof("this")-1 && !strcmp(Z_STRVAL(final_name), "this")) {
+ if (!exception_thrown) {
+ exception_thrown = 1;
+ zend_throw_error(NULL, "Cannot re-assign $this");
+ }
+ } else {
+ ZVAL_MAKE_REF(entry);
+ Z_ADDREF_P(entry);
+ if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) {
+ if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
+ orig_var = Z_INDIRECT_P(orig_var);
+ }
+ zval_ptr_dtor(orig_var);
+ ZVAL_COPY_VALUE(orig_var, entry);
+ } else {
+ zend_hash_add_new(symbol_table, Z_STR(final_name), entry);
+ }
+ count++;
+ }
+ zend_string_release(Z_STR(final_name));
+ } ZEND_HASH_FOREACH_END();
+
+ return count;
+}
+/* }}} */
+
+static zend_long php_extract_prefix_invalid(zend_array *arr, zend_array *symbol_table, zval *prefix) /* {{{ */
+{
+ int exception_thrown = 0;
+ zend_long count = 0;
+ zend_string *var_name;
+ zend_ulong num_key;
+ zval *entry, *orig_var, final_name;
+
+ ZEND_HASH_FOREACH_KEY_VAL_IND(arr, num_key, var_name, entry) {
+ if (var_name) {
+ if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) {
+ php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1);
+ if (!php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
+ zend_string_release(Z_STR(final_name));
+ continue;
+ }
+ } else {
+ ZVAL_STR_COPY(&final_name, var_name);
+ }
+ } else {
+ zend_string *str = zend_long_to_str(num_key);
+ php_prefix_varname(&final_name, prefix, ZSTR_VAL(str), ZSTR_LEN(str), 1);
+ zend_string_release(str);
+ if (!php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
+ zend_string_release(Z_STR(final_name));
+ continue;
+ }
+ }
+ if (Z_STRLEN(final_name) == sizeof("this")-1 && !strcmp(Z_STRVAL(final_name), "this")) {
+ if (!exception_thrown) {
+ exception_thrown = 1;
+ zend_throw_error(NULL, "Cannot re-assign $this");
+ }
+ } else {
+ ZVAL_DEREF(entry);
+ if (Z_REFCOUNTED_P(entry)) Z_ADDREF_P(entry);
+ if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) {
+ if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
+ orig_var = Z_INDIRECT_P(orig_var);
+ }
+ ZVAL_DEREF(orig_var);
+ zval_ptr_dtor(orig_var);
+ ZVAL_COPY_VALUE(orig_var, entry);
+ } else {
+ zend_hash_add_new(symbol_table, Z_STR(final_name), entry);
+ }
+ count++;
+ }
+ zend_string_release(Z_STR(final_name));
+ } ZEND_HASH_FOREACH_END();
+
+ return count;
+}
+/* }}} */
+
+static zend_long php_extract_ref_skip(zend_array *arr, zend_array *symbol_table) /* {{{ */
+{
+ int exception_thrown = 0;
+ zend_long count = 0;
+ zend_string *var_name;
+ zval *entry, *orig_var;
+
+ ZEND_HASH_FOREACH_STR_KEY_VAL_IND(arr, var_name, entry) {
+ if (!var_name) {
+ continue;
+ }
+ if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) {
+ continue;
+ }
+ if (ZSTR_LEN(var_name) == sizeof("this")-1 && !strcmp(ZSTR_VAL(var_name), "this")) {
+ if (!exception_thrown) {
+ exception_thrown = 1;
+ zend_throw_error(NULL, "Cannot re-assign $this");
+ }
+ continue;
+ }
+ orig_var = zend_hash_find(symbol_table, var_name);
+ if (orig_var) {
+ if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
+ orig_var = Z_INDIRECT_P(orig_var);
+ if (Z_TYPE_P(orig_var) == IS_UNDEF) {
+ ZVAL_MAKE_REF(entry);
+ Z_ADDREF_P(entry);
+ ZVAL_COPY_VALUE(orig_var, entry);
+ count++;
}
}
+ } else {
+ ZVAL_MAKE_REF(entry);
+ Z_ADDREF_P(entry);
+ zend_hash_add_new(symbol_table, var_name, entry);
count++;
}
- zval_dtor(&final_name);
} ZEND_HASH_FOREACH_END();
- zval_ptr_dtor(&var_array);
+
+ return count;
+}
+/* }}} */
+
+static zend_long php_extract_skip(zend_array *arr, zend_array *symbol_table) /* {{{ */
+{
+ int exception_thrown = 0;
+ zend_long count = 0;
+ zend_string *var_name;
+ zval *entry, *orig_var;
+
+ ZEND_HASH_FOREACH_STR_KEY_VAL_IND(arr, var_name, entry) {
+ if (!var_name) {
+ continue;
+ }
+ if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) {
+ continue;
+ }
+ if (ZSTR_LEN(var_name) == sizeof("this")-1 && !strcmp(ZSTR_VAL(var_name), "this")) {
+ if (!exception_thrown) {
+ exception_thrown = 1;
+ zend_throw_error(NULL, "Cannot re-assign $this");
+ }
+ continue;
+ }
+ orig_var = zend_hash_find(symbol_table, var_name);
+ if (orig_var) {
+ if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
+ orig_var = Z_INDIRECT_P(orig_var);
+ if (Z_TYPE_P(orig_var) == IS_UNDEF) {
+ ZVAL_DEREF(entry);
+ if (Z_REFCOUNTED_P(entry)) Z_ADDREF_P(entry);
+ ZVAL_COPY_VALUE(orig_var, entry);
+ count++;
+ }
+ }
+ } else {
+ ZVAL_DEREF(entry);
+ if (Z_REFCOUNTED_P(entry)) Z_ADDREF_P(entry);
+ zend_hash_add_new(symbol_table, var_name, entry);
+ count++;
+ }
+ } ZEND_HASH_FOREACH_END();
+
+ return count;
+}
+/* }}} */
+
+/* {{{ proto int extract(array var_array [, int extract_type [, string prefix]])
+ Imports variables into symbol table from an array */
+PHP_FUNCTION(extract)
+{
+ zval *var_array_param, *prefix = NULL;
+ zend_long extract_refs;
+ zend_long extract_type = EXTR_OVERWRITE;
+ zend_long count;
+ zend_array *symbol_table;
+
+ ZEND_PARSE_PARAMETERS_START(1, 3)
+ Z_PARAM_ARRAY_EX2(var_array_param, 0, 1, 0)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_LONG(extract_type)
+ Z_PARAM_ZVAL(prefix)
+ ZEND_PARSE_PARAMETERS_END();
+
+ extract_refs = (extract_type & EXTR_REFS);
+ if (extract_refs) {
+ SEPARATE_ZVAL(var_array_param);
+ }
+ extract_type &= 0xff;
+
+ if (extract_type < EXTR_OVERWRITE || extract_type > EXTR_IF_EXISTS) {
+ php_error_docref(NULL, E_WARNING, "Invalid extract type");
+ return;
+ }
+
+ if (extract_type > EXTR_SKIP && extract_type <= EXTR_PREFIX_IF_EXISTS && ZEND_NUM_ARGS() < 3) {
+ php_error_docref(NULL, E_WARNING, "specified extract type requires the prefix parameter");
+ return;
+ }
+
+ if (prefix) {
+ convert_to_string(prefix);
+ if (Z_STRLEN_P(prefix) && !php_valid_var_name(Z_STRVAL_P(prefix), Z_STRLEN_P(prefix))) {
+ php_error_docref(NULL, E_WARNING, "prefix is not a valid identifier");
+ return;
+ }
+ }
+
+ if (zend_forbid_dynamic_call("extract()") == FAILURE) {
+ return;
+ }
+
+ symbol_table = zend_rebuild_symbol_table();
+
+ if (extract_refs) {
+ switch (extract_type) {
+ case EXTR_IF_EXISTS:
+ count = php_extract_ref_if_exists(Z_ARRVAL_P(var_array_param), symbol_table);
+ break;
+ case EXTR_OVERWRITE:
+ count = php_extract_ref_overwrite(Z_ARRVAL_P(var_array_param), symbol_table);
+ break;
+ case EXTR_PREFIX_IF_EXISTS:
+ count = php_extract_ref_prefix_if_exists(Z_ARRVAL_P(var_array_param), symbol_table, prefix);
+ break;
+ case EXTR_PREFIX_SAME:
+ count = php_extract_ref_prefix_same(Z_ARRVAL_P(var_array_param), symbol_table, prefix);
+ break;
+ case EXTR_PREFIX_ALL:
+ count = php_extract_ref_prefix_all(Z_ARRVAL_P(var_array_param), symbol_table, prefix);
+ break;
+ case EXTR_PREFIX_INVALID:
+ count = php_extract_ref_prefix_invalid(Z_ARRVAL_P(var_array_param), symbol_table, prefix);
+ break;
+ default:
+ count = php_extract_ref_skip(Z_ARRVAL_P(var_array_param), symbol_table);
+ break;
+ }
+ } else {
+ switch (extract_type) {
+ case EXTR_IF_EXISTS:
+ count = php_extract_if_exists(Z_ARRVAL_P(var_array_param), symbol_table);
+ break;
+ case EXTR_OVERWRITE:
+ count = php_extract_overwrite(Z_ARRVAL_P(var_array_param), symbol_table);
+ break;
+ case EXTR_PREFIX_IF_EXISTS:
+ count = php_extract_prefix_if_exists(Z_ARRVAL_P(var_array_param), symbol_table, prefix);
+ break;
+ case EXTR_PREFIX_SAME:
+ count = php_extract_prefix_same(Z_ARRVAL_P(var_array_param), symbol_table, prefix);
+ break;
+ case EXTR_PREFIX_ALL:
+ count = php_extract_prefix_all(Z_ARRVAL_P(var_array_param), symbol_table, prefix);
+ break;
+ case EXTR_PREFIX_INVALID:
+ count = php_extract_prefix_invalid(Z_ARRVAL_P(var_array_param), symbol_table, prefix);
+ break;
+ default:
+ count = php_extract_skip(Z_ARRVAL_P(var_array_param), symbol_table);
+ break;
+ }
+ }
RETURN_LONG(count);
}
@@ -1937,9 +2603,9 @@ PHP_FUNCTION(compact)
uint32_t num_args, i;
zend_array *symbol_table;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &num_args) == FAILURE) {
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(1, -1)
+ Z_PARAM_VARIADIC('+', args, num_args)
+ ZEND_PARSE_PARAMETERS_END();
if (zend_forbid_dynamic_call("compact()") == FAILURE) {
return;
@@ -1953,13 +2619,13 @@ PHP_FUNCTION(compact)
/* compact() is probably most used with a single array of var_names
or multiple string names, rather than a combination of both.
So quickly guess a minimum result size based on that */
- if (ZEND_NUM_ARGS() == 1 && Z_TYPE(args[0]) == IS_ARRAY) {
+ if (num_args && Z_TYPE(args[0]) == IS_ARRAY) {
array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL(args[0])));
} else {
- array_init_size(return_value, ZEND_NUM_ARGS());
+ array_init_size(return_value, num_args);
}
- for (i=0; i<ZEND_NUM_ARGS(); i++) {
+ for (i = 0; i < num_args; i++) {
php_compact_var(symbol_table, return_value, &args[i]);
}
}
@@ -2043,9 +2709,10 @@ PHP_FUNCTION(array_fill_keys)
{
zval *keys, *val, *entry;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "az", &keys, &val) == FAILURE) {
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(2, 2)
+ Z_PARAM_ARRAY(keys)
+ Z_PARAM_ZVAL(val)
+ ZEND_PARSE_PARAMETERS_END();
/* Initialize return array */
array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(keys)));
@@ -2094,9 +2761,12 @@ PHP_FUNCTION(range)
int err = 0, is_step_double = 0;
double step = 1.0;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz|z", &zlow, &zhigh, &zstep) == FAILURE) {
- RETURN_FALSE;
- }
+ ZEND_PARSE_PARAMETERS_START(2, 3)
+ Z_PARAM_ZVAL(zlow)
+ Z_PARAM_ZVAL(zhigh)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_ZVAL(zstep)
+ ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
if (zstep) {
if (Z_TYPE_P(zstep) == IS_DOUBLE ||
@@ -2141,11 +2811,7 @@ PHP_FUNCTION(range)
zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
for (; low >= high; low -= (unsigned int)lstep) {
- if (CG(one_char_string)[low]) {
- ZVAL_INTERNED_STR(&tmp, CG(one_char_string)[low]);
- } else {
- ZVAL_STRINGL(&tmp, (char*)&low, 1);
- }
+ ZVAL_INTERNED_STR(&tmp, ZSTR_CHAR(low));
ZEND_HASH_FILL_ADD(&tmp);
if (((signed int)low - lstep) < 0) {
break;
@@ -2161,11 +2827,7 @@ PHP_FUNCTION(range)
zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
for (; low <= high; low += (unsigned int)lstep) {
- if (CG(one_char_string)[low]) {
- ZVAL_INTERNED_STR(&tmp, CG(one_char_string)[low]);
- } else {
- ZVAL_STRINGL(&tmp, (char*)&low, 1);
- }
+ ZVAL_INTERNED_STR(&tmp, ZSTR_CHAR(low));
ZEND_HASH_FILL_ADD(&tmp);
if (((signed int)low + lstep) > 255) {
break;
@@ -2174,11 +2836,7 @@ PHP_FUNCTION(range)
} ZEND_HASH_FILL_END();
} else {
array_init(return_value);
- if (CG(one_char_string)[low]) {
- ZVAL_INTERNED_STR(&tmp, CG(one_char_string)[low]);
- } else {
- ZVAL_STRINGL(&tmp, (char*)&low, 1);
- }
+ ZVAL_INTERNED_STR(&tmp, ZSTR_CHAR(low));
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
}
} else if (Z_TYPE_P(zlow) == IS_DOUBLE || Z_TYPE_P(zhigh) == IS_DOUBLE || is_step_double) {
@@ -2376,9 +3034,9 @@ PHP_FUNCTION(shuffle)
{
zval *array;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/", &array) == FAILURE) {
- RETURN_FALSE;
- }
+ ZEND_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY_EX(array, 0, 1)
+ ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
php_array_data_shuffle(array);
@@ -2537,9 +3195,10 @@ PHP_FUNCTION(array_push)
argc; /* Number of function arguments */
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/+", &stack, &args, &argc) == FAILURE) {
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(2, -1)
+ Z_PARAM_ARRAY_EX(stack, 0, 1)
+ Z_PARAM_VARIADIC('+', args, argc)
+ ZEND_PARSE_PARAMETERS_END();
/* For each subsequent argument, make it a reference, increase refcount, and add it to the end of the array */
for (i = 0; i < argc; i++) {
@@ -2736,9 +3395,10 @@ PHP_FUNCTION(array_unshift)
zend_string *key;
zval *value;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/+", &stack, &args, &argc) == FAILURE) {
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(2, -1)
+ Z_PARAM_ARRAY_EX(stack, 0, 1)
+ Z_PARAM_VARIADIC('+', args, argc)
+ ZEND_PARSE_PARAMETERS_END();
zend_hash_init(&new_hash, zend_hash_num_elements(Z_ARRVAL_P(stack)) + argc, NULL, ZVAL_PTR_DTOR, 0);
for (i = 0; i < argc; i++) {
@@ -2788,7 +3448,7 @@ PHP_FUNCTION(array_unshift)
Z_ARRVAL_P(stack)->nNextFreeElement = new_hash.nNextFreeElement;
Z_ARRVAL_P(stack)->arData = new_hash.arData;
Z_ARRVAL_P(stack)->pDestructor = new_hash.pDestructor;
-
+
zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack));
/* Clean up and return the number of elements in the stack */
@@ -2807,9 +3467,13 @@ PHP_FUNCTION(array_splice)
length = 0;
int num_in; /* Number of elements in the input array */
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/l|lz/", &array, &offset, &length, &repl_array) == FAILURE) {
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(2, 4)
+ Z_PARAM_ARRAY_EX(array, 0, 1)
+ Z_PARAM_LONG(offset)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_LONG(length)
+ Z_PARAM_ZVAL(repl_array)
+ ZEND_PARSE_PARAMETERS_END();
num_in = zend_hash_num_elements(Z_ARRVAL_P(array));
@@ -3143,47 +3807,53 @@ static inline void php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAMETE
Z_PARAM_VARIADIC('+', args, argc)
ZEND_PARSE_PARAMETERS_END();
- for (i = 0; i < argc; i++) {
- zval *arg = args + i;
-
- ZVAL_DEREF(arg);
- if (Z_TYPE_P(arg) != IS_ARRAY) {
- php_error_docref(NULL, E_WARNING, "Argument #%d is not an array", i + 1);
- RETURN_NULL();
- }
- }
-
if (replace) {
HashTable *dest;
+ for (i = 0; i < argc; i++) {
+ zval *arg = args + i;
+
+ if (Z_TYPE_P(arg) != IS_ARRAY) {
+ php_error_docref(NULL, E_WARNING, "Argument #%d is not an array", i + 1);
+ RETURN_NULL();
+ }
+ }
+
/* copy first array */
arg = args;
- ZVAL_DEREF(arg);
dest = zend_array_dup(Z_ARRVAL_P(arg));
ZVAL_ARR(return_value, dest);
if (recursive) {
for (i = 1; i < argc; i++) {
arg = args + i;
- ZVAL_DEREF(arg);
php_array_replace_recursive(dest, Z_ARRVAL_P(arg));
}
} else {
for (i = 1; i < argc; i++) {
arg = args + i;
- ZVAL_DEREF(arg);
zend_hash_merge(dest, Z_ARRVAL_P(arg), zval_add_ref, 1);
}
}
} else {
zval *src_entry;
HashTable *src, *dest;
+ uint32_t count = 0;
+
+ for (i = 0; i < argc; i++) {
+ zval *arg = args + i;
+
+ if (Z_TYPE_P(arg) != IS_ARRAY) {
+ php_error_docref(NULL, E_WARNING, "Argument #%d is not an array", i + 1);
+ RETURN_NULL();
+ }
+ count += zend_hash_num_elements(Z_ARRVAL_P(arg));
+ }
arg = args;
- ZVAL_DEREF(arg);
src = Z_ARRVAL_P(arg);
/* copy first array */
- array_init_size(return_value, zend_hash_num_elements(src));
+ array_init_size(return_value, count);
dest = Z_ARRVAL_P(return_value);
if (src->u.flags & HASH_FLAG_PACKED) {
zend_hash_real_init(dest, 1);
@@ -3215,13 +3885,11 @@ static inline void php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAMETE
if (recursive) {
for (i = 1; i < argc; i++) {
arg = args + i;
- ZVAL_DEREF(arg);
php_array_merge_recursive(dest, Z_ARRVAL_P(arg));
}
} else {
for (i = 1; i < argc; i++) {
arg = args + i;
- ZVAL_DEREF(arg);
php_array_merge(dest, Z_ARRVAL_P(arg));
}
}
@@ -3272,6 +3940,8 @@ PHP_FUNCTION(array_keys)
zend_bool strict = 0; /* do strict comparison */
zend_ulong num_idx;
zend_string *str_idx;
+ zend_array *arrval;
+ zend_ulong elem_count;
ZEND_PARSE_PARAMETERS_START(1, 3)
Z_PARAM_ARRAY(input)
@@ -3279,13 +3949,20 @@ PHP_FUNCTION(array_keys)
Z_PARAM_ZVAL(search_value)
Z_PARAM_BOOL(strict)
ZEND_PARSE_PARAMETERS_END();
+ arrval = Z_ARRVAL_P(input);
+ elem_count = zend_hash_num_elements(arrval);
+
+ /* Base case: empty input */
+ if (!elem_count) {
+ RETURN_ZVAL(input, 1, 0)
+ }
/* Initialize return array */
if (search_value != NULL) {
array_init(return_value);
if (strict) {
- ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(input), num_idx, str_idx, entry) {
+ ZEND_HASH_FOREACH_KEY_VAL_IND(arrval, num_idx, str_idx, entry) {
ZVAL_DEREF(entry);
if (fast_is_identical_function(search_value, entry)) {
if (str_idx) {
@@ -3297,7 +3974,7 @@ PHP_FUNCTION(array_keys)
}
} ZEND_HASH_FOREACH_END();
} else {
- ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(input), num_idx, str_idx, entry) {
+ ZEND_HASH_FOREACH_KEY_VAL_IND(arrval, num_idx, str_idx, entry) {
if (fast_equal_check_function(search_value, entry)) {
if (str_idx) {
ZVAL_STR_COPY(&new_val, str_idx);
@@ -3309,21 +3986,26 @@ PHP_FUNCTION(array_keys)
} ZEND_HASH_FOREACH_END();
}
} else {
- array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(input)));
- if (!zend_hash_num_elements(Z_ARRVAL_P(input))) {
- return;
- }
+ array_init_size(return_value, elem_count);
zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
- /* Go through input array and add keys to the return array */
- ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(input), num_idx, str_idx, entry) {
- if (str_idx) {
- ZVAL_STR_COPY(&new_val, str_idx);
- } else {
- ZVAL_LONG(&new_val, num_idx);
+ if (HT_IS_PACKED(arrval) && HT_IS_WITHOUT_HOLES(arrval)) {
+ /* Optimistic case: range(0..n-1) for vector-like packed array */
+ ZVAL_LONG(&new_val, 0);
+ for (; Z_LVAL(new_val) < elem_count; ++Z_LVAL(new_val)) {
+ ZEND_HASH_FILL_ADD(&new_val);
}
- ZEND_HASH_FILL_ADD(&new_val);
- } ZEND_HASH_FOREACH_END();
+ } else {
+ /* Go through input array and add keys to the return array */
+ ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(input), num_idx, str_idx, entry) {
+ if (str_idx) {
+ ZVAL_STR_COPY(&new_val, str_idx);
+ } else {
+ ZVAL_LONG(&new_val, num_idx);
+ }
+ ZEND_HASH_FILL_ADD(&new_val);
+ } ZEND_HASH_FOREACH_END();
+ }
} ZEND_HASH_FILL_END();
}
}
@@ -3335,23 +4017,34 @@ PHP_FUNCTION(array_values)
{
zval *input, /* Input array */
*entry; /* An entry in the input array */
+ zend_array *arrval;
+ zend_long arrlen;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_ARRAY(input)
ZEND_PARSE_PARAMETERS_END();
- /* Initialize return array */
- array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(input)));
+ arrval = Z_ARRVAL_P(input);
- if (!zend_hash_num_elements(Z_ARRVAL_P(input))) {
- return;
+ /* Return empty input as is */
+ arrlen = zend_hash_num_elements(arrval);
+ if (!arrlen) {
+ RETURN_ZVAL(input, 1, 0);
+ }
+
+ /* Return vector-like packed arrays as-is */
+ if (HT_IS_PACKED(arrval) && HT_IS_WITHOUT_HOLES(arrval) &&
+ arrval->nNextFreeElement == arrlen) {
+ RETURN_ZVAL(input, 1, 0);
}
+ /* Initialize return array */
+ array_init_size(return_value, zend_hash_num_elements(arrval));
zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
/* Go through input array and add values to the return array */
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
- ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(input), entry) {
+ ZEND_HASH_FOREACH_VAL(arrval, entry) {
if (UNEXPECTED(Z_ISREF_P(entry) && Z_REFCOUNT_P(entry) == 1)) {
entry = Z_REFVAL_P(entry);
}
@@ -3371,9 +4064,9 @@ PHP_FUNCTION(array_count_values)
*tmp;
HashTable *myht;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &input) == FAILURE) {
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY(input)
+ ZEND_PARSE_PARAMETERS_END();
/* Initialize return array */
array_init(return_value);
@@ -3472,9 +4165,12 @@ PHP_FUNCTION(array_column)
HashTable *arr_hash;
zval *zcolval = NULL, *zkeyval = NULL, rvc, rvk;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "hz!|z!", &arr_hash, &zcolumn, &zkey) == FAILURE) {
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(2, 3)
+ Z_PARAM_ARRAY_HT(arr_hash)
+ Z_PARAM_ZVAL_EX(zcolumn, 1, 0)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_ZVAL_EX(zkey, 1, 0)
+ ZEND_PARSE_PARAMETERS_END();
if ((zcolumn && !array_column_param_helper(zcolumn, "column")) ||
(zkey && !array_column_param_helper(zkey, "index"))) {
@@ -3550,9 +4246,11 @@ PHP_FUNCTION(array_reverse)
zend_ulong num_key;
zend_bool preserve_keys = 0; /* whether to preserve keys */
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|b", &input, &preserve_keys) == FAILURE) {
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(1, 2)
+ Z_PARAM_ARRAY(input)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_BOOL(preserve_keys)
+ ZEND_PARSE_PARAMETERS_END();
/* Initialize return array */
array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(input)));
@@ -3599,9 +4297,11 @@ PHP_FUNCTION(array_pad)
zend_string *key;
zval *value;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "alz", &input, &pad_size, &pad_value) == FAILURE) {
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(3, 3)
+ Z_PARAM_ARRAY(input)
+ Z_PARAM_LONG(pad_size)
+ Z_PARAM_ZVAL(pad_value)
+ ZEND_PARSE_PARAMETERS_END();
/* Do some initial calculations */
input_size = zend_hash_num_elements(Z_ARRVAL_P(input));
@@ -3681,9 +4381,9 @@ PHP_FUNCTION(array_flip)
zend_ulong num_idx;
zend_string *str_idx;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY(array)
+ ZEND_PARSE_PARAMETERS_END();
array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(array)));
@@ -3720,9 +4420,11 @@ PHP_FUNCTION(array_change_key_case)
zend_ulong num_key;
zend_long change_to_upper=0;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|l", &array, &change_to_upper) == FAILURE) {
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(1, 2)
+ Z_PARAM_ARRAY(array)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_LONG(change_to_upper)
+ ZEND_PARSE_PARAMETERS_END();
array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(array)));
@@ -3765,33 +4467,68 @@ static void array_bucketindex_swap(void *p, void *q) /* {{{ */
PHP_FUNCTION(array_unique)
{
zval *array;
- uint idx;
+ uint32_t idx;
Bucket *p;
struct bucketindex *arTmp, *cmpdata, *lastkept;
unsigned int i;
zend_long sort_type = PHP_SORT_STRING;
compare_func_t cmp;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|l", &array, &sort_type) == FAILURE) {
+ ZEND_PARSE_PARAMETERS_START(1, 2)
+ Z_PARAM_ARRAY(array)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_LONG(sort_type)
+ ZEND_PARSE_PARAMETERS_END();
+
+ if (Z_ARRVAL_P(array)->nNumOfElements <= 1) { /* nothing to do */
+ ZVAL_COPY(return_value, array);
return;
}
- cmp = php_get_data_compare_func(sort_type, 0);
+ if (sort_type == PHP_SORT_STRING) {
+ HashTable seen;
+ zend_long num_key;
+ zend_string *str_key;
+ zval *val;
+ zend_hash_init(&seen, zend_hash_num_elements(Z_ARRVAL_P(array)), NULL, NULL, 0);
+ array_init(return_value);
- if (Z_ARRVAL_P(array)->nNumOfElements <= 1) { /* nothing to do */
- ZVAL_COPY(return_value, array);
+ ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(array), num_key, str_key, val) {
+ zval *retval;
+ if (Z_TYPE_P(val) == IS_STRING) {
+ retval = zend_hash_add_empty_element(&seen, Z_STR_P(val));
+ } else {
+ zend_string *str_val = zval_get_string(val);
+ retval = zend_hash_add_empty_element(&seen, str_val);
+ zend_string_release(str_val);
+ }
+
+ if (retval) {
+ /* First occurrence of the value */
+ if (UNEXPECTED(Z_ISREF_P(val) && Z_REFCOUNT_P(val) == 1)) {
+ ZVAL_DEREF(val);
+ }
+ Z_TRY_ADDREF_P(val);
+
+ if (str_key) {
+ zend_hash_add_new(Z_ARRVAL_P(return_value), str_key, val);
+ } else {
+ zend_hash_index_add_new(Z_ARRVAL_P(return_value), num_key, val);
+ }
+ }
+ } ZEND_HASH_FOREACH_END();
+
+ zend_hash_destroy(&seen);
return;
}
+ cmp = php_get_data_compare_func(sort_type, 0);
+
RETVAL_ARR(zend_array_dup(Z_ARRVAL_P(array)));
/* create and sort array with pointers to the target_hash buckets */
arTmp = (struct bucketindex *) pemalloc((Z_ARRVAL_P(array)->nNumOfElements + 1) * sizeof(struct bucketindex), Z_ARRVAL_P(array)->u.flags & HASH_FLAG_PERSISTENT);
- if (!arTmp) {
- zval_dtor(return_value);
- RETURN_FALSE;
- }
for (i = 0, idx = 0; idx < Z_ARRVAL_P(array)->nNumUsed; idx++) {
p = Z_ARRVAL_P(array)->arData + idx;
if (Z_TYPE(p->val) == IS_UNDEF) continue;
@@ -3852,7 +4589,7 @@ static int zval_user_compare(zval *a, zval *b) /* {{{ */
if (zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
zend_long ret = zval_get_long(&retval);
zval_ptr_dtor(&retval);
- return ret < 0 ? -1 : ret > 0 ? 1 : 0;;
+ return ret < 0 ? -1 : ret > 0 ? 1 : 0;
} else {
return 0;
}
@@ -3861,7 +4598,7 @@ static int zval_user_compare(zval *a, zval *b) /* {{{ */
static void php_array_intersect_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_type) /* {{{ */
{
- uint idx;
+ uint32_t idx;
Bucket *p;
int argc, i;
zval *args;
@@ -3962,7 +4699,7 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int
zval *args = NULL;
HashTable *hash;
int arr_argc, i, c = 0;
- uint idx;
+ uint32_t idx;
Bucket **lists, *list, **ptrs, *p;
uint32_t req_args;
char *param_spec;
@@ -4082,13 +4819,6 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int
}
hash = Z_ARRVAL(args[i]);
list = (Bucket *) pemalloc((hash->nNumOfElements + 1) * sizeof(Bucket), hash->u.flags & HASH_FLAG_PERSISTENT);
- if (!list) {
- PHP_ARRAY_CMP_FUNC_RESTORE();
-
- efree(ptrs);
- efree(lists);
- RETURN_FALSE;
- }
lists[i] = list;
ptrs[i] = list;
for (idx = 0; idx < hash->nNumUsed; idx++) {
@@ -4289,7 +5019,7 @@ PHP_FUNCTION(array_uintersect_uassoc)
static void php_array_diff_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_type) /* {{{ */
{
- uint idx;
+ uint32_t idx;
Bucket *p;
int argc, i;
zval *args;
@@ -4385,7 +5115,7 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_
zval *args = NULL;
HashTable *hash;
int arr_argc, i, c;
- uint idx;
+ uint32_t idx;
Bucket **lists, *list, **ptrs, *p;
uint32_t req_args;
char *param_spec;
@@ -4504,13 +5234,6 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_
}
hash = Z_ARRVAL(args[i]);
list = (Bucket *) pemalloc((hash->nNumOfElements + 1) * sizeof(Bucket), hash->u.flags & HASH_FLAG_PERSISTENT);
- if (!list) {
- PHP_ARRAY_CMP_FUNC_RESTORE();
-
- efree(ptrs);
- efree(lists);
- RETURN_FALSE;
- }
lists[i] = list;
ptrs[i] = list;
for (idx = 0; idx < hash->nNumUsed; idx++) {
@@ -4677,9 +5400,9 @@ PHP_FUNCTION(array_diff)
return;
}
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(1, -1)
+ Z_PARAM_VARIADIC('+', args, argc)
+ ZEND_PARSE_PARAMETERS_END();
if (Z_TYPE(args[0]) != IS_ARRAY) {
php_error_docref(NULL, E_WARNING, "Argument #1 is not an array");
@@ -4818,7 +5541,7 @@ PHP_FUNCTION(array_multisort)
zval* args;
zval** arrays;
Bucket** indirect;
- uint idx;
+ uint32_t idx;
Bucket* p;
HashTable* hash;
int argc;
@@ -4829,9 +5552,9 @@ PHP_FUNCTION(array_multisort)
int sort_type = PHP_SORT_REGULAR;
int i, k, n;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(1, -1)
+ Z_PARAM_VARIADIC('+', args, argc)
+ ZEND_PARSE_PARAMETERS_END();
/* Allocate space for storing pointers to input arrays and sort flags. */
arrays = (zval **)ecalloc(argc, sizeof(zval *));
@@ -5002,9 +5725,11 @@ PHP_FUNCTION(array_rand)
uint32_t bitset_len;
ALLOCA_FLAG(use_heap)
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|l", &input, &num_req) == FAILURE) {
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(1, 2)
+ Z_PARAM_ARRAY(input)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_LONG(num_req)
+ ZEND_PARSE_PARAMETERS_END();
num_avail = zend_hash_num_elements(Z_ARRVAL_P(input));
@@ -5105,9 +5830,9 @@ PHP_FUNCTION(array_sum)
*entry,
entry_n;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &input) == FAILURE) {
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY(input)
+ ZEND_PARSE_PARAMETERS_END();
ZVAL_LONG(return_value, 0);
@@ -5131,9 +5856,9 @@ PHP_FUNCTION(array_product)
entry_n;
double dval;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &input) == FAILURE) {
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ARRAY(input)
+ ZEND_PARSE_PARAMETERS_END();
ZVAL_LONG(return_value, 1);
if (!zend_hash_num_elements(Z_ARRVAL_P(input))) {
@@ -5175,9 +5900,12 @@ PHP_FUNCTION(array_reduce)
zval *initial = NULL;
HashTable *htbl;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "af|z", &input, &fci, &fci_cache, &initial) == FAILURE) {
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(2, 3)
+ Z_PARAM_ARRAY(input)
+ Z_PARAM_FUNC(fci, fci_cache)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_ZVAL(initial)
+ ZEND_PARSE_PARAMETERS_END();
if (ZEND_NUM_ARGS() > 2) {
@@ -5237,9 +5965,12 @@ PHP_FUNCTION(array_filter)
zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
zend_ulong num_key;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|fl", &array, &fci, &fci_cache, &use_type) == FAILURE) {
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(1, 3)
+ Z_PARAM_ARRAY(array)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_FUNC(fci, fci_cache)
+ Z_PARAM_LONG(use_type)
+ ZEND_PARSE_PARAMETERS_END();
array_init(return_value);
if (zend_hash_num_elements(Z_ARRVAL_P(array)) == 0) {
@@ -5333,6 +6064,7 @@ PHP_FUNCTION(array_map)
zend_ulong num_key;
zend_string *str_key;
zval *zv, arg;
+ int ret;
if (Z_TYPE(arrays[0]) != IS_ARRAY) {
php_error_docref(NULL, E_WARNING, "Argument #%d should be an array", 2);
@@ -5355,13 +6087,11 @@ PHP_FUNCTION(array_map)
fci.no_separation = 0;
ZVAL_COPY(&arg, zv);
-
- if (zend_call_function(&fci, &fci_cache) != SUCCESS || Z_TYPE(result) == IS_UNDEF) {
- zval_dtor(return_value);
- zval_ptr_dtor(&arg);
+ ret = zend_call_function(&fci, &fci_cache);
+ i_zval_ptr_dtor(&arg ZEND_FILE_LINE_CC);
+ if (ret != SUCCESS || Z_TYPE(result) == IS_UNDEF) {
+ zend_array_destroy(Z_ARR_P(return_value));
RETURN_NULL();
- } else {
- zval_ptr_dtor(&arg);
}
if (str_key) {
zend_hash_add_new(Z_ARRVAL_P(return_value), str_key, &result);
@@ -5445,7 +6175,7 @@ PHP_FUNCTION(array_map)
if (zend_call_function(&fci, &fci_cache) != SUCCESS || Z_TYPE(result) == IS_UNDEF) {
efree(array_pos);
- zval_dtor(return_value);
+ zend_array_destroy(Z_ARR_P(return_value));
for (i = 0; i < n_arrays; i++) {
zval_ptr_dtor(&params[i]);
}
@@ -5507,7 +6237,7 @@ PHP_FUNCTION(array_key_exists)
Split array into chunks */
PHP_FUNCTION(array_chunk)
{
- int argc = ZEND_NUM_ARGS(), num_in;
+ int num_in;
zend_long size, current = 0;
zend_string *str_key;
zend_ulong num_key;
@@ -5516,9 +6246,13 @@ PHP_FUNCTION(array_chunk)
zval chunk;
zval *entry;
- if (zend_parse_parameters(argc, "al|b", &input, &size, &preserve_keys) == FAILURE) {
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(2, 3)
+ Z_PARAM_ARRAY(input)
+ Z_PARAM_LONG(size)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_BOOL(preserve_keys)
+ ZEND_PARSE_PARAMETERS_END();
+
/* Do bounds checking for size parameter. */
if (size < 1) {
php_error_docref(NULL, E_WARNING, "Size parameter expected to be greater than 0");
@@ -5577,9 +6311,10 @@ PHP_FUNCTION(array_combine)
zval *entry_keys, *entry_values;
int num_keys, num_values;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "hh", &keys, &values) == FAILURE) {
- return;
- }
+ ZEND_PARSE_PARAMETERS_START(2, 2)
+ Z_PARAM_ARRAY_HT(keys)
+ Z_PARAM_ARRAY_HT(values)
+ ZEND_PARSE_PARAMETERS_END();
num_keys = zend_hash_num_elements(keys);
num_values = zend_hash_num_elements(values);