helly           Wed Oct  5 17:59:14 2005 EDT

  Modified files:              (Branch: PHP_5_1)
    /php-src/ext/spl    spl_iterators.c 
  Log:
  - Synch RecursiveIteratorIterator, fixes a few memory corruptions/memleaks
  
  
http://cvs.php.net/diff.php/php-src/ext/spl/spl_iterators.c?r1=1.73.2.3&r2=1.73.2.4&ty=u
Index: php-src/ext/spl/spl_iterators.c
diff -u php-src/ext/spl/spl_iterators.c:1.73.2.3 
php-src/ext/spl/spl_iterators.c:1.73.2.4
--- php-src/ext/spl/spl_iterators.c:1.73.2.3    Mon Oct  3 12:05:08 2005
+++ php-src/ext/spl/spl_iterators.c     Wed Oct  5 17:59:13 2005
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: spl_iterators.c,v 1.73.2.3 2005/10/03 16:05:08 helly Exp $ */
+/* $Id: spl_iterators.c,v 1.73.2.4 2005/10/05 21:59:13 helly Exp $ */
 
 #ifdef HAVE_CONFIG_H
 # include "config.h"
@@ -89,6 +89,10 @@
        int                      level;
        RecursiveIteratorMode    mode;
        int                      flags;
+       int                      max_depth;
+       zend_bool                in_iteration;
+       zend_function            *beginIteration;
+       zend_function            *endIteration;
        zend_function            *callHasChildren;
        zend_function            *callGetChildren;
        zend_function            *beginChildren;
@@ -116,14 +120,14 @@
                sub_iter->funcs->dtor(sub_iter TSRMLS_CC);
                zval_ptr_dtor(&object->iterators[object->level--].zobject);
        }
-       erealloc(object->iterators, sizeof(spl_sub_iterator));
+       object->iterators = erealloc(object->iterators, 
sizeof(spl_sub_iterator));
        object->level = 0;
 
        zval_ptr_dtor(&iter->zobject);  
        efree(iter);
 }
        
-static int spl_recursive_it_valid_ex(spl_recursive_it_object *object TSRMLS_DC)
+static int spl_recursive_it_valid_ex(spl_recursive_it_object *object, zval 
*zthis TSRMLS_DC)
 {
        zend_object_iterator      *sub_iter;
        int                       level = object->level;
@@ -135,6 +139,10 @@
                }
                level--;
        }
+       if (object->endIteration && object->in_iteration) {
+               zend_call_method_with_0_params(&zthis, object->ce, 
&object->endIteration, "endIteration", NULL);
+       }
+       object->in_iteration = 0;
        return FAILURE;
 }
 
@@ -142,7 +150,7 @@
 {
        spl_recursive_it_object   *object = 
(spl_recursive_it_object*)iter->data;
        
-       return spl_recursive_it_valid_ex(object TSRMLS_CC);
+       return spl_recursive_it_valid_ex(object, 
((spl_recursive_it_iterator*)iter)->zobject TSRMLS_CC);
 }
 
 static void spl_recursive_it_get_current_data(zend_object_iterator *iter, zval 
***data TSRMLS_DC)
@@ -199,6 +207,7 @@
                                        has_children = zend_is_true(retval);
                                        zval_ptr_dtor(&retval);
                                        if (has_children) {
+                                               if (object->max_depth == -1 || 
object->max_depth > object->level) {
                                                switch (object->mode) {
                                                case RIT_LEAVES_ONLY:
                                                case RIT_CHILD_FIRST:
@@ -208,6 +217,14 @@
                                                        
object->iterators[object->level].state = RS_SELF;
                                                        goto next_step;
                                                }
+                                               } else {
+                                                       /* do not recurse into 
*/
+                                                       if (object->mode == 
RIT_LEAVES_ONLY) {
+                                                               /* this is not 
a leave, so skip it */
+                                                               
object->iterators[object->level].state = RS_NEXT;
+                                                               goto next_step;
+                                                       }
+                                               }
                                        }
                                }
                                if (object->nextElement) {
@@ -306,6 +323,10 @@
        if (sub_iter->funcs->rewind) {
                sub_iter->funcs->rewind(sub_iter TSRMLS_CC);
        }
+       if (object->beginIteration && !object->in_iteration) {
+               zend_call_method_with_0_params(&zthis, object->ce, 
&object->beginIteration, "beginIteration", NULL);
+       }
+       object->in_iteration = 1;
        spl_recursive_it_move_forward_ex(object, zthis TSRMLS_CC);
 }
 
@@ -371,7 +392,18 @@
        intern->level = 0;
        intern->mode = mode;
        intern->flags = flags;
+       intern->max_depth = -1;
+       intern->in_iteration = 0;
        intern->ce = Z_OBJCE_P(object);
+
+       zend_hash_find(&intern->ce->function_table, "beginiteration", 
sizeof("beginiteration"), (void **) &intern->beginIteration);
+       if (intern->beginIteration->common.scope == 
spl_ce_RecursiveIteratorIterator) {
+               intern->beginIteration = NULL;
+       }
+       zend_hash_find(&intern->ce->function_table, "enditeration", 
sizeof("enditeration"), (void **) &intern->endIteration);
+       if (intern->endIteration->common.scope == 
spl_ce_RecursiveIteratorIterator) {
+               intern->endIteration = NULL;
+       }
        zend_hash_find(&intern->ce->function_table, "callhaschildren", 
sizeof("callHasChildren"), (void **) &intern->callHasChildren);
        if (intern->callHasChildren->common.scope == 
spl_ce_RecursiveIteratorIterator) {
                intern->callHasChildren = NULL;
@@ -417,7 +449,7 @@
 {
        spl_recursive_it_object   *object = 
(spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       RETURN_BOOL(spl_recursive_it_valid_ex(object TSRMLS_CC) == SUCCESS);
+       RETURN_BOOL(spl_recursive_it_valid_ex(object, getThis() TSRMLS_CC) == 
SUCCESS);
 } /* }}} */
 
 /* {{{ proto mixed RecursiveIteratorIterator::key()
@@ -497,6 +529,20 @@
        RETURN_ZVAL(object->iterators[level].zobject, 1, 0);
 } /* }}} */
 
+/* {{{ proto RecursiveIterator RecursiveIteratorIterator::beginIteration()
+   Called when iteration begins (after first rewind() call) */
+SPL_METHOD(RecursiveIteratorIterator, beginIteration)
+{
+       /* nothing to do */
+} /* }}} */
+
+/* {{{ proto RecursiveIterator RecursiveIteratorIterator::endIteration()
+   Called when iteration ends (when valid() first returns false */
+SPL_METHOD(RecursiveIteratorIterator, endIteration)
+{
+       /* nothing to do */
+} /* }}} */
+
 /* {{{ proto bool RecursiveIteratorIterator::callHasChildren()
    Called for each element to test whether it has children */
 SPL_METHOD(RecursiveIteratorIterator, callHasChildren)
@@ -554,6 +600,36 @@
        /* nothing to do */
 } /* }}} */
 
+/* {{{ proto RecursiveIterator 
RecursiveIteratorIterator::setMaxDepth([$max_depth = -1])
+   Set the maximum allowed depth (or any depth if pmax_depth = -1] */
+SPL_METHOD(RecursiveIteratorIterator, setMaxDepth)
+{
+       spl_recursive_it_object   *object = 
(spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       long  max_depth = -1;
+       
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &max_depth) 
== FAILURE) {
+               return;
+       }
+       if (max_depth < -1) {
+               zend_throw_exception(spl_ce_OutOfRangeException, "Parameter 
max_depth must be >= -1", 0 TSRMLS_CC);
+               return;
+       }
+       object->max_depth = max_depth;
+} /* }}} */
+
+/* {{{ proto RecursiveIterator RecursiveIteratorIterator::getMaxDepth()
+   Return the maximum accepted depth or false if any depth is allowed */
+SPL_METHOD(RecursiveIteratorIterator, getMaxDepth)
+{
+       spl_recursive_it_object   *object = 
(spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+       if (object->max_depth == -1) {
+               RETURN_FALSE;
+       } else {
+               RETURN_LONG(object->max_depth);
+       }
+} /* }}} */
+
 static union _zend_function *spl_recursive_it_get_method(zval **object_ptr, 
char *method, int method_len TSRMLS_DC)
 {
        union _zend_function    *function_handler;
@@ -586,6 +662,7 @@
                        
zval_ptr_dtor(&object->iterators[object->level--].zobject);
                }
                efree(object->iterators);
+               object->iterators = NULL;
        }
 
        zend_hash_destroy(object->std.properties);
@@ -627,21 +704,30 @@
        ZEND_ARG_INFO(0, level)
 ZEND_END_ARG_INFO();
 
+static
+ZEND_BEGIN_ARG_INFO(arginfo_recursive_it_setMaxDepth, 0) 
+       ZEND_ARG_INFO(0, max_depth)
+ZEND_END_ARG_INFO();
+
 static zend_function_entry spl_funcs_RecursiveIteratorIterator[] = {
-       SPL_ME(RecursiveIteratorIterator, __construct,   
arginfo_recursive_it___construct, ZEND_ACC_PUBLIC)
-       SPL_ME(RecursiveIteratorIterator, rewind,        NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(RecursiveIteratorIterator, valid,         NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(RecursiveIteratorIterator, key,           NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(RecursiveIteratorIterator, current,       NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(RecursiveIteratorIterator, next,          NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(RecursiveIteratorIterator, getDepth,      NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(RecursiveIteratorIterator, __construct,       
arginfo_recursive_it___construct,    ZEND_ACC_PUBLIC)
+       SPL_ME(RecursiveIteratorIterator, rewind,            NULL,              
                  ZEND_ACC_PUBLIC)
+       SPL_ME(RecursiveIteratorIterator, valid,             NULL,              
                  ZEND_ACC_PUBLIC)
+       SPL_ME(RecursiveIteratorIterator, key,               NULL,              
                  ZEND_ACC_PUBLIC)
+       SPL_ME(RecursiveIteratorIterator, current,           NULL,              
                  ZEND_ACC_PUBLIC)
+       SPL_ME(RecursiveIteratorIterator, next,              NULL,              
                  ZEND_ACC_PUBLIC)
+       SPL_ME(RecursiveIteratorIterator, getDepth,          NULL,              
                  ZEND_ACC_PUBLIC)
        SPL_ME(RecursiveIteratorIterator, getSubIterator,    
arginfo_recursive_it_getSubIterator, ZEND_ACC_PUBLIC)
-       SPL_ME(RecursiveIteratorIterator, getInnerIterator,  NULL, 
ZEND_ACC_PUBLIC)
-       SPL_ME(RecursiveIteratorIterator, callHasChildren,   NULL, 
ZEND_ACC_PUBLIC)
-       SPL_ME(RecursiveIteratorIterator, callGetChildren,   NULL, 
ZEND_ACC_PUBLIC)
-       SPL_ME(RecursiveIteratorIterator, beginChildren,     NULL, 
ZEND_ACC_PUBLIC)
-       SPL_ME(RecursiveIteratorIterator, endChildren,       NULL, 
ZEND_ACC_PUBLIC)
-       SPL_ME(RecursiveIteratorIterator, nextElement,       NULL, 
ZEND_ACC_PUBLIC)
+       SPL_ME(RecursiveIteratorIterator, getInnerIterator,  NULL,              
                  ZEND_ACC_PUBLIC)
+       SPL_ME(RecursiveIteratorIterator, beginIteration,    NULL,              
                  ZEND_ACC_PUBLIC)
+       SPL_ME(RecursiveIteratorIterator, endIteration,      NULL,              
                  ZEND_ACC_PUBLIC)
+       SPL_ME(RecursiveIteratorIterator, callHasChildren,   NULL,              
                  ZEND_ACC_PUBLIC)
+       SPL_ME(RecursiveIteratorIterator, callGetChildren,   NULL,              
                  ZEND_ACC_PUBLIC)
+       SPL_ME(RecursiveIteratorIterator, beginChildren,     NULL,              
                  ZEND_ACC_PUBLIC)
+       SPL_ME(RecursiveIteratorIterator, endChildren,       NULL,              
                  ZEND_ACC_PUBLIC)
+       SPL_ME(RecursiveIteratorIterator, nextElement,       NULL,              
                  ZEND_ACC_PUBLIC)
+       SPL_ME(RecursiveIteratorIterator, setMaxDepth,       
arginfo_recursive_it_setMaxDepth,    ZEND_ACC_PUBLIC)
+       SPL_ME(RecursiveIteratorIterator, getMaxDepth,       NULL,              
                  ZEND_ACC_PUBLIC)
        {NULL, NULL, NULL}
 };
 

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to