Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 18 additions & 7 deletions ext/standard/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -2377,7 +2377,7 @@ PHP_FUNCTION(array_unshift)
Z_ARRVAL_P(stack)->arData = new_hash.arData;
Z_ARRVAL_P(stack)->arHash = new_hash.arHash;
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 */
Expand Down Expand Up @@ -3650,7 +3650,7 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int
ZVAL_UNDEF(&list->val);
if (hash->nNumOfElements > 1) {
if (behavior == INTERSECT_NORMAL) {
zend_sort((void *) lists[i], hash->nNumOfElements,
zend_sort((void *) lists[i], hash->nNumOfElements,
sizeof(Bucket), intersect_data_compare_func, (swap_func_t)zend_hash_bucket_swap);
} else if (behavior & INTERSECT_ASSOC) { /* triggered also when INTERSECT_KEY */
zend_sort((void *) lists[i], hash->nNumOfElements,
Expand Down Expand Up @@ -4677,15 +4677,18 @@ PHP_FUNCTION(array_product)
PHP_FUNCTION(array_reduce)
{
zval *input;
zval args[2];
zval *operand;
zval args[3];
zval result;
zval retval;
zend_fcall_info fci;
zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
zval *initial = NULL;
HashTable *htbl;

zend_ulong arr_num_key;
zend_string *arr_str_key;
zval *arr_val;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "af|z", &input, &fci, &fci_cache, &initial) == FAILURE) {
return;
}
Expand All @@ -4707,20 +4710,28 @@ PHP_FUNCTION(array_reduce)
}

fci.retval = &retval;
fci.param_count = 2;
fci.param_count = 3;
fci.no_separation = 0;

ZEND_HASH_FOREACH_VAL(htbl, operand) {
ZEND_HASH_FOREACH_KEY_VAL(htbl, arr_num_key, arr_str_key, arr_val) {
ZVAL_COPY(&args[0], &result);
ZVAL_COPY(&args[1], operand);
ZVAL_COPY(&args[1], arr_val);
if (arr_str_key == NULL) {
ZVAL_LONG(&args[2], arr_num_key);
} else {
ZVAL_STRINGL(&args[2], arr_str_key->val, arr_str_key->len);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And also ZVAL_STR(&args[2], zend_string_copy(arr_str_key));

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or ZVAL_STR_COPY(&args[2], arr_str_key).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, this is better

}

fci.params = args;

if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
zval_ptr_dtor(&args[2]);
zval_ptr_dtor(&args[1]);
zval_ptr_dtor(&args[0]);
zval_ptr_dtor(&result);
ZVAL_COPY_VALUE(&result, &retval);
} else {
zval_ptr_dtor(&args[2]);
zval_ptr_dtor(&args[1]);
zval_ptr_dtor(&args[0]);
return;
Expand Down
18 changes: 18 additions & 0 deletions ext/standard/tests/array/array_reduce.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ function reduce_null($w, $v) { return $w . $v; }
$initial = null;
var_dump(array_reduce($array, 'reduce_null', $initial), $initial);

echo "\n*** Testing array_reduce() to integer with integer array keys ***\n";
function reduce_integer_keys($w, $v, $k) { return $w * ($k + 1); }
$initial = 1;
var_dump(array_reduce($array, 'reduce_integer_keys', $initial), $initial);

echo "\n*** Testing array_reduce() to string with string array keys ***\n";
$stringKeyedArray = ['foo' => 1, 'bar' => 2, 'bas' => 3];
$initial = 'quux';
var_dump(array_reduce($stringKeyedArray, function ($w, $v, $k) { return $w . $k; }, $initial), $initial);

echo "\nDone";
?>
--EXPECTF--
Expand Down Expand Up @@ -76,4 +86,12 @@ array(4) {
string(19) "foofoobarquxquxquux"
NULL

*** Testing array_reduce() to integer with integer array keys ***
int(720)
int(1)

*** Testing array_reduce() to string with string array keys ***
string(13) "quuxfoobarbas"
string(4) "quux"

Done
30 changes: 20 additions & 10 deletions ext/standard/tests/array/array_reduce_variation1.phpt
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
--TEST--
Test array_reduce() function : variation
Test array_reduce() function : variation
--FILE--
<?php
/* Prototype : mixed array_reduce(array input, mixed callback [, int initial])
* Description: Iteratively reduce the array to a single value via the callback.
* Description: Iteratively reduce the array to a single value via the callback.
* Source code: ext/standard/array.c
* Alias to functions:
* Alias to functions:
*/

echo "*** Testing array_reduce() : variation ***\n";
Expand All @@ -15,30 +15,40 @@ function oneArg($v) {
return $v;
}

function threeArgs($v, $w, $x) {
return $v + $w + $x;
function twoArgs($v, $w) {
return $v + $w;
}

function fourArgs($v, $w, $x, $y) {
return $v + $w + $x + $y;
}

$array = array(1);

echo "\n--- Testing with a callback with too few parameters ---\n";
echo "\n--- Testing with a callback with one parameter ---\n";
var_dump(array_reduce($array, "oneArg", 2));

echo "\n--- Testing with a callback with two parameters ---\n";
var_dump(array_reduce($array, "twoArgs", 2));

echo "\n--- Testing with a callback with too many parameters ---\n";
var_dump(array_reduce($array, "threeArgs", 2));
var_dump(array_reduce($array, "fourArgs", 2));

?>
===DONE===
--EXPECTF--
*** Testing array_reduce() : variation ***

--- Testing with a callback with too few parameters ---
--- Testing with a callback with one parameter ---
int(2)

--- Testing with a callback with two parameters ---
int(3)

--- Testing with a callback with too many parameters ---

Warning: Missing argument 3 for threeArgs() in %sarray_reduce_variation1.php on line %d
Warning: Missing argument 4 for fourArgs() in %sarray_reduce_variation1.php on line %d

Notice: Undefined variable: x in %sarray_reduce_variation1.php on line %d
Notice: Undefined variable: y in %sarray_reduce_variation1.php on line %d
int(3)
===DONE===