Annotation of embedaddon/php/ext/spl/spl_iterators.c, revision 1.1

1.1     ! misho       1: /*
        !             2:    +----------------------------------------------------------------------+
        !             3:    | PHP Version 5                                                        |
        !             4:    +----------------------------------------------------------------------+
        !             5:    | Copyright (c) 1997-2012 The PHP Group                                |
        !             6:    +----------------------------------------------------------------------+
        !             7:    | This source file is subject to version 3.01 of the PHP license,      |
        !             8:    | that is bundled with this package in the file LICENSE, and is        |
        !             9:    | available through the world-wide-web at the following url:           |
        !            10:    | http://www.php.net/license/3_01.txt                                  |
        !            11:    | If you did not receive a copy of the PHP license and are unable to   |
        !            12:    | obtain it through the world-wide-web, please send a note to          |
        !            13:    | license@php.net so we can mail you a copy immediately.               |
        !            14:    +----------------------------------------------------------------------+
        !            15:    | Authors: Marcus Boerger <helly@php.net>                              |
        !            16:    +----------------------------------------------------------------------+
        !            17:  */
        !            18: 
        !            19: /* $Id: spl_iterators.c 321634 2012-01-01 13:15:04Z felipe $ */
        !            20: 
        !            21: #ifdef HAVE_CONFIG_H
        !            22: # include "config.h"
        !            23: #endif
        !            24: 
        !            25: #include "php.h"
        !            26: #include "php_ini.h"
        !            27: #include "ext/standard/info.h"
        !            28: #include "zend_exceptions.h"
        !            29: #include "zend_interfaces.h"
        !            30: 
        !            31: #include "php_spl.h"
        !            32: #include "spl_functions.h"
        !            33: #include "spl_engine.h"
        !            34: #include "spl_iterators.h"
        !            35: #include "spl_directory.h"
        !            36: #include "spl_array.h"
        !            37: #include "spl_exceptions.h"
        !            38: #include "ext/standard/php_smart_str.h"
        !            39: 
        !            40: #ifdef accept
        !            41: #undef accept
        !            42: #endif
        !            43: 
        !            44: PHPAPI zend_class_entry *spl_ce_RecursiveIterator;
        !            45: PHPAPI zend_class_entry *spl_ce_RecursiveIteratorIterator;
        !            46: PHPAPI zend_class_entry *spl_ce_FilterIterator;
        !            47: PHPAPI zend_class_entry *spl_ce_RecursiveFilterIterator;
        !            48: PHPAPI zend_class_entry *spl_ce_ParentIterator;
        !            49: PHPAPI zend_class_entry *spl_ce_SeekableIterator;
        !            50: PHPAPI zend_class_entry *spl_ce_LimitIterator;
        !            51: PHPAPI zend_class_entry *spl_ce_CachingIterator;
        !            52: PHPAPI zend_class_entry *spl_ce_RecursiveCachingIterator;
        !            53: PHPAPI zend_class_entry *spl_ce_OuterIterator;
        !            54: PHPAPI zend_class_entry *spl_ce_IteratorIterator;
        !            55: PHPAPI zend_class_entry *spl_ce_NoRewindIterator;
        !            56: PHPAPI zend_class_entry *spl_ce_InfiniteIterator;
        !            57: PHPAPI zend_class_entry *spl_ce_EmptyIterator;
        !            58: PHPAPI zend_class_entry *spl_ce_AppendIterator;
        !            59: PHPAPI zend_class_entry *spl_ce_RegexIterator;
        !            60: PHPAPI zend_class_entry *spl_ce_RecursiveRegexIterator;
        !            61: PHPAPI zend_class_entry *spl_ce_Countable;
        !            62: PHPAPI zend_class_entry *spl_ce_RecursiveTreeIterator;
        !            63: 
        !            64: ZEND_BEGIN_ARG_INFO(arginfo_recursive_it_void, 0)
        !            65: ZEND_END_ARG_INFO()
        !            66: 
        !            67: const zend_function_entry spl_funcs_RecursiveIterator[] = {
        !            68:        SPL_ABSTRACT_ME(RecursiveIterator, hasChildren,  arginfo_recursive_it_void)
        !            69:        SPL_ABSTRACT_ME(RecursiveIterator, getChildren,  arginfo_recursive_it_void)
        !            70:        PHP_FE_END
        !            71: };
        !            72: 
        !            73: typedef enum {
        !            74:        RIT_LEAVES_ONLY = 0,
        !            75:        RIT_SELF_FIRST  = 1,
        !            76:        RIT_CHILD_FIRST = 2
        !            77: } RecursiveIteratorMode;
        !            78: 
        !            79: #define RIT_CATCH_GET_CHILD CIT_CATCH_GET_CHILD
        !            80: 
        !            81: typedef enum {
        !            82:        RTIT_BYPASS_CURRENT = 4,
        !            83:        RTIT_BYPASS_KEY     = 8
        !            84: } RecursiveTreeIteratorFlags;
        !            85: 
        !            86: typedef enum {
        !            87:        RS_NEXT  = 0,
        !            88:        RS_TEST  = 1,
        !            89:        RS_SELF  = 2,
        !            90:        RS_CHILD = 3,
        !            91:        RS_START = 4
        !            92: } RecursiveIteratorState;
        !            93: 
        !            94: typedef struct _spl_sub_iterator {
        !            95:        zend_object_iterator    *iterator;
        !            96:        zval                    *zobject;
        !            97:        zend_class_entry        *ce;
        !            98:        RecursiveIteratorState  state;
        !            99: } spl_sub_iterator;
        !           100: 
        !           101: typedef struct _spl_recursive_it_object {
        !           102:        zend_object              std;
        !           103:        spl_sub_iterator         *iterators;
        !           104:        int                      level;
        !           105:        RecursiveIteratorMode    mode;
        !           106:        int                      flags;
        !           107:        int                      max_depth;
        !           108:        zend_bool                in_iteration;
        !           109:        zend_function            *beginIteration;
        !           110:        zend_function            *endIteration;
        !           111:        zend_function            *callHasChildren;
        !           112:        zend_function            *callGetChildren;
        !           113:        zend_function            *beginChildren;
        !           114:        zend_function            *endChildren;
        !           115:        zend_function            *nextElement;
        !           116:        zend_class_entry         *ce;
        !           117:        smart_str                prefix[6];
        !           118: } spl_recursive_it_object;
        !           119: 
        !           120: typedef struct _spl_recursive_it_iterator {
        !           121:        zend_object_iterator   intern;
        !           122:        zval                   *zobject;
        !           123: } spl_recursive_it_iterator;
        !           124: 
        !           125: static zend_object_handlers spl_handlers_rec_it_it;
        !           126: static zend_object_handlers spl_handlers_dual_it;
        !           127: 
        !           128: #define SPL_FETCH_AND_CHECK_DUAL_IT(var, objzval) \
        !           129:        do { \
        !           130:                spl_dual_it_object *it = zend_object_store_get_object((objzval) TSRMLS_CC); \
        !           131:                if (it->dit_type == DIT_Unknown) { \
        !           132:                        zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, \
        !           133:                                "The object is in an invalid state as the parent constructor was not called"); \
        !           134:                        return; \
        !           135:                } \
        !           136:                (var) = it; \
        !           137:        } while (0)
        !           138: 
        !           139: static void spl_recursive_it_dtor(zend_object_iterator *_iter TSRMLS_DC)
        !           140: {
        !           141:        spl_recursive_it_iterator *iter   = (spl_recursive_it_iterator*)_iter;
        !           142:        spl_recursive_it_object   *object = (spl_recursive_it_object*)_iter->data;
        !           143:        zend_object_iterator      *sub_iter;
        !           144: 
        !           145:        while (object->level > 0) {
        !           146:                sub_iter = object->iterators[object->level].iterator;
        !           147:                sub_iter->funcs->dtor(sub_iter TSRMLS_CC);
        !           148:                zval_ptr_dtor(&object->iterators[object->level--].zobject);
        !           149:        }
        !           150:        object->iterators = erealloc(object->iterators, sizeof(spl_sub_iterator));
        !           151:        object->level = 0;
        !           152: 
        !           153:        zval_ptr_dtor(&iter->zobject);
        !           154:        efree(iter);
        !           155: }
        !           156: 
        !           157: static int spl_recursive_it_valid_ex(spl_recursive_it_object *object, zval *zthis TSRMLS_DC)
        !           158: {
        !           159:        zend_object_iterator      *sub_iter;
        !           160:        int                       level = object->level;
        !           161:        
        !           162:        while (level >=0) {
        !           163:                sub_iter = object->iterators[level].iterator;
        !           164:                if (sub_iter->funcs->valid(sub_iter TSRMLS_CC) == SUCCESS) {
        !           165:                        return SUCCESS;
        !           166:                }
        !           167:                level--;
        !           168:        }
        !           169:        if (object->endIteration && object->in_iteration) {
        !           170:                zend_call_method_with_0_params(&zthis, object->ce, &object->endIteration, "endIteration", NULL);
        !           171:        }
        !           172:        object->in_iteration = 0;
        !           173:        return FAILURE;
        !           174: }
        !           175: 
        !           176: static int spl_recursive_it_valid(zend_object_iterator *iter TSRMLS_DC)
        !           177: {
        !           178:        spl_recursive_it_object   *object = (spl_recursive_it_object*)iter->data;
        !           179:        
        !           180:        return spl_recursive_it_valid_ex(object, ((spl_recursive_it_iterator*)iter)->zobject TSRMLS_CC);
        !           181: }
        !           182: 
        !           183: static void spl_recursive_it_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC)
        !           184: {
        !           185:        spl_recursive_it_object   *object = (spl_recursive_it_object*)iter->data;
        !           186:        zend_object_iterator      *sub_iter = object->iterators[object->level].iterator;
        !           187:        
        !           188:        sub_iter->funcs->get_current_data(sub_iter, data TSRMLS_CC);
        !           189: }
        !           190: 
        !           191: static int spl_recursive_it_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
        !           192: {
        !           193:        spl_recursive_it_object   *object = (spl_recursive_it_object*)iter->data;
        !           194:        zend_object_iterator      *sub_iter = object->iterators[object->level].iterator;
        !           195: 
        !           196:        if (sub_iter->funcs->get_current_key) {
        !           197:                return sub_iter->funcs->get_current_key(sub_iter, str_key, str_key_len, int_key TSRMLS_CC);
        !           198:        } else {
        !           199:                *int_key = iter->index;
        !           200:                return HASH_KEY_IS_LONG;
        !           201:        }
        !           202: }
        !           203: 
        !           204: static void spl_recursive_it_move_forward_ex(spl_recursive_it_object *object, zval *zthis TSRMLS_DC)
        !           205: {
        !           206:        zend_object_iterator      *iterator;
        !           207:        zval                      *zobject;
        !           208:        zend_class_entry          *ce;
        !           209:        zval                      *retval, *child;
        !           210:        zend_object_iterator      *sub_iter;
        !           211:        int                       has_children;
        !           212: 
        !           213:        while (!EG(exception)) {
        !           214: next_step:
        !           215:                iterator = object->iterators[object->level].iterator;
        !           216:                switch (object->iterators[object->level].state) {
        !           217:                        case RS_NEXT:
        !           218:                                iterator->funcs->move_forward(iterator TSRMLS_CC);
        !           219:                                if (EG(exception)) {
        !           220:                                        if (!(object->flags & RIT_CATCH_GET_CHILD)) {
        !           221:                                                return;
        !           222:                                        } else {
        !           223:                                                zend_clear_exception(TSRMLS_C);
        !           224:                                        }
        !           225:                                }
        !           226:                        case RS_START:
        !           227:                                if (iterator->funcs->valid(iterator TSRMLS_CC) == FAILURE) {
        !           228:                                        break;
        !           229:                                }
        !           230:                                object->iterators[object->level].state = RS_TEST;                                       
        !           231:                                /* break; */
        !           232:                        case RS_TEST:
        !           233:                                ce = object->iterators[object->level].ce;
        !           234:                                zobject = object->iterators[object->level].zobject;
        !           235:                                if (object->callHasChildren) {
        !           236:                                        zend_call_method_with_0_params(&zthis, object->ce, &object->callHasChildren, "callHasChildren", &retval);
        !           237:                                } else {
        !           238:                                        zend_call_method_with_0_params(&zobject, ce, NULL, "haschildren", &retval);
        !           239:                                }
        !           240:                                if (EG(exception)) {
        !           241:                                        if (!(object->flags & RIT_CATCH_GET_CHILD)) {
        !           242:                                                object->iterators[object->level].state = RS_NEXT;
        !           243:                                                return;
        !           244:                                        } else {
        !           245:                                                zend_clear_exception(TSRMLS_C);
        !           246:                                        }
        !           247:                                }
        !           248:                                if (retval) {
        !           249:                                        has_children = zend_is_true(retval);
        !           250:                                        zval_ptr_dtor(&retval);
        !           251:                                        if (has_children) {
        !           252:                                                if (object->max_depth == -1 || object->max_depth > object->level) {
        !           253:                                                        switch (object->mode) {
        !           254:                                                        case RIT_LEAVES_ONLY:
        !           255:                                                        case RIT_CHILD_FIRST:
        !           256:                                                                object->iterators[object->level].state = RS_CHILD;
        !           257:                                                                goto next_step;
        !           258:                                                        case RIT_SELF_FIRST:
        !           259:                                                                object->iterators[object->level].state = RS_SELF;
        !           260:                                                                goto next_step;
        !           261:                                                        }
        !           262:                                                } else {
        !           263:                                                        /* do not recurse into */
        !           264:                                                        if (object->mode == RIT_LEAVES_ONLY) {
        !           265:                                                                /* this is not a leave, so skip it */
        !           266:                                                                object->iterators[object->level].state = RS_NEXT;
        !           267:                                                                goto next_step;
        !           268:                                                        }
        !           269:                                                }
        !           270:                                        }
        !           271:                                }
        !           272:                                if (object->nextElement) {
        !           273:                                        zend_call_method_with_0_params(&zthis, object->ce, &object->nextElement, "nextelement", NULL);
        !           274:                                }
        !           275:                                object->iterators[object->level].state = RS_NEXT;
        !           276:                                if (EG(exception)) {
        !           277:                                        if (!(object->flags & RIT_CATCH_GET_CHILD)) {
        !           278:                                                return;
        !           279:                                        } else {
        !           280:                                                zend_clear_exception(TSRMLS_C);
        !           281:                                        }
        !           282:                                }
        !           283:                                return /* self */;
        !           284:                        case RS_SELF:
        !           285:                                if (object->nextElement && (object->mode == RIT_SELF_FIRST || object->mode == RIT_CHILD_FIRST)) {
        !           286:                                        zend_call_method_with_0_params(&zthis, object->ce, &object->nextElement, "nextelement", NULL);
        !           287:                                }
        !           288:                                if (object->mode == RIT_SELF_FIRST) {
        !           289:                                        object->iterators[object->level].state = RS_CHILD;
        !           290:                                } else {
        !           291:                                        object->iterators[object->level].state = RS_NEXT;
        !           292:                                }
        !           293:                                return /* self */;
        !           294:                        case RS_CHILD:
        !           295:                                ce = object->iterators[object->level].ce;
        !           296:                                zobject = object->iterators[object->level].zobject;
        !           297:                                if (object->callGetChildren) {
        !           298:                                        zend_call_method_with_0_params(&zthis, object->ce, &object->callGetChildren, "callGetChildren", &child);
        !           299:                                } else {
        !           300:                                        zend_call_method_with_0_params(&zobject, ce, NULL, "getchildren", &child);
        !           301:                                }
        !           302: 
        !           303:                                if (EG(exception)) {
        !           304:                                        if (!(object->flags & RIT_CATCH_GET_CHILD)) {
        !           305:                                                return;
        !           306:                                        } else {
        !           307:                                                zend_clear_exception(TSRMLS_C);
        !           308:                                                if (child) {
        !           309:                                                        zval_ptr_dtor(&child);
        !           310:                                                }
        !           311:                                                object->iterators[object->level].state = RS_NEXT;
        !           312:                                                goto next_step;
        !           313:                                        }
        !           314:                                }
        !           315: 
        !           316:                                ce = child && Z_TYPE_P(child) == IS_OBJECT ? Z_OBJCE_P(child) : NULL;
        !           317:                                if (!ce || !instanceof_function(ce, spl_ce_RecursiveIterator TSRMLS_CC)) {
        !           318:                                        if (child) {
        !           319:                                                zval_ptr_dtor(&child);
        !           320:                                        }
        !           321:                                        zend_throw_exception(spl_ce_UnexpectedValueException, "Objects returned by RecursiveIterator::getChildren() must implement RecursiveIterator", 0 TSRMLS_CC);
        !           322:                                        return;
        !           323:                                }
        !           324:                                if (object->mode == RIT_CHILD_FIRST) {
        !           325:                                        object->iterators[object->level].state = RS_SELF;
        !           326:                                } else {
        !           327:                                        object->iterators[object->level].state = RS_NEXT;
        !           328:                                }
        !           329:                                object->iterators = erealloc(object->iterators, sizeof(spl_sub_iterator) * (++object->level+1));
        !           330:                                sub_iter = ce->get_iterator(ce, child, 0 TSRMLS_CC);
        !           331:                                object->iterators[object->level].iterator = sub_iter;
        !           332:                                object->iterators[object->level].zobject = child;
        !           333:                                object->iterators[object->level].ce = ce;
        !           334:                                object->iterators[object->level].state = RS_START;
        !           335:                                if (sub_iter->funcs->rewind) {
        !           336:                                        sub_iter->funcs->rewind(sub_iter TSRMLS_CC);
        !           337:                                }
        !           338:                                if (object->beginChildren) {
        !           339:                                        zend_call_method_with_0_params(&zthis, object->ce, &object->beginChildren, "beginchildren", NULL);
        !           340:                                        if (EG(exception)) {
        !           341:                                                if (!(object->flags & RIT_CATCH_GET_CHILD)) {
        !           342:                                                        return;
        !           343:                                                } else {
        !           344:                                                        zend_clear_exception(TSRMLS_C);
        !           345:                                                }
        !           346:                                        }
        !           347:                                }
        !           348:                                goto next_step;
        !           349:                }
        !           350:                /* no more elements */
        !           351:                if (object->level > 0) {
        !           352:                        if (object->endChildren) {
        !           353:                                zend_call_method_with_0_params(&zthis, object->ce, &object->endChildren, "endchildren", NULL);
        !           354:                                if (EG(exception)) {
        !           355:                                        if (!(object->flags & RIT_CATCH_GET_CHILD)) {
        !           356:                                                return;
        !           357:                                        } else {
        !           358:                                                zend_clear_exception(TSRMLS_C);
        !           359:                                        }
        !           360:                                }
        !           361:                        }
        !           362:                        iterator->funcs->dtor(iterator TSRMLS_CC);
        !           363:                        zval_ptr_dtor(&object->iterators[object->level].zobject);
        !           364:                        object->level--;
        !           365:                } else {
        !           366:                        return; /* done completeley */
        !           367:                }
        !           368:        }
        !           369: }
        !           370: 
        !           371: static void spl_recursive_it_rewind_ex(spl_recursive_it_object *object, zval *zthis TSRMLS_DC)
        !           372: {
        !           373:        zend_object_iterator      *sub_iter;
        !           374:        
        !           375:        if (!object->iterators) {
        !           376:                php_error_docref(NULL TSRMLS_CC, E_ERROR, "The %s instance wasn't initialized properly", Z_OBJCE_P(zthis)->name);
        !           377:        }
        !           378: 
        !           379:        while (object->level) {
        !           380:                sub_iter = object->iterators[object->level].iterator;
        !           381:                sub_iter->funcs->dtor(sub_iter TSRMLS_CC);
        !           382:                zval_ptr_dtor(&object->iterators[object->level--].zobject);
        !           383:                if (!EG(exception) && (!object->endChildren || object->endChildren->common.scope != spl_ce_RecursiveIteratorIterator)) {
        !           384:                        zend_call_method_with_0_params(&zthis, object->ce, &object->endChildren, "endchildren", NULL);
        !           385:                }
        !           386:        }
        !           387:        object->iterators = erealloc(object->iterators, sizeof(spl_sub_iterator));
        !           388:        object->iterators[0].state = RS_START;
        !           389:        sub_iter = object->iterators[0].iterator;
        !           390:        if (sub_iter->funcs->rewind) {
        !           391:                sub_iter->funcs->rewind(sub_iter TSRMLS_CC);
        !           392:        }
        !           393:        if (!EG(exception) && object->beginIteration && !object->in_iteration) {
        !           394:                zend_call_method_with_0_params(&zthis, object->ce, &object->beginIteration, "beginIteration", NULL);
        !           395:        }
        !           396:        object->in_iteration = 1;
        !           397:        spl_recursive_it_move_forward_ex(object, zthis TSRMLS_CC);
        !           398: }
        !           399: 
        !           400: static void spl_recursive_it_move_forward(zend_object_iterator *iter TSRMLS_DC)
        !           401: {
        !           402:        spl_recursive_it_move_forward_ex((spl_recursive_it_object*)iter->data, ((spl_recursive_it_iterator*)iter)->zobject TSRMLS_CC);
        !           403: }
        !           404: 
        !           405: static void spl_recursive_it_rewind(zend_object_iterator *iter TSRMLS_DC)
        !           406: {
        !           407:        spl_recursive_it_rewind_ex((spl_recursive_it_object*)iter->data, ((spl_recursive_it_iterator*)iter)->zobject TSRMLS_CC);
        !           408: }
        !           409: 
        !           410: static zend_object_iterator *spl_recursive_it_get_iterator(zend_class_entry *ce, zval *zobject, int by_ref TSRMLS_DC)
        !           411: {
        !           412:        spl_recursive_it_iterator *iterator;
        !           413:        spl_recursive_it_object   *object;
        !           414: 
        !           415:        if (by_ref) {
        !           416:                zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
        !           417:        }
        !           418:        iterator = emalloc(sizeof(spl_recursive_it_iterator));
        !           419:        object   = (spl_recursive_it_object*)zend_object_store_get_object(zobject TSRMLS_CC);
        !           420:        if (object->iterators == NULL) {
        !           421:                zend_error(E_ERROR, "The object to be iterated is in an invalid state: "
        !           422:                                "the parent constructor has not been called");
        !           423:        }
        !           424: 
        !           425:        Z_ADDREF_P(zobject);
        !           426:        iterator->intern.data = (void*)object;
        !           427:        iterator->intern.funcs = ce->iterator_funcs.funcs;
        !           428:        iterator->zobject = zobject;
        !           429:        return (zend_object_iterator*)iterator;
        !           430: }
        !           431: 
        !           432: zend_object_iterator_funcs spl_recursive_it_iterator_funcs = {
        !           433:        spl_recursive_it_dtor,
        !           434:        spl_recursive_it_valid,
        !           435:        spl_recursive_it_get_current_data,
        !           436:        spl_recursive_it_get_current_key,
        !           437:        spl_recursive_it_move_forward,
        !           438:        spl_recursive_it_rewind
        !           439: };
        !           440: 
        !           441: static void spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *ce_base, zend_class_entry *ce_inner, recursive_it_it_type rit_type)
        !           442: {
        !           443:        zval                      *object = getThis();
        !           444:        spl_recursive_it_object   *intern;
        !           445:        zval                      *iterator;
        !           446:        zend_class_entry          *ce_iterator;
        !           447:        long                       mode, flags;
        !           448:        int                        inc_refcount = 1;
        !           449:        zend_error_handling        error_handling;
        !           450: 
        !           451:        zend_replace_error_handling(EH_THROW, spl_ce_InvalidArgumentException, &error_handling TSRMLS_CC);
        !           452: 
        !           453:        switch(rit_type) {
        !           454:                case RIT_RecursiveTreeIterator: {
        !           455: 
        !           456:                        zval *caching_it, *caching_it_flags, *user_caching_it_flags = NULL;
        !           457:                        mode = RIT_SELF_FIRST;
        !           458:                        flags = RTIT_BYPASS_KEY;
        !           459: 
        !           460:                        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "o|lzl", &iterator, &flags, &user_caching_it_flags, &mode) == SUCCESS) {
        !           461:                                if (instanceof_function(Z_OBJCE_P(iterator), zend_ce_aggregate TSRMLS_CC)) {
        !           462:                                        zval *aggregate = iterator;
        !           463:                                        zend_call_method_with_0_params(&aggregate, Z_OBJCE_P(aggregate), &Z_OBJCE_P(aggregate)->iterator_funcs.zf_new_iterator, "getiterator", &iterator);
        !           464:                                        inc_refcount = 0;
        !           465:                                }
        !           466: 
        !           467:                                MAKE_STD_ZVAL(caching_it_flags);
        !           468:                                if (user_caching_it_flags) {
        !           469:                                        ZVAL_ZVAL(caching_it_flags, user_caching_it_flags, 1, 0);
        !           470:                                } else {
        !           471:                                        ZVAL_LONG(caching_it_flags, CIT_CATCH_GET_CHILD);
        !           472:                                }
        !           473:                                spl_instantiate_arg_ex2(spl_ce_RecursiveCachingIterator, &caching_it, 1, iterator, caching_it_flags TSRMLS_CC);
        !           474:                                zval_ptr_dtor(&caching_it_flags);
        !           475:                                if (inc_refcount == 0 && iterator) {
        !           476:                                        zval_ptr_dtor(&iterator);
        !           477:                                }
        !           478:                                iterator = caching_it;
        !           479:                                inc_refcount = 0;
        !           480:                        } else {
        !           481:                                iterator = NULL;
        !           482:                        }
        !           483:                        break;
        !           484:                }
        !           485:                case RIT_RecursiveIteratorIterator:
        !           486:                default: {
        !           487:                        mode = RIT_LEAVES_ONLY;
        !           488:                        flags = 0;
        !           489: 
        !           490:                        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "o|ll", &iterator, &mode, &flags) == SUCCESS) {
        !           491:                                if (instanceof_function(Z_OBJCE_P(iterator), zend_ce_aggregate TSRMLS_CC)) {
        !           492:                                        zval *aggregate = iterator;
        !           493:                                        zend_call_method_with_0_params(&aggregate, Z_OBJCE_P(aggregate), &Z_OBJCE_P(aggregate)->iterator_funcs.zf_new_iterator, "getiterator", &iterator);
        !           494:                                        inc_refcount = 0;
        !           495:                                }
        !           496:                        } else {
        !           497:                                iterator = NULL;
        !           498:                        }
        !           499:                        break;
        !           500:                }
        !           501:        }
        !           502:        if (!iterator || !instanceof_function(Z_OBJCE_P(iterator), spl_ce_RecursiveIterator TSRMLS_CC)) {
        !           503:                if (iterator && !inc_refcount) {
        !           504:                        zval_ptr_dtor(&iterator);
        !           505:                }
        !           506:                zend_throw_exception(spl_ce_InvalidArgumentException, "An instance of RecursiveIterator or IteratorAggregate creating it is required", 0 TSRMLS_CC);
        !           507:                zend_restore_error_handling(&error_handling TSRMLS_CC);
        !           508:                return;
        !           509:        }
        !           510: 
        !           511:        intern = (spl_recursive_it_object*)zend_object_store_get_object(object TSRMLS_CC);
        !           512:        intern->iterators = emalloc(sizeof(spl_sub_iterator));
        !           513:        intern->level = 0;
        !           514:        intern->mode = mode;
        !           515:        intern->flags = flags;
        !           516:        intern->max_depth = -1;
        !           517:        intern->in_iteration = 0;
        !           518:        intern->ce = Z_OBJCE_P(object);
        !           519: 
        !           520:        zend_hash_find(&intern->ce->function_table, "beginiteration", sizeof("beginiteration"), (void **) &intern->beginIteration);
        !           521:        if (intern->beginIteration->common.scope == ce_base) {
        !           522:                intern->beginIteration = NULL;
        !           523:        }
        !           524:        zend_hash_find(&intern->ce->function_table, "enditeration", sizeof("enditeration"), (void **) &intern->endIteration);
        !           525:        if (intern->endIteration->common.scope == ce_base) {
        !           526:                intern->endIteration = NULL;
        !           527:        }
        !           528:        zend_hash_find(&intern->ce->function_table, "callhaschildren", sizeof("callHasChildren"), (void **) &intern->callHasChildren);
        !           529:        if (intern->callHasChildren->common.scope == ce_base) {
        !           530:                intern->callHasChildren = NULL;
        !           531:        }
        !           532:        zend_hash_find(&intern->ce->function_table, "callgetchildren", sizeof("callGetChildren"), (void **) &intern->callGetChildren);
        !           533:        if (intern->callGetChildren->common.scope == ce_base) {
        !           534:                intern->callGetChildren = NULL;
        !           535:        }
        !           536:        zend_hash_find(&intern->ce->function_table, "beginchildren", sizeof("beginchildren"), (void **) &intern->beginChildren);
        !           537:        if (intern->beginChildren->common.scope == ce_base) {
        !           538:                intern->beginChildren = NULL;
        !           539:        }
        !           540:        zend_hash_find(&intern->ce->function_table, "endchildren", sizeof("endchildren"), (void **) &intern->endChildren);
        !           541:        if (intern->endChildren->common.scope == ce_base) {
        !           542:                intern->endChildren = NULL;
        !           543:        }
        !           544:        zend_hash_find(&intern->ce->function_table, "nextelement", sizeof("nextElement"), (void **) &intern->nextElement);
        !           545:        if (intern->nextElement->common.scope == ce_base) {
        !           546:                intern->nextElement = NULL;
        !           547:        }
        !           548:        ce_iterator = Z_OBJCE_P(iterator); /* respect inheritance, don't use spl_ce_RecursiveIterator */
        !           549:        intern->iterators[0].iterator = ce_iterator->get_iterator(ce_iterator, iterator, 0 TSRMLS_CC);
        !           550:        if (inc_refcount) {
        !           551:                Z_ADDREF_P(iterator);
        !           552:        }
        !           553:        intern->iterators[0].zobject = iterator;
        !           554:        intern->iterators[0].ce = ce_iterator;
        !           555:        intern->iterators[0].state = RS_START;
        !           556: 
        !           557:        zend_restore_error_handling(&error_handling TSRMLS_CC);
        !           558: 
        !           559:        if (EG(exception)) {
        !           560:                zend_object_iterator *sub_iter;
        !           561: 
        !           562:                while (intern->level >= 0) {
        !           563:                        sub_iter = intern->iterators[intern->level].iterator;
        !           564:                        sub_iter->funcs->dtor(sub_iter TSRMLS_CC);
        !           565:                        zval_ptr_dtor(&intern->iterators[intern->level--].zobject);
        !           566:                }
        !           567:                efree(intern->iterators);
        !           568:                intern->iterators = NULL;
        !           569:        }
        !           570: }
        !           571: 
        !           572: /* {{{ proto void RecursiveIteratorIterator::__construct(RecursiveIterator|IteratorAggregate it [, int mode = RIT_LEAVES_ONLY [, int flags = 0]]) throws InvalidArgumentException
        !           573:    Creates a RecursiveIteratorIterator from a RecursiveIterator. */
        !           574: SPL_METHOD(RecursiveIteratorIterator, __construct)
        !           575: {
        !           576:        spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_RecursiveIteratorIterator, zend_ce_iterator, RIT_RecursiveIteratorIterator);
        !           577: } /* }}} */
        !           578: 
        !           579: /* {{{ proto void RecursiveIteratorIterator::rewind()
        !           580:    Rewind the iterator to the first element of the top level inner iterator. */
        !           581: SPL_METHOD(RecursiveIteratorIterator, rewind)
        !           582: {
        !           583:        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        !           584:        
        !           585:        if (zend_parse_parameters_none() == FAILURE) {
        !           586:                return;
        !           587:        }
        !           588: 
        !           589:        spl_recursive_it_rewind_ex(object, getThis() TSRMLS_CC);
        !           590: } /* }}} */
        !           591: 
        !           592: /* {{{ proto bool RecursiveIteratorIterator::valid()
        !           593:    Check whether the current position is valid */
        !           594: SPL_METHOD(RecursiveIteratorIterator, valid)
        !           595: {
        !           596:        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        !           597:        
        !           598:        if (zend_parse_parameters_none() == FAILURE) {
        !           599:                return;
        !           600:        }
        !           601: 
        !           602:        RETURN_BOOL(spl_recursive_it_valid_ex(object, getThis() TSRMLS_CC) == SUCCESS);
        !           603: } /* }}} */
        !           604: 
        !           605: /* {{{ proto mixed RecursiveIteratorIterator::key()
        !           606:    Access the current key */
        !           607: SPL_METHOD(RecursiveIteratorIterator, key)
        !           608: {
        !           609:        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        !           610:        zend_object_iterator      *iterator = object->iterators[object->level].iterator;
        !           611:        
        !           612:        if (zend_parse_parameters_none() == FAILURE) {
        !           613:                return;
        !           614:        }
        !           615: 
        !           616:        if (iterator->funcs->get_current_key) {
        !           617:                char *str_key;
        !           618:                uint str_key_len;
        !           619:                ulong int_key;
        !           620: 
        !           621:                switch (iterator->funcs->get_current_key(iterator, &str_key, &str_key_len, &int_key TSRMLS_CC)) {
        !           622:                        case HASH_KEY_IS_LONG:
        !           623:                                RETURN_LONG(int_key);
        !           624:                                break;
        !           625:                        case HASH_KEY_IS_STRING:
        !           626:                                RETURN_STRINGL(str_key, str_key_len-1, 0);
        !           627:                                break;
        !           628:                        default:
        !           629:                                RETURN_NULL();
        !           630:                }
        !           631:        } else {
        !           632:                RETURN_NULL();
        !           633:        }
        !           634: } /* }}} */
        !           635: 
        !           636: /* {{{ proto mixed RecursiveIteratorIterator::current()
        !           637:    Access the current element value */
        !           638: SPL_METHOD(RecursiveIteratorIterator, current)
        !           639: {
        !           640:        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        !           641:        zend_object_iterator      *iterator = object->iterators[object->level].iterator;
        !           642:        zval                      **data;
        !           643:        
        !           644:        if (zend_parse_parameters_none() == FAILURE) {
        !           645:                return;
        !           646:        }
        !           647: 
        !           648:        iterator->funcs->get_current_data(iterator, &data TSRMLS_CC);
        !           649:        if (data && *data) {
        !           650:                RETURN_ZVAL(*data, 1, 0);
        !           651:        }
        !           652: } /* }}} */
        !           653: 
        !           654: /* {{{ proto void RecursiveIteratorIterator::next()
        !           655:    Move forward to the next element */
        !           656: SPL_METHOD(RecursiveIteratorIterator, next)
        !           657: {
        !           658:        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        !           659:        
        !           660:        if (zend_parse_parameters_none() == FAILURE) {
        !           661:                return;
        !           662:        }
        !           663: 
        !           664:        spl_recursive_it_move_forward_ex(object, getThis() TSRMLS_CC);
        !           665: } /* }}} */
        !           666: 
        !           667: /* {{{ proto int RecursiveIteratorIterator::getDepth()
        !           668:    Get the current depth of the recursive iteration */
        !           669: SPL_METHOD(RecursiveIteratorIterator, getDepth)
        !           670: {
        !           671:        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        !           672:        
        !           673:        if (zend_parse_parameters_none() == FAILURE) {
        !           674:                return;
        !           675:        }
        !           676:        
        !           677:        RETURN_LONG(object->level);
        !           678: } /* }}} */
        !           679: 
        !           680: /* {{{ proto RecursiveIterator RecursiveIteratorIterator::getSubIterator([int level])
        !           681:    The current active sub iterator or the iterator at specified level */
        !           682: SPL_METHOD(RecursiveIteratorIterator, getSubIterator)
        !           683: {
        !           684:        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        !           685:        long  level = object->level;
        !           686:        
        !           687:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &level) == FAILURE) {
        !           688:                return;
        !           689:        }
        !           690:        if (level < 0 || level > object->level) {
        !           691:                RETURN_NULL();
        !           692:        }
        !           693:        RETURN_ZVAL(object->iterators[level].zobject, 1, 0);
        !           694: } /* }}} */
        !           695: 
        !           696: /* {{{ proto RecursiveIterator RecursiveIteratorIterator::getInnerIterator()
        !           697:    The current active sub iterator */
        !           698: SPL_METHOD(RecursiveIteratorIterator, getInnerIterator)
        !           699: {
        !           700:        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        !           701:        long  level = object->level;
        !           702:        
        !           703:        if (zend_parse_parameters_none() == FAILURE) {
        !           704:                return;
        !           705:        }
        !           706:        
        !           707:        RETURN_ZVAL(object->iterators[level].zobject, 1, 0);
        !           708: } /* }}} */
        !           709: 
        !           710: /* {{{ proto RecursiveIterator RecursiveIteratorIterator::beginIteration()
        !           711:    Called when iteration begins (after first rewind() call) */
        !           712: SPL_METHOD(RecursiveIteratorIterator, beginIteration)
        !           713: {
        !           714:        if (zend_parse_parameters_none() == FAILURE) {
        !           715:                return;
        !           716:        }
        !           717:        /* nothing to do */
        !           718: } /* }}} */
        !           719: 
        !           720: /* {{{ proto RecursiveIterator RecursiveIteratorIterator::endIteration()
        !           721:    Called when iteration ends (when valid() first returns false */
        !           722: SPL_METHOD(RecursiveIteratorIterator, endIteration)
        !           723: {
        !           724:        if (zend_parse_parameters_none() == FAILURE) {
        !           725:                return;
        !           726:        }
        !           727:        /* nothing to do */
        !           728: } /* }}} */
        !           729: 
        !           730: /* {{{ proto bool RecursiveIteratorIterator::callHasChildren()
        !           731:    Called for each element to test whether it has children */
        !           732: SPL_METHOD(RecursiveIteratorIterator, callHasChildren)
        !           733: {
        !           734:        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        !           735:        zend_class_entry *ce = object->iterators[object->level].ce;
        !           736:        zval *retval, *zobject;
        !           737:        
        !           738:        if (zend_parse_parameters_none() == FAILURE) {
        !           739:                return;
        !           740:        }
        !           741: 
        !           742:        zobject = object->iterators[object->level].zobject;
        !           743:        if (!zobject) {
        !           744:                RETURN_FALSE;
        !           745:        } else {
        !           746:                zend_call_method_with_0_params(&zobject, ce, NULL, "haschildren", &retval);
        !           747:                if (retval) {
        !           748:                        RETURN_ZVAL(retval, 0, 1);
        !           749:                } else {
        !           750:                        RETURN_FALSE;
        !           751:                }
        !           752:        }
        !           753: } /* }}} */
        !           754: 
        !           755: /* {{{ proto RecursiveIterator RecursiveIteratorIterator::callGetChildren()
        !           756:    Return children of current element */
        !           757: SPL_METHOD(RecursiveIteratorIterator, callGetChildren)
        !           758: {
        !           759:        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        !           760:        zend_class_entry *ce = object->iterators[object->level].ce;
        !           761:        zval *retval, *zobject;
        !           762:        
        !           763:        if (zend_parse_parameters_none() == FAILURE) {
        !           764:                return;
        !           765:        }
        !           766: 
        !           767:        zobject = object->iterators[object->level].zobject;
        !           768:        if (!zobject) {
        !           769:                return;
        !           770:        } else {
        !           771:                zend_call_method_with_0_params(&zobject, ce, NULL, "getchildren", &retval);
        !           772:                if (retval) {
        !           773:                        RETURN_ZVAL(retval, 0, 1);
        !           774:                }
        !           775:        }
        !           776: } /* }}} */
        !           777: 
        !           778: /* {{{ proto void RecursiveIteratorIterator::beginChildren()
        !           779:    Called when recursing one level down */
        !           780: SPL_METHOD(RecursiveIteratorIterator, beginChildren)
        !           781: {
        !           782:        if (zend_parse_parameters_none() == FAILURE) {
        !           783:                return;
        !           784:        }
        !           785:        /* nothing to do */
        !           786: } /* }}} */
        !           787: 
        !           788: /* {{{ proto void RecursiveIteratorIterator::endChildren()
        !           789:    Called when end recursing one level */
        !           790: SPL_METHOD(RecursiveIteratorIterator, endChildren)
        !           791: {
        !           792:        if (zend_parse_parameters_none() == FAILURE) {
        !           793:                return;
        !           794:        }
        !           795:        /* nothing to do */
        !           796: } /* }}} */
        !           797: 
        !           798: /* {{{ proto void RecursiveIteratorIterator::nextElement()
        !           799:    Called when the next element is available */
        !           800: SPL_METHOD(RecursiveIteratorIterator, nextElement)
        !           801: {
        !           802:        if (zend_parse_parameters_none() == FAILURE) {
        !           803:                return;
        !           804:        }
        !           805:        /* nothing to do */
        !           806: } /* }}} */
        !           807: 
        !           808: /* {{{ proto void RecursiveIteratorIterator::setMaxDepth([$max_depth = -1])
        !           809:    Set the maximum allowed depth (or any depth if pmax_depth = -1] */
        !           810: SPL_METHOD(RecursiveIteratorIterator, setMaxDepth)
        !           811: {
        !           812:        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        !           813:        long  max_depth = -1;
        !           814:        
        !           815:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &max_depth) == FAILURE) {
        !           816:                return;
        !           817:        }
        !           818:        if (max_depth < -1) {
        !           819:                zend_throw_exception(spl_ce_OutOfRangeException, "Parameter max_depth must be >= -1", 0 TSRMLS_CC);
        !           820:                return;
        !           821:        }
        !           822:        object->max_depth = max_depth;
        !           823: } /* }}} */
        !           824: 
        !           825: /* {{{ proto int|false RecursiveIteratorIterator::getMaxDepth()
        !           826:    Return the maximum accepted depth or false if any depth is allowed */
        !           827: SPL_METHOD(RecursiveIteratorIterator, getMaxDepth)
        !           828: {
        !           829:        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        !           830: 
        !           831:        if (zend_parse_parameters_none() == FAILURE) {
        !           832:                return;
        !           833:        }
        !           834:        
        !           835:        if (object->max_depth == -1) {
        !           836:                RETURN_FALSE;
        !           837:        } else {
        !           838:                RETURN_LONG(object->max_depth);
        !           839:        }
        !           840: } /* }}} */
        !           841: 
        !           842: static union _zend_function *spl_recursive_it_get_method(zval **object_ptr, char *method, int method_len TSRMLS_DC)
        !           843: {
        !           844:        union _zend_function    *function_handler;
        !           845:        spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(*object_ptr TSRMLS_CC);
        !           846:        long                     level = object->level;
        !           847:        zval                    *zobj;
        !           848: 
        !           849:        if (!object->iterators) {
        !           850:                php_error_docref(NULL TSRMLS_CC, E_ERROR, "The %s instance wasn't initialized properly", Z_OBJCE_PP(object_ptr)->name);
        !           851:        }
        !           852:        zobj = object->iterators[level].zobject;
        !           853: 
        !           854:        function_handler = std_object_handlers.get_method(object_ptr, method, method_len TSRMLS_CC);
        !           855:        if (!function_handler) {
        !           856:                if (zend_hash_find(&Z_OBJCE_P(zobj)->function_table, method, method_len+1, (void **) &function_handler) == FAILURE) {
        !           857:                        if (Z_OBJ_HT_P(zobj)->get_method) {
        !           858:                                *object_ptr = zobj;
        !           859:                                function_handler = Z_OBJ_HT_P(*object_ptr)->get_method(object_ptr, method, method_len TSRMLS_CC);
        !           860:                        }
        !           861:                }
        !           862:        }
        !           863:        return function_handler;
        !           864: }
        !           865: 
        !           866: /* {{{ spl_RecursiveIteratorIterator_dtor */
        !           867: static void spl_RecursiveIteratorIterator_dtor(zend_object *_object, zend_object_handle handle TSRMLS_DC)
        !           868: {
        !           869:        spl_recursive_it_object   *object = (spl_recursive_it_object *)_object;
        !           870:        zend_object_iterator      *sub_iter;
        !           871: 
        !           872:        /* call standard dtor */
        !           873:        zend_objects_destroy_object(_object, handle TSRMLS_CC);
        !           874: 
        !           875:        if (object->iterators) {
        !           876:                while (object->level >= 0) {
        !           877:                        sub_iter = object->iterators[object->level].iterator;
        !           878:                        sub_iter->funcs->dtor(sub_iter TSRMLS_CC);
        !           879:                        zval_ptr_dtor(&object->iterators[object->level--].zobject);
        !           880:                }
        !           881:                efree(object->iterators);
        !           882:                object->iterators = NULL;
        !           883:        }
        !           884: }
        !           885: /* }}} */
        !           886: 
        !           887: /* {{{ spl_RecursiveIteratorIterator_dtor */
        !           888: static void spl_RecursiveIteratorIterator_free_storage(void *_object TSRMLS_DC)
        !           889: {
        !           890:        spl_recursive_it_object   *object = (spl_recursive_it_object *)_object;
        !           891: 
        !           892:        zend_object_std_dtor(&object->std TSRMLS_CC);
        !           893:        smart_str_free(&object->prefix[0]);
        !           894:        smart_str_free(&object->prefix[1]);
        !           895:        smart_str_free(&object->prefix[2]);
        !           896:        smart_str_free(&object->prefix[3]);
        !           897:        smart_str_free(&object->prefix[4]);
        !           898:        smart_str_free(&object->prefix[5]);
        !           899: 
        !           900:        efree(object);
        !           901: }
        !           902: /* }}} */
        !           903: 
        !           904: /* {{{ spl_RecursiveIteratorIterator_new_ex */
        !           905: static zend_object_value spl_RecursiveIteratorIterator_new_ex(zend_class_entry *class_type, int init_prefix TSRMLS_DC)
        !           906: {
        !           907:        zend_object_value retval;
        !           908:        spl_recursive_it_object *intern;
        !           909:        zval *tmp;
        !           910: 
        !           911:        intern = emalloc(sizeof(spl_recursive_it_object));
        !           912:        memset(intern, 0, sizeof(spl_recursive_it_object));
        !           913: 
        !           914:        if (init_prefix) {
        !           915:                smart_str_appendl(&intern->prefix[0], "",    0);
        !           916:                smart_str_appendl(&intern->prefix[1], "| ",  2);
        !           917:                smart_str_appendl(&intern->prefix[2], "  ",  2);
        !           918:                smart_str_appendl(&intern->prefix[3], "|-",  2);
        !           919:                smart_str_appendl(&intern->prefix[4], "\\-", 2);
        !           920:                smart_str_appendl(&intern->prefix[5], "",    0);
        !           921:        }
        !           922: 
        !           923:        zend_object_std_init(&intern->std, class_type TSRMLS_CC);
        !           924:        zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
        !           925: 
        !           926:        retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)spl_RecursiveIteratorIterator_dtor, (zend_objects_free_object_storage_t) spl_RecursiveIteratorIterator_free_storage, NULL TSRMLS_CC);
        !           927:        retval.handlers = &spl_handlers_rec_it_it;
        !           928:        return retval;
        !           929: }
        !           930: /* }}} */
        !           931: 
        !           932: /* {{{ spl_RecursiveIteratorIterator_new */
        !           933: static zend_object_value spl_RecursiveIteratorIterator_new(zend_class_entry *class_type TSRMLS_DC)
        !           934: {
        !           935:        return spl_RecursiveIteratorIterator_new_ex(class_type, 0 TSRMLS_CC);
        !           936: }
        !           937: /* }}} */
        !           938: 
        !           939: /* {{{ spl_RecursiveTreeIterator_new */
        !           940: static zend_object_value spl_RecursiveTreeIterator_new(zend_class_entry *class_type TSRMLS_DC)
        !           941: {
        !           942:        return spl_RecursiveIteratorIterator_new_ex(class_type, 1 TSRMLS_CC);
        !           943: }
        !           944: /* }}} */
        !           945: 
        !           946: ZEND_BEGIN_ARG_INFO_EX(arginfo_recursive_it___construct, 0, 0, 1) 
        !           947:        ZEND_ARG_OBJ_INFO(0, iterator, Traversable, 0)
        !           948:        ZEND_ARG_INFO(0, mode)
        !           949:        ZEND_ARG_INFO(0, flags)
        !           950: ZEND_END_ARG_INFO();
        !           951: 
        !           952: ZEND_BEGIN_ARG_INFO_EX(arginfo_recursive_it_getSubIterator, 0, 0, 0)
        !           953:        ZEND_ARG_INFO(0, level)
        !           954: ZEND_END_ARG_INFO();
        !           955: 
        !           956: ZEND_BEGIN_ARG_INFO_EX(arginfo_recursive_it_setMaxDepth, 0, 0, 0)
        !           957:        ZEND_ARG_INFO(0, max_depth)
        !           958: ZEND_END_ARG_INFO();
        !           959: 
        !           960: static const zend_function_entry spl_funcs_RecursiveIteratorIterator[] = {
        !           961:        SPL_ME(RecursiveIteratorIterator, __construct,       arginfo_recursive_it___construct,    ZEND_ACC_PUBLIC)
        !           962:        SPL_ME(RecursiveIteratorIterator, rewind,            arginfo_recursive_it_void,           ZEND_ACC_PUBLIC)
        !           963:        SPL_ME(RecursiveIteratorIterator, valid,             arginfo_recursive_it_void,           ZEND_ACC_PUBLIC)
        !           964:        SPL_ME(RecursiveIteratorIterator, key,               arginfo_recursive_it_void,           ZEND_ACC_PUBLIC)
        !           965:        SPL_ME(RecursiveIteratorIterator, current,           arginfo_recursive_it_void,           ZEND_ACC_PUBLIC)
        !           966:        SPL_ME(RecursiveIteratorIterator, next,              arginfo_recursive_it_void,           ZEND_ACC_PUBLIC)
        !           967:        SPL_ME(RecursiveIteratorIterator, getDepth,          arginfo_recursive_it_void,           ZEND_ACC_PUBLIC)
        !           968:        SPL_ME(RecursiveIteratorIterator, getSubIterator,    arginfo_recursive_it_getSubIterator, ZEND_ACC_PUBLIC)
        !           969:        SPL_ME(RecursiveIteratorIterator, getInnerIterator,  arginfo_recursive_it_void,           ZEND_ACC_PUBLIC)
        !           970:        SPL_ME(RecursiveIteratorIterator, beginIteration,    arginfo_recursive_it_void,           ZEND_ACC_PUBLIC)
        !           971:        SPL_ME(RecursiveIteratorIterator, endIteration,      arginfo_recursive_it_void,           ZEND_ACC_PUBLIC)
        !           972:        SPL_ME(RecursiveIteratorIterator, callHasChildren,   arginfo_recursive_it_void,           ZEND_ACC_PUBLIC)
        !           973:        SPL_ME(RecursiveIteratorIterator, callGetChildren,   arginfo_recursive_it_void,           ZEND_ACC_PUBLIC)
        !           974:        SPL_ME(RecursiveIteratorIterator, beginChildren,     arginfo_recursive_it_void,           ZEND_ACC_PUBLIC)
        !           975:        SPL_ME(RecursiveIteratorIterator, endChildren,       arginfo_recursive_it_void,           ZEND_ACC_PUBLIC)
        !           976:        SPL_ME(RecursiveIteratorIterator, nextElement,       arginfo_recursive_it_void,           ZEND_ACC_PUBLIC)
        !           977:        SPL_ME(RecursiveIteratorIterator, setMaxDepth,       arginfo_recursive_it_setMaxDepth,    ZEND_ACC_PUBLIC)
        !           978:        SPL_ME(RecursiveIteratorIterator, getMaxDepth,       arginfo_recursive_it_void,           ZEND_ACC_PUBLIC)
        !           979:        PHP_FE_END
        !           980: };
        !           981: 
        !           982: static void spl_recursive_tree_iterator_get_prefix(spl_recursive_it_object *object, zval *return_value TSRMLS_DC)
        !           983: {
        !           984:        smart_str  str = {0};
        !           985:        zval      *has_next;
        !           986:        int        level;
        !           987: 
        !           988:        smart_str_appendl(&str, object->prefix[0].c, object->prefix[0].len);
        !           989:        
        !           990:        for (level = 0; level < object->level; ++level) {
        !           991:                zend_call_method_with_0_params(&object->iterators[level].zobject, object->iterators[level].ce, NULL, "hasnext", &has_next);
        !           992:                if (has_next) {
        !           993:                        if (Z_LVAL_P(has_next)) {
        !           994:                                smart_str_appendl(&str, object->prefix[1].c, object->prefix[1].len);
        !           995:                        } else {
        !           996:                                smart_str_appendl(&str, object->prefix[2].c, object->prefix[2].len);
        !           997:                        }
        !           998:                        zval_ptr_dtor(&has_next);
        !           999:                }
        !          1000:        }
        !          1001:        zend_call_method_with_0_params(&object->iterators[level].zobject, object->iterators[level].ce, NULL, "hasnext", &has_next);
        !          1002:        if (has_next) {
        !          1003:                if (Z_LVAL_P(has_next)) {
        !          1004:                        smart_str_appendl(&str, object->prefix[3].c, object->prefix[3].len);
        !          1005:                } else {
        !          1006:                        smart_str_appendl(&str, object->prefix[4].c, object->prefix[4].len);
        !          1007:                }
        !          1008:                zval_ptr_dtor(&has_next);
        !          1009:        }
        !          1010: 
        !          1011:        smart_str_appendl(&str, object->prefix[5].c, object->prefix[5].len);
        !          1012:        smart_str_0(&str);
        !          1013: 
        !          1014:        RETVAL_STRINGL(str.c, str.len, 0);
        !          1015: }
        !          1016: 
        !          1017: static void spl_recursive_tree_iterator_get_entry(spl_recursive_it_object * object, zval * return_value TSRMLS_DC)
        !          1018: {
        !          1019:        zend_object_iterator      *iterator = object->iterators[object->level].iterator;
        !          1020:        zval                     **data;
        !          1021:        zend_error_handling        error_handling;
        !          1022: 
        !          1023:        iterator->funcs->get_current_data(iterator, &data TSRMLS_CC);
        !          1024: 
        !          1025:        zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling TSRMLS_CC);
        !          1026:        if (data && *data) {
        !          1027:                RETVAL_ZVAL(*data, 1, 0);
        !          1028:        }
        !          1029:        if (Z_TYPE_P(return_value) == IS_ARRAY) {
        !          1030:                zval_dtor(return_value);
        !          1031:                ZVAL_STRINGL(return_value, "Array", sizeof("Array")-1, 1);
        !          1032:        } else {
        !          1033:                convert_to_string(return_value);
        !          1034:        }
        !          1035:        zend_restore_error_handling(&error_handling TSRMLS_CC);
        !          1036: }
        !          1037: 
        !          1038: static void spl_recursive_tree_iterator_get_postfix(spl_recursive_it_object * object, zval * return_value TSRMLS_DC)
        !          1039: {
        !          1040:        RETVAL_STRINGL("", 0, 1);
        !          1041: }
        !          1042: 
        !          1043: /* {{{ proto void RecursiveTreeIterator::__construct(RecursiveIterator|IteratorAggregate it [, int flags = RTIT_BYPASS_KEY [, int cit_flags = CIT_CATCH_GET_CHILD [, mode = RIT_SELF_FIRST ]]]) throws InvalidArgumentException
        !          1044:    RecursiveIteratorIterator to generate ASCII graphic trees for the entries in a RecursiveIterator */
        !          1045: SPL_METHOD(RecursiveTreeIterator, __construct)
        !          1046: {
        !          1047:        spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_RecursiveTreeIterator, zend_ce_iterator, RIT_RecursiveTreeIterator);
        !          1048: } /* }}} */
        !          1049: 
        !          1050: /* {{{ proto void RecursiveTreeIterator::setPrefixPart(int part, string prefix) throws OutOfRangeException
        !          1051:    Sets prefix parts as used in getPrefix() */
        !          1052: SPL_METHOD(RecursiveTreeIterator, setPrefixPart)
        !          1053: {
        !          1054:        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        !          1055:        long  part;
        !          1056:        char* prefix;
        !          1057:        int   prefix_len;
        !          1058:        
        !          1059:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &part, &prefix, &prefix_len) == FAILURE) {
        !          1060:                return;
        !          1061:        }
        !          1062:        if (0 > part || part > 5) {
        !          1063:                zend_throw_exception_ex(spl_ce_OutOfRangeException, 0 TSRMLS_CC, "Use RecursiveTreeIterator::PREFIX_* constant");
        !          1064:                return;
        !          1065:        }
        !          1066:        
        !          1067:        smart_str_free(&object->prefix[part]);
        !          1068:        smart_str_appendl(&object->prefix[part], prefix, prefix_len);
        !          1069: } /* }}} */
        !          1070: 
        !          1071: /* {{{ proto string RecursiveTreeIterator::getPrefix()
        !          1072:    Returns the string to place in front of current element */
        !          1073: SPL_METHOD(RecursiveTreeIterator, getPrefix)
        !          1074: {
        !          1075:        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        !          1076: 
        !          1077:        if (zend_parse_parameters_none() == FAILURE) {
        !          1078:                return;
        !          1079:        }
        !          1080:        spl_recursive_tree_iterator_get_prefix(object, return_value TSRMLS_CC);
        !          1081: } /* }}} */
        !          1082: 
        !          1083: /* {{{ proto string RecursiveTreeIterator::getEntry()
        !          1084:    Returns the string presentation built for current element */
        !          1085: SPL_METHOD(RecursiveTreeIterator, getEntry)
        !          1086: {
        !          1087:        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        !          1088: 
        !          1089:        if (zend_parse_parameters_none() == FAILURE) {
        !          1090:                return;
        !          1091:        }
        !          1092:        
        !          1093:        spl_recursive_tree_iterator_get_entry(object, return_value TSRMLS_CC);
        !          1094: } /* }}} */
        !          1095: 
        !          1096: /* {{{ proto string RecursiveTreeIterator::getPostfix()
        !          1097:    Returns the string to place after the current element */
        !          1098: SPL_METHOD(RecursiveTreeIterator, getPostfix)
        !          1099: {
        !          1100:        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        !          1101: 
        !          1102:        if (zend_parse_parameters_none() == FAILURE) {
        !          1103:                return;
        !          1104:        }
        !          1105:        
        !          1106:        spl_recursive_tree_iterator_get_postfix(object, return_value TSRMLS_CC);
        !          1107: } /* }}} */
        !          1108: 
        !          1109: /* {{{ proto mixed RecursiveTreeIterator::current()
        !          1110:    Returns the current element prefixed and postfixed */
        !          1111: SPL_METHOD(RecursiveTreeIterator, current)
        !          1112: {
        !          1113:        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        !          1114:        zval                       prefix, entry, postfix;
        !          1115:        char                      *str, *ptr;
        !          1116:        size_t                     str_len;
        !          1117:        
        !          1118:        if (zend_parse_parameters_none() == FAILURE) {
        !          1119:                return;
        !          1120:        }
        !          1121: 
        !          1122:        if (object->flags & RTIT_BYPASS_CURRENT) {
        !          1123:                zend_object_iterator      *iterator = object->iterators[object->level].iterator;
        !          1124:                zval                      **data;
        !          1125: 
        !          1126:                iterator->funcs->get_current_data(iterator, &data TSRMLS_CC);
        !          1127:                if (data && *data) {
        !          1128:                        RETURN_ZVAL(*data, 1, 0);
        !          1129:                } else {
        !          1130:                        RETURN_NULL();
        !          1131:                }
        !          1132:        }
        !          1133: 
        !          1134:        spl_recursive_tree_iterator_get_prefix(object, &prefix TSRMLS_CC);
        !          1135:        spl_recursive_tree_iterator_get_entry(object, &entry TSRMLS_CC);
        !          1136:        spl_recursive_tree_iterator_get_postfix(object, &postfix TSRMLS_CC);
        !          1137: 
        !          1138:        str_len = Z_STRLEN(prefix) + Z_STRLEN(entry) + Z_STRLEN(postfix);
        !          1139:        str = (char *) emalloc(str_len + 1U);
        !          1140:        ptr = str;
        !          1141: 
        !          1142:        memcpy(ptr, Z_STRVAL(prefix), Z_STRLEN(prefix));
        !          1143:        ptr += Z_STRLEN(prefix);
        !          1144:        memcpy(ptr, Z_STRVAL(entry), Z_STRLEN(entry));
        !          1145:        ptr += Z_STRLEN(entry);
        !          1146:        memcpy(ptr, Z_STRVAL(postfix), Z_STRLEN(postfix));
        !          1147:        ptr += Z_STRLEN(postfix);
        !          1148:        *ptr = 0;
        !          1149: 
        !          1150:        zval_dtor(&prefix);
        !          1151:        zval_dtor(&entry);
        !          1152:        zval_dtor(&postfix);
        !          1153: 
        !          1154:        RETURN_STRINGL(str, str_len, 0);
        !          1155: } /* }}} */
        !          1156: 
        !          1157: /* {{{ proto mixed RecursiveTreeIterator::key()
        !          1158:    Returns the current key prefixed and postfixed */
        !          1159: SPL_METHOD(RecursiveTreeIterator, key)
        !          1160: {
        !          1161:        spl_recursive_it_object   *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        !          1162:        zend_object_iterator      *iterator = object->iterators[object->level].iterator;
        !          1163:        zval                       prefix, key, postfix, key_copy;
        !          1164:        char                      *str, *ptr;
        !          1165:        size_t                     str_len;
        !          1166:        
        !          1167:        if (zend_parse_parameters_none() == FAILURE) {
        !          1168:                return;
        !          1169:        }
        !          1170: 
        !          1171:        if (iterator->funcs->get_current_key) {
        !          1172:                char *str_key;
        !          1173:                uint str_key_len;
        !          1174:                ulong int_key;
        !          1175: 
        !          1176:                switch (iterator->funcs->get_current_key(iterator, &str_key, &str_key_len, &int_key TSRMLS_CC)) {
        !          1177:                        case HASH_KEY_IS_LONG:
        !          1178:                                ZVAL_LONG(&key, int_key);
        !          1179:                                break;
        !          1180:                        case HASH_KEY_IS_STRING:
        !          1181:                                ZVAL_STRINGL(&key, str_key, str_key_len-1, 0);
        !          1182:                                break;
        !          1183:                        default:
        !          1184:                                ZVAL_NULL(&key);
        !          1185:                }
        !          1186:        } else {
        !          1187:                ZVAL_NULL(&key);
        !          1188:        }
        !          1189: 
        !          1190:        if (object->flags & RTIT_BYPASS_KEY) {
        !          1191:                zval *key_ptr = &key;
        !          1192:                RETVAL_ZVAL(key_ptr, 1, 0);
        !          1193:                zval_dtor(&key);
        !          1194:                return;
        !          1195:        }
        !          1196: 
        !          1197:        if (Z_TYPE(key) != IS_STRING) {
        !          1198:                int use_copy;
        !          1199:                zend_make_printable_zval(&key, &key_copy, &use_copy);
        !          1200:                if (use_copy) {
        !          1201:                        key = key_copy;
        !          1202:                }
        !          1203:        }
        !          1204: 
        !          1205:        spl_recursive_tree_iterator_get_prefix(object, &prefix TSRMLS_CC);
        !          1206:        spl_recursive_tree_iterator_get_postfix(object, &postfix TSRMLS_CC);
        !          1207: 
        !          1208:        str_len = Z_STRLEN(prefix) + Z_STRLEN(key) + Z_STRLEN(postfix);
        !          1209:        str = (char *) emalloc(str_len + 1U);
        !          1210:        ptr = str;
        !          1211: 
        !          1212:        memcpy(ptr, Z_STRVAL(prefix), Z_STRLEN(prefix));
        !          1213:        ptr += Z_STRLEN(prefix);
        !          1214:        memcpy(ptr, Z_STRVAL(key), Z_STRLEN(key));
        !          1215:        ptr += Z_STRLEN(key);
        !          1216:        memcpy(ptr, Z_STRVAL(postfix), Z_STRLEN(postfix));
        !          1217:        ptr += Z_STRLEN(postfix);
        !          1218:        *ptr = 0;
        !          1219: 
        !          1220:        zval_dtor(&prefix);
        !          1221:        zval_dtor(&key);
        !          1222:        zval_dtor(&postfix);
        !          1223: 
        !          1224:        RETVAL_STRINGL(str, str_len, 0);
        !          1225: } /* }}} */
        !          1226: 
        !          1227: ZEND_BEGIN_ARG_INFO_EX(arginfo_recursive_tree_it___construct, 0, 0, 1) 
        !          1228:        ZEND_ARG_OBJ_INFO(0, iterator, Traversable, 0)
        !          1229:        ZEND_ARG_INFO(0, flags)
        !          1230:        ZEND_ARG_INFO(0, caching_it_flags)
        !          1231:        ZEND_ARG_INFO(0, mode)
        !          1232: ZEND_END_ARG_INFO();
        !          1233: 
        !          1234: ZEND_BEGIN_ARG_INFO_EX(arginfo_recursive_tree_it_setPrefixPart, 0, 0, 2)
        !          1235:        ZEND_ARG_INFO(0, part)
        !          1236:        ZEND_ARG_INFO(0, value)
        !          1237: ZEND_END_ARG_INFO();
        !          1238: 
        !          1239: static const zend_function_entry spl_funcs_RecursiveTreeIterator[] = {
        !          1240:        SPL_ME(RecursiveTreeIterator,     __construct,       arginfo_recursive_tree_it___construct,   ZEND_ACC_PUBLIC)
        !          1241:        SPL_ME(RecursiveIteratorIterator, rewind,            arginfo_recursive_it_void,               ZEND_ACC_PUBLIC)
        !          1242:        SPL_ME(RecursiveIteratorIterator, valid,             arginfo_recursive_it_void,               ZEND_ACC_PUBLIC)
        !          1243:        SPL_ME(RecursiveTreeIterator,     key,               arginfo_recursive_it_void,               ZEND_ACC_PUBLIC)
        !          1244:        SPL_ME(RecursiveTreeIterator,     current,           arginfo_recursive_it_void,               ZEND_ACC_PUBLIC)
        !          1245:        SPL_ME(RecursiveIteratorIterator, next,              arginfo_recursive_it_void,               ZEND_ACC_PUBLIC)
        !          1246:        SPL_ME(RecursiveIteratorIterator, beginIteration,    arginfo_recursive_it_void,               ZEND_ACC_PUBLIC)
        !          1247:        SPL_ME(RecursiveIteratorIterator, endIteration,      arginfo_recursive_it_void,               ZEND_ACC_PUBLIC)
        !          1248:        SPL_ME(RecursiveIteratorIterator, callHasChildren,   arginfo_recursive_it_void,               ZEND_ACC_PUBLIC)
        !          1249:        SPL_ME(RecursiveIteratorIterator, callGetChildren,   arginfo_recursive_it_void,               ZEND_ACC_PUBLIC)
        !          1250:        SPL_ME(RecursiveIteratorIterator, beginChildren,     arginfo_recursive_it_void,               ZEND_ACC_PUBLIC)
        !          1251:        SPL_ME(RecursiveIteratorIterator, endChildren,       arginfo_recursive_it_void,               ZEND_ACC_PUBLIC)
        !          1252:        SPL_ME(RecursiveIteratorIterator, nextElement,       arginfo_recursive_it_void,               ZEND_ACC_PUBLIC)
        !          1253:        SPL_ME(RecursiveTreeIterator,     getPrefix,         arginfo_recursive_it_void,               ZEND_ACC_PUBLIC)
        !          1254:        SPL_ME(RecursiveTreeIterator,     setPrefixPart,     arginfo_recursive_tree_it_setPrefixPart, ZEND_ACC_PUBLIC)
        !          1255:        SPL_ME(RecursiveTreeIterator,     getEntry,          arginfo_recursive_it_void,               ZEND_ACC_PUBLIC)
        !          1256:        SPL_ME(RecursiveTreeIterator,     getPostfix,        arginfo_recursive_it_void,               ZEND_ACC_PUBLIC)
        !          1257:        PHP_FE_END
        !          1258: };
        !          1259: 
        !          1260: #if MBO_0
        !          1261: static int spl_dual_it_gets_implemented(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
        !          1262: {
        !          1263:        class_type->iterator_funcs.zf_valid = NULL;
        !          1264:        class_type->iterator_funcs.zf_current = NULL;
        !          1265:        class_type->iterator_funcs.zf_key = NULL;
        !          1266:        class_type->iterator_funcs.zf_next = NULL;
        !          1267:        class_type->iterator_funcs.zf_rewind = NULL;
        !          1268:        if (!class_type->iterator_funcs.funcs) {
        !          1269:                class_type->iterator_funcs.funcs = &zend_interface_iterator_funcs_iterator;
        !          1270:        }
        !          1271: 
        !          1272:        return SUCCESS;
        !          1273: }
        !          1274: #endif
        !          1275: 
        !          1276: static union _zend_function *spl_dual_it_get_method(zval **object_ptr, char *method, int method_len TSRMLS_DC)
        !          1277: {
        !          1278:        union _zend_function *function_handler;
        !          1279:        spl_dual_it_object   *intern;
        !          1280: 
        !          1281:        intern = (spl_dual_it_object*)zend_object_store_get_object(*object_ptr TSRMLS_CC);
        !          1282: 
        !          1283:        function_handler = std_object_handlers.get_method(object_ptr, method, method_len TSRMLS_CC);
        !          1284:        if (!function_handler && intern->inner.ce) {
        !          1285:                if (zend_hash_find(&intern->inner.ce->function_table, method, method_len+1, (void **) &function_handler) == FAILURE) {
        !          1286:                        if (Z_OBJ_HT_P(intern->inner.zobject)->get_method) {
        !          1287:                                *object_ptr = intern->inner.zobject;
        !          1288:                                function_handler = Z_OBJ_HT_P(*object_ptr)->get_method(object_ptr, method, method_len TSRMLS_CC);
        !          1289:                        }
        !          1290:                }
        !          1291:        }
        !          1292:        return function_handler;
        !          1293: }
        !          1294: 
        !          1295: #if MBO_0
        !          1296: int spl_dual_it_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
        !          1297: {
        !          1298:        zval ***func_params, func;
        !          1299:        zval *retval_ptr;
        !          1300:        int arg_count;
        !          1301:        int current = 0;
        !          1302:        int success;
        !          1303:        void **p;
        !          1304:        spl_dual_it_object   *intern;
        !          1305: 
        !          1306:        intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        !          1307: 
        !          1308:        ZVAL_STRING(&func, method, 0);
        !          1309:        if (!zend_is_callable(&func, 0, &method TSRMLS_CC)) {
        !          1310:                php_error_docref(NULL TSRMLS_CC, E_ERROR, "Method %s::%s() does not exist", intern->inner.ce->name, method);
        !          1311:                return FAILURE;
        !          1312:        }
        !          1313: 
        !          1314:        p = EG(argument_stack).top_element-2;
        !          1315:        arg_count = (ulong) *p;
        !          1316: 
        !          1317:        func_params = safe_emalloc(sizeof(zval **), arg_count, 0);
        !          1318: 
        !          1319:        current = 0;
        !          1320:        while (arg_count-- > 0) {
        !          1321:                func_params[current] = (zval **) p - (arg_count-current);
        !          1322:                current++;
        !          1323:        }
        !          1324:        arg_count = current; /* restore */
        !          1325: 
        !          1326:        if (call_user_function_ex(EG(function_table), NULL, &func, &retval_ptr, arg_count, func_params, 0, NULL TSRMLS_CC) == SUCCESS && retval_ptr) {
        !          1327:                RETURN_ZVAL(retval_ptr, 0, 1);
        !          1328:                
        !          1329:                success = SUCCESS;
        !          1330:        } else {
        !          1331:                php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to call %s::%s()", intern->inner.ce->name, method);
        !          1332:                success = FAILURE;
        !          1333:        }
        !          1334: 
        !          1335:        efree(func_params); 
        !          1336:        return success;
        !          1337: }
        !          1338: #endif
        !          1339: 
        !          1340: #define SPL_CHECK_CTOR(intern, classname) \
        !          1341:        if (intern->dit_type == DIT_Unknown) { \
        !          1342:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Classes derived from %s must call %s::__construct()", \
        !          1343:                                (spl_ce_##classname)->name, (spl_ce_##classname)->name); \
        !          1344:                return; \
        !          1345:        }
        !          1346: 
        !          1347: #define APPENDIT_CHECK_CTOR(intern) SPL_CHECK_CTOR(intern, AppendIterator)
        !          1348: 
        !          1349: static inline int spl_dual_it_fetch(spl_dual_it_object *intern, int check_more TSRMLS_DC);
        !          1350: 
        !          1351: static inline int spl_cit_check_flags(int flags)
        !          1352: {
        !          1353:        int cnt = 0;
        !          1354: 
        !          1355:        cnt += (flags & CIT_CALL_TOSTRING) ? 1 : 0;
        !          1356:        cnt += (flags & CIT_TOSTRING_USE_KEY) ? 1 : 0;
        !          1357:        cnt += (flags & CIT_TOSTRING_USE_CURRENT) ? 1 : 0;
        !          1358:        cnt += (flags & CIT_TOSTRING_USE_INNER) ? 1 : 0;
        !          1359:        
        !          1360:        return cnt <= 1 ? SUCCESS : FAILURE;
        !          1361: }
        !          1362: 
        !          1363: static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *ce_base, zend_class_entry *ce_inner, dual_it_type dit_type)
        !          1364: {
        !          1365:        zval                 *zobject, *retval;
        !          1366:        spl_dual_it_object   *intern;
        !          1367:        zend_class_entry     *ce = NULL;
        !          1368:        int                   inc_refcount = 1;
        !          1369:        zend_error_handling   error_handling;
        !          1370: 
        !          1371:        intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        !          1372:        
        !          1373:        if (intern->dit_type != DIT_Unknown) {
        !          1374:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "%s::getIterator() must be called exactly once per instance", ce_base->name);
        !          1375:                return NULL;
        !          1376:        }
        !          1377: 
        !          1378:        zend_replace_error_handling(EH_THROW, spl_ce_InvalidArgumentException, &error_handling TSRMLS_CC);
        !          1379: 
        !          1380:        intern->dit_type = dit_type;
        !          1381:        switch (dit_type) {
        !          1382:                case DIT_LimitIterator: {
        !          1383:                        intern->u.limit.offset = 0; /* start at beginning */
        !          1384:                        intern->u.limit.count = -1; /* get all */
        !          1385:                        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|ll", &zobject, ce_inner, &intern->u.limit.offset, &intern->u.limit.count) == FAILURE) {
        !          1386:                                zend_restore_error_handling(&error_handling TSRMLS_CC);
        !          1387:                                return NULL;
        !          1388:                        }
        !          1389:                        if (intern->u.limit.offset < 0) {
        !          1390:                                zend_throw_exception(spl_ce_OutOfRangeException, "Parameter offset must be >= 0", 0 TSRMLS_CC);
        !          1391:                                zend_restore_error_handling(&error_handling TSRMLS_CC);
        !          1392:                                return NULL;
        !          1393:                        }
        !          1394:                        if (intern->u.limit.count < 0 && intern->u.limit.count != -1) {
        !          1395:                                zend_throw_exception(spl_ce_OutOfRangeException, "Parameter count must either be -1 or a value greater than or equal 0", 0 TSRMLS_CC);
        !          1396:                                zend_restore_error_handling(&error_handling TSRMLS_CC);
        !          1397:                                return NULL;
        !          1398:                        }
        !          1399:                        break;
        !          1400:                }
        !          1401:                case DIT_CachingIterator:
        !          1402:                case DIT_RecursiveCachingIterator: {
        !          1403:                        long flags = CIT_CALL_TOSTRING;
        !          1404:                        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|l", &zobject, ce_inner, &flags) == FAILURE) {
        !          1405:                                zend_restore_error_handling(&error_handling TSRMLS_CC);
        !          1406:                                return NULL;
        !          1407:                        }
        !          1408:                        if (spl_cit_check_flags(flags) != SUCCESS) {
        !          1409:                                zend_throw_exception(spl_ce_InvalidArgumentException, "Flags must contain only one of CALL_TOSTRING, TOSTRING_USE_KEY, TOSTRING_USE_CURRENT, TOSTRING_USE_CURRENT", 0 TSRMLS_CC);
        !          1410:                                zend_restore_error_handling(&error_handling TSRMLS_CC);
        !          1411:                                return NULL;
        !          1412:                        }
        !          1413:                        intern->u.caching.flags |= flags & CIT_PUBLIC;
        !          1414:                        MAKE_STD_ZVAL(intern->u.caching.zcache);
        !          1415:                        array_init(intern->u.caching.zcache);
        !          1416:                        break;
        !          1417:                }
        !          1418:                case DIT_IteratorIterator: {
        !          1419:                        zend_class_entry **pce_cast;
        !          1420:                        char * class_name = NULL;
        !          1421:                        int class_name_len = 0;
        !          1422: 
        !          1423:                        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|s", &zobject, ce_inner, &class_name, &class_name_len) == FAILURE) {
        !          1424:                                zend_restore_error_handling(&error_handling TSRMLS_CC);
        !          1425:                                return NULL;
        !          1426:                        }
        !          1427:                        ce = Z_OBJCE_P(zobject);
        !          1428:                        if (!instanceof_function(ce, zend_ce_iterator TSRMLS_CC)) {
        !          1429:                                if (ZEND_NUM_ARGS() > 1) {
        !          1430:                                        if (zend_lookup_class(class_name, class_name_len, &pce_cast TSRMLS_CC) == FAILURE 
        !          1431:                                        || !instanceof_function(ce, *pce_cast TSRMLS_CC)
        !          1432:                                        || !(*pce_cast)->get_iterator
        !          1433:                                        ) {
        !          1434:                                                zend_throw_exception(spl_ce_LogicException, "Class to downcast to not found or not base class or does not implement Traversable", 0 TSRMLS_CC);
        !          1435:                                                zend_restore_error_handling(&error_handling TSRMLS_CC);
        !          1436:                                                return NULL;
        !          1437:                                        }
        !          1438:                                        ce = *pce_cast;
        !          1439:                                }
        !          1440:                                if (instanceof_function(ce, zend_ce_aggregate TSRMLS_CC)) {
        !          1441:                                        zend_call_method_with_0_params(&zobject, ce, &ce->iterator_funcs.zf_new_iterator, "getiterator", &retval);
        !          1442:                                        if (EG(exception)) {
        !          1443:                                                if (retval) {
        !          1444:                                                        zval_ptr_dtor(&retval);
        !          1445:                                                }
        !          1446:                                                zend_restore_error_handling(&error_handling TSRMLS_CC);
        !          1447:                                                return NULL;
        !          1448:                                        }
        !          1449:                                        if (!retval || Z_TYPE_P(retval) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(retval), zend_ce_traversable TSRMLS_CC)) {
        !          1450:                                                zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "%s::getIterator() must return an object that implements Traversable", ce->name);
        !          1451:                                                zend_restore_error_handling(&error_handling TSRMLS_CC);
        !          1452:                                                return NULL;
        !          1453:                                        }
        !          1454:                                        zobject = retval;
        !          1455:                                        ce = Z_OBJCE_P(zobject);
        !          1456:                                        inc_refcount = 0;
        !          1457:                                }
        !          1458:                        }
        !          1459:                        break;
        !          1460:                }
        !          1461:                case DIT_AppendIterator:
        !          1462:                        spl_instantiate(spl_ce_ArrayIterator, &intern->u.append.zarrayit, 1 TSRMLS_CC);
        !          1463:                        zend_call_method_with_0_params(&intern->u.append.zarrayit, spl_ce_ArrayIterator, &spl_ce_ArrayIterator->constructor, "__construct", NULL);
        !          1464:                        intern->u.append.iterator = spl_ce_ArrayIterator->get_iterator(spl_ce_ArrayIterator, intern->u.append.zarrayit, 0 TSRMLS_CC);
        !          1465:                        zend_restore_error_handling(&error_handling TSRMLS_CC);
        !          1466:                        return intern;
        !          1467: #if HAVE_PCRE || HAVE_BUNDLED_PCRE
        !          1468:                case DIT_RegexIterator:
        !          1469:                case DIT_RecursiveRegexIterator: {
        !          1470:                        char *regex;
        !          1471:                        int regex_len;
        !          1472:                        long mode = REGIT_MODE_MATCH;
        !          1473: 
        !          1474:                        intern->u.regex.use_flags = ZEND_NUM_ARGS() >= 5;
        !          1475:                        intern->u.regex.flags = 0;
        !          1476:                        intern->u.regex.preg_flags = 0;
        !          1477:                        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|lll", &zobject, ce_inner, &regex, &regex_len, &mode, &intern->u.regex.flags, &intern->u.regex.preg_flags) == FAILURE) {
        !          1478:                                zend_restore_error_handling(&error_handling TSRMLS_CC);
        !          1479:                                return NULL;
        !          1480:                        }
        !          1481:                        if (mode < 0 || mode >= REGIT_MODE_MAX) {
        !          1482:                                zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Illegal mode %ld", mode);
        !          1483:                                zend_restore_error_handling(&error_handling TSRMLS_CC);
        !          1484:                                return NULL;
        !          1485:                        }
        !          1486:                        intern->u.regex.mode = mode;
        !          1487:                        intern->u.regex.regex = estrndup(regex, regex_len);
        !          1488:                        intern->u.regex.pce = pcre_get_compiled_regex_cache(regex, regex_len TSRMLS_CC);
        !          1489:                        if (intern->u.regex.pce == NULL) {
        !          1490:                                /* pcre_get_compiled_regex_cache has already sent error */
        !          1491:                                zend_restore_error_handling(&error_handling TSRMLS_CC);
        !          1492:                                return NULL;
        !          1493:                        }
        !          1494:                        intern->u.regex.pce->refcount++;
        !          1495:                        break;
        !          1496:                }
        !          1497: #endif
        !          1498:                default:
        !          1499:                        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zobject, ce_inner) == FAILURE) {
        !          1500:                                zend_restore_error_handling(&error_handling TSRMLS_CC);
        !          1501:                                return NULL;
        !          1502:                        }
        !          1503:                        break;
        !          1504:        }
        !          1505: 
        !          1506:        zend_restore_error_handling(&error_handling TSRMLS_CC);
        !          1507: 
        !          1508:        if (inc_refcount) {
        !          1509:                Z_ADDREF_P(zobject);
        !          1510:        }
        !          1511:        intern->inner.zobject = zobject;
        !          1512:        intern->inner.ce = dit_type == DIT_IteratorIterator ? ce : Z_OBJCE_P(zobject);
        !          1513:        intern->inner.object = zend_object_store_get_object(zobject TSRMLS_CC);
        !          1514:        intern->inner.iterator = intern->inner.ce->get_iterator(intern->inner.ce, zobject, 0 TSRMLS_CC);
        !          1515: 
        !          1516:        return intern;
        !          1517: }
        !          1518: 
        !          1519: /* {{{ proto void FilterIterator::__construct(Iterator it) 
        !          1520:    Create an Iterator from another iterator */
        !          1521: SPL_METHOD(FilterIterator, __construct)
        !          1522: {
        !          1523:        spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_FilterIterator, zend_ce_iterator, DIT_FilterIterator);
        !          1524: } /* }}} */
        !          1525: 
        !          1526: /* {{{ proto Iterator FilterIterator::getInnerIterator() 
        !          1527:        proto Iterator CachingIterator::getInnerIterator()
        !          1528:        proto Iterator LimitIterator::getInnerIterator()
        !          1529:        proto Iterator ParentIterator::getInnerIterator()
        !          1530:    Get the inner iterator */
        !          1531: SPL_METHOD(dual_it, getInnerIterator)
        !          1532: {
        !          1533:        spl_dual_it_object   *intern;
        !          1534:        
        !          1535:        if (zend_parse_parameters_none() == FAILURE) {
        !          1536:                return;
        !          1537:        }
        !          1538:        
        !          1539:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          1540: 
        !          1541:        if (intern->inner.zobject) {
        !          1542:                RETVAL_ZVAL(intern->inner.zobject, 1, 0);
        !          1543:        } else {
        !          1544:                RETURN_NULL();
        !          1545:        }
        !          1546: } /* }}} */
        !          1547: 
        !          1548: static inline void spl_dual_it_require(spl_dual_it_object *intern TSRMLS_DC)
        !          1549: {
        !          1550:        if (!intern->inner.iterator) {
        !          1551:                php_error_docref(NULL TSRMLS_CC, E_ERROR, "The inner constructor wasn't initialized with an iterator instance");
        !          1552:        }
        !          1553: }
        !          1554: 
        !          1555: static inline void spl_dual_it_free(spl_dual_it_object *intern TSRMLS_DC)
        !          1556: {
        !          1557:        if (intern->inner.iterator && intern->inner.iterator->funcs->invalidate_current) {
        !          1558:                intern->inner.iterator->funcs->invalidate_current(intern->inner.iterator TSRMLS_CC);
        !          1559:        }
        !          1560:        if (intern->current.data) {
        !          1561:                zval_ptr_dtor(&intern->current.data);
        !          1562:                intern->current.data = NULL;
        !          1563:        }
        !          1564:        if (intern->current.str_key) {
        !          1565:                efree(intern->current.str_key);
        !          1566:                intern->current.str_key = NULL;
        !          1567:        }
        !          1568:        if (intern->dit_type == DIT_CachingIterator || intern->dit_type == DIT_RecursiveCachingIterator) {
        !          1569:                if (intern->u.caching.zstr) {
        !          1570:                        zval_ptr_dtor(&intern->u.caching.zstr);
        !          1571:                        intern->u.caching.zstr = NULL;
        !          1572:                }
        !          1573:                if (intern->u.caching.zchildren) {
        !          1574:                        zval_ptr_dtor(&intern->u.caching.zchildren);
        !          1575:                        intern->u.caching.zchildren = NULL;
        !          1576:                }
        !          1577:        }
        !          1578: }
        !          1579: 
        !          1580: static inline void spl_dual_it_rewind(spl_dual_it_object *intern TSRMLS_DC)
        !          1581: {
        !          1582:        spl_dual_it_free(intern TSRMLS_CC);
        !          1583:        intern->current.pos = 0;
        !          1584:        if (intern->inner.iterator->funcs->rewind) {
        !          1585:                intern->inner.iterator->funcs->rewind(intern->inner.iterator TSRMLS_CC);
        !          1586:        }
        !          1587: }
        !          1588: 
        !          1589: static inline int spl_dual_it_valid(spl_dual_it_object *intern TSRMLS_DC)
        !          1590: {
        !          1591:        if (!intern->inner.iterator) {
        !          1592:                return FAILURE;
        !          1593:        }
        !          1594:        /* FAILURE / SUCCESS */
        !          1595:        return intern->inner.iterator->funcs->valid(intern->inner.iterator TSRMLS_CC);
        !          1596: }
        !          1597: 
        !          1598: static inline int spl_dual_it_fetch(spl_dual_it_object *intern, int check_more TSRMLS_DC)
        !          1599: {
        !          1600:        zval **data;
        !          1601: 
        !          1602:        spl_dual_it_free(intern TSRMLS_CC);
        !          1603:        if (!check_more || spl_dual_it_valid(intern TSRMLS_CC) == SUCCESS) {
        !          1604:                intern->inner.iterator->funcs->get_current_data(intern->inner.iterator, &data TSRMLS_CC);
        !          1605:                if (data && *data) {
        !          1606:                        intern->current.data = *data;
        !          1607:                        Z_ADDREF_P(intern->current.data);
        !          1608:                }
        !          1609:                if (intern->inner.iterator->funcs->get_current_key) {
        !          1610:                        intern->current.key_type = intern->inner.iterator->funcs->get_current_key(intern->inner.iterator, &intern->current.str_key, &intern->current.str_key_len, &intern->current.int_key TSRMLS_CC);
        !          1611:                } else {
        !          1612:                        intern->current.key_type = HASH_KEY_IS_LONG;
        !          1613:                        intern->current.int_key = intern->current.pos;
        !          1614:                }
        !          1615:                return EG(exception) ? FAILURE : SUCCESS;
        !          1616:        }
        !          1617:        return FAILURE;
        !          1618: }
        !          1619: 
        !          1620: static inline void spl_dual_it_next(spl_dual_it_object *intern, int do_free TSRMLS_DC)
        !          1621: {
        !          1622:        if (do_free) {
        !          1623:                spl_dual_it_free(intern TSRMLS_CC);
        !          1624:        } else {
        !          1625:                spl_dual_it_require(intern TSRMLS_CC);
        !          1626:        }
        !          1627:        intern->inner.iterator->funcs->move_forward(intern->inner.iterator TSRMLS_CC);
        !          1628:        intern->current.pos++;
        !          1629: }
        !          1630: 
        !          1631: /* {{{ proto void ParentIterator::rewind()
        !          1632:        proto void IteratorIterator::rewind()
        !          1633:    Rewind the iterator
        !          1634:    */
        !          1635: SPL_METHOD(dual_it, rewind)
        !          1636: {
        !          1637:        spl_dual_it_object   *intern;
        !          1638:        
        !          1639:        if (zend_parse_parameters_none() == FAILURE) {
        !          1640:                return;
        !          1641:        }
        !          1642:        
        !          1643:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          1644:        
        !          1645:        spl_dual_it_rewind(intern TSRMLS_CC);
        !          1646:        spl_dual_it_fetch(intern, 1 TSRMLS_CC);
        !          1647: } /* }}} */
        !          1648: 
        !          1649: /* {{{ proto bool FilterIterator::valid()
        !          1650:        proto bool ParentIterator::valid()
        !          1651:        proto bool IteratorIterator::valid()
        !          1652:        proto bool NoRewindIterator::valid()
        !          1653:    Check whether the current element is valid */
        !          1654: SPL_METHOD(dual_it, valid)
        !          1655: {
        !          1656:        spl_dual_it_object   *intern;
        !          1657: 
        !          1658:        if (zend_parse_parameters_none() == FAILURE) {
        !          1659:                return;
        !          1660:        }
        !          1661:        
        !          1662:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          1663: 
        !          1664:        RETURN_BOOL(intern->current.data);
        !          1665: } /* }}} */
        !          1666: 
        !          1667: /* {{{ proto mixed FilterIterator::key()
        !          1668:        proto mixed CachingIterator::key()
        !          1669:        proto mixed LimitIterator::key()
        !          1670:        proto mixed ParentIterator::key()
        !          1671:        proto mixed IteratorIterator::key()
        !          1672:        proto mixed NoRewindIterator::key()
        !          1673:        proto mixed AppendIterator::key()
        !          1674:    Get the current key */
        !          1675: SPL_METHOD(dual_it, key)
        !          1676: {
        !          1677:        spl_dual_it_object   *intern;
        !          1678: 
        !          1679:        if (zend_parse_parameters_none() == FAILURE) {
        !          1680:                return;
        !          1681:        }
        !          1682:        
        !          1683:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          1684: 
        !          1685:        if (intern->current.data) {
        !          1686:                if (intern->current.key_type == HASH_KEY_IS_STRING) {
        !          1687:                        RETURN_STRINGL(intern->current.str_key, intern->current.str_key_len-1, 1);
        !          1688:                } else {
        !          1689:                        RETURN_LONG(intern->current.int_key);
        !          1690:                }
        !          1691:        }
        !          1692:        RETURN_NULL();
        !          1693: } /* }}} */
        !          1694: 
        !          1695: /* {{{ proto mixed FilterIterator::current()
        !          1696:        proto mixed CachingIterator::current()
        !          1697:        proto mixed LimitIterator::current()
        !          1698:        proto mixed ParentIterator::current()
        !          1699:        proto mixed IteratorIterator::current()
        !          1700:        proto mixed NoRewindIterator::current()
        !          1701:        proto mixed AppendIterator::current()
        !          1702:    Get the current element value */
        !          1703: SPL_METHOD(dual_it, current)
        !          1704: {
        !          1705:        spl_dual_it_object   *intern;
        !          1706:        
        !          1707:        if (zend_parse_parameters_none() == FAILURE) {
        !          1708:                return;
        !          1709:        }
        !          1710: 
        !          1711:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          1712: 
        !          1713:        if (intern->current.data) {
        !          1714:                RETVAL_ZVAL(intern->current.data, 1, 0);
        !          1715:        } else {
        !          1716:                RETURN_NULL();
        !          1717:        }
        !          1718: } /* }}} */
        !          1719: 
        !          1720: /* {{{ proto void ParentIterator::next()
        !          1721:        proto void IteratorIterator::next()
        !          1722:        proto void NoRewindIterator::next()
        !          1723:    Move the iterator forward */
        !          1724: SPL_METHOD(dual_it, next)
        !          1725: {
        !          1726:        spl_dual_it_object   *intern;
        !          1727:        
        !          1728:        if (zend_parse_parameters_none() == FAILURE) {
        !          1729:                return;
        !          1730:        }
        !          1731: 
        !          1732:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          1733: 
        !          1734:        spl_dual_it_next(intern, 1 TSRMLS_CC);
        !          1735:        spl_dual_it_fetch(intern, 1 TSRMLS_CC);
        !          1736: } /* }}} */
        !          1737: 
        !          1738: static inline void spl_filter_it_fetch(zval *zthis, spl_dual_it_object *intern TSRMLS_DC)
        !          1739: {
        !          1740:        zval *retval;
        !          1741: 
        !          1742:        while (spl_dual_it_fetch(intern, 1 TSRMLS_CC) == SUCCESS) {
        !          1743:                zend_call_method_with_0_params(&zthis, intern->std.ce, NULL, "accept", &retval);
        !          1744:                if (retval) {
        !          1745:                        if (zend_is_true(retval)) {
        !          1746:                                zval_ptr_dtor(&retval);
        !          1747:                                return;
        !          1748:                        }
        !          1749:                        zval_ptr_dtor(&retval);
        !          1750:                }
        !          1751:                if (EG(exception)) {
        !          1752:                        return;
        !          1753:                }
        !          1754:                intern->inner.iterator->funcs->move_forward(intern->inner.iterator TSRMLS_CC);
        !          1755:        }
        !          1756:        spl_dual_it_free(intern TSRMLS_CC);
        !          1757: }
        !          1758: 
        !          1759: static inline void spl_filter_it_rewind(zval *zthis, spl_dual_it_object *intern TSRMLS_DC)
        !          1760: {
        !          1761:        spl_dual_it_rewind(intern TSRMLS_CC);
        !          1762:        spl_filter_it_fetch(zthis, intern TSRMLS_CC);
        !          1763: }
        !          1764: 
        !          1765: static inline void spl_filter_it_next(zval *zthis, spl_dual_it_object *intern TSRMLS_DC)
        !          1766: {
        !          1767:        spl_dual_it_next(intern, 1 TSRMLS_CC);
        !          1768:        spl_filter_it_fetch(zthis, intern TSRMLS_CC);
        !          1769: }
        !          1770: 
        !          1771: /* {{{ proto void FilterIterator::rewind()
        !          1772:    Rewind the iterator */
        !          1773: SPL_METHOD(FilterIterator, rewind)
        !          1774: {
        !          1775:        spl_dual_it_object   *intern;
        !          1776:        
        !          1777:        if (zend_parse_parameters_none() == FAILURE) {
        !          1778:                return;
        !          1779:        }
        !          1780: 
        !          1781:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          1782:        spl_filter_it_rewind(getThis(), intern TSRMLS_CC);
        !          1783: } /* }}} */
        !          1784: 
        !          1785: /* {{{ proto void FilterIterator::next()
        !          1786:    Move the iterator forward */
        !          1787: SPL_METHOD(FilterIterator, next)
        !          1788: {
        !          1789:        spl_dual_it_object   *intern;
        !          1790:        
        !          1791:        if (zend_parse_parameters_none() == FAILURE) {
        !          1792:                return;
        !          1793:        }
        !          1794: 
        !          1795:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          1796:        spl_filter_it_next(getThis(), intern TSRMLS_CC);
        !          1797: } /* }}} */
        !          1798: 
        !          1799: /* {{{ proto void RecursiveFilterIterator::__construct(RecursiveIterator it)
        !          1800:    Create a RecursiveFilterIterator from a RecursiveIterator */
        !          1801: SPL_METHOD(RecursiveFilterIterator, __construct)
        !          1802: {
        !          1803:        spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_RecursiveFilterIterator, spl_ce_RecursiveIterator, DIT_RecursiveFilterIterator);
        !          1804: } /* }}} */
        !          1805: 
        !          1806: /* {{{ proto bool RecursiveFilterIterator::hasChildren()
        !          1807:    Check whether the inner iterator's current element has children */
        !          1808: SPL_METHOD(RecursiveFilterIterator, hasChildren)
        !          1809: {
        !          1810:        spl_dual_it_object   *intern;
        !          1811:        zval                 *retval;
        !          1812:        
        !          1813:        if (zend_parse_parameters_none() == FAILURE) {
        !          1814:                return;
        !          1815:        }
        !          1816: 
        !          1817:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          1818: 
        !          1819:        zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "haschildren", &retval);
        !          1820:        if (retval) {
        !          1821:                RETURN_ZVAL(retval, 0, 1);
        !          1822:        } else {
        !          1823:                RETURN_FALSE;
        !          1824:        }
        !          1825: } /* }}} */
        !          1826: 
        !          1827: /* {{{ proto RecursiveFilterIterator RecursiveFilterIterator::getChildren()
        !          1828:    Return the inner iterator's children contained in a RecursiveFilterIterator */
        !          1829: SPL_METHOD(RecursiveFilterIterator, getChildren)
        !          1830: {
        !          1831:        spl_dual_it_object   *intern;
        !          1832:        zval                 *retval;
        !          1833:        
        !          1834:        if (zend_parse_parameters_none() == FAILURE) {
        !          1835:                return;
        !          1836:        }
        !          1837: 
        !          1838:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          1839: 
        !          1840:        zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &retval);
        !          1841:        if (!EG(exception) && retval) {
        !          1842:                spl_instantiate_arg_ex1(Z_OBJCE_P(getThis()), &return_value, 0, retval TSRMLS_CC);
        !          1843:        }
        !          1844:        if (retval) {
        !          1845:                zval_ptr_dtor(&retval);
        !          1846:        }
        !          1847: } /* }}} */
        !          1848: 
        !          1849: /* {{{ proto void ParentIterator::__construct(RecursiveIterator it)
        !          1850:    Create a ParentIterator from a RecursiveIterator */
        !          1851: SPL_METHOD(ParentIterator, __construct)
        !          1852: {
        !          1853:        spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_ParentIterator, spl_ce_RecursiveIterator, DIT_ParentIterator);
        !          1854: } /* }}} */
        !          1855: 
        !          1856: #if HAVE_PCRE || HAVE_BUNDLED_PCRE
        !          1857: /* {{{ proto void RegexIterator::__construct(Iterator it, string regex [, int mode [, int flags [, int preg_flags]]]) 
        !          1858:    Create an RegexIterator from another iterator and a regular expression */
        !          1859: SPL_METHOD(RegexIterator, __construct)
        !          1860: {
        !          1861:        spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_RegexIterator, zend_ce_iterator, DIT_RegexIterator);
        !          1862: } /* }}} */
        !          1863: 
        !          1864: /* {{{ proto bool RegexIterator::accept()
        !          1865:    Match (string)current() against regular expression */
        !          1866: SPL_METHOD(RegexIterator, accept)
        !          1867: {
        !          1868:        spl_dual_it_object *intern;
        !          1869:        char       *subject, tmp[32], *result;
        !          1870:        int        subject_len, use_copy, count = 0, result_len;
        !          1871:        zval       subject_copy, zcount, *replacement, tmp_replacement;
        !          1872:        
        !          1873:        if (zend_parse_parameters_none() == FAILURE) {
        !          1874:                return;
        !          1875:        }
        !          1876:        
        !          1877:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          1878:        
        !          1879:        if (intern->current.data == NULL) {
        !          1880:                RETURN_FALSE;
        !          1881:        }
        !          1882:        
        !          1883:        if (intern->u.regex.flags & REGIT_USE_KEY) {
        !          1884:                if (intern->current.key_type == HASH_KEY_IS_LONG) {
        !          1885:                        subject_len = slprintf(tmp, sizeof(tmp), "%ld", intern->current.int_key);
        !          1886:                        subject = &tmp[0];
        !          1887:                        use_copy = 0;
        !          1888:                } else {
        !          1889:                        subject_len = intern->current.str_key_len - 1;
        !          1890:                        subject = estrndup(intern->current.str_key, subject_len);
        !          1891:                        use_copy = 1;
        !          1892:                }
        !          1893:        } else {
        !          1894:                zend_make_printable_zval(intern->current.data, &subject_copy, &use_copy);
        !          1895:                if (use_copy) {
        !          1896:                        subject = Z_STRVAL(subject_copy);
        !          1897:                        subject_len = Z_STRLEN(subject_copy);
        !          1898:                } else {
        !          1899:                        subject = Z_STRVAL_P(intern->current.data);
        !          1900:                        subject_len = Z_STRLEN_P(intern->current.data);
        !          1901:                }
        !          1902:        }
        !          1903: 
        !          1904:        switch (intern->u.regex.mode)
        !          1905:        {
        !          1906:        case REGIT_MODE_MAX: /* won't happen but makes compiler happy */
        !          1907:        case REGIT_MODE_MATCH:
        !          1908:                count = pcre_exec(intern->u.regex.pce->re, intern->u.regex.pce->extra, subject, subject_len, 0, 0, NULL, 0);
        !          1909:                RETVAL_BOOL(count >= 0);
        !          1910:                break;
        !          1911: 
        !          1912:        case REGIT_MODE_ALL_MATCHES:
        !          1913:        case REGIT_MODE_GET_MATCH:
        !          1914:                if (!use_copy) {
        !          1915:                        subject = estrndup(subject, subject_len);
        !          1916:                        use_copy = 1;
        !          1917:                }
        !          1918:                zval_ptr_dtor(&intern->current.data);
        !          1919:                ALLOC_INIT_ZVAL(intern->current.data);
        !          1920:                php_pcre_match_impl(intern->u.regex.pce, subject, subject_len, &zcount, 
        !          1921:                        intern->current.data, intern->u.regex.mode == REGIT_MODE_ALL_MATCHES, intern->u.regex.use_flags, intern->u.regex.preg_flags, 0 TSRMLS_CC);
        !          1922:                count = zend_hash_num_elements(Z_ARRVAL_P(intern->current.data));
        !          1923:                RETVAL_BOOL(count > 0);
        !          1924:                break;
        !          1925: 
        !          1926:        case REGIT_MODE_SPLIT:
        !          1927:                if (!use_copy) {
        !          1928:                        subject = estrndup(subject, subject_len);
        !          1929:                        use_copy = 1;
        !          1930:                }
        !          1931:                zval_ptr_dtor(&intern->current.data);
        !          1932:                ALLOC_INIT_ZVAL(intern->current.data);
        !          1933:                php_pcre_split_impl(intern->u.regex.pce, subject, subject_len, intern->current.data, -1, intern->u.regex.preg_flags TSRMLS_CC);
        !          1934:                count = zend_hash_num_elements(Z_ARRVAL_P(intern->current.data));
        !          1935:                RETVAL_BOOL(count > 1);
        !          1936:                break;
        !          1937: 
        !          1938:        case REGIT_MODE_REPLACE:
        !          1939:                replacement = zend_read_property(intern->std.ce, getThis(), "replacement", sizeof("replacement")-1, 1 TSRMLS_CC);
        !          1940:                if (Z_TYPE_P(replacement) != IS_STRING) {
        !          1941:                        tmp_replacement = *replacement;
        !          1942:                        zval_copy_ctor(&tmp_replacement);
        !          1943:                        convert_to_string(&tmp_replacement);
        !          1944:                        replacement = &tmp_replacement;
        !          1945:                }
        !          1946:                result = php_pcre_replace_impl(intern->u.regex.pce, subject, subject_len, replacement, 0, &result_len, -1, &count TSRMLS_CC);
        !          1947:                
        !          1948:                if (intern->u.regex.flags & REGIT_USE_KEY) {
        !          1949:                        if (intern->current.key_type != HASH_KEY_IS_LONG) {
        !          1950:                                efree(intern->current.str_key);
        !          1951:                        }
        !          1952:                        intern->current.key_type = HASH_KEY_IS_STRING;
        !          1953:                        intern->current.str_key = result;
        !          1954:                        intern->current.str_key_len = result_len + 1;
        !          1955:                } else {
        !          1956:                        zval_ptr_dtor(&intern->current.data);
        !          1957:                        MAKE_STD_ZVAL(intern->current.data);
        !          1958:                        ZVAL_STRINGL(intern->current.data, result, result_len, 0);
        !          1959:                }
        !          1960: 
        !          1961:                if (replacement == &tmp_replacement) {
        !          1962:                        zval_dtor(replacement);
        !          1963:                }
        !          1964:                RETVAL_BOOL(count > 0);
        !          1965:        }
        !          1966: 
        !          1967:        if (intern->u.regex.flags & REGIT_INVERTED) {
        !          1968:                RETVAL_BOOL(Z_LVAL_P(return_value));
        !          1969:        }
        !          1970: 
        !          1971:        if (use_copy) {
        !          1972:                efree(subject);
        !          1973:        }
        !          1974: } /* }}} */
        !          1975: 
        !          1976: /* {{{ proto bool RegexIterator::getMode()
        !          1977:    Returns current operation mode */
        !          1978: SPL_METHOD(RegexIterator, getMode)
        !          1979: {
        !          1980:        spl_dual_it_object *intern;
        !          1981: 
        !          1982:        if (zend_parse_parameters_none() == FAILURE) {
        !          1983:                return;
        !          1984:        }
        !          1985:        
        !          1986:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          1987:        
        !          1988:        RETURN_LONG(intern->u.regex.mode);
        !          1989: } /* }}} */
        !          1990: 
        !          1991: /* {{{ proto bool RegexIterator::setMode(int new_mode)
        !          1992:    Set new operation mode */
        !          1993: SPL_METHOD(RegexIterator, setMode)
        !          1994: {
        !          1995:        spl_dual_it_object *intern;
        !          1996:        long mode;
        !          1997: 
        !          1998:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &mode) == FAILURE) {
        !          1999:                return;
        !          2000:        }
        !          2001: 
        !          2002:        if (mode < 0 || mode >= REGIT_MODE_MAX) {
        !          2003:                zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Illegal mode %ld", mode);
        !          2004:                return;/* NULL */
        !          2005:        }
        !          2006:        
        !          2007:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2008: 
        !          2009:        intern->u.regex.mode = mode;
        !          2010: } /* }}} */
        !          2011: 
        !          2012: /* {{{ proto bool RegexIterator::getFlags()
        !          2013:    Returns current operation flags */
        !          2014: SPL_METHOD(RegexIterator, getFlags)
        !          2015: {
        !          2016:        spl_dual_it_object *intern;
        !          2017: 
        !          2018:        if (zend_parse_parameters_none() == FAILURE) {
        !          2019:                return;
        !          2020:        }
        !          2021:        
        !          2022:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2023:        
        !          2024:        RETURN_LONG(intern->u.regex.flags);
        !          2025: } /* }}} */
        !          2026: 
        !          2027: /* {{{ proto bool RegexIterator::setFlags(int new_flags)
        !          2028:    Set operation flags */
        !          2029: SPL_METHOD(RegexIterator, setFlags)
        !          2030: {
        !          2031:        spl_dual_it_object *intern;
        !          2032:        long flags;
        !          2033: 
        !          2034:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &flags) == FAILURE) {
        !          2035:                return;
        !          2036:        }
        !          2037:        
        !          2038:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2039: 
        !          2040:        intern->u.regex.flags = flags;
        !          2041: } /* }}} */
        !          2042: 
        !          2043: /* {{{ proto bool RegexIterator::getFlags()
        !          2044:    Returns current PREG flags (if in use or NULL) */
        !          2045: SPL_METHOD(RegexIterator, getPregFlags)
        !          2046: {
        !          2047:        spl_dual_it_object *intern;
        !          2048:        
        !          2049:        if (zend_parse_parameters_none() == FAILURE) {
        !          2050:                return;
        !          2051:        }
        !          2052:        
        !          2053:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2054: 
        !          2055:        if (intern->u.regex.use_flags) {
        !          2056:                RETURN_LONG(intern->u.regex.preg_flags);
        !          2057:        } else {
        !          2058:                return;
        !          2059:        }
        !          2060: } /* }}} */
        !          2061: 
        !          2062: /* {{{ proto bool RegexIterator::setPregFlags(int new_flags)
        !          2063:    Set PREG flags */
        !          2064: SPL_METHOD(RegexIterator, setPregFlags)
        !          2065: {
        !          2066:        spl_dual_it_object *intern;
        !          2067:        long preg_flags;
        !          2068: 
        !          2069:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &preg_flags) == FAILURE) {
        !          2070:                return;
        !          2071:        }
        !          2072:        
        !          2073:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2074: 
        !          2075:        intern->u.regex.preg_flags = preg_flags;
        !          2076:        intern->u.regex.use_flags = 1;
        !          2077: } /* }}} */
        !          2078: 
        !          2079: /* {{{ proto void RecursiveRegexIterator::__construct(RecursiveIterator it, string regex [, int mode [, int flags [, int preg_flags]]]) 
        !          2080:    Create an RecursiveRegexIterator from another recursive iterator and a regular expression */
        !          2081: SPL_METHOD(RecursiveRegexIterator, __construct)
        !          2082: {
        !          2083:        spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_RecursiveRegexIterator, spl_ce_RecursiveIterator, DIT_RecursiveRegexIterator);
        !          2084: } /* }}} */
        !          2085: 
        !          2086: /* {{{ proto RecursiveRegexIterator RecursiveRegexIterator::getChildren()
        !          2087:    Return the inner iterator's children contained in a RecursiveRegexIterator */
        !          2088: SPL_METHOD(RecursiveRegexIterator, getChildren)
        !          2089: {
        !          2090:        spl_dual_it_object   *intern;
        !          2091:        zval                 *retval, *regex;
        !          2092:        
        !          2093:        if (zend_parse_parameters_none() == FAILURE) {
        !          2094:                return;
        !          2095:        }
        !          2096: 
        !          2097:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2098: 
        !          2099:        zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &retval);
        !          2100:        if (!EG(exception)) {
        !          2101:                MAKE_STD_ZVAL(regex);
        !          2102:                ZVAL_STRING(regex, intern->u.regex.regex, 1);
        !          2103:                spl_instantiate_arg_ex2(Z_OBJCE_P(getThis()), &return_value, 0, retval, regex TSRMLS_CC);
        !          2104:                zval_ptr_dtor(&regex);
        !          2105:        }
        !          2106:        if (retval) {
        !          2107:                zval_ptr_dtor(&retval);
        !          2108:        }
        !          2109: } /* }}} */
        !          2110: 
        !          2111: #endif
        !          2112: 
        !          2113: /* {{{ spl_dual_it_dtor */
        !          2114: static void spl_dual_it_dtor(zend_object *_object, zend_object_handle handle TSRMLS_DC)
        !          2115: {
        !          2116:        spl_dual_it_object        *object = (spl_dual_it_object *)_object;
        !          2117: 
        !          2118:        /* call standard dtor */
        !          2119:        zend_objects_destroy_object(_object, handle TSRMLS_CC);
        !          2120: 
        !          2121:        spl_dual_it_free(object TSRMLS_CC);
        !          2122: 
        !          2123:        if (object->inner.iterator) {
        !          2124:                object->inner.iterator->funcs->dtor(object->inner.iterator TSRMLS_CC);
        !          2125:        }
        !          2126: }
        !          2127: /* }}} */
        !          2128: 
        !          2129: /* {{{ spl_dual_it_free_storage */
        !          2130: static void spl_dual_it_free_storage(void *_object TSRMLS_DC)
        !          2131: {
        !          2132:        spl_dual_it_object        *object = (spl_dual_it_object *)_object;
        !          2133: 
        !          2134:        if (object->inner.zobject) {
        !          2135:                zval_ptr_dtor(&object->inner.zobject);
        !          2136:        }
        !          2137:        
        !          2138:        if (object->dit_type == DIT_AppendIterator) {
        !          2139:                object->u.append.iterator->funcs->dtor(object->u.append.iterator TSRMLS_CC);
        !          2140:                if (object->u.append.zarrayit) {
        !          2141:                        zval_ptr_dtor(&object->u.append.zarrayit);
        !          2142:                }
        !          2143:        }
        !          2144: 
        !          2145:        if (object->dit_type == DIT_CachingIterator || object->dit_type == DIT_RecursiveCachingIterator) {
        !          2146:                if (object->u.caching.zcache) {
        !          2147:                        zval_ptr_dtor(&object->u.caching.zcache);
        !          2148:                        object->u.caching.zcache = NULL;
        !          2149:                }
        !          2150:        }
        !          2151: 
        !          2152: #if HAVE_PCRE || HAVE_BUNDLED_PCRE
        !          2153:        if (object->dit_type == DIT_RegexIterator || object->dit_type == DIT_RecursiveRegexIterator) {
        !          2154:                if (object->u.regex.pce) {
        !          2155:                        object->u.regex.pce->refcount--;
        !          2156:                }
        !          2157:                if (object->u.regex.regex) {
        !          2158:                        efree(object->u.regex.regex);
        !          2159:                }
        !          2160:        }
        !          2161: #endif
        !          2162: 
        !          2163:        zend_object_std_dtor(&object->std TSRMLS_CC);
        !          2164: 
        !          2165:        efree(object);
        !          2166: }
        !          2167: /* }}} */
        !          2168: 
        !          2169: /* {{{ spl_dual_it_new */
        !          2170: static zend_object_value spl_dual_it_new(zend_class_entry *class_type TSRMLS_DC)
        !          2171: {
        !          2172:        zend_object_value retval;
        !          2173:        spl_dual_it_object *intern;
        !          2174:        zval *tmp;
        !          2175: 
        !          2176:        intern = emalloc(sizeof(spl_dual_it_object));
        !          2177:        memset(intern, 0, sizeof(spl_dual_it_object));
        !          2178:        intern->dit_type = DIT_Unknown;
        !          2179: 
        !          2180:        zend_object_std_init(&intern->std, class_type TSRMLS_CC);
        !          2181:        zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
        !          2182: 
        !          2183:        retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)spl_dual_it_dtor, (zend_objects_free_object_storage_t) spl_dual_it_free_storage, NULL TSRMLS_CC);
        !          2184:        retval.handlers = &spl_handlers_dual_it;
        !          2185:        return retval;
        !          2186: }
        !          2187: /* }}} */
        !          2188: 
        !          2189: ZEND_BEGIN_ARG_INFO(arginfo_filter_it___construct, 0) 
        !          2190:        ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
        !          2191: ZEND_END_ARG_INFO();
        !          2192: 
        !          2193: static const zend_function_entry spl_funcs_FilterIterator[] = {
        !          2194:        SPL_ME(FilterIterator,  __construct,      arginfo_filter_it___construct, ZEND_ACC_PUBLIC)
        !          2195:        SPL_ME(FilterIterator,  rewind,           arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2196:        SPL_ME(dual_it,         valid,            arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2197:        SPL_ME(dual_it,         key,              arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2198:        SPL_ME(dual_it,         current,          arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2199:        SPL_ME(FilterIterator,  next,             arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2200:        SPL_ME(dual_it,         getInnerIterator, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2201:        SPL_ABSTRACT_ME(FilterIterator, accept,   arginfo_recursive_it_void)
        !          2202:        PHP_FE_END
        !          2203: };
        !          2204: 
        !          2205: ZEND_BEGIN_ARG_INFO(arginfo_parent_it___construct, 0) 
        !          2206:        ZEND_ARG_OBJ_INFO(0, iterator, RecursiveIterator, 0)
        !          2207: ZEND_END_ARG_INFO();
        !          2208: 
        !          2209: static const zend_function_entry spl_funcs_RecursiveFilterIterator[] = {
        !          2210:        SPL_ME(RecursiveFilterIterator,  __construct,      arginfo_parent_it___construct, ZEND_ACC_PUBLIC)
        !          2211:        SPL_ME(RecursiveFilterIterator,  hasChildren,      arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2212:        SPL_ME(RecursiveFilterIterator,  getChildren,      arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2213:        PHP_FE_END
        !          2214: };
        !          2215: 
        !          2216: static const zend_function_entry spl_funcs_ParentIterator[] = {
        !          2217:        SPL_ME(ParentIterator,  __construct,      arginfo_parent_it___construct, ZEND_ACC_PUBLIC)
        !          2218:        SPL_MA(ParentIterator,  accept,           RecursiveFilterIterator, hasChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2219:        PHP_FE_END
        !          2220: };
        !          2221: 
        !          2222: #if HAVE_PCRE || HAVE_BUNDLED_PCRE
        !          2223: ZEND_BEGIN_ARG_INFO_EX(arginfo_regex_it___construct, 0, 0, 2) 
        !          2224:        ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
        !          2225:        ZEND_ARG_INFO(0, regex)
        !          2226:        ZEND_ARG_INFO(0, mode)
        !          2227:        ZEND_ARG_INFO(0, flags)
        !          2228:        ZEND_ARG_INFO(0, preg_flags)
        !          2229: ZEND_END_ARG_INFO();
        !          2230: 
        !          2231: ZEND_BEGIN_ARG_INFO_EX(arginfo_regex_it_set_mode, 0, 0, 1) 
        !          2232:        ZEND_ARG_INFO(0, mode)
        !          2233: ZEND_END_ARG_INFO();
        !          2234: 
        !          2235: ZEND_BEGIN_ARG_INFO_EX(arginfo_regex_it_set_flags, 0, 0, 1) 
        !          2236:        ZEND_ARG_INFO(0, flags)
        !          2237: ZEND_END_ARG_INFO();
        !          2238: 
        !          2239: ZEND_BEGIN_ARG_INFO_EX(arginfo_regex_it_set_preg_flags, 0, 0, 1) 
        !          2240:        ZEND_ARG_INFO(0, preg_flags)
        !          2241: ZEND_END_ARG_INFO();
        !          2242: 
        !          2243: static const zend_function_entry spl_funcs_RegexIterator[] = {
        !          2244:        SPL_ME(RegexIterator,   __construct,      arginfo_regex_it___construct,    ZEND_ACC_PUBLIC)
        !          2245:        SPL_ME(RegexIterator,   accept,           arginfo_recursive_it_void,       ZEND_ACC_PUBLIC)
        !          2246:        SPL_ME(RegexIterator,   getMode,          arginfo_recursive_it_void,       ZEND_ACC_PUBLIC)
        !          2247:        SPL_ME(RegexIterator,   setMode,          arginfo_regex_it_set_mode,       ZEND_ACC_PUBLIC)
        !          2248:        SPL_ME(RegexIterator,   getFlags,         arginfo_recursive_it_void,       ZEND_ACC_PUBLIC)
        !          2249:        SPL_ME(RegexIterator,   setFlags,         arginfo_regex_it_set_flags,      ZEND_ACC_PUBLIC)
        !          2250:        SPL_ME(RegexIterator,   getPregFlags,     arginfo_recursive_it_void,       ZEND_ACC_PUBLIC)
        !          2251:        SPL_ME(RegexIterator,   setPregFlags,     arginfo_regex_it_set_preg_flags, ZEND_ACC_PUBLIC)
        !          2252:        PHP_FE_END
        !          2253: };
        !          2254: 
        !          2255: ZEND_BEGIN_ARG_INFO_EX(arginfo_rec_regex_it___construct, 0, 0, 2) 
        !          2256:        ZEND_ARG_OBJ_INFO(0, iterator, RecursiveIterator, 0)
        !          2257:        ZEND_ARG_INFO(0, regex)
        !          2258:        ZEND_ARG_INFO(0, mode)
        !          2259:        ZEND_ARG_INFO(0, flags)
        !          2260:        ZEND_ARG_INFO(0, preg_flags)
        !          2261: ZEND_END_ARG_INFO();
        !          2262: 
        !          2263: static const zend_function_entry spl_funcs_RecursiveRegexIterator[] = {
        !          2264:        SPL_ME(RecursiveRegexIterator,  __construct,      arginfo_rec_regex_it___construct, ZEND_ACC_PUBLIC)
        !          2265:        SPL_ME(RecursiveFilterIterator, hasChildren,      arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2266:        SPL_ME(RecursiveRegexIterator,  getChildren,      arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2267:        PHP_FE_END
        !          2268: };
        !          2269: #endif
        !          2270: 
        !          2271: static inline int spl_limit_it_valid(spl_dual_it_object *intern TSRMLS_DC)
        !          2272: {
        !          2273:        /* FAILURE / SUCCESS */
        !          2274:        if (intern->u.limit.count != -1 && intern->current.pos >= intern->u.limit.offset + intern->u.limit.count) {
        !          2275:                return FAILURE;
        !          2276:        } else {
        !          2277:                return spl_dual_it_valid(intern TSRMLS_CC);
        !          2278:        }
        !          2279: }
        !          2280: 
        !          2281: static inline void spl_limit_it_seek(spl_dual_it_object *intern, long pos TSRMLS_DC)
        !          2282: {
        !          2283:        zval  *zpos;
        !          2284: 
        !          2285:        spl_dual_it_free(intern TSRMLS_CC);
        !          2286:        if (pos < intern->u.limit.offset) {
        !          2287:                zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0 TSRMLS_CC, "Cannot seek to %ld which is below the offset %ld", pos, intern->u.limit.offset);
        !          2288:                return;
        !          2289:        }
        !          2290:        if (pos >= intern->u.limit.offset + intern->u.limit.count && intern->u.limit.count != -1) {
        !          2291:                zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0 TSRMLS_CC, "Cannot seek to %ld which is behind offset %ld plus count %ld", pos, intern->u.limit.offset, intern->u.limit.count);
        !          2292:                return;
        !          2293:        }
        !          2294:        if (pos != intern->current.pos && instanceof_function(intern->inner.ce, spl_ce_SeekableIterator TSRMLS_CC)) {
        !          2295:                MAKE_STD_ZVAL(zpos);
        !          2296:                ZVAL_LONG(zpos, pos);
        !          2297:                spl_dual_it_free(intern TSRMLS_CC);
        !          2298:                zend_call_method_with_1_params(&intern->inner.zobject, intern->inner.ce, NULL, "seek", NULL, zpos);
        !          2299:                zval_ptr_dtor(&zpos);
        !          2300:                if (!EG(exception)) {
        !          2301:                        intern->current.pos = pos;
        !          2302:                        if (spl_limit_it_valid(intern TSRMLS_CC) == SUCCESS) {
        !          2303:                                spl_dual_it_fetch(intern, 0 TSRMLS_CC);
        !          2304:                        }
        !          2305:                }
        !          2306:        } else {
        !          2307:                /* emulate the forward seek, by next() calls */
        !          2308:                /* a back ward seek is done by a previous rewind() */
        !          2309:                if (pos < intern->current.pos) {
        !          2310:                        spl_dual_it_rewind(intern TSRMLS_CC);
        !          2311:                }
        !          2312:                while (pos > intern->current.pos && spl_dual_it_valid(intern TSRMLS_CC) == SUCCESS) {
        !          2313:                        spl_dual_it_next(intern, 1 TSRMLS_CC);
        !          2314:                }
        !          2315:                if (spl_dual_it_valid(intern TSRMLS_CC) == SUCCESS) {
        !          2316:                        spl_dual_it_fetch(intern, 1 TSRMLS_CC);
        !          2317:                }
        !          2318:        }
        !          2319: }
        !          2320: 
        !          2321: /* {{{ proto LimitIterator::__construct(Iterator it [, int offset, int count])
        !          2322:    Construct a LimitIterator from an Iterator with a given starting offset and optionally a maximum count */
        !          2323: SPL_METHOD(LimitIterator, __construct)
        !          2324: {
        !          2325:        spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_LimitIterator, zend_ce_iterator, DIT_LimitIterator);
        !          2326: } /* }}} */
        !          2327: 
        !          2328: /* {{{ proto void LimitIterator::rewind() 
        !          2329:    Rewind the iterator to the specified starting offset */
        !          2330: SPL_METHOD(LimitIterator, rewind)
        !          2331: {
        !          2332:        spl_dual_it_object   *intern;
        !          2333: 
        !          2334:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2335:        spl_dual_it_rewind(intern TSRMLS_CC);
        !          2336:        spl_limit_it_seek(intern, intern->u.limit.offset TSRMLS_CC);
        !          2337: } /* }}} */
        !          2338: 
        !          2339: /* {{{ proto bool LimitIterator::valid()
        !          2340:    Check whether the current element is valid */
        !          2341: SPL_METHOD(LimitIterator, valid)
        !          2342: {
        !          2343:        spl_dual_it_object   *intern;
        !          2344: 
        !          2345:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2346: 
        !          2347: /*     RETURN_BOOL(spl_limit_it_valid(intern TSRMLS_CC) == SUCCESS);*/
        !          2348:        RETURN_BOOL((intern->u.limit.count == -1 || intern->current.pos < intern->u.limit.offset + intern->u.limit.count) && intern->current.data);
        !          2349: } /* }}} */
        !          2350: 
        !          2351: /* {{{ proto void LimitIterator::next()
        !          2352:    Move the iterator forward */
        !          2353: SPL_METHOD(LimitIterator, next)
        !          2354: {
        !          2355:        spl_dual_it_object   *intern;
        !          2356: 
        !          2357:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2358: 
        !          2359:        spl_dual_it_next(intern, 1 TSRMLS_CC);
        !          2360:        if (intern->u.limit.count == -1 || intern->current.pos < intern->u.limit.offset + intern->u.limit.count) {
        !          2361:                spl_dual_it_fetch(intern, 1 TSRMLS_CC);
        !          2362:        }
        !          2363: } /* }}} */
        !          2364: 
        !          2365: /* {{{ proto void LimitIterator::seek(int position)
        !          2366:    Seek to the given position */
        !          2367: SPL_METHOD(LimitIterator, seek)
        !          2368: {
        !          2369:        spl_dual_it_object   *intern;
        !          2370:        long                 pos;
        !          2371: 
        !          2372:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &pos) == FAILURE) {
        !          2373:                return;
        !          2374:        }
        !          2375: 
        !          2376:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2377:        spl_limit_it_seek(intern, pos TSRMLS_CC);
        !          2378:        RETURN_LONG(intern->current.pos);
        !          2379: } /* }}} */
        !          2380: 
        !          2381: /* {{{ proto int LimitIterator::getPosition()
        !          2382:    Return the current position */
        !          2383: SPL_METHOD(LimitIterator, getPosition)
        !          2384: {
        !          2385:        spl_dual_it_object   *intern;
        !          2386:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2387:        RETURN_LONG(intern->current.pos);
        !          2388: } /* }}} */
        !          2389: 
        !          2390: ZEND_BEGIN_ARG_INFO(arginfo_seekable_it_seek, 0) 
        !          2391:        ZEND_ARG_INFO(0, position)
        !          2392: ZEND_END_ARG_INFO();
        !          2393: 
        !          2394: static const zend_function_entry spl_funcs_SeekableIterator[] = {
        !          2395:        SPL_ABSTRACT_ME(SeekableIterator, seek, arginfo_seekable_it_seek)
        !          2396:        PHP_FE_END
        !          2397: };
        !          2398: 
        !          2399: ZEND_BEGIN_ARG_INFO_EX(arginfo_limit_it___construct, 0, 0, 1) 
        !          2400:        ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
        !          2401:        ZEND_ARG_INFO(0, offset)
        !          2402:        ZEND_ARG_INFO(0, count)
        !          2403: ZEND_END_ARG_INFO();
        !          2404: 
        !          2405: ZEND_BEGIN_ARG_INFO(arginfo_limit_it_seek, 0) 
        !          2406:        ZEND_ARG_INFO(0, position)
        !          2407: ZEND_END_ARG_INFO();
        !          2408: 
        !          2409: static const zend_function_entry spl_funcs_LimitIterator[] = {
        !          2410:        SPL_ME(LimitIterator,   __construct,      arginfo_limit_it___construct, ZEND_ACC_PUBLIC)
        !          2411:        SPL_ME(LimitIterator,   rewind,           arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2412:        SPL_ME(LimitIterator,   valid,            arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2413:        SPL_ME(dual_it,         key,              arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2414:        SPL_ME(dual_it,         current,          arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2415:        SPL_ME(LimitIterator,   next,             arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2416:        SPL_ME(LimitIterator,   seek,             arginfo_limit_it_seek, ZEND_ACC_PUBLIC)
        !          2417:        SPL_ME(LimitIterator,   getPosition,      arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2418:        SPL_ME(dual_it,         getInnerIterator, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2419:        PHP_FE_END
        !          2420: };
        !          2421: 
        !          2422: static inline int spl_caching_it_valid(spl_dual_it_object *intern TSRMLS_DC)
        !          2423: {
        !          2424:        return intern->u.caching.flags & CIT_VALID ? SUCCESS : FAILURE;
        !          2425: }
        !          2426: 
        !          2427: static inline int spl_caching_it_has_next(spl_dual_it_object *intern TSRMLS_DC)
        !          2428: {
        !          2429:        return spl_dual_it_valid(intern TSRMLS_CC);
        !          2430: }
        !          2431: 
        !          2432: static inline void spl_caching_it_next(spl_dual_it_object *intern TSRMLS_DC)
        !          2433: {
        !          2434:        if (spl_dual_it_fetch(intern, 1 TSRMLS_CC) == SUCCESS) {
        !          2435:                intern->u.caching.flags |= CIT_VALID;
        !          2436:                /* Full cache ? */
        !          2437:                if (intern->u.caching.flags & CIT_FULL_CACHE) {
        !          2438:                        zval *zcacheval;
        !          2439:                        
        !          2440:                        MAKE_STD_ZVAL(zcacheval);
        !          2441:                        ZVAL_ZVAL(zcacheval, intern->current.data, 1, 0);
        !          2442:                        if (intern->current.key_type == HASH_KEY_IS_LONG) {
        !          2443:                                add_index_zval(intern->u.caching.zcache, intern->current.int_key, zcacheval);
        !          2444:                        } else {
        !          2445:                                zend_symtable_update(HASH_OF(intern->u.caching.zcache), intern->current.str_key, intern->current.str_key_len, &zcacheval, sizeof(void*), NULL);
        !          2446:                        }
        !          2447:                }
        !          2448:                /* Recursion ? */
        !          2449:                if (intern->dit_type == DIT_RecursiveCachingIterator) {
        !          2450:                        zval *retval, *zchildren, zflags;
        !          2451:                        zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "haschildren", &retval);
        !          2452:                        if (EG(exception)) {
        !          2453:                                if (retval) {
        !          2454:                                        zval_ptr_dtor(&retval);
        !          2455:                                }
        !          2456:                                if (intern->u.caching.flags & CIT_CATCH_GET_CHILD) {
        !          2457:                                        zend_clear_exception(TSRMLS_C);
        !          2458:                                } else {
        !          2459:                                        return;
        !          2460:                                }
        !          2461:                        } else {
        !          2462:                                if (zend_is_true(retval)) {
        !          2463:                                        zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &zchildren);
        !          2464:                                        if (EG(exception)) {
        !          2465:                                                if (zchildren) {
        !          2466:                                                        zval_ptr_dtor(&zchildren);
        !          2467:                                                }
        !          2468:                                                if (intern->u.caching.flags & CIT_CATCH_GET_CHILD) {
        !          2469:                                                        zend_clear_exception(TSRMLS_C);
        !          2470:                                                } else {
        !          2471:                                                        zval_ptr_dtor(&retval);
        !          2472:                                                        return;
        !          2473:                                                }
        !          2474:                                        } else {
        !          2475:                                                INIT_PZVAL(&zflags);
        !          2476:                                                ZVAL_LONG(&zflags, intern->u.caching.flags & CIT_PUBLIC);
        !          2477:                                                spl_instantiate_arg_ex2(spl_ce_RecursiveCachingIterator, &intern->u.caching.zchildren, 1, zchildren, &zflags TSRMLS_CC);
        !          2478:                                                zval_ptr_dtor(&zchildren);
        !          2479:                                        }
        !          2480:                                }
        !          2481:                                zval_ptr_dtor(&retval);
        !          2482:                                if (EG(exception)) {
        !          2483:                                        if (intern->u.caching.flags & CIT_CATCH_GET_CHILD) {
        !          2484:                                                zend_clear_exception(TSRMLS_C);
        !          2485:                                        } else {
        !          2486:                                                return;
        !          2487:                                        }
        !          2488:                                }
        !          2489:                        }
        !          2490:                }
        !          2491:                if (intern->u.caching.flags & (CIT_TOSTRING_USE_INNER|CIT_CALL_TOSTRING)) {
        !          2492:                        int  use_copy;
        !          2493:                        zval expr_copy;
        !          2494:                        ALLOC_ZVAL(intern->u.caching.zstr);
        !          2495:                        if (intern->u.caching.flags & CIT_TOSTRING_USE_INNER) {
        !          2496:                                *intern->u.caching.zstr = *intern->inner.zobject;
        !          2497:                        } else {
        !          2498:                                *intern->u.caching.zstr = *intern->current.data;
        !          2499:                        }
        !          2500:                        zend_make_printable_zval(intern->u.caching.zstr, &expr_copy, &use_copy);
        !          2501:                        if (use_copy) {
        !          2502:                                *intern->u.caching.zstr = expr_copy;
        !          2503:                                INIT_PZVAL(intern->u.caching.zstr);
        !          2504:                                zval_copy_ctor(intern->u.caching.zstr);
        !          2505:                                zval_dtor(&expr_copy);
        !          2506:                        } else {
        !          2507:                                INIT_PZVAL(intern->u.caching.zstr);
        !          2508:                                zval_copy_ctor(intern->u.caching.zstr);
        !          2509:                        }
        !          2510:                }
        !          2511:                spl_dual_it_next(intern, 0 TSRMLS_CC);  
        !          2512:        } else {
        !          2513:                intern->u.caching.flags &= ~CIT_VALID;
        !          2514:        }
        !          2515: }
        !          2516: 
        !          2517: static inline void spl_caching_it_rewind(spl_dual_it_object *intern TSRMLS_DC)
        !          2518: {
        !          2519:        spl_dual_it_rewind(intern TSRMLS_CC);
        !          2520:        zend_hash_clean(HASH_OF(intern->u.caching.zcache));
        !          2521:        spl_caching_it_next(intern TSRMLS_CC);
        !          2522: }
        !          2523: 
        !          2524: /* {{{ proto void CachingIterator::__construct(Iterator it [, flags = CIT_CALL_TOSTRING])
        !          2525:    Construct a CachingIterator from an Iterator */
        !          2526: SPL_METHOD(CachingIterator, __construct)
        !          2527: {
        !          2528:        spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_CachingIterator, zend_ce_iterator, DIT_CachingIterator);
        !          2529: } /* }}} */
        !          2530: 
        !          2531: /* {{{ proto void CachingIterator::rewind()
        !          2532:    Rewind the iterator */
        !          2533: SPL_METHOD(CachingIterator, rewind)
        !          2534: {
        !          2535:        spl_dual_it_object   *intern;
        !          2536:        
        !          2537:        if (zend_parse_parameters_none() == FAILURE) {
        !          2538:                return;
        !          2539:        }
        !          2540: 
        !          2541:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2542: 
        !          2543:        spl_caching_it_rewind(intern TSRMLS_CC);
        !          2544: } /* }}} */
        !          2545: 
        !          2546: /* {{{ proto bool CachingIterator::valid()
        !          2547:    Check whether the current element is valid */
        !          2548: SPL_METHOD(CachingIterator, valid)
        !          2549: {
        !          2550:        spl_dual_it_object   *intern;
        !          2551:        
        !          2552:        if (zend_parse_parameters_none() == FAILURE) {
        !          2553:                return;
        !          2554:        }
        !          2555: 
        !          2556:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2557: 
        !          2558:        RETURN_BOOL(spl_caching_it_valid(intern TSRMLS_CC) == SUCCESS);
        !          2559: } /* }}} */
        !          2560: 
        !          2561: /* {{{ proto void CachingIterator::next()
        !          2562:    Move the iterator forward */
        !          2563: SPL_METHOD(CachingIterator, next)
        !          2564: {
        !          2565:        spl_dual_it_object   *intern;
        !          2566:        
        !          2567:        if (zend_parse_parameters_none() == FAILURE) {
        !          2568:                return;
        !          2569:        }
        !          2570: 
        !          2571:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2572: 
        !          2573:        spl_caching_it_next(intern TSRMLS_CC);
        !          2574: } /* }}} */
        !          2575: 
        !          2576: /* {{{ proto bool CachingIterator::hasNext()
        !          2577:    Check whether the inner iterator has a valid next element */
        !          2578: SPL_METHOD(CachingIterator, hasNext)
        !          2579: {
        !          2580:        spl_dual_it_object   *intern;
        !          2581:        
        !          2582:        if (zend_parse_parameters_none() == FAILURE) {
        !          2583:                return;
        !          2584:        }
        !          2585: 
        !          2586:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2587: 
        !          2588:        RETURN_BOOL(spl_caching_it_has_next(intern TSRMLS_CC) == SUCCESS);
        !          2589: } /* }}} */
        !          2590: 
        !          2591: /* {{{ proto string CachingIterator::__toString()
        !          2592:    Return the string representation of the current element */
        !          2593: SPL_METHOD(CachingIterator, __toString)
        !          2594: {
        !          2595:        spl_dual_it_object   *intern;
        !          2596: 
        !          2597:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2598: 
        !          2599:        if (!(intern->u.caching.flags & (CIT_CALL_TOSTRING|CIT_TOSTRING_USE_KEY|CIT_TOSTRING_USE_CURRENT|CIT_TOSTRING_USE_INNER)))      {
        !          2600:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "%s does not fetch string value (see CachingIterator::__construct)", Z_OBJCE_P(getThis())->name);
        !          2601:                return;
        !          2602:        }
        !          2603:        if (intern->u.caching.flags & CIT_TOSTRING_USE_KEY) {
        !          2604:                if (intern->current.key_type == HASH_KEY_IS_STRING) {
        !          2605:                        RETURN_STRINGL(intern->current.str_key, intern->current.str_key_len-1, 1);
        !          2606:                } else {
        !          2607:                        RETVAL_LONG(intern->current.int_key);
        !          2608:                        convert_to_string(return_value);
        !          2609:                        return;
        !          2610:                }
        !          2611:        } else if (intern->u.caching.flags & CIT_TOSTRING_USE_CURRENT) {
        !          2612:                MAKE_COPY_ZVAL(&intern->current.data, return_value);
        !          2613:                convert_to_string(return_value);
        !          2614:                return;
        !          2615:        }
        !          2616:        if (intern->u.caching.zstr) {
        !          2617:                RETURN_STRINGL(Z_STRVAL_P(intern->u.caching.zstr), Z_STRLEN_P(intern->u.caching.zstr), 1);
        !          2618:        } else {
        !          2619:                RETURN_NULL();
        !          2620:        }
        !          2621: } /* }}} */
        !          2622: 
        !          2623: /* {{{ proto void CachingIterator::offsetSet(mixed index, mixed newval)
        !          2624:    Set given index in cache */
        !          2625: SPL_METHOD(CachingIterator, offsetSet)
        !          2626: {
        !          2627:        spl_dual_it_object   *intern;
        !          2628:        char *arKey;
        !          2629:        uint nKeyLength;
        !          2630:        zval *value;
        !          2631: 
        !          2632:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2633: 
        !          2634:        if (!(intern->u.caching.flags & CIT_FULL_CACHE))        {
        !          2635:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "%s does not use a full cache (see CachingIterator::__construct)", Z_OBJCE_P(getThis())->name);
        !          2636:                return;
        !          2637:        }
        !          2638: 
        !          2639:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &arKey, &nKeyLength, &value) == FAILURE) {
        !          2640:                return;
        !          2641:        }
        !          2642: 
        !          2643:        Z_ADDREF_P(value);
        !          2644:        zend_symtable_update(HASH_OF(intern->u.caching.zcache), arKey, nKeyLength+1, &value, sizeof(value), NULL);
        !          2645: }
        !          2646: /* }}} */
        !          2647: 
        !          2648: /* {{{ proto string CachingIterator::offsetGet(mixed index)
        !          2649:    Return the internal cache if used */
        !          2650: SPL_METHOD(CachingIterator, offsetGet)
        !          2651: {
        !          2652:        spl_dual_it_object   *intern;
        !          2653:        char *arKey;
        !          2654:        uint nKeyLength;
        !          2655:        zval **value;
        !          2656: 
        !          2657:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2658: 
        !          2659:        if (!(intern->u.caching.flags & CIT_FULL_CACHE))        {
        !          2660:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "%s does not use a full cache (see CachingIterator::__construct)", Z_OBJCE_P(getThis())->name);
        !          2661:                return;
        !          2662:        }
        !          2663: 
        !          2664:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arKey, &nKeyLength) == FAILURE) {
        !          2665:                return;
        !          2666:        }
        !          2667: 
        !          2668:        if (zend_symtable_find(HASH_OF(intern->u.caching.zcache), arKey, nKeyLength+1, (void**)&value) == FAILURE) {
        !          2669:                zend_error(E_NOTICE, "Undefined index:  %s", arKey);
        !          2670:                return;
        !          2671:        }
        !          2672:        
        !          2673:        RETURN_ZVAL(*value, 1, 0);
        !          2674: }
        !          2675: /* }}} */
        !          2676: 
        !          2677: /* {{{ proto void CachingIterator::offsetUnset(mixed index)
        !          2678:    Unset given index in cache */
        !          2679: SPL_METHOD(CachingIterator, offsetUnset)
        !          2680: {
        !          2681:        spl_dual_it_object   *intern;
        !          2682:        char *arKey;
        !          2683:        uint nKeyLength;
        !          2684: 
        !          2685:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2686: 
        !          2687:        if (!(intern->u.caching.flags & CIT_FULL_CACHE))        {
        !          2688:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "%s does not use a full cache (see CachingIterator::__construct)", Z_OBJCE_P(getThis())->name);
        !          2689:                return;
        !          2690:        }
        !          2691: 
        !          2692:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arKey, &nKeyLength) == FAILURE) {
        !          2693:                return;
        !          2694:        }
        !          2695: 
        !          2696:        zend_symtable_del(HASH_OF(intern->u.caching.zcache), arKey, nKeyLength+1);
        !          2697: }
        !          2698: /* }}} */
        !          2699: 
        !          2700: /* {{{ proto bool CachingIterator::offsetExists(mixed index)
        !          2701:    Return whether the requested index exists */
        !          2702: SPL_METHOD(CachingIterator, offsetExists)
        !          2703: {
        !          2704:        spl_dual_it_object   *intern;
        !          2705:        char *arKey;
        !          2706:        uint nKeyLength;
        !          2707:        
        !          2708:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2709: 
        !          2710:        if (!(intern->u.caching.flags & CIT_FULL_CACHE))        {
        !          2711:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "%s does not use a full cache (see CachingIterator::__construct)", Z_OBJCE_P(getThis())->name);
        !          2712:                return;
        !          2713:        }
        !          2714:        
        !          2715:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arKey, &nKeyLength) == FAILURE) {
        !          2716:                return;
        !          2717:        }
        !          2718: 
        !          2719:        RETURN_BOOL(zend_symtable_exists(HASH_OF(intern->u.caching.zcache), arKey, nKeyLength+1));
        !          2720: }
        !          2721: /* }}} */
        !          2722: 
        !          2723: /* {{{ proto bool CachingIterator::getCache()
        !          2724:    Return the cache */
        !          2725: SPL_METHOD(CachingIterator, getCache)
        !          2726: {
        !          2727:        spl_dual_it_object   *intern;
        !          2728:        
        !          2729:        if (zend_parse_parameters_none() == FAILURE) {
        !          2730:                return;
        !          2731:        }
        !          2732:        
        !          2733:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2734: 
        !          2735:        if (!(intern->u.caching.flags & CIT_FULL_CACHE))        {
        !          2736:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "%v does not use a full cache (see CachingIterator::__construct)", Z_OBJCE_P(getThis())->name);
        !          2737:                return;
        !          2738:        }
        !          2739: 
        !          2740:        RETURN_ZVAL(intern->u.caching.zcache, 1, 0);
        !          2741: }
        !          2742: /* }}} */
        !          2743: 
        !          2744: /* {{{ proto int CachingIterator::getFlags()
        !          2745:    Return the internal flags */
        !          2746: SPL_METHOD(CachingIterator, getFlags)
        !          2747: {
        !          2748:        spl_dual_it_object   *intern;
        !          2749: 
        !          2750:        if (zend_parse_parameters_none() == FAILURE) {
        !          2751:                return;
        !          2752:        }
        !          2753:        
        !          2754:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2755: 
        !          2756:        RETURN_LONG(intern->u.caching.flags);
        !          2757: }
        !          2758: /* }}} */
        !          2759: 
        !          2760: /* {{{ proto void CachingIterator::setFlags(int flags)
        !          2761:    Set the internal flags */
        !          2762: SPL_METHOD(CachingIterator, setFlags)
        !          2763: {
        !          2764:        spl_dual_it_object   *intern;
        !          2765:        long flags;
        !          2766: 
        !          2767:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2768: 
        !          2769:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &flags) == FAILURE) {
        !          2770:                return;
        !          2771:        }
        !          2772: 
        !          2773:        if (spl_cit_check_flags(flags) != SUCCESS) {
        !          2774:                zend_throw_exception(spl_ce_InvalidArgumentException , "Flags must contain only one of CALL_TOSTRING, TOSTRING_USE_KEY, TOSTRING_USE_CURRENT, TOSTRING_USE_INNER", 0 TSRMLS_CC);
        !          2775:                return;
        !          2776:        }
        !          2777:        if ((intern->u.caching.flags & CIT_CALL_TOSTRING) != 0 && (flags & CIT_CALL_TOSTRING) == 0) {
        !          2778:                zend_throw_exception(spl_ce_InvalidArgumentException, "Unsetting flag CALL_TO_STRING is not possible", 0 TSRMLS_CC);
        !          2779:                return;
        !          2780:        }
        !          2781:        if ((intern->u.caching.flags & CIT_TOSTRING_USE_INNER) != 0 && (flags & CIT_TOSTRING_USE_INNER) == 0) {
        !          2782:                zend_throw_exception(spl_ce_InvalidArgumentException, "Unsetting flag TOSTRING_USE_INNER is not possible", 0 TSRMLS_CC);
        !          2783:                return;
        !          2784:        }
        !          2785:        if ((flags & CIT_FULL_CACHE) != 0 && (intern->u.caching.flags & CIT_FULL_CACHE) == 0) {
        !          2786:                /* clear on (re)enable */
        !          2787:                zend_hash_clean(HASH_OF(intern->u.caching.zcache));
        !          2788:        }
        !          2789:        intern->u.caching.flags = (intern->u.caching.flags & ~CIT_PUBLIC) | (flags & CIT_PUBLIC);
        !          2790: }
        !          2791: /* }}} */
        !          2792: 
        !          2793: /* {{{ proto void CachingIterator::count()
        !          2794:    Number of cached elements */
        !          2795: SPL_METHOD(CachingIterator, count)
        !          2796: {
        !          2797:        spl_dual_it_object   *intern;
        !          2798: 
        !          2799:        if (zend_parse_parameters_none() == FAILURE) {
        !          2800:                return;
        !          2801:        }
        !          2802:        
        !          2803:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2804: 
        !          2805:        if (!(intern->u.caching.flags & CIT_FULL_CACHE))        {
        !          2806:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "%v does not use a full cache (see CachingIterator::__construct)", Z_OBJCE_P(getThis())->name);
        !          2807:                return;
        !          2808:        }
        !          2809: 
        !          2810:        RETURN_LONG(zend_hash_num_elements(HASH_OF(intern->u.caching.zcache)));
        !          2811: }
        !          2812: /* }}} */
        !          2813: 
        !          2814: ZEND_BEGIN_ARG_INFO_EX(arginfo_caching_it___construct, 0, 0, 1) 
        !          2815:        ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
        !          2816:        ZEND_ARG_INFO(0, flags)
        !          2817: ZEND_END_ARG_INFO();
        !          2818: 
        !          2819: ZEND_BEGIN_ARG_INFO(arginfo_caching_it_setFlags, 0) 
        !          2820:        ZEND_ARG_INFO(0, flags)
        !          2821: ZEND_END_ARG_INFO();
        !          2822: 
        !          2823: ZEND_BEGIN_ARG_INFO(arginfo_caching_it_offsetGet, 0)
        !          2824:        ZEND_ARG_INFO(0, index)
        !          2825: ZEND_END_ARG_INFO();
        !          2826: 
        !          2827: ZEND_BEGIN_ARG_INFO(arginfo_caching_it_offsetSet, 0)
        !          2828:        ZEND_ARG_INFO(0, index)
        !          2829:        ZEND_ARG_INFO(0, newval)
        !          2830: ZEND_END_ARG_INFO();
        !          2831: 
        !          2832: static const zend_function_entry spl_funcs_CachingIterator[] = {
        !          2833:        SPL_ME(CachingIterator, __construct,      arginfo_caching_it___construct, ZEND_ACC_PUBLIC)
        !          2834:        SPL_ME(CachingIterator, rewind,           arginfo_recursive_it_void,      ZEND_ACC_PUBLIC)
        !          2835:        SPL_ME(CachingIterator, valid,            arginfo_recursive_it_void,      ZEND_ACC_PUBLIC)
        !          2836:        SPL_ME(dual_it,         key,              arginfo_recursive_it_void,      ZEND_ACC_PUBLIC)
        !          2837:        SPL_ME(dual_it,         current,          arginfo_recursive_it_void,      ZEND_ACC_PUBLIC)
        !          2838:        SPL_ME(CachingIterator, next,             arginfo_recursive_it_void,      ZEND_ACC_PUBLIC)
        !          2839:        SPL_ME(CachingIterator, hasNext,          arginfo_recursive_it_void,      ZEND_ACC_PUBLIC)
        !          2840:        SPL_ME(CachingIterator, __toString,       arginfo_recursive_it_void,      ZEND_ACC_PUBLIC)
        !          2841:        SPL_ME(dual_it,         getInnerIterator, arginfo_recursive_it_void,      ZEND_ACC_PUBLIC)
        !          2842:        SPL_ME(CachingIterator, getFlags,         arginfo_recursive_it_void,      ZEND_ACC_PUBLIC)
        !          2843:        SPL_ME(CachingIterator, setFlags,         arginfo_caching_it_setFlags,    ZEND_ACC_PUBLIC)
        !          2844:        SPL_ME(CachingIterator, offsetGet,        arginfo_caching_it_offsetGet,   ZEND_ACC_PUBLIC)
        !          2845:        SPL_ME(CachingIterator, offsetSet,        arginfo_caching_it_offsetSet,   ZEND_ACC_PUBLIC)
        !          2846:        SPL_ME(CachingIterator, offsetUnset,      arginfo_caching_it_offsetGet,   ZEND_ACC_PUBLIC)
        !          2847:        SPL_ME(CachingIterator, offsetExists,     arginfo_caching_it_offsetGet,   ZEND_ACC_PUBLIC)
        !          2848:        SPL_ME(CachingIterator, getCache,         arginfo_recursive_it_void,      ZEND_ACC_PUBLIC)
        !          2849:        SPL_ME(CachingIterator, count,            arginfo_recursive_it_void,      ZEND_ACC_PUBLIC)
        !          2850:        PHP_FE_END
        !          2851: };
        !          2852: 
        !          2853: /* {{{ proto void RecursiveCachingIterator::__construct(RecursiveIterator it [, flags = CIT_CALL_TOSTRING])
        !          2854:    Create an iterator from a RecursiveIterator */
        !          2855: SPL_METHOD(RecursiveCachingIterator, __construct)
        !          2856: {
        !          2857:        spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_RecursiveCachingIterator, spl_ce_RecursiveIterator, DIT_RecursiveCachingIterator);
        !          2858: } /* }}} */
        !          2859: 
        !          2860: /* {{{ proto bool RecursiveCachingIterator::hasChildren()
        !          2861:    Check whether the current element of the inner iterator has children */
        !          2862: SPL_METHOD(RecursiveCachingIterator, hasChildren)
        !          2863: {
        !          2864:        spl_dual_it_object   *intern;
        !          2865: 
        !          2866:        if (zend_parse_parameters_none() == FAILURE) {
        !          2867:                return;
        !          2868:        }
        !          2869:        
        !          2870:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2871: 
        !          2872:        RETURN_BOOL(intern->u.caching.zchildren);
        !          2873: } /* }}} */
        !          2874: 
        !          2875: /* {{{ proto RecursiveCachingIterator RecursiveCachingIterator::getChildren()
        !          2876:   Return the inner iterator's children as a RecursiveCachingIterator */
        !          2877: SPL_METHOD(RecursiveCachingIterator, getChildren)
        !          2878: {
        !          2879:        spl_dual_it_object   *intern;
        !          2880:        
        !          2881:        if (zend_parse_parameters_none() == FAILURE) {
        !          2882:                return;
        !          2883:        }
        !          2884: 
        !          2885:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2886: 
        !          2887:        if (intern->u.caching.zchildren) {
        !          2888:                RETURN_ZVAL(intern->u.caching.zchildren, 1, 0);
        !          2889:        } else {
        !          2890:                RETURN_NULL();
        !          2891:        }
        !          2892: } /* }}} */
        !          2893: 
        !          2894: ZEND_BEGIN_ARG_INFO_EX(arginfo_caching_rec_it___construct, 0, ZEND_RETURN_VALUE, 1) 
        !          2895:        ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
        !          2896:        ZEND_ARG_INFO(0, flags)
        !          2897: ZEND_END_ARG_INFO();
        !          2898: 
        !          2899: static const zend_function_entry spl_funcs_RecursiveCachingIterator[] = {
        !          2900:        SPL_ME(RecursiveCachingIterator, __construct,   arginfo_caching_rec_it___construct, ZEND_ACC_PUBLIC)
        !          2901:        SPL_ME(RecursiveCachingIterator, hasChildren,   arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2902:        SPL_ME(RecursiveCachingIterator, getChildren,   arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2903:        PHP_FE_END
        !          2904: };
        !          2905: 
        !          2906: /* {{{ proto void IteratorIterator::__construct(Traversable it)
        !          2907:    Create an iterator from anything that is traversable */
        !          2908: SPL_METHOD(IteratorIterator, __construct)
        !          2909: {
        !          2910:        spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_IteratorIterator, zend_ce_traversable, DIT_IteratorIterator);
        !          2911: } /* }}} */
        !          2912: 
        !          2913: ZEND_BEGIN_ARG_INFO(arginfo_iterator_it___construct, 0) 
        !          2914:        ZEND_ARG_OBJ_INFO(0, iterator, Traversable, 0)
        !          2915: ZEND_END_ARG_INFO();
        !          2916: 
        !          2917: static const zend_function_entry spl_funcs_IteratorIterator[] = {
        !          2918:        SPL_ME(IteratorIterator, __construct,      arginfo_iterator_it___construct, ZEND_ACC_PUBLIC)
        !          2919:        SPL_ME(dual_it,          rewind,           arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2920:        SPL_ME(dual_it,          valid,            arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2921:        SPL_ME(dual_it,          key,              arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2922:        SPL_ME(dual_it,          current,          arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2923:        SPL_ME(dual_it,          next,             arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2924:        SPL_ME(dual_it,          getInnerIterator, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          2925:        PHP_FE_END
        !          2926: };
        !          2927: 
        !          2928: /* {{{ proto void NoRewindIterator::__construct(Iterator it)
        !          2929:    Create an iterator from another iterator */
        !          2930: SPL_METHOD(NoRewindIterator, __construct)
        !          2931: {
        !          2932:        spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_NoRewindIterator, zend_ce_iterator, DIT_NoRewindIterator);
        !          2933: } /* }}} */
        !          2934: 
        !          2935: /* {{{ proto void NoRewindIterator::rewind()
        !          2936:    Prevent a call to inner iterators rewind() */
        !          2937: SPL_METHOD(NoRewindIterator, rewind)
        !          2938: {
        !          2939:        if (zend_parse_parameters_none() == FAILURE) {
        !          2940:                return;
        !          2941:        }
        !          2942:        /* nothing to do */
        !          2943: } /* }}} */
        !          2944: 
        !          2945: /* {{{ proto bool NoRewindIterator::valid()
        !          2946:    Return inner iterators valid() */
        !          2947: SPL_METHOD(NoRewindIterator, valid)
        !          2948: {
        !          2949:        spl_dual_it_object   *intern;
        !          2950:        
        !          2951:        if (zend_parse_parameters_none() == FAILURE) {
        !          2952:                return;
        !          2953:        }
        !          2954: 
        !          2955:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2956:        RETURN_BOOL(intern->inner.iterator->funcs->valid(intern->inner.iterator TSRMLS_CC) == SUCCESS);
        !          2957: } /* }}} */
        !          2958: 
        !          2959: /* {{{ proto mixed NoRewindIterator::key()
        !          2960:    Return inner iterators key() */
        !          2961: SPL_METHOD(NoRewindIterator, key)
        !          2962: {
        !          2963:        spl_dual_it_object   *intern;
        !          2964:        
        !          2965:        if (zend_parse_parameters_none() == FAILURE) {
        !          2966:                return;
        !          2967:        }
        !          2968: 
        !          2969:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          2970: 
        !          2971:        if (intern->inner.iterator->funcs->get_current_key) {
        !          2972:                char *str_key;
        !          2973:                uint str_key_len;
        !          2974:                ulong int_key;
        !          2975:                switch (intern->inner.iterator->funcs->get_current_key(intern->inner.iterator, &str_key, &str_key_len, &int_key TSRMLS_CC)) {
        !          2976:                        case HASH_KEY_IS_LONG:
        !          2977:                                RETURN_LONG(int_key);
        !          2978:                                break;
        !          2979:                        case HASH_KEY_IS_STRING:
        !          2980:                                RETURN_STRINGL(str_key, str_key_len-1, 0);
        !          2981:                                break;
        !          2982:                        default:
        !          2983:                                RETURN_NULL();
        !          2984:                }
        !          2985:        } else {
        !          2986:                RETURN_NULL();
        !          2987:        }
        !          2988: } /* }}} */
        !          2989: 
        !          2990: /* {{{ proto mixed NoRewindIterator::current()
        !          2991:    Return inner iterators current() */
        !          2992: SPL_METHOD(NoRewindIterator, current)
        !          2993: {
        !          2994:        spl_dual_it_object   *intern;
        !          2995:        zval **data;
        !          2996:        
        !          2997:        if (zend_parse_parameters_none() == FAILURE) {
        !          2998:                return;
        !          2999:        }
        !          3000: 
        !          3001:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          3002:        intern->inner.iterator->funcs->get_current_data(intern->inner.iterator, &data TSRMLS_CC);
        !          3003:        if (data && *data) {
        !          3004:                RETURN_ZVAL(*data, 1, 0);
        !          3005:        }
        !          3006: } /* }}} */
        !          3007: 
        !          3008: /* {{{ proto void NoRewindIterator::next()
        !          3009:    Return inner iterators next() */
        !          3010: SPL_METHOD(NoRewindIterator, next)
        !          3011: {
        !          3012:        spl_dual_it_object   *intern;
        !          3013:        
        !          3014:        if (zend_parse_parameters_none() == FAILURE) {
        !          3015:                return;
        !          3016:        }
        !          3017: 
        !          3018:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          3019:        intern->inner.iterator->funcs->move_forward(intern->inner.iterator TSRMLS_CC);
        !          3020: } /* }}} */
        !          3021: 
        !          3022: ZEND_BEGIN_ARG_INFO(arginfo_norewind_it___construct, 0) 
        !          3023:        ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
        !          3024: ZEND_END_ARG_INFO();
        !          3025: 
        !          3026: static const zend_function_entry spl_funcs_NoRewindIterator[] = {
        !          3027:        SPL_ME(NoRewindIterator, __construct,      arginfo_norewind_it___construct, ZEND_ACC_PUBLIC)
        !          3028:        SPL_ME(NoRewindIterator, rewind,           arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          3029:        SPL_ME(NoRewindIterator, valid,            arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          3030:        SPL_ME(NoRewindIterator, key,              arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          3031:        SPL_ME(NoRewindIterator, current,          arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          3032:        SPL_ME(NoRewindIterator, next,             arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          3033:        SPL_ME(dual_it,          getInnerIterator, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          3034:        PHP_FE_END
        !          3035: };
        !          3036: 
        !          3037: /* {{{ proto void InfiniteIterator::__construct(Iterator it)
        !          3038:    Create an iterator from another iterator */
        !          3039: SPL_METHOD(InfiniteIterator, __construct)
        !          3040: {
        !          3041:        spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_InfiniteIterator, zend_ce_iterator, DIT_InfiniteIterator);
        !          3042: } /* }}} */
        !          3043: 
        !          3044: /* {{{ proto void InfiniteIterator::next()
        !          3045:    Prevent a call to inner iterators rewind() (internally the current data will be fetched if valid()) */
        !          3046: SPL_METHOD(InfiniteIterator, next)
        !          3047: {
        !          3048:        spl_dual_it_object   *intern;
        !          3049:        
        !          3050:        if (zend_parse_parameters_none() == FAILURE) {
        !          3051:                return;
        !          3052:        }
        !          3053: 
        !          3054:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          3055: 
        !          3056:        spl_dual_it_next(intern, 1 TSRMLS_CC);
        !          3057:        if (spl_dual_it_valid(intern TSRMLS_CC) == SUCCESS) {
        !          3058:                spl_dual_it_fetch(intern, 0 TSRMLS_CC);
        !          3059:        } else {
        !          3060:                spl_dual_it_rewind(intern TSRMLS_CC);
        !          3061:                if (spl_dual_it_valid(intern TSRMLS_CC) == SUCCESS) {
        !          3062:                        spl_dual_it_fetch(intern, 0 TSRMLS_CC);
        !          3063:                }
        !          3064:        }
        !          3065: } /* }}} */
        !          3066: 
        !          3067: static const zend_function_entry spl_funcs_InfiniteIterator[] = {
        !          3068:        SPL_ME(InfiniteIterator, __construct,      arginfo_norewind_it___construct, ZEND_ACC_PUBLIC)
        !          3069:        SPL_ME(InfiniteIterator, next,             arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          3070:        PHP_FE_END
        !          3071: };
        !          3072: 
        !          3073: /* {{{ proto void EmptyIterator::rewind()
        !          3074:    Does nothing  */
        !          3075: SPL_METHOD(EmptyIterator, rewind)
        !          3076: {
        !          3077:        if (zend_parse_parameters_none() == FAILURE) {
        !          3078:                return;
        !          3079:        }
        !          3080: } /* }}} */
        !          3081: 
        !          3082: /* {{{ proto false EmptyIterator::valid()
        !          3083:    Return false */
        !          3084: SPL_METHOD(EmptyIterator, valid)
        !          3085: {
        !          3086:        if (zend_parse_parameters_none() == FAILURE) {
        !          3087:                return;
        !          3088:        }
        !          3089:        RETURN_FALSE;
        !          3090: } /* }}} */
        !          3091: 
        !          3092: /* {{{ proto void EmptyIterator::key()
        !          3093:    Throws exception BadMethodCallException */
        !          3094: SPL_METHOD(EmptyIterator, key)
        !          3095: {
        !          3096:        if (zend_parse_parameters_none() == FAILURE) {
        !          3097:                return;
        !          3098:        }
        !          3099:        zend_throw_exception(spl_ce_BadMethodCallException, "Accessing the key of an EmptyIterator", 0 TSRMLS_CC);
        !          3100: } /* }}} */
        !          3101: 
        !          3102: /* {{{ proto void EmptyIterator::current()
        !          3103:    Throws exception BadMethodCallException */
        !          3104: SPL_METHOD(EmptyIterator, current)
        !          3105: {
        !          3106:        if (zend_parse_parameters_none() == FAILURE) {
        !          3107:                return;
        !          3108:        }
        !          3109:        zend_throw_exception(spl_ce_BadMethodCallException, "Accessing the value of an EmptyIterator", 0 TSRMLS_CC);
        !          3110: } /* }}} */
        !          3111: 
        !          3112: /* {{{ proto void EmptyIterator::next()
        !          3113:    Does nothing */
        !          3114: SPL_METHOD(EmptyIterator, next)
        !          3115: {
        !          3116:        if (zend_parse_parameters_none() == FAILURE) {
        !          3117:                return;
        !          3118:        }
        !          3119: } /* }}} */
        !          3120: 
        !          3121: static const zend_function_entry spl_funcs_EmptyIterator[] = {
        !          3122:        SPL_ME(EmptyIterator, rewind,           arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          3123:        SPL_ME(EmptyIterator, valid,            arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          3124:        SPL_ME(EmptyIterator, key,              arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          3125:        SPL_ME(EmptyIterator, current,          arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          3126:        SPL_ME(EmptyIterator, next,             arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          3127:        PHP_FE_END
        !          3128: };
        !          3129: 
        !          3130: int spl_append_it_next_iterator(spl_dual_it_object *intern TSRMLS_DC) /* {{{*/
        !          3131: {
        !          3132:        spl_dual_it_free(intern TSRMLS_CC);
        !          3133: 
        !          3134:        if (intern->inner.zobject) {
        !          3135:                zval_ptr_dtor(&intern->inner.zobject);
        !          3136:                intern->inner.zobject = NULL;
        !          3137:                intern->inner.ce = NULL;
        !          3138:                intern->inner.object = NULL;
        !          3139:                if (intern->inner.iterator) {
        !          3140:                        intern->inner.iterator->funcs->dtor(intern->inner.iterator TSRMLS_CC);
        !          3141:                        intern->inner.iterator = NULL;
        !          3142:                }
        !          3143:        }
        !          3144:        if (intern->u.append.iterator->funcs->valid(intern->u.append.iterator TSRMLS_CC) == SUCCESS) {
        !          3145:                zval **it;
        !          3146: 
        !          3147:                intern->u.append.iterator->funcs->get_current_data(intern->u.append.iterator, &it TSRMLS_CC);
        !          3148:                Z_ADDREF_PP(it);
        !          3149:                intern->inner.zobject = *it;
        !          3150:                intern->inner.ce = Z_OBJCE_PP(it);
        !          3151:                intern->inner.object = zend_object_store_get_object(*it TSRMLS_CC);
        !          3152:                intern->inner.iterator = intern->inner.ce->get_iterator(intern->inner.ce, *it, 0 TSRMLS_CC);
        !          3153:                spl_dual_it_rewind(intern TSRMLS_CC);
        !          3154:                return SUCCESS;
        !          3155:        } else {
        !          3156:                return FAILURE;
        !          3157:        }
        !          3158: } /* }}} */
        !          3159: 
        !          3160: void spl_append_it_fetch(spl_dual_it_object *intern TSRMLS_DC) /* {{{*/
        !          3161: {
        !          3162:        while (spl_dual_it_valid(intern TSRMLS_CC) != SUCCESS) {
        !          3163:                intern->u.append.iterator->funcs->move_forward(intern->u.append.iterator TSRMLS_CC);
        !          3164:                if (spl_append_it_next_iterator(intern TSRMLS_CC) != SUCCESS) {
        !          3165:                        return;
        !          3166:                }
        !          3167:        }
        !          3168:        spl_dual_it_fetch(intern, 0 TSRMLS_CC);
        !          3169: } /* }}} */
        !          3170: 
        !          3171: void spl_append_it_next(spl_dual_it_object *intern TSRMLS_DC) /* {{{ */
        !          3172: {
        !          3173:        if (spl_dual_it_valid(intern TSRMLS_CC) == SUCCESS) {
        !          3174:                spl_dual_it_next(intern, 1 TSRMLS_CC);
        !          3175:        }
        !          3176:        spl_append_it_fetch(intern TSRMLS_CC);
        !          3177: } /* }}} */
        !          3178: 
        !          3179: /* {{{ proto void AppendIterator::__construct()
        !          3180:    Create an AppendIterator */
        !          3181: SPL_METHOD(AppendIterator, __construct)
        !          3182: {
        !          3183:        spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_AppendIterator, zend_ce_iterator, DIT_AppendIterator);
        !          3184: } /* }}} */
        !          3185: 
        !          3186: /* {{{ proto void AppendIterator::append(Iterator it)
        !          3187:    Append an iterator */
        !          3188: SPL_METHOD(AppendIterator, append)
        !          3189: {
        !          3190:        spl_dual_it_object   *intern;
        !          3191:        zval *it;
        !          3192: 
        !          3193:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          3194: 
        !          3195:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "O", &it, zend_ce_iterator) == FAILURE) {
        !          3196:                return;
        !          3197:        }
        !          3198:        spl_array_iterator_append(intern->u.append.zarrayit, it TSRMLS_CC);
        !          3199: 
        !          3200:        if (!intern->inner.iterator || spl_dual_it_valid(intern TSRMLS_CC) != SUCCESS) {
        !          3201:                if (intern->u.append.iterator->funcs->valid(intern->u.append.iterator TSRMLS_CC) != SUCCESS) {
        !          3202:                        intern->u.append.iterator->funcs->rewind(intern->u.append.iterator TSRMLS_CC);
        !          3203:                }
        !          3204:                do {
        !          3205:                        spl_append_it_next_iterator(intern TSRMLS_CC);
        !          3206:                } while (intern->inner.zobject != it);
        !          3207:                spl_append_it_fetch(intern TSRMLS_CC);
        !          3208:        }
        !          3209: } /* }}} */
        !          3210: 
        !          3211: /* {{{ proto void AppendIterator::rewind()
        !          3212:    Rewind to the first iterator and rewind the first iterator, too */
        !          3213: SPL_METHOD(AppendIterator, rewind)
        !          3214: {
        !          3215:        spl_dual_it_object   *intern;
        !          3216:        
        !          3217:        if (zend_parse_parameters_none() == FAILURE) {
        !          3218:                return;
        !          3219:        }
        !          3220: 
        !          3221:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          3222:        
        !          3223:        intern->u.append.iterator->funcs->rewind(intern->u.append.iterator TSRMLS_CC);
        !          3224:        if (spl_append_it_next_iterator(intern TSRMLS_CC) == SUCCESS) {
        !          3225:                spl_append_it_fetch(intern TSRMLS_CC);
        !          3226:        }
        !          3227: } /* }}} */
        !          3228: 
        !          3229: /* {{{ proto bool AppendIterator::valid()
        !          3230:    Check if the current state is valid */
        !          3231: SPL_METHOD(AppendIterator, valid)
        !          3232: {
        !          3233:        spl_dual_it_object   *intern;
        !          3234: 
        !          3235:        if (zend_parse_parameters_none() == FAILURE) {
        !          3236:                return;
        !          3237:        }
        !          3238:        
        !          3239:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          3240: 
        !          3241:        RETURN_BOOL(intern->current.data);
        !          3242: } /* }}} */
        !          3243: 
        !          3244: /* {{{ proto void AppendIterator::next()
        !          3245:    Forward to next element */
        !          3246: SPL_METHOD(AppendIterator, next)
        !          3247: {
        !          3248:        spl_dual_it_object   *intern;
        !          3249:        
        !          3250:        if (zend_parse_parameters_none() == FAILURE) {
        !          3251:                return;
        !          3252:        }
        !          3253: 
        !          3254:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          3255:        
        !          3256:        spl_append_it_next(intern TSRMLS_CC);
        !          3257: } /* }}} */
        !          3258: 
        !          3259: /* {{{ proto int AppendIterator::getIteratorIndex()
        !          3260:    Get index of iterator */
        !          3261: SPL_METHOD(AppendIterator, getIteratorIndex)
        !          3262: {
        !          3263:        spl_dual_it_object   *intern;
        !          3264:        
        !          3265:        if (zend_parse_parameters_none() == FAILURE) {
        !          3266:                return;
        !          3267:        }
        !          3268: 
        !          3269:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          3270: 
        !          3271:        APPENDIT_CHECK_CTOR(intern);
        !          3272:        spl_array_iterator_key(intern->u.append.zarrayit, return_value TSRMLS_CC);
        !          3273: } /* }}} */
        !          3274: 
        !          3275: /* {{{ proto ArrayIterator AppendIterator::getArrayIterator()
        !          3276:    Get access to inner ArrayIterator */
        !          3277: SPL_METHOD(AppendIterator, getArrayIterator)
        !          3278: {
        !          3279:        spl_dual_it_object   *intern;
        !          3280:        
        !          3281:        if (zend_parse_parameters_none() == FAILURE) {
        !          3282:                return;
        !          3283:        }
        !          3284: 
        !          3285:        SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis());
        !          3286: 
        !          3287:        RETURN_ZVAL(intern->u.append.zarrayit, 1, 0);
        !          3288: } /* }}} */
        !          3289: 
        !          3290: ZEND_BEGIN_ARG_INFO(arginfo_append_it_append, 0) 
        !          3291:        ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
        !          3292: ZEND_END_ARG_INFO();
        !          3293: 
        !          3294: static const zend_function_entry spl_funcs_AppendIterator[] = {
        !          3295:        SPL_ME(AppendIterator, __construct,      arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          3296:        SPL_ME(AppendIterator, append,           arginfo_append_it_append, ZEND_ACC_PUBLIC)
        !          3297:        SPL_ME(AppendIterator, rewind,           arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          3298:        SPL_ME(AppendIterator, valid,            arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          3299:        SPL_ME(dual_it,        key,              arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          3300:        SPL_ME(dual_it,        current,          arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          3301:        SPL_ME(AppendIterator, next,             arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          3302:        SPL_ME(dual_it,        getInnerIterator, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          3303:        SPL_ME(AppendIterator, getIteratorIndex, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          3304:        SPL_ME(AppendIterator, getArrayIterator, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
        !          3305:        PHP_FE_END
        !          3306: };
        !          3307: 
        !          3308: PHPAPI int spl_iterator_apply(zval *obj, spl_iterator_apply_func_t apply_func, void *puser TSRMLS_DC)
        !          3309: {
        !          3310:        zend_object_iterator   *iter;
        !          3311:        zend_class_entry       *ce = Z_OBJCE_P(obj);
        !          3312: 
        !          3313:        iter = ce->get_iterator(ce, obj, 0 TSRMLS_CC);
        !          3314: 
        !          3315:        if (EG(exception)) {
        !          3316:                goto done;
        !          3317:        }
        !          3318: 
        !          3319:        iter->index = 0;
        !          3320:        if (iter->funcs->rewind) {
        !          3321:                iter->funcs->rewind(iter TSRMLS_CC);
        !          3322:                if (EG(exception)) {
        !          3323:                        goto done;
        !          3324:                }
        !          3325:        }
        !          3326: 
        !          3327:        while (iter->funcs->valid(iter TSRMLS_CC) == SUCCESS) {
        !          3328:                if (EG(exception)) {
        !          3329:                        goto done;
        !          3330:                }
        !          3331:                if (apply_func(iter, puser TSRMLS_CC) == ZEND_HASH_APPLY_STOP || EG(exception)) {
        !          3332:                        goto done;
        !          3333:                }
        !          3334:                iter->index++;
        !          3335:                iter->funcs->move_forward(iter TSRMLS_CC);
        !          3336:                if (EG(exception)) {
        !          3337:                        goto done;
        !          3338:                }
        !          3339:        }
        !          3340: 
        !          3341: done:
        !          3342:        if (iter) {
        !          3343:                iter->funcs->dtor(iter TSRMLS_CC);
        !          3344:        }
        !          3345:        return EG(exception) ? FAILURE : SUCCESS;
        !          3346: }
        !          3347: /* }}} */
        !          3348: 
        !          3349: static int spl_iterator_to_array_apply(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{ */
        !          3350: {
        !          3351:        zval                    **data, *return_value = (zval*)puser;
        !          3352:        char                    *str_key;
        !          3353:        uint                    str_key_len;
        !          3354:        ulong                   int_key;
        !          3355:        int                     key_type;
        !          3356: 
        !          3357:        iter->funcs->get_current_data(iter, &data TSRMLS_CC);
        !          3358:        if (EG(exception)) {
        !          3359:                return ZEND_HASH_APPLY_STOP;
        !          3360:        }
        !          3361:        if (data == NULL || *data == NULL) {
        !          3362:                return ZEND_HASH_APPLY_STOP;
        !          3363:        }
        !          3364:        if (iter->funcs->get_current_key) {
        !          3365:                key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC);
        !          3366:                if (EG(exception)) {
        !          3367:                        return ZEND_HASH_APPLY_STOP;
        !          3368:                }
        !          3369:                Z_ADDREF_PP(data);
        !          3370:                switch(key_type) {
        !          3371:                        case HASH_KEY_IS_STRING:
        !          3372:                                add_assoc_zval_ex(return_value, str_key, str_key_len, *data);
        !          3373:                                efree(str_key);
        !          3374:                                break;
        !          3375:                        case HASH_KEY_IS_LONG:
        !          3376:                                add_index_zval(return_value, int_key, *data);
        !          3377:                                break;
        !          3378:                }
        !          3379:        } else {
        !          3380:                Z_ADDREF_PP(data);
        !          3381:                add_next_index_zval(return_value, *data);
        !          3382:        }
        !          3383:        return ZEND_HASH_APPLY_KEEP;
        !          3384: }
        !          3385: /* }}} */
        !          3386: 
        !          3387: static int spl_iterator_to_values_apply(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{ */
        !          3388: {
        !          3389:        zval **data, *return_value = (zval*)puser;
        !          3390: 
        !          3391:        iter->funcs->get_current_data(iter, &data TSRMLS_CC);
        !          3392:        if (EG(exception)) {
        !          3393:                return ZEND_HASH_APPLY_STOP;
        !          3394:        }
        !          3395:        if (data == NULL || *data == NULL) {
        !          3396:                return ZEND_HASH_APPLY_STOP;
        !          3397:        }
        !          3398:        Z_ADDREF_PP(data);
        !          3399:        add_next_index_zval(return_value, *data);
        !          3400:        return ZEND_HASH_APPLY_KEEP;
        !          3401: }
        !          3402: /* }}} */
        !          3403: 
        !          3404: /* {{{ proto array iterator_to_array(Traversable it [, bool use_keys = true]) 
        !          3405:    Copy the iterator into an array */
        !          3406: PHP_FUNCTION(iterator_to_array)
        !          3407: {
        !          3408:        zval  *obj;
        !          3409:        zend_bool use_keys = 1;
        !          3410: 
        !          3411:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|b", &obj, zend_ce_traversable, &use_keys) == FAILURE) {
        !          3412:                RETURN_FALSE;
        !          3413:        }
        !          3414: 
        !          3415:        array_init(return_value);
        !          3416: 
        !          3417:        if (spl_iterator_apply(obj, use_keys ? spl_iterator_to_array_apply : spl_iterator_to_values_apply, (void*)return_value TSRMLS_CC) != SUCCESS) {
        !          3418:                zval_dtor(return_value);
        !          3419:                RETURN_NULL();
        !          3420:        }
        !          3421: } /* }}} */
        !          3422: 
        !          3423: static int spl_iterator_count_apply(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{ */
        !          3424: {
        !          3425:        (*(long*)puser)++;
        !          3426:        return ZEND_HASH_APPLY_KEEP;
        !          3427: }
        !          3428: /* }}} */
        !          3429: 
        !          3430: /* {{{ proto int iterator_count(Traversable it) 
        !          3431:    Count the elements in an iterator */
        !          3432: PHP_FUNCTION(iterator_count)
        !          3433: {
        !          3434:        zval  *obj;
        !          3435:        long  count = 0;
        !          3436: 
        !          3437:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &obj, zend_ce_traversable) == FAILURE) {
        !          3438:                RETURN_FALSE;
        !          3439:        }
        !          3440:        
        !          3441:        if (spl_iterator_apply(obj, spl_iterator_count_apply, (void*)&count TSRMLS_CC) == SUCCESS) {
        !          3442:                RETURN_LONG(count);
        !          3443:        }
        !          3444: }
        !          3445: /* }}} */
        !          3446: 
        !          3447: typedef struct {
        !          3448:        zval                   *obj;
        !          3449:        zval                   *args;
        !          3450:        long                   count;
        !          3451:        zend_fcall_info        fci;
        !          3452:        zend_fcall_info_cache  fcc;
        !          3453: } spl_iterator_apply_info;
        !          3454: 
        !          3455: static int spl_iterator_func_apply(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{ */
        !          3456: {
        !          3457:        zval *retval;
        !          3458:        spl_iterator_apply_info  *apply_info = (spl_iterator_apply_info*)puser;
        !          3459:        int result;
        !          3460: 
        !          3461:        apply_info->count++;
        !          3462:        zend_fcall_info_call(&apply_info->fci, &apply_info->fcc, &retval, NULL TSRMLS_CC);
        !          3463:        if (retval) {
        !          3464:                result = zend_is_true(retval) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_STOP;
        !          3465:                zval_ptr_dtor(&retval);
        !          3466:        } else {
        !          3467:                result = ZEND_HASH_APPLY_STOP;
        !          3468:        }
        !          3469:        return result;
        !          3470: }
        !          3471: /* }}} */
        !          3472: 
        !          3473: /* {{{ proto int iterator_apply(Traversable it, mixed function [, mixed params])
        !          3474:    Calls a function for every element in an iterator */
        !          3475: PHP_FUNCTION(iterator_apply)
        !          3476: {
        !          3477:        spl_iterator_apply_info  apply_info;
        !          3478: 
        !          3479:        apply_info.args = NULL;
        !          3480:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Of|a!", &apply_info.obj, zend_ce_traversable, &apply_info.fci, &apply_info.fcc, &apply_info.args) == FAILURE) {
        !          3481:                return;
        !          3482:        }
        !          3483: 
        !          3484:        apply_info.count = 0;
        !          3485:        zend_fcall_info_args(&apply_info.fci, apply_info.args TSRMLS_CC);
        !          3486:        if (spl_iterator_apply(apply_info.obj, spl_iterator_func_apply, (void*)&apply_info TSRMLS_CC) == SUCCESS) {
        !          3487:                RETVAL_LONG(apply_info.count);
        !          3488:        } else {
        !          3489:                RETVAL_FALSE;
        !          3490:        }
        !          3491:        zend_fcall_info_args(&apply_info.fci, NULL TSRMLS_CC);
        !          3492: }
        !          3493: /* }}} */
        !          3494: 
        !          3495: static const zend_function_entry spl_funcs_OuterIterator[] = {
        !          3496:        SPL_ABSTRACT_ME(OuterIterator, getInnerIterator,   arginfo_recursive_it_void)
        !          3497:        PHP_FE_END
        !          3498: };
        !          3499: 
        !          3500: static const zend_function_entry spl_funcs_Countable[] = {
        !          3501:        SPL_ABSTRACT_ME(Countable, count,   arginfo_recursive_it_void)
        !          3502:        PHP_FE_END
        !          3503: };
        !          3504: 
        !          3505: /* {{{ PHP_MINIT_FUNCTION(spl_iterators)
        !          3506:  */
        !          3507: PHP_MINIT_FUNCTION(spl_iterators)
        !          3508: {
        !          3509:        REGISTER_SPL_INTERFACE(RecursiveIterator);
        !          3510:        REGISTER_SPL_ITERATOR(RecursiveIterator);
        !          3511: 
        !          3512:        REGISTER_SPL_STD_CLASS_EX(RecursiveIteratorIterator, spl_RecursiveIteratorIterator_new, spl_funcs_RecursiveIteratorIterator);
        !          3513:        REGISTER_SPL_ITERATOR(RecursiveIteratorIterator);
        !          3514: 
        !          3515:        memcpy(&spl_handlers_rec_it_it, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
        !          3516:        spl_handlers_rec_it_it.get_method = spl_recursive_it_get_method;
        !          3517:        spl_handlers_rec_it_it.clone_obj = NULL;
        !          3518: 
        !          3519:        memcpy(&spl_handlers_dual_it, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
        !          3520:        spl_handlers_dual_it.get_method = spl_dual_it_get_method;
        !          3521:        /*spl_handlers_dual_it.call_method = spl_dual_it_call_method;*/
        !          3522:        spl_handlers_dual_it.clone_obj = NULL;
        !          3523:        
        !          3524:        spl_ce_RecursiveIteratorIterator->get_iterator = spl_recursive_it_get_iterator;
        !          3525:        spl_ce_RecursiveIteratorIterator->iterator_funcs.funcs = &spl_recursive_it_iterator_funcs;
        !          3526: 
        !          3527:        REGISTER_SPL_CLASS_CONST_LONG(RecursiveIteratorIterator, "LEAVES_ONLY",     RIT_LEAVES_ONLY);
        !          3528:        REGISTER_SPL_CLASS_CONST_LONG(RecursiveIteratorIterator, "SELF_FIRST",      RIT_SELF_FIRST);
        !          3529:        REGISTER_SPL_CLASS_CONST_LONG(RecursiveIteratorIterator, "CHILD_FIRST",     RIT_CHILD_FIRST);
        !          3530:        REGISTER_SPL_CLASS_CONST_LONG(RecursiveIteratorIterator, "CATCH_GET_CHILD", RIT_CATCH_GET_CHILD);
        !          3531: 
        !          3532:        REGISTER_SPL_INTERFACE(OuterIterator);
        !          3533:        REGISTER_SPL_ITERATOR(OuterIterator);
        !          3534: 
        !          3535:        REGISTER_SPL_STD_CLASS_EX(IteratorIterator, spl_dual_it_new, spl_funcs_IteratorIterator);
        !          3536:        REGISTER_SPL_ITERATOR(IteratorIterator);
        !          3537:        REGISTER_SPL_IMPLEMENTS(IteratorIterator, OuterIterator);
        !          3538: 
        !          3539:        REGISTER_SPL_SUB_CLASS_EX(FilterIterator, IteratorIterator, spl_dual_it_new, spl_funcs_FilterIterator);
        !          3540:        spl_ce_FilterIterator->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
        !          3541: 
        !          3542:        REGISTER_SPL_SUB_CLASS_EX(RecursiveFilterIterator, FilterIterator, spl_dual_it_new, spl_funcs_RecursiveFilterIterator);
        !          3543:        REGISTER_SPL_IMPLEMENTS(RecursiveFilterIterator, RecursiveIterator);
        !          3544: 
        !          3545:        REGISTER_SPL_SUB_CLASS_EX(ParentIterator, RecursiveFilterIterator, spl_dual_it_new, spl_funcs_ParentIterator);
        !          3546: 
        !          3547:        REGISTER_SPL_INTERFACE(Countable);
        !          3548:        REGISTER_SPL_INTERFACE(SeekableIterator);
        !          3549:        REGISTER_SPL_ITERATOR(SeekableIterator);
        !          3550: 
        !          3551:        REGISTER_SPL_SUB_CLASS_EX(LimitIterator, IteratorIterator, spl_dual_it_new, spl_funcs_LimitIterator);
        !          3552: 
        !          3553:        REGISTER_SPL_SUB_CLASS_EX(CachingIterator, IteratorIterator, spl_dual_it_new, spl_funcs_CachingIterator);
        !          3554:        REGISTER_SPL_IMPLEMENTS(CachingIterator, ArrayAccess);
        !          3555:        REGISTER_SPL_IMPLEMENTS(CachingIterator, Countable);
        !          3556: 
        !          3557:        REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "CALL_TOSTRING",        CIT_CALL_TOSTRING); 
        !          3558:        REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "CATCH_GET_CHILD",      CIT_CATCH_GET_CHILD); 
        !          3559:        REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "TOSTRING_USE_KEY",     CIT_TOSTRING_USE_KEY);
        !          3560:        REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "TOSTRING_USE_CURRENT", CIT_TOSTRING_USE_CURRENT);
        !          3561:        REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "TOSTRING_USE_INNER",   CIT_TOSTRING_USE_INNER);
        !          3562:        REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "FULL_CACHE",           CIT_FULL_CACHE); 
        !          3563: 
        !          3564:        REGISTER_SPL_SUB_CLASS_EX(RecursiveCachingIterator, CachingIterator, spl_dual_it_new, spl_funcs_RecursiveCachingIterator);
        !          3565:        REGISTER_SPL_IMPLEMENTS(RecursiveCachingIterator, RecursiveIterator);
        !          3566:        
        !          3567:        REGISTER_SPL_SUB_CLASS_EX(NoRewindIterator, IteratorIterator, spl_dual_it_new, spl_funcs_NoRewindIterator);
        !          3568: 
        !          3569:        REGISTER_SPL_SUB_CLASS_EX(AppendIterator, IteratorIterator, spl_dual_it_new, spl_funcs_AppendIterator);
        !          3570: 
        !          3571:        REGISTER_SPL_IMPLEMENTS(RecursiveIteratorIterator, OuterIterator);
        !          3572: 
        !          3573:        REGISTER_SPL_SUB_CLASS_EX(InfiniteIterator, IteratorIterator, spl_dual_it_new, spl_funcs_InfiniteIterator);
        !          3574: #if HAVE_PCRE || HAVE_BUNDLED_PCRE
        !          3575:        REGISTER_SPL_SUB_CLASS_EX(RegexIterator, FilterIterator, spl_dual_it_new, spl_funcs_RegexIterator);
        !          3576:        REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "USE_KEY",     REGIT_USE_KEY);
        !          3577:        REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "MATCH",       REGIT_MODE_MATCH);
        !          3578:        REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "GET_MATCH",   REGIT_MODE_GET_MATCH);
        !          3579:        REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "ALL_MATCHES", REGIT_MODE_ALL_MATCHES);
        !          3580:        REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "SPLIT",       REGIT_MODE_SPLIT);
        !          3581:        REGISTER_SPL_CLASS_CONST_LONG(RegexIterator, "REPLACE",     REGIT_MODE_REPLACE);
        !          3582:        REGISTER_SPL_PROPERTY(RegexIterator, "replacement", 0);
        !          3583:        REGISTER_SPL_SUB_CLASS_EX(RecursiveRegexIterator, RegexIterator, spl_dual_it_new, spl_funcs_RecursiveRegexIterator);
        !          3584:        REGISTER_SPL_IMPLEMENTS(RecursiveRegexIterator, RecursiveIterator);
        !          3585: #else
        !          3586:        spl_ce_RegexIterator = NULL;
        !          3587:        spl_ce_RecursiveRegexIterator = NULL;
        !          3588: #endif
        !          3589: 
        !          3590:        REGISTER_SPL_STD_CLASS_EX(EmptyIterator, NULL, spl_funcs_EmptyIterator);
        !          3591:        REGISTER_SPL_ITERATOR(EmptyIterator);
        !          3592: 
        !          3593:        REGISTER_SPL_SUB_CLASS_EX(RecursiveTreeIterator, RecursiveIteratorIterator, spl_RecursiveTreeIterator_new, spl_funcs_RecursiveTreeIterator);
        !          3594:        REGISTER_SPL_CLASS_CONST_LONG(RecursiveTreeIterator, "BYPASS_CURRENT",      RTIT_BYPASS_CURRENT);
        !          3595:        REGISTER_SPL_CLASS_CONST_LONG(RecursiveTreeIterator, "BYPASS_KEY",          RTIT_BYPASS_KEY);
        !          3596:        REGISTER_SPL_CLASS_CONST_LONG(RecursiveTreeIterator, "PREFIX_LEFT",         0);
        !          3597:        REGISTER_SPL_CLASS_CONST_LONG(RecursiveTreeIterator, "PREFIX_MID_HAS_NEXT", 1);
        !          3598:        REGISTER_SPL_CLASS_CONST_LONG(RecursiveTreeIterator, "PREFIX_MID_LAST",     2);
        !          3599:        REGISTER_SPL_CLASS_CONST_LONG(RecursiveTreeIterator, "PREFIX_END_HAS_NEXT", 3);
        !          3600:        REGISTER_SPL_CLASS_CONST_LONG(RecursiveTreeIterator, "PREFIX_END_LAST",     4);
        !          3601:        REGISTER_SPL_CLASS_CONST_LONG(RecursiveTreeIterator, "PREFIX_RIGHT",        5);
        !          3602: 
        !          3603:        return SUCCESS;
        !          3604: }
        !          3605: /* }}} */
        !          3606: 
        !          3607: /*
        !          3608:  * Local variables:
        !          3609:  * tab-width: 4
        !          3610:  * c-basic-offset: 4
        !          3611:  * End:
        !          3612:  * vim600: fdm=marker
        !          3613:  * vim: noet sw=4 ts=4
        !          3614:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>