diff --git a/src/collections_methods.c b/src/collections_methods.c index 310957b..65fdd61 100644 --- a/src/collections_methods.c +++ b/src/collections_methods.c @@ -224,8 +224,11 @@ PHP_METHOD(Collection, all) zend_array* current = COLLECTION_FETCH_CURRENT(); ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket) CALLBACK_KEYVAL_INVOKE(params, bucket); - if (!zend_is_true(&retval)) + if (!zend_is_true(&retval)) { + zval_ptr_dtor(&retval); RETURN_FALSE; + } + zval_ptr_dtor(&retval); ZEND_HASH_FOREACH_END(); RETURN_TRUE; } @@ -241,8 +244,11 @@ PHP_METHOD(Collection, any) zend_array* current = COLLECTION_FETCH_CURRENT(); ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket) CALLBACK_KEYVAL_INVOKE(params, bucket); - if (zend_is_true(&retval)) + if (zend_is_true(&retval)) { + zval_ptr_dtor(&retval); RETURN_TRUE; + } + zval_ptr_dtor(&retval); ZEND_HASH_FOREACH_END(); RETURN_FALSE; } @@ -270,9 +276,9 @@ PHP_METHOD(Collection, associate) zend_hash_next_index_insert(new_collection, value); else ERR_BAD_KEY_TYPE(); - zval_ptr_dtor(&retval); } else ERR_BAD_CALLBACK_RETVAL(); + zval_ptr_dtor(&retval); ZEND_HASH_FOREACH_END(); RETVAL_NEW_COLLECTION(new_collection); } @@ -303,9 +309,9 @@ PHP_METHOD(Collection, associateTo) zend_hash_next_index_insert(dest_arr, value); else ERR_BAD_KEY_TYPE(); - zval_ptr_dtor(&retval); } else ERR_BAD_CALLBACK_RETVAL(); + zval_ptr_dtor(&retval); ZEND_HASH_FOREACH_END(); RETVAL_ZVAL(dest, 1, 0); } @@ -328,6 +334,7 @@ PHP_METHOD(Collection, associateBy) zend_hash_add(new_collection, Z_STR(retval), &bucket->val); else ERR_BAD_CALLBACK_RETVAL(); + zval_ptr_dtor(&retval); ZEND_HASH_FOREACH_END(); RETVAL_NEW_COLLECTION(new_collection); } @@ -353,6 +360,7 @@ PHP_METHOD(Collection, associateByTo) zend_hash_add(dest_arr, Z_STR(retval), &bucket->val); else ERR_BAD_CALLBACK_RETVAL(); + zval_ptr_dtor(&retval); ZEND_HASH_FOREACH_END(); RETVAL_ZVAL(dest, 1, 0); } @@ -567,10 +575,13 @@ PHP_METHOD(Collection, dropLastWhile) ARRAY_CLONE(new_collection, current); ZEND_HASH_REVERSE_FOREACH_BUCKET(new_collection, Bucket* bucket) CALLBACK_KEYVAL_INVOKE(params, bucket); - if (zend_is_true(&retval)) + if (zend_is_true(&retval)) { + zval_ptr_dtor(&retval); zend_hash_del_bucket(new_collection, bucket); - else + } else { + zval_ptr_dtor(&retval); break; + } ZEND_HASH_FOREACH_END(); RETVAL_NEW_COLLECTION(new_collection); } @@ -587,10 +598,13 @@ PHP_METHOD(Collection, dropWhile) ARRAY_CLONE(new_collection, current); ZEND_HASH_FOREACH_BUCKET(new_collection, Bucket* bucket) CALLBACK_KEYVAL_INVOKE(params, bucket); - if (zend_is_true(&retval)) + if (zend_is_true(&retval)) { + zval_ptr_dtor(&retval); zend_hash_del_bucket(new_collection, bucket); - else + } else { + zval_ptr_dtor(&retval); break; + } ZEND_HASH_FOREACH_END(); RETVAL_NEW_COLLECTION(new_collection); } @@ -640,6 +654,7 @@ PHP_METHOD(Collection, filter) else zend_hash_index_add(new_collection, bucket->h, &bucket->val); } + zval_ptr_dtor(&retval); ZEND_HASH_FOREACH_END(); RETVAL_NEW_COLLECTION(new_collection); } @@ -664,6 +679,7 @@ PHP_METHOD(Collection, filterNot) else zend_hash_index_add(new_collection, bucket->h, &bucket->val); } + zval_ptr_dtor(&retval); ZEND_HASH_FOREACH_END(); RETVAL_NEW_COLLECTION(new_collection); } @@ -691,6 +707,7 @@ PHP_METHOD(Collection, filterNotTo) else zend_hash_index_add(dest_arr, bucket->h, &bucket->val); } + zval_ptr_dtor(&retval); ZEND_HASH_FOREACH_END(); RETVAL_ZVAL(dest, 1, 0); } @@ -718,6 +735,7 @@ PHP_METHOD(Collection, filterTo) else zend_hash_index_add(dest_arr, bucket->h, &bucket->val); } + zval_ptr_dtor(&retval); ZEND_HASH_FOREACH_END(); RETVAL_ZVAL(dest, 1, 0); } @@ -742,8 +760,11 @@ PHP_METHOD(Collection, first) INIT_FCI(2); ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket) CALLBACK_KEYVAL_INVOKE(params, bucket); - if (zend_is_true(&retval)) + if (zend_is_true(&retval)) { + zval_ptr_dtor(&retval); RETURN_ZVAL(&bucket->val, 1, 0); + } + zval_ptr_dtor(&retval); ZEND_HASH_FOREACH_END(); RETVAL_NULL(); } @@ -828,12 +849,52 @@ PHP_METHOD(Collection, flatten) PHP_METHOD(Collection, fold) { - + zval* initial; + zend_fcall_info fci; + zend_fcall_info_cache fcc; + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_ZVAL(initial) + Z_PARAM_FUNC(fci, fcc) + ZEND_PARSE_PARAMETERS_END(); + zend_array* current = COLLECTION_FETCH_CURRENT(); + INIT_FCI(3); + ZVAL_COPY(¶ms[0], initial); + ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket) + ZVAL_COPY_VALUE(¶ms[1], &bucket->val); + if (bucket->key) + ZVAL_STR(¶ms[2], bucket->key); + else + ZVAL_LONG(¶ms[2], bucket->h); + zend_call_function(&fci, &fcc); + zval_ptr_dtor(¶ms[0]); + ZVAL_COPY_VALUE(¶ms[0], &retval); + ZEND_HASH_FOREACH_END(); + RETVAL_ZVAL(&retval, 0, 0); } PHP_METHOD(Collection, foldRight) { - + zval* initial; + zend_fcall_info fci; + zend_fcall_info_cache fcc; + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_ZVAL(initial) + Z_PARAM_FUNC(fci, fcc) + ZEND_PARSE_PARAMETERS_END(); + zend_array* current = COLLECTION_FETCH_CURRENT(); + INIT_FCI(3); + ZVAL_COPY(¶ms[0], initial); + ZEND_HASH_REVERSE_FOREACH_BUCKET(current, Bucket* bucket) + ZVAL_COPY_VALUE(¶ms[1], &bucket->val); + if (bucket->key) + ZVAL_STR(¶ms[2], bucket->key); + else + ZVAL_LONG(¶ms[2], bucket->h); + zend_call_function(&fci, &fcc); + zval_ptr_dtor(¶ms[0]); + ZVAL_COPY_VALUE(¶ms[0], &retval); + ZEND_HASH_FOREACH_END(); + RETVAL_ZVAL(&retval, 0, 0); } PHP_METHOD(Collection, forEach) @@ -847,6 +908,7 @@ PHP_METHOD(Collection, forEach) zend_array* current = COLLECTION_FETCH_CURRENT(); ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket) CALLBACK_KEYVAL_INVOKE(params, bucket); + zval_ptr_dtor(&retval); ZEND_HASH_FOREACH_END(); } @@ -877,7 +939,7 @@ PHP_METHOD(Collection, get) INIT_FCI(1); ZVAL_COPY_VALUE(¶ms[0], key); zend_call_function(&fci, &fcc); - RETVAL_ZVAL(&retval, 1, 0); + RETVAL_ZVAL(&retval, 0, 0); } PHP_METHOD(Collection, groupBy) @@ -921,10 +983,12 @@ PHP_METHOD(Collection, indexOfFirst) ZVAL_COPY_VALUE(¶ms[0], &bucket->val); zend_call_function(&fci, &fcc); if (zend_is_true(&retval)) { + zval_ptr_dtor(&retval); if (bucket->key) RETURN_STR(bucket->key); RETURN_LONG(bucket->h); } + zval_ptr_dtor(&retval); ZEND_HASH_FOREACH_END(); RETVAL_NULL(); } @@ -942,10 +1006,12 @@ PHP_METHOD(Collection, indexOfLast) ZVAL_COPY_VALUE(¶ms[0], &bucket->val); zend_call_function(&fci, &fcc); if (zend_is_true(&retval)) { + zval_ptr_dtor(&retval); if (bucket->key) RETURN_STR(bucket->key); RETURN_LONG(bucket->h); } + zval_ptr_dtor(&retval); ZEND_HASH_FOREACH_END(); RETVAL_NULL(); } @@ -1017,8 +1083,11 @@ PHP_METHOD(Collection, last) INIT_FCI(2); ZEND_HASH_REVERSE_FOREACH_BUCKET(current, Bucket* bucket) CALLBACK_KEYVAL_INVOKE(params, bucket); - if (zend_is_true(&retval)) + if (zend_is_true(&retval)) { + zval_ptr_dtor(&retval); RETURN_ZVAL(&bucket->val, 1, 0); + } + zval_ptr_dtor(&retval); ZEND_HASH_FOREACH_END(); RETVAL_NULL(); } @@ -1197,8 +1266,11 @@ PHP_METHOD(Collection, none) zend_array* current = COLLECTION_FETCH_CURRENT(); ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket) CALLBACK_KEYVAL_INVOKE(params, bucket); - if (zend_is_true(&retval)) + if (zend_is_true(&retval)) { + zval_ptr_dtor(&retval); RETURN_FALSE; + } + zval_ptr_dtor(&retval); ZEND_HASH_FOREACH_END(); RETURN_TRUE; } @@ -1214,6 +1286,7 @@ PHP_METHOD(Collection, onEach) zend_array* current = COLLECTION_FETCH_CURRENT(); ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket) CALLBACK_KEYVAL_INVOKE(params, bucket); + zval_ptr_dtor(&retval); ZEND_HASH_FOREACH_END(); RETVAL_ZVAL(getThis(), 1, 0); } @@ -1246,6 +1319,7 @@ PHP_METHOD(Collection, partition) zend_hash_next_index_insert(which, &bucket->val); else zend_hash_index_add(which, bucket->h, &bucket->val); + zval_ptr_dtor(&retval); ZEND_HASH_FOREACH_END(); zval first, second; ZVAL_ARR(&first, first_arr); @@ -1417,6 +1491,7 @@ PHP_METHOD(Collection, removeAll) CALLBACK_KEYVAL_INVOKE(params, bucket); if (zend_is_true(&retval)) zend_hash_del_bucket(current, bucket); + zval_ptr_dtor(&retval); ZEND_HASH_FOREACH_END(); } @@ -1439,6 +1514,7 @@ PHP_METHOD(Collection, retainAll) CALLBACK_KEYVAL_INVOKE(params, bucket); if (!zend_is_true(&retval)) zend_hash_del_bucket(current, bucket); + zval_ptr_dtor(&retval); ZEND_HASH_FOREACH_END(); } @@ -1554,6 +1630,7 @@ PHP_METHOD(Collection, single) else RETURN_NULL(); } + zval_ptr_dtor(&retval); ZEND_HASH_FOREACH_END(); if (Z_TYPE(single) == IS_UNDEF) RETURN_NULL() @@ -1723,10 +1800,13 @@ PHP_METHOD(Collection, takeLastWhile) Bucket* taken[num_elements]; ZEND_HASH_REVERSE_FOREACH_BUCKET(current, Bucket* bucket) CALLBACK_KEYVAL_INVOKE(params, bucket); - if (zend_is_true(&retval)) + if (zend_is_true(&retval)) { + zval_ptr_dtor(&retval); taken[--num_elements] = bucket; - else + } else { + zval_ptr_dtor(&retval); break; + } ZEND_HASH_FOREACH_END(); memset(&taken[0], 0, num_elements * sizeof(Bucket*)); int i = 0; @@ -1758,14 +1838,17 @@ PHP_METHOD(Collection, takeWhile) ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket) CALLBACK_KEYVAL_INVOKE(params, bucket); if (zend_is_true(&retval)) { + zval_ptr_dtor(&retval); if (bucket->key) zend_hash_add_new(new_collection, bucket->key, &bucket->val); else if (HT_IS_PACKED(current)) zend_hash_next_index_insert(new_collection, &bucket->val); else zend_hash_index_add_new(new_collection, bucket->h, &bucket->val); - } else + } else { + zval_ptr_dtor(&retval); break; + } ZEND_HASH_FOREACH_END(); RETVAL_NEW_COLLECTION(new_collection); } diff --git a/tests/041-fold.phpt b/tests/041-fold.phpt new file mode 100644 index 0000000..4b22faa --- /dev/null +++ b/tests/041-fold.phpt @@ -0,0 +1,14 @@ +--TEST-- +Test Collection::fold() and Collection::foldRight(). +--FILE-- +fold('foo', $reduce_cb) != 'fooa0b1c2d3e4') + echo 'Collection::fold() failed.', PHP_EOL; +if ($collection->foldRight('bar', $reduce_cb) != 'bare4d3c2b1a0') + echo 'Collection::foldRight() failed.', PHP_EOL; +?> +--EXPECT--