summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Boerger <helly@php.net>2006-07-16 21:12:32 +0000
committerMarcus Boerger <helly@php.net>2006-07-16 21:12:32 +0000
commit55f0596fabfe9613d535adcb19caa820b2104e51 (patch)
tree6bd3b70c35d123b9c900278cb2adcde0be3d1253
parentbf4c9ef68616eb6998154b04337bbbe2ffac67fb (diff)
downloadphp-git-55f0596fabfe9613d535adcb19caa820b2104e51.tar.gz
- MFH:
. Upgrade RegexIterator capabilities, see docu . Update docu . Add test (which fails right now: iterator_049.phpt) . Add tests for new functionality
-rwxr-xr-xext/spl/internal/filteriterator.inc10
-rwxr-xr-xext/spl/internal/recursiveregexiterator.inc55
-rwxr-xr-xext/spl/internal/regexiterator.inc90
-rwxr-xr-xext/spl/spl.php263
-rwxr-xr-xext/spl/spl_iterators.c84
-rwxr-xr-xext/spl/spl_iterators.h10
-rwxr-xr-xext/spl/tests/iterator_049.phpt24
-rwxr-xr-xext/spl/tests/iterator_050.phpt93
-rwxr-xr-xext/spl/tests/iterator_051.phpt159
-rwxr-xr-xext/spl/tests/iterator_052.phpt129
-rwxr-xr-xext/spl/tests/iterator_053.phpt237
-rwxr-xr-xext/spl/tests/iterator_054.phpt84
-rwxr-xr-xext/spl/tests/iterator_055.phpt93
13 files changed, 1220 insertions, 111 deletions
diff --git a/ext/spl/internal/filteriterator.inc b/ext/spl/internal/filteriterator.inc
index cc9c999a40..9820d48318 100755
--- a/ext/spl/internal/filteriterator.inc
+++ b/ext/spl/internal/filteriterator.inc
@@ -4,13 +4,13 @@
* @ingroup SPL
* @brief class FilterIterator
* @author Marcus Boerger
- * @date 2003 - 2005
+ * @date 2003 - 2006
*
* SPL - Standard PHP Library
*/
/**
- * @brief Regular expression filter for string iterators
+ * @brief Abstract filter for iterators
* @author Marcus Boerger
* @version 1.1
* @since PHP 5.0
@@ -28,11 +28,9 @@ abstract class FilterIterator implements OuterIterator
private $it;
/**
- * Constructs a filter around an iterator whose elemnts are strings.
- * If the given iterator is of type spl_sequence then its rewind()
- * method is called.
+ * Constructs a filter around another iterator.
*
- * @param it Object that implements at least spl_forward
+ * @param it Iterator to filter
*/
function __construct(Iterator $it) {
$this->it = $it;
diff --git a/ext/spl/internal/recursiveregexiterator.inc b/ext/spl/internal/recursiveregexiterator.inc
new file mode 100755
index 0000000000..caaee97b54
--- /dev/null
+++ b/ext/spl/internal/recursiveregexiterator.inc
@@ -0,0 +1,55 @@
+<?php
+
+/** @file recursiveregexiterator.inc
+ * @ingroup SPL
+ * @brief class RegexIterator
+ * @author Marcus Boerger
+ * @date 2003 - 2006
+ *
+ * SPL - Standard PHP Library
+ */
+
+/**
+ * @brief Recursive regular expression filter for iterators
+ * @author Marcus Boerger
+ * @version 1.0
+ * @since PHP 5.1
+ *
+ * This filter iterator assumes that the inner iterator
+ */
+class RecursiveRegexIterator extends RegexIterator implements RecursiveIterator
+{
+ /**
+ * Constructs a regular expression filter around an iterator whose
+ * elemnts or keys are strings.
+ *
+ * @param it Object that implements at least
+ */
+ function __construct(RecursiveIterator $it, $regex, $flags = 0, $mode = 0, $preg_flags = 0) {
+ parent::__construct($it, $regex, $flags, $mode, $preg_flags);
+ }
+
+ /** @return whether the current element has children
+ */
+ function hasChildren()
+ {
+ return $this->getInnerIterator()->hasChildren();
+ }
+
+ /** @return an iterator for the current elements children
+ *
+ * @note the returned iterator will be of the same class as $this
+ */
+ function getChildren()
+ {
+ if (empty($this->ref))
+ {
+ $this->ref = new ReflectionClass($this);
+ }
+ return $this->ref->newInstance($this->getInnerIterator()->getChildren());
+ }
+
+ private $ref;
+}
+
+?> \ No newline at end of file
diff --git a/ext/spl/internal/regexiterator.inc b/ext/spl/internal/regexiterator.inc
new file mode 100755
index 0000000000..84ebf986d2
--- /dev/null
+++ b/ext/spl/internal/regexiterator.inc
@@ -0,0 +1,90 @@
+<?php
+
+/** @file regexiterator.inc
+ * @ingroup SPL
+ * @brief class RegexIterator
+ * @author Marcus Boerger
+ * @date 2003 - 2006
+ *
+ * SPL - Standard PHP Library
+ */
+
+/**
+ * @brief Regular expression filter for iterators
+ * @author Marcus Boerger
+ * @version 1.1
+ * @since PHP 5.1
+ *
+ * This filter iterator assumes that the inner iterator
+ */
+class RegexIterator implements FilterIterator
+{
+ const USE_KEY = 0x00000001;
+
+ const MATCH = 0;
+ const GET_MATCH = 1;
+ const ALL_MATCHES = 2;
+ const SPLIT = 3;
+
+ private $regex; /**< the regular expression to match against */
+ private $flags; /**< special flags (USE_KEY) */
+ private $mode; /**< operation mode (MATCH, GET_MATCH, ALL_MATCHES, SPLIT) */
+ private $preg_flags;/**< PREG_* flags, see preg_match(), preg_match_all(), preg_split() */
+ private $current; /**< the value used for current() */
+
+ /**
+ * Constructs a regular expression filter around an iterator whose
+ * elemnts or keys are strings.
+ *
+ * @param it Object that implements at least
+ */
+ function __construct(Iterator $it, $regex, $flags = 0, $mode = 0, $preg_flags = 0) {
+ parent::__construct($it);
+ $this->regex = $regex;
+ $this->flags = $flags;
+ $this->mode = $mode;
+ $this->preg_flags = $preg_flags;
+ }
+
+ /**
+ * Match current or key against regular expression using mode, flags and
+ * preg_flags.
+ *
+ * @return whether this is a match
+ *
+ * @warning never call this twice for the same state
+ */
+ function accept()
+ {
+ $matches = array();
+ $this->current = parent::current();
+ /* note that we use $this->current, rather than calling parent::current() */
+ $subject = ($this->flags & self::USE_KEY) ? parent::key() : $this->current;
+ switch($this->mode)
+ {
+ case self::MATCH:
+ return preg_match($this->regex, $subject, $matches, $this->preg_flags);
+
+ case self::GET_MATCH:
+ $this->current = array();
+ return preg_match($this->regex, $subject, $this->current, $this->preg_flags) > 0;
+
+ case self::ALL_MATCHES:
+ $this->current = array();
+ return preg_match_all($this->regex, $subject, $this->current, $this->preg_flags) > 0;
+
+ case self::SPLIT:
+ $this->current = array();
+ preg_split($this->regex, $subject, $this->current, $this->preg_flags) > 1;
+ }
+ }
+
+ /** @return the current value after accept has been called
+ */
+ function current()
+ {
+ return $this->current;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/ext/spl/spl.php b/ext/spl/spl.php
index f704e044ba..625042f72d 100755
--- a/ext/spl/spl.php
+++ b/ext/spl/spl.php
@@ -6,7 +6,7 @@
*
* SPL - Standard PHP Library
*
- * (c) Marcus Boerger, 2003 - 2005
+ * (c) Marcus Boerger, 2003 - 2006
*/
/** @mainpage SPL - Standard PHP Library
@@ -46,6 +46,8 @@
* - class EmptyIterator implements Iterator
* - class InfiniteIterator extends IteratorIterator
* - class AppendIterator implements OuterIterator
+ * - class RegexIterator extends FilterIterator
+ * - class RegursiveRegexIterator extends RegexIterator implements RecursiveIterator
*
* 2) Directories and Files
*
@@ -66,8 +68,8 @@
*
* SPL offers advanced Array overloading:
*
- * - class ArrayObject implements IteratorAggregate
- * - class ArrayIterator implements Iterator
+ * - class ArrayObject implements IteratorAggregate, ArrayAccess, Countable
+ * - class ArrayIterator implements Iterator, ArrayAccess, Countable, SeekableIterator
* - class RecursiveArrayIterator extends ArrayIterator implements RecursiveIterator
*
* As the above suggest an ArrayObject creates an ArrayIterator when it comes to
@@ -128,7 +130,7 @@
* You can download this documentation as a chm file
* <a href="http://php.net/~helly/php/ext/spl/spl.chm">here</a>.
*
- * (c) Marcus Boerger, 2003 - 2005
+ * (c) Marcus Boerger, 2003 - 2006
*/
/** @defgroup ZendEngine Zend engine classes
@@ -157,7 +159,7 @@
* @param class_name name of class to load
* @param file_extensions file extensions (use defaults if NULL)
*/
-function spl_autoload(string $class_name, string $file_extensions = NULL);
+function spl_autoload(string $class_name, string $file_extensions = NULL) {/**/};
/** @ingroup SPL
* @brief Manual invocation of all registerd autoload functions
@@ -165,7 +167,7 @@ function spl_autoload(string $class_name, string $file_extensions = NULL);
*
* @param class_name name of class to load
*/
-function spl_autoload_call(string $class_name);
+function spl_autoload_call(string $class_name) {/**/};
/** @ingroup SPL
* @brief Register and return default file extensions for spl_autoload
@@ -176,7 +178,7 @@ function spl_autoload_call(string $class_name);
* @return comma separated list of file extensions to use in default autoload
* function.
*/
-function spl_autoload_extensions($file_extensions);
+function spl_autoload_extensions($file_extensions) {/**/};
/** @ingroup SPL
* @brief Return all registered autoload functionns
@@ -184,7 +186,7 @@ function spl_autoload_extensions($file_extensions);
*
* @return array of all registered autoload functions or false
*/
-function spl_autoload_functions();
+function spl_autoload_functions() {/**/};
/** @ingroup SPL
* @brief Register given function as autoload implementation
@@ -194,7 +196,7 @@ function spl_autoload_functions();
* function name to register as autoload function.
* @param throw whether to throw or issue an error on failure.
*/
-function spl_autoload_register(string $autoload_function = "spl_autoload", $throw = true);
+function spl_autoload_register(string $autoload_function = "spl_autoload", $throw = true) {/**/};
/** @ingroup SPL
* @brief Unregister given function as autoload implementation
@@ -203,7 +205,7 @@ function spl_autoload_register(string $autoload_function = "spl_autoload", $thro
* @param autoload_function name of function or array of object/class and
* function name to unregister as autoload function.
*/
-function spl_autoload_unregister(string $autoload_function = "spl_autoload");
+function spl_autoload_unregister(string $autoload_function = "spl_autoload") {/**/};
/** @ingroup SPL
* @brief Return an array of classes and interfaces in SPL
@@ -211,7 +213,7 @@ function spl_autoload_unregister(string $autoload_function = "spl_autoload");
* @return array containing the names of all clsses and interfaces defined in
* extension SPL
*/
-function spl_classes();
+function spl_classes() {/**/};
/** @ingroup SPL
* @brief Count the elements in an iterator
@@ -219,7 +221,7 @@ function spl_classes();
*
* @return number of elements in an iterator
*/
-function iterator_count(Traversable $it);
+function iterator_count(Traversable $it) {/**/};
/** @ingroup SPL
* @brief Copy iterator elements into an array
@@ -228,7 +230,7 @@ function iterator_count(Traversable $it);
* @param it iterator to copy
* @return array with elements copied from the iterator
*/
-function iterator_to_array(Traversable $it);
+function iterator_to_array(Traversable $it) {/**/};
/** @ingroup ZendEngine
* @brief Basic Exception class.
@@ -611,7 +613,7 @@ class ArrayObject implements IteratorAggregate, ArrayAccess, Countable
* @param $flags see setFlags().
* @param $iterator_class class used in getIterator()
*/
- function __construct($array, $flags = 0, $iterator_class = "ArrayIterator");
+ function __construct($array, $flags = 0, $iterator_class = "ArrayIterator") {/**/}
/** Set behavior flags.
*
@@ -620,72 +622,94 @@ class ArrayObject implements IteratorAggregate, ArrayAccess, Countable
* when accessed as list (var_dump, foreach, etc.)
* 1 set: array indices can be accessed as properties in read/write
*/
- function setFlags($flags);
+ function setFlags($flags) {/**/}
- /**
- * @ return current flags
+ /** @return current flags
*/
- function getFlags();
+ function getFlags() {/**/}
- /**
- * @param $array new array or object
+ /** Sort the entries by values.
+ */
+ function asort() {/**/}
+
+ /** Sort the entries by key.
*/
- function exchangeArray($array);
+ function ksort() {/**/}
+
+ /** Sort the entries by values using user defined function.
+ */
+ function uasort(mixed cmp_function) {/**/}
+
+ /** Sort the entries by key using user defined function.
+ */
+ function uksort(mixed cmp_function) {/**/}
+
+ /** Sort the entries by values using "natural order" algorithm.
+ */
+ function natsort() {/**/}
+
+ /** Sort the entries by values using case insensitive "natural order" algorithm.
+ */
+ function natcasesort() {/**/}
+
+ /** @param $array new array or object
+ */
+ function exchangeArray($array) {/**/}
/** @return the iterator which is an ArrayIterator object connected to
* this object.
*/
- function getIterator();
+ function getIterator() {/**/}
/** @param $index offset to inspect
* @return whetehr offset $index esists
*/
- function offsetExists($index);
+ function offsetExists($index) {/**/}
/** @param $index offset to return value for
* @return value at offset $index
*/
- function offsetGet($index);
+ function offsetGet($index) {/**/}
/** @param $index index to set
* @param $newval new value to store at offset $index
*/
- function offsetSet($index, $newval);
+ function offsetSet($index, $newval) {/**/}
/** @param $index offset to unset
*/
- function offsetUnset($index);
+ function offsetUnset($index) {/**/}
/** @param $value is appended as last element
* @warning this method cannot be called when the ArrayObject refers to
* an object.
*/
- function append($value);
+ function append($value) {/**/}
/** @return a \b copy of the array
* @note when the ArrayObject refers to an object then this method
* returns an array of the public properties.
*/
- function getArrayCopy();
+ function getArrayCopy() {/**/}
/** @return the number of elements in the array or the number of public
* properties in the object.
*/
- function count();
+ function count() {/**/}
/* @param $iterator_class new class used in getIterator()
*/
- function setIteratorClass($itertor_class);
+ function setIteratorClass($itertor_class) {/**/}
/* @return class used in getIterator()
*/
- function getIteratorClass();
+ function getIteratorClass() {/**/}
}
/** @ingroup SPL
* @brief An Array iterator
* @since PHP 5.0
- * @version 1.1
+ * @version 1.2
*
* This iterator allows to unset and modify values and keys while iterating
* over Arrays and Objects.
@@ -709,7 +733,7 @@ class ArrayIterator implements SeekableIterator, ArrayAccess, Countable
* @param $array the array to use.
* @param $flags see setFlags().
*/
- function __construct($array, $flags = 0);
+ function __construct($array, $flags = 0) {/**/}
/** Set behavior flags.
*
@@ -718,53 +742,92 @@ class ArrayIterator implements SeekableIterator, ArrayAccess, Countable
* when accessed as list (var_dump, foreach, etc.)
* 1 set: array indices can be accessed as properties in read/write
*/
- function setFlags($flags);
+ function setFlags($flags) {/**/}
/**
- * @ return current flags
+ * @return current flags
*/
- function getFlags();
+ function getFlags() {/**/}
+ /** Sort the entries by values.
+ */
+ function asort() {/**/}
+
+ /** Sort the entries by key.
+ */
+ function ksort() {/**/}
+
+ /** Sort the entries by values using user defined function.
+ */
+ function uasort(mixed cmp_function) {/**/}
+
+ /** Sort the entries by key using user defined function.
+ */
+ function uksort(mixed cmp_function) {/**/}
+
+ /** Sort the entries by values using "natural order" algorithm.
+ */
+ function natsort() {/**/}
+
+ /** Sort the entries by values using case insensitive "natural order" algorithm.
+ */
+ function natcasesort() {/**/}
+
/** @param $index offset to inspect
* @return whetehr offset $index esists
*/
- function offsetExists($index);
+ function offsetExists($index) {/**/}
/** @param $index offset to return value for
* @return value at offset $index
*/
- function offsetGet($index);
+ function offsetGet($index) {/**/}
/** @param $index index to set
* @param $newval new value to store at offset $index
*/
- function offsetSet($index, $newval);
+ function offsetSet($index, $newval) {/**/}
/** @param $index offset to unset
*/
- function offsetUnset($index);
+ function offsetUnset($index) {/**/}
/** @param $value is appended as last element
* @warning this method cannot be called when the ArrayIterator refers to
* an object.
*/
- function append($value);
+ function append($value) {/**/}
/** @return a \b copy of the array
* @note when the ArrayIterator refers to an object then this method
* returns an array of the public properties.
*/
- function getArrayCopy();
+ function getArrayCopy() {/**/}
/** @param $position offset to seek to
* @throw OutOfBoundsException if $position is invalid
*/
- function seek($position);
+ function seek($position) {/**/}
/** @return the number of elements in the array or the number of public
* properties in the object.
*/
- function count();
+ function count() {/**/}
+
+ /** @copydoc Iterator::rewind */
+ function rewind() {/**/}
+
+ /** @copydoc Iterator::valid */
+ function valid() {/**/}
+
+ /** @copydoc Iterator::current */
+ function current() {/**/}
+
+ /** @copydoc Iterator::key */
+ function key() {/**/}
+
+ /** @copydoc Iterator::next */
+ function next() {/**/}
}
/** @ingroup SPL
@@ -777,95 +840,95 @@ class SplFileInfo
*
* @param $file_name path or file name
*/
- function __construct($file_name);
+ function __construct($file_name) {/**/}
/** @return the path part only.
*/
- function getPath();
+ function getPath() {/**/}
/** @return the filename only.
*/
- function getFilename();
+ function getFilename() {/**/}
/** @return SplFileInfo created for the file
* @param class_name name of class to instantiate
* @see SplFileInfo::setInfoClass()
*/
- function getFileInfo(string class_name = NULL);
+ function getFileInfo(string class_name = NULL) {/**/}
/** @return The current entries path and file name.
*/
- function getPathname();
+ function getPathname() {/**/}
/** @return SplFileInfo created for the path
* @param class_name name of class to instantiate
* @see SplFileInfo::setInfoClass()
*/
- function getPathInfo(string class_name = NULL);
+ function getPathInfo(string class_name = NULL) {/**/}
/** @return The current entry's permissions.
*/
- function getPerms();
+ function getPerms() {/**/}
/** @return The current entry's inode.
*/
- function getInode();
+ function getInode() {/**/}
/** @return The current entry's size in bytes .
*/
- function getSize();
+ function getSize() {/**/}
/** @return The current entry's owner name.
*/
- function getOwner();
+ function getOwner() {/**/}
/** @return The current entry's group name.
*/
- function getGroup();
+ function getGroup() {/**/}
/** @return The current entry's last access time.
*/
- function getATime();
+ function getATime() {/**/}
/** @return The current entry's last modification time.
*/
- function getMTime();
+ function getMTime() {/**/}
/** @return The current entry's last change time.
*/
- function getCTime();
+ function getCTime() {/**/}
/** @return The current entry's size in bytes .
*/
- function getType();
+ function getType() {/**/}
/** @return Whether the current entry is writeable.
*/
- function isWritable();
+ function isWritable() {/**/}
/** @return Whether the current entry is readable.
*/
- function isReadable();
+ function isReadable() {/**/}
/** @return Whether the current entry is executable.
*/
- function isExecutable();
+ function isExecutable() {/**/}
/** @return Whether the current entry is .
*/
- function isFile();
+ function isFile() {/**/}
/** @return Whether the current entry is a directory.
*/
- function isDir();
+ function isDir() {/**/}
/** @return whether the current entry is a link.
*/
- function isLink();
+ function isLink() {/**/}
/** @return getPathname()
*/
- function __toString();
+ function __toString() {/**/}
/** Open the current file as a SplFileObject instance
*
@@ -880,17 +943,17 @@ class SplFileInfo
* @see SplFileInfo::setFileClass()
* @see file()
*/
- function openFile($mode = 'r', $use_include_path = false, $context = NULL);
+ function openFile($mode = 'r', $use_include_path = false, $context = NULL) {/**/}
/** @param class_name name of class used with openFile(). Must be derived
* from SPLFileObject.
*/
- function setFileClass(string class_name = "SplFileObject");
+ function setFileClass(string class_name = "SplFileObject") {/**/}
/** @param class_name name of class used with getFileInfo(), getPathInfo().
- * Must be derived from SplFileInfo.
+ * Must be derived from SplFileInfo.
*/
- function setInfoClass(string class_name = "SplFileInfo");
+ function setInfoClass(string class_name = "SplFileInfo") {/**/}
}
/** @ingroup SPL
@@ -904,27 +967,36 @@ class DirectoryIterator extends SplFileInfo implements Iterator
*
* @param $path directory to iterate.
*/
- function __construct($path);
+ function __construct($path) {/**/}
+ /** @copydoc Iterator::rewind */
+ function rewind() {/**/}
+
+ /** @copydoc Iterator::valid */
+ function valid() {/**/}
+
/** @return index of entry
*/
- function key();
+ function key() {/**/}
/** @return $this
*/
- function current();
+ function current() {/**/}
+
+ /** @copydoc Iterator::next */
+ function next() {/**/}
/** @return Whether the current entry is either '.' or '..'.
*/
- function isDot();
+ function isDot() {/**/}
/** @return whether the current entry is a link.
*/
- function isLink();
+ function isLink() {/**/}
/** @return getFilename()
*/
- function __toString();
+ function __toString() {/**/}
}
/** @ingroup SPL
@@ -946,31 +1018,31 @@ class RecursiveDirectoryIterator extends DirectoryIterator implements RecursiveI
* - KEY_AS_FILENAME
* - NEW_CURRENT_AND_KEY
*/
- function __construct($path, $flags = 0);
+ function __construct($path, $flags = 0) {/**/}
/** @return getPathname() or getFilename() depending on flags
*/
- function key();
+ function key() {/**/}
/** @return getFilename() or getFileInfo() depending on flags
*/
- function current();
+ function current() {/**/}
/** @return whether the current is a directory (not '.' or '..').
*/
- function hasChildren();
+ function hasChildren() {/**/}
/** @return a RecursiveDirectoryIterator for the current entry.
*/
- function getChildren();
+ function getChildren() {/**/}
/** @return sub path only (without main path)
*/
- function getSubPath();
+ function getSubPath() {/**/}
/** @return the current sub path
*/
- function getSubPathname();
+ function getSubPathname() {/**/}
}
/** @ingroup SPL
@@ -984,15 +1056,34 @@ class RecursiveDirectoryIterator extends DirectoryIterator implements RecursiveI
* has subelements, hasChildren() returns true. This will trigger a call to
* getChildren() which returns the iterator for that sub element.
*/
-class SimpleXMLIterator extends SimpleXMLElement implements RecursiveIterator
+class SimpleXMLIterator extends SimpleXMLElement implements RecursiveIterator, Countable
{
/** @return whether the current node has sub nodes.
*/
- function hasChildren();
+ function hasChildren() {/**/}
/** @return a SimpleXMLIterator for the current node.
*/
- function getChildren();
+ function getChildren() {/**/}
+
+ /** @return number of elements/attributes seen with foreach()
+ */
+ function count() {/**/}
+
+ /** @copydoc Iterator::rewind */
+ function rewind() {/**/}
+
+ /** @copydoc Iterator::valid */
+ function valid() {/**/}
+
+ /** @copydoc Iterator::current */
+ function current() {/**/}
+
+ /** @copydoc Iterator::key */
+ function key() {/**/}
+
+ /** @copydoc Iterator::next */
+ function next() {/**/}
}
/** @ingroup SPL
diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c
index 294bc12126..b62e404f3a 100755
--- a/ext/spl/spl_iterators.c
+++ b/ext/spl/spl_iterators.c
@@ -996,12 +996,20 @@ static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, z
char *regex;
int len, poptions, coptions;
pcre_extra *extra = NULL;
+ long mode = REGIT_MODE_MATCH;
intern->u.regex.flags = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|l", &zobject, ce_inner, &regex, &len, &intern->u.regex.flags) == FAILURE) {
+ intern->u.regex.preg_flags = 0;
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|lll", &zobject, ce_inner, &regex, &len, &intern->u.regex.flags, &mode, &intern->u.regex.preg_flags) == FAILURE) {
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
return NULL;
}
+ if (mode < 0 || mode >= REGIT_MODE_MAX) {
+ zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Illegal mode %ld", mode);
+ php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
+ return NULL;
+ }
+ intern->u.regex.mode = mode;
intern->u.regex.regex = estrndup(regex, len);
intern->u.regex.pce = pcre_get_compiled_regex_cache(regex, len, &extra, &poptions, &coptions TSRMLS_CC);
intern->u.regex.pce->refcount++;
@@ -1357,7 +1365,7 @@ SPL_METHOD(ParentIterator, getChildren)
} /* }}} */
#if HAVE_PCRE || HAVE_BUNDLED_PCRE
-/* {{{ proto void RegexIterator::__construct(Iterator it, string $regex [, int $flags])
+/* {{{ proto void RegexIterator::__construct(Iterator it, string regex [, int flags [, int mode [, int preg_flags]]])
Create an RegexIterator from another iterator and a regular expression */
SPL_METHOD(RegexIterator, __construct)
{
@@ -1368,22 +1376,22 @@ SPL_METHOD(RegexIterator, __construct)
Match (string)current() against regular expression */
SPL_METHOD(RegexIterator, accept)
{
- spl_dual_it_object *intern;
- int count;
- char *subject, tmp[32];
- int subject_len, use_copy = 0;
- zval subject_copy;
- pcre_extra *extra;
+ spl_dual_it_object *intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+ char *subject, tmp[32];
+ int subject_len, use_copy, count;
+ zval subject_copy, zcount;
+ pcre *regex = intern->u.regex.pce->re;
+ pcre_extra *extra = intern->u.regex.pce->extra;
- intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
-
if (intern->u.regex.flags & REGIT_USE_KEY) {
if (intern->current.key_type == HASH_KEY_IS_LONG) {
subject_len = snprintf(tmp, sizeof(tmp), "%ld", intern->current.int_key);
subject = &tmp[0];
+ use_copy = 0;
} else {
- subject_len = intern->current.str_key_len;
- subject = intern->current.str_key;
+ subject_len = intern->current.str_key_len - 1;
+ subject = estrndup(intern->current.str_key, subject_len);
+ use_copy = 1;
}
} else {
zend_make_printable_zval(intern->current.data, &subject_copy, &use_copy);
@@ -1396,17 +1404,49 @@ SPL_METHOD(RegexIterator, accept)
}
}
- extra = intern->u.regex.pce->extra;
- count = pcre_exec(intern->u.regex.pce->re, extra, subject, subject_len, 0, 0, NULL, 0);
+ switch (intern->u.regex.mode)
+ {
+ case REGIT_MODE_MAX: /* won't happen but makes compiler happy */
+ case REGIT_MODE_MATCH:
+ count = pcre_exec(regex, extra, subject, subject_len, 0, 0, NULL, 0);
+ RETVAL_BOOL(count >= 0);
+ break;
- if (use_copy) {
- zval_dtor(&subject_copy);
+ case REGIT_MODE_ALL_MATCHES:
+ case REGIT_MODE_GET_MATCH:
+ if (!use_copy) {
+ subject = estrndup(subject, subject_len);
+ use_copy = 1;
+ }
+ zval_ptr_dtor(&intern->current.data);
+ MAKE_STD_ZVAL(intern->current.data);
+ array_init(intern->current.data);
+ php_pcre_match(regex, extra, subject, subject_len, &zcount,
+ intern->current.data, intern->u.regex.mode == REGIT_MODE_ALL_MATCHES, 0, 0, 0, 0 TSRMLS_CC);
+ count = zend_hash_num_elements(Z_ARRVAL_P(intern->current.data));
+ RETVAL_BOOL(count > 0);
+ break;
+
+ case REGIT_MODE_SPLIT:
+ if (!use_copy) {
+ subject = estrndup(subject, subject_len);
+ use_copy = 1;
+ }
+ zval_ptr_dtor(&intern->current.data);
+ MAKE_STD_ZVAL(intern->current.data);
+ array_init(intern->current.data);
+ php_pcre_split(regex, extra, subject, subject_len, intern->current.data, 0, -1, 0, 0, 0 TSRMLS_CC);
+ count = zend_hash_num_elements(Z_ARRVAL_P(intern->current.data));
+ RETVAL_BOOL(count > 1);
+ break;
}
- RETURN_BOOL(count >= 0);
+ if (use_copy) {
+ efree(subject);
+ }
} /* }}} */
-/* {{{ proto void RecursiveRegexIterator::__construct(RecursiveIterator it, string $regex [, int $flags])
+/* {{{ proto void RecursiveRegexIterator::__construct(RecursiveIterator it, string regex [, int flags [, int mode [, int preg_flags]]])
Create an RecursiveRegexIterator from another recursive iterator and a regular expression */
SPL_METHOD(RecursiveRegexIterator, __construct)
{
@@ -1547,6 +1587,8 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_regex_it___construct, 0, 0, 2)
ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
ZEND_ARG_INFO(0, regex)
ZEND_ARG_INFO(0, flags)
+ ZEND_ARG_INFO(0, mode)
+ ZEND_ARG_INFO(0, preg_flags)
ZEND_END_ARG_INFO();
static zend_function_entry spl_funcs_RegexIterator[] = {
@@ -2734,7 +2776,11 @@ PHP_MINIT_FUNCTION(spl_iterators)
REGISTER_SPL_SUB_CLASS_EX(InfiniteIterator, IteratorIterator, spl_dual_it_new, spl_funcs_InfiniteIterator);
#if HAVE_PCRE || HAVE_BUNDLED_PCRE
REGISTER_SPL_SUB_CLASS_EX(RegexIterator, FilterIterator, spl_dual_it_new, spl_funcs_RegexIterator);
- REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "USE_KEY", REGIT_USE_KEY);
+ REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "USE_KEY", REGIT_USE_KEY);
+ REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "MATCH", REGIT_MODE_MATCH);
+ REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "GET_MATCH", REGIT_MODE_GET_MATCH);
+ REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "ALL_MATCHES", REGIT_MODE_ALL_MATCHES);
+ REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "SPLIT", REGIT_MODE_SPLIT);
REGISTER_SPL_SUB_CLASS_EX(RecursiveRegexIterator, RegexIterator, spl_dual_it_new, spl_funcs_RecursiveRegexIterator);
REGISTER_SPL_IMPLEMENTS(RecursiveRegexIterator, RecursiveIterator);
#else
diff --git a/ext/spl/spl_iterators.h b/ext/spl/spl_iterators.h
index af4eccd8ff..c2ee24949c 100755
--- a/ext/spl/spl_iterators.h
+++ b/ext/spl/spl_iterators.h
@@ -95,6 +95,14 @@ enum {
REGIT_USE_KEY = 0x00000001,
};
+typedef enum {
+ REGIT_MODE_MATCH,
+ REGIT_MODE_GET_MATCH,
+ REGIT_MODE_ALL_MATCHES,
+ REGIT_MODE_SPLIT,
+ REGIT_MODE_MAX,
+} regex_mode;
+
typedef struct _spl_dual_it_object {
zend_object std;
struct {
@@ -130,6 +138,8 @@ typedef struct _spl_dual_it_object {
#if HAVE_PCRE || HAVE_BUNDLED_PCRE
struct {
int flags;
+ regex_mode mode;
+ long preg_flags;
pcre_cache_entry *pce;
char *regex;
} regex;
diff --git a/ext/spl/tests/iterator_049.phpt b/ext/spl/tests/iterator_049.phpt
new file mode 100755
index 0000000000..9a5d4029f8
--- /dev/null
+++ b/ext/spl/tests/iterator_049.phpt
@@ -0,0 +1,24 @@
+--TEST--
+SPL: ArrayIterator with NULL key
+--SKIPIF--
+<?php if (!extension_loaded("spl")) print "skip"; ?>
+--FILE--
+<?php
+
+$ar = new ArrayIterator(array(NULL=>NULL));
+var_dump($ar);
+var_dump($ar->getArrayCopy());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+object(ArrayIterator)#1 (1) {
+ [""]=>
+ NULL
+}
+array(1) {
+ [""]=>
+ NULL
+}
+===DONE===
diff --git a/ext/spl/tests/iterator_050.phpt b/ext/spl/tests/iterator_050.phpt
new file mode 100755
index 0000000000..983dfa4573
--- /dev/null
+++ b/ext/spl/tests/iterator_050.phpt
@@ -0,0 +1,93 @@
+--TEST--
+SPL: RegexIterator::GET_MATCH
+--SKIPIF--
+<?php if (!extension_loaded("spl")) print "skip"; ?>
+--FILE--
+<?php
+
+class MyRegexIterator extends RegexIterator
+{
+ function show()
+ {
+ foreach($this as $k => $v)
+ {
+ var_dump($k);
+ var_dump($v);
+ }
+ }
+}
+
+$ar = new ArrayIterator(array('1','1,2','1,2,3','',NULL,array(),'FooBar',',',',,'));
+$it = new MyRegexIterator($ar, '/(\d),(\d)/', 0, RegexIterator::GET_MATCH);
+$it->show();
+
+$it = new MyRegexIterator($ar, '/(\d)/', 0, RegexIterator::GET_MATCH);
+$it->show();
+
+var_dump($ar);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+int(1)
+array(3) {
+ [0]=>
+ string(3) "1,2"
+ [1]=>
+ string(1) "1"
+ [2]=>
+ string(1) "2"
+}
+int(2)
+array(3) {
+ [0]=>
+ string(3) "1,2"
+ [1]=>
+ string(1) "1"
+ [2]=>
+ string(1) "2"
+}
+int(0)
+array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+}
+int(1)
+array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+}
+int(2)
+array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+}
+object(ArrayIterator)#%d (9) {
+ [0]=>
+ %s(1) "1"
+ [1]=>
+ %s(3) "1,2"
+ [2]=>
+ %s(5) "1,2,3"
+ [3]=>
+ %s(0) ""
+ [4]=>
+ NULL
+ [5]=>
+ array(0) {
+ }
+ [6]=>
+ %s(6) "FooBar"
+ [7]=>
+ %s(1) ","
+ [8]=>
+ %s(2) ",,"
+}
+===DONE===
diff --git a/ext/spl/tests/iterator_051.phpt b/ext/spl/tests/iterator_051.phpt
new file mode 100755
index 0000000000..d396612ca6
--- /dev/null
+++ b/ext/spl/tests/iterator_051.phpt
@@ -0,0 +1,159 @@
+--TEST--
+SPL: RegexIterator::GET_MATCH, USE_KEY
+--SKIPIF--
+<?php if (!extension_loaded("spl")) print "skip"; ?>
+--FILE--
+<?php
+
+class MyRegexIterator extends RegexIterator
+{
+ function show()
+ {
+ foreach($this as $k => $v)
+ {
+ var_dump($k);
+ var_dump($v);
+ }
+ }
+}
+
+$ar = new ArrayIterator(array('1'=>0,'1,2'=>1,'1,2,3'=>2,0=>3,'FooBar'=>4,','=>5,',,'=>6));
+$it = new MyRegexIterator($ar, '/(\d),(\d)/', RegexIterator::USE_KEY, RegexIterator::GET_MATCH);
+$it->show();
+
+$it = new MyRegexIterator($ar, '/(\d)/', RegexIterator::USE_KEY, RegexIterator::GET_MATCH);
+$it->show();
+
+var_dump($ar);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+string(3) "1,2"
+array(3) {
+ [0]=>
+ string(3) "1,2"
+ [1]=>
+ string(1) "1"
+ [2]=>
+ string(1) "2"
+}
+string(5) "1,2,3"
+array(3) {
+ [0]=>
+ string(3) "1,2"
+ [1]=>
+ string(1) "1"
+ [2]=>
+ string(1) "2"
+}
+int(1)
+array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+}
+string(3) "1,2"
+array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+}
+string(5) "1,2,3"
+array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+}
+int(0)
+array(2) {
+ [0]=>
+ string(1) "0"
+ [1]=>
+ string(1) "0"
+}
+object(ArrayIterator)#%d (7) {
+ [1]=>
+ int(0)
+ ["1,2"]=>
+ int(1)
+ ["1,2,3"]=>
+ int(2)
+ [0]=>
+ int(3)
+ ["FooBar"]=>
+ int(4)
+ [","]=>
+ int(5)
+ [",,"]=>
+ int(6)
+}
+===DONE===
+--UEXPECTF--
+unicode(3) "1,2"
+array(3) {
+ [0]=>
+ string(3) "1,2"
+ [1]=>
+ string(1) "1"
+ [2]=>
+ string(1) "2"
+}
+unicode(5) "1,2,3"
+array(3) {
+ [0]=>
+ string(3) "1,2"
+ [1]=>
+ string(1) "1"
+ [2]=>
+ string(1) "2"
+}
+int(1)
+array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+}
+unicode(3) "1,2"
+array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+}
+unicode(5) "1,2,3"
+array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+}
+int(0)
+array(2) {
+ [0]=>
+ string(1) "0"
+ [1]=>
+ string(1) "0"
+}
+object(ArrayIterator)#%d (7) {
+ [1]=>
+ int(0)
+ [u"1,2"]=>
+ int(1)
+ [u"1,2,3"]=>
+ int(2)
+ [0]=>
+ int(3)
+ [u"FooBar"]=>
+ int(4)
+ [u","]=>
+ int(5)
+ [u",,"]=>
+ int(6)
+}
+===DONE===
diff --git a/ext/spl/tests/iterator_052.phpt b/ext/spl/tests/iterator_052.phpt
new file mode 100755
index 0000000000..574868bd65
--- /dev/null
+++ b/ext/spl/tests/iterator_052.phpt
@@ -0,0 +1,129 @@
+--TEST--
+SPL: RegexIterator::ALL_MATCHES
+--SKIPIF--
+<?php if (!extension_loaded("spl")) print "skip"; ?>
+--FILE--
+<?php
+
+class MyRegexIterator extends RegexIterator
+{
+ function show()
+ {
+ foreach($this as $k => $v)
+ {
+ var_dump($k);
+ var_dump($v);
+ }
+ }
+}
+
+$ar = new ArrayIterator(array('1','1,2','1,2,3','',NULL,array(),'FooBar',',',',,'));
+$it = new MyRegexIterator($ar, '/(\d),(\d)/', 0, RegexIterator::ALL_MATCHES);
+$it->show();
+
+$it = new MyRegexIterator($ar, '/(\d)/', 0, RegexIterator::ALL_MATCHES);
+$it->show();
+
+var_dump($ar);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+int(1)
+array(1) {
+ [0]=>
+ array(3) {
+ [0]=>
+ string(3) "1,2"
+ [1]=>
+ string(1) "1"
+ [2]=>
+ string(1) "2"
+ }
+}
+int(2)
+array(1) {
+ [0]=>
+ array(3) {
+ [0]=>
+ string(3) "1,2"
+ [1]=>
+ string(1) "1"
+ [2]=>
+ string(1) "2"
+ }
+}
+int(0)
+array(1) {
+ [0]=>
+ array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ }
+}
+int(1)
+array(2) {
+ [0]=>
+ array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ }
+ [1]=>
+ array(2) {
+ [0]=>
+ string(1) "2"
+ [1]=>
+ string(1) "2"
+ }
+}
+int(2)
+array(3) {
+ [0]=>
+ array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ }
+ [1]=>
+ array(2) {
+ [0]=>
+ string(1) "2"
+ [1]=>
+ string(1) "2"
+ }
+ [2]=>
+ array(2) {
+ [0]=>
+ string(1) "3"
+ [1]=>
+ string(1) "3"
+ }
+}
+object(ArrayIterator)#%d (9) {
+ [0]=>
+ %s(1) "1"
+ [1]=>
+ %s(3) "1,2"
+ [2]=>
+ %s(5) "1,2,3"
+ [3]=>
+ %s(0) ""
+ [4]=>
+ NULL
+ [5]=>
+ array(0) {
+ }
+ [6]=>
+ %s(6) "FooBar"
+ [7]=>
+ %s(1) ","
+ [8]=>
+ %s(2) ",,"
+}
+===DONE===
diff --git a/ext/spl/tests/iterator_053.phpt b/ext/spl/tests/iterator_053.phpt
new file mode 100755
index 0000000000..bc4b1440d6
--- /dev/null
+++ b/ext/spl/tests/iterator_053.phpt
@@ -0,0 +1,237 @@
+--TEST--
+SPL: RegexIterator::ALL_MATCHES, USE_KEY
+--SKIPIF--
+<?php if (!extension_loaded("spl")) print "skip"; ?>
+--FILE--
+<?php
+
+class MyRegexIterator extends RegexIterator
+{
+ function show()
+ {
+ foreach($this as $k => $v)
+ {
+ var_dump($k);
+ var_dump($v);
+ }
+ }
+}
+
+$ar = new ArrayIterator(array('1'=>0,'1,2'=>1,'1,2,3'=>2,0=>3,'FooBar'=>4,','=>5,',,'=>6));
+$it = new MyRegexIterator($ar, '/(\d),(\d)/', RegexIterator::USE_KEY, RegexIterator::ALL_MATCHES);
+$it->show();
+
+$it = new MyRegexIterator($ar, '/(\d)/', RegexIterator::USE_KEY, RegexIterator::ALL_MATCHES);
+$it->show();
+
+var_dump($ar);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+string(3) "1,2"
+array(1) {
+ [0]=>
+ array(3) {
+ [0]=>
+ string(3) "1,2"
+ [1]=>
+ string(1) "1"
+ [2]=>
+ string(1) "2"
+ }
+}
+string(5) "1,2,3"
+array(1) {
+ [0]=>
+ array(3) {
+ [0]=>
+ string(3) "1,2"
+ [1]=>
+ string(1) "1"
+ [2]=>
+ string(1) "2"
+ }
+}
+int(1)
+array(1) {
+ [0]=>
+ array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ }
+}
+string(3) "1,2"
+array(2) {
+ [0]=>
+ array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ }
+ [1]=>
+ array(2) {
+ [0]=>
+ string(1) "2"
+ [1]=>
+ string(1) "2"
+ }
+}
+string(5) "1,2,3"
+array(3) {
+ [0]=>
+ array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ }
+ [1]=>
+ array(2) {
+ [0]=>
+ string(1) "2"
+ [1]=>
+ string(1) "2"
+ }
+ [2]=>
+ array(2) {
+ [0]=>
+ string(1) "3"
+ [1]=>
+ string(1) "3"
+ }
+}
+int(0)
+array(1) {
+ [0]=>
+ array(2) {
+ [0]=>
+ string(1) "0"
+ [1]=>
+ string(1) "0"
+ }
+}
+object(ArrayIterator)#%d (7) {
+ [1]=>
+ int(0)
+ ["1,2"]=>
+ int(1)
+ ["1,2,3"]=>
+ int(2)
+ [0]=>
+ int(3)
+ ["FooBar"]=>
+ int(4)
+ [","]=>
+ int(5)
+ [",,"]=>
+ int(6)
+}
+===DONE===
+--UEXPECTF--
+unicode(3) "1,2"
+array(1) {
+ [0]=>
+ array(3) {
+ [0]=>
+ string(3) "1,2"
+ [1]=>
+ string(1) "1"
+ [2]=>
+ string(1) "2"
+ }
+}
+unicode(5) "1,2,3"
+array(1) {
+ [0]=>
+ array(3) {
+ [0]=>
+ string(3) "1,2"
+ [1]=>
+ string(1) "1"
+ [2]=>
+ string(1) "2"
+ }
+}
+int(1)
+array(1) {
+ [0]=>
+ array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ }
+}
+unicode(3) "1,2"
+array(2) {
+ [0]=>
+ array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ }
+ [1]=>
+ array(2) {
+ [0]=>
+ string(1) "2"
+ [1]=>
+ string(1) "2"
+ }
+}
+unicode(5) "1,2,3"
+array(3) {
+ [0]=>
+ array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ }
+ [1]=>
+ array(2) {
+ [0]=>
+ string(1) "2"
+ [1]=>
+ string(1) "2"
+ }
+ [2]=>
+ array(2) {
+ [0]=>
+ string(1) "3"
+ [1]=>
+ string(1) "3"
+ }
+}
+int(0)
+array(1) {
+ [0]=>
+ array(2) {
+ [0]=>
+ string(1) "0"
+ [1]=>
+ string(1) "0"
+ }
+}
+object(ArrayIterator)#%d (7) {
+ [1]=>
+ int(0)
+ [u"1,2"]=>
+ int(1)
+ [u"1,2,3"]=>
+ int(2)
+ [0]=>
+ int(3)
+ [u"FooBar"]=>
+ int(4)
+ [u","]=>
+ int(5)
+ [u",,"]=>
+ int(6)
+}
+===DONE===
diff --git a/ext/spl/tests/iterator_054.phpt b/ext/spl/tests/iterator_054.phpt
new file mode 100755
index 0000000000..b3aaf4f45f
--- /dev/null
+++ b/ext/spl/tests/iterator_054.phpt
@@ -0,0 +1,84 @@
+--TEST--
+SPL: RegexIterator::SPLIT
+--SKIPIF--
+<?php if (!extension_loaded("spl")) print "skip"; ?>
+--FILE--
+<?php
+
+class MyRegexIterator extends RegexIterator
+{
+ function show()
+ {
+ foreach($this as $k => $v)
+ {
+ var_dump($k);
+ var_dump($v);
+ }
+ }
+}
+
+$ar = new ArrayIterator(array('1','1,2','1,2,3','',NULL,array(),'FooBar',',',',,'));
+$it = new MyRegexIterator($ar, '/,/', 0, RegexIterator::SPLIT);
+
+$it->show();
+
+var_dump($ar);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+int(1)
+array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "2"
+}
+int(2)
+array(3) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "2"
+ [2]=>
+ string(1) "3"
+}
+int(7)
+array(2) {
+ [0]=>
+ string(0) ""
+ [1]=>
+ string(0) ""
+}
+int(8)
+array(3) {
+ [0]=>
+ string(0) ""
+ [1]=>
+ string(0) ""
+ [2]=>
+ string(0) ""
+}
+object(ArrayIterator)#%d (9) {
+ [0]=>
+ %s(1) "1"
+ [1]=>
+ %s(3) "1,2"
+ [2]=>
+ %s(5) "1,2,3"
+ [3]=>
+ %s(0) ""
+ [4]=>
+ NULL
+ [5]=>
+ array(0) {
+ }
+ [6]=>
+ %s(6) "FooBar"
+ [7]=>
+ %s(1) ","
+ [8]=>
+ %s(2) ",,"
+}
+===DONE===
diff --git a/ext/spl/tests/iterator_055.phpt b/ext/spl/tests/iterator_055.phpt
new file mode 100755
index 0000000000..9d881a1129
--- /dev/null
+++ b/ext/spl/tests/iterator_055.phpt
@@ -0,0 +1,93 @@
+--TEST--
+SPL: RegexIterator::SPLIT, USE_KEY
+--SKIPIF--
+<?php if (!extension_loaded("spl")) print "skip"; ?>
+--FILE--
+<?php
+
+class MyRegexIterator extends RegexIterator
+{
+ function show()
+ {
+ foreach($this as $k => $v)
+ {
+ var_dump($k);
+ var_dump($v);
+ }
+ }
+}
+
+$ar = new ArrayIterator(array('1'=>0,'1,2'=>1,'1,2,3'=>2,0=>3,'FooBar'=>4,','=>5,',,'=>6));
+$it = new MyRegexIterator($ar, '/(\d),(\d)/', RegexIterator::USE_KEY, RegexIterator::SPLIT);
+
+$it->show();
+
+var_dump($ar);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+string(3) "1,2"
+array(2) {
+ [0]=>
+ string(0) ""
+ [1]=>
+ string(0) ""
+}
+string(5) "1,2,3"
+array(2) {
+ [0]=>
+ string(0) ""
+ [1]=>
+ string(2) ",3"
+}
+object(ArrayIterator)#%d (7) {
+ [1]=>
+ int(0)
+ ["1,2"]=>
+ int(1)
+ ["1,2,3"]=>
+ int(2)
+ [0]=>
+ int(3)
+ ["FooBar"]=>
+ int(4)
+ [","]=>
+ int(5)
+ [",,"]=>
+ int(6)
+}
+===DONE===
+--UEXPECTF--
+unicode(3) "1,2"
+array(2) {
+ [0]=>
+ string(0) ""
+ [1]=>
+ string(0) ""
+}
+unicode(5) "1,2,3"
+array(2) {
+ [0]=>
+ string(0) ""
+ [1]=>
+ string(2) ",3"
+}
+object(ArrayIterator)#%d (7) {
+ [1]=>
+ int(0)
+ [u"1,2"]=>
+ int(1)
+ [u"1,2,3"]=>
+ int(2)
+ [0]=>
+ int(3)
+ [u"FooBar"]=>
+ int(4)
+ [u","]=>
+ int(5)
+ [u",,"]=>
+ int(6)
+}
+===DONE===