From 8d62f9a288decd136b04718541bab83aba596696 Mon Sep 17 00:00:00 2001 From: CismonX Date: Mon, 26 Mar 2018 19:58:40 +0800 Subject: [PATCH] Add `associateBy()` and `associateByTo()` --- src/collections_me.c | 2 +- src/collections_methods.c | 46 ++++++++++++++++++++++++++++++++-- tests/005-associate-to.phpt | 4 +-- tests/006-associate-by-to.phpt | 20 +++++++++++++++ 4 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 tests/006-associate-by-to.phpt diff --git a/src/collections_me.c b/src/collections_me.c index 034c5bd..ff45b20 100644 --- a/src/collections_me.c +++ b/src/collections_me.c @@ -130,7 +130,7 @@ const zend_function_entry collection_methods[] = { PHP_ME(Collection, associate, transform_arginfo, ZEND_ACC_PUBLIC) PHP_ME(Collection, associateTo, destination_transform_arginfo, ZEND_ACC_PUBLIC) PHP_ME(Collection, associateBy, associate_by_arginfo, ZEND_ACC_PUBLIC) - PHP_ME(Collection, associateByTo, associate_by_arginfo, ZEND_ACC_PUBLIC) + PHP_ME(Collection, associateByTo, associate_by_to_arginfo, ZEND_ACC_PUBLIC) PHP_ME(Collection, average, NULL, ZEND_ACC_PUBLIC) PHP_ME(Collection, containsAll, other_arginfo, ZEND_ACC_PUBLIC) PHP_ME(Collection, containsKey, key_arginfo, ZEND_ACC_PUBLIC) diff --git a/src/collections_methods.c b/src/collections_methods.c index efa633b..105b5e0 100644 --- a/src/collections_methods.c +++ b/src/collections_methods.c @@ -212,12 +212,54 @@ PHP_METHOD(Collection, associateTo) PHP_METHOD(Collection, associateBy) { - + zend_fcall_info fci; + zend_fcall_info_cache fcc; + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_FUNC(fci, fcc) + ZEND_PARSE_PARAMETERS_END(); + INIT_FCI(); + zval* current = COLLECTION_FETCH_EX(); + ARRAY_NEW_EX(new_collection, current); + ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(current), Bucket* bucket) + ZVAL_COPY_VALUE(¶ms[0], &bucket->val); + CALLBACK_PASS_PAIR(bucket); + zend_call_function(&fci, &fcc); + zval_ptr_dtor(¶ms[0]); + if (Z_TYPE(retval) == IS_LONG) + zend_hash_index_add(new_collection, Z_LVAL(retval), &bucket->val); + else if (Z_TYPE(retval) == IS_STRING) + zend_hash_add(new_collection, Z_STR(retval), &bucket->val); + else + ERR_BAD_CALLBACK_RETVAL(); + ZEND_HASH_FOREACH_END(); + RETVAL_NEW_COLLECTION(new_collection); } PHP_METHOD(Collection, associateByTo) { - + zend_fcall_info fci; + zend_fcall_info_cache fcc; + zval* dest; + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_OBJECT_OF_CLASS(dest, collections_collection_ce) + Z_PARAM_FUNC(fci, fcc) + ZEND_PARSE_PARAMETERS_END(); + INIT_FCI(); + zval* current = COLLECTION_FETCH_EX(); + zend_array* dest_arr = Z_ARRVAL_P(COLLECTION_FETCH(dest)); + ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(current), Bucket* bucket) + ZVAL_COPY_VALUE(¶ms[0], &bucket->val); + CALLBACK_PASS_PAIR(bucket); + zend_call_function(&fci, &fcc); + zval_ptr_dtor(¶ms[0]); + if (Z_TYPE(retval) == IS_LONG) + zend_hash_index_add(dest_arr, Z_LVAL(retval), &bucket->val); + else if (Z_TYPE(retval) == IS_STRING) + zend_hash_add(dest_arr, Z_STR(retval), &bucket->val); + else + ERR_BAD_CALLBACK_RETVAL(); + ZEND_HASH_FOREACH_END(); + RETVAL_ZVAL(dest, 1, 0); } PHP_METHOD(Collection, average) diff --git a/tests/005-associate-to.phpt b/tests/005-associate-to.phpt index 8ff5c00..f7a602c 100644 --- a/tests/005-associate-to.phpt +++ b/tests/005-associate-to.phpt @@ -7,14 +7,14 @@ $collection = Collection::init($array) ->associate(function ($value, $key) { return new Pair($value, $key); }); +if ($collection->toArray() != array_flip($array)) + echo 'Collection::associate() failed.', PHP_EOL; $array1 = ['baz' => 1]; $collection1 = Collection::init($array1); $array2 = $collection->associateTo($collection1, function ($value, $key) { return new Pair($key, $value); })->toArray(); -if ($collection->toArray() != array_flip($array)) - echo 'Collection::associate() failed.', PHP_EOL; if ($array2 != $array1 + array_flip($array) || $collection1->toArray() != $array2) echo 'Collection::associateTo() failed.', PHP_EOL; ?> diff --git a/tests/006-associate-by-to.phpt b/tests/006-associate-by-to.phpt new file mode 100644 index 0000000..1e93a86 --- /dev/null +++ b/tests/006-associate-by-to.phpt @@ -0,0 +1,20 @@ +--TEST-- +Test Collection::associateBy() and Collection::associateByTo(). +--FILE-- + 'b', 'cd' => 'd', 'fgh' => 'i']; +$collection = Collection::init($array) + ->associateBy(function ($value, $key) { + return strlen($key) - 1; + }); +if ($collection->toArray() != array_values($array)) + echo 'Collection::associateBy() failed.', PHP_EOL; +$array1 = ['foo' => 'bar']; +$collection1 = Collection::init($array1); +$array2 = $collection->associateByTo($collection1, function ($value, $key) { + return $key; +})->toArray(); +if ($array2 != $array1 + $collection->toArray() || $collection1->toArray() != $array2) + echo 'Collection::associateTo() failed.', PHP_EOL; +?> +--EXPECT--