]> granicus.if.org Git - php/commitdiff
- Add RecursiveFilterIterator
authorMarcus Boerger <helly@php.net>
Wed, 10 Aug 2005 19:48:48 +0000 (19:48 +0000)
committerMarcus Boerger <helly@php.net>
Wed, 10 Aug 2005 19:48:48 +0000 (19:48 +0000)
- Derive ParentIterator from RecursiveIterator
# Actually brought up by a user. It is of course better to filter first and
# do the recursion only for accepted values. Otherwise you would iterate
# children and possibly recurse into them just to ignore them later anyway.

ext/spl/internal/parentiterator.inc
ext/spl/internal/recursivefilteriterator.inc [new file with mode: 0755]
ext/spl/spl_iterators.c

index 7fb0f11dd36dfd84035e68be8d0e1bdb300e23ed..c5551a886b9b643854e6f226b2a71cd0f339a947 100755 (executable)
 /**
  * @brief   Iterator to filter parents
  * @author  Marcus Boerger
- * @version 1.1
- * @since PHP 5.0
+ * @version 1.2
+ * @since PHP 6.0
  *
  * This extended FilterIterator allows a recursive iteration using 
  * RecursiveIteratorIterator that only shows those elements which have 
  * children.
  */
-class ParentIterator extends FilterIterator implements RecursiveIterator
+class ParentIterator extends RecursiveFilterIterator
 {
        /** @param $it the RecursiveIterator to filter
         */
@@ -35,13 +35,6 @@ class ParentIterator extends FilterIterator implements RecursiveIterator
                return $this->it->hasChildren();
        }
 
-       /** @return whether the current element has children
-        */
-       function hasChildren()
-       {
-               return $this->it->hasChildren();
-       }
-
        /** @return the ParentIterator for the current elements children
         */
        function getChildren()
diff --git a/ext/spl/internal/recursivefilteriterator.inc b/ext/spl/internal/recursivefilteriterator.inc
new file mode 100755 (executable)
index 0000000..3cb3de0
--- /dev/null
@@ -0,0 +1,48 @@
+<?php
+
+/** @file recursivefilteriterator.inc
+ * @ingroup SPL
+ * @brief class RecursiveFilterIterator
+ * @author  Marcus Boerger
+ * @date    2003 - 2005
+ *
+ * SPL - Standard PHP Library
+ */
+
+/**
+ * @brief   Iterator to filter recursive iterators
+ * @author  Marcus Boerger
+ * @version 1.0
+ * @since PHP 6.0
+ *
+ * This extended FilterIterator allows a recursive iteration using 
+ * RecursiveIteratorIterator that only shows those elements which
+ * are accepted. It is of course better to filter before doing the 
+ * recursion since it allows to prevent recursion into children that 
+ * get declined later anyway.
+ */
+class RecursiveFilterIterator extends FilterIterator implements RecursiveIterator
+{
+       /** @param $it the RecursiveIterator to filter
+        */
+       function __construct(RecursiveIterator $it)
+       {
+               parent::__construct($it);
+       }
+       
+       /** @return whether the current element has children
+        */
+       function hasChildren()
+       {
+               return $this->it->hasChildren();
+       }
+
+       /** @return the ParentIterator for the current elements children
+        */
+       function getChildren()
+       {
+               return new RecursiveFilterIterator($this->it->getChildren());
+       }
+}
+
+?>
\ No newline at end of file
index 4eb16ff7272da2b1877ae20dcda6c01c8af289dd..10607de947d784a79cec3b1368ebbdbbaa56ddc5 100755 (executable)
@@ -41,6 +41,7 @@
 PHPAPI zend_class_entry *spl_ce_RecursiveIterator;
 PHPAPI zend_class_entry *spl_ce_RecursiveIteratorIterator;
 PHPAPI zend_class_entry *spl_ce_FilterIterator;
+PHPAPI zend_class_entry *spl_ce_RecursiveFilterIterator;
 PHPAPI zend_class_entry *spl_ce_ParentIterator;
 PHPAPI zend_class_entry *spl_ce_SeekableIterator;
 PHPAPI zend_class_entry *spl_ce_LimitIterator;
@@ -1041,6 +1042,40 @@ SPL_METHOD(FilterIterator, next)
        spl_filter_it_next(getThis(), intern TSRMLS_CC);
 } /* }}} */
 
+/* {{{ proto RecursiveFilterIterator::__construct(RecursiveIterator it)
+   Create a RecursiveFilterIterator from a RecursiveIterator */
+SPL_METHOD(RecursiveFilterIterator, __construct)
+{
+       spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_RecursiveIterator, DIT_Default);
+} /* }}} */
+
+/* {{{ proto boolean RecursiveFilterIterator::hasChildren()
+   Check whether the inner iterator's current element has children */
+SPL_METHOD(RecursiveFilterIterator, hasChildren)
+{
+       spl_dual_it_object   *intern;
+       zval                 *retval;
+
+       intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+       zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "haschildren", &retval);
+       RETURN_ZVAL(retval, 0, 1);
+} /* }}} */
+
+/* {{{ proto RecursiveFilterIterator RecursiveFilterIterator::getChildren()
+   Return the inner iterator's children contained in a RecursiveFilterIterator */
+SPL_METHOD(RecursiveFilterIterator, getChildren)
+{
+       spl_dual_it_object   *intern;
+       zval                 *retval;
+
+       intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+       zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &retval);
+       spl_instantiate_arg_ex1(spl_ce_RecursiveFilterIterator, &return_value, 0, retval TSRMLS_CC);
+       zval_ptr_dtor(&retval);
+} /* }}} */
+
 /* {{{ proto ParentIterator::__construct(RecursiveIterator it)
    Create a ParentIterator from a RecursiveIterator */
 SPL_METHOD(ParentIterator, __construct)
@@ -1142,15 +1177,21 @@ static zend_function_entry spl_funcs_FilterIterator[] = {
 
 static
 ZEND_BEGIN_ARG_INFO(arginfo_parent_it___construct, 0) 
-       ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
+       ZEND_ARG_OBJ_INFO(0, iterator, RecursiveIterator, 0)
 ZEND_END_ARG_INFO();
 
+static zend_function_entry spl_funcs_RecursiveFilterIterator[] = {
+       SPL_ME(RecursiveFilterIterator,  __construct,      arginfo_parent_it___construct, ZEND_ACC_PUBLIC)
+       SPL_ME(RecursiveFilterIterator,  hasChildren,      NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(RecursiveFilterIterator,  getChildren,      NULL, ZEND_ACC_PUBLIC)
+       {NULL, NULL, NULL}
+};
+
 static zend_function_entry spl_funcs_ParentIterator[] = {
        SPL_ME(ParentIterator,  __construct,      arginfo_parent_it___construct, ZEND_ACC_PUBLIC)
        SPL_MA(ParentIterator,  accept,           ParentIterator, hasChildren, NULL, ZEND_ACC_PUBLIC)
        SPL_ME(ParentIterator,  hasChildren,      NULL, ZEND_ACC_PUBLIC)
        SPL_ME(ParentIterator,  getChildren,      NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(dual_it,         getInnerIterator, NULL, ZEND_ACC_PUBLIC)
        {NULL, NULL, NULL}
 };
 
@@ -1938,10 +1979,11 @@ PHP_MINIT_FUNCTION(spl_iterators)
 
        REGISTER_SPL_STD_CLASS_EX(FilterIterator, spl_dual_it_new, spl_funcs_FilterIterator);
        REGISTER_SPL_ITERATOR(FilterIterator);
-       spl_ce_FilterIterator->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
 
-       REGISTER_SPL_SUB_CLASS_EX(ParentIterator, FilterIterator, spl_dual_it_new, spl_funcs_ParentIterator);
-       REGISTER_SPL_IMPLEMENTS(ParentIterator, RecursiveIterator);
+       REGISTER_SPL_SUB_CLASS_EX(RecursiveFilterIterator, FilterIterator, spl_dual_it_new, spl_funcs_RecursiveFilterIterator);
+       REGISTER_SPL_IMPLEMENTS(RecursiveFilterIterator, RecursiveIterator);
+
+       REGISTER_SPL_SUB_CLASS_EX(ParentIterator, RecursiveFilterIterator, spl_dual_it_new, spl_funcs_ParentIterator);
 
        REGISTER_SPL_INTERFACE(SeekableIterator);
        REGISTER_SPL_ITERATOR(SeekableIterator);