From 283fdafd569deb29646eac08da6b03a03ad2ec3f Mon Sep 17 00:00:00 2001 From: CismonX Date: Tue, 1 May 2018 17:35:19 +0800 Subject: [PATCH] Add `maxBy()`, `minBy()`. Remove ZTS relevant code. --- src/collections.c | 13 +-------- src/collections_methods.c | 61 ++++++++++++++++++++++++++++++++++----- src/php_collections.h | 8 ----- tests/028-min-max-by.phpt | 22 ++++++++++++++ 4 files changed, 76 insertions(+), 28 deletions(-) create mode 100644 tests/028-min-max-by.phpt diff --git a/src/collections.c b/src/collections.c index 561275e..8ceee3e 100644 --- a/src/collections.c +++ b/src/collections.c @@ -46,14 +46,6 @@ PHP_MINIT_FUNCTION(collections) return SUCCESS; } -PHP_RINIT_FUNCTION(collections) -{ -#if defined(COMPILE_DL_COLLECTIONS) && defined(ZTS) - ZEND_TSRMLS_CACHE_UPDATE(); -#endif - return SUCCESS; -} - PHP_MINFO_FUNCTION(collections) { php_info_print_table_start(); @@ -67,7 +59,7 @@ zend_module_entry collections_module_entry = { NULL, PHP_MINIT(collections), NULL, - PHP_RINIT(collections), + NULL, NULL, PHP_MINFO(collections), PHP_COLLECTIONS_VERSION, @@ -75,8 +67,5 @@ zend_module_entry collections_module_entry = { }; #ifdef COMPILE_DL_COLLECTIONS -#ifdef ZTS -ZEND_TSRMLS_CACHE_DEFINE() -#endif ZEND_GET_MODULE(collections) #endif diff --git a/src/collections_methods.c b/src/collections_methods.c index 8aef7a8..6e29c31 100644 --- a/src/collections_methods.c +++ b/src/collections_methods.c @@ -113,6 +113,11 @@ /// Unused global variable. zval rv; +static zend_always_inline int bucket_compare_numeric(Bucket* op1, Bucket* op2) +{ + return numeric_compare_function(&op1->val, &op2->val); +} + int count_collection(zval* obj, zend_long* count) { zend_array* current = COLLECTION_FETCH(obj); @@ -963,15 +968,35 @@ PHP_METHOD(Collection, mapValuesTo) PHP_METHOD(Collection, max) { zend_array* current = COLLECTION_FETCH_CURRENT(); - zval* retval = zend_hash_minmax(current, numeric_compare_function, 1); - if (retval) - RETURN_ZVAL(retval, 0, 0); + zval* max = zend_hash_minmax(current, bucket_compare_numeric, 1); + if (max) + RETURN_ZVAL(max, 0, 0); RETVAL_NULL(); } PHP_METHOD(Collection, maxBy) { - + zend_fcall_info fci; + zend_fcall_info_cache fcc; + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_FUNC(fci, fcc) + ZEND_PARSE_PARAMETERS_END(); + zend_array* current = COLLECTION_FETCH_CURRENT(); + ARRAY_NEW_EX(max_by, current); + INIT_FCI(2); + ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket) + CALLBACK_KEYVAL_INVOKE(params, bucket); + zend_hash_index_add(max_by, bucket - current->arData, &retval); + ZEND_HASH_FOREACH_END(); + zval* max = zend_hash_minmax(max_by, bucket_compare_numeric, 1); + if (max) { + zend_ulong offset = *(zend_ulong*)(max + 1); + zval* ret = &(current->arData + offset)->val; + RETVAL_ZVAL(ret, 1, 0); + } else + RETVAL_NULL(); + zend_hash_destroy(max_by); + efree(max_by); } PHP_METHOD(Collection, maxWith) @@ -982,15 +1007,35 @@ PHP_METHOD(Collection, maxWith) PHP_METHOD(Collection, min) { zend_array* current = COLLECTION_FETCH_CURRENT(); - zval* retval = zend_hash_minmax(current, numeric_compare_function, 0); - if (retval) - RETURN_ZVAL(retval, 0, 0); + zval* min = zend_hash_minmax(current, bucket_compare_numeric, 0); + if (min) + RETURN_ZVAL(min, 0, 0); RETVAL_NULL(); } PHP_METHOD(Collection, minBy) { - + zend_fcall_info fci; + zend_fcall_info_cache fcc; + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_FUNC(fci, fcc) + ZEND_PARSE_PARAMETERS_END(); + zend_array* current = COLLECTION_FETCH_CURRENT(); + ARRAY_NEW_EX(min_by, current); + INIT_FCI(2); + ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket) + CALLBACK_KEYVAL_INVOKE(params, bucket); + zend_hash_index_add(min_by, bucket - current->arData, &retval); + ZEND_HASH_FOREACH_END(); + zval* min = zend_hash_minmax(min_by, bucket_compare_numeric, 0); + if (max) { + zend_ulong offset = *(zend_ulong*)(min + 1); + zval* ret = &(current->arData + offset)->val; + RETVAL_ZVAL(ret, 1, 0); + } else + RETVAL_NULL(); + zend_hash_destroy(min_by); + efree(min_by); } PHP_METHOD(Collection, minWith) diff --git a/src/php_collections.h b/src/php_collections.h index 049bcfa..2e17bc8 100644 --- a/src/php_collections.h +++ b/src/php_collections.h @@ -39,12 +39,4 @@ void collection_offset_unset(zval* object, zval* offset); extern const zend_function_entry collection_methods[]; extern const zend_function_entry pair_methods[]; -#ifdef ZTS -#include "TSRM.h" -#endif - -#if defined(ZTS) && defined(COMPILE_DL_COLLECTIONS) -ZEND_TSRMLS_CACHE_EXTERN() -#endif - #endif // !PHP_COLLECTIONS_FE_H diff --git a/tests/028-min-max-by.phpt b/tests/028-min-max-by.phpt new file mode 100644 index 0000000..474b122 --- /dev/null +++ b/tests/028-min-max-by.phpt @@ -0,0 +1,22 @@ +--TEST-- +Test Collection::minBy() and Collection::maxBy(). +--FILE-- +maxBy(function ($value) { + return $value[0]; +}); +if ($result != $array[1]) + echo 'Collection::maxBy() failed.', PHP_EOL; +$result = $collection->minBy(function ($value) { + return $value[2]; +}); +if ($result != $array[0]) + echo 'Collection::minBy() failed.', PHP_EOL; +?> +--EXPECT--