Add `minus()`. Remove `isNotEmpty()`. Fix bugs.

This commit is contained in:
CismonX 2018-09-05 18:44:16 +08:00
parent 72504b9e7d
commit ce709d801d
8 changed files with 80 additions and 48 deletions

View File

@ -165,7 +165,7 @@ const zend_function_entry collection_methods[] = {
PHP_ME(Collection, intersectKeys, other_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, intersectValues, other_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, isEmpty, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Collection, isNotEmpty, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Collection, isPacked, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Collection, keys, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Collection, last, predicate_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, lastIndexOf, element_arginfo, ZEND_ACC_PUBLIC)
@ -180,7 +180,6 @@ const zend_function_entry collection_methods[] = {
PHP_ME(Collection, minus, elements_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, none, predicate_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, onEach, action_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, packed, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Collection, partition, predicate_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, plus, elements_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, putAll, elements_arginfo, ZEND_ACC_PUBLIC)

View File

@ -27,7 +27,7 @@
#define IS_COLLECTION_P(zval) \
Z_TYPE_P(zval) == IS_OBJECT && Z_OBJCE_P(zval) == collections_collection_ce
#define IS_PAIR(zval) \
EXPECTED(Z_TYPE(zval) == IS_OBJECT) && EXPECTED(Z_OBJCE(zval) == collections_pair_ce)
Z_TYPE(zval) == IS_OBJECT && Z_OBJCE(zval) == collections_pair_ce
#define SEPARATE_COLLECTION(ht, obj) \
if (GC_REFCOUNT(ht) > 1) { \
@ -607,7 +607,7 @@ PHP_METHOD(Collection, associate)
ARRAY_NEW_EX(new_collection, current);
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
CALLBACK_KEYVAL_INVOKE(params, bucket);
if (IS_PAIR(retval)) {
if (EXPECTED(IS_PAIR(retval))) {
zval* key = PAIR_FIRST(Z_OBJ(retval));
zval* value = PAIR_SECOND(Z_OBJ(retval));
if (Z_TYPE_P(key) == IS_LONG) {
@ -642,7 +642,7 @@ PHP_METHOD(Collection, associateTo)
SEPARATE_COLLECTION(dest_arr, dest);
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
CALLBACK_KEYVAL_INVOKE(params, bucket);
if (IS_PAIR(retval)) {
if (EXPECTED(IS_PAIR(retval))) {
zval* key = PAIR_FIRST(Z_OBJ(retval));
zval* value = PAIR_SECOND(Z_OBJ(retval));
if (Z_TYPE_P(key) == IS_LONG) {
@ -738,19 +738,15 @@ PHP_METHOD(Collection, containsAll)
ZEND_PARSE_PARAMETERS_END();
ELEMENTS_VALIDATE(elements, ERR_BAD_ARGUMENT_TYPE, return);
zend_array* current = COLLECTION_FETCH_CURRENT();
equal_check_func_t eql = NULL;
ZEND_HASH_FOREACH_BUCKET(elements_arr, Bucket* bucket)
if (UNEXPECTED(eql == NULL)) {
eql = equal_check_func_init(&bucket->val);
}
if (bucket->key) {
zval* result = zend_hash_find(current, bucket->key);
if (!result || !eql(&bucket->val, result)) {
if (!result || !fast_equal_check_function(&bucket->val, result)) {
RETURN_FALSE;
}
} else {
zval* result = zend_hash_index_find(current, bucket->h);
if (!result || !eql(&bucket->val, result)) {
if (!result || !fast_equal_check_function(&bucket->val, result)) {
RETURN_FALSE;
}
}
@ -1465,7 +1461,7 @@ PHP_METHOD(Collection, groupBy)
CALLBACK_KEYVAL_INVOKE(params, bucket);
zval* key;
zval* value;
if (IS_PAIR(retval)) {
if (EXPECTED(IS_PAIR(retval))) {
key = PAIR_FIRST(Z_OBJ(retval));
value = PAIR_SECOND(Z_OBJ(retval));
} else {
@ -1507,7 +1503,7 @@ PHP_METHOD(Collection, groupByTo)
CALLBACK_KEYVAL_INVOKE(params, bucket);
zval* key;
zval* value;
if (IS_PAIR(retval)) {
if (EXPECTED(IS_PAIR(retval))) {
key = PAIR_FIRST(Z_OBJ(retval));
value = PAIR_SECOND(Z_OBJ(retval));
} else {
@ -1680,10 +1676,10 @@ PHP_METHOD(Collection, isEmpty)
RETVAL_BOOL(zend_hash_num_elements(current) == 0);
}
PHP_METHOD(Collection, isNotEmpty)
PHP_METHOD(Collection, isPacked)
{
zend_array* current = COLLECTION_FETCH_CURRENT();
RETVAL_BOOL(zend_hash_num_elements(current));
RETVAL_BOOL(HT_IS_PACKED(current));
}
PHP_METHOD(Collection, keys)
@ -1947,7 +1943,31 @@ PHP_METHOD(Collection, minWith)
PHP_METHOD(Collection, minus)
{
zval* elements;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_ZVAL(elements)
ZEND_PARSE_PARAMETERS_END();
ELEMENTS_VALIDATE(elements, ERR_BAD_ARGUMENT_TYPE, return);
zend_array* current = COLLECTION_FETCH_CURRENT();
ARRAY_NEW(new_collection, 8);
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
zval* result;
if (bucket->key) {
result = zend_hash_find(elements_arr, bucket->key);
} else {
result = zend_hash_index_find(elements_arr, bucket->h);
}
if (result && fast_equal_check_function(result, &bucket->val)) {
continue;
}
Z_TRY_ADDREF(bucket->val);
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, none)
@ -1986,12 +2006,6 @@ PHP_METHOD(Collection, onEach)
RETVAL_ZVAL(getThis(), 1, 0);
}
PHP_METHOD(Collection, packed)
{
zend_array* current = COLLECTION_FETCH_CURRENT();
RETVAL_BOOL(HT_IS_PACKED(current));
}
PHP_METHOD(Collection, partition)
{
zend_fcall_info fci;
@ -2274,6 +2288,11 @@ PHP_METHOD(Collection, shuffle)
} else {
zend_array_destroy(current);
}
if (GC_REFCOUNT(current) > 1) {
GC_DELREF(current);
} else {
zend_array_destroy(current);
}
COLLECTION_FETCH_CURRENT() = shuffled;
}

View File

@ -53,7 +53,7 @@ PHP_METHOD(Collection, intersect);
PHP_METHOD(Collection, intersectKeys);
PHP_METHOD(Collection, intersectValues);
PHP_METHOD(Collection, isEmpty);
PHP_METHOD(Collection, isNotEmpty);
PHP_METHOD(Collection, isPacked);
PHP_METHOD(Collection, keys);
PHP_METHOD(Collection, last);
PHP_METHOD(Collection, lastIndexOf);
@ -68,7 +68,6 @@ PHP_METHOD(Collection, minWith);
PHP_METHOD(Collection, minus);
PHP_METHOD(Collection, none);
PHP_METHOD(Collection, onEach);
PHP_METHOD(Collection, packed);
PHP_METHOD(Collection, partition);
PHP_METHOD(Collection, plus);
PHP_METHOD(Collection, putAll);

View File

@ -425,11 +425,11 @@ class Collection implements ArrayAccess, Countable
function isEmpty() {}
/**
* Returns true if the collection is not empty.
*
* Check whether the collection wraps a packed hashtable (regular array).
*
* @return bool
*/
function isNotEmpty() {}
function isPacked() {}
/**
* Return a collection of all keys in the collection.
@ -587,13 +587,6 @@ class Collection implements ArrayAccess, Countable
*/
function onEach($action) {}
/**
* Check whether the collection wraps a packed hashtable (regular array).
*
* @return bool
*/
function packed() {}
/**
* Splits the original collection into pair of collections, where first collection contains
* elements for which predicate yielded true, while second collection contains elements for

View File

@ -1,11 +1,11 @@
--TEST--
Test Collection::isEmpty() and Collection::isNotEmpty().
Test Collection::isEmpty().
--FILE--
<?php
if (!Collection::init()->isEmpty()) {
echo 'Collection::isEmpty() failed.', PHP_EOL;
}
if (!Collection::init(['foo', 'bar'])->isNotEmpty()) {
if (Collection::init(['foo', 'bar'])->isEmpty()) {
echo 'Collection::isNotEmpty() failed.', PHP_EOL;
}
?>

12
tests/040-is-packed.phpt Normal file
View File

@ -0,0 +1,12 @@
--TEST--
Test Collection::isPacked().
--FILE--
<?php
$case = Collection::init(['a', 'b', 'c'])->isPacked();
$case1 = Collection::init(['foo' => 'bar', 'baz'])->isPacked();
$case2 = Collection::init()->isPacked();
if (!$case || $case1 || $case2) {
echo 'Collection::isPacked() failed.', PHP_EOL;
}
?>
--EXPECT--

View File

@ -1,12 +0,0 @@
--TEST--
Test Collection::packed().
--FILE--
<?php
$case = Collection::init(['a', 'b', 'c'])->packed();
$case1 = Collection::init(['foo' => 'bar', 'baz'])->packed();
$case2 = Collection::init()->packed();
if (!$case || $case1 || $case2) {
echo 'Collection::packed() failed.', PHP_EOL;
}
?>
--EXPECT--

22
tests/053-minus.phpt Normal file
View File

@ -0,0 +1,22 @@
--TEST--
Test Collection::minus().
--FILE--
<?php
$array = [
'a' => 'b',
'c' => 'd',
'e' => 'f'
];
$array1 = [
'a' => 'g',
'c' => 'd',
'h' => 'f'
];
$collection = Collection::init($array);
$collection1 = Collection::init($array1);
$subtraction = array_diff_assoc($array, $array1);
if ($collection->minus($collection1)->toArray() != $subtraction) {
echo 'Collection::minus() failed.', PHP_EOL;
}
?>
--EXPECT--