This commit is contained in:
CismonX 2018-08-13 20:08:05 +08:00
commit f5a217fd24
2 changed files with 114 additions and 17 deletions

View File

@ -224,8 +224,11 @@ PHP_METHOD(Collection, all)
zend_array* current = COLLECTION_FETCH_CURRENT();
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
CALLBACK_KEYVAL_INVOKE(params, bucket);
if (!zend_is_true(&retval))
if (!zend_is_true(&retval)) {
zval_ptr_dtor(&retval);
RETURN_FALSE;
}
zval_ptr_dtor(&retval);
ZEND_HASH_FOREACH_END();
RETURN_TRUE;
}
@ -241,8 +244,11 @@ PHP_METHOD(Collection, any)
zend_array* current = COLLECTION_FETCH_CURRENT();
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
CALLBACK_KEYVAL_INVOKE(params, bucket);
if (zend_is_true(&retval))
if (zend_is_true(&retval)) {
zval_ptr_dtor(&retval);
RETURN_TRUE;
}
zval_ptr_dtor(&retval);
ZEND_HASH_FOREACH_END();
RETURN_FALSE;
}
@ -270,9 +276,9 @@ PHP_METHOD(Collection, associate)
zend_hash_next_index_insert(new_collection, value);
else
ERR_BAD_KEY_TYPE();
zval_ptr_dtor(&retval);
} else
ERR_BAD_CALLBACK_RETVAL();
zval_ptr_dtor(&retval);
ZEND_HASH_FOREACH_END();
RETVAL_NEW_COLLECTION(new_collection);
}
@ -303,9 +309,9 @@ PHP_METHOD(Collection, associateTo)
zend_hash_next_index_insert(dest_arr, value);
else
ERR_BAD_KEY_TYPE();
zval_ptr_dtor(&retval);
} else
ERR_BAD_CALLBACK_RETVAL();
zval_ptr_dtor(&retval);
ZEND_HASH_FOREACH_END();
RETVAL_ZVAL(dest, 1, 0);
}
@ -328,6 +334,7 @@ PHP_METHOD(Collection, associateBy)
zend_hash_add(new_collection, Z_STR(retval), &bucket->val);
else
ERR_BAD_CALLBACK_RETVAL();
zval_ptr_dtor(&retval);
ZEND_HASH_FOREACH_END();
RETVAL_NEW_COLLECTION(new_collection);
}
@ -353,6 +360,7 @@ PHP_METHOD(Collection, associateByTo)
zend_hash_add(dest_arr, Z_STR(retval), &bucket->val);
else
ERR_BAD_CALLBACK_RETVAL();
zval_ptr_dtor(&retval);
ZEND_HASH_FOREACH_END();
RETVAL_ZVAL(dest, 1, 0);
}
@ -567,10 +575,13 @@ PHP_METHOD(Collection, dropLastWhile)
ARRAY_CLONE(new_collection, current);
ZEND_HASH_REVERSE_FOREACH_BUCKET(new_collection, Bucket* bucket)
CALLBACK_KEYVAL_INVOKE(params, bucket);
if (zend_is_true(&retval))
if (zend_is_true(&retval)) {
zval_ptr_dtor(&retval);
zend_hash_del_bucket(new_collection, bucket);
else
} else {
zval_ptr_dtor(&retval);
break;
}
ZEND_HASH_FOREACH_END();
RETVAL_NEW_COLLECTION(new_collection);
}
@ -587,10 +598,13 @@ PHP_METHOD(Collection, dropWhile)
ARRAY_CLONE(new_collection, current);
ZEND_HASH_FOREACH_BUCKET(new_collection, Bucket* bucket)
CALLBACK_KEYVAL_INVOKE(params, bucket);
if (zend_is_true(&retval))
if (zend_is_true(&retval)) {
zval_ptr_dtor(&retval);
zend_hash_del_bucket(new_collection, bucket);
else
} else {
zval_ptr_dtor(&retval);
break;
}
ZEND_HASH_FOREACH_END();
RETVAL_NEW_COLLECTION(new_collection);
}
@ -640,6 +654,7 @@ PHP_METHOD(Collection, filter)
else
zend_hash_index_add(new_collection, bucket->h, &bucket->val);
}
zval_ptr_dtor(&retval);
ZEND_HASH_FOREACH_END();
RETVAL_NEW_COLLECTION(new_collection);
}
@ -664,6 +679,7 @@ PHP_METHOD(Collection, filterNot)
else
zend_hash_index_add(new_collection, bucket->h, &bucket->val);
}
zval_ptr_dtor(&retval);
ZEND_HASH_FOREACH_END();
RETVAL_NEW_COLLECTION(new_collection);
}
@ -691,6 +707,7 @@ PHP_METHOD(Collection, filterNotTo)
else
zend_hash_index_add(dest_arr, bucket->h, &bucket->val);
}
zval_ptr_dtor(&retval);
ZEND_HASH_FOREACH_END();
RETVAL_ZVAL(dest, 1, 0);
}
@ -718,6 +735,7 @@ PHP_METHOD(Collection, filterTo)
else
zend_hash_index_add(dest_arr, bucket->h, &bucket->val);
}
zval_ptr_dtor(&retval);
ZEND_HASH_FOREACH_END();
RETVAL_ZVAL(dest, 1, 0);
}
@ -742,8 +760,11 @@ PHP_METHOD(Collection, first)
INIT_FCI(2);
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
CALLBACK_KEYVAL_INVOKE(params, bucket);
if (zend_is_true(&retval))
if (zend_is_true(&retval)) {
zval_ptr_dtor(&retval);
RETURN_ZVAL(&bucket->val, 1, 0);
}
zval_ptr_dtor(&retval);
ZEND_HASH_FOREACH_END();
RETVAL_NULL();
}
@ -828,12 +849,52 @@ PHP_METHOD(Collection, flatten)
PHP_METHOD(Collection, fold)
{
zval* initial;
zend_fcall_info fci;
zend_fcall_info_cache fcc;
ZEND_PARSE_PARAMETERS_START(2, 2)
Z_PARAM_ZVAL(initial)
Z_PARAM_FUNC(fci, fcc)
ZEND_PARSE_PARAMETERS_END();
zend_array* current = COLLECTION_FETCH_CURRENT();
INIT_FCI(3);
ZVAL_COPY(&params[0], initial);
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
ZVAL_COPY_VALUE(&params[1], &bucket->val);
if (bucket->key)
ZVAL_STR(&params[2], bucket->key);
else
ZVAL_LONG(&params[2], bucket->h);
zend_call_function(&fci, &fcc);
zval_ptr_dtor(&params[0]);
ZVAL_COPY_VALUE(&params[0], &retval);
ZEND_HASH_FOREACH_END();
RETVAL_ZVAL(&retval, 0, 0);
}
PHP_METHOD(Collection, foldRight)
{
zval* initial;
zend_fcall_info fci;
zend_fcall_info_cache fcc;
ZEND_PARSE_PARAMETERS_START(2, 2)
Z_PARAM_ZVAL(initial)
Z_PARAM_FUNC(fci, fcc)
ZEND_PARSE_PARAMETERS_END();
zend_array* current = COLLECTION_FETCH_CURRENT();
INIT_FCI(3);
ZVAL_COPY(&params[0], initial);
ZEND_HASH_REVERSE_FOREACH_BUCKET(current, Bucket* bucket)
ZVAL_COPY_VALUE(&params[1], &bucket->val);
if (bucket->key)
ZVAL_STR(&params[2], bucket->key);
else
ZVAL_LONG(&params[2], bucket->h);
zend_call_function(&fci, &fcc);
zval_ptr_dtor(&params[0]);
ZVAL_COPY_VALUE(&params[0], &retval);
ZEND_HASH_FOREACH_END();
RETVAL_ZVAL(&retval, 0, 0);
}
PHP_METHOD(Collection, forEach)
@ -847,6 +908,7 @@ PHP_METHOD(Collection, forEach)
zend_array* current = COLLECTION_FETCH_CURRENT();
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
CALLBACK_KEYVAL_INVOKE(params, bucket);
zval_ptr_dtor(&retval);
ZEND_HASH_FOREACH_END();
}
@ -877,7 +939,7 @@ PHP_METHOD(Collection, get)
INIT_FCI(1);
ZVAL_COPY_VALUE(&params[0], key);
zend_call_function(&fci, &fcc);
RETVAL_ZVAL(&retval, 1, 0);
RETVAL_ZVAL(&retval, 0, 0);
}
PHP_METHOD(Collection, groupBy)
@ -921,10 +983,12 @@ PHP_METHOD(Collection, indexOfFirst)
ZVAL_COPY_VALUE(&params[0], &bucket->val);
zend_call_function(&fci, &fcc);
if (zend_is_true(&retval)) {
zval_ptr_dtor(&retval);
if (bucket->key)
RETURN_STR(bucket->key);
RETURN_LONG(bucket->h);
}
zval_ptr_dtor(&retval);
ZEND_HASH_FOREACH_END();
RETVAL_NULL();
}
@ -942,10 +1006,12 @@ PHP_METHOD(Collection, indexOfLast)
ZVAL_COPY_VALUE(&params[0], &bucket->val);
zend_call_function(&fci, &fcc);
if (zend_is_true(&retval)) {
zval_ptr_dtor(&retval);
if (bucket->key)
RETURN_STR(bucket->key);
RETURN_LONG(bucket->h);
}
zval_ptr_dtor(&retval);
ZEND_HASH_FOREACH_END();
RETVAL_NULL();
}
@ -1017,8 +1083,11 @@ PHP_METHOD(Collection, last)
INIT_FCI(2);
ZEND_HASH_REVERSE_FOREACH_BUCKET(current, Bucket* bucket)
CALLBACK_KEYVAL_INVOKE(params, bucket);
if (zend_is_true(&retval))
if (zend_is_true(&retval)) {
zval_ptr_dtor(&retval);
RETURN_ZVAL(&bucket->val, 1, 0);
}
zval_ptr_dtor(&retval);
ZEND_HASH_FOREACH_END();
RETVAL_NULL();
}
@ -1197,8 +1266,11 @@ PHP_METHOD(Collection, none)
zend_array* current = COLLECTION_FETCH_CURRENT();
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
CALLBACK_KEYVAL_INVOKE(params, bucket);
if (zend_is_true(&retval))
if (zend_is_true(&retval)) {
zval_ptr_dtor(&retval);
RETURN_FALSE;
}
zval_ptr_dtor(&retval);
ZEND_HASH_FOREACH_END();
RETURN_TRUE;
}
@ -1214,6 +1286,7 @@ PHP_METHOD(Collection, onEach)
zend_array* current = COLLECTION_FETCH_CURRENT();
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
CALLBACK_KEYVAL_INVOKE(params, bucket);
zval_ptr_dtor(&retval);
ZEND_HASH_FOREACH_END();
RETVAL_ZVAL(getThis(), 1, 0);
}
@ -1246,6 +1319,7 @@ PHP_METHOD(Collection, partition)
zend_hash_next_index_insert(which, &bucket->val);
else
zend_hash_index_add(which, bucket->h, &bucket->val);
zval_ptr_dtor(&retval);
ZEND_HASH_FOREACH_END();
zval first, second;
ZVAL_ARR(&first, first_arr);
@ -1417,6 +1491,7 @@ PHP_METHOD(Collection, removeAll)
CALLBACK_KEYVAL_INVOKE(params, bucket);
if (zend_is_true(&retval))
zend_hash_del_bucket(current, bucket);
zval_ptr_dtor(&retval);
ZEND_HASH_FOREACH_END();
}
@ -1439,6 +1514,7 @@ PHP_METHOD(Collection, retainAll)
CALLBACK_KEYVAL_INVOKE(params, bucket);
if (!zend_is_true(&retval))
zend_hash_del_bucket(current, bucket);
zval_ptr_dtor(&retval);
ZEND_HASH_FOREACH_END();
}
@ -1554,6 +1630,7 @@ PHP_METHOD(Collection, single)
else
RETURN_NULL();
}
zval_ptr_dtor(&retval);
ZEND_HASH_FOREACH_END();
if (Z_TYPE(single) == IS_UNDEF)
RETURN_NULL()
@ -1723,10 +1800,13 @@ PHP_METHOD(Collection, takeLastWhile)
Bucket* taken[num_elements];
ZEND_HASH_REVERSE_FOREACH_BUCKET(current, Bucket* bucket)
CALLBACK_KEYVAL_INVOKE(params, bucket);
if (zend_is_true(&retval))
if (zend_is_true(&retval)) {
zval_ptr_dtor(&retval);
taken[--num_elements] = bucket;
else
} else {
zval_ptr_dtor(&retval);
break;
}
ZEND_HASH_FOREACH_END();
memset(&taken[0], 0, num_elements * sizeof(Bucket*));
int i = 0;
@ -1758,14 +1838,17 @@ PHP_METHOD(Collection, takeWhile)
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
CALLBACK_KEYVAL_INVOKE(params, bucket);
if (zend_is_true(&retval)) {
zval_ptr_dtor(&retval);
if (bucket->key)
zend_hash_add_new(new_collection, bucket->key, &bucket->val);
else if (HT_IS_PACKED(current))
zend_hash_next_index_insert(new_collection, &bucket->val);
else
zend_hash_index_add_new(new_collection, bucket->h, &bucket->val);
} else
} else {
zval_ptr_dtor(&retval);
break;
}
ZEND_HASH_FOREACH_END();
RETVAL_NEW_COLLECTION(new_collection);
}

14
tests/041-fold.phpt Normal file
View File

@ -0,0 +1,14 @@
--TEST--
Test Collection::fold() and Collection::foldRight().
--FILE--
<?php
$collection = Collection::init(['a', 'b', 'c', 'd', 'e']);
$reduce_cb = function ($acc, $value, $key) {
return $acc.$value.strval($key);
};
if ($collection->fold('foo', $reduce_cb) != 'fooa0b1c2d3e4')
echo 'Collection::fold() failed.', PHP_EOL;
if ($collection->foldRight('bar', $reduce_cb) != 'bare4d3c2b1a0')
echo 'Collection::foldRight() failed.', PHP_EOL;
?>
--EXPECT--