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 */