helly Sat Feb 2 23:09:38 2008 UTC Modified files: (Branch: PHP_5_3) /php-src NEWS /php-src/ext/spl php_spl.c spl_directory.c spl_directory.h Log: - MFH Synch directory changes [DOC] # Class FilesystemIterator was introduced to have a better DirectoryIterator # without having to change DirectoryIterator or RecursiveDirectoryIterator. # On top of FilterIterator the new GlobIterator was introduced. This one allows # to implement Countable(). But a glob stream flattens all structure, so it # cannot be derived from RedursiveIterator. With the new structure all children # of FilesystemIterator have nearly the same behavior. Just their capabilities # are a bit different. Check out new inheritance tree on SplFileInfo: # # [EMAIL PROTECTED] PHP_5_3]$ php ext/spl/examples/class_tree.php SplFileInfo # make: `sapi/cli/php' is up to date. # SplFileInfo # |-DirectoryIterator (Iterator) # | \-FilesystemIterator # | |-GlobIterator (Countable) # | \-RecursiveDirectoryIterator (RecursiveIterator) # | \-Phar (ArrayAccess, Countable) # |-PharFileInfo # \-SplFileObject (RecursiveIterator, SeekableIterator) # \-SplTempFileObject
http://cvs.php.net/viewvc.cgi/php-src/NEWS?r1=1.2027.2.547.2.965.2.104&r2=1.2027.2.547.2.965.2.105&diff_format=u Index: php-src/NEWS diff -u php-src/NEWS:1.2027.2.547.2.965.2.104 php-src/NEWS:1.2027.2.547.2.965.2.105 --- php-src/NEWS:1.2027.2.547.2.965.2.104 Fri Feb 1 18:01:50 2008 +++ php-src/NEWS Sat Feb 2 23:09:37 2008 @@ -29,6 +29,8 @@ SplObjectStorage. (Marcus) . Added ArrayAccess support to SplObjectStorage. (Marcus) . Added SplDoublyLinkedList, SplStack, SplQueue classes. (Etienne) + . Added FilesystemIterator. (Marcus) + . Added GlobIterator. (Marcus) - Added ability to use Traversable objects instead of plain arrays in ext/soap. (Joshua Reese, Dmitry) - Added "?:" operator. (Marcus) http://cvs.php.net/viewvc.cgi/php-src/ext/spl/php_spl.c?r1=1.52.2.28.2.17.2.10&r2=1.52.2.28.2.17.2.11&diff_format=u Index: php-src/ext/spl/php_spl.c diff -u php-src/ext/spl/php_spl.c:1.52.2.28.2.17.2.10 php-src/ext/spl/php_spl.c:1.52.2.28.2.17.2.11 --- php-src/ext/spl/php_spl.c:1.52.2.28.2.17.2.10 Fri Feb 1 23:46:36 2008 +++ php-src/ext/spl/php_spl.c Sat Feb 2 23:09:38 2008 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_spl.c,v 1.52.2.28.2.17.2.10 2008/02/01 23:46:36 helly Exp $ */ +/* $Id: php_spl.c,v 1.52.2.28.2.17.2.11 2008/02/02 23:09:38 helly Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -164,7 +164,9 @@ SPL_ADD_CLASS(DirectoryIterator, z_list, sub, allow, ce_flags); \ SPL_ADD_CLASS(DomainException, z_list, sub, allow, ce_flags); \ SPL_ADD_CLASS(EmptyIterator, z_list, sub, allow, ce_flags); \ + SPL_ADD_CLASS(FilesystemIterator, z_list, sub, allow, ce_flags); \ SPL_ADD_CLASS(FilterIterator, z_list, sub, allow, ce_flags); \ + SPL_ADD_CLASS(GlobIterator, z_list, sub, allow, ce_flags); \ SPL_ADD_CLASS(InfiniteIterator, z_list, sub, allow, ce_flags); \ SPL_ADD_CLASS(InvalidArgumentException, z_list, sub, allow, ce_flags); \ SPL_ADD_CLASS(IteratorIterator, z_list, sub, allow, ce_flags); \ @@ -537,6 +539,9 @@ } RETURN_FALSE; } + if (error) { + efree(error); + } zend_str_tolower(func_name, func_name_len); http://cvs.php.net/viewvc.cgi/php-src/ext/spl/spl_directory.c?r1=1.45.2.27.2.23.2.11&r2=1.45.2.27.2.23.2.12&diff_format=u Index: php-src/ext/spl/spl_directory.c diff -u php-src/ext/spl/spl_directory.c:1.45.2.27.2.23.2.11 php-src/ext/spl/spl_directory.c:1.45.2.27.2.23.2.12 --- php-src/ext/spl/spl_directory.c:1.45.2.27.2.23.2.11 Thu Jan 31 02:35:44 2008 +++ php-src/ext/spl/spl_directory.c Sat Feb 2 23:09:38 2008 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: spl_directory.c,v 1.45.2.27.2.23.2.11 2008/01/31 02:35:44 auroraeosrose Exp $ */ +/* $Id: spl_directory.c,v 1.45.2.27.2.23.2.12 2008/02/02 23:09:38 helly Exp $ */ #ifdef HAVE_CONFIG_H # include "config.h" @@ -50,7 +50,9 @@ /* decalre the class entry */ PHPAPI zend_class_entry *spl_ce_SplFileInfo; PHPAPI zend_class_entry *spl_ce_DirectoryIterator; +PHPAPI zend_class_entry *spl_ce_FilesystemIterator; PHPAPI zend_class_entry *spl_ce_RecursiveDirectoryIterator; +PHPAPI zend_class_entry *spl_ce_GlobIterator; PHPAPI zend_class_entry *spl_ce_SplFileObject; PHPAPI zend_class_entry *spl_ce_SplTempFileObject; @@ -88,6 +90,7 @@ case SPL_FS_DIR: if (intern->u.dir.dirp) { php_stream_close(intern->u.dir.dirp); + intern->u.dir.dirp = NULL; } if (intern->u.dir.sub_path) { efree(intern->u.dir.sub_path); @@ -184,6 +187,19 @@ } } /* }}} */ +static int spl_filesystem_dir_read(spl_filesystem_object *intern TSRMLS_DC) /* {{{ */ +{ + if (!intern->u.dir.dirp || !php_stream_readdir(intern->u.dir.dirp, &intern->u.dir.entry)) { + intern->u.dir.entry.d_name[0] = '\0'; + return 0; + } else { + return 1; + } +} +/* }}} */ + +#define IS_SLASH_AT(zs, pos) (IS_SLASH(zs[pos])) + /* {{{ spl_filesystem_dir_open */ /* open a directory resource */ static void spl_filesystem_dir_open(spl_filesystem_object* intern, char *path TSRMLS_DC) @@ -192,11 +208,7 @@ intern->_path_len = strlen(path); intern->u.dir.dirp = php_stream_opendir(path, ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL); - if (intern->_path_len && (path[intern->_path_len-1] == '/' -#if defined(PHP_WIN32) || defined(NETWARE) - || path[intern->_path_len-1] == '\\' -#endif - )) { + if (intern->_path_len && IS_SLASH_AT(path, intern->_path_len-1)) { intern->_path = estrndup(path, --intern->_path_len); } else { intern->_path = estrndup(path, intern->_path_len); @@ -207,9 +219,7 @@ /* throw exception: should've been already happened */ intern->u.dir.entry.d_name[0] = '\0'; } else { - if (!php_stream_readdir(intern->u.dir.dirp, &intern->u.dir.entry)) { - intern->u.dir.entry.d_name[0] = '\0'; - } + spl_filesystem_dir_read(intern TSRMLS_CC); } } /* }}} */ @@ -233,11 +243,7 @@ zend_list_addref(Z_RESVAL_P(intern->u.file.zcontext)); } - if (intern->file_name[intern->file_name_len-1] == '/' -#if defined(PHP_WIN32) || defined(NETWARE) - ||intern->file_name[intern->file_name_len-1] == '\\' -#endif - ) { + if (intern->file_name_len && IS_SLASH_AT(intern->file_name, intern->file_name_len-1)) { intern->file_name_len--; } @@ -341,7 +347,6 @@ if (file_path && !use_copy) { efree(file_path); } - return NULL; #else if (file_path && !use_copy) { efree(file_path); @@ -350,6 +355,7 @@ file_path_len = 1; file_path = "/"; #endif + return NULL; } php_set_error_handling(EH_THROW, spl_ce_RuntimeException TSRMLS_CC); @@ -503,7 +509,7 @@ efree(pnstr); } if (intern->type == SPL_FS_DIR) { - pnstr = spl_gen_private_prop_name(spl_ce_RecursiveDirectoryIterator, "glob", sizeof("glob")-1, &pnlen TSRMLS_CC); + pnstr = spl_gen_private_prop_name(spl_ce_DirectoryIterator, "glob", sizeof("glob")-1, &pnlen TSRMLS_CC); if (php_stream_is(intern->u.dir.dirp ,&php_glob_stream_ops)) { add_assoc_stringl_ex(&zrv, pnstr, pnlen+1, intern->_path, intern->_path_len, 1); } else { @@ -537,21 +543,29 @@ } /* }}}} */ -/* {{{ proto void DirectoryIterator::__construct(string path) - Cronstructs a new dir iterator from a path. */ -SPL_METHOD(DirectoryIterator, __construct) +#define DIT_CTOR_FLAGS 0x00000001 +#define DIT_CTOR_GLOB 0x00000002 + +void spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAMETERS, int ctor_flags) /* {{{ */ { spl_filesystem_object *intern; char *path; - int len; + int parsed, len; + long flags; - php_set_error_handling(EH_THROW, spl_ce_RuntimeException TSRMLS_CC); + php_set_error_handling(EH_THROW, spl_ce_UnexpectedValueException TSRMLS_CC); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &path, &len) == FAILURE) { + if (ctor_flags & DIT_CTOR_FLAGS) { + flags = SPL_FILE_DIR_CURRENT_AS_FILEINFO; + parsed = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &path, &len, &flags); + } else { + flags = 0; + parsed = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &path, &len); + } + if (parsed == FAILURE) { php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); return; } - if (!len) { php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Directory name must not be empty."); @@ -559,14 +573,29 @@ } intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - spl_filesystem_dir_open(intern, path TSRMLS_CC); + if ((ctor_flags & DIT_CTOR_GLOB) && strstr(path, "glob://") != path) { + spprintf(&path, 0, "glob://%s", path); + spl_filesystem_dir_open(intern, path TSRMLS_CC); + efree(path); + } else { + spl_filesystem_dir_open(intern, path TSRMLS_CC); + } + intern->u.dir.is_recursive = instanceof_function(intern->std.ce, spl_ce_RecursiveDirectoryIterator TSRMLS_CC) ? 1 : 0; - intern->flags = 0; + intern->flags = flags; php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); } /* }}} */ +/* {{{ proto void DirectoryIterator::__construct(string path) + Cronstructs a new dir iterator from a path. */ +SPL_METHOD(DirectoryIterator, __construct) +{ + spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); +} +/* }}} */ + /* {{{ proto void DirectoryIterator::rewind() Rewind dir back to the start */ SPL_METHOD(DirectoryIterator, rewind) @@ -577,9 +606,7 @@ if (intern->u.dir.dirp) { php_stream_rewinddir(intern->u.dir.dirp); } - if (!intern->u.dir.dirp || !php_stream_readdir(intern->u.dir.dirp, &intern->u.dir.entry)) { - intern->u.dir.entry.d_name[0] = '\0'; - } + spl_filesystem_dir_read(intern TSRMLS_CC); } /* }}} */ @@ -612,9 +639,7 @@ spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); intern->u.dir.index++; - if (!intern->u.dir.dirp || !php_stream_readdir(intern->u.dir.dirp, &intern->u.dir.entry)) { - intern->u.dir.entry.d_name[0] = '\0'; - } + spl_filesystem_dir_read(intern TSRMLS_CC); if (intern->file_name) { efree(intern->file_name); intern->file_name = NULL; @@ -740,9 +765,9 @@ } /* }}} */ -/* {{{ proto string RecursiveDirectoryIterator::key() +/* {{{ proto string FilesystemIterator::key() Return getPathname() or getFilename() depending on flags */ -SPL_METHOD(RecursiveDirectoryIterator, key) +SPL_METHOD(FilesystemIterator, key) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); @@ -755,9 +780,9 @@ } /* }}} */ -/* {{{ proto string RecursiveDirectoryIterator::current() +/* {{{ proto string FilesystemIterator::current() Return getFilename(), getFileInfo() or $this depending on flags */ -SPL_METHOD(RecursiveDirectoryIterator, current) +SPL_METHOD(FilesystemIterator, current) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); @@ -1042,34 +1067,17 @@ } /* }}} */ -/* {{{ proto void RecursiveDirectoryIterator::__construct(string path [, int flags]) +/* {{{ proto void FilesystemIterator::__construct(string path [, int flags]) Cronstructs a new dir iterator from a path. */ -SPL_METHOD(RecursiveDirectoryIterator, __construct) +SPL_METHOD(FilesystemIterator, __construct) { - spl_filesystem_object *intern; - char *path; - int len; - long flags = SPL_FILE_DIR_CURRENT_AS_FILEINFO; - - php_set_error_handling(EH_THROW, spl_ce_UnexpectedValueException TSRMLS_CC); - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &path, &len, &flags) == FAILURE) { - php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); - return; - } - - intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - spl_filesystem_dir_open(intern, path TSRMLS_CC); - intern->u.dir.is_recursive = instanceof_function(intern->std.ce, spl_ce_RecursiveDirectoryIterator TSRMLS_CC) ? 1 : 0; - intern->flags = flags; - - php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); + spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIT_CTOR_FLAGS); } /* }}} */ -/* {{{ proto void RecursiveDirectoryIterator::rewind() +/* {{{ proto void FilesystemIterator::rewind() Rewind dir back to the start */ -SPL_METHOD(RecursiveDirectoryIterator, rewind) +SPL_METHOD(FilesystemIterator, rewind) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); @@ -1078,24 +1086,20 @@ php_stream_rewinddir(intern->u.dir.dirp); } do { - if (!intern->u.dir.dirp || !php_stream_readdir(intern->u.dir.dirp, &intern->u.dir.entry)) { - intern->u.dir.entry.d_name[0] = '\0'; - } + spl_filesystem_dir_read(intern TSRMLS_CC); } while (spl_filesystem_is_dot(intern->u.dir.entry.d_name)); } /* }}} */ -/* {{{ proto void RecursiveDirectoryIterator::next() +/* {{{ proto void FilesystemIterator::next() Move to next entry */ -SPL_METHOD(RecursiveDirectoryIterator, next) +SPL_METHOD(FilesystemIterator, next) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); intern->u.dir.index++; do { - if (!intern->u.dir.dirp || !php_stream_readdir(intern->u.dir.dirp, &intern->u.dir.entry)) { - intern->u.dir.entry.d_name[0] = '\0'; - } + spl_filesystem_dir_read(intern TSRMLS_CC); } while (spl_filesystem_is_dot(intern->u.dir.entry.d_name)); if (intern->file_name) { efree(intern->file_name); @@ -1112,7 +1116,7 @@ spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); if (spl_filesystem_is_invalid_or_dot(intern->u.dir.entry.d_name)) { - RETURN_BOOL(0); + RETURN_FALSE; } else { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &allow_links) == FAILURE) { return; @@ -1121,7 +1125,7 @@ if (!allow_links) { php_stat(intern->file_name, intern->file_name_len, FS_IS_LINK, return_value TSRMLS_CC); if (zend_is_true(return_value)) { - RETURN_BOOL(0); + RETURN_FALSE; } } php_stat(intern->file_name, intern->file_name_len, FS_IS_DIR, return_value TSRMLS_CC); @@ -1133,16 +1137,18 @@ Returns an iterator for the current entry if it is a directory */ SPL_METHOD(RecursiveDirectoryIterator, getChildren) { - zval zpath; + zval zpath, zflags; spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); spl_filesystem_object *subdir; spl_filesystem_object_get_file_name(intern TSRMLS_CC); + INIT_PZVAL(&zflags); INIT_PZVAL(&zpath); + ZVAL_LONG(&zflags, intern->flags); ZVAL_STRINGL(&zpath, intern->file_name, intern->file_name_len, 0); - spl_instantiate_arg_ex1(spl_ce_RecursiveDirectoryIterator, &return_value, 0, &zpath TSRMLS_CC); + spl_instantiate_arg_ex2(spl_ce_RecursiveDirectoryIterator, &return_value, 0, &zpath, &zflags TSRMLS_CC); subdir = (spl_filesystem_object*)zend_object_store_get_object(return_value TSRMLS_CC); if (subdir) { @@ -1154,7 +1160,6 @@ } subdir->info_class = intern->info_class; subdir->file_class = intern->file_class; - subdir->flags = intern->flags; subdir->oth = intern->oth; } } @@ -1191,12 +1196,36 @@ } /* }}} */ -/* define an overloaded iterator structure */ -typedef struct { - zend_object_iterator intern; - zval *current; - spl_filesystem_object *object; -} spl_filesystem_dir_it; +/* {{{ proto int RecursiveDirectoryIterator::__construct(string path [, int flags]) + Cronstructs a new dir iterator from a path. */ +SPL_METHOD(RecursiveDirectoryIterator, __construct) +{ + spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIT_CTOR_FLAGS); +} +/* }}} */ + +/* {{{ proto int GlobIterator::__construct(string path [, int flags]) + Cronstructs a new dir iterator from a glob expression (no glob:// needed). */ +SPL_METHOD(GlobIterator, __construct) +{ + spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIT_CTOR_FLAGS|DIT_CTOR_GLOB); +} +/* }}} */ + +/* {{{ proto int GlobIterator::cont() + Return the number of directories and files found by globbing */ +SPL_METHOD(GlobIterator, count) +{ + spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + + if (php_stream_is(intern->u.dir.dirp ,&php_glob_stream_ops)) { + RETURN_LONG(php_glob_stream_get_count(intern->u.dir.dirp, NULL)); + } else { + /* should not happen */ + php_error_docref(NULL TSRMLS_CC, E_ERROR, "GlobIterator lost glob state"); + } +} +/* }}} */ /* forward declarations to the iterator handlers */ static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter TSRMLS_DC); @@ -1219,20 +1248,19 @@ /* {{{ spl_ce_dir_get_iterator */ zend_object_iterator *spl_filesystem_dir_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) { - spl_filesystem_dir_it *iterator; - spl_filesystem_object *dir_object; + spl_filesystem_iterator *iterator; + spl_filesystem_object *dir_object; if (by_ref) { zend_error(E_ERROR, "An iterator cannot be used with foreach by reference"); } - iterator = emalloc(sizeof(spl_filesystem_dir_it)); dir_object = (spl_filesystem_object*)zend_object_store_get_object(object TSRMLS_CC); + iterator = spl_filesystem_object_to_iterator(dir_object); Z_SET_REFCOUNT_P(object, Z_REFCOUNT_P(object) + 2); iterator->intern.data = (void*)object; iterator->intern.funcs = &spl_filesystem_dir_it_funcs; iterator->current = object; - iterator->object = dir_object; return (zend_object_iterator*)iterator; } @@ -1241,20 +1269,18 @@ /* {{{ spl_filesystem_dir_it_dtor */ static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter TSRMLS_DC) { - spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter; + spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter; zval_ptr_dtor(&iterator->current); zval_ptr_dtor((zval**)&iterator->intern.data); - - efree(iterator); + iterator->intern.data = NULL; /* mark as unused */ } /* }}} */ /* {{{ spl_filesystem_dir_it_valid */ static int spl_filesystem_dir_it_valid(zend_object_iterator *iter TSRMLS_DC) { - spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter; - spl_filesystem_object *object = iterator->object; + spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter); return object->u.dir.entry.d_name[0] != '\0' ? SUCCESS : FAILURE; } @@ -1264,7 +1290,7 @@ /* {{{ spl_filesystem_dir_it_current_data */ static void spl_filesystem_dir_it_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) { - spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter; + spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter; *data = &iterator->current; } @@ -1273,8 +1299,7 @@ /* {{{ spl_filesystem_dir_it_current_key */ static int spl_filesystem_dir_it_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) { - spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter; - spl_filesystem_object *object = iterator->object; + spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter); *int_key = object->u.dir.index; return HASH_KEY_IS_LONG; @@ -1284,13 +1309,10 @@ /* {{{ spl_filesystem_dir_it_move_forward */ static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter TSRMLS_DC) { - spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter; - spl_filesystem_object *object = iterator->object; + spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter); object->u.dir.index++; - if (!object->u.dir.dirp || !php_stream_readdir(object->u.dir.dirp, &object->u.dir.entry)) { - object->u.dir.entry.d_name[0] = '\0'; - } + spl_filesystem_dir_read(object TSRMLS_CC); if (object->file_name) { efree(object->file_name); object->file_name = NULL; @@ -1301,38 +1323,34 @@ /* {{{ spl_filesystem_dir_it_rewind */ static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter TSRMLS_DC) { - spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter; - spl_filesystem_object *object = iterator->object; + spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter); object->u.dir.index = 0; if (object->u.dir.dirp) { php_stream_rewinddir(object->u.dir.dirp); } - if (!object->u.dir.dirp || !php_stream_readdir(object->u.dir.dirp, &object->u.dir.entry)) { - object->u.dir.entry.d_name[0] = '\0'; - } + spl_filesystem_dir_read(object TSRMLS_CC); } /* }}} */ /* {{{ spl_filesystem_tree_it_dtor */ static void spl_filesystem_tree_it_dtor(zend_object_iterator *iter TSRMLS_DC) { - spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter; + spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter; if (iterator->current) { zval_ptr_dtor(&iterator->current); } zval_ptr_dtor((zval**)&iterator->intern.data); - - efree(iterator); + iterator->intern.data = NULL; /* mark as unused */ } /* }}} */ /* {{{ spl_filesystem_tree_it_current_data */ static void spl_filesystem_tree_it_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) { - spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter; - spl_filesystem_object *object = iterator->object; + spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter; + spl_filesystem_object *object = spl_filesystem_iterator_to_object(iterator); if (object->flags & SPL_FILE_DIR_CURRENT_AS_PATHNAME) { if (!iterator->current) { @@ -1357,8 +1375,7 @@ /* {{{ spl_filesystem_tree_it_current_key */ static int spl_filesystem_tree_it_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) { - spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter; - spl_filesystem_object *object = iterator->object; + spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter); if (object->flags & SPL_FILE_DIR_KEY_AS_FILENAME) { *str_key_len = strlen(object->u.dir.entry.d_name) + 1; @@ -1375,14 +1392,12 @@ /* {{{ spl_filesystem_tree_it_move_forward */ static void spl_filesystem_tree_it_move_forward(zend_object_iterator *iter TSRMLS_DC) { - spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter; - spl_filesystem_object *object = iterator->object; + spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter; + spl_filesystem_object *object = spl_filesystem_iterator_to_object(iterator); object->u.dir.index++; do { - if (!object->u.dir.dirp || !php_stream_readdir(object->u.dir.dirp, &object->u.dir.entry)) { - object->u.dir.entry.d_name[0] = '\0'; - } + spl_filesystem_dir_read(object TSRMLS_CC); } while (spl_filesystem_is_dot(object->u.dir.entry.d_name)); if (object->file_name) { efree(object->file_name); @@ -1398,17 +1413,15 @@ /* {{{ spl_filesystem_tree_it_rewind */ static void spl_filesystem_tree_it_rewind(zend_object_iterator *iter TSRMLS_DC) { - spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter; - spl_filesystem_object *object = iterator->object; + spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter; + spl_filesystem_object *object = spl_filesystem_iterator_to_object(iterator); object->u.dir.index = 0; if (object->u.dir.dirp) { php_stream_rewinddir(object->u.dir.dirp); } do { - if (!object->u.dir.dirp || !php_stream_readdir(object->u.dir.dirp, &object->u.dir.entry)) { - object->u.dir.entry.d_name[0] = '\0'; - } + spl_filesystem_dir_read(object TSRMLS_CC); } while (spl_filesystem_is_dot(object->u.dir.entry.d_name)); if (iterator->current) { zval_ptr_dtor(&iterator->current); @@ -1430,20 +1443,19 @@ /* {{{ spl_ce_dir_get_iterator */ zend_object_iterator *spl_filesystem_tree_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) { - spl_filesystem_dir_it *iterator; + spl_filesystem_iterator *iterator; spl_filesystem_object *dir_object; if (by_ref) { zend_error(E_ERROR, "An iterator cannot be used with foreach by reference"); } - iterator = emalloc(sizeof(spl_filesystem_dir_it)); dir_object = (spl_filesystem_object*)zend_object_store_get_object(object TSRMLS_CC); + iterator = spl_filesystem_object_to_iterator(dir_object); Z_ADDREF_P(object); iterator->intern.data = (void*)object; iterator->intern.funcs = &spl_filesystem_tree_it_funcs; iterator->current = NULL; - iterator->object = dir_object; return (zend_object_iterator*)iterator; } @@ -1562,12 +1574,17 @@ ZEND_ARG_INFO(0, allow_links) ZEND_END_ARG_INFO() +static const zend_function_entry spl_FilesystemIterator_functions[] = { + SPL_ME(FilesystemIterator, __construct, arginfo_r_dir___construct, ZEND_ACC_PUBLIC) + SPL_ME(FilesystemIterator, rewind, NULL, ZEND_ACC_PUBLIC) + SPL_ME(FilesystemIterator, next, NULL, ZEND_ACC_PUBLIC) + SPL_ME(FilesystemIterator, key, NULL, ZEND_ACC_PUBLIC) + SPL_ME(FilesystemIterator, current, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + static const zend_function_entry spl_RecursiveDirectoryIterator_functions[] = { SPL_ME(RecursiveDirectoryIterator, __construct, arginfo_r_dir___construct, ZEND_ACC_PUBLIC) - SPL_ME(RecursiveDirectoryIterator, rewind, NULL, ZEND_ACC_PUBLIC) - SPL_ME(RecursiveDirectoryIterator, next, NULL, ZEND_ACC_PUBLIC) - SPL_ME(RecursiveDirectoryIterator, key, NULL, ZEND_ACC_PUBLIC) - SPL_ME(RecursiveDirectoryIterator, current, NULL, ZEND_ACC_PUBLIC) SPL_ME(RecursiveDirectoryIterator, hasChildren, arginfo_r_dir_hasChildren, ZEND_ACC_PUBLIC) SPL_ME(RecursiveDirectoryIterator, getChildren, NULL, ZEND_ACC_PUBLIC) SPL_ME(RecursiveDirectoryIterator, getSubPath, NULL, ZEND_ACC_PUBLIC) @@ -1575,6 +1592,12 @@ {NULL, NULL, NULL} }; +static const zend_function_entry spl_GlobIterator_functions[] = { + SPL_ME(GlobIterator, __construct, arginfo_r_dir___construct, ZEND_ACC_PUBLIC) + SPL_ME(GlobIterator, count, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + static int spl_filesystem_file_read(spl_filesystem_object *intern, int silent TSRMLS_DC) /* {{{ */ { char *buf; @@ -2444,19 +2467,24 @@ spl_ce_DirectoryIterator->get_iterator = spl_filesystem_dir_get_iterator; - REGISTER_SPL_SUB_CLASS_EX(RecursiveDirectoryIterator, DirectoryIterator, spl_filesystem_object_new, spl_RecursiveDirectoryIterator_functions); - REGISTER_SPL_IMPLEMENTS(RecursiveDirectoryIterator, RecursiveIterator); + REGISTER_SPL_SUB_CLASS_EX(FilesystemIterator, DirectoryIterator, spl_filesystem_object_new, spl_FilesystemIterator_functions); - REGISTER_SPL_CLASS_CONST_LONG(RecursiveDirectoryIterator, "CURRENT_MODE_MASK", SPL_FILE_DIR_CURRENT_MODE_MASK); - REGISTER_SPL_CLASS_CONST_LONG(RecursiveDirectoryIterator, "CURRENT_AS_PATHNAME", SPL_FILE_DIR_CURRENT_AS_PATHNAME); - REGISTER_SPL_CLASS_CONST_LONG(RecursiveDirectoryIterator, "CURRENT_AS_FILEINFO", SPL_FILE_DIR_CURRENT_AS_FILEINFO); - REGISTER_SPL_CLASS_CONST_LONG(RecursiveDirectoryIterator, "CURRENT_AS_SELF", 0); - REGISTER_SPL_CLASS_CONST_LONG(RecursiveDirectoryIterator, "KEY_MODE_MASK", SPL_FILE_DIR_KEY_MODE_MASK); - REGISTER_SPL_CLASS_CONST_LONG(RecursiveDirectoryIterator, "KEY_AS_PATHNAME", 0); - REGISTER_SPL_CLASS_CONST_LONG(RecursiveDirectoryIterator, "KEY_AS_FILENAME", SPL_FILE_DIR_KEY_AS_FILENAME); - REGISTER_SPL_CLASS_CONST_LONG(RecursiveDirectoryIterator, "NEW_CURRENT_AND_KEY", SPL_FILE_DIR_KEY_AS_FILENAME|SPL_FILE_DIR_CURRENT_AS_FILEINFO); + REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "CURRENT_MODE_MASK", SPL_FILE_DIR_CURRENT_MODE_MASK); + REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "CURRENT_AS_PATHNAME", SPL_FILE_DIR_CURRENT_AS_PATHNAME); + REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "CURRENT_AS_FILEINFO", SPL_FILE_DIR_CURRENT_AS_FILEINFO); + REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "CURRENT_AS_SELF", 0); + REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "KEY_MODE_MASK", SPL_FILE_DIR_KEY_MODE_MASK); + REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "KEY_AS_PATHNAME", 0); + REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "KEY_AS_FILENAME", SPL_FILE_DIR_KEY_AS_FILENAME); + REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "NEW_CURRENT_AND_KEY", SPL_FILE_DIR_KEY_AS_FILENAME|SPL_FILE_DIR_CURRENT_AS_FILEINFO); + + spl_ce_FilesystemIterator->get_iterator = spl_filesystem_tree_get_iterator; + + REGISTER_SPL_SUB_CLASS_EX(RecursiveDirectoryIterator, FilesystemIterator, spl_filesystem_object_new, spl_RecursiveDirectoryIterator_functions); + REGISTER_SPL_IMPLEMENTS(RecursiveDirectoryIterator, RecursiveIterator); - spl_ce_RecursiveDirectoryIterator->get_iterator = spl_filesystem_tree_get_iterator; + REGISTER_SPL_SUB_CLASS_EX(GlobIterator, FilesystemIterator, spl_filesystem_object_new, spl_GlobIterator_functions); + REGISTER_SPL_IMPLEMENTS(GlobIterator, Countable); REGISTER_SPL_SUB_CLASS_EX(SplFileObject, SplFileInfo, spl_filesystem_object_new, spl_SplFileObject_functions); REGISTER_SPL_IMPLEMENTS(SplFileObject, RecursiveIterator); http://cvs.php.net/viewvc.cgi/php-src/ext/spl/spl_directory.h?r1=1.12.2.5.2.4.2.4&r2=1.12.2.5.2.4.2.5&diff_format=u Index: php-src/ext/spl/spl_directory.h diff -u php-src/ext/spl/spl_directory.h:1.12.2.5.2.4.2.4 php-src/ext/spl/spl_directory.h:1.12.2.5.2.4.2.5 --- php-src/ext/spl/spl_directory.h:1.12.2.5.2.4.2.4 Wed Jan 30 20:31:07 2008 +++ php-src/ext/spl/spl_directory.h Sat Feb 2 23:09:38 2008 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: spl_directory.h,v 1.12.2.5.2.4.2.4 2008/01/30 20:31:07 helly Exp $ */ +/* $Id: spl_directory.h,v 1.12.2.5.2.4.2.5 2008/02/02 23:09:38 helly Exp $ */ #ifndef SPL_DIRECTORY_H #define SPL_DIRECTORY_H @@ -26,7 +26,9 @@ extern PHPAPI zend_class_entry *spl_ce_SplFileInfo; extern PHPAPI zend_class_entry *spl_ce_DirectoryIterator; +extern PHPAPI zend_class_entry *spl_ce_FilesystemIterator; extern PHPAPI zend_class_entry *spl_ce_RecursiveDirectoryIterator; +extern PHPAPI zend_class_entry *spl_ce_GlobIterator; extern PHPAPI zend_class_entry *spl_ce_SplFileObject; extern PHPAPI zend_class_entry *spl_ce_SplTempFileObject; @@ -50,6 +52,13 @@ spl_foreign_clone_t clone; } spl_other_handler; +/* define an overloaded iterator structure */ +typedef struct { + zend_object_iterator intern; + zval *current; + spl_filesystem_object *object; +} spl_filesystem_iterator; + struct _spl_filesystem_object { zend_object std; void *oth; @@ -89,8 +98,19 @@ char escape; } file; } u; + spl_filesystem_iterator it; }; +static inline spl_filesystem_iterator* spl_filesystem_object_to_iterator(spl_filesystem_object *obj) +{ + return &obj->it; +} + +static inline spl_filesystem_object* spl_filesystem_iterator_to_object(spl_filesystem_iterator *it) +{ + return (spl_filesystem_object*)((char*)it - XtOffsetOf(spl_filesystem_object, it)); +} + #define SPL_FILE_OBJECT_DROP_NEW_LINE 0x00000001 /* drop new lines */ #define SPL_FILE_OBJECT_READ_AHEAD 0x00000002 /* read on rewind/next */ #define SPL_FILE_OBJECT_SKIP_EMPTY 0x00000006 /* skip empty lines */
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php