Add `filter()` and `filterNot()`
This commit is contained in:
parent
3d996ade8b
commit
9b08894ae5
|
@ -44,12 +44,15 @@
|
||||||
fci.retval = &retval; \
|
fci.retval = &retval; \
|
||||||
fci.params = params;
|
fci.params = params;
|
||||||
|
|
||||||
#define CALLBACK_PASS_PAIR(bucket) \
|
#define CALLBACK_KEYVAL_INVOKE(params, bucket) \
|
||||||
|
ZVAL_COPY_VALUE(¶ms[0], &bucket->val); \
|
||||||
ZVAL_COPY(¶ms[0], &(bucket)->val); \
|
ZVAL_COPY(¶ms[0], &(bucket)->val); \
|
||||||
if ((bucket)->key) \
|
if ((bucket)->key) \
|
||||||
ZVAL_STR(¶ms[1], (bucket)->key); \
|
ZVAL_STR(¶ms[1], (bucket)->key); \
|
||||||
else \
|
else \
|
||||||
ZVAL_LONG(¶ms[1], (bucket)->h)
|
ZVAL_LONG(¶ms[1], (bucket)->h); \
|
||||||
|
zend_call_function(&fci, &fcc); \
|
||||||
|
zval_ptr_dtor(¶ms[0])
|
||||||
|
|
||||||
#define INIT_EQUAL_CHECK_FUNC(val) \
|
#define INIT_EQUAL_CHECK_FUNC(val) \
|
||||||
int (*equal_check_func)(zval*, zval*); \
|
int (*equal_check_func)(zval*, zval*); \
|
||||||
|
@ -195,10 +198,7 @@ PHP_METHOD(Collection, all)
|
||||||
INIT_FCI();
|
INIT_FCI();
|
||||||
zval* current = COLLECTION_FETCH_EX();
|
zval* current = COLLECTION_FETCH_EX();
|
||||||
ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(current), Bucket* bucket)
|
ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(current), Bucket* bucket)
|
||||||
ZVAL_COPY_VALUE(¶ms[0], &bucket->val);
|
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
||||||
CALLBACK_PASS_PAIR(bucket);
|
|
||||||
zend_call_function(&fci, &fcc);
|
|
||||||
zval_ptr_dtor(¶ms[0]);
|
|
||||||
if (!zend_is_true(&retval))
|
if (!zend_is_true(&retval))
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
ZEND_HASH_FOREACH_END();
|
ZEND_HASH_FOREACH_END();
|
||||||
|
@ -215,10 +215,7 @@ PHP_METHOD(Collection, any)
|
||||||
INIT_FCI();
|
INIT_FCI();
|
||||||
zval* current = COLLECTION_FETCH_EX();
|
zval* current = COLLECTION_FETCH_EX();
|
||||||
ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(current), Bucket* bucket)
|
ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(current), Bucket* bucket)
|
||||||
ZVAL_COPY_VALUE(¶ms[0], &bucket->val);
|
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
||||||
CALLBACK_PASS_PAIR(bucket);
|
|
||||||
zend_call_function(&fci, &fcc);
|
|
||||||
zval_ptr_dtor(¶ms[0]);
|
|
||||||
if (zend_is_true(&retval))
|
if (zend_is_true(&retval))
|
||||||
RETURN_TRUE;
|
RETURN_TRUE;
|
||||||
ZEND_HASH_FOREACH_END();
|
ZEND_HASH_FOREACH_END();
|
||||||
|
@ -236,10 +233,7 @@ PHP_METHOD(Collection, associate)
|
||||||
zval* current = COLLECTION_FETCH_EX();
|
zval* current = COLLECTION_FETCH_EX();
|
||||||
ARRAY_NEW_EX(new_collection, current);
|
ARRAY_NEW_EX(new_collection, current);
|
||||||
ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(current), Bucket* bucket)
|
ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(current), Bucket* bucket)
|
||||||
ZVAL_COPY_VALUE(¶ms[0], &bucket->val);
|
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
||||||
CALLBACK_PASS_PAIR(bucket);
|
|
||||||
zend_call_function(&fci, &fcc);
|
|
||||||
zval_ptr_dtor(¶ms[0]);
|
|
||||||
if (IS_PAIR(retval)) {
|
if (IS_PAIR(retval)) {
|
||||||
zval* key = PAIR_FETCH_FIRST(&retval);
|
zval* key = PAIR_FETCH_FIRST(&retval);
|
||||||
zval* value = PAIR_FETCH_SECOND(&retval);
|
zval* value = PAIR_FETCH_SECOND(&retval);
|
||||||
|
@ -271,10 +265,7 @@ PHP_METHOD(Collection, associateTo)
|
||||||
zval* current = COLLECTION_FETCH_EX();
|
zval* current = COLLECTION_FETCH_EX();
|
||||||
zend_array* dest_arr = Z_ARRVAL_P(COLLECTION_FETCH(dest));
|
zend_array* dest_arr = Z_ARRVAL_P(COLLECTION_FETCH(dest));
|
||||||
ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(current), Bucket* bucket)
|
ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(current), Bucket* bucket)
|
||||||
ZVAL_COPY_VALUE(¶ms[0], &bucket->val);
|
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
||||||
CALLBACK_PASS_PAIR(bucket);
|
|
||||||
zend_call_function(&fci, &fcc);
|
|
||||||
zval_ptr_dtor(¶ms[0]);
|
|
||||||
if (IS_PAIR(retval)) {
|
if (IS_PAIR(retval)) {
|
||||||
zval* key = PAIR_FETCH_FIRST(&retval);
|
zval* key = PAIR_FETCH_FIRST(&retval);
|
||||||
zval* value = PAIR_FETCH_SECOND(&retval);
|
zval* value = PAIR_FETCH_SECOND(&retval);
|
||||||
|
@ -304,10 +295,7 @@ PHP_METHOD(Collection, associateBy)
|
||||||
zval* current = COLLECTION_FETCH_EX();
|
zval* current = COLLECTION_FETCH_EX();
|
||||||
ARRAY_NEW_EX(new_collection, current);
|
ARRAY_NEW_EX(new_collection, current);
|
||||||
ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(current), Bucket* bucket)
|
ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(current), Bucket* bucket)
|
||||||
ZVAL_COPY_VALUE(¶ms[0], &bucket->val);
|
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
||||||
CALLBACK_PASS_PAIR(bucket);
|
|
||||||
zend_call_function(&fci, &fcc);
|
|
||||||
zval_ptr_dtor(¶ms[0]);
|
|
||||||
if (Z_TYPE(retval) == IS_LONG)
|
if (Z_TYPE(retval) == IS_LONG)
|
||||||
zend_hash_index_add(new_collection, Z_LVAL(retval), &bucket->val);
|
zend_hash_index_add(new_collection, Z_LVAL(retval), &bucket->val);
|
||||||
else if (Z_TYPE(retval) == IS_STRING)
|
else if (Z_TYPE(retval) == IS_STRING)
|
||||||
|
@ -331,10 +319,7 @@ PHP_METHOD(Collection, associateByTo)
|
||||||
zval* current = COLLECTION_FETCH_EX();
|
zval* current = COLLECTION_FETCH_EX();
|
||||||
zend_array* dest_arr = Z_ARRVAL_P(COLLECTION_FETCH(dest));
|
zend_array* dest_arr = Z_ARRVAL_P(COLLECTION_FETCH(dest));
|
||||||
ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(current), Bucket* bucket)
|
ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(current), Bucket* bucket)
|
||||||
ZVAL_COPY_VALUE(¶ms[0], &bucket->val);
|
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
||||||
CALLBACK_PASS_PAIR(bucket);
|
|
||||||
zend_call_function(&fci, &fcc);
|
|
||||||
zval_ptr_dtor(¶ms[0]);
|
|
||||||
if (Z_TYPE(retval) == IS_LONG)
|
if (Z_TYPE(retval) == IS_LONG)
|
||||||
zend_hash_index_add(dest_arr, Z_LVAL(retval), &bucket->val);
|
zend_hash_index_add(dest_arr, Z_LVAL(retval), &bucket->val);
|
||||||
else if (Z_TYPE(retval) == IS_STRING)
|
else if (Z_TYPE(retval) == IS_STRING)
|
||||||
|
@ -552,10 +537,7 @@ PHP_METHOD(Collection, dropLastWhile)
|
||||||
zval* current = COLLECTION_FETCH_EX();
|
zval* current = COLLECTION_FETCH_EX();
|
||||||
ARRAY_CLONE(new_collection, current);
|
ARRAY_CLONE(new_collection, current);
|
||||||
ZEND_HASH_REVERSE_FOREACH_BUCKET(new_collection, Bucket* bucket)
|
ZEND_HASH_REVERSE_FOREACH_BUCKET(new_collection, Bucket* bucket)
|
||||||
ZVAL_COPY_VALUE(¶ms[0], &bucket->val);
|
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
||||||
CALLBACK_PASS_PAIR(bucket);
|
|
||||||
zend_call_function(&fci, &fcc);
|
|
||||||
zval_ptr_dtor(¶ms[0]);
|
|
||||||
if (zend_is_true(&retval))
|
if (zend_is_true(&retval))
|
||||||
zend_hash_del_bucket(new_collection, bucket);
|
zend_hash_del_bucket(new_collection, bucket);
|
||||||
else
|
else
|
||||||
|
@ -575,10 +557,7 @@ PHP_METHOD(Collection, dropWhile)
|
||||||
zval* current = COLLECTION_FETCH_EX();
|
zval* current = COLLECTION_FETCH_EX();
|
||||||
ARRAY_CLONE(new_collection, current);
|
ARRAY_CLONE(new_collection, current);
|
||||||
ZEND_HASH_FOREACH_BUCKET(new_collection, Bucket* bucket)
|
ZEND_HASH_FOREACH_BUCKET(new_collection, Bucket* bucket)
|
||||||
ZVAL_COPY_VALUE(¶ms[0], &bucket->val);
|
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
||||||
CALLBACK_PASS_PAIR(bucket);
|
|
||||||
zend_call_function(&fci, &fcc);
|
|
||||||
zval_ptr_dtor(¶ms[0]);
|
|
||||||
if (zend_is_true(&retval))
|
if (zend_is_true(&retval))
|
||||||
zend_hash_del_bucket(new_collection, bucket);
|
zend_hash_del_bucket(new_collection, bucket);
|
||||||
else
|
else
|
||||||
|
@ -614,12 +593,44 @@ PHP_METHOD(Collection, fill)
|
||||||
|
|
||||||
PHP_METHOD(Collection, filter)
|
PHP_METHOD(Collection, filter)
|
||||||
{
|
{
|
||||||
|
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)
|
||||||
|
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
||||||
|
if (zend_is_true(&retval))
|
||||||
|
if (bucket->key)
|
||||||
|
zend_hash_add(new_collection, bucket->key, &bucket->val);
|
||||||
|
else
|
||||||
|
zend_hash_index_add(new_collection, bucket->h, &bucket->val);
|
||||||
|
ZEND_HASH_FOREACH_END();
|
||||||
|
RETVAL_NEW_COLLECTION(new_collection);
|
||||||
}
|
}
|
||||||
|
|
||||||
PHP_METHOD(Collection, filterNot)
|
PHP_METHOD(Collection, filterNot)
|
||||||
{
|
{
|
||||||
|
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)
|
||||||
|
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
||||||
|
if (!zend_is_true(&retval))
|
||||||
|
if (bucket->key)
|
||||||
|
zend_hash_add(new_collection, bucket->key, &bucket->val);
|
||||||
|
else
|
||||||
|
zend_hash_index_add(new_collection, bucket->h, &bucket->val);
|
||||||
|
ZEND_HASH_FOREACH_END();
|
||||||
|
RETVAL_NEW_COLLECTION(new_collection);
|
||||||
}
|
}
|
||||||
|
|
||||||
PHP_METHOD(Collection, filterNotTo)
|
PHP_METHOD(Collection, filterNotTo)
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
--TEST--
|
||||||
|
Test Collection::filter() and Collection::filterNot().
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
$array = [1, 3, 4, 5, 8, 10, 13];
|
||||||
|
$pred_is_odd = function ($value) {
|
||||||
|
return $value % 2;
|
||||||
|
};
|
||||||
|
$pred_is_even = function ($value) {
|
||||||
|
return $value % 2 == 0;
|
||||||
|
};
|
||||||
|
$collection = Collection::init($array)->filter($pred_is_odd);
|
||||||
|
$collection1 = Collection::init($array)->filterNot($pred_is_odd);
|
||||||
|
if ($collection->toArray() != array_filter($array, $pred_is_odd))
|
||||||
|
echo 'Collection::filter() failed.', PHP_EOL;
|
||||||
|
if ($collection1->toArray() != array_filter($array, $pred_is_even))
|
||||||
|
echo 'Collection::filter() failed.', PHP_EOL;
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
Reference in New Issue