]> granicus.if.org Git - php/commitdiff
- MFH iterator_apply()
authorMarcus Boerger <helly@php.net>
Wed, 7 Jun 2006 09:44:42 +0000 (09:44 +0000)
committerMarcus Boerger <helly@php.net>
Wed, 7 Jun 2006 09:44:42 +0000 (09:44 +0000)
ext/spl/php_spl.c
ext/spl/spl_iterators.c
ext/spl/spl_iterators.h
ext/spl/tests/spl_004.phpt [new file with mode: 0755]

index 2b61aa568ede88ab247d218a5857369346d40432..fce87de40c0bc22c1aaa82b1b18fb778f26fbbfe 100755 (executable)
@@ -610,7 +610,14 @@ PHP_MINFO_FUNCTION(spl)
 
 static
 ZEND_BEGIN_ARG_INFO(arginfo_iterator, 0)
-       ZEND_ARG_INFO(0, iterator)
+       ZEND_ARG_OBJ_INFO(0, iterator, Traversable, 0)
+ZEND_END_ARG_INFO();
+
+static
+ZEND_BEGIN_ARG_INFO_EX(arginfo_iterator_apply, 0, 0, 2)
+       ZEND_ARG_OBJ_INFO(0, iterator, Traversable, 0)
+       ZEND_ARG_INFO(0, function)
+       ZEND_ARG_ARRAY_INFO(0, args, 1)
 ZEND_END_ARG_INFO();
 
 /* {{{ spl_functions
@@ -628,6 +635,7 @@ zend_function_entry spl_functions[] = {
 #ifdef SPL_ITERATORS_H
        PHP_FE(iterator_to_array,       arginfo_iterator)
        PHP_FE(iterator_count,          arginfo_iterator)
+       PHP_FE(iterator_apply,          arginfo_iterator_apply)
 #endif /* SPL_ITERATORS_H */
        {NULL, NULL, NULL}
 };
index 1caf3aa3cf011b475b894990fa9040a9131df210..294bc12126178c25f9ee897f62ffcceacbaeeaa9 100755 (executable)
@@ -2575,7 +2575,7 @@ static int spl_iterator_to_array_apply(zend_object_iterator *iter, void *puser T
    Copy the iterator into an array */
 PHP_FUNCTION(iterator_to_array)
 {
-       zval                   *obj;
+       zval  *obj;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &obj, zend_ce_traversable) == FAILURE) {
                RETURN_FALSE;
@@ -2600,8 +2600,8 @@ static int spl_iterator_count_apply(zend_object_iterator *iter, void *puser TSRM
    Count the elements in an iterator */
 PHP_FUNCTION(iterator_count)
 {
-       zval                   *obj;
-       long                    count = 0;
+       zval  *obj;
+       long  count = 0;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &obj, zend_ce_traversable) == FAILURE) {
                RETURN_FALSE;
@@ -2613,6 +2613,54 @@ PHP_FUNCTION(iterator_count)
 }
 /* }}} */
 
+typedef struct {
+       zval                   *obj;
+       zval                   *args;
+       long                   count;
+       zend_fcall_info        fci;
+       zend_fcall_info_cache  fcc;
+} spl_iterator_apply_info;
+
+static int spl_iterator_func_apply(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{ */
+{
+       zval *retval;
+       spl_iterator_apply_info  *apply_info = (spl_iterator_apply_info*)puser;
+       int result;
+
+       apply_info->count++;
+       zend_fcall_info_call(&apply_info->fci, &apply_info->fcc, &retval, NULL TSRMLS_CC);
+       if (retval) {
+               result = zend_is_true(retval) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_STOP;
+               zval_ptr_dtor(&retval);
+       } else {
+               result = ZEND_HASH_APPLY_STOP;
+       }
+       return result;
+}
+/* }}} */
+
+/* {{{ proto int iterator_apply(Traversable it, mixed function [, mixed params])
+   Calls a function for every element in an iterator */
+PHP_FUNCTION(iterator_apply)
+{
+       spl_iterator_apply_info  apply_info;
+
+       apply_info.args = NULL;
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Of|a!", &apply_info.obj, zend_ce_traversable, &apply_info.fci, &apply_info.fcc, &apply_info.args) == FAILURE) {
+               return;
+       }
+
+       apply_info.count = 0;
+       zend_fcall_info_args(&apply_info.fci, apply_info.args TSRMLS_CC);
+       if (spl_iterator_apply(apply_info.obj, spl_iterator_func_apply, (void*)&apply_info TSRMLS_CC) == SUCCESS) {
+               RETVAL_LONG(apply_info.count);
+       } else {
+               RETVAL_FALSE;
+       }
+       zend_fcall_info_args(&apply_info.fci, NULL TSRMLS_CC);
+}
+/* }}} */
+
 static zend_function_entry spl_funcs_OuterIterator[] = {
        SPL_ABSTRACT_ME(OuterIterator, getInnerIterator,   NULL)
        {NULL, NULL, NULL}
index 8a608def63d653b5c919ebb5eab2abf34694536a..af4eccd8ffb536f08bff4a0edbd076e17737f938 100755 (executable)
@@ -55,6 +55,7 @@ PHP_MINIT_FUNCTION(spl_iterators);
 
 PHP_FUNCTION(iterator_to_array);
 PHP_FUNCTION(iterator_count);
+PHP_FUNCTION(iterator_apply);
 
 typedef enum {
        DIT_Default = 0,
diff --git a/ext/spl/tests/spl_004.phpt b/ext/spl/tests/spl_004.phpt
new file mode 100755 (executable)
index 0000000..60da280
--- /dev/null
@@ -0,0 +1,86 @@
+--TEST--
+SPL: iterator_apply()
+--SKIPIF--
+<?php if (!extension_loaded("spl")) print "skip"; ?>
+--FILE--
+<?php
+
+function my_error_handler($errno, $errstr, $errfile, $errline) {
+       echo "Error: $errstr\n";
+}
+
+set_error_handler('my_error_handler');
+
+function test_arg($arg)
+{
+       if ($arg instanceof Iterator)
+       {
+               var_dump($arg->key());
+               var_dump($arg->current());
+       }
+       else
+       {
+               var_dump($arg);
+       }
+       return true;
+}
+
+function test()
+{
+       static $arg = 0;
+       var_dump($arg++);
+       return true;
+}
+
+$it = new RecursiveArrayIterator(array(1, array(21, 22), 3));
+
+var_dump(iterator_apply($it, 'test', NULL));
+
+echo "===ARGS===\n";
+var_dump(iterator_apply($it, 'test_arg', array($it)));
+
+echo "===RECURSIVE===\n";
+$it = new RecursiveIteratorIterator($it);
+var_dump(iterator_apply($it, 'test'));
+
+echo "===ERRORS===\n";
+var_dump(iterator_apply($it, 'test', 1));
+var_dump(iterator_apply($it, 'non_existing_functon'));
+var_dump(iterator_apply($it, 'non_existing_functon', NULL, 2));
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+int(0)
+int(1)
+int(2)
+int(3)
+===ARGS===
+int(0)
+int(1)
+int(1)
+array(2) {
+  [0]=>
+  int(21)
+  [1]=>
+  int(22)
+}
+int(2)
+int(3)
+int(3)
+===RECURSIVE===
+int(3)
+int(4)
+int(5)
+int(6)
+int(4)
+===ERRORS===
+Error: Argument 3 passed to iterator_apply() must be an array, integer given
+Error: iterator_apply() expects parameter 3 to be array, integer given
+NULL
+Error: iterator_apply() expects parameter 2 to be function,%sstring given
+NULL
+Error: iterator_apply() expects at most 3 parameters, 4 given
+NULL
+===DONE===