]> granicus.if.org Git - php/commitdiff
- Implement classes IteratorIterator and NoRewindIterator in C
authorMarcus Boerger <helly@php.net>
Sun, 31 Oct 2004 18:43:00 +0000 (18:43 +0000)
committerMarcus Boerger <helly@php.net>
Sun, 31 Oct 2004 18:43:00 +0000 (18:43 +0000)
ext/spl/internal/iteratoriterator.inc [moved from ext/spl/examples/iteratoriterator.inc with 86% similarity]
ext/spl/internal/norewinditerator.inc [moved from ext/spl/examples/norewinditerator.inc with 84% similarity]
ext/spl/php_spl.c
ext/spl/spl_iterators.c
ext/spl/spl_iterators.h
ext/spl/tests/array_014.phpt
ext/spl/tests/iterator_005.phpt [new file with mode: 0755]
ext/spl/tests/iterator_006.phpt [new file with mode: 0755]
ext/spl/tests/iterator_007.phpt [new file with mode: 0755]

similarity index 86%
rename from ext/spl/examples/iteratoriterator.inc
rename to ext/spl/internal/iteratoriterator.inc
index 8ed8c6fcd712492a71aad4901384cf737b9163e8..03cbc9f8762c06125a7a630fe09ffbcbeeb02607 100755 (executable)
@@ -1,7 +1,16 @@
 <?php
 
-/** \ingroup SPL
- * \brief Basic Iterator wrapper
+/** @file iteratoriterator.inc
+ * @ingroup SPL
+ * @brief class IteratorIterator
+ * @author  Marcus Boerger
+ * @date    2003 - 2004
+ *
+ * SPL - Standard PHP Library
+ */
+
+/** @ingroup SPL
+ * @brief Basic Iterator wrapper
  */
 class IteratorIterator implements OuterIterator
 {
similarity index 84%
rename from ext/spl/examples/norewinditerator.inc
rename to ext/spl/internal/norewinditerator.inc
index dbf69c5531bbff5004e2df5af393faf0152d4ef2..32e89da50ecb13eadf3c7673836fef223d7e18a8 100755 (executable)
@@ -1,7 +1,7 @@
 <?php
 
 /** @file norewinditerator.inc
- * @ingroup Examples
+ * @ingroup SPL
  * @brief class NoRewindIterator
  * @author  Marcus Boerger
  * @date    2003 - 2004
@@ -10,7 +10,7 @@
  */
 
 /** @ingroup Examples
- * @brief   An Iterator that doesn't call rewind
+ * @brief   An Iterator wrapper that doesn't call rewind
  * @author  Marcus Boerger
  * @version 1.1
  *
index d8a298676c2a72840a5d7d7de975f71840cf9ca8..b0011106b196194c7f20864c67c70640436a71f9 100755 (executable)
@@ -167,7 +167,9 @@ PHP_FUNCTION(class_implements)
        SPL_ADD_CLASS(CachingRecursiveIterator, z_list, sub, allow, ce_flags); \
        SPL_ADD_CLASS(DirectoryIterator, z_list, sub, allow, ce_flags); \
        SPL_ADD_CLASS(FilterIterator, z_list, sub, allow, ce_flags); \
+       SPL_ADD_CLASS(IteratorIterator, z_list, sub, allow, ce_flags); \
        SPL_ADD_CLASS(LimitIterator, z_list, sub, allow, ce_flags); \
+       SPL_ADD_CLASS(NoRewindIterator, z_list, sub, allow, ce_flags); \
        SPL_ADD_CLASS(OuterIterator, z_list, sub, allow, ce_flags); \
        SPL_ADD_CLASS(ParentIterator, z_list, sub, allow, ce_flags); \
        SPL_ADD_CLASS(RecursiveDirectoryIterator, z_list, sub, allow, ce_flags); \
index 0ce034f4c3aab61b260fed6fbd3b6f6299024e94..59edd2208b11c48f265f672eecf4bef183da6a75 100755 (executable)
@@ -45,6 +45,8 @@ zend_class_entry *spl_ce_LimitIterator;
 zend_class_entry *spl_ce_CachingIterator;
 zend_class_entry *spl_ce_CachingRecursiveIterator;
 zend_class_entry *spl_ce_OuterIterator;
+zend_class_entry *spl_ce_IteratorIterator;
+zend_class_entry *spl_ce_NoRewindIterator;
 
 function_entry spl_funcs_RecursiveIterator[] = {
        SPL_ABSTRACT_ME(RecursiveIterator, hasChildren,  NULL)
@@ -565,6 +567,8 @@ int spl_dual_it_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
 }
 #endif
 
+static INLINE int spl_dual_it_fetch(spl_dual_it_object *intern, int check_more TSRMLS_DC);
+
 static INLINE spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *ce_inner, dual_it_type dit_type)
 {
        zval                 *zobject;
@@ -605,6 +609,22 @@ static INLINE spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAME
                        intern->u.caching.flags |= flags & CIT_PUBLIC;
                        break;
                }
+               case DIT_IteratorIterator: {
+                       zend_class_entry *ce;
+
+                       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zobject, ce_inner) == FAILURE) {
+                               php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
+                               return NULL;
+                       }
+                       ce = Z_OBJCE_P(zobject);
+                       if (!instanceof_function(ce, zend_ce_iterator TSRMLS_CC)) {
+                               if (instanceof_function(ce, zend_ce_aggregate TSRMLS_CC)) {
+                                       zval *retval;
+                                       zobject = zend_call_method_with_0_params(&zobject, ce, &ce->iterator_funcs.zf_new_iterator, "getiterator", &retval);
+                               }
+                       }
+                       break;
+               }
                default:
                        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zobject, ce_inner) == FAILURE) {
                                php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
@@ -728,6 +748,7 @@ static INLINE void spl_dual_it_next(spl_dual_it_object *intern, int do_free TSRM
 }
 
 /* {{{ proto void ParentIterator::rewind()
+       proto void IteratorIterator::rewind()
    Rewind the iterator
    */
 SPL_METHOD(dual_it, rewind)
@@ -741,6 +762,8 @@ SPL_METHOD(dual_it, rewind)
 
 /* {{{ proto boolean FilterIterator::valid()
        proto boolean ParentIterator::valid()
+       proto boolean IteratorIterator::valid()
+       proto boolean NoRewindIterator::valid()
    Check whether the current element is valid */
 SPL_METHOD(dual_it, valid)
 {
@@ -755,6 +778,8 @@ SPL_METHOD(dual_it, valid)
        proto mixed CachingIterator::key()
        proto mixed LimitIterator::key()
        proto mixed ParentIterator::key()
+       proto mixed IteratorIterator::key()
+       proto mixed NoRewindIterator::key()
    Get the current key */
 SPL_METHOD(dual_it, key)
 {
@@ -776,6 +801,8 @@ SPL_METHOD(dual_it, key)
        proto mixed CachingIterator::current()
        proto mixed LimitIterator::current()
        proto mixed ParentIterator::current()
+       proto mixed IteratorIterator::current()
+       proto mixed NoRewindIterator::current()
    Get the current element value */
 SPL_METHOD(dual_it, current)
 {
@@ -791,6 +818,8 @@ SPL_METHOD(dual_it, current)
 } /* }}} */
 
 /* {{{ proto void ParentIterator::next()
+       proto void IteratorIterator::next()
+       proto void NoRewindIterator::next()
    Move the iterator forward */
 SPL_METHOD(dual_it, next)
 {
@@ -1273,7 +1302,7 @@ SPL_METHOD(CachingIterator, __toString)
 static
 ZEND_BEGIN_ARG_INFO(arginfo_caching_it___construct, 0) 
        ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
-       ZEND_ARG_INFO(0, getStrVal)
+       ZEND_ARG_INFO(0, flags)
 ZEND_END_ARG_INFO();
 
 static zend_function_entry spl_funcs_CachingIterator[] = {
@@ -1325,8 +1354,7 @@ SPL_METHOD(CachingRecursiveIterator, getChildren)
 static
 ZEND_BEGIN_ARG_INFO_EX(arginfo_caching_rec_it___construct, 0, ZEND_RETURN_REFERENCE_AGNOSTIC, 2) 
        ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
-       ZEND_ARG_INFO(0, getStrVal)
-       ZEND_ARG_INFO(0, catch_getChildren)
+       ZEND_ARG_INFO(0, flags)
 ZEND_END_ARG_INFO();
 
 static zend_function_entry spl_funcs_CachingRecursiveIterator[] = {
@@ -1336,6 +1364,65 @@ static zend_function_entry spl_funcs_CachingRecursiveIterator[] = {
        {NULL, NULL, NULL}
 };
 
+/* {{{ proto IteratorIterator::__construct(Traversable it)
+   Create an iterator from anything that is traversable */
+SPL_METHOD(IteratorIterator, __construct)
+{
+       spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, zend_ce_traversable, DIT_IteratorIterator);
+} /* }}} */
+
+static
+ZEND_BEGIN_ARG_INFO(arginfo_iterator_it___construct, 0) 
+       ZEND_ARG_OBJ_INFO(0, iterator, Traversable, 0)
+ZEND_END_ARG_INFO();
+
+static zend_function_entry spl_funcs_IteratorIterator[] = {
+       SPL_ME(IteratorIterator, __construct,      arginfo_iterator_it___construct, ZEND_ACC_PUBLIC)
+       SPL_ME(dual_it,          rewind,           NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(dual_it,          valid,            NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(dual_it,          key,              NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(dual_it,          current,          NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(dual_it,          next,             NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(dual_it,          getInnerIterator, NULL, ZEND_ACC_PUBLIC)
+       {NULL, NULL, NULL}
+};
+
+/* {{{ proto NoRewindIterator::__construct(Iterator it)
+   Create an iterator from another iterator */
+SPL_METHOD(NoRewindIterator, __construct)
+{
+       spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, zend_ce_iterator, DIT_NoRewindIterator);
+} /* }}} */
+
+/* {{{ proto NoRewindIterator::rewind()
+   Prevent a call to inner iterators rewind() (internally the current data will be fetched if valid()) */
+SPL_METHOD(NoRewindIterator, rewind)
+{
+       spl_dual_it_object   *intern;
+
+       intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+       spl_dual_it_fetch(intern, 1 TSRMLS_CC);
+} /* }}} */
+
+static
+ZEND_BEGIN_ARG_INFO(arginfo_norewind_it___construct, 0) 
+       ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
+ZEND_END_ARG_INFO();
+
+static zend_function_entry spl_funcs_NoRewindIterator[] = {
+       SPL_ME(NoRewindIterator, __construct,      arginfo_norewind_it___construct, ZEND_ACC_PUBLIC)
+       SPL_ME(NoRewindIterator, rewind,           NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(dual_it,          valid,            NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(dual_it,          key,              NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(dual_it,          current,          NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(dual_it,          next,             NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(dual_it,          getInnerIterator, NULL, ZEND_ACC_PUBLIC)
+       {NULL, NULL, NULL}
+};
+
+zend_object_iterator_funcs spl_norewind_it_iterator_funcs;
+
 /* {{{ array iterator_to_array(IteratorAggregate it) 
    Copy the iterator into an array */
 PHP_FUNCTION(iterator_to_array)
@@ -1452,6 +1539,12 @@ PHP_MINIT_FUNCTION(spl_iterators)
        REGISTER_SPL_SUB_CLASS_EX(CachingRecursiveIterator, CachingIterator, spl_dual_it_new, spl_funcs_CachingRecursiveIterator);
        REGISTER_SPL_IMPLEMENTS(CachingRecursiveIterator, RecursiveIterator);
        
+       REGISTER_SPL_STD_CLASS_EX(IteratorIterator, spl_dual_it_new, spl_funcs_IteratorIterator);
+       REGISTER_SPL_ITERATOR(IteratorIterator);
+
+       REGISTER_SPL_STD_CLASS_EX(NoRewindIterator, spl_dual_it_new, spl_funcs_NoRewindIterator);
+       REGISTER_SPL_ITERATOR(NoRewindIterator);
+
        REGISTER_SPL_INTERFACE(OuterIterator);
        REGISTER_SPL_ITERATOR(OuterIterator);
 
@@ -1459,6 +1552,8 @@ PHP_MINIT_FUNCTION(spl_iterators)
        REGISTER_SPL_IMPLEMENTS(CachingIterator, OuterIterator);
        REGISTER_SPL_IMPLEMENTS(FilterIterator, OuterIterator);
        REGISTER_SPL_IMPLEMENTS(LimitIterator, OuterIterator);
+       REGISTER_SPL_IMPLEMENTS(IteratorIterator, OuterIterator);
+       REGISTER_SPL_IMPLEMENTS(NoRewindIterator, OuterIterator);
 
        return SUCCESS;
 }
index 3459b0f94bcc7b9f78e774ebeabd1d4dd81177a8..22da632d55d9afd254aab8c88548cc9f42ea93bc 100755 (executable)
@@ -33,6 +33,8 @@ extern zend_class_entry *spl_ce_LimitIterator;
 extern zend_class_entry *spl_ce_CachingIterator;
 extern zend_class_entry *spl_ce_CachingRecursiveIterator;
 extern zend_class_entry *spl_ce_OuterIterator;
+extern zend_class_entry *spl_ce_IteratorIterator;
+extern zend_class_entry *spl_ce_NoRewindIterator;
 
 PHP_MINIT_FUNCTION(spl_iterators);
 
@@ -43,7 +45,9 @@ typedef enum {
        DIT_Default = 0,
        DIT_LimitIterator,
        DIT_CachingIterator,
-       DIT_CachingRecursiveIterator
+       DIT_CachingRecursiveIterator,
+       DIT_IteratorIterator,
+       DIT_NoRewindIterator,
 } dual_it_type;
 
 enum {
index 6cd560fe3070b5e6cc84c49277d8451c7abdecbb..d4ea0ab39ad6bfdb4cecbcff1cd6d809e5133c35 100755 (executable)
@@ -1,25 +1,21 @@
 --TEST--
-SPL: ArrayIterator::seek()
+SPL: ArrayItaerator/Object and IteratorIterator
 --SKIPIF--
 <?php if (!extension_loaded("spl")) print "skip"; ?>
 --FILE--
 <?php
 
-$it = new ArrayIterator(range(0,10));
-var_dump($it->count());
-$it->seek(5);
-var_dump($it->current());
-$it->seek(4);
-var_dump($it->current());
-$it->seek(-1);
-var_dump($it->current());
-$it->seek(12);
-var_dump($it->current());
+$it = new ArrayIterator(range(0,3));
 
-$pos = 0;
-foreach($it as $v)
+foreach(new IteratorIterator($it) as $v)
+{
+       var_dump($v);
+}
+
+$it = new ArrayObject(range(0,3));
+
+foreach(new IteratorIterator($it) as $v)
 {
-       $it->seek($pos++);
        var_dump($v);
 }
 
@@ -27,20 +23,12 @@ foreach($it as $v)
 ===DONE===
 <?php exit(0); ?>
 --EXPECTF--
-int(11)
-int(5)
-int(4)
 int(0)
-NULL
+int(1)
+int(2)
+int(3)
 int(0)
 int(1)
 int(2)
 int(3)
-int(4)
-int(5)
-int(6)
-int(7)
-int(8)
-int(9)
-int(10)
 ===DONE===
diff --git a/ext/spl/tests/iterator_005.phpt b/ext/spl/tests/iterator_005.phpt
new file mode 100755 (executable)
index 0000000..4aae600
--- /dev/null
@@ -0,0 +1,54 @@
+--TEST--
+SPL: IteratorIterator and ArrayIterator/Object
+--SKIPIF--
+<?php if (!extension_loaded("spl")) print "skip"; ?>
+--FILE--
+<?php
+
+class ArrayIteratorEx extends ArrayIterator
+{
+       function rewind()
+       {
+               echo __METHOD__ . "\n";
+               return parent::rewind();
+       }
+}
+
+$it = new ArrayIteratorEx(range(0,3));
+
+foreach(new IteratorIterator($it) as $v)
+{
+       var_dump($v);
+}
+
+class ArrayObjectEx extends ArrayObject
+{
+       function getIterator()
+       {
+               echo __METHOD__ . "\n";
+               return parent::getIterator();
+       }
+}
+
+$it = new ArrayObjectEx(range(0,3));
+
+foreach(new IteratorIterator($it) as $v)
+{
+       var_dump($v);
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+ArrayIteratorEx::rewind
+int(0)
+int(1)
+int(2)
+int(3)
+ArrayObjectEx::getIterator
+int(0)
+int(1)
+int(2)
+int(3)
+===DONE===
diff --git a/ext/spl/tests/iterator_006.phpt b/ext/spl/tests/iterator_006.phpt
new file mode 100755 (executable)
index 0000000..855741c
--- /dev/null
@@ -0,0 +1,24 @@
+--TEST--
+SPL: IteratorIterator and SimpleXMlElement
+--SKIPIF--
+<?php if (!extension_loaded("spl")) print "skip"; ?>
+--FILE--
+<?php
+
+$root = simplexml_load_string('<?xml version="1.0"?>
+<root>
+ <child>Hello</child>
+ <child>World</child>
+</root>
+');
+
+foreach (new IteratorIterator($root->child) as $child) {
+       echo $child."\n";
+}
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Hello
+World
+===DONE===
diff --git a/ext/spl/tests/iterator_007.phpt b/ext/spl/tests/iterator_007.phpt
new file mode 100755 (executable)
index 0000000..e40e2a2
--- /dev/null
@@ -0,0 +1,174 @@
+--TEST--
+SPL: NoRewindIterator
+--SKIPIF--
+<?php if (!extension_loaded("spl")) print "skip"; ?>
+--FILE--
+<?php
+
+class ArrayIteratorEx extends ArrayIterator
+{
+       function rewind()
+       {
+               echo __METHOD__ . "\n";
+               parent::rewind();
+       }
+       function valid()
+       {
+               echo __METHOD__ . "\n";
+               return parent::valid();
+       }
+       function current()
+       {
+               echo __METHOD__ . "\n";
+               return parent::current();
+       }
+       function key()
+       {
+               echo __METHOD__ . "\n";
+               return parent::key();
+       }
+       function next()
+       {
+               echo __METHOD__ . "\n";
+               parent::next();
+       }
+}
+
+class NoRewindIteratorEx extends NoRewindIterator
+{
+       function rewind()
+       {
+               echo __METHOD__ . "\n";
+               parent::rewind();
+       }
+       function valid()
+       {
+               echo __METHOD__ . "\n";
+               return parent::valid();
+       }
+       function current()
+       {
+               echo __METHOD__ . "\n";
+               return parent::current();
+       }
+       function key()
+       {
+               echo __METHOD__ . "\n";
+               return parent::key();
+       }
+       function next()
+       {
+               echo __METHOD__ . "\n";
+               parent::next();
+       }
+}
+
+$it = new NoRewindIteratorEx(new ArrayIteratorEx(range(0,3)));
+
+echo "===0===\n";
+foreach ($it->getInnerIterator() as $v) {
+       var_dump($v);
+}
+
+echo "===1===\n";
+foreach ($it as $v) {
+       var_dump($v);
+}
+
+$pos =0;
+
+$it = new NoRewindIteratorEx(new ArrayIteratorEx(range(0,3)));
+
+echo "===2===\n";
+foreach ($it as $v) {
+       var_dump($v);
+       if ($pos++ > 1) {
+               break;
+       }
+}
+
+echo "===3===\n";
+foreach ($it as $v) {
+       var_dump($v);
+}
+
+echo "===4===\n";
+foreach ($it as $v) {
+       var_dump($v);
+}
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+===0===
+ArrayIteratorEx::rewind
+ArrayIteratorEx::valid
+ArrayIteratorEx::current
+int(0)
+ArrayIteratorEx::next
+ArrayIteratorEx::valid
+ArrayIteratorEx::current
+int(1)
+ArrayIteratorEx::next
+ArrayIteratorEx::valid
+ArrayIteratorEx::current
+int(2)
+ArrayIteratorEx::next
+ArrayIteratorEx::valid
+ArrayIteratorEx::current
+int(3)
+ArrayIteratorEx::next
+ArrayIteratorEx::valid
+===1===
+NoRewindIteratorEx::rewind
+ArrayIteratorEx::valid
+NoRewindIteratorEx::valid
+===2===
+NoRewindIteratorEx::rewind
+ArrayIteratorEx::valid
+ArrayIteratorEx::current
+ArrayIteratorEx::key
+NoRewindIteratorEx::valid
+NoRewindIteratorEx::current
+int(0)
+NoRewindIteratorEx::next
+ArrayIteratorEx::next
+ArrayIteratorEx::valid
+ArrayIteratorEx::current
+ArrayIteratorEx::key
+NoRewindIteratorEx::valid
+NoRewindIteratorEx::current
+int(1)
+NoRewindIteratorEx::next
+ArrayIteratorEx::next
+ArrayIteratorEx::valid
+ArrayIteratorEx::current
+ArrayIteratorEx::key
+NoRewindIteratorEx::valid
+NoRewindIteratorEx::current
+int(2)
+===3===
+NoRewindIteratorEx::rewind
+ArrayIteratorEx::valid
+ArrayIteratorEx::current
+ArrayIteratorEx::key
+NoRewindIteratorEx::valid
+NoRewindIteratorEx::current
+int(2)
+NoRewindIteratorEx::next
+ArrayIteratorEx::next
+ArrayIteratorEx::valid
+ArrayIteratorEx::current
+ArrayIteratorEx::key
+NoRewindIteratorEx::valid
+NoRewindIteratorEx::current
+int(3)
+NoRewindIteratorEx::next
+ArrayIteratorEx::next
+ArrayIteratorEx::valid
+NoRewindIteratorEx::valid
+===4===
+NoRewindIteratorEx::rewind
+ArrayIteratorEx::valid
+NoRewindIteratorEx::valid
+===DONE===