Bug fix. Performance boost.
This commit is contained in:
parent
f2402b9f67
commit
b5c3a0b4ad
|
@ -31,7 +31,6 @@ PHP_MINIT_FUNCTION(collections)
|
||||||
2, zend_ce_countable,
|
2, zend_ce_countable,
|
||||||
#endif
|
#endif
|
||||||
zend_ce_arrayaccess);
|
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));
|
collection_handlers = (zend_object_handlers*)emalloc(sizeof(zend_object_handlers));
|
||||||
memcpy(collection_handlers, &std_object_handlers, sizeof(zend_object_handlers));
|
memcpy(collection_handlers, &std_object_handlers, sizeof(zend_object_handlers));
|
||||||
collection_handlers->count_elements = count_collection;
|
collection_handlers->count_elements = count_collection;
|
||||||
|
|
|
@ -13,8 +13,7 @@
|
||||||
zend_object* (name) = (zend_object*)ecalloc(1, sizeof(zend_object) + \
|
zend_object* (name) = (zend_object*)ecalloc(1, sizeof(zend_object) + \
|
||||||
zend_object_properties_size(ce)); \
|
zend_object_properties_size(ce)); \
|
||||||
zend_object_std_init(name, ce); \
|
zend_object_std_init(name, ce); \
|
||||||
object_properties_init(name, ce); \
|
(name)->handlers = object_handlers
|
||||||
(name)->handlers = object_handlers;
|
|
||||||
#define NEW_COLLECTION_OBJ(name) \
|
#define NEW_COLLECTION_OBJ(name) \
|
||||||
NEW_OBJ(name, collections_collection_ce, collection_handlers)
|
NEW_OBJ(name, collections_collection_ce, collection_handlers)
|
||||||
#define NEW_PAIR_OBJ(name) \
|
#define NEW_PAIR_OBJ(name) \
|
||||||
|
@ -29,15 +28,14 @@
|
||||||
zend_update_property(ce, obj, #property_name, sizeof #property_name - 1, value)
|
zend_update_property(ce, obj, #property_name, sizeof #property_name - 1, value)
|
||||||
#define OBJ_PROPERTY_FETCH(ce, obj, property_name) \
|
#define OBJ_PROPERTY_FETCH(ce, obj, property_name) \
|
||||||
zend_read_property(ce, obj, #property_name, sizeof #property_name - 1, 1, &rv)
|
zend_read_property(ce, obj, #property_name, sizeof #property_name - 1, 1, &rv)
|
||||||
#define COLLECTION_UPDATE(obj, value) OBJ_PROPERTY_UPDATE(collections_collection_ce, obj, _, value)
|
|
||||||
#define COLLECTION_UPDATE_EX(value) COLLECTION_UPDATE(getThis(), value)
|
|
||||||
#define COLLECTION_FETCH(obj) OBJ_PROPERTY_FETCH(collections_collection_ce, obj, _)
|
|
||||||
#define COLLECTION_FETCH_EX() Z_ARRVAL_P(COLLECTION_FETCH(getThis()))
|
|
||||||
#define PAIR_UPDATE_FIRST(obj, value) OBJ_PROPERTY_UPDATE(collections_pair_ce, obj, first, value)
|
#define PAIR_UPDATE_FIRST(obj, value) OBJ_PROPERTY_UPDATE(collections_pair_ce, obj, first, value)
|
||||||
#define PAIR_UPDATE_SECOND(obj, value) OBJ_PROPERTY_UPDATE(collections_pair_ce, obj, second, value)
|
#define PAIR_UPDATE_SECOND(obj, value) OBJ_PROPERTY_UPDATE(collections_pair_ce, obj, second, value)
|
||||||
#define PAIR_FETCH_FIRST(obj) OBJ_PROPERTY_FETCH(collections_pair_ce, obj, first)
|
#define PAIR_FETCH_FIRST(obj) OBJ_PROPERTY_FETCH(collections_pair_ce, obj, first)
|
||||||
#define PAIR_FETCH_SECOND(obj) OBJ_PROPERTY_FETCH(collections_pair_ce, obj, second)
|
#define PAIR_FETCH_SECOND(obj) OBJ_PROPERTY_FETCH(collections_pair_ce, obj, second)
|
||||||
|
|
||||||
|
#define COLLECTION_FETCH(obj) Z_OBJPROP_P(obj)
|
||||||
|
#define COLLECTION_FETCH_EX() COLLECTION_FETCH(getThis())
|
||||||
|
|
||||||
#define INIT_FCI() \
|
#define INIT_FCI() \
|
||||||
zval params[2], retval; \
|
zval params[2], retval; \
|
||||||
fci.param_count = 2; \
|
fci.param_count = 2; \
|
||||||
|
@ -46,7 +44,6 @@
|
||||||
|
|
||||||
#define CALLBACK_KEYVAL_INVOKE(params, bucket) \
|
#define CALLBACK_KEYVAL_INVOKE(params, bucket) \
|
||||||
ZVAL_COPY_VALUE(¶ms[0], &bucket->val); \
|
ZVAL_COPY_VALUE(¶ms[0], &bucket->val); \
|
||||||
ZVAL_COPY(¶ms[0], &(bucket)->val); \
|
|
||||||
if ((bucket)->key) \
|
if ((bucket)->key) \
|
||||||
ZVAL_STR(¶ms[1], (bucket)->key); \
|
ZVAL_STR(¶ms[1], (bucket)->key); \
|
||||||
else \
|
else \
|
||||||
|
@ -71,9 +68,12 @@
|
||||||
#define ERR_NOT_ARITHMETIC() PHP_COLLECTIONS_ERROR(E_WARNING, "Elements should be int or double")
|
#define ERR_NOT_ARITHMETIC() PHP_COLLECTIONS_ERROR(E_WARNING, "Elements should be int or double")
|
||||||
|
|
||||||
#define ELEMENTS_VALIDATE(elements) \
|
#define ELEMENTS_VALIDATE(elements) \
|
||||||
|
zend_array* elements##_arr; \
|
||||||
if (IS_COLLECTION_P(elements)) \
|
if (IS_COLLECTION_P(elements)) \
|
||||||
(elements) = COLLECTION_FETCH(elements); \
|
(elements##_arr) = COLLECTION_FETCH(elements); \
|
||||||
else if (UNEXPECTED(Z_TYPE_P(elements) != IS_ARRAY)) { \
|
else if (UNEXPECTED(Z_TYPE_P(elements) == IS_ARRAY))\
|
||||||
|
(elements##_arr) = Z_ARRVAL_P(elements); \
|
||||||
|
else { \
|
||||||
ERR_BAD_ARGUMENT_TYPE(); \
|
ERR_BAD_ARGUMENT_TYPE(); \
|
||||||
return; \
|
return; \
|
||||||
}
|
}
|
||||||
|
@ -96,14 +96,11 @@
|
||||||
|
|
||||||
#define RETVAL_NEW_COLLECTION(collection) \
|
#define RETVAL_NEW_COLLECTION(collection) \
|
||||||
do { \
|
do { \
|
||||||
ALLOW_COW_VIOLATION(collection); \
|
|
||||||
NEW_COLLECTION_OBJ(obj); \
|
NEW_COLLECTION_OBJ(obj); \
|
||||||
zval _retval; \
|
zend_array* new_arr = collection; \
|
||||||
ZVAL_OBJ(&_retval, obj); \
|
if (GC_REFCOUNT(new_arr) > 1) \
|
||||||
zval _property; \
|
new_arr = zend_array_dup(new_arr) \
|
||||||
ZVAL_ARR(&_property, collection); \
|
object_properties_init_ex(obj, new_arr); \
|
||||||
COLLECTION_UPDATE(&_retval, &_property); \
|
|
||||||
zval_ptr_dtor(&_property); \
|
|
||||||
RETVAL_OBJ(obj); \
|
RETVAL_OBJ(obj); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -117,14 +114,14 @@ zval rv;
|
||||||
|
|
||||||
int count_collection(zval* obj, zend_long* count)
|
int count_collection(zval* obj, zend_long* count)
|
||||||
{
|
{
|
||||||
zend_array* current = Z_ARRVAL_P(COLLECTION_FETCH(obj));
|
zend_array* current = COLLECTION_FETCH(obj);
|
||||||
*count = zend_hash_num_elements(current);
|
*count = zend_hash_num_elements(current);
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int collection_offset_exists(zval* object, zval* offset, int check_empty)
|
int collection_offset_exists(zval* object, zval* offset, int check_empty)
|
||||||
{
|
{
|
||||||
zend_array* current = Z_ARRVAL_P(COLLECTION_FETCH(object));
|
zend_array* current = COLLECTION_FETCH(object);
|
||||||
if (check_empty)
|
if (check_empty)
|
||||||
return zend_hash_num_elements(current) == 0;
|
return zend_hash_num_elements(current) == 0;
|
||||||
if (Z_TYPE_P(offset) == IS_LONG)
|
if (Z_TYPE_P(offset) == IS_LONG)
|
||||||
|
@ -136,7 +133,7 @@ int collection_offset_exists(zval* object, zval* offset, int check_empty)
|
||||||
|
|
||||||
void collection_offset_set(zval* object, zval* offset, zval* value)
|
void collection_offset_set(zval* object, zval* offset, zval* value)
|
||||||
{
|
{
|
||||||
zend_array* current = Z_ARRVAL_P(COLLECTION_FETCH(object));
|
zend_array* current = COLLECTION_FETCH(object);
|
||||||
if (Z_TYPE_P(offset) == IS_LONG)
|
if (Z_TYPE_P(offset) == IS_LONG)
|
||||||
zend_hash_index_update(current, Z_LVAL_P(offset), value);
|
zend_hash_index_update(current, Z_LVAL_P(offset), value);
|
||||||
else if (Z_TYPE_P(offset) == IS_STRING)
|
else if (Z_TYPE_P(offset) == IS_STRING)
|
||||||
|
@ -147,7 +144,7 @@ zval* collection_offset_get(zval* object, zval* offset, int type, zval* retval)
|
||||||
{
|
{
|
||||||
// Note that we don't handle type. So don't do any fancy things with Collection
|
// Note that we don't handle type. So don't do any fancy things with Collection
|
||||||
// such as fetching a reference of a value, etc.
|
// such as fetching a reference of a value, etc.
|
||||||
zend_array* current = Z_ARRVAL_P(COLLECTION_FETCH(object));
|
zend_array* current = COLLECTION_FETCH(object);
|
||||||
zval* found = NULL;
|
zval* found = NULL;
|
||||||
if (Z_TYPE_P(offset) == IS_LONG)
|
if (Z_TYPE_P(offset) == IS_LONG)
|
||||||
found = zend_hash_index_find(current, Z_LVAL_P(offset));
|
found = zend_hash_index_find(current, Z_LVAL_P(offset));
|
||||||
|
@ -159,7 +156,7 @@ zval* collection_offset_get(zval* object, zval* offset, int type, zval* retval)
|
||||||
|
|
||||||
void collection_offset_unset(zval* object, zval* offset)
|
void collection_offset_unset(zval* object, zval* offset)
|
||||||
{
|
{
|
||||||
zend_array* current = Z_ARRVAL_P(COLLECTION_FETCH(object));
|
zend_array* current = COLLECTION_FETCH(object);
|
||||||
if (Z_TYPE_P(offset) == IS_LONG)
|
if (Z_TYPE_P(offset) == IS_LONG)
|
||||||
zend_hash_index_del(current, Z_LVAL_P(offset));
|
zend_hash_index_del(current, Z_LVAL_P(offset));
|
||||||
else if (Z_TYPE_P(offset) == IS_STRING)
|
else if (Z_TYPE_P(offset) == IS_STRING)
|
||||||
|
@ -177,7 +174,7 @@ PHP_METHOD(Collection, addAll)
|
||||||
ELEMENTS_VALIDATE(elements);
|
ELEMENTS_VALIDATE(elements);
|
||||||
zend_array* current = COLLECTION_FETCH_EX();
|
zend_array* current = COLLECTION_FETCH_EX();
|
||||||
ZEND_HASH_FILL_PACKED(current)
|
ZEND_HASH_FILL_PACKED(current)
|
||||||
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(elements), zval* val)
|
ZEND_HASH_FOREACH_VAL(elements_arr, zval* val)
|
||||||
ZEND_HASH_FILL_ADD(val);
|
ZEND_HASH_FILL_ADD(val);
|
||||||
ZEND_HASH_FOREACH_END();
|
ZEND_HASH_FOREACH_END();
|
||||||
ZEND_HASH_FILL_END();
|
ZEND_HASH_FILL_END();
|
||||||
|
@ -258,7 +255,7 @@ PHP_METHOD(Collection, associateTo)
|
||||||
ZEND_PARSE_PARAMETERS_END();
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
INIT_FCI();
|
INIT_FCI();
|
||||||
zend_array* current = COLLECTION_FETCH_EX();
|
zend_array* current = COLLECTION_FETCH_EX();
|
||||||
zend_array* dest_arr = Z_ARRVAL_P(COLLECTION_FETCH(dest));
|
zend_array* dest_arr = COLLECTION_FETCH(dest);
|
||||||
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
|
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
|
||||||
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
||||||
if (IS_PAIR(retval)) {
|
if (IS_PAIR(retval)) {
|
||||||
|
@ -312,7 +309,7 @@ PHP_METHOD(Collection, associateByTo)
|
||||||
ZEND_PARSE_PARAMETERS_END();
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
INIT_FCI();
|
INIT_FCI();
|
||||||
zend_array* current = COLLECTION_FETCH_EX();
|
zend_array* current = COLLECTION_FETCH_EX();
|
||||||
zend_array* dest_arr = Z_ARRVAL_P(COLLECTION_FETCH(dest));
|
zend_array* dest_arr = COLLECTION_FETCH(dest);
|
||||||
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
|
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
|
||||||
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
||||||
if (Z_TYPE(retval) == IS_LONG)
|
if (Z_TYPE(retval) == IS_LONG)
|
||||||
|
@ -351,7 +348,7 @@ PHP_METHOD(Collection, containsAll)
|
||||||
ELEMENTS_VALIDATE(elements);
|
ELEMENTS_VALIDATE(elements);
|
||||||
zval rv;
|
zval rv;
|
||||||
zend_array* current = COLLECTION_FETCH_EX();
|
zend_array* current = COLLECTION_FETCH_EX();
|
||||||
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(elements), zval* element)
|
ZEND_HASH_FOREACH_VAL(elements_arr, zval* element)
|
||||||
INIT_EQUAL_CHECK_FUNC(element);
|
INIT_EQUAL_CHECK_FUNC(element);
|
||||||
int result = 0;
|
int result = 0;
|
||||||
ZEND_HASH_FOREACH_VAL(current, zval* val)
|
ZEND_HASH_FOREACH_VAL(current, zval* val)
|
||||||
|
@ -479,7 +476,7 @@ PHP_METHOD(Collection, drop)
|
||||||
ZEND_PARSE_PARAMETERS_END();
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
ERR_BAD_SIZE();
|
ERR_BAD_SIZE();
|
||||||
RETURN_NULL();
|
return;
|
||||||
}
|
}
|
||||||
zend_array* current = COLLECTION_FETCH_EX();
|
zend_array* current = COLLECTION_FETCH_EX();
|
||||||
ARRAY_CLONE(new_collection, current);
|
ARRAY_CLONE(new_collection, current);
|
||||||
|
@ -501,9 +498,8 @@ PHP_METHOD(Collection, dropLast)
|
||||||
ZEND_PARSE_PARAMETERS_END();
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
ERR_BAD_SIZE();
|
ERR_BAD_SIZE();
|
||||||
RETURN_NULL();
|
return;
|
||||||
}
|
}
|
||||||
zval rv;
|
|
||||||
zend_array* current = COLLECTION_FETCH_EX();
|
zend_array* current = COLLECTION_FETCH_EX();
|
||||||
ARRAY_CLONE(new_collection, current);
|
ARRAY_CLONE(new_collection, current);
|
||||||
unsigned idx = new_collection->nNumUsed;
|
unsigned idx = new_collection->nNumUsed;
|
||||||
|
@ -572,8 +568,6 @@ PHP_METHOD(Collection, fill)
|
||||||
Bucket* bucket = current->arData;
|
Bucket* bucket = current->arData;
|
||||||
Bucket* end = bucket + current->nNumUsed;
|
Bucket* end = bucket + current->nNumUsed;
|
||||||
for (bucket += from_idx; num_elements > 0 && bucket < end; ++bucket, --num_elements) {
|
for (bucket += from_idx; num_elements > 0 && bucket < end; ++bucket, --num_elements) {
|
||||||
if (Z_REFCOUNTED(bucket->val))
|
|
||||||
GC_ADDREF(Z_COUNTED(bucket->val));
|
|
||||||
if (bucket->key)
|
if (bucket->key)
|
||||||
zend_hash_update(current, bucket->key, element);
|
zend_hash_update(current, bucket->key, element);
|
||||||
else
|
else
|
||||||
|
@ -634,7 +628,7 @@ PHP_METHOD(Collection, filterNotTo)
|
||||||
ZEND_PARSE_PARAMETERS_END();
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
INIT_FCI();
|
INIT_FCI();
|
||||||
zend_array* current = COLLECTION_FETCH_EX();
|
zend_array* current = COLLECTION_FETCH_EX();
|
||||||
zend_array* dest_arr = Z_ARRVAL_P(COLLECTION_FETCH(dest));
|
zend_array* dest_arr = COLLECTION_FETCH(dest);
|
||||||
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
|
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
|
||||||
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
||||||
if (!zend_is_true(&retval))
|
if (!zend_is_true(&retval))
|
||||||
|
@ -657,7 +651,7 @@ PHP_METHOD(Collection, filterTo)
|
||||||
ZEND_PARSE_PARAMETERS_END();
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
INIT_FCI();
|
INIT_FCI();
|
||||||
zend_array* current = COLLECTION_FETCH_EX();
|
zend_array* current = COLLECTION_FETCH_EX();
|
||||||
zend_array* dest_arr = Z_ARRVAL_P(COLLECTION_FETCH(dest));
|
zend_array* dest_arr = COLLECTION_FETCH(dest);
|
||||||
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
|
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
|
||||||
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
||||||
if (zend_is_true(&retval))
|
if (zend_is_true(&retval))
|
||||||
|
@ -707,7 +701,7 @@ PHP_METHOD(Collection, flatMap)
|
||||||
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
||||||
zval* retval_p = &retval;
|
zval* retval_p = &retval;
|
||||||
ELEMENTS_VALIDATE(retval_p);
|
ELEMENTS_VALIDATE(retval_p);
|
||||||
ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(retval_p), Bucket* bucket)
|
ZEND_HASH_FOREACH_BUCKET(retval_p_arr, Bucket* bucket)
|
||||||
if (Z_REFCOUNTED(bucket->val))
|
if (Z_REFCOUNTED(bucket->val))
|
||||||
GC_ADDREF(Z_COUNTED(bucket->val));
|
GC_ADDREF(Z_COUNTED(bucket->val));
|
||||||
if (bucket->key)
|
if (bucket->key)
|
||||||
|
@ -731,12 +725,12 @@ PHP_METHOD(Collection, flatMapTo)
|
||||||
ZEND_PARSE_PARAMETERS_END();
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
INIT_FCI();
|
INIT_FCI();
|
||||||
zend_array* current = COLLECTION_FETCH_EX();
|
zend_array* current = COLLECTION_FETCH_EX();
|
||||||
zend_array* dest_arr = Z_ARRVAL_P(COLLECTION_FETCH(dest));
|
zend_array* dest_arr = COLLECTION_FETCH(dest);
|
||||||
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
|
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
|
||||||
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
||||||
zval* retval_p = &retval;
|
zval* retval_p = &retval;
|
||||||
ELEMENTS_VALIDATE(retval_p);
|
ELEMENTS_VALIDATE(retval_p);
|
||||||
ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(retval_p), Bucket* bucket)
|
ZEND_HASH_FOREACH_BUCKET(retval_p_arr, Bucket* bucket)
|
||||||
if (Z_REFCOUNTED(bucket->val))
|
if (Z_REFCOUNTED(bucket->val))
|
||||||
GC_ADDREF(Z_COUNTED(bucket->val));
|
GC_ADDREF(Z_COUNTED(bucket->val));
|
||||||
if (bucket->key)
|
if (bucket->key)
|
||||||
|
@ -808,8 +802,7 @@ PHP_METHOD(Collection, init)
|
||||||
ZEND_PARSE_PARAMETERS_END();
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
if (elements) {
|
if (elements) {
|
||||||
ELEMENTS_VALIDATE(elements);
|
ELEMENTS_VALIDATE(elements);
|
||||||
ARRAY_CLONE(new_collection, Z_ARRVAL_P(elements));
|
RETURN_NEW_COLLECTION(elements_arr);
|
||||||
RETURN_NEW_COLLECTION(new_collection);
|
|
||||||
}
|
}
|
||||||
ARRAY_NEW(collection, 0);
|
ARRAY_NEW(collection, 0);
|
||||||
RETVAL_NEW_COLLECTION(collection);
|
RETVAL_NEW_COLLECTION(collection);
|
||||||
|
@ -1123,10 +1116,9 @@ PHP_METHOD(Collection, takeWhile)
|
||||||
|
|
||||||
PHP_METHOD(Collection, toArray)
|
PHP_METHOD(Collection, toArray)
|
||||||
{
|
{
|
||||||
zval rv;
|
zend_array* retval = COLLECTION_FETCH_EX();
|
||||||
zend_array* data = COLLECTION_FETCH_EX();
|
GC_ADDREF(retval);
|
||||||
GC_ADDREF(data);
|
RETVAL_ARR(retval);
|
||||||
RETVAL_ARR(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PHP_METHOD(Collection, toCollection)
|
PHP_METHOD(Collection, toCollection)
|
||||||
|
|
Reference in New Issue