Fix bugs. Refactor code. Improve performance of `Pair`.
This commit is contained in:
parent
f26e503772
commit
639479d031
|
@ -19,18 +19,10 @@ zend_object_handlers collection_handlers;
|
||||||
zend_class_entry* collections_collection_ce;
|
zend_class_entry* collections_collection_ce;
|
||||||
zend_class_entry* collections_pair_ce;
|
zend_class_entry* collections_pair_ce;
|
||||||
|
|
||||||
zend_string* collections_pair_first;
|
|
||||||
zend_string* collections_pair_second;
|
|
||||||
|
|
||||||
ZEND_DECLARE_MODULE_GLOBALS(collections)
|
ZEND_DECLARE_MODULE_GLOBALS(collections)
|
||||||
|
|
||||||
PHP_MINIT_FUNCTION(collections)
|
static zend_always_inline void collection_ce_init()
|
||||||
{
|
{
|
||||||
#ifdef ZTS
|
|
||||||
ZEND_INIT_MODULE_GLOBALS(collections, NULL, NULL);
|
|
||||||
#endif
|
|
||||||
collections_pair_first = zend_string_init("first", sizeof "first" - 1, 1);
|
|
||||||
collections_pair_second = zend_string_init("second", sizeof "second" - 1, 1);
|
|
||||||
zend_class_entry collection_ce;
|
zend_class_entry collection_ce;
|
||||||
INIT_CLASS_ENTRY_EX(collection_ce, "Collection", sizeof "Collection" - 1, collection_methods);
|
INIT_CLASS_ENTRY_EX(collection_ce, "Collection", sizeof "Collection" - 1, collection_methods);
|
||||||
collections_collection_ce = zend_register_internal_class(&collection_ce);
|
collections_collection_ce = zend_register_internal_class(&collection_ce);
|
||||||
|
@ -46,14 +38,33 @@ PHP_MINIT_FUNCTION(collections)
|
||||||
#endif
|
#endif
|
||||||
zend_ce_arrayaccess);
|
zend_ce_arrayaccess);
|
||||||
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.unset_dimension = collection_offset_unset;
|
collection_handlers.unset_dimension = collection_offset_unset;
|
||||||
|
collection_handlers.unset_property = collection_property_unset;
|
||||||
collection_handlers.write_dimension = collection_offset_set;
|
collection_handlers.write_dimension = collection_offset_set;
|
||||||
|
collection_handlers.write_property = collection_property_set;
|
||||||
collection_handlers.read_dimension = collection_offset_get;
|
collection_handlers.read_dimension = collection_offset_get;
|
||||||
|
collection_handlers.read_property = collection_property_get;
|
||||||
collection_handlers.has_dimension = collection_offset_exists;
|
collection_handlers.has_dimension = collection_offset_exists;
|
||||||
|
collection_handlers.has_property = collection_property_exists;
|
||||||
|
collection_handlers.count_elements = count_collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
static zend_always_inline void pair_ce_init()
|
||||||
|
{
|
||||||
zend_class_entry pair_ce;
|
zend_class_entry pair_ce;
|
||||||
INIT_CLASS_ENTRY_EX(pair_ce, "Pair", sizeof "Pair" - 1, pair_methods);
|
INIT_CLASS_ENTRY_EX(pair_ce, "Pair", sizeof "Pair" - 1, pair_methods);
|
||||||
collections_pair_ce = zend_register_internal_class(&pair_ce);
|
collections_pair_ce = zend_register_internal_class(&pair_ce);
|
||||||
|
zend_declare_property_null(collections_pair_ce, "first", sizeof "first" - 1, ZEND_ACC_PUBLIC);
|
||||||
|
zend_declare_property_null(collections_pair_ce, "second", sizeof "second" - 1, ZEND_ACC_PUBLIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_MINIT_FUNCTION(collections)
|
||||||
|
{
|
||||||
|
#ifdef ZTS
|
||||||
|
ZEND_INIT_MODULE_GLOBALS(collections, NULL, NULL);
|
||||||
|
#endif
|
||||||
|
collection_ce_init();
|
||||||
|
pair_ce_init();
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,41 +12,23 @@
|
||||||
#include "php_collections_me.h"
|
#include "php_collections_me.h"
|
||||||
|
|
||||||
#if PHP_VERSION_ID < 70300
|
#if PHP_VERSION_ID < 70300
|
||||||
#define GC_ADDREF(p) ++GC_REFCOUNT(p)
|
#define GC_ADDREF(p) ++GC_REFCOUNT(p)
|
||||||
#define GC_DELREF(p) --GC_REFCOUNT(p)
|
#define GC_DELREF(p) --GC_REFCOUNT(p)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define FCI_G COLLECTIONS_G(fci)
|
#define FCI_G COLLECTIONS_G(fci)
|
||||||
#define FCC_G COLLECTIONS_G(fcc)
|
#define FCC_G COLLECTIONS_G(fcc)
|
||||||
|
|
||||||
#define NEW_OBJ(name, ce, object_handlers) \
|
#define COLLECTION_FETCH(val) (Z_OBJ_P(val)->properties)
|
||||||
zend_object* (name) = (zend_object*)ecalloc(1, sizeof(zend_object) + \
|
#define COLLECTION_FETCH_CURRENT() COLLECTION_FETCH(getThis())
|
||||||
zend_object_properties_size(ce)); \
|
#define PAIR_FETCH_FIRST(obj) OBJ_PROP_NUM(obj, 0)
|
||||||
zend_object_std_init(name, ce); \
|
#define PAIR_FETCH_SECOND(obj) OBJ_PROP_NUM(obj, 1)
|
||||||
(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); \
|
|
||||||
name->properties = (zend_array*)emalloc(sizeof(zend_array)); \
|
|
||||||
zend_hash_init(name->properties, 2, NULL, ZVAL_PTR_DTOR, 0)
|
|
||||||
|
|
||||||
#define IS_COLLECTION_P(zval) \
|
#define IS_COLLECTION_P(zval) \
|
||||||
Z_TYPE_P(zval) == IS_OBJECT && Z_OBJCE_P(zval) == collections_collection_ce
|
Z_TYPE_P(zval) == IS_OBJECT && Z_OBJCE_P(zval) == collections_collection_ce
|
||||||
#define IS_PAIR(zval) \
|
#define IS_PAIR(zval) \
|
||||||
EXPECTED(Z_TYPE(zval) == IS_OBJECT) && EXPECTED(Z_OBJCE(zval) == collections_pair_ce)
|
EXPECTED(Z_TYPE(zval) == IS_OBJECT) && EXPECTED(Z_OBJCE(zval) == collections_pair_ce)
|
||||||
|
|
||||||
#define OBJ_PROPERTY_UPDATE(obj, property_name, value) \
|
|
||||||
zend_hash_update((obj)->properties, property_name, value)
|
|
||||||
#define OBJ_PROPERTY_FETCH(obj, property_name) \
|
|
||||||
zend_hash_find((obj)->properties, property_name)
|
|
||||||
#define PAIR_UPDATE_FIRST(obj, value) OBJ_PROPERTY_UPDATE(obj, collections_pair_first, value)
|
|
||||||
#define PAIR_UPDATE_SECOND(obj, value) OBJ_PROPERTY_UPDATE(obj, collections_pair_second, value)
|
|
||||||
#define PAIR_FETCH_FIRST(obj) OBJ_PROPERTY_FETCH(obj, collections_pair_first)
|
|
||||||
#define PAIR_FETCH_SECOND(obj) OBJ_PROPERTY_FETCH(obj, collections_pair_second)
|
|
||||||
#define COLLECTION_FETCH(obj) Z_OBJ_P(obj)->properties
|
|
||||||
#define COLLECTION_FETCH_CURRENT() COLLECTION_FETCH(getThis())
|
|
||||||
|
|
||||||
#define SEPARATE_COLLECTION(ht, obj) \
|
#define SEPARATE_COLLECTION(ht, obj) \
|
||||||
if (GC_REFCOUNT(ht) > 1) \
|
if (GC_REFCOUNT(ht) > 1) \
|
||||||
{ \
|
{ \
|
||||||
|
@ -118,7 +100,7 @@
|
||||||
#define RETVAL_NEW_COLLECTION(collection) \
|
#define RETVAL_NEW_COLLECTION(collection) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
NEW_COLLECTION_OBJ(obj); \
|
zend_object* obj = create_collection_obj(); \
|
||||||
if (GC_REFCOUNT(collection) > 1) \
|
if (GC_REFCOUNT(collection) > 1) \
|
||||||
GC_ADDREF(collection); \
|
GC_ADDREF(collection); \
|
||||||
obj->properties = collection; \
|
obj->properties = collection; \
|
||||||
|
@ -136,6 +118,39 @@ typedef int (*equal_check_func_t)(zval*, zval*);
|
||||||
/// Unused global variable.
|
/// Unused global variable.
|
||||||
zval rv;
|
zval rv;
|
||||||
|
|
||||||
|
static zend_always_inline void pair_update_first(zend_object* obj, zval* value)
|
||||||
|
{
|
||||||
|
zval_ptr_dtor(PAIR_FETCH_FIRST(obj));
|
||||||
|
ZVAL_COPY_VALUE(PAIR_FETCH_FIRST(obj), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static zend_always_inline void pair_update_second(zend_object* obj, zval* value)
|
||||||
|
{
|
||||||
|
zval_ptr_dtor(PAIR_FETCH_SECOND(obj));
|
||||||
|
ZVAL_COPY_VALUE(PAIR_FETCH_SECOND(obj), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static zend_always_inline zend_object* create_object(zend_class_entry* ce,
|
||||||
|
zend_object_handlers* handlers)
|
||||||
|
{
|
||||||
|
zend_object* obj = (zend_object*)ecalloc(1, sizeof(zend_object) +
|
||||||
|
zend_object_properties_size(ce));
|
||||||
|
zend_object_std_init(obj, ce);
|
||||||
|
object_properties_init(obj, ce);
|
||||||
|
obj->handlers = handlers;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
static zend_always_inline zend_object* create_collection_obj()
|
||||||
|
{
|
||||||
|
return create_object(collections_collection_ce, &collection_handlers);
|
||||||
|
}
|
||||||
|
|
||||||
|
static zend_always_inline zend_object* create_pair_obj()
|
||||||
|
{
|
||||||
|
return create_object(collections_pair_ce, &std_object_handlers);
|
||||||
|
}
|
||||||
|
|
||||||
static zend_always_inline void bucket_to_pair(zend_object* pair, Bucket* bucket)
|
static zend_always_inline void bucket_to_pair(zend_object* pair, Bucket* bucket)
|
||||||
{
|
{
|
||||||
zval key;
|
zval key;
|
||||||
|
@ -148,8 +163,8 @@ static zend_always_inline void bucket_to_pair(zend_object* pair, Bucket* bucket)
|
||||||
{
|
{
|
||||||
ZVAL_LONG(&key, bucket->h);
|
ZVAL_LONG(&key, bucket->h);
|
||||||
}
|
}
|
||||||
PAIR_UPDATE_FIRST(pair, &key);
|
pair_update_first(pair, &key);
|
||||||
PAIR_UPDATE_SECOND(pair, &bucket->val);
|
pair_update_second(pair, &bucket->val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bucket_compare_numeric(const void* op1, const void* op2)
|
static int bucket_compare_numeric(const void* op1, const void* op2)
|
||||||
|
@ -448,6 +463,37 @@ int collection_offset_exists(zval* object, zval* offset, int check_empty)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int collection_property_exists(zval* object, zval* member, int has_set_exists,
|
||||||
|
void** unused)
|
||||||
|
{
|
||||||
|
zend_array* current = COLLECTION_FETCH(object);
|
||||||
|
zval* found = NULL;
|
||||||
|
if (EXPECTED(Z_TYPE_P(member) == IS_STRING))
|
||||||
|
{
|
||||||
|
found = zend_hash_find(current, Z_STR_P(member));
|
||||||
|
}
|
||||||
|
else if (EXPECTED(Z_TYPE_P(member) == IS_LONG))
|
||||||
|
{
|
||||||
|
found = zend_hash_index_find(current, Z_LVAL_P(member));
|
||||||
|
}
|
||||||
|
if (found == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// whether property exists and is not NULL
|
||||||
|
if (has_set_exists == 0)
|
||||||
|
{
|
||||||
|
return Z_TYPE_P(found) != IS_NULL;
|
||||||
|
}
|
||||||
|
// whether property exists and is true
|
||||||
|
else if (has_set_exists == 1)
|
||||||
|
{
|
||||||
|
return zend_is_true(found);
|
||||||
|
}
|
||||||
|
// whether property exists
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
void collection_offset_set(zval* object, zval* offset, zval* value)
|
void collection_offset_set(zval* object, zval* offset, zval* value)
|
||||||
{
|
{
|
||||||
zend_array* current = COLLECTION_FETCH(object);
|
zend_array* current = COLLECTION_FETCH(object);
|
||||||
|
@ -464,10 +510,15 @@ void collection_offset_set(zval* object, zval* offset, zval* value)
|
||||||
{
|
{
|
||||||
ERR_BAD_KEY_TYPE();
|
ERR_BAD_KEY_TYPE();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Z_TRY_ADDREF_P(value);
|
Z_TRY_ADDREF_P(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void collection_property_set(zval* object, zval* member, zval* value, void** unused)
|
||||||
|
{
|
||||||
|
collection_offset_set(object, member, value);
|
||||||
|
}
|
||||||
|
|
||||||
zval* collection_offset_get(zval* object, zval* offset, int type, zval* retval)
|
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
|
||||||
|
@ -482,10 +533,23 @@ zval* collection_offset_get(zval* object, zval* offset, int type, zval* retval)
|
||||||
{
|
{
|
||||||
found = zend_hash_find(current, Z_STR_P(offset));
|
found = zend_hash_find(current, Z_STR_P(offset));
|
||||||
}
|
}
|
||||||
ZVAL_COPY(retval, found);
|
if (found)
|
||||||
|
{
|
||||||
|
ZVAL_COPY_VALUE(retval, found);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retval = &EG(uninitialized_zval);
|
||||||
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
zval* collection_property_get(zval* object, zval* member, int type, void** unused,
|
||||||
|
zval* retval)
|
||||||
|
{
|
||||||
|
return collection_offset_get(object, member, type, retval);
|
||||||
|
}
|
||||||
|
|
||||||
void collection_offset_unset(zval* object, zval* offset)
|
void collection_offset_unset(zval* object, zval* offset)
|
||||||
{
|
{
|
||||||
zend_array* current = COLLECTION_FETCH(object);
|
zend_array* current = COLLECTION_FETCH(object);
|
||||||
|
@ -500,6 +564,11 @@ void collection_offset_unset(zval* object, zval* offset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void collection_property_unset(zval* object, zval* member, void** unused)
|
||||||
|
{
|
||||||
|
collection_offset_unset(object, member);
|
||||||
|
}
|
||||||
|
|
||||||
PHP_METHOD(Collection, __construct) {}
|
PHP_METHOD(Collection, __construct) {}
|
||||||
|
|
||||||
PHP_METHOD(Collection, addAll)
|
PHP_METHOD(Collection, addAll)
|
||||||
|
@ -1769,7 +1838,7 @@ PHP_METHOD(Collection, maxWith)
|
||||||
zend_array* current = COLLECTION_FETCH_CURRENT();
|
zend_array* current = COLLECTION_FETCH_CURRENT();
|
||||||
ARRAY_CLONE(max_with, current);
|
ARRAY_CLONE(max_with, current);
|
||||||
ZEND_HASH_FOREACH_BUCKET(max_with, Bucket* bucket)
|
ZEND_HASH_FOREACH_BUCKET(max_with, Bucket* bucket)
|
||||||
NEW_PAIR_OBJ(obj);
|
zend_object* obj = create_pair_obj();
|
||||||
bucket_to_pair(obj, bucket);
|
bucket_to_pair(obj, bucket);
|
||||||
ZVAL_OBJ(&bucket->val, obj);
|
ZVAL_OBJ(&bucket->val, obj);
|
||||||
ZEND_HASH_FOREACH_END();
|
ZEND_HASH_FOREACH_END();
|
||||||
|
@ -1853,7 +1922,7 @@ PHP_METHOD(Collection, minWith)
|
||||||
zend_array* current = COLLECTION_FETCH_CURRENT();
|
zend_array* current = COLLECTION_FETCH_CURRENT();
|
||||||
ARRAY_CLONE(min_with, current);
|
ARRAY_CLONE(min_with, current);
|
||||||
ZEND_HASH_FOREACH_BUCKET(min_with, Bucket* bucket)
|
ZEND_HASH_FOREACH_BUCKET(min_with, Bucket* bucket)
|
||||||
NEW_PAIR_OBJ(obj);
|
zend_object* obj = create_pair_obj();
|
||||||
bucket_to_pair(obj, bucket);
|
bucket_to_pair(obj, bucket);
|
||||||
ZVAL_OBJ(&bucket->val, obj);
|
ZVAL_OBJ(&bucket->val, obj);
|
||||||
ZEND_HASH_FOREACH_END();
|
ZEND_HASH_FOREACH_END();
|
||||||
|
@ -1949,7 +2018,7 @@ PHP_METHOD(Collection, partition)
|
||||||
ZEND_PARSE_PARAMETERS_END();
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
INIT_FCI(&fci, 2);
|
INIT_FCI(&fci, 2);
|
||||||
zend_array* current = COLLECTION_FETCH_CURRENT();
|
zend_array* current = COLLECTION_FETCH_CURRENT();
|
||||||
NEW_PAIR_OBJ(pair);
|
zend_object* pair = create_pair_obj();
|
||||||
ARRAY_NEW_EX(first_arr, current);
|
ARRAY_NEW_EX(first_arr, current);
|
||||||
ARRAY_NEW_EX(second_arr, current);
|
ARRAY_NEW_EX(second_arr, current);
|
||||||
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
|
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
|
||||||
|
@ -1973,8 +2042,8 @@ PHP_METHOD(Collection, partition)
|
||||||
zval first, second;
|
zval first, second;
|
||||||
ZVAL_ARR(&first, first_arr);
|
ZVAL_ARR(&first, first_arr);
|
||||||
ZVAL_ARR(&second, second_arr);
|
ZVAL_ARR(&second, second_arr);
|
||||||
PAIR_UPDATE_FIRST(pair, &first);
|
pair_update_first(pair, &first);
|
||||||
PAIR_UPDATE_SECOND(pair, &second);
|
pair_update_second(pair, &second);
|
||||||
RETVAL_OBJ(pair);
|
RETVAL_OBJ(pair);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2519,7 +2588,7 @@ PHP_METHOD(Collection, sortWith)
|
||||||
zend_array* current = COLLECTION_FETCH_CURRENT();
|
zend_array* current = COLLECTION_FETCH_CURRENT();
|
||||||
ARRAY_CLONE(sorted_with, current);
|
ARRAY_CLONE(sorted_with, current);
|
||||||
ZEND_HASH_FOREACH_BUCKET(sorted_with, Bucket* bucket)
|
ZEND_HASH_FOREACH_BUCKET(sorted_with, Bucket* bucket)
|
||||||
NEW_PAIR_OBJ(obj);
|
zend_object* obj = create_pair_obj();
|
||||||
bucket_to_pair(obj, bucket);
|
bucket_to_pair(obj, bucket);
|
||||||
ZVAL_OBJ(&bucket->val, obj);
|
ZVAL_OBJ(&bucket->val, obj);
|
||||||
ZEND_HASH_FOREACH_END();
|
ZEND_HASH_FOREACH_END();
|
||||||
|
@ -2672,7 +2741,7 @@ PHP_METHOD(Collection, sortedWith)
|
||||||
zend_array* current = COLLECTION_FETCH_CURRENT();
|
zend_array* current = COLLECTION_FETCH_CURRENT();
|
||||||
ARRAY_CLONE(sorted_with, current);
|
ARRAY_CLONE(sorted_with, current);
|
||||||
ZEND_HASH_FOREACH_BUCKET(sorted_with, Bucket* bucket)
|
ZEND_HASH_FOREACH_BUCKET(sorted_with, Bucket* bucket)
|
||||||
NEW_PAIR_OBJ(obj);
|
zend_object* obj = create_pair_obj();
|
||||||
bucket_to_pair(obj, bucket);
|
bucket_to_pair(obj, bucket);
|
||||||
ZVAL_OBJ(&bucket->val, obj);
|
ZVAL_OBJ(&bucket->val, obj);
|
||||||
ZEND_HASH_FOREACH_END();
|
ZEND_HASH_FOREACH_END();
|
||||||
|
@ -2903,7 +2972,7 @@ PHP_METHOD(Collection, toPairs)
|
||||||
zend_array* current = COLLECTION_FETCH_CURRENT();
|
zend_array* current = COLLECTION_FETCH_CURRENT();
|
||||||
ARRAY_NEW_EX(new_collection, current);
|
ARRAY_NEW_EX(new_collection, current);
|
||||||
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
|
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
|
||||||
NEW_PAIR_OBJ(obj);
|
zend_object* obj = create_pair_obj();
|
||||||
bucket_to_pair(obj, bucket);
|
bucket_to_pair(obj, bucket);
|
||||||
zval pair;
|
zval pair;
|
||||||
ZVAL_OBJ(&pair, obj);
|
ZVAL_OBJ(&pair, obj);
|
||||||
|
@ -2935,8 +3004,8 @@ PHP_METHOD(Pair, __construct)
|
||||||
Z_PARAM_ZVAL(first)
|
Z_PARAM_ZVAL(first)
|
||||||
Z_PARAM_ZVAL(second)
|
Z_PARAM_ZVAL(second)
|
||||||
ZEND_PARSE_PARAMETERS_END();
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
zend_array* properties = Z_OBJ_P(getThis())->properties = (zend_array*)emalloc(sizeof(zend_array));
|
Z_TRY_ADDREF_P(first);
|
||||||
zend_hash_init(properties, 2, NULL, ZVAL_PTR_DTOR, 0);
|
Z_TRY_ADDREF_P(second);
|
||||||
PAIR_UPDATE_FIRST(Z_OBJ_P(getThis()), first);
|
pair_update_first(Z_OBJ_P(getThis()), first);
|
||||||
PAIR_UPDATE_SECOND(Z_OBJ_P(getThis()), second);
|
pair_update_second(Z_OBJ_P(getThis()), second);
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,9 +48,6 @@ ZEND_TSRMLS_CACHE_EXTERN()
|
||||||
extern PHP_COLLECTIONS_API zend_class_entry* collections_collection_ce;
|
extern PHP_COLLECTIONS_API zend_class_entry* collections_collection_ce;
|
||||||
extern PHP_COLLECTIONS_API zend_class_entry* collections_pair_ce;
|
extern PHP_COLLECTIONS_API zend_class_entry* collections_pair_ce;
|
||||||
|
|
||||||
extern zend_string* collections_pair_first;
|
|
||||||
extern zend_string* collections_pair_second;
|
|
||||||
|
|
||||||
extern zend_object_handlers collection_handlers;
|
extern zend_object_handlers collection_handlers;
|
||||||
|
|
||||||
int count_collection(zval* obj, zend_long* count);
|
int count_collection(zval* obj, zend_long* count);
|
||||||
|
@ -58,6 +55,10 @@ 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);
|
||||||
zval* collection_offset_get(zval* object, zval* offset, int type, zval* retval);
|
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);
|
||||||
|
int collection_property_exists(zval* object, zval* member, int has_set_exists, void**);
|
||||||
|
void collection_property_set(zval* object, zval* member, zval* value, void**);
|
||||||
|
zval* collection_property_get(zval* object, zval* member, int type, void**, zval* retval);
|
||||||
|
void collection_property_unset(zval* object, zval* member, void**);
|
||||||
|
|
||||||
extern const zend_function_entry collection_methods[];
|
extern const zend_function_entry collection_methods[];
|
||||||
extern const zend_function_entry pair_methods[];
|
extern const zend_function_entry pair_methods[];
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
--TEST--
|
||||||
|
Test accessing elements of Collection as object properties.
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
$collection = Collection::init([
|
||||||
|
'a' => 'b',
|
||||||
|
'c' => 'd',
|
||||||
|
'e' => 0,
|
||||||
|
'f' => null
|
||||||
|
]);
|
||||||
|
if (!property_exists($collection, 'e') || !property_exists($collection, 'f') ||
|
||||||
|
!isset($collection->e) || isset($collection->f) ||
|
||||||
|
!empty($collection->e) || !empty($collection->f)
|
||||||
|
) {
|
||||||
|
echo 'Test for handlers.has_property failed.', PHP_EOL;
|
||||||
|
}
|
||||||
|
if ($collection->a != 'b') {
|
||||||
|
echo 'Test for handlers.read_property failed.', PHP_EOL;
|
||||||
|
}
|
||||||
|
$collection->c = 'g';
|
||||||
|
if ($collection->c != 'g') {
|
||||||
|
echo 'Test for handlers.write_property failed.', PHP_EOL;
|
||||||
|
}
|
||||||
|
unset($collection->e);
|
||||||
|
if (isset($collection->e)) {
|
||||||
|
echo 'Test for handlers.unset_property failed.', PHP_EOL;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
Reference in New Issue