]> granicus.if.org Git - php/commitdiff
- MFH:
authorMarcus Boerger <helly@php.net>
Sun, 16 Jul 2006 21:12:32 +0000 (21:12 +0000)
committerMarcus Boerger <helly@php.net>
Sun, 16 Jul 2006 21:12:32 +0000 (21:12 +0000)
  . Upgrade RegexIterator capabilities, see docu
  . Update docu
  . Add test (which fails right now: iterator_049.phpt)
  . Add tests for new functionality

13 files changed:
ext/spl/internal/filteriterator.inc
ext/spl/internal/recursiveregexiterator.inc [new file with mode: 0755]
ext/spl/internal/regexiterator.inc [new file with mode: 0755]
ext/spl/spl.php
ext/spl/spl_iterators.c
ext/spl/spl_iterators.h
ext/spl/tests/iterator_049.phpt [new file with mode: 0755]
ext/spl/tests/iterator_050.phpt [new file with mode: 0755]
ext/spl/tests/iterator_051.phpt [new file with mode: 0755]
ext/spl/tests/iterator_052.phpt [new file with mode: 0755]
ext/spl/tests/iterator_053.phpt [new file with mode: 0755]
ext/spl/tests/iterator_054.phpt [new file with mode: 0755]
ext/spl/tests/iterator_055.phpt [new file with mode: 0755]

index cc9c999a4041cb2a89587509fc3b0a606c3f4eba..9820d48318e7fcc41c7b48bd944a7a5cef14f80b 100755 (executable)
@@ -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 (executable)
index 0000000..caaee97
--- /dev/null
@@ -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 (executable)
index 0000000..84ebf98
--- /dev/null
@@ -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
index f704e044bad6cadbd6fa7f7bd8a7e45abc61de81..625042f72dcf29a57c2d462db95be45a6eb74a80 100755 (executable)
@@ -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
  * 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
  * @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
index 294bc12126178c25f9ee897f62ffcceacbaeeaa9..b62e404f3ae3f69533792a34c638bd97bccc7cb1 100755 (executable)
@@ -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
index af4eccd8ffb536f08bff4a0edbd076e17737f938..c2ee24949c8af9992922d6e7f39abde54e06c74c 100755 (executable)
@@ -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 (executable)
index 0000000..9a5d402
--- /dev/null
@@ -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 (executable)
index 0000000..983dfa4
--- /dev/null
@@ -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 (executable)
index 0000000..d396612
--- /dev/null
@@ -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 (executable)
index 0000000..574868b
--- /dev/null
@@ -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 (executable)
index 0000000..bc4b144
--- /dev/null
@@ -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 (executable)
index 0000000..b3aaf4f
--- /dev/null
@@ -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 (executable)
index 0000000..9d881a1
--- /dev/null
@@ -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===