From 8722173ad5d3132bfefbeb753c29e246876b0492 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Tue, 21 Aug 2012 13:32:15 +0800 Subject: [PATCH] Implemented FR #62840 (Add sort flag to ArrayObject::ksort) --- NEWS | 3 ++ ext/spl/spl_array.c | 46 ++++++++++++++------- ext/spl/tests/arrayObject_asort_basic1.phpt | 20 ++++++++- ext/spl/tests/arrayObject_ksort_basic1.phpt | 26 ++++++++++-- 4 files changed, 73 insertions(+), 22 deletions(-) diff --git a/NEWS b/NEWS index 27a34c3c68..d60f51b530 100644 --- a/NEWS +++ b/NEWS @@ -38,6 +38,9 @@ PHP NEWS . Fixed bug (segfault due to PS(mod_user_implemented) not be reseted when close handler call exit). (Laruence) +- SPL: + . Implemented FR #62840 (Add sort flag to ArrayObject::ksort). (Laruence) + - Standard: . Fixed bug #62836 (Seg fault or broken object references on unserialize()). (Laruence) diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index e2ea17a3fe..1e4577a3f9 100755 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -58,6 +58,10 @@ PHPAPI zend_class_entry *spl_ce_RecursiveArrayIterator; #define SPL_ARRAY_INT_MASK 0xFFFF0000 #define SPL_ARRAY_CLONE_MASK 0x0300FFFF +#define SPL_ARRAY_METHOD_NO_ARG 0 +#define SPL_ARRAY_METHOD_USE_ARG 1 +#define SPL_ARRAY_METHOD_MAY_USER_ARG 2 + typedef struct _spl_array_object { zend_object std; zval *array; @@ -1426,26 +1430,36 @@ static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, int fnam { spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(getThis() TSRMLS_CC); HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); - zval *tmp, *arg; + zval *tmp, *arg = NULL; zval *retval_ptr = NULL; MAKE_STD_ZVAL(tmp); Z_TYPE_P(tmp) = IS_ARRAY; Z_ARRVAL_P(tmp) = aht; - if (use_arg) { - if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg) == FAILURE) { + if (!use_arg) { + aht->nApplyCount++; + zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, 1, tmp, NULL TSRMLS_CC); + aht->nApplyCount--; + } else if (use_arg == SPL_ARRAY_METHOD_MAY_USER_ARG) { + if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "|z", &arg) == FAILURE) { Z_TYPE_P(tmp) = IS_NULL; zval_ptr_dtor(&tmp); - zend_throw_exception(spl_ce_BadMethodCallException, "Function expects exactly one argument", 0 TSRMLS_CC); + zend_throw_exception(spl_ce_BadMethodCallException, "Function expects one argument at most", 0 TSRMLS_CC); return; } aht->nApplyCount++; - zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, 2, tmp, arg TSRMLS_CC); + zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, arg? 2 : 1, tmp, arg TSRMLS_CC); aht->nApplyCount--; } else { + if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg) == FAILURE) { + Z_TYPE_P(tmp) = IS_NULL; + zval_ptr_dtor(&tmp); + zend_throw_exception(spl_ce_BadMethodCallException, "Function expects exactly one argument", 0 TSRMLS_CC); + return; + } aht->nApplyCount++; - zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, 1, tmp, NULL TSRMLS_CC); + zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, 2, tmp, arg TSRMLS_CC); aht->nApplyCount--; } Z_TYPE_P(tmp) = IS_NULL; /* we want to destroy the zval, not the hashtable */ @@ -1461,35 +1475,35 @@ SPL_METHOD(cname, fname) \ spl_array_method(INTERNAL_FUNCTION_PARAM_PASSTHRU, #fname, sizeof(#fname)-1, use_arg); \ } -/* {{{ proto int ArrayObject::asort() - proto int ArrayIterator::asort() +/* {{{ proto int ArrayObject::asort([int $sort_flags = SORT_REGULAR ]) + proto int ArrayIterator::asort([int $sort_flags = SORT_REGULAR ]) Sort the entries by values. */ -SPL_ARRAY_METHOD(Array, asort, 0) /* }}} */ +SPL_ARRAY_METHOD(Array, asort, SPL_ARRAY_METHOD_MAY_USER_ARG) /* }}} */ -/* {{{ proto int ArrayObject::ksort() - proto int ArrayIterator::ksort() +/* {{{ proto int ArrayObject::ksort([int $sort_flags = SORT_REGULAR ]) + proto int ArrayIterator::ksort([int $sort_flags = SORT_REGULAR ]) Sort the entries by key. */ -SPL_ARRAY_METHOD(Array, ksort, 0) /* }}} */ +SPL_ARRAY_METHOD(Array, ksort, SPL_ARRAY_METHOD_MAY_USER_ARG) /* }}} */ /* {{{ proto int ArrayObject::uasort(callback cmp_function) proto int ArrayIterator::uasort(callback cmp_function) Sort the entries by values user defined function. */ -SPL_ARRAY_METHOD(Array, uasort, 1) /* }}} */ +SPL_ARRAY_METHOD(Array, uasort, SPL_ARRAY_METHOD_USE_ARG) /* }}} */ /* {{{ proto int ArrayObject::uksort(callback cmp_function) proto int ArrayIterator::uksort(callback cmp_function) Sort the entries by key using user defined function. */ -SPL_ARRAY_METHOD(Array, uksort, 1) /* }}} */ +SPL_ARRAY_METHOD(Array, uksort, SPL_ARRAY_METHOD_USE_ARG) /* }}} */ /* {{{ proto int ArrayObject::natsort() proto int ArrayIterator::natsort() Sort the entries by values using "natural order" algorithm. */ -SPL_ARRAY_METHOD(Array, natsort, 0) /* }}} */ +SPL_ARRAY_METHOD(Array, natsort, SPL_ARRAY_METHOD_NO_ARG) /* }}} */ /* {{{ proto int ArrayObject::natcasesort() proto int ArrayIterator::natcasesort() Sort the entries by key using case insensitive "natural order" algorithm. */ -SPL_ARRAY_METHOD(Array, natcasesort, 0) /* }}} */ +SPL_ARRAY_METHOD(Array, natcasesort, SPL_ARRAY_METHOD_NO_ARG) /* }}} */ /* {{{ proto mixed|NULL ArrayIterator::current() Return current array entry */ diff --git a/ext/spl/tests/arrayObject_asort_basic1.phpt b/ext/spl/tests/arrayObject_asort_basic1.phpt index ec69049a32..53df1d502b 100644 --- a/ext/spl/tests/arrayObject_asort_basic1.phpt +++ b/ext/spl/tests/arrayObject_asort_basic1.phpt @@ -17,12 +17,14 @@ var_dump($ao1->asort()); var_dump($ao1); var_dump($ao2->asort('blah')); var_dump($ao2); +var_dump($ao2->asort(SORT_NUMERIC)); +var_dump($ao2); ?> ===DONE=== --EXPECTF-- *** Testing ArrayObject::asort() : basic functionality *** bool(true) -object(ArrayObject)#1 (1) { +object(ArrayObject)#%d (1) { ["storage":"ArrayObject":private]=> array(3) { [1]=> @@ -33,8 +35,22 @@ object(ArrayObject)#1 (1) { int(4) } } + +Warning: asort() expects parameter 2 to be long, string given in %sarrayObject_asort_basic1.php on line %d +bool(false) +object(ArrayObject)#%d (1) { + ["storage":"ArrayObject":private]=> + array(3) { + ["a"]=> + int(4) + ["b"]=> + int(2) + ["c"]=> + int(3) + } +} bool(true) -object(ArrayObject)#2 (1) { +object(ArrayObject)#%d (1) { ["storage":"ArrayObject":private]=> array(3) { ["b"]=> diff --git a/ext/spl/tests/arrayObject_ksort_basic1.phpt b/ext/spl/tests/arrayObject_ksort_basic1.phpt index 9c8d1e7345..8f37938126 100644 --- a/ext/spl/tests/arrayObject_ksort_basic1.phpt +++ b/ext/spl/tests/arrayObject_ksort_basic1.phpt @@ -16,12 +16,14 @@ var_dump($ao1->ksort()); var_dump($ao1); var_dump($ao2->ksort('blah')); var_dump($ao2); +var_dump($ao2->ksort(SORT_STRING)); +var_dump($ao2); ?> ===DONE=== --EXPECTF-- *** Testing ArrayObject::ksort() : basic functionality *** bool(true) -object(ArrayObject)#1 (1) { +object(ArrayObject)#%d (1) { ["storage":"ArrayObject":private]=> array(3) { [0]=> @@ -32,18 +34,34 @@ object(ArrayObject)#1 (1) { int(3) } } -bool(true) + +Warning: ksort() expects parameter 2 to be long, string given in %sarrayObject_ksort_basic1.php on line %d +bool(false) object(ArrayObject)#2 (1) { ["storage":"ArrayObject":private]=> array(4) { - ["a"]=> - int(2) ["b"]=> int(4) + ["a"]=> + int(2) ["q"]=> int(3) [99]=> string(1) "x" } } +bool(true) +object(ArrayObject)#%d (1) { + ["storage":"ArrayObject":private]=> + array(4) { + [99]=> + string(1) "x" + ["a"]=> + int(2) + ["b"]=> + int(4) + ["q"]=> + int(3) + } +} ===DONE=== -- 2.40.0