diff --git a/src/collections_me.c b/src/collections_me.c index 5dd8abd..c1594aa 100644 --- a/src/collections_me.c +++ b/src/collections_me.c @@ -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) diff --git a/src/collections_methods.c b/src/collections_methods.c index fe8a15b..bfb0d06 100644 --- a/src/collections_methods.c +++ b/src/collections_methods.c @@ -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; } diff --git a/src/php_collections_me.h b/src/php_collections_me.h index efa9840..3c53ceb 100644 --- a/src/php_collections_me.h +++ b/src/php_collections_me.h @@ -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); diff --git a/stubs/Collection.php b/stubs/Collection.php index 72f4da1..b6225f8 100644 --- a/stubs/Collection.php +++ b/stubs/Collection.php @@ -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 diff --git a/tests/026-is-empty.phpt b/tests/026-is-empty.phpt index 81230ca..507f877 100644 --- a/tests/026-is-empty.phpt +++ b/tests/026-is-empty.phpt @@ -1,11 +1,11 @@ --TEST-- -Test Collection::isEmpty() and Collection::isNotEmpty(). +Test Collection::isEmpty(). --FILE-- 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; } ?> diff --git a/tests/040-is-packed.phpt b/tests/040-is-packed.phpt new file mode 100644 index 0000000..153e9a0 --- /dev/null +++ b/tests/040-is-packed.phpt @@ -0,0 +1,12 @@ +--TEST-- +Test Collection::isPacked(). +--FILE-- +isPacked(); +$case1 = Collection::init(['foo' => 'bar', 'baz'])->isPacked(); +$case2 = Collection::init()->isPacked(); +if (!$case || $case1 || $case2) { + echo 'Collection::isPacked() failed.', PHP_EOL; +} +?> +--EXPECT-- diff --git a/tests/040-packed.phpt b/tests/040-packed.phpt deleted file mode 100644 index 2910a73..0000000 --- a/tests/040-packed.phpt +++ /dev/null @@ -1,12 +0,0 @@ ---TEST-- -Test Collection::packed(). ---FILE-- -packed(); -$case1 = Collection::init(['foo' => 'bar', 'baz'])->packed(); -$case2 = Collection::init()->packed(); -if (!$case || $case1 || $case2) { - echo 'Collection::packed() failed.', PHP_EOL; -} -?> ---EXPECT-- diff --git a/tests/053-minus.phpt b/tests/053-minus.phpt new file mode 100644 index 0000000..c4552c0 --- /dev/null +++ b/tests/053-minus.phpt @@ -0,0 +1,22 @@ +--TEST-- +Test Collection::minus(). +--FILE-- + '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--