From 0ffe933887b7f432fa23f618625af4fdb01582bc Mon Sep 17 00:00:00 2001 From: hassan Date: Sun, 28 Nov 2021 09:49:55 +0200 Subject: [PATCH 1/8] implement grouping in array_column --- ext/standard/array.c | 94 ++++++++++++++++++++------ ext/standard/basic_functions_arginfo.h | 1 + 2 files changed, 75 insertions(+), 20 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index c3d4c3d7a78a3..ff6862401d850 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -4285,34 +4285,23 @@ PHP_FUNCTION(array_column) zend_string *index_str = NULL; zend_long index_long; bool index_is_null = 1; + bool group_bool = 0; + bool group_is_null = 1; - ZEND_PARSE_PARAMETERS_START(2, 3) + ZEND_PARSE_PARAMETERS_START(2, 4) Z_PARAM_ARRAY_HT(input) Z_PARAM_STR_OR_LONG_OR_NULL(column_str, column_long, column_is_null) Z_PARAM_OPTIONAL Z_PARAM_STR_OR_LONG_OR_NULL(index_str, index_long, index_is_null) + Z_PARAM_BOOL_OR_NULL(group_bool, group_is_null) ZEND_PARSE_PARAMETERS_END(); void* cache_slot_column[3] = { NULL, NULL, NULL }; void* cache_slot_index[3] = { NULL, NULL, NULL }; array_init_size(return_value, zend_hash_num_elements(input)); - /* Index param is not passed */ - if (index_is_null) { - zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); - ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { - ZEND_HASH_FOREACH_VAL(input, data) { - ZVAL_DEREF(data); - if (column_is_null) { - Z_TRY_ADDREF_P(data); - colval = data; - } else if ((colval = array_column_fetch_prop(data, column_str, column_long, cache_slot_column, &rv)) == NULL) { - continue; - } - ZEND_HASH_FILL_ADD(colval); - } ZEND_HASH_FOREACH_END(); - } ZEND_HASH_FILL_END(); - } else { + if (!group_is_null && group_bool && !index_is_null) { + ZEND_HASH_FOREACH_VAL(input, data) { ZVAL_DEREF(data); @@ -4325,14 +4314,79 @@ PHP_FUNCTION(array_column) zval rv; zval *keyval = array_column_fetch_prop(data, index_str, index_long, cache_slot_index, &rv); - if (keyval) { - array_set_zval_key(Z_ARRVAL_P(return_value), keyval, colval); + zval *group_entry; + + convert_to_string(keyval); + group_entry = zend_symtable_find(Z_ARRVAL_P(return_value), Z_STR_P(keyval)); + + if (group_entry != NULL) { + if (Z_TYPE_P(colval) == IS_ARRAY) { + add_index_array(group_entry, Z_ARRVAL_P(group_entry)->nNumUsed, Z_ARRVAL_P(colval)); + } else if (Z_TYPE_P(colval) == IS_STRING) { + add_index_str(group_entry, Z_ARRVAL_P(group_entry)->nNumUsed, Z_STR_P(colval)); + } else { + add_index_long(group_entry, Z_ARRVAL_P(group_entry)->nNumUsed, Z_LVAL_P(colval)); + } + + array_set_zval_key(Z_ARRVAL_P(return_value), keyval, group_entry); zval_ptr_dtor(colval); zval_ptr_dtor(keyval); } else { - zend_hash_next_index_insert(Z_ARRVAL_P(return_value), colval); + zval ft; + array_init_size(&ft, 1); + if (Z_TYPE_P(colval) == IS_ARRAY) { + add_index_array(&ft, Z_ARRVAL_P(&ft)->nNumUsed, Z_ARRVAL_P(colval)); + } else if (Z_TYPE_P(colval) == IS_STRING) { + add_index_str(&ft, Z_ARRVAL_P(&ft)->nNumUsed, Z_STR_P(colval)); + } else { + add_index_long(&ft, Z_ARRVAL_P(&ft)->nNumUsed, Z_LVAL_P(colval)); + } + array_set_zval_key(Z_ARRVAL_P(return_value), keyval, &ft); + ZVAL_UNDEF(&ft); + zval_ptr_dtor(&ft); + zval_ptr_dtor(colval); + zval_ptr_dtor(keyval); } + } ZEND_HASH_FOREACH_END(); + } else { + /* Index param is not passed */ + if (index_is_null) { + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { + ZEND_HASH_FOREACH_VAL(input, data) { + ZVAL_DEREF(data); + if (column_is_null) { + Z_TRY_ADDREF_P(data); + colval = data; + } else if ((colval = array_column_fetch_prop(data, column_str, column_long, cache_slot_column, &rv)) == NULL) { + continue; + } + ZEND_HASH_FILL_ADD(colval); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FILL_END(); + } else { + ZEND_HASH_FOREACH_VAL(input, data) { + ZVAL_DEREF(data); + + if (column_is_null) { + Z_TRY_ADDREF_P(data); + colval = data; + } else if ((colval = array_column_fetch_prop(data, column_str, column_long, cache_slot_column, &rv)) == NULL) { + continue; + } + + zval rv; + zval *keyval = array_column_fetch_prop(data, index_str, index_long, cache_slot_index, &rv); + if (keyval) { + array_set_zval_key(Z_ARRVAL_P(return_value), keyval, colval); + zval_ptr_dtor(colval); + zval_ptr_dtor(keyval); + } else { + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), colval); + } + } ZEND_HASH_FOREACH_END(); + } } } /* }}} */ diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index ab7776d630919..47937706d69f6 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -245,6 +245,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_column, 0, 2, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO(0, array, IS_ARRAY, 0) ZEND_ARG_TYPE_MASK(0, column_key, MAY_BE_LONG|MAY_BE_STRING|MAY_BE_NULL, NULL) ZEND_ARG_TYPE_MASK(0, index_key, MAY_BE_LONG|MAY_BE_STRING|MAY_BE_NULL, "null") + ZEND_ARG_TYPE_MASK(0, group_key, MAY_BE_BOOL|MAY_BE_NULL, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_reverse, 0, 1, IS_ARRAY, 0) From 2568278b27e3933ccc637eea5eacf6ff52efda68 Mon Sep 17 00:00:00 2001 From: hassan Date: Sun, 28 Nov 2021 09:50:17 +0200 Subject: [PATCH 2/8] add tests to array column grouping --- .../tests/array/array_column_group_001.phpt | 100 ++++++++++++++++++ .../tests/array/array_column_group_002.phpt | 45 ++++++++ .../tests/array/array_column_group_003.phpt | 38 +++++++ .../tests/array/array_column_group_004.phpt | 92 ++++++++++++++++ 4 files changed, 275 insertions(+) create mode 100644 ext/standard/tests/array/array_column_group_001.phpt create mode 100644 ext/standard/tests/array/array_column_group_002.phpt create mode 100644 ext/standard/tests/array/array_column_group_003.phpt create mode 100644 ext/standard/tests/array/array_column_group_004.phpt diff --git a/ext/standard/tests/array/array_column_group_001.phpt b/ext/standard/tests/array/array_column_group_001.phpt new file mode 100644 index 0000000000000..951579b5a628c --- /dev/null +++ b/ext/standard/tests/array/array_column_group_001.phpt @@ -0,0 +1,100 @@ +--TEST-- +Group the whole array using integer index +--FILE-- + 1, 'name' => 'hassan', 'score' => 'A', 's' => '1'], + ['id' => 2, 'name' => 'hassan', 'score' => 'B', 's' => '2'], + ['id' => 3, 'name' => 'ahmed', 'score' => 'C', 's' => '1'], + ['id' => 4, 'name' => 'moustafa', 'score' => 'D', 's' => '2'], + ['id' => 5, 'name' => 'hassan', 'score' => 'A', 's' => '3'], + ['id' => 6, 'name' => 'wael', 'score' => 'A', 's' => '3'], + ['id' => 6, 'name' => 'wael', 'score' => 'D', 's' => '1'], +]; + +print_r(array_column($ar, null, 'id', true)); +?> +--EXPECT-- +Array +( + [1] => Array + ( + [0] => Array + ( + [id] => 1 + [name] => hassan + [score] => A + [s] => 1 + ) + + ) + + [2] => Array + ( + [0] => Array + ( + [id] => 2 + [name] => hassan + [score] => B + [s] => 2 + ) + + ) + + [3] => Array + ( + [0] => Array + ( + [id] => 3 + [name] => ahmed + [score] => C + [s] => 1 + ) + + ) + + [4] => Array + ( + [0] => Array + ( + [id] => 4 + [name] => moustafa + [score] => D + [s] => 2 + ) + + ) + + [5] => Array + ( + [0] => Array + ( + [id] => 5 + [name] => hassan + [score] => A + [s] => 3 + ) + + ) + + [6] => Array + ( + [0] => Array + ( + [id] => 6 + [name] => wael + [score] => A + [s] => 3 + ) + + [1] => Array + ( + [id] => 6 + [name] => wael + [score] => D + [s] => 1 + ) + + ) + +) diff --git a/ext/standard/tests/array/array_column_group_002.phpt b/ext/standard/tests/array/array_column_group_002.phpt new file mode 100644 index 0000000000000..6af9dcae2470e --- /dev/null +++ b/ext/standard/tests/array/array_column_group_002.phpt @@ -0,0 +1,45 @@ +--TEST-- +Group an element using string index +--FILE-- + 1, 'name' => 'hassan', 'score' => 'A', 's' => '1'], + ['id' => 2, 'name' => 'hassan', 'score' => 'B', 's' => '2'], + ['id' => 3, 'name' => 'ahmed', 'score' => 'C', 's' => '1'], + ['id' => 4, 'name' => 'moustafa', 'score' => 'D', 's' => '2'], + ['id' => 5, 'name' => 'hassan', 'score' => 'A', 's' => '3'], + ['id' => 6, 'name' => 'wael', 'score' => 'A', 's' => '3'], + ['id' => 6, 'name' => 'wael', 'score' => 'D', 's' => '1'], +]; + +print_r(array_column($ar, 'name', 'score', true)); + +?> +--EXPECT-- +Array +( + [A] => Array + ( + [0] => hassan + [1] => hassan + [2] => wael + ) + + [B] => Array + ( + [0] => hassan + ) + + [C] => Array + ( + [0] => ahmed + ) + + [D] => Array + ( + [0] => moustafa + [1] => wael + ) + +) diff --git a/ext/standard/tests/array/array_column_group_003.phpt b/ext/standard/tests/array/array_column_group_003.phpt new file mode 100644 index 0000000000000..970efba01ff3b --- /dev/null +++ b/ext/standard/tests/array/array_column_group_003.phpt @@ -0,0 +1,38 @@ +--TEST-- +Group an element using an integer but casted into a string +--FILE-- + 1, 'name' => 'hassan', 'score' => 'A', 's' => '1'], + ['id' => 2, 'name' => 'hassan', 'score' => 'B', 's' => '2'], + ['id' => 3, 'name' => 'ahmed', 'score' => 'C', 's' => '1'], + ['id' => 4, 'name' => 'moustafa', 'score' => 'D', 's' => '2'], + ['id' => 5, 'name' => 'hassan', 'score' => 'A', 's' => '3'], + ['id' => 6, 'name' => 'wael', 'score' => 'A', 's' => '3'], + ['id' => 6, 'name' => 'wael', 'score' => 'D', 's' => '1'], +]; +print_r(array_column($ar, 'score', 's', true)); +?> +--EXPECT-- +Array +( + [1] => Array + ( + [0] => A + [1] => C + [2] => D + ) + + [2] => Array + ( + [0] => B + [1] => D + ) + + [3] => Array + ( + [0] => A + [1] => A + ) + +) diff --git a/ext/standard/tests/array/array_column_group_004.phpt b/ext/standard/tests/array/array_column_group_004.phpt new file mode 100644 index 0000000000000..d40c58cdb89e1 --- /dev/null +++ b/ext/standard/tests/array/array_column_group_004.phpt @@ -0,0 +1,92 @@ +--TEST-- +Group the whole array using string index +--FILE-- + 1, 'name' => 'hassan', 'score' => 'A', 's' => '1'], + ['id' => 2, 'name' => 'hassan', 'score' => 'B', 's' => '2'], + ['id' => 3, 'name' => 'ahmed', 'score' => 'C', 's' => '1'], + ['id' => 4, 'name' => 'moustafa', 'score' => 'D', 's' => '2'], + ['id' => 5, 'name' => 'hassan', 'score' => 'A', 's' => '3'], + ['id' => 6, 'name' => 'wael', 'score' => 'A', 's' => '3'], + ['id' => 6, 'name' => 'wael', 'score' => 'D', 's' => '1'], +]; + +print_r(array_column($ar, null, 'name', true)); +?> +--EXPECT-- +Array +( + [hassan] => Array + ( + [0] => Array + ( + [id] => 1 + [name] => hassan + [score] => A + [s] => 1 + ) + + [1] => Array + ( + [id] => 2 + [name] => hassan + [score] => B + [s] => 2 + ) + + [2] => Array + ( + [id] => 5 + [name] => hassan + [score] => A + [s] => 3 + ) + + ) + + [ahmed] => Array + ( + [0] => Array + ( + [id] => 3 + [name] => ahmed + [score] => C + [s] => 1 + ) + + ) + + [moustafa] => Array + ( + [0] => Array + ( + [id] => 4 + [name] => moustafa + [score] => D + [s] => 2 + ) + + ) + + [wael] => Array + ( + [0] => Array + ( + [id] => 6 + [name] => wael + [score] => A + [s] => 3 + ) + + [1] => Array + ( + [id] => 6 + [name] => wael + [score] => D + [s] => 1 + ) + + ) + +) From f478cc9f589c6386d72e14263b3254599c05e0ea Mon Sep 17 00:00:00 2001 From: hassan Date: Tue, 30 Nov 2021 15:38:30 +0200 Subject: [PATCH 3/8] no need to update symtable --- ext/standard/array.c | 37 ++++++++++++------------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index ff6862401d850..ad064ff3a6733 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -4302,6 +4302,9 @@ PHP_FUNCTION(array_column) array_init_size(return_value, zend_hash_num_elements(input)); if (!group_is_null && group_bool && !index_is_null) { + zval *group_entry; + zval ft; + ZEND_HASH_FOREACH_VAL(input, data) { ZVAL_DEREF(data); @@ -4314,41 +4317,25 @@ PHP_FUNCTION(array_column) zval rv; zval *keyval = array_column_fetch_prop(data, index_str, index_long, cache_slot_index, &rv); - zval *group_entry; convert_to_string(keyval); group_entry = zend_symtable_find(Z_ARRVAL_P(return_value), Z_STR_P(keyval)); if (group_entry != NULL) { - if (Z_TYPE_P(colval) == IS_ARRAY) { - add_index_array(group_entry, Z_ARRVAL_P(group_entry)->nNumUsed, Z_ARRVAL_P(colval)); - } else if (Z_TYPE_P(colval) == IS_STRING) { - add_index_str(group_entry, Z_ARRVAL_P(group_entry)->nNumUsed, Z_STR_P(colval)); - } else { - add_index_long(group_entry, Z_ARRVAL_P(group_entry)->nNumUsed, Z_LVAL_P(colval)); - } - - array_set_zval_key(Z_ARRVAL_P(return_value), keyval, group_entry); - zval_ptr_dtor(colval); - zval_ptr_dtor(keyval); + ZVAL_COPY_VALUE(&ft, group_entry); } else { - zval ft; - array_init_size(&ft, 1); - if (Z_TYPE_P(colval) == IS_ARRAY) { - add_index_array(&ft, Z_ARRVAL_P(&ft)->nNumUsed, Z_ARRVAL_P(colval)); - } else if (Z_TYPE_P(colval) == IS_STRING) { - add_index_str(&ft, Z_ARRVAL_P(&ft)->nNumUsed, Z_STR_P(colval)); - } else { - add_index_long(&ft, Z_ARRVAL_P(&ft)->nNumUsed, Z_LVAL_P(colval)); - } - array_set_zval_key(Z_ARRVAL_P(return_value), keyval, &ft); - ZVAL_UNDEF(&ft); - zval_ptr_dtor(&ft); - zval_ptr_dtor(colval); + array_init(&ft); + zend_symtable_update(Z_ARRVAL_P(return_value), Z_STR_P(keyval), &ft); + } + + zend_hash_next_index_insert_new(Z_ARRVAL_P(&ft), colval); + + if (keyval) { zval_ptr_dtor(keyval); } } ZEND_HASH_FOREACH_END(); + } else { /* Index param is not passed */ if (index_is_null) { From 0ca49e9976a504e43c833ac6c2dc9c3afdeb63ed Mon Sep 17 00:00:00 2001 From: hassan Date: Wed, 1 Dec 2021 13:07:49 +0200 Subject: [PATCH 4/8] revoke and simplifying the grouping logic --- ext/standard/array.c | 30 +-- .../tests/array/array_column_group_001.phpt | 182 ++++++++++-------- 2 files changed, 117 insertions(+), 95 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index ad064ff3a6733..585667b448cf6 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -4303,7 +4303,7 @@ PHP_FUNCTION(array_column) if (!group_is_null && group_bool && !index_is_null) { zval *group_entry; - zval ft; + zval fpal; ZEND_HASH_FOREACH_VAL(input, data) { ZVAL_DEREF(data); @@ -4318,22 +4318,30 @@ PHP_FUNCTION(array_column) zval rv; zval *keyval = array_column_fetch_prop(data, index_str, index_long, cache_slot_index, &rv); - convert_to_string(keyval); - group_entry = zend_symtable_find(Z_ARRVAL_P(return_value), Z_STR_P(keyval)); + if (keyval) { - if (group_entry != NULL) { - ZVAL_COPY_VALUE(&ft, group_entry); - } else { - array_init(&ft); - zend_symtable_update(Z_ARRVAL_P(return_value), Z_STR_P(keyval), &ft); - } + if (Z_TYPE_P(keyval) == IS_LONG) { + group_entry = zend_hash_index_find(Z_ARRVAL_P(return_value), Z_LVAL_P(keyval)); + } else { + group_entry = zend_symtable_find(Z_ARRVAL_P(return_value), Z_STR_P(keyval)); + } - zend_hash_next_index_insert_new(Z_ARRVAL_P(&ft), colval); + if (group_entry != NULL) { + ZVAL_COPY_VALUE(&fpal, group_entry); + } else { + array_init(&fpal); + array_set_zval_key(Z_ARRVAL_P(return_value), keyval, &fpal); + zval_ptr_dtor(&fpal); + } + + zend_hash_next_index_insert_new(Z_ARRVAL_P(&fpal), colval); - if (keyval) { zval_ptr_dtor(keyval); + } else { + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), colval); } + } ZEND_HASH_FOREACH_END(); } else { diff --git a/ext/standard/tests/array/array_column_group_001.phpt b/ext/standard/tests/array/array_column_group_001.phpt index 951579b5a628c..729d00a11936b 100644 --- a/ext/standard/tests/array/array_column_group_001.phpt +++ b/ext/standard/tests/array/array_column_group_001.phpt @@ -12,89 +12,103 @@ $ar = [ ['id' => 6, 'name' => 'wael', 'score' => 'D', 's' => '1'], ]; -print_r(array_column($ar, null, 'id', true)); +var_dump(array_column($ar, null, 'id', true)); ?> --EXPECT-- -Array -( - [1] => Array - ( - [0] => Array - ( - [id] => 1 - [name] => hassan - [score] => A - [s] => 1 - ) - - ) - - [2] => Array - ( - [0] => Array - ( - [id] => 2 - [name] => hassan - [score] => B - [s] => 2 - ) - - ) - - [3] => Array - ( - [0] => Array - ( - [id] => 3 - [name] => ahmed - [score] => C - [s] => 1 - ) - - ) - - [4] => Array - ( - [0] => Array - ( - [id] => 4 - [name] => moustafa - [score] => D - [s] => 2 - ) - - ) - - [5] => Array - ( - [0] => Array - ( - [id] => 5 - [name] => hassan - [score] => A - [s] => 3 - ) - - ) - - [6] => Array - ( - [0] => Array - ( - [id] => 6 - [name] => wael - [score] => A - [s] => 3 - ) - - [1] => Array - ( - [id] => 6 - [name] => wael - [score] => D - [s] => 1 - ) - - ) - -) +array(6) { + [1]=> + array(1) { + [0]=> + array(4) { + ["id"]=> + int(1) + ["name"]=> + string(6) "hassan" + ["score"]=> + string(1) "A" + ["s"]=> + string(1) "1" + } + } + [2]=> + array(1) { + [0]=> + array(4) { + ["id"]=> + int(2) + ["name"]=> + string(6) "hassan" + ["score"]=> + string(1) "B" + ["s"]=> + string(1) "2" + } + } + [3]=> + array(1) { + [0]=> + array(4) { + ["id"]=> + int(3) + ["name"]=> + string(5) "ahmed" + ["score"]=> + string(1) "C" + ["s"]=> + string(1) "1" + } + } + [4]=> + array(1) { + [0]=> + array(4) { + ["id"]=> + int(4) + ["name"]=> + string(8) "moustafa" + ["score"]=> + string(1) "D" + ["s"]=> + string(1) "2" + } + } + [5]=> + array(1) { + [0]=> + array(4) { + ["id"]=> + int(5) + ["name"]=> + string(6) "hassan" + ["score"]=> + string(1) "A" + ["s"]=> + string(1) "3" + } + } + [6]=> + array(2) { + [0]=> + array(4) { + ["id"]=> + int(6) + ["name"]=> + string(4) "wael" + ["score"]=> + string(1) "A" + ["s"]=> + string(1) "3" + } + [1]=> + array(4) { + ["id"]=> + int(6) + ["name"]=> + string(4) "wael" + ["score"]=> + string(1) "D" + ["s"]=> + string(1) "1" + } + } +} \ No newline at end of file From c24f0114d1d2324bc85974c45ecaef6d1b576260 Mon Sep 17 00:00:00 2001 From: hassan Date: Mon, 6 Dec 2021 22:11:44 +0200 Subject: [PATCH 5/8] separate in a new function --- ext/standard/array.c | 138 ++++++++++++++----------- ext/standard/basic_functions_arginfo.h | 9 +- 2 files changed, 87 insertions(+), 60 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 585667b448cf6..b803e46b542f3 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -4300,11 +4300,22 @@ PHP_FUNCTION(array_column) void* cache_slot_index[3] = { NULL, NULL, NULL }; array_init_size(return_value, zend_hash_num_elements(input)); - if (!group_is_null && group_bool && !index_is_null) { - - zval *group_entry; - zval fpal; - + /* Index param is not passed */ + if (index_is_null) { + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { + ZEND_HASH_FOREACH_VAL(input, data) { + ZVAL_DEREF(data); + if (column_is_null) { + Z_TRY_ADDREF_P(data); + colval = data; + } else if ((colval = array_column_fetch_prop(data, column_str, column_long, cache_slot_column, &rv)) == NULL) { + continue; + } + ZEND_HASH_FILL_ADD(colval); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FILL_END(); + } else { ZEND_HASH_FOREACH_VAL(input, data) { ZVAL_DEREF(data); @@ -4317,72 +4328,81 @@ PHP_FUNCTION(array_column) zval rv; zval *keyval = array_column_fetch_prop(data, index_str, index_long, cache_slot_index, &rv); - if (keyval) { + array_set_zval_key(Z_ARRVAL_P(return_value), keyval, colval); + zval_ptr_dtor(colval); + zval_ptr_dtor(keyval); + } else { + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), colval); + } + } ZEND_HASH_FOREACH_END(); + } +} +/* }}} */ - if (Z_TYPE_P(keyval) == IS_LONG) { - group_entry = zend_hash_index_find(Z_ARRVAL_P(return_value), Z_LVAL_P(keyval)); - } else { - group_entry = zend_symtable_find(Z_ARRVAL_P(return_value), Z_STR_P(keyval)); - } +/* {{{ Return all the values from a single column in the input array, identified by the + value_key and optionally indexed by the index_key in an indexed array */ +PHP_FUNCTION(array_column_group) +{ + HashTable *input; + zval *colval, *data, rv; + zend_string *column_str = NULL; + zend_long column_long; + bool column_is_null = 0; + zend_string *index_str = NULL; + zend_long index_long; + bool index_is_null = 1; - if (group_entry != NULL) { - ZVAL_COPY_VALUE(&fpal, group_entry); - } else { - array_init(&fpal); - array_set_zval_key(Z_ARRVAL_P(return_value), keyval, &fpal); - zval_ptr_dtor(&fpal); - } + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_ARRAY_HT(input) + Z_PARAM_STR_OR_LONG_OR_NULL(column_str, column_long, column_is_null) + Z_PARAM_OPTIONAL + Z_PARAM_STR_OR_LONG_OR_NULL(index_str, index_long, index_is_null) + ZEND_PARSE_PARAMETERS_END(); + + void* cache_slot_column[3] = { NULL, NULL, NULL }; + void* cache_slot_index[3] = { NULL, NULL, NULL }; - zend_hash_next_index_insert_new(Z_ARRVAL_P(&fpal), colval); + zval *group_entry; + zval fpal; - zval_ptr_dtor(keyval); + array_init_size(return_value, zend_hash_num_elements(input)); + ZEND_HASH_FOREACH_VAL(input, data) { + ZVAL_DEREF(data); + + if (column_is_null) { + Z_TRY_ADDREF_P(data); + colval = data; + } else if ((colval = array_column_fetch_prop(data, column_str, column_long, cache_slot_column, &rv)) == NULL) { + continue; + } + + zval rv; + zval *keyval = array_column_fetch_prop(data, index_str, index_long, cache_slot_index, &rv); + + if (keyval) { + + if (Z_TYPE_P(keyval) == IS_LONG) { + group_entry = zend_hash_index_find(Z_ARRVAL_P(return_value), Z_LVAL_P(keyval)); } else { - zend_hash_next_index_insert(Z_ARRVAL_P(return_value), colval); + group_entry = zend_symtable_find(Z_ARRVAL_P(return_value), Z_STR_P(keyval)); } + if (group_entry != NULL) { + ZVAL_COPY_VALUE(&fpal, group_entry); + } else { + array_init(&fpal); + array_set_zval_key(Z_ARRVAL_P(return_value), keyval, &fpal); + zval_ptr_dtor(&fpal); + } - } ZEND_HASH_FOREACH_END(); + zend_hash_next_index_insert_new(Z_ARRVAL_P(&fpal), colval); - } else { - /* Index param is not passed */ - if (index_is_null) { - zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); - ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { - ZEND_HASH_FOREACH_VAL(input, data) { - ZVAL_DEREF(data); - if (column_is_null) { - Z_TRY_ADDREF_P(data); - colval = data; - } else if ((colval = array_column_fetch_prop(data, column_str, column_long, cache_slot_column, &rv)) == NULL) { - continue; - } - ZEND_HASH_FILL_ADD(colval); - } ZEND_HASH_FOREACH_END(); - } ZEND_HASH_FILL_END(); + zval_ptr_dtor(keyval); } else { - ZEND_HASH_FOREACH_VAL(input, data) { - ZVAL_DEREF(data); - - if (column_is_null) { - Z_TRY_ADDREF_P(data); - colval = data; - } else if ((colval = array_column_fetch_prop(data, column_str, column_long, cache_slot_column, &rv)) == NULL) { - continue; - } - - zval rv; - zval *keyval = array_column_fetch_prop(data, index_str, index_long, cache_slot_index, &rv); - if (keyval) { - array_set_zval_key(Z_ARRVAL_P(return_value), keyval, colval); - zval_ptr_dtor(colval); - zval_ptr_dtor(keyval); - } else { - zend_hash_next_index_insert(Z_ARRVAL_P(return_value), colval); - } - } ZEND_HASH_FOREACH_END(); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), colval); } - } + } ZEND_HASH_FOREACH_END(); } /* }}} */ diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index 47937706d69f6..cffc57dcb5c0a 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -245,7 +245,12 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_column, 0, 2, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO(0, array, IS_ARRAY, 0) ZEND_ARG_TYPE_MASK(0, column_key, MAY_BE_LONG|MAY_BE_STRING|MAY_BE_NULL, NULL) ZEND_ARG_TYPE_MASK(0, index_key, MAY_BE_LONG|MAY_BE_STRING|MAY_BE_NULL, "null") - ZEND_ARG_TYPE_MASK(0, group_key, MAY_BE_BOOL|MAY_BE_NULL, "null") +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_column_group, 0, 2, IS_ARRAY, 0) + ZEND_ARG_TYPE_INFO(0, array, IS_ARRAY, 0) + ZEND_ARG_TYPE_MASK(0, column_key, MAY_BE_LONG|MAY_BE_STRING|MAY_BE_NULL, NULL) + ZEND_ARG_TYPE_MASK(0, index_key, MAY_BE_LONG|MAY_BE_STRING|MAY_BE_NULL, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_reverse, 0, 1, IS_ARRAY, 0) @@ -2288,6 +2293,7 @@ ZEND_FUNCTION(array_key_last); ZEND_FUNCTION(array_values); ZEND_FUNCTION(array_count_values); ZEND_FUNCTION(array_column); +ZEND_FUNCTION(array_column_group); ZEND_FUNCTION(array_reverse); ZEND_FUNCTION(array_pad); ZEND_FUNCTION(array_flip); @@ -2916,6 +2922,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(array_values, arginfo_array_values) ZEND_FE(array_count_values, arginfo_array_count_values) ZEND_FE(array_column, arginfo_array_column) + ZEND_FE(array_column_group, arginfo_array_column_group) ZEND_FE(array_reverse, arginfo_array_reverse) ZEND_FE(array_pad, arginfo_array_pad) ZEND_FE(array_flip, arginfo_array_flip) From 933b81d666f1e787fe82ac0da98489fb5ef60523 Mon Sep 17 00:00:00 2001 From: hassan Date: Mon, 6 Dec 2021 22:12:02 +0200 Subject: [PATCH 6/8] update the test cases --- ext/standard/tests/array/array_column_group_001.phpt | 2 +- ext/standard/tests/array/array_column_group_002.phpt | 2 +- ext/standard/tests/array/array_column_group_003.phpt | 2 +- ext/standard/tests/array/array_column_group_004.phpt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/standard/tests/array/array_column_group_001.phpt b/ext/standard/tests/array/array_column_group_001.phpt index 729d00a11936b..85fe9de0949c0 100644 --- a/ext/standard/tests/array/array_column_group_001.phpt +++ b/ext/standard/tests/array/array_column_group_001.phpt @@ -12,7 +12,7 @@ $ar = [ ['id' => 6, 'name' => 'wael', 'score' => 'D', 's' => '1'], ]; -var_dump(array_column($ar, null, 'id', true)); +var_dump(array_column_group($ar, null, 'id')); ?> --EXPECT-- array(6) { diff --git a/ext/standard/tests/array/array_column_group_002.phpt b/ext/standard/tests/array/array_column_group_002.phpt index 6af9dcae2470e..f9b8fbad69fba 100644 --- a/ext/standard/tests/array/array_column_group_002.phpt +++ b/ext/standard/tests/array/array_column_group_002.phpt @@ -13,7 +13,7 @@ $ar = [ ['id' => 6, 'name' => 'wael', 'score' => 'D', 's' => '1'], ]; -print_r(array_column($ar, 'name', 'score', true)); +print_r(array_column_group($ar, 'name', 'score')); ?> --EXPECT-- diff --git a/ext/standard/tests/array/array_column_group_003.phpt b/ext/standard/tests/array/array_column_group_003.phpt index 970efba01ff3b..0379f892e02b5 100644 --- a/ext/standard/tests/array/array_column_group_003.phpt +++ b/ext/standard/tests/array/array_column_group_003.phpt @@ -11,7 +11,7 @@ $ar = [ ['id' => 6, 'name' => 'wael', 'score' => 'A', 's' => '3'], ['id' => 6, 'name' => 'wael', 'score' => 'D', 's' => '1'], ]; -print_r(array_column($ar, 'score', 's', true)); +print_r(array_column_group($ar, 'score', 's')); ?> --EXPECT-- Array diff --git a/ext/standard/tests/array/array_column_group_004.phpt b/ext/standard/tests/array/array_column_group_004.phpt index d40c58cdb89e1..4bc29d1c20b3e 100644 --- a/ext/standard/tests/array/array_column_group_004.phpt +++ b/ext/standard/tests/array/array_column_group_004.phpt @@ -12,7 +12,7 @@ $ar = [ ['id' => 6, 'name' => 'wael', 'score' => 'D', 's' => '1'], ]; -print_r(array_column($ar, null, 'name', true)); +print_r(array_column_group($ar, null, 'name')); ?> --EXPECT-- Array From 502787c37e89fba3ecae8e30cf16896b9829bff5 Mon Sep 17 00:00:00 2001 From: hassan Date: Sun, 12 Dec 2021 13:50:44 +0200 Subject: [PATCH 7/8] update function signature --- ext/standard/array.c | 2 +- ext/standard/basic_functions_arginfo.h | 6 +++--- ext/standard/tests/array/array_column_group_001.phpt | 2 +- ext/standard/tests/array/array_column_group_002.phpt | 2 +- ext/standard/tests/array/array_column_group_003.phpt | 2 +- ext/standard/tests/array/array_column_group_004.phpt | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index b803e46b542f3..de641d7cb001e 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -4342,7 +4342,7 @@ PHP_FUNCTION(array_column) /* {{{ Return all the values from a single column in the input array, identified by the value_key and optionally indexed by the index_key in an indexed array */ -PHP_FUNCTION(array_column_group) +PHP_FUNCTION(array_group) { HashTable *input; zval *colval, *data, rv; diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index cffc57dcb5c0a..1ae631f54fd23 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -247,7 +247,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_column, 0, 2, IS_ARRAY, 0) ZEND_ARG_TYPE_MASK(0, index_key, MAY_BE_LONG|MAY_BE_STRING|MAY_BE_NULL, "null") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_column_group, 0, 2, IS_ARRAY, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_group, 0, 2, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO(0, array, IS_ARRAY, 0) ZEND_ARG_TYPE_MASK(0, column_key, MAY_BE_LONG|MAY_BE_STRING|MAY_BE_NULL, NULL) ZEND_ARG_TYPE_MASK(0, index_key, MAY_BE_LONG|MAY_BE_STRING|MAY_BE_NULL, "null") @@ -2293,7 +2293,7 @@ ZEND_FUNCTION(array_key_last); ZEND_FUNCTION(array_values); ZEND_FUNCTION(array_count_values); ZEND_FUNCTION(array_column); -ZEND_FUNCTION(array_column_group); +ZEND_FUNCTION(array_group); ZEND_FUNCTION(array_reverse); ZEND_FUNCTION(array_pad); ZEND_FUNCTION(array_flip); @@ -2922,7 +2922,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(array_values, arginfo_array_values) ZEND_FE(array_count_values, arginfo_array_count_values) ZEND_FE(array_column, arginfo_array_column) - ZEND_FE(array_column_group, arginfo_array_column_group) + ZEND_FE(array_group, arginfo_array_group) ZEND_FE(array_reverse, arginfo_array_reverse) ZEND_FE(array_pad, arginfo_array_pad) ZEND_FE(array_flip, arginfo_array_flip) diff --git a/ext/standard/tests/array/array_column_group_001.phpt b/ext/standard/tests/array/array_column_group_001.phpt index 85fe9de0949c0..7cf539d078483 100644 --- a/ext/standard/tests/array/array_column_group_001.phpt +++ b/ext/standard/tests/array/array_column_group_001.phpt @@ -12,7 +12,7 @@ $ar = [ ['id' => 6, 'name' => 'wael', 'score' => 'D', 's' => '1'], ]; -var_dump(array_column_group($ar, null, 'id')); +var_dump(array_group($ar, null, 'id')); ?> --EXPECT-- array(6) { diff --git a/ext/standard/tests/array/array_column_group_002.phpt b/ext/standard/tests/array/array_column_group_002.phpt index f9b8fbad69fba..9495c24b5d841 100644 --- a/ext/standard/tests/array/array_column_group_002.phpt +++ b/ext/standard/tests/array/array_column_group_002.phpt @@ -13,7 +13,7 @@ $ar = [ ['id' => 6, 'name' => 'wael', 'score' => 'D', 's' => '1'], ]; -print_r(array_column_group($ar, 'name', 'score')); +print_r(array_group($ar, 'name', 'score')); ?> --EXPECT-- diff --git a/ext/standard/tests/array/array_column_group_003.phpt b/ext/standard/tests/array/array_column_group_003.phpt index 0379f892e02b5..aa81952621912 100644 --- a/ext/standard/tests/array/array_column_group_003.phpt +++ b/ext/standard/tests/array/array_column_group_003.phpt @@ -11,7 +11,7 @@ $ar = [ ['id' => 6, 'name' => 'wael', 'score' => 'A', 's' => '3'], ['id' => 6, 'name' => 'wael', 'score' => 'D', 's' => '1'], ]; -print_r(array_column_group($ar, 'score', 's')); +print_r(array_group($ar, 'score', 's')); ?> --EXPECT-- Array diff --git a/ext/standard/tests/array/array_column_group_004.phpt b/ext/standard/tests/array/array_column_group_004.phpt index 4bc29d1c20b3e..3d646779b7a8e 100644 --- a/ext/standard/tests/array/array_column_group_004.phpt +++ b/ext/standard/tests/array/array_column_group_004.phpt @@ -12,7 +12,7 @@ $ar = [ ['id' => 6, 'name' => 'wael', 'score' => 'D', 's' => '1'], ]; -print_r(array_column_group($ar, null, 'name')); +print_r(array_group($ar, null, 'name')); ?> --EXPECT-- Array From 9deac57e1602beabe56120209aba30c621c44e26 Mon Sep 17 00:00:00 2001 From: hassan Date: Sun, 12 Dec 2021 13:59:31 +0200 Subject: [PATCH 8/8] rename test cases and rewind array_column changes --- ext/standard/array.c | 5 +---- .../{array_column_group_001.phpt => array_group_001.phpt} | 0 .../{array_column_group_002.phpt => array_group_002.phpt} | 0 .../{array_column_group_003.phpt => array_group_003.phpt} | 0 .../{array_column_group_004.phpt => array_group_004.phpt} | 0 5 files changed, 1 insertion(+), 4 deletions(-) rename ext/standard/tests/array/{array_column_group_001.phpt => array_group_001.phpt} (100%) rename ext/standard/tests/array/{array_column_group_002.phpt => array_group_002.phpt} (100%) rename ext/standard/tests/array/{array_column_group_003.phpt => array_group_003.phpt} (100%) rename ext/standard/tests/array/{array_column_group_004.phpt => array_group_004.phpt} (100%) diff --git a/ext/standard/array.c b/ext/standard/array.c index de641d7cb001e..f3a0695ee0945 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -4285,15 +4285,12 @@ PHP_FUNCTION(array_column) zend_string *index_str = NULL; zend_long index_long; bool index_is_null = 1; - bool group_bool = 0; - bool group_is_null = 1; - ZEND_PARSE_PARAMETERS_START(2, 4) + ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_ARRAY_HT(input) Z_PARAM_STR_OR_LONG_OR_NULL(column_str, column_long, column_is_null) Z_PARAM_OPTIONAL Z_PARAM_STR_OR_LONG_OR_NULL(index_str, index_long, index_is_null) - Z_PARAM_BOOL_OR_NULL(group_bool, group_is_null) ZEND_PARSE_PARAMETERS_END(); void* cache_slot_column[3] = { NULL, NULL, NULL }; diff --git a/ext/standard/tests/array/array_column_group_001.phpt b/ext/standard/tests/array/array_group_001.phpt similarity index 100% rename from ext/standard/tests/array/array_column_group_001.phpt rename to ext/standard/tests/array/array_group_001.phpt diff --git a/ext/standard/tests/array/array_column_group_002.phpt b/ext/standard/tests/array/array_group_002.phpt similarity index 100% rename from ext/standard/tests/array/array_column_group_002.phpt rename to ext/standard/tests/array/array_group_002.phpt diff --git a/ext/standard/tests/array/array_column_group_003.phpt b/ext/standard/tests/array/array_group_003.phpt similarity index 100% rename from ext/standard/tests/array/array_column_group_003.phpt rename to ext/standard/tests/array/array_group_003.phpt diff --git a/ext/standard/tests/array/array_column_group_004.phpt b/ext/standard/tests/array/array_group_004.phpt similarity index 100% rename from ext/standard/tests/array/array_column_group_004.phpt rename to ext/standard/tests/array/array_group_004.phpt