From e9e1c966d71a19430d2f1ec3c53571870d3cc55e Mon Sep 17 00:00:00 2001 From: CismonX Date: Sat, 18 Aug 2018 14:54:26 +0800 Subject: [PATCH] Add `sortWith()` and `sortedWith()`. --- src/collections_methods.c | 52 ++++++++++++++++++++++++++-- tests/043-min-max-with.phpt | 4 +-- tests/044-sort-with-sorted-with.phpt | 35 +++++++++++++++++++ 3 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 tests/044-sort-with-sorted-with.phpt diff --git a/src/collections_methods.c b/src/collections_methods.c index 47dd7b0..16e016c 100644 --- a/src/collections_methods.c +++ b/src/collections_methods.c @@ -2081,7 +2081,35 @@ PHP_METHOD(Collection, sortDescending) PHP_METHOD(Collection, sortWith) { - + zend_fcall_info fci; + zend_fcall_info_cache fcc; + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_FUNC(fci, fcc) + ZEND_PARSE_PARAMETERS_END(); + FCI_G = &fci; + FCC_G = &fcc; + zend_array* current = COLLECTION_FETCH_CURRENT(); + zend_array* sorted_with = zend_array_dup(current); + ZEND_HASH_FOREACH_BUCKET(sorted_with, Bucket* bucket) + NEW_PAIR_OBJ(obj); + BUCKET_2_PAIR(obj, bucket); + ZVAL_OBJ(&bucket->val, obj); + ZEND_HASH_FOREACH_END(); + zend_hash_sort(sorted_with, bucket_compare_userland, 1); + ZEND_HASH_FOREACH_VAL(sorted_with, zval* val) + zend_object* pair = Z_OBJ_P(val); + ZVAL_COPY_VALUE(val, PAIR_FETCH_SECOND(pair)); + GC_DELREF(pair); + ZEND_HASH_FOREACH_END(); + if (GC_REFCOUNT(current) > 1) + { + GC_DELREF(current); + } + else + { + zend_array_destroy(current); + } + COLLECTION_FETCH_CURRENT() = sorted_with; } PHP_METHOD(Collection, sorted) @@ -2106,7 +2134,27 @@ PHP_METHOD(Collection, sortedDescending) PHP_METHOD(Collection, sortedWith) { - + zend_fcall_info fci; + zend_fcall_info_cache fcc; + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_FUNC(fci, fcc) + ZEND_PARSE_PARAMETERS_END(); + FCI_G = &fci; + FCC_G = &fcc; + zend_array* current = COLLECTION_FETCH_CURRENT(); + zend_array* sorted_with = zend_array_dup(current); + ZEND_HASH_FOREACH_BUCKET(sorted_with, Bucket* bucket) + NEW_PAIR_OBJ(obj); + BUCKET_2_PAIR(obj, bucket); + ZVAL_OBJ(&bucket->val, obj); + ZEND_HASH_FOREACH_END(); + zend_hash_sort(sorted_with, bucket_compare_userland, 1); + ZEND_HASH_FOREACH_VAL(sorted_with, zval* val) + zend_object* pair = Z_OBJ_P(val); + ZVAL_COPY_VALUE(val, PAIR_FETCH_SECOND(pair)); + GC_DELREF(pair); + ZEND_HASH_FOREACH_END(); + RETVAL_NEW_COLLECTION(sorted_with); } PHP_METHOD(Collection, take) diff --git a/tests/043-min-max-with.phpt b/tests/043-min-max-with.phpt index c05bbaa..f8bc7c0 100644 --- a/tests/043-min-max-with.phpt +++ b/tests/043-min-max-with.phpt @@ -8,10 +8,10 @@ $array = [ 'e' => ['b' => 5, 'c' => 4] ]; $collection = Collection::init($array); -$by_b = function($p1, $p2) { +$by_b = function ($p1, $p2) { return $p1->second['b'] - $p2->second['b']; }; -$by_c = function($p1, $p2) { +$by_c = function ($p1, $p2) { return strval($p1->second['c'] - $p2->second['c']); }; if ($collection->minWith($by_b) != $array['a'] || $collection->minWith($by_c) != $array['d']) diff --git a/tests/044-sort-with-sorted-with.phpt b/tests/044-sort-with-sorted-with.phpt new file mode 100644 index 0000000..19e0bbd --- /dev/null +++ b/tests/044-sort-with-sorted-with.phpt @@ -0,0 +1,35 @@ +--TEST-- +Test Collection::sortWith() and Collection::sortedWith(). +--FILE-- + ['b' => 2, 'c' => 6], + 'd' => ['b' => 3, 'c' => 1], + 'e' => ['b' => 5, 'c' => 4], + 'f' => ['b' => 1, 'c' => 3] +]; +$collection = Collection::init($array); +$by_b = function ($p1, $p2) { + return $p1->second['b'] - $p2->second['b']; +}; +$usort_by_b = function ($v1, $v2) { + return $v1['b'] - $v2['b']; +}; +$sorted_by_b = $collection->sortedWith($by_b); +$array1 = $array; +usort($array1, $usort_by_b); +if ($sorted_by_b->toArray() != $array1) + echo 'Collection::sortedWith() failed.', PHP_EOL; +$by_c = function ($p1, $p2) { + return $p1->second['c'] - $p2->second['c']; +}; +$usort_by_c = function ($v1, $v2) { + return $v1['c'] - $v2['c']; +}; +$collection->sortWith($by_c); +$array2 = $array; +usort($array2, $usort_by_c); +if ($collection->toArray() != $array2) + echo 'Collection::sortedWith() failed.', PHP_EOL; +?> +--EXPECT--