]> granicus.if.org Git - php/commitdiff
- MFH Add class SplFileInfo as base for DirectoryIterator and SplFileObject
authorMarcus Boerger <helly@php.net>
Tue, 29 Nov 2005 03:33:59 +0000 (03:33 +0000)
committerMarcus Boerger <helly@php.net>
Tue, 29 Nov 2005 03:33:59 +0000 (03:33 +0000)
# As discussed with ilia before 5.1.0

ext/spl/examples/nocvsdir.php
ext/spl/php_spl.c
ext/spl/spl_directory.c
ext/spl/spl_directory.h
ext/spl/tests/iterator_028.phpt
ext/spl/tests/spl_autoload_004.phpt
ext/spl/tests/sxe_001.phpt
ext/spl/tests/sxe_004.phpt

index e89dc13d9f6443367b515d590ff0d600535e39ab..a6b182f5f36fcebc40352de0429f2920006aa043 100755 (executable)
@@ -30,18 +30,13 @@ class NoCvsDirectory extends RecursiveFilterIterator
 {
        function __construct($path)
        {
-               parent::__construct(new RecursiveDirectoryIterator($path));
+               parent::__construct(new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::CURRENT_AS_PATHNAME));
        }
 
        function accept()
        {
                return $this->getInnerIterator()->getFilename() != 'CVS';
        }
-       
-       function getChildren()
-       {
-               return new NoCvsDirectory($this->current()->getPathName());
-       }
 }
 
 $it = new RecursiveIteratorIterator(new NoCvsDirectory($argv[1]));
index a8a9f0e0a3655b45f15f1cabcadc3beef9d044d9..b491fa8127912509e725b0184069d3ab2e4c9645 100755 (executable)
@@ -183,6 +183,7 @@ PHP_FUNCTION(class_implements)
        SPL_ADD_CLASS(RuntimeException, z_list, sub, allow, ce_flags); \
        SPL_ADD_CLASS(SeekableIterator, z_list, sub, allow, ce_flags); \
        SPL_ADD_CLASS(SimpleXMLIterator, z_list, sub, allow, ce_flags); \
+       SPL_ADD_CLASS(SplFileInfo, z_list, sub, allow, ce_flags); \
        SPL_ADD_CLASS(SplFileObject, z_list, sub, allow, ce_flags); \
        SPL_ADD_CLASS(SplObjectStorage, z_list, sub, allow, ce_flags); \
        SPL_ADD_CLASS(SplObserver, z_list, sub, allow, ce_flags); \
index 52471d83ee58c7ea597bec22b2014e40e904d1f6..5349c33d34750fe09480273f207db7d042b8559d 100755 (executable)
 #include "ext/standard/php_filestat.h"
 
 /* declare the class handlers */
-static zend_object_handlers spl_ce_dir_handlers;
+static zend_object_handlers spl_filesystem_object_handlers;
 
 /* decalre the class entry */
+PHPAPI zend_class_entry *spl_ce_SplFileInfo;
 PHPAPI zend_class_entry *spl_ce_DirectoryIterator;
 PHPAPI zend_class_entry *spl_ce_RecursiveDirectoryIterator;
 PHPAPI zend_class_entry *spl_ce_SplFileObject;
+PHPAPI zend_class_entry *spl_ce_SplTempFileObject;
 
-static zend_object_value spl_file_object_new_ex(zend_class_entry *class_type, spl_file_object **obj TSRMLS_DC);
-static int spl_file_object_open(spl_file_object *intern, int use_include_path, int silent TSRMLS_DC);
+static void spl_filesystem_file_free_line(spl_filesystem_object *intern TSRMLS_DC) /* {{{ */
+{
+       if (intern->u.file.current_line) {
+               efree(intern->u.file.current_line);
+               intern->u.file.current_line = NULL;
+       }
+       if (intern->u.file.current_zval) {
+               zval_ptr_dtor(&intern->u.file.current_zval);
+               intern->u.file.current_zval = NULL;
+       }
+} /* }}} */
 
-/* {{{ spl_ce_dir_object_free_storage */
-/* close all resources and the memory allocated for the object */
-static void spl_ce_dir_object_free_storage(void *object TSRMLS_DC)
+static void spl_filesystem_object_free_storage(void *object TSRMLS_DC) /* {{{ */
 {
-       spl_ce_dir_object *intern = (spl_ce_dir_object *)object;
+       spl_filesystem_object *intern = (spl_filesystem_object*)object;
 
        zend_hash_destroy(intern->std.properties);
        FREE_HASHTABLE(intern->std.properties);
@@ -67,19 +76,39 @@ static void spl_ce_dir_object_free_storage(void *object TSRMLS_DC)
        if (intern->path) {
                efree(intern->path);
        }
-       if (intern->dirp) {
-               php_stream_close(intern->dirp);
-       }
-       if (intern->path_name) {
-               efree(intern->path_name);
+       if (intern->file_name) {
+               efree(intern->file_name);
        }
-       if (intern->sub_path) {
-               efree(intern->sub_path);
+       switch(intern->type) {
+       case SPL_FS_INFO:
+               break;
+       case SPL_FS_DIR:
+               if (intern->u.dir.dirp) {
+                       php_stream_close(intern->u.dir.dirp);
+               }
+               if (intern->u.dir.sub_path) {
+                       efree(intern->u.dir.sub_path);
+               }               
+               break;
+       case SPL_FS_FILE:
+               if (intern->u.file.stream) {
+                       if (intern->u.file.zcontext) {
+/*                             zend_list_delref(Z_RESVAL_P(intern->zcontext));*/
+                       }
+                       if (!intern->u.file.stream->is_persistent) {
+                               php_stream_free(intern->u.file.stream, PHP_STREAM_FREE_CLOSE);
+                       } else {
+                               php_stream_free(intern->u.file.stream, PHP_STREAM_FREE_CLOSE_PERSISTENT);
+                       }
+                       if (intern->u.file.open_mode) {
+                               efree(intern->u.file.open_mode);
+                       }
+               }
+               spl_filesystem_file_free_line(intern TSRMLS_CC);
+               break;
        }
        efree(object);
-}
-/* }}} */
-
+} /* }}} */
 
 /* {{{ spl_ce_dir_object_new */
 /* creates the object by 
@@ -92,82 +121,149 @@ static void spl_ce_dir_object_free_storage(void *object TSRMLS_DC)
    - clone
    - new
  */
-static zend_object_value spl_ce_dir_object_new_ex(zend_class_entry *class_type, spl_ce_dir_object **obj TSRMLS_DC)
+static zend_object_value spl_filesystem_object_new_ex(zend_class_entry *class_type, spl_filesystem_object **obj TSRMLS_DC)
 {
        zend_object_value retval;
-       spl_ce_dir_object *intern;
+       spl_filesystem_object *intern;
        zval *tmp;
 
-       intern = emalloc(sizeof(spl_ce_dir_object));
-       memset(intern, 0, sizeof(spl_ce_dir_object));
+       intern = emalloc(sizeof(spl_filesystem_object));
+       memset(intern, 0, sizeof(spl_filesystem_object));
        intern->std.ce = class_type;
+       /* intern->type = SPL_FS_INFO; done by set o */
+       intern->file_class = spl_ce_SplFileObject;
+       intern->info_class = spl_ce_SplFileInfo;
        if (obj) *obj = intern;
 
        ALLOC_HASHTABLE(intern->std.properties);
        zend_hash_init(intern->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
        zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
 
-       retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_ce_dir_object_free_storage, NULL TSRMLS_CC);
-       retval.handlers = &spl_ce_dir_handlers;
+       retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_filesystem_object_free_storage, NULL TSRMLS_CC);
+       retval.handlers = &spl_filesystem_object_handlers;
        return retval;
 }
 /* }}} */
 
-
-/* {{{ spl_ce_dir_object_new */
-/* See spl_ce_dir_object_new_ex */
-static zend_object_value spl_ce_dir_object_new(zend_class_entry *class_type TSRMLS_DC)
+/* {{{ spl_filesystem_object_new */
+/* See spl_filesystem_object_new_ex */
+static zend_object_value spl_filesystem_object_new(zend_class_entry *class_type TSRMLS_DC)
 {
-       return spl_ce_dir_object_new_ex(class_type, NULL TSRMLS_CC);
+       return spl_filesystem_object_new_ex(class_type, NULL TSRMLS_CC);
 }
 /* }}} */
 
-/* {{{ spl_ce_dir_open */
+static inline void spl_filesystem_object_get_file_name(spl_filesystem_object *intern TSRMLS_DC) /* {{{ */
+{
+       if (!intern->file_name) {
+               switch (intern->type) {
+               case SPL_FS_INFO:
+               case SPL_FS_FILE:
+                       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Object not initialized");
+                       break;
+               case SPL_FS_DIR:
+                       intern->file_name_len = spprintf(&intern->file_name, 0, "%s/%s", intern->path, intern->u.dir.entry.d_name);
+                       break;
+               }
+       }
+} /* }}} */
+
+/* {{{ spl_filesystem_dir_open */
 /* open a directory resource */
-static void spl_ce_dir_open(spl_ce_dir_object* intern, char *path TSRMLS_DC)
+static void spl_filesystem_dir_open(spl_filesystem_object* intern, char *path TSRMLS_DC)
 {
-       int path_len = strlen(path);
-
-       intern->dirp = php_stream_opendir(path, ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL);
+       intern->type = SPL_FS_DIR;
+       intern->path_len = strlen(path);
+       intern->u.dir.dirp = php_stream_opendir(path, ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL);
 
-       if (path_len && (path[path_len-1] == '/' || path[path_len-1] == '\\')) {
-               intern->path = estrndup(path, --path_len);
+       if (intern->path_len && (path[intern->path_len-1] == '/' || path[intern->path_len-1] == '\\')) {
+               intern->path = estrndup(path, --intern->path_len);
        } else {
-               intern->path = estrndup(path, path_len);
+               intern->path = estrndup(path, intern->path_len);
        }
-       intern->index = 0;
+       intern->u.dir.index = 0;
 
-       if (intern->dirp == NULL) {
+       if (intern->u.dir.dirp == NULL) {
                /* throw exception: should've been already happened */
-               intern->entry.d_name[0] = '\0';
+               intern->u.dir.entry.d_name[0] = '\0';
        } else {
-               if (!php_stream_readdir(intern->dirp, &intern->entry)) {
-                       intern->entry.d_name[0] = '\0';
+               if (!php_stream_readdir(intern->u.dir.dirp, &intern->u.dir.entry)) {
+                       intern->u.dir.entry.d_name[0] = '\0';
                }
        }
 }
 /* }}} */
 
-/* {{{ spl_ce_dir_object_clone */
+static int spl_filesystem_file_open(spl_filesystem_object *intern, int use_include_path, int silent TSRMLS_DC) /* {{{ */
+{
+       intern->type = SPL_FS_FILE;
+       intern->u.file.context = php_stream_context_from_zval(intern->u.file.zcontext, 0);
+       intern->u.file.stream = php_stream_open_wrapper_ex(intern->file_name, intern->u.file.open_mode, (use_include_path ? USE_PATH : 0) | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, intern->u.file.context);
+
+       if (intern->u.file.stream == NULL) {
+               if (!EG(exception)) {
+                       zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot open file %s", intern->file_name);
+               }
+               intern->file_name = NULL; /* until here it is not a copy */
+               intern->u.file.open_mode = NULL;
+               return FAILURE;
+       }
+
+       if (intern->u.file.zcontext) {
+               zend_list_addref(Z_RESVAL_P(intern->u.file.zcontext));
+       }
+
+       intern->file_name = estrndup(intern->file_name, intern->file_name_len);
+       intern->u.file.open_mode = estrndup(intern->u.file.open_mode, intern->u.file.open_mode_len);
+
+       /* avoid reference counting in debug mode, thus do it manually */
+       ZVAL_RESOURCE(&intern->u.file.zresource, php_stream_get_resource_id(intern->u.file.stream));
+       intern->u.file.zresource.refcount = 1;
+
+       zend_hash_find(&intern->std.ce->function_table, "getcurrentline", sizeof("getcurrentline"), (void **) &intern->u.file.func_getCurr);
+
+       return SUCCESS;
+} /* }}} */
+
+/* {{{ spl_filesystem_object_clone */
 /* Local zend_object_value creation (on stack)
    Load the 'other' object 
-   Create a new empty object (See spl_ce_dir_object_new_ex)
+   Create a new empty object (See spl_filesystem_object_new_ex)
    Open the directory
    Clone other members (properties)
  */
-static zend_object_value spl_ce_dir_object_clone(zval *zobject TSRMLS_DC)
+static zend_object_value spl_filesystem_object_clone(zval *zobject TSRMLS_DC)
 {
        zend_object_value new_obj_val;
        zend_object *old_object;
        zend_object *new_object;
        zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
-       spl_ce_dir_object *intern;
+       spl_filesystem_object *intern;
+       spl_filesystem_object *source;
 
        old_object = zend_objects_get_address(zobject TSRMLS_CC);
-       new_obj_val = spl_ce_dir_object_new_ex(old_object->ce, &intern TSRMLS_CC);
+       source = (spl_filesystem_object*)old_object;
+
+       new_obj_val = spl_filesystem_object_new_ex(old_object->ce, &intern TSRMLS_CC);
        new_object = &intern->std;
 
-       spl_ce_dir_open(intern, ((spl_ce_dir_object*)old_object)->path TSRMLS_CC);
+       switch (source->type) {
+       case SPL_FS_INFO:
+               source->path_len = source->path_len;
+               source->path = estrndup(source->path, source->path_len);
+               intern->file_name_len = source->file_name_len;
+               intern->file_name = estrndup(source->file_name, intern->file_name_len);
+               break;
+       case SPL_FS_DIR:
+               spl_filesystem_dir_open(intern, source->path TSRMLS_CC);
+               break;
+       case SPL_FS_FILE:
+               php_error_docref(NULL TSRMLS_CC, E_ERROR, "An object of class %s cannot be cloned", old_object->ce->name);
+               break;
+       }
+       
+       intern->file_class = source->file_class;
+       intern->info_class = source->info_class;
 
        zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC);
 
@@ -175,7 +271,113 @@ static zend_object_value spl_ce_dir_object_clone(zval *zobject TSRMLS_DC)
 }
 /* }}} */
 
-/* {{{ proto void DirectoryIterator::__construct(string path)
+void spl_filesystem_info_set_filename(spl_filesystem_object *intern, char *path, int len, int use_copy TSRMLS_DC) /* {{{ */
+{
+       char *p1, *p2;
+
+       intern->file_name = use_copy ? estrndup(path, len) : path;
+       intern->file_name_len = len;
+
+       p1 = strrchr(path, '/');
+       p2 = strrchr(path, '\\');
+       if (p1 || p2) {
+               intern->path_len = (p1 > p2 ? p1 : p2) - path;
+       } else {
+               intern->path_len = 0;
+       }
+       intern->path = estrndup(path, intern->path_len);
+} /* }}} */
+
+static spl_filesystem_object * spl_filesystem_object_create_info(spl_filesystem_object *source, char *file_path, int file_path_len, int use_copy, zend_class_entry *ce, zval *return_value TSRMLS_DC) /* {{{ */
+{
+       spl_filesystem_object *intern;
+       
+       if (!file_path || !file_path_len) {
+               zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot create SplFileInfo for empty path");
+               if (file_path && !use_copy)
+               {
+                       efree(file_path);
+               }
+               return NULL;
+       }
+
+       php_set_error_handling(EH_THROW, spl_ce_RuntimeException TSRMLS_CC);
+
+       return_value->value.obj = spl_filesystem_object_new_ex(ce ? ce : intern->info_class, &intern TSRMLS_CC);
+       Z_TYPE_P(return_value) = IS_OBJECT;
+
+       spl_filesystem_info_set_filename(intern, file_path, file_path_len, use_copy TSRMLS_CC);
+       
+       php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
+       
+       return intern;
+} /* }}} */
+
+static spl_filesystem_object * spl_filesystem_object_create_type(int ht, spl_filesystem_object *source, int type, zend_class_entry *ce, zval *return_value TSRMLS_DC) /* {{{ */
+{
+       spl_filesystem_object *intern;
+       zend_bool use_include_path = 0;
+
+       php_set_error_handling(EH_THROW, spl_ce_RuntimeException TSRMLS_CC);
+
+       switch (source->type) {
+       case SPL_FS_INFO:
+       case SPL_FS_FILE:
+               break;
+       case SPL_FS_DIR:
+               if (!source->u.dir.entry.d_name[0]) {
+                       zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Could not open file");
+                       php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
+                       return NULL;
+               }
+       }
+
+       switch (type) {
+       case SPL_FS_INFO:
+               return_value->value.obj = spl_filesystem_object_new_ex(ce ? ce : source->info_class, &intern TSRMLS_CC);
+               Z_TYPE_P(return_value) = IS_OBJECT;
+       
+               spl_filesystem_object_get_file_name(source TSRMLS_CC);
+               intern->file_name = estrndup(source->file_name, source->file_name_len);
+               intern->file_name_len = source->file_name_len;
+               break;
+       case SPL_FS_FILE:
+               return_value->value.obj = spl_filesystem_object_new_ex(ce ? ce : source->file_class, &intern TSRMLS_CC);
+               Z_TYPE_P(return_value) = IS_OBJECT;
+       
+               spl_filesystem_object_get_file_name(source TSRMLS_CC);
+               intern->file_name = source->file_name;
+               intern->file_name_len = source->file_name_len;
+       
+               intern->u.file.open_mode = "r";
+               intern->u.file.open_mode_len = 1;
+       
+               if (ht && zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sbr", 
+                               &intern->u.file.open_mode, &intern->u.file.open_mode_len, 
+                               &use_include_path, &intern->u.file.zcontext) == FAILURE) {
+                       php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
+                       intern->u.file.open_mode = NULL;
+                       zval_dtor(return_value);
+                       Z_TYPE_P(return_value) = IS_NULL;
+                       return NULL;
+               }
+       
+               if (spl_filesystem_file_open(intern, use_include_path, 0 TSRMLS_CC) == FAILURE) {
+                       php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
+                       zval_dtor(return_value);
+                       Z_TYPE_P(return_value) = IS_NULL;
+                       return NULL;
+               }
+       case SPL_FS_DIR:        
+               php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
+               zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Operation not supported");
+               return NULL;
+       }
+       php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
+       return NULL;
+} /* }}} */
+
+/* {{{ proto void DirectoryIterator::__construct(string path [, int flags])
  Cronstructs a new dir iterator from a path. */
 /* php_set_error_handling() is used to throw exceptions in case
    the constructor fails. Here we use this to ensure the object
@@ -186,20 +388,22 @@ static zend_object_value spl_ce_dir_object_clone(zval *zobject TSRMLS_DC)
  */
 SPL_METHOD(DirectoryIterator, __construct)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern;
+       spl_filesystem_object *intern;
        char *path;
        int len;
+       long flags = 0;
 
        php_set_error_handling(EH_THROW, spl_ce_RuntimeException TSRMLS_CC);
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &path, &len) == FAILURE) {
+       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_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
-       spl_ce_dir_open(intern, path TSRMLS_CC);
+       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);
 }
@@ -209,15 +413,14 @@ SPL_METHOD(DirectoryIterator, __construct)
    Rewind dir back to the start */
 SPL_METHOD(DirectoryIterator, rewind)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       intern->index = 0;
-       if (intern->dirp) {
-               php_stream_rewinddir(intern->dirp);
+       intern->u.dir.index = 0;
+       if (intern->u.dir.dirp) {
+               php_stream_rewinddir(intern->u.dir.dirp);
        }
-       if (!intern->dirp || !php_stream_readdir(intern->dirp, &intern->entry)) {
-               intern->entry.d_name[0] = '\0';
+       if (!intern->u.dir.dirp || !php_stream_readdir(intern->u.dir.dirp, &intern->u.dir.entry)) {
+               intern->u.dir.entry.d_name[0] = '\0';
        }
 }
 /* }}} */
@@ -226,11 +429,10 @@ SPL_METHOD(DirectoryIterator, rewind)
    Return current dir entry */
 SPL_METHOD(DirectoryIterator, key)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       if (intern->dirp) {
-               RETURN_LONG(intern->index);
+       if (intern->u.dir.dirp) {
+               RETURN_LONG(intern->u.dir.index);
        } else {
                RETURN_FALSE;
        }
@@ -249,16 +451,15 @@ SPL_METHOD(DirectoryIterator, current)
    Move to next entry */
 SPL_METHOD(DirectoryIterator, next)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       intern->index++;
-       if (!intern->dirp || !php_stream_readdir(intern->dirp, &intern->entry)) {
-               intern->entry.d_name[0] = '\0';
+       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';
        }
-       if (intern->path_name) {
-               efree(intern->path_name);
-               intern->path_name = NULL;
+       if (intern->file_name) {
+               efree(intern->file_name);
+               intern->file_name = NULL;
        }
 }
 /* }}} */
@@ -267,67 +468,97 @@ SPL_METHOD(DirectoryIterator, next)
    Check whether dir contains more entries */
 SPL_METHOD(DirectoryIterator, valid)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       RETURN_BOOL(intern->entry.d_name[0] != '\0');
+       RETURN_BOOL(intern->u.dir.entry.d_name[0] != '\0');
 }
 /* }}} */
 
-/* {{{ proto string DirectoryIterator::getPath()
-   Return directory path */
-SPL_METHOD(DirectoryIterator, getPath)
+/* {{{ proto string SplFileInfo::getPath()
+   Return the path */
+SPL_METHOD(SplFileInfo, getPath)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
        RETURN_STRING(intern->path, 1);
 }
 /* }}} */
 
+/* {{{ proto string SplFileInfo::getFilename()
+   Return filename only */
+SPL_METHOD(SplFileInfo, getFilename)
+{
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+       if (intern->path_len) {
+               RETURN_STRINGL(intern->file_name + intern->path_len + 1, intern->file_name_len - (intern->path_len + 1), 1);
+       } else {
+               RETURN_STRINGL(intern->file_name, intern->file_name_len, 1);
+       }
+}
+/* }}} */
+
 /* {{{ proto string DirectoryIterator::getFilename()
    Return filename of current dir entry */
 SPL_METHOD(DirectoryIterator, getFilename)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       RETURN_STRING(intern->entry.d_name, 1);
+       RETURN_STRING(intern->u.dir.entry.d_name, 1);
 }
 /* }}} */
 
-static inline void spl_dir_get_path_name(spl_ce_dir_object *intern)
+/* {{{ proto string SplFileInfo::getPathname()
+   Return path and filename */
+SPL_METHOD(SplFileInfo, getPathname)
 {
-       if (!intern->path_name) {
-               intern->path_name_len = spprintf(&intern->path_name, 0, "%s/%s", intern->path, intern->entry.d_name);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+       switch (intern->type) {
+       case SPL_FS_INFO:
+       case SPL_FS_FILE:
+               RETURN_STRINGL(intern->file_name, intern->file_name_len, 1);
+       case SPL_FS_DIR:
+               if (intern->u.dir.entry.d_name[0]) {
+                       spl_filesystem_object_get_file_name(intern TSRMLS_CC);
+                       RETURN_STRINGL(intern->file_name, intern->file_name_len, 1);
+               }
        }
+       RETURN_BOOL(0);
 }
+/* }}} */
 
-/* {{{ proto string DirectoryIterator::getPathname()
-   Return path and filename of current dir entry */
-SPL_METHOD(DirectoryIterator, getPathname)
+/* {{{ proto string RecursiveDirectoryIterator::key()
+   Return getPathname() or getFilename() depending on flags */
+SPL_METHOD(RecursiveDirectoryIterator, key)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       if (intern->entry.d_name[0]) {
-               spl_dir_get_path_name(intern);
-               RETURN_STRINGL(intern->path_name, intern->path_name_len, 1);
+       if (intern->flags & SPL_FILE_DIR_KEY_AS_FILENAME) {
+               RETURN_STRING(intern->u.dir.entry.d_name, 1);
        } else {
-               RETURN_BOOL(0);
+               spl_filesystem_object_get_file_name(intern TSRMLS_CC);
+               RETURN_STRINGL(intern->file_name, intern->file_name_len, 1);
        }
 }
 /* }}} */
 
-/* {{{ proto string RecursiveDirectoryIterator::key()
-   Return path and filename of current dir entry */
-SPL_METHOD(RecursiveDirectoryIterator, key)
+/* {{{ proto string RecursiveDirectoryIterator::current()
+   Return getFilename() or getFileInfo() depending on flags */
+SPL_METHOD(RecursiveDirectoryIterator, current)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       spl_dir_get_path_name(intern);
-       RETURN_STRINGL(intern->path_name, intern->path_name_len, 1);
+       if (intern->flags & SPL_FILE_DIR_CURRENT_AS_PATHNAME) {
+               spl_filesystem_object_get_file_name(intern TSRMLS_CC);
+               RETURN_STRINGL(intern->file_name, intern->file_name_len, 1);
+       } else if (intern->flags & SPL_FILE_DIR_CURRENT_AS_FILEINFO) {
+               spl_filesystem_object_get_file_name(intern TSRMLS_CC);
+               spl_filesystem_object_create_type(0, intern, SPL_FS_INFO, NULL, return_value TSRMLS_CC);
+       } else {
+               RETURN_ZVAL(getThis(), 1, 0);
+               /*RETURN_STRING(intern->u.dir.entry.d_name, 1);*/
+       }
 }
 /* }}} */
 
@@ -335,159 +566,210 @@ SPL_METHOD(RecursiveDirectoryIterator, key)
    Returns true if current entry is '.' or  '..' */
 SPL_METHOD(DirectoryIterator, isDot)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       RETURN_BOOL(!strcmp(intern->entry.d_name, ".") || !strcmp(intern->entry.d_name, ".."));
+       RETURN_BOOL(!strcmp(intern->u.dir.entry.d_name, ".") || !strcmp(intern->u.dir.entry.d_name, ".."));
 }
 /* }}} */
 
-/* {{{ DirectoryFunction */
-#define DirectoryFunction(func_name, func_num) \
-SPL_METHOD(DirectoryIterator, func_name) \
+/* {{{ proto void SplFileInfo::__construct(string file_name)
+ Cronstructs a new SplFileInfo from a path. */
+/* php_set_error_handling() is used to throw exceptions in case
+   the constructor fails. Here we use this to ensure the object
+   has a valid directory resource.
+   
+   When the constructor gets called the object is already created 
+   by the engine, so we must only call 'additional' initializations.
+ */
+SPL_METHOD(SplFileInfo, __construct)
+{
+       spl_filesystem_object *intern;
+       char *path;
+       int len;
+
+       php_set_error_handling(EH_THROW, spl_ce_RuntimeException TSRMLS_CC);
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &path, &len) == 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_info_set_filename(intern, path, len, 1 TSRMLS_CC);
+       
+       /* intern->type = SPL_FS_INFO; already set */
+
+       php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ FileInfoFunction */
+#define FileInfoFunction(func_name, func_num) \
+SPL_METHOD(SplFileInfo, func_name) \
 { \
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(getThis() TSRMLS_CC); \
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); \
  \
-       spl_dir_get_path_name(intern); \
-       php_stat(intern->path_name, intern->path_name_len, func_num, return_value TSRMLS_CC); \
+       spl_filesystem_object_get_file_name(intern TSRMLS_CC); \
+       php_stat(intern->file_name, intern->file_name_len, func_num, return_value TSRMLS_CC); \
 }
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::getPerms()
+/* {{{ proto int SplFileInfo::getPerms()
    Get file permissions */
-DirectoryFunction(getPerms, FS_PERMS)
+FileInfoFunction(getPerms, FS_PERMS)
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::getInode()
+/* {{{ proto int SplFileInfo::getInode()
    Get file inode */
-DirectoryFunction(getInode, FS_INODE)
+FileInfoFunction(getInode, FS_INODE)
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::getSize()
+/* {{{ proto int SplFileInfo::getSize()
    Get file size */
-DirectoryFunction(getSize, FS_SIZE)
+FileInfoFunction(getSize, FS_SIZE)
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::getOwner()
+/* {{{ proto int SplFileInfo::getOwner()
    Get file owner */
-DirectoryFunction(getOwner, FS_OWNER)
+FileInfoFunction(getOwner, FS_OWNER)
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::getGroup()
+/* {{{ proto int SplFileInfo::getGroup()
    Get file group */
-DirectoryFunction(getGroup, FS_GROUP)
+FileInfoFunction(getGroup, FS_GROUP)
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::getATime()
+/* {{{ proto int SplFileInfo::getATime()
    Get last access time of file */
-DirectoryFunction(getATime, FS_ATIME)
+FileInfoFunction(getATime, FS_ATIME)
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::getMTime()
+/* {{{ proto int SplFileInfo::getMTime()
    Get last modification time of file */
-DirectoryFunction(getMTime, FS_MTIME)
+FileInfoFunction(getMTime, FS_MTIME)
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::getCTime()
+/* {{{ proto int SplFileInfo::getCTime()
    Get inode modification time of file */
-DirectoryFunction(getCTime, FS_CTIME)
+FileInfoFunction(getCTime, FS_CTIME)
 /* }}} */
 
-/* {{{ proto string DirectoryIterator::getType()
+/* {{{ proto string SplFileInfo::getType()
    Get file type */
-DirectoryFunction(getType, FS_TYPE)
+FileInfoFunction(getType, FS_TYPE)
 /* }}} */
 
-/* {{{ proto bool DirectoryIterator::isWritable()
+/* {{{ proto bool SplFileInfo::isWritable()
    Returns true if file can be written */
-DirectoryFunction(isWritable, FS_IS_W)
+FileInfoFunction(isWritable, FS_IS_W)
 /* }}} */
 
-/* {{{ proto bool DirectoryIterator::isReadable()
+/* {{{ proto bool SplFileInfo::isReadable()
    Returns true if file can be read */
-DirectoryFunction(isReadable, FS_IS_R)
+FileInfoFunction(isReadable, FS_IS_R)
 /* }}} */
 
-/* {{{ proto bool DirectoryIterator::isExecutable()
+/* {{{ proto bool SplFileInfo::isExecutable()
    Returns true if file is executable */
-DirectoryFunction(isExecutable, FS_IS_X)
+FileInfoFunction(isExecutable, FS_IS_X)
 /* }}} */
 
-/* {{{ proto bool DirectoryIterator::isFile()
+/* {{{ proto bool SplFileInfo::isFile()
    Returns true if file is a regular file */
-DirectoryFunction(isFile, FS_IS_FILE)
+FileInfoFunction(isFile, FS_IS_FILE)
 /* }}} */
 
-/* {{{ proto bool DirectoryIterator::isDir()
+/* {{{ proto bool SplFileInfo::isDir()
    Returns true if file is directory */
-DirectoryFunction(isDir, FS_IS_DIR)
+FileInfoFunction(isDir, FS_IS_DIR)
 /* }}} */
 
-/* {{{ proto bool DirectoryIterator::isLink()
+/* {{{ proto bool SplFileInfo::isLink()
    Returns true if file is symbolic link */
-DirectoryFunction(isLink, FS_IS_LINK)
+FileInfoFunction(isLink, FS_IS_LINK)
 /* }}} */
 
-/* {{{ proto SplFileObject DirectoryIterator::openFile([string mode = 'r' [, bool use_include_path  [, resource context]]])
+/* {{{ proto SplFileObject SplFileInfo::openFile([string mode = 'r' [, bool use_include_path  [, resource context]]])
    Open the current file */
-SPL_METHOD(DirectoryIterator, openFile)
+SPL_METHOD(SplFileInfo, openFile)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *dir_obj = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
-       spl_file_object *intern;
-       zend_bool use_include_path = 0;
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       php_set_error_handling(EH_THROW, spl_ce_RuntimeException TSRMLS_CC);
+       spl_filesystem_object_create_type(ht, intern, SPL_FS_FILE, NULL, return_value TSRMLS_CC);
+}
 
-       if (!dir_obj->entry.d_name[0]) {
-               zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Could not open file");
-               zval_dtor(return_value);
+/* {{{ proto SplFileObject SplFileInfo::setFileClass([string class_name])
+   Class to use in openFile() */
+SPL_METHOD(SplFileInfo, setFileClass)
+{
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       zend_class_entry *ce = spl_ce_SplFileObject;
+       
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &ce) == FAILURE) {
                return;
        }
 
-       return_value->value.obj = spl_file_object_new_ex(spl_ce_SplFileObject, &intern TSRMLS_CC);
+       intern->file_class = ce;
+}
 
-       spl_dir_get_path_name(dir_obj);
-       intern->file_name = dir_obj->path_name;
-       intern->file_name_len = dir_obj->path_name_len;
+/* {{{ proto SplFileObject SplFileInfo::setInfoClass([string class_name])
+   Class to use in getFileInfo(), getPathInfo(), getSubPathInfo() */
+SPL_METHOD(SplFileInfo, setInfoClass)
+{
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       zend_class_entry *ce = spl_ce_SplFileInfo;
+       
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &ce) == FAILURE) {
+               return;
+       }
 
-       intern->open_mode = "r";
-       intern->open_mode_len = 1;
+       intern->file_class = ce;
+}
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sbr", 
-                       &intern->open_mode, &intern->open_mode_len, 
-                       &use_include_path, &intern->zcontext) == FAILURE) {
-               php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
-               zval_dtor(return_value);
+/* {{{ proto SplFileInfo SplFileInfo::getFileInfo([string $class_name])
+   Get/copy file info */
+SPL_METHOD(SplFileInfo, getFileInfo)
+{
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       zend_class_entry *ce = intern->info_class;
+       
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &ce) == FAILURE) {
                return;
        }
 
-       if (spl_file_object_open(intern, use_include_path, 0 TSRMLS_CC) == SUCCESS) {
-               Z_TYPE_P(return_value) = IS_OBJECT;
-       } else {
-               zval_dtor(return_value);
+       spl_filesystem_object_create_type(ht, intern, SPL_FS_INFO, ce, return_value TSRMLS_CC);
+}
+
+/* {{{ proto SplFileInfo SplFileInfo::getPathInfo([string $class_name])
+   Get/copy file info */
+SPL_METHOD(SplFileInfo, getPathInfo)
+{
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       zend_class_entry *ce = intern->info_class;
+       
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &ce) == FAILURE) {
                return;
        }
 
-       php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
-} /* }}} */
+       spl_filesystem_object_create_info(intern, intern->path, intern->path_len, 1, ce, return_value TSRMLS_CC);
+}
 
 /* {{{ proto void RecursiveDirectoryIterator::rewind()
    Rewind dir back to the start */
 SPL_METHOD(RecursiveDirectoryIterator, rewind)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       intern->index = 0;
-       if (intern->dirp) {
-               php_stream_rewinddir(intern->dirp);
+       intern->u.dir.index = 0;
+       if (intern->u.dir.dirp) {
+               php_stream_rewinddir(intern->u.dir.dirp);
        }
        do {
-               if (!intern->dirp || !php_stream_readdir(intern->dirp, &intern->entry)) {
-                       intern->entry.d_name[0] = '\0';
+               if (!intern->u.dir.dirp || !php_stream_readdir(intern->u.dir.dirp, &intern->u.dir.entry)) {
+                       intern->u.dir.entry.d_name[0] = '\0';
                }
-       } while (!strcmp(intern->entry.d_name, ".") || !strcmp(intern->entry.d_name, ".."));
+       } while (!strcmp(intern->u.dir.entry.d_name, ".") || !strcmp(intern->u.dir.entry.d_name, ".."));
 }
 /* }}} */
 
@@ -495,18 +777,17 @@ SPL_METHOD(RecursiveDirectoryIterator, rewind)
    Move to next entry */
 SPL_METHOD(RecursiveDirectoryIterator, next)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       intern->index++;
+       intern->u.dir.index++;
        do {
-               if (!intern->dirp || !php_stream_readdir(intern->dirp, &intern->entry)) {
-                       intern->entry.d_name[0] = '\0';
+               if (!intern->u.dir.dirp || !php_stream_readdir(intern->u.dir.dirp, &intern->u.dir.entry)) {
+                       intern->u.dir.entry.d_name[0] = '\0';
                }
-       } while (!strcmp(intern->entry.d_name, ".") || !strcmp(intern->entry.d_name, ".."));
-       if (intern->path_name) {
-               efree(intern->path_name);
-               intern->path_name = NULL;
+       } while (!strcmp(intern->u.dir.entry.d_name, ".") || !strcmp(intern->u.dir.entry.d_name, ".."));
+       if (intern->file_name) {
+               efree(intern->file_name);
+               intern->file_name = NULL;
        }
 }
 /* }}} */
@@ -516,23 +797,22 @@ SPL_METHOD(RecursiveDirectoryIterator, next)
 SPL_METHOD(RecursiveDirectoryIterator, hasChildren)
 {
        zend_bool allow_links = 0;
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        
-       if (!strcmp(intern->entry.d_name, ".") || !strcmp(intern->entry.d_name, "..")) {
+       if (!strcmp(intern->u.dir.entry.d_name, ".") || !strcmp(intern->u.dir.entry.d_name, "..")) {
                RETURN_BOOL(0);
        } else {
                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &allow_links) == FAILURE) {
                        return;
                }
-               spl_dir_get_path_name(intern);
+               spl_filesystem_object_get_file_name(intern TSRMLS_CC);
                if (!allow_links) {
-                       php_stat(intern->path_name, intern->path_name_len, FS_IS_LINK, return_value TSRMLS_CC);
+                       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);
                        }
                }
-               php_stat(intern->path_name, intern->path_name_len, FS_IS_DIR, return_value TSRMLS_CC);
+               php_stat(intern->file_name, intern->file_name_len, FS_IS_DIR, return_value TSRMLS_CC);
     }
 }
 /* }}} */
@@ -541,25 +821,26 @@ SPL_METHOD(RecursiveDirectoryIterator, hasChildren)
    Returns an iterator for the current entry if it is a directory */
 SPL_METHOD(RecursiveDirectoryIterator, getChildren)
 {
-       zval *object = getThis(), zpath;
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
-       spl_ce_dir_object *subdir;
+       zval zpath;
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *subdir;
        
-       spl_dir_get_path_name(intern);
+       spl_filesystem_object_get_file_name(intern TSRMLS_CC);
 
        INIT_PZVAL(&zpath);
-       ZVAL_STRINGL(&zpath, intern->path_name, intern->path_name_len, 0);
+       ZVAL_STRINGL(&zpath, intern->file_name, intern->file_name_len, 0);
 
        spl_instantiate_arg_ex1(spl_ce_RecursiveDirectoryIterator, &return_value, 0, &zpath TSRMLS_CC);
        
-       subdir = (spl_ce_dir_object*)zend_object_store_get_object(return_value TSRMLS_CC);
+       subdir = (spl_filesystem_object*)zend_object_store_get_object(return_value TSRMLS_CC);
        if (subdir) {
-               if (intern->sub_path && intern->sub_path[0]) {
-                       subdir->sub_path_len = spprintf(&subdir->sub_path, 0, "%s/%s", intern->sub_path, intern->entry.d_name);
+               if (intern->u.dir.sub_path && intern->u.dir.sub_path[0]) {
+                       subdir->u.dir.sub_path_len = spprintf(&subdir->u.dir.sub_path, 0, "%s/%s", intern->u.dir.sub_path, intern->u.dir.entry.d_name);
                } else {
-                       subdir->sub_path_len = strlen(intern->entry.d_name);
-                       subdir->sub_path = estrndup(intern->entry.d_name, subdir->sub_path_len);
+                       subdir->u.dir.sub_path_len = strlen(intern->u.dir.entry.d_name);
+                       subdir->u.dir.sub_path = estrndup(intern->u.dir.entry.d_name, subdir->u.dir.sub_path_len);
                }
+               subdir->flags = intern->flags;
        }
 }
 /* }}} */
@@ -568,11 +849,10 @@ SPL_METHOD(RecursiveDirectoryIterator, getChildren)
    Get sub path */
 SPL_METHOD(RecursiveDirectoryIterator, getSubPath)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       if (intern->sub_path) {
-               RETURN_STRINGL(intern->sub_path, intern->sub_path_len, 1);
+       if (intern->u.dir.sub_path) {
+               RETURN_STRINGL(intern->u.dir.sub_path, intern->u.dir.sub_path_len, 1);
        } else {
                RETURN_STRINGL("", 0, 1);
        }
@@ -583,16 +863,37 @@ SPL_METHOD(RecursiveDirectoryIterator, getSubPath)
    Get sub path and file name */
 SPL_METHOD(RecursiveDirectoryIterator, getSubPathname)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        char *sub_name;
        int len;
 
-       if (intern->sub_path) {
-               len = spprintf(&sub_name, 0, "%s/%s", intern->sub_path, intern->entry.d_name);
+       if (intern->u.dir.sub_path) {
+               len = spprintf(&sub_name, 0, "%s/%s", intern->u.dir.sub_path, intern->u.dir.entry.d_name);
                RETURN_STRINGL(sub_name, len, 0);
        } else {
-               RETURN_STRING(intern->entry.d_name, 1);
+               RETURN_STRING(intern->u.dir.entry.d_name, 1);
+       }
+}
+/* }}} */
+
+/* {{{ proto SplFileInfo RecursiveDirectoryIterator::getSubPathInfo([string $class_info])
+   Create SplFileInfo for sub path */
+SPL_METHOD(RecursiveDirectoryIterator, getSubPathInfo)
+{
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       char *sub_name;
+       int len;
+       zend_class_entry *ce = intern->info_class;
+       
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &ce) == FAILURE) {
+               return;
+       }
+
+       if (intern->u.dir.sub_path) {
+               len = spprintf(&sub_name, 0, "%s/%s", intern->u.dir.sub_path, intern->u.dir.entry.d_name);
+               spl_filesystem_object_create_info(intern, sub_name, len, 0, ce, return_value TSRMLS_CC);
+       } else {
+               spl_filesystem_object_create_info(intern, intern->path, intern->path_len, 1, ce, return_value TSRMLS_CC);
        }
 }
 /* }}} */
@@ -601,48 +902,47 @@ SPL_METHOD(RecursiveDirectoryIterator, getSubPathname)
 typedef struct {
        zend_object_iterator  intern;
        zval                  *current;
-       spl_ce_dir_object     *object;
-} spl_ce_dir_it;
+       spl_filesystem_object *object;
+} spl_filesystem_dir_it;
 
 /* forward declarations to the iterator handlers */
-static void spl_ce_dir_it_dtor(zend_object_iterator *iter TSRMLS_DC);
-static int spl_ce_dir_it_valid(zend_object_iterator *iter TSRMLS_DC);
-static void spl_ce_dir_it_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC);
-static int spl_ce_dir_it_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC);
-static void spl_ce_dir_it_move_forward(zend_object_iterator *iter TSRMLS_DC);
-static void spl_ce_dir_it_rewind(zend_object_iterator *iter TSRMLS_DC);
+static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter TSRMLS_DC);
+static int spl_filesystem_dir_it_valid(zend_object_iterator *iter TSRMLS_DC);
+static void spl_filesystem_dir_it_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC);
+static int spl_filesystem_dir_it_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC);
+static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter TSRMLS_DC);
+static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter TSRMLS_DC);
 
 /* iterator handler table */
-zend_object_iterator_funcs spl_ce_dir_it_funcs = {
-       spl_ce_dir_it_dtor,
-       spl_ce_dir_it_valid,
-       spl_ce_dir_it_current_data,
-       spl_ce_dir_it_current_key,
-       spl_ce_dir_it_move_forward,
-       spl_ce_dir_it_rewind
+zend_object_iterator_funcs spl_filesystem_dir_it_funcs = {
+       spl_filesystem_dir_it_dtor,
+       spl_filesystem_dir_it_valid,
+       spl_filesystem_dir_it_current_data,
+       spl_filesystem_dir_it_current_key,
+       spl_filesystem_dir_it_move_forward,
+       spl_filesystem_dir_it_rewind
 };
 
 /* {{{ spl_ce_dir_get_iterator */
-zend_object_iterator *spl_ce_dir_get_iterator(zend_class_entry *ce, zval *object TSRMLS_DC)
+zend_object_iterator *spl_filesystem_dir_get_iterator(zend_class_entry *ce, zval *object TSRMLS_DC)
 {
-       spl_ce_dir_it       *iterator   = emalloc(sizeof(spl_ce_dir_it));
-       spl_ce_dir_object   *dir_object = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_dir_it *iterator   = emalloc(sizeof(spl_filesystem_dir_it));
+       spl_filesystem_object *dir_object = (spl_filesystem_object*)zend_object_store_get_object(object TSRMLS_CC);
 
-       object->refcount++;
+       object->refcount += 2;;
        iterator->intern.data = (void*)object;
-       iterator->intern.funcs = &spl_ce_dir_it_funcs;
+       iterator->intern.funcs = &spl_filesystem_dir_it_funcs;
        iterator->current = object;
-       object->refcount++;
        iterator->object = dir_object;
        
        return (zend_object_iterator*)iterator;
 }
 /* }}} */
 
-/* {{{ spl_ce_dir_it_dtor */
-static void spl_ce_dir_it_dtor(zend_object_iterator *iter TSRMLS_DC)
+/* {{{ spl_filesystem_dir_it_dtor */
+static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter TSRMLS_DC)
 {
-       spl_ce_dir_it *iterator = (spl_ce_dir_it *)iter;
+       spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter;
 
        zval_ptr_dtor(&iterator->current);
        zval_ptr_dtor((zval**)&iterator->intern.data);
@@ -651,162 +951,218 @@ static void spl_ce_dir_it_dtor(zend_object_iterator *iter TSRMLS_DC)
 }
 /* }}} */
        
-/* {{{ spl_ce_dir_it_valid */
-static int spl_ce_dir_it_valid(zend_object_iterator *iter TSRMLS_DC)
+/* {{{ spl_filesystem_dir_it_valid */
+static int spl_filesystem_dir_it_valid(zend_object_iterator *iter TSRMLS_DC)
 {
-       spl_ce_dir_it       *iterator = (spl_ce_dir_it *)iter;
-       spl_ce_dir_object   *object   = iterator->object;
+       spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter;
+       spl_filesystem_object *object   = iterator->object;
 
-       return object->entry.d_name[0] != '\0' ? SUCCESS : FAILURE;
+       return object->u.dir.entry.d_name[0] != '\0' ? SUCCESS : FAILURE;
 }
 /* }}} */
 
 
-/* {{{ spl_ce_dir_it_current_data */
-static void spl_ce_dir_it_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC)
+/* {{{ spl_filesystem_dir_it_current_data */
+static void spl_filesystem_dir_it_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC)
 {
-       spl_ce_dir_it *iterator = (spl_ce_dir_it *)iter;
+       spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter;
        
        *data = &iterator->current;
 }
 /* }}} */
 
-/* {{{ spl_ce_dir_it_current_key */
-static int spl_ce_dir_it_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
+/* {{{ 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_ce_dir_it       *iterator = (spl_ce_dir_it *)iter;
-       spl_ce_dir_object   *object   = iterator->object;
+       spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter;
+       spl_filesystem_object *object   = iterator->object;
        
-       *int_key = object->index;
+       *int_key = object->u.dir.index;
        return HASH_KEY_IS_LONG;
 }
 /* }}} */
 
-/* {{{ spl_ce_dir_it_move_forward */
-static void spl_ce_dir_it_move_forward(zend_object_iterator *iter TSRMLS_DC)
+/* {{{ spl_filesystem_dir_it_move_forward */
+static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter TSRMLS_DC)
 {
-       spl_ce_dir_it       *iterator = (spl_ce_dir_it *)iter;
-       spl_ce_dir_object   *object   = iterator->object;
+       spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter;
+       spl_filesystem_object *object   = iterator->object;
        
-       object->index++;
-       if (!object->dirp || !php_stream_readdir(object->dirp, &object->entry)) {
-               object->entry.d_name[0] = '\0';
+       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';
        }
-       if (object->path_name) {
-               efree(object->path_name);
-               object->path_name = NULL;
+       if (object->file_name) {
+               efree(object->file_name);
+               object->file_name = NULL;
        }
 }
 /* }}} */
 
-/* {{{ spl_ce_dir_it_rewind */
-static void spl_ce_dir_it_rewind(zend_object_iterator *iter TSRMLS_DC)
+/* {{{ spl_filesystem_dir_it_rewind */
+static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter TSRMLS_DC)
 {
-       spl_ce_dir_it       *iterator = (spl_ce_dir_it *)iter;
-       spl_ce_dir_object   *object   = iterator->object;
+       spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter;
+       spl_filesystem_object *object   = iterator->object;
        
-       object->index = 0;
-       if (object->dirp) {
-               php_stream_rewinddir(object->dirp);
+       object->u.dir.index = 0;
+       if (object->u.dir.dirp) {
+               php_stream_rewinddir(object->u.dir.dirp);
        }
-       if (!object->dirp || !php_stream_readdir(object->dirp, &object->entry)) {
-               object->entry.d_name[0] = '\0';
+       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_ce_dir_tree_it_current_key */
-static int spl_ce_dir_tree_it_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
+/* {{{ spl_filesystem_tree_it_dtor */
+static void spl_filesystem_tree_it_dtor(zend_object_iterator *iter TSRMLS_DC)
 {
-       spl_ce_dir_it       *iterator = (spl_ce_dir_it *)iter;
-       spl_ce_dir_object   *object   = iterator->object;
+       spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter;
+
+       if (iterator->current) {
+               zval_ptr_dtor(&iterator->current);
+       }
+       zval_ptr_dtor((zval**)&iterator->intern.data);
+
+       efree(iterator);
+}
+/* }}} */
+       
+/* {{{ 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;
+
+       if (object->flags & SPL_FILE_DIR_CURRENT_AS_PATHNAME) {
+               if (!iterator->current) {
+                       ALLOC_INIT_ZVAL(iterator->current);
+                       spl_filesystem_object_get_file_name(object TSRMLS_CC);
+                       ZVAL_STRINGL(iterator->current, object->file_name, object->file_name_len, 1);
+               }
+               *data = &iterator->current;
+       } else if (object->flags & SPL_FILE_DIR_CURRENT_AS_FILEINFO) {
+               if (!iterator->current) {
+                       ALLOC_INIT_ZVAL(iterator->current);
+                       spl_filesystem_object_get_file_name(object TSRMLS_CC);
+                       spl_filesystem_object_create_type(0, object, SPL_FS_INFO, NULL, iterator->current TSRMLS_CC);
+               }
+               *data = &iterator->current;
+       } else {
+               *data = (zval**)&iterator->intern.data;
+       }
+}
+/* }}} */
+
+/* {{{ 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_dir_get_path_name(object);
-       *str_key_len = object->path_name_len + 1;
-       *str_key = estrndup(object->path_name, object->path_name_len);
+       if (object->flags & SPL_FILE_DIR_KEY_AS_FILENAME) {
+               *str_key_len = strlen(object->u.dir.entry.d_name) + 1;
+               *str_key = estrndup(object->u.dir.entry.d_name, *str_key_len - 1);
+       } else {
+               spl_filesystem_object_get_file_name(object TSRMLS_CC);
+               *str_key_len = object->file_name_len + 1;
+               *str_key = estrndup(object->file_name, object->file_name_len);
+       }
        return HASH_KEY_IS_STRING;
 }
 /* }}} */
 
-/* {{{ spl_ce_dir_tree_it_move_forward */
-static void spl_ce_dir_tree_it_move_forward(zend_object_iterator *iter TSRMLS_DC)
+/* {{{ spl_filesystem_tree_it_move_forward */
+static void spl_filesystem_tree_it_move_forward(zend_object_iterator *iter TSRMLS_DC)
 {
-       spl_ce_dir_it       *iterator = (spl_ce_dir_it *)iter;
-       spl_ce_dir_object   *object   = iterator->object;
+       spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter;
+       spl_filesystem_object *object   = iterator->object;
        
-       object->index++;
+       object->u.dir.index++;
        do {
-               if (!object->dirp || !php_stream_readdir(object->dirp, &object->entry)) {
-                       object->entry.d_name[0] = '\0';
+               if (!object->u.dir.dirp || !php_stream_readdir(object->u.dir.dirp, &object->u.dir.entry)) {
+                       object->u.dir.entry.d_name[0] = '\0';
                }
-       } while (!strcmp(object->entry.d_name, ".") || !strcmp(object->entry.d_name, ".."));
-       if (object->path_name) {
-               efree(object->path_name);
-               object->path_name = NULL;
+       } while (!strcmp(object->u.dir.entry.d_name, ".") || !strcmp(object->u.dir.entry.d_name, ".."));
+       if (object->file_name) {
+               efree(object->file_name);
+               object->file_name = NULL;
+       }
+       if (iterator->current) {
+               zval_ptr_dtor(&iterator->current);
+               iterator->current = NULL;
        }
 }
 /* }}} */
 
-/* {{{ spl_ce_dir_tree_it_rewind */
-static void spl_ce_dir_tree_it_rewind(zend_object_iterator *iter TSRMLS_DC)
+/* {{{ spl_filesystem_tree_it_rewind */
+static void spl_filesystem_tree_it_rewind(zend_object_iterator *iter TSRMLS_DC)
 {
-       spl_ce_dir_it       *iterator = (spl_ce_dir_it *)iter;
-       spl_ce_dir_object   *object   = iterator->object;
+       spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter;
+       spl_filesystem_object *object   = iterator->object;
        
-       object->index = 0;
-       if (object->dirp) {
-               php_stream_rewinddir(object->dirp);
+       object->u.dir.index = 0;
+       if (object->u.dir.dirp) {
+               php_stream_rewinddir(object->u.dir.dirp);
        }
        do {
-               if (!object->dirp || !php_stream_readdir(object->dirp, &object->entry)) {
-                       object->entry.d_name[0] = '\0';
+               if (!object->u.dir.dirp || !php_stream_readdir(object->u.dir.dirp, &object->u.dir.entry)) {
+                       object->u.dir.entry.d_name[0] = '\0';
                }
-       } while (!strcmp(object->entry.d_name, ".") || !strcmp(object->entry.d_name, ".."));
+       } while (!strcmp(object->u.dir.entry.d_name, ".") || !strcmp(object->u.dir.entry.d_name, ".."));
+       if (iterator->current) {
+               zval_ptr_dtor(&iterator->current);
+               iterator->current = NULL;
+       }
 }
 /* }}} */
 
 /* iterator handler table */
-zend_object_iterator_funcs spl_ce_dir_tree_it_funcs = {
-       spl_ce_dir_it_dtor,
-       spl_ce_dir_it_valid,
-       spl_ce_dir_it_current_data,
-       spl_ce_dir_tree_it_current_key,
-       spl_ce_dir_tree_it_move_forward,
-       spl_ce_dir_tree_it_rewind
+zend_object_iterator_funcs spl_filesystem_tree_it_funcs = {
+       spl_filesystem_tree_it_dtor,
+       spl_filesystem_dir_it_valid,
+       spl_filesystem_tree_it_current_data,
+       spl_filesystem_tree_it_current_key,
+       spl_filesystem_tree_it_move_forward,
+       spl_filesystem_tree_it_rewind
 };
 
 /* {{{ spl_ce_dir_get_iterator */
-zend_object_iterator *spl_ce_dir_tree_get_iterator(zend_class_entry *ce, zval *object TSRMLS_DC)
+zend_object_iterator *spl_filesystem_tree_get_iterator(zend_class_entry *ce, zval *object TSRMLS_DC)
 {
-       spl_ce_dir_it       *iterator   = emalloc(sizeof(spl_ce_dir_it));
-       spl_ce_dir_object   *dir_object = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_dir_it *iterator   = emalloc(sizeof(spl_filesystem_dir_it));
+       spl_filesystem_object *dir_object = (spl_filesystem_object*)zend_object_store_get_object(object TSRMLS_CC);
 
        object->refcount++;
        iterator->intern.data = (void*)object;
-       iterator->intern.funcs = &spl_ce_dir_tree_it_funcs;
-       iterator->current = object;
-       object->refcount++;
+       iterator->intern.funcs = &spl_filesystem_tree_it_funcs;
+       iterator->current = NULL;
        iterator->object = dir_object;
        
        return (zend_object_iterator*)iterator;
 }
 /* }}} */
 
-/* {{{ spl_ce_dir_cast */
-static int spl_ce_dir_cast(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_DC)
+/* {{{ spl_filesystem_object_cast */
+static int spl_filesystem_object_cast(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_DC)
 {
-       zval free_obj;
-       spl_ce_dir_object   *dir_object = (spl_ce_dir_object*)zend_object_store_get_object(readobj TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(readobj TSRMLS_CC);
 
-       if (type ==IS_STRING && *dir_object->entry.d_name) {
-               if (should_free) {
-                       free_obj = *writeobj;
-               }
-               ZVAL_STRING(writeobj, dir_object->entry.d_name, 1);
-               if (should_free) {
-                       zval_dtor(&free_obj);
+       if (should_free) {
+               zval_dtor(readobj);
+       }
+
+       if (type == IS_STRING) {
+               switch (intern->type) {
+               case SPL_FS_INFO:
+               case SPL_FS_FILE:
+                       ZVAL_STRINGL(writeobj, intern->file_name, intern->file_name_len, 1);
+                       return SUCCESS;
+               case SPL_FS_DIR:
+                       ZVAL_STRING(writeobj, intern->u.dir.entry.d_name, 1);
+                       return SUCCESS;
                }
-               return SUCCESS;
        }
        return FAILURE;
 }
@@ -815,146 +1171,107 @@ static int spl_ce_dir_cast(zval *readobj, zval *writeobj, int type, int should_f
 /* declare method parameters */
 /* supply a name and default to call by parameter */
 static
-ZEND_BEGIN_ARG_INFO(arginfo_dir___construct, 0) 
-       ZEND_ARG_INFO(0, path)  /* parameter name */
+ZEND_BEGIN_ARG_INFO(arginfo_info___construct, 0) 
+       ZEND_ARG_INFO(0, file_name)
 ZEND_END_ARG_INFO();
 
 static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_dir_openFile, 0, 0, 0)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_info_openFile, 0, 0, 0)
        ZEND_ARG_INFO(0, open_mode)
        ZEND_ARG_INFO(0, use_include_path)
        ZEND_ARG_INFO(0, context)
 ZEND_END_ARG_INFO();
 
+static
+ZEND_BEGIN_ARG_INFO_EX(arginfo_info_optinalFileClass, 0, 0, 0)
+       ZEND_ARG_INFO(0, class_name)
+ZEND_END_ARG_INFO();
+
 /* the method table */
 /* each method can have its own parameters and visibility */
-static zend_function_entry spl_ce_dir_class_functions[] = {
+static zend_function_entry spl_SplFileInfo_functions[] = {
+       SPL_ME(SplFileInfo,       __construct,   arginfo_info___construct, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getPath,       NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getFilename,   NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getPathname,   NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getPerms,      NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getInode,      NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getSize,       NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getOwner,      NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getGroup,      NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getATime,      NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getMTime,      NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getCTime,      NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getType,       NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       isWritable,    NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       isReadable,    NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       isExecutable,  NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       isFile,        NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       isDir,         NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       isLink,        NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getFileInfo,   arginfo_info_optinalFileClass, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getPathInfo,   arginfo_info_optinalFileClass, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       openFile,      arginfo_info_openFile,         ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       setFileClass,  arginfo_info_optinalFileClass, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       setInfoClass,  arginfo_info_optinalFileClass, ZEND_ACC_PUBLIC)
+       SPL_MA(SplFileInfo,       __toString, SplFileInfo, getPathname, NULL, ZEND_ACC_PUBLIC)
+       {NULL, NULL, NULL}
+};
+
+static
+ZEND_BEGIN_ARG_INFO(arginfo_dir___construct, 0) 
+       ZEND_ARG_INFO(0, path)
+ZEND_END_ARG_INFO();
+
+/* the method table */
+/* each method can have its own parameters and visibility */
+static zend_function_entry spl_DirectoryIterator_functions[] = {
        SPL_ME(DirectoryIterator, __construct,   arginfo_dir___construct, ZEND_ACC_PUBLIC)
+       SPL_ME(DirectoryIterator, getFilename,   NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(DirectoryIterator, isDot,         NULL, ZEND_ACC_PUBLIC)
        SPL_ME(DirectoryIterator, rewind,        NULL, ZEND_ACC_PUBLIC)
        SPL_ME(DirectoryIterator, valid,         NULL, ZEND_ACC_PUBLIC)
        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, getPath,       NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, getFilename,   NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, getPathname,   NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, getPerms,      NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, getInode,      NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, getSize,       NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, getOwner,      NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, getGroup,      NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, getATime,      NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, getMTime,      NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, getCTime,      NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, getType,       NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, isWritable,    NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, isReadable,    NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, isExecutable,  NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, isFile,        NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, isDir,         NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, isLink,        NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, isDot,         NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, openFile,      arginfo_dir_openFile, ZEND_ACC_PUBLIC)
        SPL_MA(DirectoryIterator, __toString, DirectoryIterator, getFilename, NULL, ZEND_ACC_PUBLIC)
        {NULL, NULL, NULL}
 };
 
-static zend_function_entry spl_ce_dir_tree_class_functions[] = {
+static zend_function_entry spl_RecursiveDirectoryIterator_functions[] = {
        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,   NULL, ZEND_ACC_PUBLIC)
        SPL_ME(RecursiveDirectoryIterator, getChildren,   NULL, ZEND_ACC_PUBLIC)
        SPL_ME(RecursiveDirectoryIterator, getSubPath,    NULL, ZEND_ACC_PUBLIC)
        SPL_ME(RecursiveDirectoryIterator, getSubPathname,NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(RecursiveDirectoryIterator, getSubPathInfo,arginfo_info_optinalFileClass, ZEND_ACC_PUBLIC)
        {NULL, NULL, NULL}
 };
 
-static void spl_file_object_free_line(spl_file_object *intern TSRMLS_DC) /* {{{ */
-{
-       if (intern->current_line) {
-               efree(intern->current_line);
-               intern->current_line = NULL;
-       }
-       if (intern->current_zval) {
-               zval_ptr_dtor(&intern->current_zval);
-               intern->current_zval = NULL;
-       }
-} /* }}} */
-
-static void spl_file_object_free_storage(void *object TSRMLS_DC) /* {{{ */
-{
-       spl_file_object *intern = (spl_file_object*)object;
-
-       zend_hash_destroy(intern->std.properties);
-       FREE_HASHTABLE(intern->std.properties);
-
-       if (intern->stream) {
-               if (intern->zcontext) {
-/*                     zend_list_delref(Z_RESVAL_P(intern->zcontext));*/
-               }
-               if (!intern->stream->is_persistent) {
-                       php_stream_free(intern->stream, PHP_STREAM_FREE_CLOSE);
-               } else {
-                       php_stream_free(intern->stream, PHP_STREAM_FREE_CLOSE_PERSISTENT);
-               }
-               if (intern->file_name) {
-                       efree(intern->file_name);
-               }
-               if (intern->open_mode) {
-                       efree(intern->open_mode);
-               }
-       }
-       spl_file_object_free_line(intern TSRMLS_CC);
-       efree(object);
-} /* }}} */
-
-static zend_object_value spl_file_object_new_ex(zend_class_entry *class_type, spl_file_object **obj TSRMLS_DC) /* {{{ */
-{
-       zend_object_value retval;
-       spl_file_object *intern;
-       zval *tmp;
-
-       intern = emalloc(sizeof(spl_ce_dir_object));
-       memset(intern, 0, sizeof(spl_ce_dir_object));
-       intern->std.ce = class_type;
-       if (obj) *obj = intern;
-
-       ALLOC_HASHTABLE(intern->std.properties);
-       zend_hash_init(intern->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
-       zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
-
-       retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_file_object_free_storage, NULL TSRMLS_CC);
-       retval.handlers = &spl_ce_dir_handlers;
-       return retval;
-} /* }}} */
-
-static zend_object_value spl_file_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
-{
-       return spl_file_object_new_ex(class_type, NULL TSRMLS_CC);
-} /* }}} */
-
-static int spl_file_object_read(spl_file_object *intern, int silent TSRMLS_DC) /* {{{ */
+static int spl_filesystem_file_read(spl_filesystem_object *intern, int silent TSRMLS_DC) /* {{{ */
 {
        char *buf;
        size_t line_len;
        int len;
-       long line_add = (intern->current_line || intern->current_zval) ? 1 : 0;
+       long line_add = (intern->u.file.current_line || intern->u.file.current_zval) ? 1 : 0;
 
-       spl_file_object_free_line(intern TSRMLS_CC);
+       spl_filesystem_file_free_line(intern TSRMLS_CC);
        
-       if (php_stream_eof(intern->stream)) {
+       if (php_stream_eof(intern->u.file.stream)) {
                if (!silent) {
                        zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot read from file %s", intern->file_name);
                }
                return FAILURE;
        }
 
-       buf = php_stream_get_line(intern->stream, NULL, intern->max_line_len, &line_len);
+       buf = php_stream_get_line(intern->u.file.stream, NULL, intern->u.file.max_line_len, &line_len);
 
        if (!buf) {
-               intern->current_line = estrdup("");
-               intern->current_line_len = 0;
+               intern->u.file.current_line = estrdup("");
+               intern->u.file.current_line_len = 0;
        } else {
                if (intern->flags & SPL_FILE_OBJECT_DROP_NEW_LINE) {
                        line_len = strcspn(buf, "\r\n");
@@ -966,38 +1283,38 @@ static int spl_file_object_read(spl_file_object *intern, int silent TSRMLS_DC) /
                        line_len = len;
                }
        
-               intern->current_line = buf;
-               intern->current_line_len = line_len;
+               intern->u.file.current_line = buf;
+               intern->u.file.current_line_len = line_len;
        }
-       intern->current_line_num += line_add;
+       intern->u.file.current_line_num += line_add;
 
        return SUCCESS;
 } /* }}} */
 
-static int spl_file_object_read_line(zval * this_ptr, spl_file_object *intern, int silent TSRMLS_DC) /* {{{ */
+static int spl_filesystem_file_read_line(zval * this_ptr, spl_filesystem_object *intern, int silent TSRMLS_DC) /* {{{ */
 {
        zval *retval;
 
        /* if overloaded call the function, otherwise do it directly */
-       if (intern->func_getCurr->common.scope != spl_ce_SplFileObject) {
-               if (php_stream_eof(intern->stream)) {
+       if (intern->u.file.func_getCurr->common.scope != spl_ce_SplFileObject) {
+               if (php_stream_eof(intern->u.file.stream)) {
                        if (!silent) {
                                zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot read from file %s", intern->file_name);
                        }
                        return FAILURE;
                }
-               zend_call_method_with_0_params(&getThis(), Z_OBJCE_P(getThis()), &intern->func_getCurr, "getCurrentLine", &retval);
+               zend_call_method_with_0_params(&getThis(), Z_OBJCE_P(getThis()), &intern->u.file.func_getCurr, "getCurrentLine", &retval);
                if (retval) {
-                       if (intern->current_line || intern->current_zval) {
-                               intern->current_line_num++;
+                       if (intern->u.file.current_line || intern->u.file.current_zval) {
+                               intern->u.file.current_line_num++;
                        }
-                       spl_file_object_free_line(intern TSRMLS_CC);
+                       spl_filesystem_file_free_line(intern TSRMLS_CC);
                        if (Z_TYPE_P(retval) == IS_STRING) {
-                               intern->current_line = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
-                               intern->current_line_len = Z_STRLEN_P(retval);
+                               intern->u.file.current_line = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
+                               intern->u.file.current_line_len = Z_STRLEN_P(retval);
                        } else {
-                               MAKE_STD_ZVAL(intern->current_zval);
-                               ZVAL_ZVAL(intern->current_zval, retval, 1, 0);
+                               MAKE_STD_ZVAL(intern->u.file.current_zval);
+                               ZVAL_ZVAL(intern->u.file.current_zval, retval, 1, 0);
                        }
                        zval_ptr_dtor(&retval);
                        return SUCCESS;
@@ -1005,69 +1322,88 @@ static int spl_file_object_read_line(zval * this_ptr, spl_file_object *intern, i
                        return FAILURE;
                }
        } else {
-               return spl_file_object_read(intern, silent TSRMLS_CC);
+               return spl_filesystem_file_read(intern, silent TSRMLS_CC);
        }
 } /* }}} */
 
-static void spl_file_object_rewind(spl_file_object *intern TSRMLS_DC) /* {{{ */
+static void spl_filesystem_file_rewind(spl_filesystem_object *intern TSRMLS_DC) /* {{{ */
 {
-       if (-1 == php_stream_rewind(intern->stream)) {
+       if (-1 == php_stream_rewind(intern->u.file.stream)) {
                zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot rewind file %s", intern->file_name);
        } else {
-               spl_file_object_free_line(intern TSRMLS_CC);
-               intern->current_line_num = 0;
+               spl_filesystem_file_free_line(intern TSRMLS_CC);
+               intern->u.file.current_line_num = 0;
        }
 } /* }}} */
 
-static int spl_file_object_open(spl_file_object *intern, int use_include_path, int silent TSRMLS_DC) /* {{{ */
+/* {{{ proto void SplFileObject::__construct(string filename [, string mode = 'r' [, bool use_include_path  [, resource context]]]])
+   Construct a new file object */
+SPL_METHOD(SplFileObject, __construct)
 {
-       intern->context = php_stream_context_from_zval(intern->zcontext, 0);
-       intern->stream = php_stream_open_wrapper_ex(intern->file_name, intern->open_mode, (use_include_path ? USE_PATH : 0) | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, intern->context);
-
-       if (intern->stream == NULL) {
-               if (!EG(exception)) {
-                       zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot open file %s", intern->file_name);
-               }
-               return FAILURE;
-       }
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       zend_bool use_include_path = 0;
+       char *p1, *p2;
 
-       if (intern->zcontext) {
-               zend_list_addref(Z_RESVAL_P(intern->zcontext));
-       }
+       php_set_error_handling(EH_THROW, spl_ce_RuntimeException TSRMLS_CC);
 
-       intern->file_name = estrndup(intern->file_name, intern->file_name_len);
-       intern->open_mode = estrndup(intern->open_mode, intern->open_mode_len);
+       intern->u.file.open_mode = "r";
+       intern->u.file.open_mode_len = 1;
 
-       /* avoid reference counting in debug mode, thus do it manually */
-       ZVAL_RESOURCE(&intern->zresource, php_stream_get_resource_id(intern->stream));
-       intern->zresource.refcount = 1;
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sbr", 
+                       &intern->file_name, &intern->file_name_len,
+                       &intern->u.file.open_mode, &intern->u.file.open_mode_len, 
+                       &use_include_path, &intern->u.file.zcontext) == FAILURE) {
+               php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
+               return;
+       }
+       
+       spl_filesystem_file_open(intern, use_include_path, 0 TSRMLS_CC);
 
-       zend_hash_find(&intern->std.ce->function_table, "getcurrentline", sizeof("getcurrentline"), (void **) &intern->func_getCurr);
+       p1 = strrchr(intern->file_name, '/');
+       p2 = strrchr(intern->file_name, '\\');
+       if (p1 || p2) {
+               intern->path_len = (p1 > p2 ? p1 : p2) - intern->file_name;
+       } else {
+               intern->path_len = 0;
+       }
+       intern->path = estrndup(intern->file_name, intern->path_len);
 
-       return SUCCESS;
+       php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
 } /* }}} */
 
-/* {{{ proto void SplFileObject::__construct(string filename [, string mode = 'r' [, bool use_include_path  [, resource context]]]])
-   Construct a new file reader */
-SPL_METHOD(SplFileObject, __construct)
+/* {{{ proto void SplFileObject::__construct([int max_memory])
+   Construct a new temp file object */
+SPL_METHOD(SplTempFileObject, __construct)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
-       zend_bool use_include_path = 0;
+       long max_memory = PHP_STREAM_MAX_MEM;
+       char tmp_fname[48];
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
        php_set_error_handling(EH_THROW, spl_ce_RuntimeException TSRMLS_CC);
 
-       intern->open_mode = "r";
-       intern->open_mode_len = 1;
-
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sbr", 
-                       &intern->file_name, &intern->file_name_len,
-                       &intern->open_mode, &intern->open_mode_len, 
-                       &use_include_path, &intern->zcontext) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &max_memory) == FAILURE) {
                php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
                return;
        }
+
+       if (max_memory < 0) {
+               intern->file_name = "php://memory";
+               intern->file_name_len = 12;
+       } else if (ZEND_NUM_ARGS()) {
+               intern->file_name_len = snprintf(tmp_fname, sizeof(tmp_fname), "php://temp/maxmemory:%ld", max_memory);
+               intern->file_name = tmp_fname;
+       } else {
+               intern->file_name = "php://temp";
+               intern->file_name_len = 10;
+       }
+       intern->u.file.open_mode = "wb";
+       intern->u.file.open_mode_len = 1;
+       intern->u.file.zcontext = NULL;
        
-       spl_file_object_open(intern, use_include_path, 0 TSRMLS_CC);
+       spl_filesystem_file_open(intern, 0, 0 TSRMLS_CC);
+
+       intern->path_len = 0;
+       intern->path = estrndup("", 0);
 
        php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
 } /* }}} */
@@ -1076,16 +1412,16 @@ SPL_METHOD(SplFileObject, __construct)
    Rewind the file and read the first line */
 SPL_METHOD(SplFileObject, rewind)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       spl_file_object_rewind(intern TSRMLS_CC);
+       spl_filesystem_file_rewind(intern TSRMLS_CC);
 } /* }}} */
 
 /* {{{ proto string SplFileObject::getFilename()
    Return the filename */
 SPL_METHOD(SplFileObject, getFilename)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
        RETURN_STRINGL(intern->file_name, intern->file_name_len, 1);    
 } /* }}} */
@@ -1094,45 +1430,45 @@ SPL_METHOD(SplFileObject, getFilename)
    Return whether end of file is reached */
 SPL_METHOD(SplFileObject, eof)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       RETURN_BOOL(php_stream_eof(intern->stream));
+       RETURN_BOOL(php_stream_eof(intern->u.file.stream));
 } /* }}} */
 
 /* {{{ proto void SplFileObject::valid()
    Return !eof() */
 SPL_METHOD(SplFileObject, valid)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       RETVAL_BOOL(!php_stream_eof(intern->stream));
+       RETVAL_BOOL(!php_stream_eof(intern->u.file.stream));
 } /* }}} */
 
 /* {{{ proto string SplFileObject::fgets()
    Rturn next line from file */
 SPL_METHOD(SplFileObject, fgets)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       if (spl_file_object_read(intern, 0 TSRMLS_CC) == FAILURE) {
+       if (spl_filesystem_file_read(intern, 0 TSRMLS_CC) == FAILURE) {
                RETURN_FALSE;
        }
-       RETURN_STRINGL(intern->current_line, intern->current_line_len, 1);
+       RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len, 1);
 } /* }}} */
 
 /* {{{ proto string SplFileObject::current()
    Return current line from file */
 SPL_METHOD(SplFileObject, current)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       if (!intern->current_line) {
-               spl_file_object_read_line(getThis(), intern, 1 TSRMLS_CC);
+       if (!intern->u.file.current_line) {
+               spl_filesystem_file_read_line(getThis(), intern, 1 TSRMLS_CC);
        }
-       if (intern->current_line) {
-               RETURN_STRINGL(intern->current_line, intern->current_line_len, 1);
-       } else if (intern->current_zval) {
-               RETURN_ZVAL(intern->current_zval, 1, 0);
+       if (intern->u.file.current_line) {
+               RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len, 1);
+       } else if (intern->u.file.current_zval) {
+               RETURN_ZVAL(intern->u.file.current_zval, 1, 0);
        }
        RETURN_FALSE;
 } /* }}} */
@@ -1141,30 +1477,30 @@ SPL_METHOD(SplFileObject, current)
    Return line number */
 SPL_METHOD(SplFileObject, key)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
 /*     Do not read the next line to support correct counting with fgetc()
        if (!intern->current_line) {
-               spl_file_object_read_line(getThis(), intern, 1 TSRMLS_CC);
+               spl_filesystem_file_read_line(getThis(), intern, 1 TSRMLS_CC);
        } */
-       RETURN_LONG(intern->current_line_num);
+       RETURN_LONG(intern->u.file.current_line_num);
 } /* }}} */
 
 /* {{{ proto void SplFileObject::next()
    Read next line */
 SPL_METHOD(SplFileObject, next)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       spl_file_object_free_line(intern TSRMLS_CC);
-       intern->current_line_num++;
+       spl_filesystem_file_free_line(intern TSRMLS_CC);
+       intern->u.file.current_line_num++;
 } /* }}} */
 
 /* {{{ proto void SplFileObject::setFlags(int flags)
    Set file handling flags */
 SPL_METHOD(SplFileObject, setFlags)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
        zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &intern->flags);
 } /* }}} */
@@ -1173,7 +1509,7 @@ SPL_METHOD(SplFileObject, setFlags)
    Get file handling flags */
 SPL_METHOD(SplFileObject, getFlags)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
        RETURN_LONG(intern->flags);
 } /* }}} */
@@ -1184,7 +1520,7 @@ SPL_METHOD(SplFileObject, setMaxLineLen)
 {
        long max_len;
 
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &max_len) == FAILURE) {
                return;
@@ -1195,19 +1531,19 @@ SPL_METHOD(SplFileObject, setMaxLineLen)
                return;
        }
        
-       intern->max_line_len = max_len;
+       intern->u.file.max_line_len = max_len;
 } /* }}} */
 
 /* {{{ proto int SplFileObject::getMaxLineLen()
    Get maximum line length */
 SPL_METHOD(SplFileObject, getMaxLineLen)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       RETURN_LONG((long)intern->max_line_len);
+       RETURN_LONG((long)intern->u.file.max_line_len);
 } /* }}} */
 
-/* {{{ proto bool hasChildren()
+/* {{{ proto bool SplFileObject>>hasChildren()
    Rturn false */
 SPL_METHOD(SplFileObject, hasChildren)
 {
@@ -1221,12 +1557,12 @@ SPL_METHOD(SplFileObject, getChildren)
        /* return NULL */
 } /* }}} */
 
-static int spl_file_object_call(INTERNAL_FUNCTION_PARAMETERS, spl_file_object *intern, zend_function *func_ptr, zval *arg2) /* {{{ */
+static int spl_filesystem_file_call(INTERNAL_FUNCTION_PARAMETERS, spl_filesystem_object *intern, zend_function *func_ptr, zval *arg2) /* {{{ */
 {
        zend_fcall_info fci;
        zend_fcall_info_cache fcic;
        zval z_fname;
-       zval * zresource_ptr = &intern->zresource, *retval;
+       zval * zresource_ptr = &intern->u.file.zresource, *retval;
        int result;
 
        zval ***params = (zval***)safe_emalloc(ZEND_NUM_ARGS(), sizeof(zval**), (arg2 ? 2 : 1) * sizeof(zval**));
@@ -1268,14 +1604,14 @@ static int spl_file_object_call(INTERNAL_FUNCTION_PARAMETERS, spl_file_object *i
 { \
        zend_function *func_ptr; \
        zend_hash_find(EG(function_table), #func_name, sizeof(#func_name), (void **) &func_ptr); \
-       spl_file_object_call(INTERNAL_FUNCTION_PARAM_PASSTHRU, intern, func_ptr, arg2); \
+       spl_filesystem_file_call(INTERNAL_FUNCTION_PARAM_PASSTHRU, intern, func_ptr, arg2); \
 }
 
 /* {{{ FileFunction */
 #define FileFunction(func_name) \
 SPL_METHOD(SplFileObject, func_name) \
 { \
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC); \
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); \
        FileFunctionCall(func_name, NULL); \
 }
 /* }}} */
@@ -1284,13 +1620,13 @@ SPL_METHOD(SplFileObject, func_name) \
    Return current line as csv */
 SPL_METHOD(SplFileObject, fgetcsv)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        zval *arg2 = NULL;
        MAKE_STD_ZVAL(arg2);
-       ZVAL_LONG(arg2, intern->max_line_len);
+       ZVAL_LONG(arg2, intern->u.file.max_line_len);
 
-       spl_file_object_free_line(intern TSRMLS_CC);
-       intern->current_line_num++;
+       spl_filesystem_file_free_line(intern TSRMLS_CC);
+       intern->u.file.current_line_num++;
 
        FileFunctionCall(fgetcsv, arg2);
 
@@ -1307,9 +1643,9 @@ FileFunction(flock)
    Flush the file */
 SPL_METHOD(SplFileObject, fflush)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       RETURN_BOOL(!php_stream_flush(intern->stream));
+       RETURN_BOOL(!php_stream_flush(intern->u.file.stream));
 } /* }}} */
 
 
@@ -1317,8 +1653,8 @@ SPL_METHOD(SplFileObject, fflush)
    Return current file position */
 SPL_METHOD(SplFileObject, ftell)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);  
-       long ret = php_stream_tell(intern->stream);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);      
+       long ret = php_stream_tell(intern->u.file.stream);
 
        if (ret == -1) {
                RETURN_FALSE;
@@ -1331,34 +1667,34 @@ SPL_METHOD(SplFileObject, ftell)
    Return current file position */
 SPL_METHOD(SplFileObject, fseek)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        long pos, whence = SEEK_SET;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &pos, &whence) == FAILURE) {
                return;
        }
 
-       spl_file_object_free_line(intern TSRMLS_CC);
-       RETURN_LONG(php_stream_seek(intern->stream, pos, whence));
+       spl_filesystem_file_free_line(intern TSRMLS_CC);
+       RETURN_LONG(php_stream_seek(intern->u.file.stream, pos, whence));
 } /* }}} */
 
 /* {{{ proto int SplFileObject::fgetc()
    Get a character form the file */
 SPL_METHOD(SplFileObject, fgetc)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        char buf[2];
        int result;
 
-       spl_file_object_free_line(intern TSRMLS_CC);
+       spl_filesystem_file_free_line(intern TSRMLS_CC);
 
-       result = php_stream_getc(intern->stream);
+       result = php_stream_getc(intern->u.file.stream);
 
        if (result == EOF) {
                RETVAL_FALSE;
        } else {
                if (result == '\n') {
-                       intern->current_line_num++;
+                       intern->u.file.current_line_num++;
                }
                buf[0] = result;
                buf[1] = '\0';
@@ -1371,13 +1707,13 @@ SPL_METHOD(SplFileObject, fgetc)
    Get a line from file pointer and strip HTML tags */
 SPL_METHOD(SplFileObject, fgetss)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        zval *arg2 = NULL;
        MAKE_STD_ZVAL(arg2);
-       ZVAL_LONG(arg2, intern->max_line_len);
+       ZVAL_LONG(arg2, intern->u.file.max_line_len);
 
-       spl_file_object_free_line(intern TSRMLS_CC);
-       intern->current_line_num++;
+       spl_filesystem_file_free_line(intern TSRMLS_CC);
+       intern->u.file.current_line_num++;
 
        FileFunctionCall(fgetss, arg2);
 
@@ -1388,19 +1724,19 @@ SPL_METHOD(SplFileObject, fgetss)
    Output all remaining data from a file pointer */
 SPL_METHOD(SplFileObject, fpassthru)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       RETURN_LONG(php_stream_passthru(intern->stream));
+       RETURN_LONG(php_stream_passthru(intern->u.file.stream));
 } /* }}} */
 
 /* {{{ proto bool SplFileObject::fscanf(string format [, string ...])
    Implements a mostly ANSI compatible fscanf() */
 SPL_METHOD(SplFileObject, fscanf)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       spl_file_object_free_line(intern TSRMLS_CC);
-       intern->current_line_num++;
+       spl_filesystem_file_free_line(intern TSRMLS_CC);
+       intern->u.file.current_line_num++;
 
        FileFunctionCall(fscanf, NULL);
 }
@@ -1410,7 +1746,7 @@ SPL_METHOD(SplFileObject, fscanf)
    Binary-safe file write */
 SPL_METHOD(SplFileObject, fwrite)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        char *str;
        int str_len;
        int ret;
@@ -1430,12 +1766,12 @@ SPL_METHOD(SplFileObject, fwrite)
        if (PG(magic_quotes_runtime)) {
                str = estrndup(str, str_len);
                php_stripslashes(str, &str_len TSRMLS_CC);
-               ret = php_stream_write(intern->stream, str, str_len);
+               ret = php_stream_write(intern->u.file.stream, str, str_len);
                efree(str);
                RETURN_LONG(ret);
        }
 
-       RETURN_LONG(php_stream_write(intern->stream, str, str_len));
+       RETURN_LONG(php_stream_write(intern->u.file.stream, str, str_len));
 } /* }}} */
 
 /* {{{ proto bool SplFileObject::fstat()
@@ -1447,26 +1783,26 @@ FileFunction(fstat)
    Truncate file to 'size' length */
 SPL_METHOD(SplFileObject, ftruncate)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        long size;
        
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &size) == FAILURE) {
                return;
        }
 
-       if (!php_stream_truncate_supported(intern->stream)) {
+       if (!php_stream_truncate_supported(intern->u.file.stream)) {
                zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Can't truncate file %s", intern->file_name);
                RETURN_FALSE;
        }
        
-       RETURN_BOOL(0 == php_stream_truncate_set_size(intern->stream, size));
+       RETURN_BOOL(0 == php_stream_truncate_set_size(intern->u.file.stream, size));
 } /* }}} */
 
 /* {{{ proto void SplFileObject::seek(int line_pos)
    Seek to specified line */
 SPL_METHOD(SplFileObject, seek)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        long line_pos;
        
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &line_pos) == FAILURE) {
@@ -1477,13 +1813,12 @@ SPL_METHOD(SplFileObject, seek)
                RETURN_FALSE;           
        }
        
-       spl_file_object_rewind(intern TSRMLS_CC);
+       spl_filesystem_file_rewind(intern TSRMLS_CC);
        
-       while(intern->current_line_num < line_pos) {
-               spl_file_object_read_line(getThis(), intern, 1 TSRMLS_CC);
+       while(intern->u.file.current_line_num < line_pos) {
+               spl_filesystem_file_read_line(getThis(), intern, 1 TSRMLS_CC);
        }
-}
-/* }}} */
+} /* }}} */
 
 /* {{{ Function/Class/Method definitions */
 static
@@ -1548,7 +1883,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_seek, 0, 0, 1)
        ZEND_ARG_INFO(0, line_pos)
 ZEND_END_ARG_INFO();
 
-static zend_function_entry spl_file_object_class_functions[] = {
+static zend_function_entry spl_SplFileObject_functions[] = {
        SPL_ME(SplFileObject, __construct,    arginfo_file_object___construct,   ZEND_ACC_PUBLIC)
        SPL_ME(SplFileObject, getFilename,    NULL, ZEND_ACC_PUBLIC)
        SPL_ME(SplFileObject, rewind,         NULL, ZEND_ACC_PUBLIC)
@@ -1582,29 +1917,52 @@ static zend_function_entry spl_file_object_class_functions[] = {
        SPL_MA(SplFileObject, __toString,     SplFileObject, current,    NULL, ZEND_ACC_PUBLIC)
        {NULL, NULL, NULL}
 };
+
+static
+ZEND_BEGIN_ARG_INFO_EX(arginfo_temp_file_object___construct, 0, 0, 1)
+       ZEND_ARG_INFO(0, max_memory)
+ZEND_END_ARG_INFO();
+
+static zend_function_entry spl_SplTempFileObject_functions[] = {
+       SPL_ME(SplTempFileObject, __construct, arginfo_temp_file_object___construct,  ZEND_ACC_PUBLIC)
+       {NULL, NULL, NULL}
+};
 /* }}} */
 
 /* {{{ PHP_MINIT_FUNCTION(spl_directory)
  */
 PHP_MINIT_FUNCTION(spl_directory)
 {
-       REGISTER_SPL_STD_CLASS_EX(DirectoryIterator, spl_ce_dir_object_new, spl_ce_dir_class_functions);
+       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;
+
+       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);
-       memcpy(&spl_ce_dir_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
-       spl_ce_dir_handlers.clone_obj = spl_ce_dir_object_clone;
-       spl_ce_dir_handlers.cast_object = spl_ce_dir_cast;
 
-       spl_ce_DirectoryIterator->get_iterator = spl_ce_dir_get_iterator;
+       spl_ce_DirectoryIterator->get_iterator = spl_filesystem_dir_get_iterator;
 
-       REGISTER_SPL_SUB_CLASS_EX(RecursiveDirectoryIterator, DirectoryIterator, spl_ce_dir_object_new, spl_ce_dir_tree_class_functions);
+       REGISTER_SPL_SUB_CLASS_EX(RecursiveDirectoryIterator, DirectoryIterator, spl_filesystem_object_new, spl_RecursiveDirectoryIterator_functions);
        REGISTER_SPL_IMPLEMENTS(RecursiveDirectoryIterator, RecursiveIterator);
 
-       spl_ce_RecursiveDirectoryIterator->get_iterator = spl_ce_dir_tree_get_iterator;
+       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_STD_CLASS_EX(SplFileObject, spl_file_object_new, spl_file_object_class_functions);
+       spl_ce_RecursiveDirectoryIterator->get_iterator = spl_filesystem_tree_get_iterator;
+
+       REGISTER_SPL_SUB_CLASS_EX(SplFileObject, SplFileInfo, spl_filesystem_object_new, spl_SplFileObject_functions);
        REGISTER_SPL_IMPLEMENTS(SplFileObject, RecursiveIterator);
        REGISTER_SPL_IMPLEMENTS(SplFileObject, SeekableIterator);
 
+       REGISTER_SPL_SUB_CLASS_EX(SplTempFileObject, SplFileObject, spl_filesystem_object_new, spl_SplTempFileObject_functions);
+
        REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "DROP_NEW_LINE", SPL_FILE_OBJECT_DROP_NEW_LINE);
 
        return SUCCESS;
index 10922da6d2cd4e20415bfec097fade0854343364..7f4b9faf7086c9a94d6ef5808777bf8d4ecba28c 100755 (executable)
 #include "php.h"
 #include "php_spl.h"
 
+extern PHPAPI zend_class_entry *spl_ce_SplFileInfo;
 extern PHPAPI zend_class_entry *spl_ce_DirectoryIterator;
 extern PHPAPI zend_class_entry *spl_ce_RecursiveDirectoryIterator;
 extern PHPAPI zend_class_entry *spl_ce_SplFileObject;
+extern PHPAPI zend_class_entry *spl_ce_SplTempFileObject;
 
 PHP_MINIT_FUNCTION(spl_directory);
 
-typedef struct _spl_ce_dir_object {
-       zend_object       std;
-       php_stream        *dirp;
-       php_stream_dirent entry;
-       char              *path;
-       char              *path_name;
-       int               path_name_len;
-       char              *sub_path;
-       int               sub_path_len;
-       int               index;
-} spl_ce_dir_object;
+typedef enum {
+       SPL_FS_INFO,
+       SPL_FS_DIR,
+       SPL_FS_FILE,
+} SPL_FS_OBJ_TYPE;
 
-typedef struct _spl_file_object {
+typedef struct _spl_filesystem_object {
        zend_object        std;
-       php_stream         *stream;
-       php_stream_context *context;
-       zval               *zcontext;
+       char               *path;
+       int                path_len;
        char               *file_name;
-       int                file_name_len;
-       char               *open_mode;
-       int                open_mode_len;
-       zval               *current_zval;
-       char               *current_line;
-       size_t             current_line_len;
-       size_t             max_line_len;
-       long               current_line_num;
+       int                file_name_len; 
+       SPL_FS_OBJ_TYPE    type;
        long               flags;
-       zval               zresource;
-       zend_function      *func_getCurr;
-} spl_file_object;
+       zend_class_entry   *file_class;
+       zend_class_entry   *info_class;
+       union {
+               struct {
+                       php_stream         *dirp;
+                       php_stream_dirent  entry;
+                       char               *sub_path;
+                       int                sub_path_len;
+                       int                index;
+                       int                is_recursive;
+               } dir;
+               struct {
+                       php_stream         *stream;
+                       php_stream_context *context;
+                       zval               *zcontext;
+                       char               *open_mode;
+                       int                open_mode_len;
+                       zval               *current_zval;
+                       char               *current_line;
+                       size_t             current_line_len;
+                       size_t             max_line_len;
+                       long               current_line_num;
+                       zval               zresource;
+                       zend_function      *func_getCurr;
+               } file;
+       } u;
+} spl_filesystem_object;
 
 #define SPL_FILE_OBJECT_DROP_NEW_LINE      0x00000001 /* drop new lines */
 
+#define SPL_FILE_DIR_CURRENT_AS_FILEINFO   0x00000010 /* make RecursiveDirectoryTree::current() return SplFileInfo */
+#define SPL_FILE_DIR_CURRENT_AS_PATHNAME   0x00000020 /* make RecursiveDirectoryTree::current() return getPathname() */
+#define SPL_FILE_DIR_CURRENT_MODE_MASK     0x000000F0 /* make RecursiveDirectoryTree::key() return getFilename() */
+
+#define SPL_FILE_DIR_KEY_AS_FILENAME       0x00000100 /* make RecursiveDirectoryTree::key() return getFilename() */
+#define SPL_FILE_DIR_KEY_MODE_MASK         0x00000F00 /* make RecursiveDirectoryTree::key() return getFilename() */
+
 #endif /* SPL_DIRECTORY_H */
 
 /*
index 7ec76d814410a9ee3c13b7f4c83438464872f5d7..8b53b2123a1733807166523a123ea3439d072455 100755 (executable)
@@ -110,61 +110,3 @@ bool(false)
 string(33) "Parameter max_depth must be >= -1"
 int(4)
 ===DONE===
---UEXPECT--
-===?===
-bool(false)
-0: 1
-0: 2
-1: 31
-1: 32
-2: 331
-3: 3321
-4: 33221
-0: 4
-===2===
-int(2)
-0: 1
-0: 2
-1: 31
-1: 32
-2: 331
-0: 4
-===X===
-bool(false)
-0: 1
-0: 2
-1: 31
-1: 32
-2: 331
-3: 3321
-4: 33221
-0: 4
-===3===
-int(3)
-0: 1
-0: 2
-1: 31
-1: 32
-2: 331
-3: 3321
-0: 4
-===5===
-int(5)
-0: 1
-0: 2
-1: 31
-1: 32
-2: 331
-3: 3321
-4: 33221
-0: 4
-===0===
-int(0)
-0: 1
-0: 2
-0: 4
-===-1===
-bool(false)
-unicode(33) "Parameter max_depth must be >= -1"
-int(4)
-===DONE===
index d995961d7a1abfb10447afd94b3beca0fa21d00a..1f26521b9049078f747eb5121a69b569023ecca7 100755 (executable)
@@ -41,16 +41,3 @@ array(1) {
 MyAutoLoader::autoLoad(TestClass)
 bool(false)
 ===DONE===
---UEXPECTF--
-array(1) {
-  [0]=>
-  array(2) {
-    [0]=>
-    unicode(12) "MyAutoLoader"
-    [1]=>
-    unicode(8) "autoLoad"
-  }
-}
-MyAutoLoader::autoLoad(TestClass)
-bool(false)
-===DONE===
index 72180d6a1e4debb14b6c8eaae996b97c2deecc69..c6e6b41d0c3b78c8b60487f037e177dea3b3f5f1 100755 (executable)
@@ -26,38 +26,39 @@ $xml =<<<EOF
 </sxe>
 EOF;
 
-$sxe = simplexml_load_string($xml, 'SimpleXMLIterator');
-
-print_r($sxe);
+var_dump(simplexml_load_string($xml, 'SimpleXMLIterator'));
 
 ?>
 ===DONE===
---EXPECT--
-SimpleXMLIterator Object
-(
-    [elem1] => SimpleXMLIterator Object
-        (
-            [comment] => SimpleXMLIterator Object
-                (
-                )
-
-            [elem2] => SimpleXMLIterator Object
-                (
-                    [elem3] => SimpleXMLIterator Object
-                        (
-                            [elem4] => SimpleXMLIterator Object
-                                (
-                                    [test] => SimpleXMLIterator Object
-                                        (
-                                        )
-
-                                )
-
-                        )
-
-                )
-
-        )
-
-)
+--EXPECTF--
+object(SimpleXMLIterator)#%d (2) {
+  ["@attributes"]=>
+  array(1) {
+    ["id"]=>
+    string(5) "elem1"
+  }
+  ["elem1"]=>
+  object(SimpleXMLIterator)#%d (3) {
+    ["@attributes"]=>
+    array(1) {
+      ["attr1"]=>
+      string(5) "first"
+    }
+    ["comment"]=>
+    object(SimpleXMLIterator)#%d (0) {
+    }
+    ["elem2"]=>
+    object(SimpleXMLIterator)#%d (1) {
+      ["elem3"]=>
+      object(SimpleXMLIterator)#%d (1) {
+        ["elem4"]=>
+        object(SimpleXMLIterator)#%d (1) {
+          ["test"]=>
+          object(SimpleXMLIterator)#%d (0) {
+          }
+        }
+      }
+    }
+  }
+}
 ===DONE===
index 487de45071003f31f05ea78b339090b564333258..718a626b615405adbaefb27b4289976b051c382e 100755 (executable)
@@ -145,62 +145,3 @@ SXETest::next
 SXETest::valid
 SXETest::valid
 ===DONE===
---UEXPECTF--
-SXETest::rewind
-SXETest::valid
-SXETest::hasChildren
-SXETest::valid
-SXETest::current
-unicode(7) "SXETest"
-unicode(10) "Bla bla 1."
-SXETest::getChildren
-SXETest::rewind
-SXETest::valid
-SXETest::hasChildren
-SXETest::valid
-SXETest::current
-unicode(7) "SXETest"
-unicode(28) "Here we have some text data."
-SXETest::getChildren
-SXETest::rewind
-SXETest::valid
-SXETest::hasChildren
-SXETest::valid
-SXETest::current
-unicode(7) "SXETest"
-unicode(19) "And here some more."
-SXETest::getChildren
-SXETest::rewind
-SXETest::valid
-SXETest::hasChildren
-SXETest::valid
-SXETest::current
-unicode(7) "SXETest"
-unicode(15) "Wow once again."
-SXETest::next
-SXETest::valid
-SXETest::next
-SXETest::valid
-SXETest::next
-SXETest::valid
-SXETest::next
-SXETest::valid
-SXETest::hasChildren
-SXETest::valid
-SXETest::current
-unicode(7) "SXETest"
-unicode(10) "Bla bla 2."
-SXETest::getChildren
-SXETest::rewind
-SXETest::valid
-SXETest::hasChildren
-SXETest::valid
-SXETest::current
-unicode(7) "SXETest"
-unicode(7) "Foo Bar"
-SXETest::next
-SXETest::valid
-SXETest::next
-SXETest::valid
-SXETest::valid
-===DONE===