diff --git a/.travis.yml b/.travis.yml index eb3f49a..ec26a9c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,5 +14,4 @@ script: - phpize - ./configure - make - - echo $'n\n' | make test - - sudo make install \ No newline at end of file + - make test \ No newline at end of file diff --git a/config.m4 b/config.m4 index fe70154..e8469a1 100644 --- a/config.m4 +++ b/config.m4 @@ -1,15 +1,7 @@ PHP_ARG_ENABLE(collections, for collections support, [ --enable-collections Enable collections support]) -PHP_ARG_ENABLE(collections-debug, for debug support, -[ --enable-collections-debug Compile with debug symbols], no, no) - if test "$PHP_COLLECTIONS" != "no"; then - if test "$PHP_COLLECTIONS_DEBUG" != "no"; then - CFLAGS="-g -O0" - else - CFLAGS="-O2" - fi COLLECTIONS_SRC="src/collections.c src/collections_me.c src/collections_methods.c" diff --git a/src/collections.c b/src/collections.c index d3329be..6787c97 100644 --- a/src/collections.c +++ b/src/collections.c @@ -40,6 +40,10 @@ PHP_MINIT_FUNCTION(collections) 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; + collection_handlers->unset_dimension = collection_offset_unset; + collection_handlers->write_dimension = collection_offset_set; + collection_handlers->read_dimension = collection_offset_get; + collection_handlers->has_dimension = collection_offset_exists; 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); diff --git a/src/collections_me.c b/src/collections_me.c index 8de9b6e..af49843 100644 --- a/src/collections_me.c +++ b/src/collections_me.c @@ -6,7 +6,6 @@ #include -#include "php_collections.h" #include "php_collections_me.h" ZEND_BEGIN_ARG_INFO(action_arginfo, 0) @@ -40,10 +39,6 @@ ZEND_BEGIN_ARG_INFO(initial_operation_arginfo, 0) ZEND_ARG_CALLABLE_INFO(0, operation, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(key_arginfo, 0) - ZEND_ARG_INFO(0, key) -ZEND_END_ARG_INFO() - ZEND_BEGIN_ARG_INFO(keys_arginfo, 0) ZEND_ARG_INFO(0, keys) ZEND_END_ARG_INFO() @@ -86,6 +81,10 @@ ZEND_BEGIN_ARG_INFO(associate_by_to_arginfo, 0) ZEND_ARG_CALLABLE_INFO(0, key_selector, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO(contains_key_arginfo, 0) + ZEND_ARG_INFO(0, key) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO(copy_of_arginfo, 0) ZEND_ARG_TYPE_INFO(0, new_size, IS_LONG, 0) ZEND_END_ARG_INFO() @@ -132,7 +131,7 @@ const zend_function_entry collection_methods[] = { PHP_ME(Collection, associateByTo, associate_by_to_arginfo, ZEND_ACC_PUBLIC) PHP_ME(Collection, average, NULL, ZEND_ACC_PUBLIC) PHP_ME(Collection, containsAll, other_arginfo, ZEND_ACC_PUBLIC) - PHP_ME(Collection, containsKey, key_arginfo, ZEND_ACC_PUBLIC) + PHP_ME(Collection, containsKey, contains_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, copy_of_range_arginfo, ZEND_ACC_PUBLIC) @@ -189,9 +188,6 @@ const zend_function_entry collection_methods[] = { PHP_ME(Collection, minusValues, elements_arginfo, ZEND_ACC_PUBLIC) PHP_ME(Collection, minusValuesAssign, elements_arginfo, ZEND_ACC_PUBLIC) PHP_ME(Collection, none, predicate_arginfo, ZEND_ACC_PUBLIC) - PHP_ME(Collection, offsetUnset, key_arginfo, ZEND_ACC_PUBLIC) - PHP_ME(Collection, offsetSet, key_value_arginfo, ZEND_ACC_PUBLIC) - PHP_ME(Collection, offsetExists, key_arginfo, ZEND_ACC_PUBLIC) PHP_ME(Collection, onEach, action_arginfo, ZEND_ACC_PUBLIC) PHP_ME(Collection, orEmpty, NULL, ZEND_ACC_PUBLIC) PHP_ME(Collection, partition, predicate_arginfo, ZEND_ACC_PUBLIC) diff --git a/src/collections_methods.c b/src/collections_methods.c index 3d59c70..e21a043 100644 --- a/src/collections_methods.c +++ b/src/collections_methods.c @@ -111,6 +111,54 @@ int count_collection(zval* obj, zend_long* count) return SUCCESS; } +int collection_offset_exists(zval* object, zval* offset, int check_empty) +{ + zval rv; + zval* current = COLLECTION_FETCH(object); + if (check_empty) + return zend_hash_num_elements(Z_ARRVAL_P(current)) == 0; + if (Z_TYPE_P(offset) == IS_LONG) + return zend_hash_index_exists(Z_ARRVAL_P(current), Z_LVAL_P(offset)); + if (Z_TYPE_P(offset) == IS_STRING) + return zend_hash_exists(Z_ARRVAL_P(current), Z_STR_P(offset)); + return 0; +} + +void collection_offset_set(zval* object, zval* offset, zval* value) +{ + zval rv; + zval* current = COLLECTION_FETCH(object); + if (Z_TYPE_P(offset) == IS_LONG) + zend_hash_index_update(Z_ARRVAL_P(current), Z_LVAL_P(offset), value); + else if (Z_TYPE_P(offset) == IS_STRING) + zend_hash_update(Z_ARRVAL_P(current), Z_STR_P(offset), value); +} + +zval* collection_offset_get(zval* object, zval* offset, int type, zval* retval) +{ + // Note that we don't handler type. So don't do any fancy things with Collection + // such as fetching a reference of a value, etc. + zval rv; + zval* current = COLLECTION_FETCH(object); + zval* found = NULL; + if (Z_TYPE_P(offset) == IS_LONG) + found = zend_hash_index_find(Z_ARRVAL_P(current), Z_LVAL_P(offset)); + else if (Z_TYPE_P(offset) == IS_STRING) + found = zend_hash_find(Z_ARRVAL_P(current), Z_STR_P(offset)); + ZVAL_COPY(retval, found); + return retval; +} + +void collection_offset_unset(zval* object, zval* offset) +{ + zval rv; + zval* current = COLLECTION_FETCH(object); + if (Z_TYPE_P(offset) == IS_LONG) + zend_hash_index_del(Z_ARRVAL_P(current), Z_LVAL_P(offset)); + else if (Z_TYPE_P(offset) == IS_STRING) + zend_hash_del(Z_ARRVAL_P(current), Z_STR_P(offset)); +} + PHP_METHOD(Collection, __construct) {} PHP_METHOD(Collection, addAll) @@ -702,26 +750,6 @@ PHP_METHOD(Collection, none) } -PHP_METHOD(Collection, offsetUnset) -{ - -} - -PHP_METHOD(Collection, offsetSet) -{ - -} - -PHP_METHOD(Collection, offsetGet) -{ - -} - -PHP_METHOD(Collection, offsetExists) -{ - -} - PHP_METHOD(Collection, onEach) { diff --git a/src/php_collections.h b/src/php_collections.h index ff59362..e3cd184 100644 --- a/src/php_collections.h +++ b/src/php_collections.h @@ -20,9 +20,9 @@ extern zend_module_entry collections_module_entry; #define PHP_COLLECTIONS_API #endif -#if PHP_VERSION_ID < 70300 -#define GC_ADDREF(p) ++GC_REFCOUNT(p) -#define GC_DELREF(p) --GC_REFCOUNT(p) +#if PHP_VERSION_ID < 70300 +#define GC_ADDREF(p) ++GC_REFCOUNT(p) +#define GC_DELREF(p) --GC_REFCOUNT(p) #endif extern zend_string* collection_property_name; @@ -35,6 +35,10 @@ extern PHP_COLLECTIONS_API zend_class_entry* collections_pair_ce; extern zend_object_handlers* collection_handlers; int count_collection(zval* obj, zend_long* count); +int collection_offset_exists(zval* object, zval* offset, int check_empty); +void collection_offset_set(zval* object, zval* offset, zval* value); +zval* collection_offset_get(zval* object, zval* offset, int type, zval* rv); +void collection_offset_unset(zval* object, zval* offset); extern const zend_function_entry collection_methods[]; extern const zend_function_entry pair_methods[]; diff --git a/src/php_collections_me.h b/src/php_collections_me.h index 81c6040..15aa009 100644 --- a/src/php_collections_me.h +++ b/src/php_collections_me.h @@ -74,10 +74,6 @@ PHP_METHOD(Collection, minusKeysAssign); PHP_METHOD(Collection, minusValues); PHP_METHOD(Collection, minusValuesAssign); PHP_METHOD(Collection, none); -PHP_METHOD(Collection, offsetUnset); -PHP_METHOD(Collection, offsetSet); -PHP_METHOD(Collection, offsetGet); -PHP_METHOD(Collection, offsetExists); PHP_METHOD(Collection, onEach); PHP_METHOD(Collection, orEmpty); PHP_METHOD(Collection, partition); diff --git a/stubs/Collection.php b/stubs/Collection.php index 72497c9..4888943 100644 --- a/stubs/Collection.php +++ b/stubs/Collection.php @@ -581,21 +581,33 @@ class Collection implements ArrayAccess, Countable function none($predicate) {} /** + * This method is implemented in handlers.unset_dimension. + * There's no method with name 'offsetUnset'. + * * @internal */ function offsetUnset($key) {} /** + * This method is implemented in handlers.write_dimension. + * There's no method with name 'offsetSet'. + * * @internal */ function offsetSet($key, $value) {} /** + * This method is implemented in handlers.read_dimension. + * There's no method with name 'offsetGet'. + * * @internal */ function offsetGet($key) {} /** + * This method is implemented in handlers.has_dimension. + * There's no method with name 'offsetExists'. + * * @internal */ function offsetExists($key) {} diff --git a/tests/012-countable.phpt b/tests/012-countable.phpt index aa3399e..17b32cf 100644 --- a/tests/012-countable.phpt +++ b/tests/012-countable.phpt @@ -1,5 +1,5 @@ --TEST-- -Test Collection::count() and countable interface. +Test Collection::count() and implementation of interface Countable. --FILE-- count() != count($array)) echo 'Collection::count() failed.', PHP_EOL; if (count($collection) != count($array)) - echo 'Test for countable interface failed.', PHP_EOL; + echo 'Test for handlers.count_elements failed.', PHP_EOL; ?> --EXPECT-- diff --git a/tests/013-array-access.phpt b/tests/013-array-access.phpt new file mode 100644 index 0000000..325823d --- /dev/null +++ b/tests/013-array-access.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test implementation of interface ArrayAccess. +--FILE-- + 'b', 'c' => 'd', 'e' => ['f' => 'g']]; +$collection = Collection::init($array); +$collection['a'] = 'foo'; +$collection['h'] = 'bar'; +unset($collection['c']); +if (empty($collection) || isset($collection['t']) || !isset($collection['e'])) + echo 'Test for handlers.has_dimension failed.', PHP_EOL; +if ($collection['e']['f'] != 'g') + echo 'Test for handlers.read_dimension failed.', PHP_EOL; +if ($collection['a'] != 'foo' || $collection['h'] != 'bar') + echo 'Test for handlers.write_dimension failed.', PHP_EOL; +if (isset($collection['c'])) + echo 'Test for handlers.unset_dimension failed.', PHP_EOL; +?> +--EXPECT--