Implement `copyOfRange()` and `count()`
This commit is contained in:
parent
a7a39c889a
commit
f7b924801b
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <php.h>
|
||||
#include <php_ini.h>
|
||||
#include <zend_interfaces.h>
|
||||
#include <ext/standard/info.h>
|
||||
|
||||
#include "php_collections.h"
|
||||
|
@ -18,6 +19,8 @@ zend_string* collection_property_name;
|
|||
zend_string* pair_first_name;
|
||||
zend_string* pair_second_name;
|
||||
|
||||
zend_object_handlers* collection_handlers;
|
||||
|
||||
zend_class_entry* collections_collection_ce;
|
||||
zend_class_entry* collections_pair_ce;
|
||||
|
||||
|
@ -26,7 +29,17 @@ PHP_MINIT_FUNCTION(collections)
|
|||
zend_class_entry collection_ce;
|
||||
INIT_CLASS_ENTRY_EX(collection_ce, "Collection", sizeof "Collection" - 1, collection_methods);
|
||||
collections_collection_ce = zend_register_internal_class(&collection_ce);
|
||||
zend_class_implements(collections_collection_ce,
|
||||
#if PHP_VERSION_ID < 70200
|
||||
1,
|
||||
#else
|
||||
2, zend_ce_countable,
|
||||
#endif
|
||||
zend_ce_arrayaccess);
|
||||
zend_declare_property_null(collections_collection_ce, "_", sizeof "_" - 1, ZEND_ACC_PRIVATE);
|
||||
collection_handlers = (zend_object_handlers*)emalloc(sizeof(zend_object_handlers));
|
||||
memcpy(collection_handlers, &std_object_handlers, sizeof(zend_object_handlers));
|
||||
collection_handlers->count_elements = count_collection;
|
||||
zend_class_entry pair_ce;
|
||||
INIT_CLASS_ENTRY_EX(pair_ce, "Pair", sizeof "Pair" - 1, pair_methods);
|
||||
collections_pair_ce = zend_register_internal_class(&pair_ce);
|
||||
|
|
|
@ -35,11 +35,6 @@ ZEND_BEGIN_ARG_INFO(elements_arginfo, 0)
|
|||
ZEND_ARG_INFO(0, elements)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO(from_to_arginfo, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, from_index, IS_LONG, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, to_index, IS_LONG, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO(initial_operation_arginfo, 0)
|
||||
ZEND_ARG_INFO(0, initial)
|
||||
ZEND_ARG_CALLABLE_INFO(0, operation, 0)
|
||||
|
@ -95,6 +90,11 @@ ZEND_BEGIN_ARG_INFO(copy_of_arginfo, 0)
|
|||
ZEND_ARG_TYPE_INFO(0, new_size, IS_LONG, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO(copy_of_range_arginfo, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, from_idx, IS_LONG, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, num_elements, IS_LONG, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO(fill_arginfo, 0)
|
||||
ZEND_ARG_INFO(0, element)
|
||||
ZEND_ARG_TYPE_INFO(0, from_index, IS_LONG, 0)
|
||||
|
@ -135,7 +135,7 @@ const zend_function_entry collection_methods[] = {
|
|||
PHP_ME(Collection, containsKey, key_arginfo, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Collection, containsValue, element_arginfo, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Collection, copyOf, copy_of_arginfo, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Collection, copyOfRange, from_to_arginfo, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Collection, copyOfRange, copy_of_range_arginfo, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Collection, count, NULL, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Collection, distinct, NULL, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Collection, distinctBy, selector_arginfo, ZEND_ACC_PUBLIC)
|
||||
|
@ -210,7 +210,6 @@ const zend_function_entry collection_methods[] = {
|
|||
PHP_ME(Collection, shuffle, NULL, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Collection, single, predicate_arginfo, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Collection, slice, keys_arginfo, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Collection, sliceRange, from_to_arginfo, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Collection, sort, NULL, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Collection, sortBy, selector_arginfo, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Collection, sortByDescending, selector_arginfo, ZEND_ACC_PUBLIC)
|
||||
|
|
|
@ -9,14 +9,16 @@
|
|||
#include "php_collections.h"
|
||||
#include "php_collections_me.h"
|
||||
|
||||
#define NEW_OBJ(name, ce) \
|
||||
#define NEW_OBJ(name, ce, object_handlers) \
|
||||
zend_object* (name) = (zend_object*)ecalloc(1, sizeof(zend_object) + \
|
||||
zend_object_properties_size(ce)); \
|
||||
zend_object_std_init(name, ce); \
|
||||
object_properties_init(name, ce); \
|
||||
(name)->handlers = &std_object_handlers;
|
||||
#define NEW_COLLECTION_OBJ(name) NEW_OBJ(name, collections_collection_ce)
|
||||
#define NEW_PAIR_OBJ(name) NEW_OBJ(name, collections_pair_ce)
|
||||
(name)->handlers = object_handlers;
|
||||
#define NEW_COLLECTION_OBJ(name) \
|
||||
NEW_OBJ(name, collections_collection_ce, collection_handlers)
|
||||
#define NEW_PAIR_OBJ(name) \
|
||||
NEW_OBJ(name, collections_pair_ce, &std_object_handlers)
|
||||
|
||||
#define IS_COLLECTION_P(zval) \
|
||||
Z_TYPE_P(zval) == IS_OBJECT && Z_OBJCE_P(zval) == collections_collection_ce
|
||||
|
@ -58,12 +60,12 @@
|
|||
else \
|
||||
equal_check_func = fast_equal_check_function;
|
||||
|
||||
|
||||
#define PHP_COLLECTIONS_ERROR(type, msg) php_error_docref(NULL, type, msg)
|
||||
#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 ERR_BAD_INDEX() PHP_COLLECTIONS_ERROR(E_WARNING, "Index must be non-negative")
|
||||
#define ERR_NOT_ARITHMETIC() PHP_COLLECTIONS_ERROR(E_WARNING, "Elements should be int or double")
|
||||
|
||||
#define ELEMENTS_VALIDATE(elements) \
|
||||
|
@ -101,6 +103,14 @@
|
|||
return; \
|
||||
}
|
||||
|
||||
int count_collection(zval* obj, zend_long* count)
|
||||
{
|
||||
zval rv;
|
||||
zval* current = COLLECTION_FETCH(obj);
|
||||
*count = zend_hash_num_elements(Z_ARRVAL_P(current));
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
PHP_METHOD(Collection, __construct) {}
|
||||
|
||||
PHP_METHOD(Collection, addAll)
|
||||
|
@ -387,12 +397,38 @@ PHP_METHOD(Collection, copyOf)
|
|||
|
||||
PHP_METHOD(Collection, copyOfRange)
|
||||
{
|
||||
|
||||
zend_long from_idx, num_elements;
|
||||
ZEND_PARSE_PARAMETERS_START(2, 2)
|
||||
Z_PARAM_LONG(from_idx)
|
||||
Z_PARAM_LONG(num_elements)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
if (from_idx < 0) {
|
||||
ERR_BAD_INDEX();
|
||||
RETURN_NULL();
|
||||
}
|
||||
if (num_elements < 0) {
|
||||
ERR_BAD_SIZE();
|
||||
RETURN_NULL();
|
||||
}
|
||||
zval rv;
|
||||
zval* current = COLLECTION_FETCH_EX();
|
||||
ARRAY_NEW(new_collection, num_elements);
|
||||
Bucket* bucket = Z_ARRVAL_P(current)->arData;
|
||||
Bucket* end = bucket + Z_ARRVAL_P(current)->nNumUsed;
|
||||
for (bucket += from_idx; num_elements > 0 && bucket < end; ++bucket, --num_elements) {
|
||||
if (bucket->key)
|
||||
zend_hash_add(new_collection, bucket->key, &bucket->val);
|
||||
else
|
||||
zend_hash_next_index_insert(new_collection, &bucket->val);
|
||||
}
|
||||
RETVAL_NEW_COLLECTION(new_collection);
|
||||
}
|
||||
|
||||
PHP_METHOD(Collection, count)
|
||||
{
|
||||
|
||||
zend_long count;
|
||||
count_collection(getThis(), &count);
|
||||
RETVAL_LONG(count);
|
||||
}
|
||||
|
||||
PHP_METHOD(Collection, distinct)
|
||||
|
@ -783,11 +819,6 @@ PHP_METHOD(Collection, slice)
|
|||
|
||||
}
|
||||
|
||||
PHP_METHOD(Collection, sliceRange)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
PHP_METHOD(Collection, sort)
|
||||
{
|
||||
|
||||
|
|
|
@ -27,6 +27,10 @@ extern zend_string* pair_second_name;
|
|||
extern PHP_COLLECTIONS_API zend_class_entry* collections_collection_ce;
|
||||
extern PHP_COLLECTIONS_API zend_class_entry* collections_pair_ce;
|
||||
|
||||
extern zend_object_handlers* collection_handlers;
|
||||
|
||||
int count_collection(zval* obj, zend_long* count);
|
||||
|
||||
extern const zend_function_entry collection_methods[];
|
||||
extern const zend_function_entry pair_methods[];
|
||||
|
||||
|
|
|
@ -96,7 +96,6 @@ PHP_METHOD(Collection, reversed);
|
|||
PHP_METHOD(Collection, shuffle);
|
||||
PHP_METHOD(Collection, single);
|
||||
PHP_METHOD(Collection, slice);
|
||||
PHP_METHOD(Collection, sliceRange);
|
||||
PHP_METHOD(Collection, sort);
|
||||
PHP_METHOD(Collection, sortBy);
|
||||
PHP_METHOD(Collection, sortByDescending);
|
||||
|
|
|
@ -117,10 +117,10 @@ class Collection implements ArrayAccess, Countable
|
|||
* Returns new collection which is a copy of range of original collection.
|
||||
*
|
||||
* @param int $from_index
|
||||
* @param int $to_index
|
||||
* @param int $num_elements
|
||||
* @return Collection
|
||||
*/
|
||||
function copyOfRange($from_index, $to_index) {}
|
||||
function copyOfRange($from_index, $num_elements) {}
|
||||
|
||||
/**
|
||||
* Returns the number of elements in this collection.
|
||||
|
@ -746,14 +746,6 @@ class Collection implements ArrayAccess, Countable
|
|||
*/
|
||||
function slice($keys) {}
|
||||
|
||||
/**
|
||||
* Returns a collection containing elements at indices in the specified indices range.
|
||||
*
|
||||
* @param int $from_index
|
||||
* @param int $to_index[optional]
|
||||
*/
|
||||
function sliceRange($from_index, $to_index) {}
|
||||
|
||||
/**
|
||||
* Sorts the collection in-place according to the natural order of its elements.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
--TEST--
|
||||
Test Collection::copyOfRange();
|
||||
--FILE--
|
||||
<?php
|
||||
// An ordinary array.
|
||||
$array = [3, 7, 6, 9, 2];
|
||||
// An associative array, however, Collection::copyOfRange() still works,
|
||||
// and string keys will be preserved.
|
||||
// Note that zend_array is ordered and random access has constant time complexity.
|
||||
$array1 = ['a' => 'b', 'c', 'd' => 'e'];
|
||||
$array2 = Collection::init($array)->copyOfRange(2, 4)->toArray();
|
||||
$array3 = Collection::init($array1)->copyOfRange(1, 2)->toArray();
|
||||
if ($array2 != array_slice($array, 2, 4) || $array3 != array_slice($array1, 1, 2))
|
||||
echo 'Collection::copyOfRange() failed.', PHP_EOL;
|
||||
?>
|
||||
--EXPECT--
|
|
@ -0,0 +1,12 @@
|
|||
--TEST--
|
||||
Test Collection::count() and countable interface.
|
||||
--FILE--
|
||||
<?php
|
||||
$array = [1, 2, 3, 4, 5, 6];
|
||||
$collection = Collection::init($array);
|
||||
if ($collection->count() != count($array))
|
||||
echo 'Collection::count() failed.', PHP_EOL;
|
||||
if (count($collection) != count($array))
|
||||
echo 'Test for countable interface failed.', PHP_EOL;
|
||||
?>
|
||||
--EXPECT--
|
Reference in New Issue