diff --git a/README.md b/README.md index d507c37..cc8887d 100644 --- a/README.md +++ b/README.md @@ -30,14 +30,15 @@ $employees = [ // sorted by the descending order of their age. $names = Collection::init($employees) ->filter(function ($it) { - return $it->get('sex') == 'male'; + return $it['sex'] == 'male'; }) ->sortedByDescending(function ($it) { - return $it->get('age'); + return $it['age']; }) ->map(function ($it) { - return $it->get('name'); + return $it['name']; }) ->toArray(); +// You got $names == ['David', 'Benjamin', 'Bob']. ``` diff --git a/src/collections.c b/src/collections.c index 3bbae19..b2d2b7e 100644 --- a/src/collections.c +++ b/src/collections.c @@ -26,7 +26,7 @@ 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_declare_property_null(collections_collection_ce, "_a", sizeof "_a" - 1, ZEND_ACC_PRIVATE); + zend_declare_property_null(collections_collection_ce, "_", sizeof "_" - 1, ZEND_ACC_PRIVATE); 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_methods.c b/src/collections_methods.c index 105b5e0..1c83ca2 100644 --- a/src/collections_methods.c +++ b/src/collections_methods.c @@ -23,20 +23,18 @@ #define IS_PAIR(zval) \ EXPECTED(Z_TYPE(zval) == IS_OBJECT) && EXPECTED(Z_OBJCE(zval) == collections_pair_ce) -#define OBJ_PROPERTY_UPDATE(obj, property_name, name_len, value) \ - zend_update_property(collections_collection_ce, obj, property_name, name_len, value) -#define OBJ_PROPERTY_FETCH(obj, property_name, name_len) \ - zend_read_property(collections_collection_ce, obj, property_name, name_len, 1, &rv) -#define COLLECTION_UPDATE(obj, value) OBJ_PROPERTY_UPDATE(obj, "_a", sizeof "_a" - 1, value) +#define OBJ_PROPERTY_UPDATE(ce, obj, property_name, value) \ + zend_update_property(ce, obj, #property_name, sizeof #property_name - 1, value) +#define OBJ_PROPERTY_FETCH(ce, obj, property_name) \ + 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(obj, "_a", sizeof "_a" - 1) +#define COLLECTION_FETCH(obj) OBJ_PROPERTY_FETCH(collections_collection_ce, obj, _) #define COLLECTION_FETCH_EX() COLLECTION_FETCH(getThis()) -#define PAIR_UPDATE_FIRST(obj, value) \ - OBJ_PROPERTY_UPDATE(obj, "first", sizeof "first" - 1, value) -#define PAIR_UPDATE_SECOND(obj, value) \ - OBJ_PROPERTY_UPDATE(obj, "second", sizeof "second" - 1, value) -#define PAIR_FETCH_FIRST(obj) OBJ_PROPERTY_FETCH(obj, "first", sizeof "first" - 1) -#define PAIR_FETCH_SECOND(obj) OBJ_PROPERTY_FETCH(obj, "second", sizeof "second" - 1) +#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_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 INIT_FCI() \ zval params[2], rv, retval; \ @@ -51,6 +49,16 @@ else \ ZVAL_LONG(¶ms[1], (bucket)->h) +#define INIT_EQUAL_CHECK_FUNC(val) \ + int (*equal_check_func)(zval*, zval*); \ + if (Z_TYPE_P(element) == IS_LONG) \ + equal_check_func = fast_equal_check_long; \ + else if (Z_TYPE_P(element) == IS_STRING) \ + equal_check_func = fast_equal_check_string; \ + 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") @@ -264,12 +272,42 @@ PHP_METHOD(Collection, associateByTo) PHP_METHOD(Collection, average) { - + zval rv; + zval* current = COLLECTION_FETCH_EX(); + double sum = 0; + ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL_P(current), zval* val) + if (Z_TYPE_P(val) == IS_LONG) + sum += Z_LVAL_P(val); + else if (Z_TYPE_P(val) == IS_DOUBLE) + sum += Z_DVAL_P(val); + else { + ERR_BAD_ARGUMENT_TYPE(); + RETURN_NULL(); + } + ZEND_HASH_FOREACH_END(); + RETVAL_DOUBLE(sum / zend_hash_num_elements(Z_ARRVAL_P(current))); } PHP_METHOD(Collection, containsAll) { - + zval* elements; + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ZVAL(elements) + ZEND_PARSE_PARAMETERS_END(); + ELEMENTS_VALIDATE(elements); + zval rv; + zval* current = COLLECTION_FETCH_EX(); + ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL_P(elements), zval* element) + INIT_EQUAL_CHECK_FUNC(element); + int result = 0; + ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL_P(current), zval* val) + if (result = equal_check_func(element, val)) + break; + ZEND_HASH_FOREACH_END(); + if (result == 0) + RETURN_FALSE; + ZEND_HASH_FOREACH_END(); + RETURN_TRUE; } PHP_METHOD(Collection, containsKey) diff --git a/tests/007-average.phpt b/tests/007-average.phpt new file mode 100644 index 0000000..c6ec97e --- /dev/null +++ b/tests/007-average.phpt @@ -0,0 +1,10 @@ +--TEST-- +Test Collection::average(). +--FILE-- +average(); +if ($average != array_sum($array) / count($array)) + echo 'Collection::average() failed.', PHP_EOL; +?> +--EXPECT-- diff --git a/tests/008-contains-all.phpt b/tests/008-contains-all.phpt new file mode 100644 index 0000000..a0842c0 --- /dev/null +++ b/tests/008-contains-all.phpt @@ -0,0 +1,11 @@ +--TEST-- +Test Collection::containsAll(). +--FILE-- +containsAll($array) || $collection->containsAll($array1)) + echo 'Collection::containsAll() failed.', PHP_EOL; +?> +--EXPECT--