Index: ext/spl/spl_directory.c =================================================================== RCS file: /repository/php-src/ext/spl/spl_directory.c,v retrieving revision 1.45.2.27.2.23.2.24 diff -u -p -r1.45.2.27.2.23.2.24 spl_directory.c --- ext/spl/spl_directory.c 8 Jul 2008 22:40:48 -0000 1.45.2.27.2.23.2.24 +++ ext/spl/spl_directory.c 19 Jul 2008 11:10:01 -0000 @@ -703,6 +703,43 @@ SPL_METHOD(DirectoryIterator, next) } /* }}} */ +/* {{{ proto void DirectoryIterator::seek(int position) + Seek to the given position */ +SPL_METHOD(DirectoryIterator, seek) +{ + spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + zval *retval = NULL; + long pos; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &pos) == FAILURE) { + return; + } + + if (intern->u.dir.index > pos) { + /* we first rewind */ + zend_call_method_with_0_params(&this_ptr, Z_OBJCE_P(getThis()), &intern->u.dir.func_rewind, "rewind", &retval); + if (retval) { + zval_ptr_dtor(&retval); + } + } + + while (intern->u.dir.index < pos) { + int valid = 0; + zend_call_method_with_0_params(&this_ptr, Z_OBJCE_P(getThis()), &intern->u.dir.func_valid, "valid", &retval); + if (retval) { + valid = zend_is_true(retval); + zval_ptr_dtor(&retval); + } + if (!valid) { + break; + } + zend_call_method_with_0_params(&this_ptr, Z_OBJCE_P(getThis()), &intern->u.dir.func_next, "next", &retval); + if (retval) { + zval_ptr_dtor(&retval); + } + } +} /* }}} */ + /* {{{ proto string DirectoryIterator::valid() Check whether dir contains more entries */ SPL_METHOD(DirectoryIterator, valid) @@ -1619,6 +1656,11 @@ ZEND_BEGIN_ARG_INFO(arginfo_dir___constr ZEND_ARG_INFO(0, path) ZEND_END_ARG_INFO() +static +ZEND_BEGIN_ARG_INFO(arginfo_dir_it_seek, 0) + ZEND_ARG_INFO(0, position) +ZEND_END_ARG_INFO(); + /* the method table */ /* each method can have its own parameters and visibility */ static const zend_function_entry spl_DirectoryIterator_functions[] = { @@ -1631,6 +1673,7 @@ static const zend_function_entry spl_Dir SPL_ME(DirectoryIterator, key, NULL, ZEND_ACC_PUBLIC) SPL_ME(DirectoryIterator, current, NULL, ZEND_ACC_PUBLIC) SPL_ME(DirectoryIterator, next, NULL, ZEND_ACC_PUBLIC) + SPL_ME(DirectoryIterator, seek, arginfo_dir_it_seek, ZEND_ACC_PUBLIC) SPL_MA(DirectoryIterator, __toString, DirectoryIterator, getFilename, NULL, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} }; @@ -2560,12 +2603,13 @@ PHP_MINIT_FUNCTION(spl_directory) { REGISTER_SPL_STD_CLASS_EX(SplFileInfo, spl_filesystem_object_new, spl_SplFileInfo_functions); memcpy(&spl_filesystem_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - spl_filesystem_object_handlers.clone_obj = spl_filesystem_object_clone; - spl_filesystem_object_handlers.cast_object = spl_filesystem_object_cast; - spl_filesystem_object_handlers.get_debug_info = spl_filesystem_object_get_debug_info; + spl_filesystem_object_handlers.clone_obj = spl_filesystem_object_clone; + spl_filesystem_object_handlers.cast_object = spl_filesystem_object_cast; + spl_filesystem_object_handlers.get_debug_info = spl_filesystem_object_get_debug_info; REGISTER_SPL_SUB_CLASS_EX(DirectoryIterator, SplFileInfo, spl_filesystem_object_new, spl_DirectoryIterator_functions); zend_class_implements(spl_ce_DirectoryIterator TSRMLS_CC, 1, zend_ce_iterator); + REGISTER_SPL_IMPLEMENTS(DirectoryIterator, SeekableIterator); spl_ce_DirectoryIterator->get_iterator = spl_filesystem_dir_get_iterator; Index: ext/spl/spl_directory.h =================================================================== RCS file: /repository/php-src/ext/spl/spl_directory.h,v retrieving revision 1.12.2.5.2.4.2.10 diff -u -p -r1.12.2.5.2.4.2.10 spl_directory.h --- ext/spl/spl_directory.h 20 May 2008 21:46:50 -0000 1.12.2.5.2.4.2.10 +++ ext/spl/spl_directory.h 19 Jul 2008 11:10:01 -0000 @@ -80,6 +80,9 @@ struct _spl_filesystem_object { int sub_path_len; int index; int is_recursive; + zend_function *func_rewind; + zend_function *func_next; + zend_function *func_valid; } dir; struct { php_stream *stream; Index: ext/spl/tests/dit_006.phpt =================================================================== RCS file: ext/spl/tests/dit_006.phpt diff -N ext/spl/tests/dit_006.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ext/spl/tests/dit_006.phpt 19 Jul 2008 11:10:01 -0000 @@ -0,0 +1,50 @@ +--TEST-- +SPL: DirectoryIterator and seek +--FILE-- +seek(2); + +$n = 0; +while ($di->valid()) { + $n++; + $di->next(); +} + +echo "With seek(2) we get $n\n"; +$di->seek(0); + +$m = 0; +while ($di->valid()) { + $m++; + $di->next(); +} +echo "With seek(0) we get $m\n"; + +$o = 0; +$di->rewind(); +while ($di->valid()) { + $o++; + $di->next(); +} + +echo "Without seek we get $o\n"; + +$p = 0; +$di->seek($o+1); +while ($di->valid()) { + $p++; + $di->next(); +} + +var_dump($n !== $m, $m === $o, $p === 0); +?> +===DONE=== +--EXPECTF-- +With seek(2) we get %d +With seek(0) we get %d +Without seek we get %d +bool(true) +bool(true) +bool(true) +===DONE===