diff --git a/src/collections_me.c b/src/collections_me.c index ff45b20..7d42c3c 100644 --- a/src/collections_me.c +++ b/src/collections_me.c @@ -92,7 +92,6 @@ ZEND_BEGIN_ARG_INFO(associate_by_to_arginfo, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(copy_of_arginfo, 0) - ZEND_ARG_INFO(0, elements) ZEND_ARG_TYPE_INFO(0, new_size, IS_LONG, 0) ZEND_END_ARG_INFO() diff --git a/src/collections_methods.c b/src/collections_methods.c index 1c83ca2..8442907 100644 --- a/src/collections_methods.c +++ b/src/collections_methods.c @@ -63,6 +63,7 @@ #define ERR_BAD_ARGUMENT_TYPE() PHP_COLLECTIONS_ERROR(E_WARNING, "Bad argument type") #define ERR_BAD_KEY_TYPE() PHP_COLLECTIONS_ERROR(E_WARNING, "Key must be integer or string") #define ERR_BAD_CALLBACK_RETVAL() PHP_COLLECTIONS_ERROR(E_WARNING, "Bad callback return value") +#define ERR_BAD_SIZE() PHP_COLLECTIONS_ERROR(E_WARNING, "Size must be non-negative") #define ELEMENTS_VALIDATE(elements) \ if (IS_COLLECTION_P(elements)) { \ @@ -94,6 +95,11 @@ RETVAL_OBJ(obj); \ } while (0) +#define RETURN_NEW_COLLECTION(collection) { \ + RETVAL_NEW_COLLECTION(collection); \ + return; \ + } + PHP_METHOD(Collection, __construct) {} PHP_METHOD(Collection, addAll) @@ -105,9 +111,11 @@ PHP_METHOD(Collection, addAll) ELEMENTS_VALIDATE(elements); zval rv; zval* current = COLLECTION_FETCH_EX(); - ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL_P(elements), zval* val) - zend_hash_next_index_insert(Z_ARRVAL_P(current), val); - ZEND_HASH_FOREACH_END(); + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(current)) + ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL_P(elements), zval* val) + ZEND_HASH_FILL_ADD(val); + ZEND_HASH_FOREACH_END(); + ZEND_HASH_FILL_END(); } PHP_METHOD(Collection, all) @@ -312,17 +320,68 @@ PHP_METHOD(Collection, containsAll) PHP_METHOD(Collection, containsKey) { - + zval* key; + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ZVAL(key) + ZEND_PARSE_PARAMETERS_END(); + zval rv; + zval* current = COLLECTION_FETCH_EX(); + if (Z_TYPE_P(key) == IS_LONG) + RETURN_BOOL(zend_hash_index_exists(Z_ARRVAL_P(current), Z_LVAL_P(key))); + if (Z_TYPE_P(key) == IS_STRING) + RETURN_BOOL(zend_hash_exists(Z_ARRVAL_P(current), Z_STR_P(key))); + ERR_BAD_KEY_TYPE(); + RETVAL_FALSE; } PHP_METHOD(Collection, containsValue) { - + zval* element; + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ZVAL(element) + ZEND_PARSE_PARAMETERS_END(); + zval rv; + zval* current = COLLECTION_FETCH_EX(); + INIT_EQUAL_CHECK_FUNC(element); + ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL_P(current), zval* val) + if (equal_check_func(element, val)) + RETURN_TRUE; + ZEND_HASH_FOREACH_END(); + RETURN_FALSE; } PHP_METHOD(Collection, copyOf) { - + zend_long new_size = -1; + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(new_size); + ZEND_PARSE_PARAMETERS_END(); + zval rv; + zval* current = COLLECTION_FETCH_EX(); + if (EX_NUM_ARGS() == 0) { + ARRAY_CLONE(new_collection, current); + RETURN_NEW_COLLECTION(new_collection); + } + if (UNEXPECTED(new_size < 0)) { + ERR_BAD_SIZE(); + RETURN_NULL(); + } + if (new_size == 0) + { + ARRAY_NEW(new_collection, 0); + RETURN_NEW_COLLECTION(new_collection); + } + ARRAY_NEW_EX(new_collection, current); + ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(current), Bucket* bucket) + if (bucket->key) + zend_hash_add(new_collection, bucket->key, &bucket->val); + else + zend_hash_index_add(new_collection, bucket->h, &bucket->val); + if (--new_size == 0) + break; + ZEND_HASH_FOREACH_END(); + RETVAL_NEW_COLLECTION(new_collection); } PHP_METHOD(Collection, copyOfRange) diff --git a/stubs/Collection.php b/stubs/Collection.php index 742773c..1a1e7db 100644 --- a/stubs/Collection.php +++ b/stubs/Collection.php @@ -90,7 +90,7 @@ class Collection implements ArrayAccess, Countable function containsAll($other) {} /** - * Checks if the array contains the given key. + * Checks if the collection contains the given key. * * @param int|string $key * @return bool @@ -98,7 +98,7 @@ class Collection implements ArrayAccess, Countable function containsKey($key) {} /** - * Check if the array maps one or more keys to the specified value. + * Check if the collection maps one or more keys to the specified value. * * @param mixed $element * @return bool @@ -106,16 +106,15 @@ class Collection implements ArrayAccess, Countable function containsValue($element) {} /** - * Returns new array which is a copy of the original array. + * Returns new collection which is a copy of the original collection. * - * @param array|Collection $elements * @param int $new_size[optional] * @return Collection */ - function copyOf($elements, $new_size) {} + function copyOf($new_size) {} /** - * Returns new array which is a copy of range of original array. + * Returns new collection which is a copy of range of original collection. * * @param int $from_index * @param int $to_index @@ -124,22 +123,22 @@ class Collection implements ArrayAccess, Countable function copyOfRange($from_index, $to_index) {} /** - * Returns the number of elements in this array. + * Returns the number of elements in this collection. * * @return int */ function count() {} /** - * Returns a collection containing only distinct elements from the given array. + * Returns a collection containing only distinct elements from the given collection. * * @return Collection */ function distinct() {} /** - * Returns a collection containing only elements from the given array having distinct keys - * returned by the given selector function. + * Returns a collection containing only elements from the given collection having distinct + * keys returned by the given selector function. * * @param callable $selector ($value, $key) -> $key * @return Collection @@ -181,7 +180,7 @@ class Collection implements ArrayAccess, Countable function dropWhile($predicate) {} /** - * Fills original array with the provided value. + * Fills original collection with the provided value. * * @param mixed $element * @param int $from_index[optional] @@ -306,7 +305,7 @@ class Collection implements ArrayAccess, Countable /** * Returns an element at the given key or the result of calling the `default` function - * if the index is out of bounds of this array. + * if the index is out of bounds of this collection. * * @param int|string $key * @param callable $default[optional] ($key) -> $value @@ -316,7 +315,7 @@ class Collection implements ArrayAccess, Countable /** * Groups values returned by the value_transform function applied to each element of the - * original array by the key returned by the given key_selector function applied to the element + * original collection by the key returned by the given key_selector function applied to the element * and returns a collection where each group key is associated with a list of corresponding values. * * @param callable $key_selector ($value, $key) -> $new_key @@ -338,7 +337,7 @@ class Collection implements ArrayAccess, Countable function groupByTo($destination, $key_selector, $value_transform) {} /** - * Returns first key of element, or null if the array does not contain element. + * Returns first key of element, or null if the collection does not contain element. * * @param mixed $element * @return int|string|null @@ -346,8 +345,8 @@ class Collection implements ArrayAccess, Countable function indexOf($element) {} /** - * Returns key of the first element matching the given predicate, or null if the array does - * not contain such element. + * Returns key of the first element matching the given predicate, or null if the collection + * does not contain such element. * * @param callable $predicate ($value) -> bool * @return int|string|null @@ -355,8 +354,8 @@ class Collection implements ArrayAccess, Countable function indexOfFirst($predicate) {} /** - * Returns key of the last element matching the given predicate, or null if the array does - * not contain such element. + * Returns key of the last element matching the given predicate, or null if the collection + * does not contain such element. * * @param callable $predicate ($value) -> bool * @return int|string|null @@ -380,14 +379,14 @@ class Collection implements ArrayAccess, Countable function intersect($other) {} /** - * Returns true if the array is empty. + * Returns true if the collection is empty. * * @return bool */ function isEmpty() {} /** - * Returns true if the array is not empty. + * Returns true if the collection is not empty. */ function isNotEmpty() {} @@ -407,7 +406,7 @@ class Collection implements ArrayAccess, Countable function last($predicate) {} /** - * Returns last key of element, or null if the array does not contain element. + * Returns last key of element, or null if the collection does not contain element. * * @param mixed $element * @return int|string|null diff --git a/tests/009-contains-key-value.phpt b/tests/009-contains-key-value.phpt new file mode 100644 index 0000000..f63f44a --- /dev/null +++ b/tests/009-contains-key-value.phpt @@ -0,0 +1,11 @@ +--TEST-- +Test Collection::containsKey() and Collection::containsValue(). +--FILE-- + 'bar', 12 => 6, 'baz' => 27]); +if (!$collection->containsKey('foo') || $collection->containsKey('Baz')) + echo 'Collection::containsKey() failed.', PHP_EOL; +if (!$collection->containsValue(27) || $collection->containsValue(3)) + echo 'Collection::containsValue() failed.', PHP_EOL; +?> +--EXPECT-- diff --git a/tests/010-copy-of.phpt b/tests/010-copy-of.phpt new file mode 100644 index 0000000..5fd2aa0 --- /dev/null +++ b/tests/010-copy-of.phpt @@ -0,0 +1,12 @@ +--TEST-- +Test Collection::copyOf(); +--FILE-- + 2, 3 => 'd', 'e' => 'f']; +$collection = Collection::init($array); +$collection1 = $collection->copyOf(2); +$collection2 = $collection->copyOf(); +if ($collection1->toArray() != array_slice($array, 0, 2, true) || $collection2->toArray() != $array) + echo 'Collection::copyOf() failed.', PHP_EOL; +?> +--EXPECT--