summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Boerger <helly@php.net>2005-10-08 18:57:17 +0000
committerMarcus Boerger <helly@php.net>2005-10-08 18:57:17 +0000
commit033ffc206d96e7f40882d7b7f3085ad97616ef1b (patch)
tree35a91e6adc151367dd4b1ebc87b4b4ec13623683
parent7b330f195bd755f82ca7a2ae9e3d25de9a5abb79 (diff)
downloadphp-git-033ffc206d96e7f40882d7b7f3085ad97616ef1b.tar.gz
- Add new example directorytree_size.php
- Improve SplFileInfo: . add function getFilename() . add function getPath() -Improve RecursiveTreeIterator . add const BYPASS_CURRENT to bypass current instead of getting its string representation . make key() return the parent key() which calls inner iterators key() - Improve RecursiveDirectoryIterator . add consts CURRENT_AS_FILEINFO, KEY_AS_FILENAME, NEW_CURRENT_AND_KEY . make current() return getFilename() or getFileInfo() depending on flags . make key() return getPathname() or getFilename() depending on flags - Improve DirectoryIterator . make __construct() accept flags as second parameter - Update docu
-rwxr-xr-xext/spl/examples/directorytree_size.php35
-rwxr-xr-xext/spl/examples/recursivetreeiterator.inc33
-rwxr-xr-xext/spl/internal/cachingiterator.inc8
-rwxr-xr-xext/spl/internal/recursiveiteratoriterator.inc4
-rwxr-xr-xext/spl/internal/splfileobject.inc2
-rwxr-xr-xext/spl/spl.php82
-rwxr-xr-xext/spl/spl_directory.c302
-rwxr-xr-xext/spl/spl_directory.h4
-rwxr-xr-xext/spl/spl_iterators.h6
9 files changed, 358 insertions, 118 deletions
diff --git a/ext/spl/examples/directorytree_size.php b/ext/spl/examples/directorytree_size.php
new file mode 100755
index 0000000000..d703409c45
--- /dev/null
+++ b/ext/spl/examples/directorytree_size.php
@@ -0,0 +1,35 @@
+<?php
+
+/** @file directorytree_size.php
+ * @brief Program Directory tree size example
+ * @ingroup Examples
+ * @author Marcus Boerger
+ * @date 2003 - 2005
+ *
+ * Usage: php directorytree_size.php \<path\>
+ *
+ * Simply specify the path to tree with parameter \<path\>.
+ */
+
+if ($argc < 2) {
+ echo <<<EOF
+Usage: php ${_SERVER['PHP_SELF']} <path>
+
+Displays a graphical directory tree for the given <path> with size info for all
+files.
+
+<path> The directory for which to generate the directory tree graph.
+
+
+EOF;
+ exit(1);
+}
+
+if (!class_exists("RecursiveTreeIterator", false)) require_once("recursivetreeiterator.inc");
+
+echo $argv[1]."\n";
+foreach(new RecursiveTreeIterator(new RecursiveDirectoryIterator($argv[1], RecursiveDirectoryIterator::NEW_CURRENT_AND_KEY), RecursiveTreeIterator::BYPASS_CURRENT) as $file => $fileinfo) {
+ echo $file . " (" . $fileinfo->getSize() . ")\n";
+}
+
+?> \ No newline at end of file
diff --git a/ext/spl/examples/recursivetreeiterator.inc b/ext/spl/examples/recursivetreeiterator.inc
index d525bc0782..2d2210e704 100755
--- a/ext/spl/examples/recursivetreeiterator.inc
+++ b/ext/spl/examples/recursivetreeiterator.inc
@@ -18,17 +18,20 @@
*/
class RecursiveTreeIterator extends RecursiveIteratorIterator
{
- private $callToString;
+ const BYPASS_CURRENT = 0x00000004;
+
+ private $rit_flags;
/**
* @param it iterator to use as inner iterator
- * @param flags flags passed to RecursiveIteratoIterator (parent)
+ * @param rit_flags flags passed to RecursiveIteratoIterator (parent)
* @param cit_flags flags passed to RecursiveCachingIterator (for hasNext)
+ * @param mode mode passed to RecursiveIteratoIterator (parent)
*/
- function __construct(RecursiveIterator $it, $flags = self::SELF_FIRST, $cit_flags = CachingIterator::CATCH_GET_CHILD)
+ function __construct(RecursiveIterator $it, $rit_flags = 0, $cit_flags = CachingIterator::CATCH_GET_CHILD, $mode = self::SELF_FIRST)
{
- parent::__construct(new RecursiveCachingIterator($it, $cit_flags), $flags);
- $this->callToString = (bool)($cit_flags & CachingIterator::CALL_TOSTRING);
+ parent::__construct(new RecursiveCachingIterator($it, $cit_flags), $mode, $rit_flags);
+ $this->rit_flags = $rit_flags;
}
/** Prefix strings used in getPrefix()
@@ -60,7 +63,7 @@ class RecursiveTreeIterator extends RecursiveIteratorIterator
*/
function getEntry()
{
- return $this->callToString ? $this->__toString() : @(string)parent::current();
+ return @(string)parent::current();
}
/** @return string to place after the current element
@@ -73,8 +76,22 @@ class RecursiveTreeIterator extends RecursiveIteratorIterator
/** @return the current element prefixed and postfixed
*/
function current()
- {
- return $this->getPrefix() . $this->getEntry() . $this->getPostfix();
+ {
+ if ($this->rit_flags & self::BYPASS_CURRENT)
+ {
+ return parent::current();
+ }
+ else
+ {
+ return $this->getPrefix() . $this->getEntry() . $this->getPostfix();
+ }
+ }
+
+ /** @return the current key prefixed and postfixed
+ */
+ function key()
+ {
+ return $this->getPrefix() . parent::key() . $this->getPostfix();
}
/** Aggregates the inner iterator
diff --git a/ext/spl/internal/cachingiterator.inc b/ext/spl/internal/cachingiterator.inc
index 6391322c3d..1129793873 100755
--- a/ext/spl/internal/cachingiterator.inc
+++ b/ext/spl/internal/cachingiterator.inc
@@ -27,10 +27,10 @@
*/
class CachingIterator implements OuterIterator
{
- const CALL_TOSTRING = 1;
- const CATCH_GET_CHILD = 2;
- const TOSTRING_USE_KEY = 4;
- const TOSTRING_USE_CURRENT = 8;
+ const CALL_TOSTRING = 0x00000001;
+ const CATCH_GET_CHILD = 0x00000002;
+ const TOSTRING_USE_KEY = 0x00000010;
+ const TOSTRING_USE_CURRENT = 0x00000020;
private $it;
private $current;
diff --git a/ext/spl/internal/recursiveiteratoriterator.inc b/ext/spl/internal/recursiveiteratoriterator.inc
index cc26e3ef49..aa2a9db8e7 100755
--- a/ext/spl/internal/recursiveiteratoriterator.inc
+++ b/ext/spl/internal/recursiveiteratoriterator.inc
@@ -30,9 +30,9 @@ class RecursiveIteratorIterator implements OuterIterator
/** Flag: Catches exceptions during getChildren() calls and simply jumps
* to the next element. */
- const CATCH_GET_CHILD = 2;
+ const CATCH_GET_CHILD = 0x00000002;
- private $ait = array();
+ private $ait = array();
private $level = 0;
private $mode = self::LEAVES_ONLY;
private $flags = 0;
diff --git a/ext/spl/internal/splfileobject.inc b/ext/spl/internal/splfileobject.inc
index 9d347b4b20..66e0398d3e 100755
--- a/ext/spl/internal/splfileobject.inc
+++ b/ext/spl/internal/splfileobject.inc
@@ -15,7 +15,7 @@
* @version 1.0
* @since PHP 5.1
*/
-class SplFileObject implements RecursiveIterator, SeekableIterator
+class SplFileObject extends SplFileInfo implements RecursiveIterator, SeekableIterator
{
/** Flag: wheter to suppress new lines */
const DROP_NEW_LINE = 0x00000001;
diff --git a/ext/spl/spl.php b/ext/spl/spl.php
index ef219de88f..942b824a33 100755
--- a/ext/spl/spl.php
+++ b/ext/spl/spl.php
@@ -51,9 +51,10 @@
*
* SPL offers two advanced directory and file handling classes:
*
- * - class DirectoryIterator implements Iterator
+ * - class SplFileInfo
+ * - class DirectoryIterator extends SplFileInfo implements Iterator
* - class RecursiveDirectoryIterator extends DirectoryIterator implements RecursiveIterator
- * - class SplFileObject implements RecursiveIterator, SeekableIterator
+ * - class SplFileObject extends SplFileInfo implements RecursiveIterator, SeekableIterator
*
* 3) XML
*
@@ -729,22 +730,22 @@ class ArrayIterator implements SeekableIterator, ArrayAccess, Countable
}
/** @ingroup SPL
- * @brief Directory iterator
- * @since PHP 5.0
+ * @brief File info class
+ * @since PHP 6.0
*/
-class DirectoryIterator implements Iterator
+class SplFileInfo
{
- /** Construct a directory iterator from a path-string.
+ /** Construct a file info object
*
- * @param $path directory to iterate.
+ * @param $file_name path or file name
*/
- function __construct($path);
+ function __construct($file_name);
- /** @return The opened path.
+ /** @return the path part only.
*/
function getPath();
- /** @return The current file name.
+ /** @return the filename only.
*/
function getFilename();
@@ -808,15 +809,11 @@ class DirectoryIterator implements Iterator
*/
function isDir();
- /** @return Whether the current entry is either '.' or '..'.
- */
- function isDot();
-
/** @return whether the current entry is a link.
*/
function isLink();
- /** @return getFilename()
+ /** @return getPathname()
*/
function __toString();
@@ -832,15 +829,68 @@ class DirectoryIterator implements Iterator
* @see SplFileObject
* @see file()
*/
- function DirectoryIterator::openFile($mode = 'r', $use_include_path = false, $context = NULL);
+ function openFile($mode = 'r', $use_include_path = false, $context = NULL);
+}
+
+/** @ingroup SPL
+ * @brief Directory iterator
+ * @version 1.1
+ * @since PHP 5.0
+ */
+class DirectoryIterator extends SplFileInfo implements Iterator
+{
+ /** Construct a directory iterator from a path-string.
+ *
+ * @param $path directory to iterate.
+ */
+ function __construct($path);
+
+ /** @return index of entry
+ */
+ function key();
+
+ /** @return $this
+ */
+ function current();
+
+ /** @return Whether the current entry is either '.' or '..'.
+ */
+ function isDot();
+
+ /** @return whether the current entry is a link.
+ */
+ function isLink();
+
+ /** @return getFilename()
+ */
+ function __toString();
}
/** @ingroup SPL
* @brief recursive directory iterator
+ * @version 1.1
* @since PHP 5.0
*/
class RecursiveDirectoryIterator extends DirectoryIterator implements RecursiveIterator
{
+ const CURRENT_AS_FILEINFO 0x00000010; /* make RecursiveDirectoryTree::current() return SplFileInfo */
+ const KEY_AS_FILENAME 0x00000020; /* make RecursiveDirectoryTree::key() return getFilename() */
+ const NEW_CURRENT_AND_KEY 0x00000030; /* CURRENT_AS_FILEINFO + KEY_AS_FILENAME */
+
+ /** Construct a directory iterator from a path-string.
+ *
+ * @param $path directory to iterate.
+ */
+ function __construct($path, $flags = 0);
+
+ /** @return getPathname() or getFilename() depending on flags
+ */
+ function key();
+
+ /** @return getFilename() or getFileInfo() depending on flags
+ */
+ function current();
+
/** @return whether the current is a directory (not '.' or '..').
*/
function hasChildren();
diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c
index c6ce47175c..888a4b8e84 100755
--- a/ext/spl/spl_directory.c
+++ b/ext/spl/spl_directory.c
@@ -45,7 +45,7 @@
#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;
@@ -137,7 +137,7 @@ static zend_object_value spl_filesystem_object_new_ex(zend_class_entry *class_ty
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_filesystem_object_free_storage, NULL TSRMLS_CC);
- retval.handlers = &spl_ce_dir_handlers;
+ retval.handlers = &spl_filesystem_object_handlers;
return retval;
}
/* }}} */
@@ -236,17 +236,23 @@ static zend_object_value spl_filesystem_object_clone(zval *zobject TSRMLS_DC)
zend_object *new_object;
zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
spl_filesystem_object *intern;
+ spl_filesystem_object *source;
old_object = zend_objects_get_address(zobject 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;
- switch(((spl_filesystem_object*)old_object)->type) {
+ 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, ((spl_filesystem_object*)old_object)->path TSRMLS_CC);
+ 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 %v cannot be cloned", old_object->ce->name);
@@ -259,7 +265,71 @@ static zend_object_value spl_filesystem_object_clone(zval *zobject TSRMLS_DC)
}
/* }}} */
-/* {{{ proto void DirectoryIterator::__construct(string path)
+static void spl_filesystem_object_create_type(int ht, spl_filesystem_object *source, int type, zval *return_value TSRMLS_DC) /* {{{ */
+{
+ spl_filesystem_object *intern;
+ zend_bool use_include_path = 0;
+
+ php_set_error_handling(EH_THROW, U_CLASS_ENTRY(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(U_CLASS_ENTRY(spl_ce_RuntimeException), 0 TSRMLS_CC, "Could not open file");
+ php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
+ return;
+ }
+ }
+
+ switch (type) {
+ case SPL_FS_INFO:
+ return_value->value.obj = spl_filesystem_object_new_ex(spl_ce_SplFileInfo, &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;
+
+ php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
+ break;
+ case SPL_FS_FILE:
+ return_value->value.obj = spl_filesystem_object_new_ex(spl_ce_SplFileObject, &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 (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;
+ }
+
+ 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;
+ }
+ case SPL_FS_DIR:
+ zend_throw_exception_ex(U_CLASS_ENTRY(spl_ce_RuntimeException), 0 TSRMLS_CC, "Operation not supported");
+ break;
+ }
+ php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
+} /* }}} */
+
+/* {{{ 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
@@ -273,16 +343,19 @@ SPL_METHOD(DirectoryIterator, __construct)
spl_filesystem_object *intern;
char *path;
int len;
+ long flags = 0;
php_set_error_handling(EH_THROW, U_CLASS_ENTRY(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_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, U_CLASS_ENTRY(spl_ce_RecursiveDirectoryIterator) TSRMLS_CC) ? 1 : 0;
+ intern->flags = flags;
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
}
@@ -353,9 +426,9 @@ SPL_METHOD(DirectoryIterator, valid)
}
/* }}} */
-/* {{{ proto string DirectoryIterator::getPath()
- Return directory path */
-SPL_METHOD(DirectoryIterator, getPath)
+/* {{{ proto string SplFileInfo::getPath()
+ Return the path */
+SPL_METHOD(SplFileInfo, getPath)
{
spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
@@ -363,6 +436,20 @@ SPL_METHOD(DirectoryIterator, getPath)
}
/* }}} */
+/* {{{ 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)
@@ -394,13 +481,32 @@ SPL_METHOD(SplFileInfo, getPathname)
/* }}} */
/* {{{ proto string RecursiveDirectoryIterator::key()
- Return path and filename of current dir entry */
+ Return getPathname() or getFilename() depending on flags */
SPL_METHOD(RecursiveDirectoryIterator, key)
{
spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
- spl_filesystem_object_get_file_name(intern TSRMLS_CC);
- RETURN_STRINGL(intern->file_name, intern->file_name_len, 1);
+ if (intern->flags & SPL_FILE_DIR_KEY_AS_FILENAME) {
+ RETURN_STRING(intern->u.dir.entry.d_name, 1);
+ } else {
+ spl_filesystem_object_get_file_name(intern TSRMLS_CC);
+ RETURN_STRINGL(intern->file_name, intern->file_name_len, 1);
+ }
+}
+/* }}} */
+
+/* {{{ proto string RecursiveDirectoryIterator::current()
+ Return getFilename() or getFileInfo() depending on flags */
+SPL_METHOD(RecursiveDirectoryIterator, current)
+{
+ spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ 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, return_value TSRMLS_CC);
+ } else {
+ RETURN_STRING(intern->u.dir.entry.d_name, 1);
+ }
}
/* }}} */
@@ -426,7 +532,7 @@ SPL_METHOD(DirectoryIterator, isDot)
SPL_METHOD(SplFileInfo, __construct)
{
spl_filesystem_object *intern;
- char *path;
+ char *path, *p1, *p2;
int len;
php_set_error_handling(EH_THROW, U_CLASS_ENTRY(spl_ce_RuntimeException) TSRMLS_CC);
@@ -438,8 +544,18 @@ SPL_METHOD(SplFileInfo, __construct)
intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
- intern->file_name = estrdup(path);
+ intern->file_name = estrndup(path, len);
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);
+
/* intern->type = SPL_FS_INFO; already set */
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
@@ -536,52 +652,19 @@ FileInfoFunction(isLink, FS_IS_LINK)
Open the current file */
SPL_METHOD(SplFileInfo, openFile)
{
- spl_filesystem_object *dir_obj = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
- spl_filesystem_object *intern;
- zend_bool use_include_path = 0;
-
- php_set_error_handling(EH_THROW, U_CLASS_ENTRY(spl_ce_RuntimeException) TSRMLS_CC);
-
- switch (intern->type) {
- case SPL_FS_INFO:
- case SPL_FS_FILE:
- break;
- case SPL_FS_DIR:
- if (!dir_obj->u.dir.entry.d_name[0]) {
- zend_throw_exception_ex(U_CLASS_ENTRY(spl_ce_RuntimeException), 0 TSRMLS_CC, "Could not open file");
- php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
- zval_dtor(return_value);
- return;
- }
- }
-
- return_value->value.obj = spl_filesystem_object_new_ex(spl_ce_SplFileObject, &intern TSRMLS_CC);
-
- spl_filesystem_object_get_file_name(dir_obj TSRMLS_CC);
- intern->file_name = dir_obj->file_name;
- intern->file_name_len = dir_obj->file_name_len;
-
- intern->u.file.open_mode = "r";
- intern->u.file.open_mode_len = 1;
+ spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
- if (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);
- zval_dtor(return_value);
- return;
- }
+ spl_filesystem_object_create_type(ht, intern, SPL_FS_FILE, return_value TSRMLS_CC);
+}
- if (spl_filesystem_file_open(intern, use_include_path, 0 TSRMLS_CC) == SUCCESS) {
- Z_TYPE_P(return_value) = IS_OBJECT;
- } else {
- php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
- zval_dtor(return_value);
- return;
- }
+/* {{{ proto SplFileObject SplFileInfo::getFileInfo()
+ Get/copy file info */
+SPL_METHOD(SplFileInfo, getFileInfo)
+{
+ spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
- php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
-} /* }}} */
+ spl_filesystem_object_create_type(ht, intern, SPL_FS_INFO, return_value TSRMLS_CC);
+}
/* {{{ proto void RecursiveDirectoryIterator::rewind()
Rewind dir back to the start */
@@ -668,6 +751,7 @@ SPL_METHOD(RecursiveDirectoryIterator, getChildren)
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;
}
}
/* }}} */
@@ -734,11 +818,10 @@ zend_object_iterator *spl_filesystem_dir_get_iterator(zend_class_entry *ce, zval
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_filesystem_dir_it_funcs;
iterator->current = object;
- object->refcount++;
iterator->object = dir_object;
return (zend_object_iterator*)iterator;
@@ -821,15 +904,53 @@ static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter TSRMLS_DC)
}
/* }}} */
+/* {{{ spl_filesystem_tree_it_dtor */
+static void spl_filesystem_tree_it_dtor(zend_object_iterator *iter TSRMLS_DC)
+{
+ spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter;
+
+ 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_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, 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_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);
+ 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;
}
/* }}} */
@@ -850,6 +971,10 @@ static void spl_filesystem_tree_it_move_forward(zend_object_iterator *iter TSRML
efree(object->file_name);
object->file_name = NULL;
}
+ if (iterator->current) {
+ zval_ptr_dtor(&iterator->current);
+ iterator->current = NULL;
+ }
}
/* }}} */
@@ -868,14 +993,18 @@ static void spl_filesystem_tree_it_rewind(zend_object_iterator *iter TSRMLS_DC)
object->u.dir.entry.d_name[0] = '\0';
}
} 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_filesystem_tree_it_funcs = {
- spl_filesystem_dir_it_dtor,
+ spl_filesystem_tree_it_dtor,
spl_filesystem_dir_it_valid,
- spl_filesystem_dir_it_current_data,
+ spl_filesystem_tree_it_current_data,
spl_filesystem_tree_it_current_key,
spl_filesystem_tree_it_move_forward,
spl_filesystem_tree_it_rewind
@@ -890,8 +1019,7 @@ zend_object_iterator *spl_filesystem_tree_get_iterator(zend_class_entry *ce, zva
object->refcount++;
iterator->intern.data = (void*)object;
iterator->intern.funcs = &spl_filesystem_tree_it_funcs;
- iterator->current = object;
- object->refcount++;
+ iterator->current = NULL;
iterator->object = dir_object;
return (zend_object_iterator*)iterator;
@@ -910,15 +1038,8 @@ static int spl_filesystem_object_cast(zval *readobj, zval *writeobj, int type TS
ZVAL_STRINGL(writeobj, intern->file_name, intern->file_name_len, 1);
return SUCCESS;
case SPL_FS_DIR:
- if (intern->u.dir.is_recursive) {
- spl_filesystem_object_get_file_name(intern TSRMLS_CC);
- ZVAL_STRINGL(writeobj, intern->file_name, intern->file_name_len, 1);
- return SUCCESS;
- } else if (*intern->u.dir.entry.d_name) {
- ZVAL_STRING(writeobj, intern->u.dir.entry.d_name, 1);
- return SUCCESS;
- }
- return FAILURE;
+ ZVAL_STRING(writeobj, intern->u.dir.entry.d_name, 1);
+ return SUCCESS;
}
}
return FAILURE;
@@ -943,6 +1064,8 @@ ZEND_END_ARG_INFO();
/* each method can have its own parameters and visibility */
static zend_function_entry spl_filesystem_info_class_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)
@@ -959,6 +1082,7 @@ static zend_function_entry spl_filesystem_info_class_functions[] = {
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, NULL, ZEND_ACC_PUBLIC)
SPL_ME(SplFileInfo, openFile, arginfo_info_openFile, ZEND_ACC_PUBLIC)
SPL_MA(SplFileInfo, __toString, SplFileInfo, getPathname, NULL, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
@@ -973,7 +1097,6 @@ ZEND_END_ARG_INFO();
/* each method can have its own parameters and visibility */
static zend_function_entry spl_filesystem_dir_class_functions[] = {
SPL_ME(DirectoryIterator, __construct, arginfo_dir___construct, ZEND_ACC_PUBLIC)
- SPL_ME(DirectoryIterator, getPath, NULL, 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)
@@ -989,11 +1112,11 @@ static zend_function_entry spl_filesystem_tree_class_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_MA(RecursiveDirectoryIterator, __toString, SplFileInfo, getPathname, NULL, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
@@ -1019,7 +1142,7 @@ static int spl_filesystem_file_read(spl_filesystem_object *intern, int silent TS
intern->u.file.current_line = estrdup("");
intern->u.file.current_line_len = 0;
} else {
- if (intern->u.file.flags & SPL_FILE_OBJECT_DROP_NEW_LINE) {
+ if (intern->flags & SPL_FILE_OBJECT_DROP_NEW_LINE) {
line_len = strcspn(buf, "\r\n");
buf[line_len] = '\0';
}
@@ -1088,6 +1211,7 @@ SPL_METHOD(SplFileObject, __construct)
{
spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
zend_bool use_include_path = 0;
+ char *p1, *p2;
php_set_error_handling(EH_THROW, U_CLASS_ENTRY(spl_ce_RuntimeException) TSRMLS_CC);
@@ -1104,6 +1228,15 @@ SPL_METHOD(SplFileObject, __construct)
spl_filesystem_file_open(intern, use_include_path, 0 TSRMLS_CC);
+ 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);
+
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
} /* }}} */
@@ -1201,7 +1334,7 @@ SPL_METHOD(SplFileObject, setFlags)
{
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->u.file.flags);
+ zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &intern->flags);
} /* }}} */
/* {{{ proto int SplFileObject::getFlags()
@@ -1210,7 +1343,7 @@ SPL_METHOD(SplFileObject, getFlags)
{
spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
- RETURN_LONG(intern->u.file.flags);
+ RETURN_LONG(intern->flags);
} /* }}} */
/* {{{ proto void SplFileObject::setMaxLineLen(int max_len)
@@ -1621,17 +1754,20 @@ static zend_function_entry spl_filesystem_file_class_functions[] = {
PHP_MINIT_FUNCTION(spl_directory)
{
REGISTER_SPL_STD_CLASS_EX(SplFileInfo, spl_filesystem_object_new, spl_filesystem_info_class_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_filesystem_dir_class_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_filesystem_object_clone;
- spl_ce_dir_handlers.cast_object = spl_filesystem_object_cast;
spl_ce_DirectoryIterator->get_iterator = spl_filesystem_dir_get_iterator;
REGISTER_SPL_SUB_CLASS_EX(RecursiveDirectoryIterator, DirectoryIterator, spl_filesystem_object_new, spl_filesystem_tree_class_functions);
REGISTER_SPL_IMPLEMENTS(RecursiveDirectoryIterator, RecursiveIterator);
+ REGISTER_SPL_CLASS_CONST_LONG(RecursiveDirectoryIterator, "CURRENT_AS_FILEINFO", SPL_FILE_DIR_CURRENT_AS_FILEINFO);
+ 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);
spl_ce_RecursiveDirectoryIterator->get_iterator = spl_filesystem_tree_get_iterator;
diff --git a/ext/spl/spl_directory.h b/ext/spl/spl_directory.h
index 2d1ab9ca2b..998fec139d 100755
--- a/ext/spl/spl_directory.h
+++ b/ext/spl/spl_directory.h
@@ -44,6 +44,7 @@ typedef struct _spl_filesystem_object {
char *file_name;
int file_name_len;
SPL_FS_OBJ_TYPE type;
+ long flags;
union {
struct {
php_stream *dirp;
@@ -64,7 +65,6 @@ typedef struct _spl_filesystem_object {
size_t current_line_len;
size_t max_line_len;
long current_line_num;
- long flags;
zval zresource;
zend_function *func_getCurr;
} file;
@@ -72,6 +72,8 @@ typedef struct _spl_filesystem_object {
} 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_KEY_AS_FILENAME 0x00000020 /* make RecursiveDirectoryTree::key() return getFilename() */
#endif /* SPL_DIRECTORY_H */
diff --git a/ext/spl/spl_iterators.h b/ext/spl/spl_iterators.h
index fef2bf2929..abb0534bf9 100755
--- a/ext/spl/spl_iterators.h
+++ b/ext/spl/spl_iterators.h
@@ -66,9 +66,9 @@ enum {
/* public */
CIT_CALL_TOSTRING = 0x00000001,
CIT_CATCH_GET_CHILD = 0x00000002,
- CIT_TOSTRING_USE_KEY = 0x00000004,
- CIT_TOSTRING_USE_CURRENT = 0x00000008,
- CIT_FULL_CACHE = 0x00000010,
+ CIT_TOSTRING_USE_KEY = 0x00000010,
+ CIT_TOSTRING_USE_CURRENT = 0x00000020,
+ CIT_FULL_CACHE = 0x00000100,
CIT_PUBLIC = 0x0000FFFF,
/* private */
CIT_VALID = 0x00010000,