Skip to content

Commit 4435823

Browse files
committed
Start aligning array_(sum|product)() behaviour with binary ops
1 parent ccec410 commit 4435823

File tree

3 files changed

+68
-35
lines changed

3 files changed

+68
-35
lines changed

ext/standard/array.c

Lines changed: 66 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5905,62 +5905,95 @@ PHP_FUNCTION(array_rand)
59055905
/* {{{ Returns the sum of the array entries */
59065906
PHP_FUNCTION(array_sum)
59075907
{
5908-
zval *input,
5909-
*entry,
5910-
entry_n;
5908+
HashTable *input;
5909+
zval *entry;
59115910

59125911
ZEND_PARSE_PARAMETERS_START(1, 1)
5913-
Z_PARAM_ARRAY(input)
5912+
Z_PARAM_ARRAY_HT(input)
59145913
ZEND_PARSE_PARAMETERS_END();
59155914

5916-
ZVAL_LONG(return_value, 0);
5915+
if (zend_hash_num_elements(input) == 0) {
5916+
// TODO Deprecate empty array
5917+
RETURN_LONG(0);
5918+
}
59175919

5918-
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(input), entry) {
5919-
if (Z_TYPE_P(entry) == IS_ARRAY || Z_TYPE_P(entry) == IS_OBJECT) {
5920-
continue;
5920+
ZVAL_LONG(return_value, 0);
5921+
ZEND_HASH_FOREACH_VAL(input, entry) {
5922+
zend_result status = add_function(return_value, return_value, entry);
5923+
if (status == FAILURE) {
5924+
ZEND_ASSERT(EG(exception));
5925+
zend_clear_exception();
5926+
/* BC resources: previously resources were cast to int */
5927+
if (Z_TYPE_P(entry) == IS_RESOURCE) {
5928+
zval tmp;
5929+
ZVAL_LONG(&tmp, Z_RES_HANDLE_P(entry));
5930+
add_function(return_value, return_value, &tmp);
5931+
}
5932+
/* BC non numeric strings: previously were cast to 0 */
5933+
if (Z_TYPE_P(entry) == IS_STRING) {
5934+
zval tmp;
5935+
ZVAL_LONG(&tmp, 0);
5936+
add_function(return_value, return_value, &tmp);
5937+
}
5938+
// TODO Warning/Deprecation?
59215939
}
5922-
ZVAL_COPY(&entry_n, entry);
5923-
convert_scalar_to_number(&entry_n);
5924-
fast_add_function(return_value, return_value, &entry_n);
59255940
} ZEND_HASH_FOREACH_END();
5941+
5942+
/* Traversal of array encountered a numerically catable object */
5943+
if (Z_TYPE_P(return_value) == IS_OBJECT) {
5944+
/* First try to convert to int */
5945+
zval dst;
5946+
if (Z_OBJ_HT_P(return_value)->cast_object(Z_OBJ_P(return_value), &dst, IS_LONG) == SUCCESS) {
5947+
zval_ptr_dtor(return_value);
5948+
RETURN_COPY(&dst);
5949+
}
5950+
convert_scalar_to_number(return_value);
5951+
}
59265952
}
59275953
/* }}} */
59285954

59295955
/* {{{ Returns the product of the array entries */
59305956
PHP_FUNCTION(array_product)
59315957
{
5932-
zval *input,
5933-
*entry,
5934-
entry_n;
5935-
double dval;
5958+
HashTable *input;
5959+
zval *entry;
59365960

59375961
ZEND_PARSE_PARAMETERS_START(1, 1)
5938-
Z_PARAM_ARRAY(input)
5962+
Z_PARAM_ARRAY_HT(input)
59395963
ZEND_PARSE_PARAMETERS_END();
59405964

5941-
ZVAL_LONG(return_value, 1);
5942-
if (!zend_hash_num_elements(Z_ARRVAL_P(input))) {
5943-
return;
5965+
if (zend_hash_num_elements(input) == 0) {
5966+
// TODO Deprecate empty array
5967+
RETURN_LONG(1);
59445968
}
59455969

5946-
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(input), entry) {
5947-
if (Z_TYPE_P(entry) == IS_ARRAY || Z_TYPE_P(entry) == IS_OBJECT) {
5948-
continue;
5949-
}
5950-
ZVAL_COPY(&entry_n, entry);
5951-
convert_scalar_to_number(&entry_n);
5970+
ZVAL_LONG(return_value, 1);
59525971

5953-
if (Z_TYPE(entry_n) == IS_LONG && Z_TYPE_P(return_value) == IS_LONG) {
5954-
dval = (double)Z_LVAL_P(return_value) * (double)Z_LVAL(entry_n);
5955-
if ( (double)ZEND_LONG_MIN <= dval && dval <= (double)ZEND_LONG_MAX ) {
5956-
Z_LVAL_P(return_value) *= Z_LVAL(entry_n);
5957-
continue;
5972+
ZEND_HASH_FOREACH_VAL(input, entry) {
5973+
zend_result status = mul_function(return_value, return_value, entry);
5974+
if (status == FAILURE) {
5975+
ZEND_ASSERT(EG(exception));
5976+
zend_clear_exception();
5977+
/* BC resources: previously resources were cast to int */
5978+
if (Z_TYPE_P(entry) == IS_RESOURCE) {
5979+
zval tmp;
5980+
ZVAL_LONG(&tmp, Z_RES_HANDLE_P(entry));
5981+
mul_function(return_value, return_value, &tmp);
59585982
}
5983+
/* BC non numeric strings: previously were cast to 0 */
5984+
if (Z_TYPE_P(entry) == IS_STRING) {
5985+
zval tmp;
5986+
ZVAL_LONG(&tmp, 0);
5987+
mul_function(return_value, return_value, &tmp);
5988+
}
5989+
// TODO Warning/Deprecation?
59595990
}
5960-
convert_to_double(return_value);
5961-
convert_to_double(&entry_n);
5962-
Z_DVAL_P(return_value) *= Z_DVAL(entry_n);
59635991
} ZEND_HASH_FOREACH_END();
5992+
5993+
/* Traversal of array encountered a numerically castable object */
5994+
if (Z_TYPE_P(return_value) == IS_OBJECT) {
5995+
convert_scalar_to_number(return_value);
5996+
}
59645997
}
59655998
/* }}} */
59665999

ext/standard/tests/array/array_product_variation6.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ $input = [gmp_init(25), gmp_init(6)];
88
var_dump(array_product($input));
99
?>
1010
--EXPECT--
11-
int(1)
11+
int(150)

ext/standard/tests/array/array_sum_variation9.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ $input = [gmp_init(25), gmp_init(6)];
88
var_dump(array_sum($input));
99
?>
1010
--EXPECT--
11-
int(0)
11+
int(31)

0 commit comments

Comments
 (0)