2003-11-09 14:05:36 +00:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| PHP Version 5 |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2004-01-08 18:17:39 +00:00
| Copyright ( c ) 1997 - 2004 The PHP Group |
2003-11-09 14:05:36 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| This source file is subject to version 3.0 of the PHP license , |
| that is bundled with this package in the file LICENSE , and is |
| available through the world - wide - web at the following url : |
| http : //www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world - wide - web , please send a note to |
| license @ php . net so we can mail you a copy immediately . |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Authors : Marcus Boerger < helly @ php . net > |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
2004-01-20 20:59:45 +00:00
/* $Id$ */
2003-11-09 14:05:36 +00:00
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include "php.h"
# include "php_ini.h"
# include "ext/standard/info.h"
2004-02-12 10:43:27 +00:00
# include "zend_exceptions.h"
2003-11-09 14:05:36 +00:00
# include "zend_interfaces.h"
# include "php_spl.h"
# include "spl_functions.h"
# include "spl_engine.h"
# include "spl_iterators.h"
2003-12-02 07:18:05 +00:00
# include "spl_directory.h"
2004-11-01 00:26:59 +00:00
# include "spl_array.h"
2004-11-01 17:39:59 +00:00
# include "spl_exceptions.h"
2003-11-09 14:05:36 +00:00
2003-12-08 08:39:18 +00:00
# define INLINE inline
2004-11-01 20:57:23 +00:00
PHPAPI zend_class_entry * spl_ce_RecursiveIterator ;
PHPAPI zend_class_entry * spl_ce_RecursiveIteratorIterator ;
PHPAPI zend_class_entry * spl_ce_FilterIterator ;
PHPAPI zend_class_entry * spl_ce_ParentIterator ;
PHPAPI zend_class_entry * spl_ce_SeekableIterator ;
PHPAPI zend_class_entry * spl_ce_LimitIterator ;
PHPAPI zend_class_entry * spl_ce_CachingIterator ;
PHPAPI zend_class_entry * spl_ce_CachingRecursiveIterator ;
PHPAPI zend_class_entry * spl_ce_OuterIterator ;
PHPAPI zend_class_entry * spl_ce_IteratorIterator ;
PHPAPI zend_class_entry * spl_ce_NoRewindIterator ;
PHPAPI zend_class_entry * spl_ce_InfiniteIterator ;
PHPAPI zend_class_entry * spl_ce_EmptyIterator ;
PHPAPI zend_class_entry * spl_ce_AppendIterator ;
2003-11-09 14:05:36 +00:00
function_entry spl_funcs_RecursiveIterator [ ] = {
SPL_ABSTRACT_ME ( RecursiveIterator , hasChildren , NULL )
SPL_ABSTRACT_ME ( RecursiveIterator , getChildren , NULL )
{ NULL , NULL , NULL }
} ;
2003-11-11 00:25:26 +00:00
typedef enum {
RIT_LEAVES_ONLY = 0 ,
RIT_SELF_FIRST = 1 ,
RIT_CHILD_FIRST = 2
} RecursiveIteratorMode ;
typedef enum {
RS_NEXT = 0 ,
RS_TEST = 1 ,
RS_SELF = 2 ,
RS_CHILD = 3 ,
RS_START = 4
} RecursiveIteratorState ;
2003-11-09 14:05:36 +00:00
typedef struct _spl_sub_iterator {
zend_object_iterator * iterator ;
zval * zobject ;
zend_class_entry * ce ;
2003-11-11 00:25:26 +00:00
RecursiveIteratorState state ;
2003-11-09 14:05:36 +00:00
} spl_sub_iterator ;
typedef struct _spl_recursive_it_object {
zend_object std ;
spl_sub_iterator * iterators ;
int level ;
2003-11-11 00:25:26 +00:00
RecursiveIteratorMode mode ;
2004-11-01 23:02:10 +00:00
zend_function * beginChildren ;
zend_function * endChildren ;
zend_class_entry * ce ;
2003-11-09 14:05:36 +00:00
} spl_recursive_it_object ;
typedef struct _spl_recursive_it_iterator {
zend_object_iterator intern ;
zval * zobject ;
} spl_recursive_it_iterator ;
2003-12-08 08:39:18 +00:00
static zend_object_handlers spl_handlers_rec_it_it ;
static zend_object_handlers spl_handlers_dual_it ;
2003-11-09 14:05:36 +00:00
static void spl_recursive_it_dtor ( zend_object_iterator * _iter TSRMLS_DC )
{
spl_recursive_it_iterator * iter = ( spl_recursive_it_iterator * ) _iter ;
spl_recursive_it_object * object = ( spl_recursive_it_object * ) _iter - > data ;
zend_object_iterator * sub_iter ;
while ( object - > level ) {
sub_iter = object - > iterators [ object - > level ] . iterator ;
sub_iter - > funcs - > dtor ( sub_iter TSRMLS_CC ) ;
zval_ptr_dtor ( & object - > iterators [ object - > level - - ] . zobject ) ;
}
erealloc ( object - > iterators , sizeof ( spl_sub_iterator ) ) ;
object - > level = 0 ;
zval_ptr_dtor ( & iter - > zobject ) ;
efree ( iter ) ;
}
2004-03-08 18:05:41 +00:00
static int spl_recursive_it_valid_ex ( spl_recursive_it_object * object TSRMLS_DC )
2003-11-09 14:05:36 +00:00
{
zend_object_iterator * sub_iter ;
int level = object - > level ;
while ( level > = 0 ) {
sub_iter = object - > iterators [ level ] . iterator ;
2004-03-08 18:05:41 +00:00
if ( sub_iter - > funcs - > valid ( sub_iter TSRMLS_CC ) = = SUCCESS ) {
2003-11-09 14:05:36 +00:00
return SUCCESS ;
}
level - - ;
}
return FAILURE ;
}
2004-03-08 18:05:41 +00:00
static int spl_recursive_it_valid ( zend_object_iterator * iter TSRMLS_DC )
2003-11-09 14:05:36 +00:00
{
spl_recursive_it_object * object = ( spl_recursive_it_object * ) iter - > data ;
2004-03-08 18:05:41 +00:00
return spl_recursive_it_valid_ex ( object TSRMLS_CC ) ;
2003-11-09 14:05:36 +00:00
}
static void spl_recursive_it_get_current_data ( zend_object_iterator * iter , zval * * * data TSRMLS_DC )
{
spl_recursive_it_object * object = ( spl_recursive_it_object * ) iter - > data ;
zend_object_iterator * sub_iter = object - > iterators [ object - > level ] . iterator ;
2003-11-17 00:57:01 +00:00
sub_iter - > funcs - > get_current_data ( sub_iter , data TSRMLS_CC ) ;
2003-11-09 14:05:36 +00:00
}
static int spl_recursive_it_get_current_key ( zend_object_iterator * iter , char * * str_key , uint * str_key_len , ulong * int_key TSRMLS_DC )
{
spl_recursive_it_object * object = ( spl_recursive_it_object * ) iter - > data ;
zend_object_iterator * sub_iter = object - > iterators [ object - > level ] . iterator ;
if ( sub_iter - > funcs - > get_current_key ) {
return sub_iter - > funcs - > get_current_key ( sub_iter , str_key , str_key_len , int_key TSRMLS_CC ) ;
} else {
* int_key = iter - > index ;
return HASH_KEY_IS_LONG ;
}
}
2004-11-01 22:54:12 +00:00
static void spl_recursive_it_move_forward_ex ( spl_recursive_it_object * object , zval * zthis TSRMLS_DC )
2003-11-09 14:05:36 +00:00
{
zend_object_iterator * iterator ;
zval * zobject ;
zend_class_entry * ce ;
zval * retval , * child ;
zend_object_iterator * sub_iter ;
while ( 1 ) {
2003-11-11 00:25:26 +00:00
next_step :
2003-11-09 14:05:36 +00:00
iterator = object - > iterators [ object - > level ] . iterator ;
2003-11-11 00:25:26 +00:00
switch ( object - > iterators [ object - > level ] . state ) {
case RS_NEXT :
iterator - > funcs - > move_forward ( iterator TSRMLS_CC ) ;
case RS_START :
2004-03-08 18:05:41 +00:00
if ( iterator - > funcs - > valid ( iterator TSRMLS_CC ) = = FAILURE ) {
2003-11-11 00:25:26 +00:00
break ;
}
object - > iterators [ object - > level ] . state = RS_TEST ;
/* break; */
case RS_TEST :
ce = object - > iterators [ object - > level ] . ce ;
zobject = object - > iterators [ object - > level ] . zobject ;
zend_call_method_with_0_params ( & zobject , ce , NULL , " haschildren " , & retval ) ;
if ( zend_is_true ( retval ) ) {
zval_ptr_dtor ( & retval ) ;
switch ( object - > mode ) {
case RIT_LEAVES_ONLY :
case RIT_CHILD_FIRST :
object - > iterators [ object - > level ] . state = RS_CHILD ;
goto next_step ;
case RIT_SELF_FIRST :
object - > iterators [ object - > level ] . state = RS_SELF ;
goto next_step ;
}
}
zval_ptr_dtor ( & retval ) ;
object - > iterators [ object - > level ] . state = RS_NEXT ;
return /* self */ ;
case RS_SELF :
if ( object - > mode = = RIT_SELF_FIRST ) {
object - > iterators [ object - > level ] . state = RS_CHILD ;
} else {
object - > iterators [ object - > level ] . state = RS_NEXT ;
}
return /* self */ ;
case RS_CHILD :
ce = object - > iterators [ object - > level ] . ce ;
zobject = object - > iterators [ object - > level ] . zobject ;
2003-11-09 14:05:36 +00:00
zend_call_method_with_0_params ( & zobject , ce , NULL , " getchildren " , & child ) ;
2004-04-27 17:12:11 +00:00
ce = child ? Z_OBJCE_P ( child ) : NULL ;
2003-11-09 14:05:36 +00:00
if ( ! ce | | ! instanceof_function ( ce , spl_ce_RecursiveIterator TSRMLS_CC ) ) {
2004-04-27 17:12:11 +00:00
if ( child ) {
zval_ptr_dtor ( & child ) ;
}
2004-11-01 17:39:59 +00:00
zend_throw_exception ( spl_ce_InvalidArgumentException , " Objects returned by RecursiveIterator::getChildren() must implement RecursiveIterator " , 0 TSRMLS_CC ) ;
2003-11-09 14:05:36 +00:00
return ;
}
2003-11-11 00:25:26 +00:00
if ( object - > mode = = RIT_CHILD_FIRST ) {
object - > iterators [ object - > level ] . state = RS_SELF ;
} else {
object - > iterators [ object - > level ] . state = RS_NEXT ;
}
2003-11-09 14:05:36 +00:00
object - > iterators = erealloc ( object - > iterators , sizeof ( spl_sub_iterator ) * ( + + object - > level + 1 ) ) ;
sub_iter = ce - > get_iterator ( ce , child TSRMLS_CC ) ;
object - > iterators [ object - > level ] . iterator = sub_iter ;
object - > iterators [ object - > level ] . zobject = child ;
object - > iterators [ object - > level ] . ce = ce ;
2003-11-11 00:25:26 +00:00
object - > iterators [ object - > level ] . state = RS_START ;
2003-12-02 07:18:05 +00:00
if ( sub_iter - > funcs - > rewind ) {
sub_iter - > funcs - > rewind ( sub_iter TSRMLS_CC ) ;
}
2004-11-01 23:16:43 +00:00
if ( ! object - > beginChildren | | object - > beginChildren - > common . scope ! = spl_ce_RecursiveIteratorIterator ) {
zend_call_method_with_0_params ( & zthis , object - > ce , & object - > beginChildren , " beginchildren " , NULL ) ;
}
2003-11-11 00:25:26 +00:00
goto next_step ;
2003-11-09 14:05:36 +00:00
}
/* no more elements */
if ( object - > level > 0 ) {
iterator - > funcs - > dtor ( iterator TSRMLS_CC ) ;
zval_ptr_dtor ( & object - > iterators [ object - > level ] . zobject ) ;
object - > level - - ;
2004-11-01 23:16:43 +00:00
if ( ! object - > endChildren | | object - > endChildren - > common . scope ! = spl_ce_RecursiveIteratorIterator ) {
zend_call_method_with_0_params ( & zthis , object - > ce , & object - > endChildren , " endchildren " , NULL ) ;
}
2003-11-09 14:05:36 +00:00
} else {
return ; /* done completeley */
}
}
}
2004-11-01 22:54:12 +00:00
static void spl_recursive_it_rewind_ex ( spl_recursive_it_object * object , zval * zthis TSRMLS_DC )
2003-11-09 14:05:36 +00:00
{
zend_object_iterator * sub_iter ;
while ( object - > level ) {
sub_iter = object - > iterators [ object - > level ] . iterator ;
sub_iter - > funcs - > dtor ( sub_iter TSRMLS_CC ) ;
zval_ptr_dtor ( & object - > iterators [ object - > level - - ] . zobject ) ;
2004-11-01 23:16:43 +00:00
if ( ! object - > endChildren | | object - > endChildren - > common . scope ! = spl_ce_RecursiveIteratorIterator ) {
zend_call_method_with_0_params ( & zthis , object - > ce , & object - > endChildren , " endchildren " , NULL ) ;
}
2003-11-09 14:05:36 +00:00
}
erealloc ( object - > iterators , sizeof ( spl_sub_iterator ) ) ;
2003-11-11 00:25:26 +00:00
object - > iterators [ 0 ] . state = RS_START ;
2003-11-09 14:05:36 +00:00
sub_iter = object - > iterators [ 0 ] . iterator ;
if ( sub_iter - > funcs - > rewind ) {
sub_iter - > funcs - > rewind ( sub_iter TSRMLS_CC ) ;
}
2004-11-01 22:54:12 +00:00
spl_recursive_it_move_forward_ex ( object , zthis TSRMLS_CC ) ;
2003-11-09 14:05:36 +00:00
}
static void spl_recursive_it_move_forward ( zend_object_iterator * iter TSRMLS_DC )
{
2004-11-01 22:54:12 +00:00
spl_recursive_it_move_forward_ex ( ( spl_recursive_it_object * ) iter - > data , ( ( spl_recursive_it_iterator * ) iter ) - > zobject TSRMLS_CC ) ;
2003-11-09 14:05:36 +00:00
}
static void spl_recursive_it_rewind ( zend_object_iterator * iter TSRMLS_DC )
{
2004-11-01 22:54:12 +00:00
spl_recursive_it_rewind_ex ( ( spl_recursive_it_object * ) iter - > data , ( ( spl_recursive_it_iterator * ) iter ) - > zobject TSRMLS_CC ) ;
2003-11-09 14:05:36 +00:00
}
static zend_object_iterator * spl_recursive_it_get_iterator ( zend_class_entry * ce , zval * zobject TSRMLS_DC )
{
spl_recursive_it_iterator * iterator = emalloc ( sizeof ( spl_recursive_it_iterator ) ) ;
spl_recursive_it_object * object = ( spl_recursive_it_object * ) zend_object_store_get_object ( zobject TSRMLS_CC ) ;
zobject - > refcount + + ;
iterator - > intern . data = ( void * ) object ;
iterator - > intern . funcs = ce - > iterator_funcs . funcs ;
iterator - > zobject = zobject ;
return ( zend_object_iterator * ) iterator ;
}
zend_object_iterator_funcs spl_recursive_it_iterator_funcs = {
spl_recursive_it_dtor ,
2004-03-08 18:05:41 +00:00
spl_recursive_it_valid ,
2003-11-09 14:05:36 +00:00
spl_recursive_it_get_current_data ,
spl_recursive_it_get_current_key ,
spl_recursive_it_move_forward ,
spl_recursive_it_rewind
} ;
2004-11-08 13:44:34 +00:00
/* {{{ proto RecursiveIteratorIterator::__construct(RecursiveIterator|IteratorAggregate it [, int flags = RIT_LEAVES_ONLY]) throws InvalidArgumentException
2004-05-06 09:01:31 +00:00
Creates a RecursiveIteratorIterator from a RecursiveIterator . */
2003-11-09 14:05:36 +00:00
SPL_METHOD ( RecursiveIteratorIterator , __construct )
{
zval * object = getThis ( ) ;
spl_recursive_it_object * intern ;
zval * iterator ;
zend_class_entry * ce_iterator ;
2004-02-25 20:16:27 +00:00
long mode = RIT_LEAVES_ONLY ;
2003-11-09 14:05:36 +00:00
2004-11-08 13:44:34 +00:00
php_set_error_handling ( EH_THROW , spl_ce_InvalidArgumentException TSRMLS_CC ) ;
2003-11-09 14:05:36 +00:00
2004-11-08 13:44:34 +00:00
if ( zend_parse_parameters_ex ( ZEND_PARSE_PARAMS_QUIET , ZEND_NUM_ARGS ( ) TSRMLS_CC , " o|l " , & iterator , & mode ) = = SUCCESS ) {
if ( instanceof_function ( Z_OBJCE_P ( iterator ) , zend_ce_aggregate TSRMLS_CC ) ) {
zval * aggregate = iterator ;
zend_call_method_with_0_params ( & aggregate , Z_OBJCE_P ( aggregate ) , & Z_OBJCE_P ( aggregate ) - > iterator_funcs . zf_new_iterator , " getiterator " , & iterator ) ;
}
} else {
iterator = NULL ;
}
if ( ! iterator | | ! instanceof_function ( Z_OBJCE_P ( iterator ) , spl_ce_RecursiveIterator TSRMLS_CC ) ) {
2003-11-09 14:05:36 +00:00
php_set_error_handling ( EH_NORMAL , NULL TSRMLS_CC ) ;
2004-11-08 13:44:34 +00:00
zend_throw_exception ( spl_ce_InvalidArgumentException , " An instance of RecursiveIterator or IteratorAggregate creating it is required " , 0 TSRMLS_CC ) ;
2003-11-09 14:05:36 +00:00
return ;
}
intern = ( spl_recursive_it_object * ) zend_object_store_get_object ( object TSRMLS_CC ) ;
intern - > iterators = emalloc ( sizeof ( spl_sub_iterator ) ) ;
intern - > level = 0 ;
2003-11-11 00:25:26 +00:00
intern - > mode = mode ;
2004-11-01 23:02:10 +00:00
intern - > beginChildren = NULL ;
intern - > endChildren = NULL ;
intern - > ce = Z_OBJCE_P ( object ) ;
2003-11-09 14:05:36 +00:00
ce_iterator = Z_OBJCE_P ( iterator ) ; /* respect inheritance, don't use spl_ce_RecursiveIterator */
intern - > iterators [ 0 ] . iterator = ce_iterator - > get_iterator ( ce_iterator , iterator TSRMLS_CC ) ;
2003-11-22 20:49:15 +00:00
iterator - > refcount + + ;
2003-11-09 14:05:36 +00:00
intern - > iterators [ 0 ] . zobject = iterator ;
intern - > iterators [ 0 ] . ce = ce_iterator ;
2003-11-11 00:25:26 +00:00
intern - > iterators [ 0 ] . state = RS_START ;
2003-11-09 14:05:36 +00:00
php_set_error_handling ( EH_NORMAL , NULL TSRMLS_CC ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-11-09 14:05:36 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto void RecursiveIteratorIterator::rewind()
Rewind the iterator to the first element of the top level inner iterator . */
2003-11-09 14:05:36 +00:00
SPL_METHOD ( RecursiveIteratorIterator , rewind )
{
spl_recursive_it_object * object = ( spl_recursive_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
2004-11-01 22:54:12 +00:00
spl_recursive_it_rewind_ex ( object , getThis ( ) TSRMLS_CC ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-11-09 14:05:36 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto bolean RecursiveIteratorIterator::valid()
Check whether the current position is valid */
2004-03-08 17:33:31 +00:00
SPL_METHOD ( RecursiveIteratorIterator , valid )
2003-11-09 14:05:36 +00:00
{
spl_recursive_it_object * object = ( spl_recursive_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
2004-03-08 18:05:41 +00:00
RETURN_BOOL ( spl_recursive_it_valid_ex ( object TSRMLS_CC ) = = SUCCESS ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-11-09 14:05:36 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto mixed RecursiveIteratorIterator::key()
Access the current key */
2003-11-09 14:05:36 +00:00
SPL_METHOD ( RecursiveIteratorIterator , key )
{
spl_recursive_it_object * object = ( spl_recursive_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
zend_object_iterator * iterator = object - > iterators [ object - > level ] . iterator ;
if ( iterator - > funcs - > get_current_key ) {
char * str_key ;
uint str_key_len ;
ulong int_key ;
if ( iterator - > funcs - > get_current_key ( iterator , & str_key , & str_key_len , & int_key TSRMLS_CC ) = = HASH_KEY_IS_LONG ) {
RETURN_LONG ( int_key ) ;
} else {
2003-11-17 00:57:01 +00:00
RETURN_STRINGL ( str_key , str_key_len - 1 , 0 ) ;
2003-11-09 14:05:36 +00:00
}
} else {
RETURN_NULL ( ) ;
}
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-11-09 14:05:36 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto mixed RecursiveIteratorIterator::current()
Access the current element value */
2003-11-09 14:05:36 +00:00
SPL_METHOD ( RecursiveIteratorIterator , current )
{
spl_recursive_it_object * object = ( spl_recursive_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
zend_object_iterator * iterator = object - > iterators [ object - > level ] . iterator ;
zval * * data ;
iterator - > funcs - > get_current_data ( iterator , & data TSRMLS_CC ) ;
2003-11-29 18:31:24 +00:00
RETURN_ZVAL ( * data , 1 , 0 ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-11-09 14:05:36 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto void RecursiveIteratorIterator::next()
Move forward to the next element */
2003-11-09 14:05:36 +00:00
SPL_METHOD ( RecursiveIteratorIterator , next )
{
spl_recursive_it_object * object = ( spl_recursive_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
2004-11-01 22:54:12 +00:00
spl_recursive_it_move_forward_ex ( object , getThis ( ) TSRMLS_CC ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-11-09 14:05:36 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto int RecursiveIteratorIterator::getDepth()
Get the current depth of the recursive iteration */
2003-11-22 20:49:15 +00:00
SPL_METHOD ( RecursiveIteratorIterator , getDepth )
2003-11-09 14:05:36 +00:00
{
spl_recursive_it_object * object = ( spl_recursive_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
RETURN_LONG ( object - > level ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-11-09 14:05:36 +00:00
2004-10-29 20:12:57 +00:00
/* {{{ proto RecursiveIterator RecursiveIteratorIterator::getSubIterator([int level])
The current active sub iterator or the iterator at specified level */
2003-11-18 22:14:19 +00:00
SPL_METHOD ( RecursiveIteratorIterator , getSubIterator )
{
spl_recursive_it_object * object = ( spl_recursive_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
2004-02-25 20:16:27 +00:00
long level = object - > level ;
2003-11-18 22:14:19 +00:00
2003-11-22 20:49:15 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " |l " , & level ) = = FAILURE ) {
2003-11-18 22:14:19 +00:00
return ;
}
if ( level < 0 | | level > object - > level ) {
RETURN_NULL ( ) ;
}
2003-12-10 10:19:43 +00:00
RETURN_ZVAL ( object - > iterators [ level ] . zobject , 1 , 0 ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-11-18 22:14:19 +00:00
2004-10-29 20:12:57 +00:00
/* {{{ proto RecursiveIterator RecursiveIteratorIterator::getInnerIterator()
The current active sub iterator */
SPL_METHOD ( RecursiveIteratorIterator , getInnerIterator )
{
spl_recursive_it_object * object = ( spl_recursive_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
long level = object - > level ;
RETURN_ZVAL ( object - > iterators [ level ] . zobject , 1 , 0 ) ;
} /* }}} */
2004-11-01 22:54:12 +00:00
/* {{{ proto RecursiveIterator RecursiveIteratorIterator::beginChildren()
Called when recursing one level down */
SPL_METHOD ( RecursiveIteratorIterator , beginChildren )
{
/* nothing to do */
} /* }}} */
/* {{{ proto RecursiveIterator RecursiveIteratorIterator::endChildren()
Called when end recursing one level */
SPL_METHOD ( RecursiveIteratorIterator , endChildren )
{
/* nothing to do */
} /* }}} */
2004-10-31 19:05:19 +00:00
static union _zend_function * spl_recursive_it_get_method ( zval * * object_ptr , char * method , int method_len TSRMLS_DC )
{
union _zend_function * function_handler ;
spl_recursive_it_object * object = ( spl_recursive_it_object * ) zend_object_store_get_object ( * object_ptr TSRMLS_CC ) ;
long level = object - > level ;
zval * zobj = object - > iterators [ level ] . zobject ;
function_handler = std_object_handlers . get_method ( object_ptr , method , method_len TSRMLS_CC ) ;
if ( ! function_handler ) {
if ( zend_hash_find ( & Z_OBJCE_P ( zobj ) - > function_table , method , method_len + 1 , ( void * * ) & function_handler ) = = FAILURE ) {
if ( Z_OBJ_HT_P ( zobj ) - > get_method ) {
* object_ptr = zobj ;
function_handler = Z_OBJ_HT_P ( * object_ptr ) - > get_method ( object_ptr , method , method_len TSRMLS_CC ) ;
}
}
}
return function_handler ;
}
2003-12-08 08:39:18 +00:00
/* {{{ spl_RecursiveIteratorIterator_dtor */
2004-02-04 12:45:47 +00:00
static void spl_RecursiveIteratorIterator_free_storage ( void * _object TSRMLS_DC )
2003-11-09 14:05:36 +00:00
{
spl_recursive_it_object * object = ( spl_recursive_it_object * ) _object ;
zend_object_iterator * sub_iter ;
if ( object - > iterators ) {
while ( object - > level > = 0 ) {
sub_iter = object - > iterators [ object - > level ] . iterator ;
sub_iter - > funcs - > dtor ( sub_iter TSRMLS_CC ) ;
zval_ptr_dtor ( & object - > iterators [ object - > level - - ] . zobject ) ;
}
efree ( object - > iterators ) ;
}
zend_hash_destroy ( object - > std . properties ) ;
FREE_HASHTABLE ( object - > std . properties ) ;
efree ( object ) ;
}
/* }}} */
2003-12-08 08:39:18 +00:00
/* {{{ spl_RecursiveIteratorIterator_new */
static zend_object_value spl_RecursiveIteratorIterator_new ( zend_class_entry * class_type TSRMLS_DC )
2003-11-09 14:05:36 +00:00
{
zend_object_value retval ;
spl_recursive_it_object * intern ;
zval * tmp ;
intern = emalloc ( sizeof ( spl_recursive_it_object ) ) ;
memset ( intern , 0 , sizeof ( spl_recursive_it_object ) ) ;
intern - > std . ce = class_type ;
ALLOC_HASHTABLE ( intern - > std . properties ) ;
zend_hash_init ( intern - > std . properties , 0 , NULL , ZVAL_PTR_DTOR , 0 ) ;
zend_hash_copy ( intern - > std . properties , & class_type - > default_properties , ( copy_ctor_func_t ) zval_add_ref , ( void * ) & tmp , sizeof ( zval * ) ) ;
2004-02-04 12:45:47 +00:00
retval . handle = zend_objects_store_put ( intern , NULL , ( zend_objects_free_object_storage_t ) spl_RecursiveIteratorIterator_free_storage , NULL TSRMLS_CC ) ;
2003-12-08 08:39:18 +00:00
retval . handlers = & spl_handlers_rec_it_it ;
2003-12-02 07:18:05 +00:00
return retval ;
}
/* }}} */
2004-11-01 22:54:12 +00:00
static
ZEND_BEGIN_ARG_INFO ( arginfo_recursive_it___construct , 0 )
2004-11-08 13:44:34 +00:00
ZEND_ARG_OBJ_INFO ( 0 , iterator , Traversable , 0 )
2004-11-01 22:54:12 +00:00
ZEND_ARG_INFO ( 0 , mode )
ZEND_END_ARG_INFO ( ) ;
static
ZEND_BEGIN_ARG_INFO ( arginfo_recursive_it_getSubIterator , 0 )
ZEND_ARG_INFO ( 0 , level )
ZEND_END_ARG_INFO ( ) ;
static zend_function_entry spl_funcs_RecursiveIteratorIterator [ ] = {
SPL_ME ( RecursiveIteratorIterator , __construct , arginfo_recursive_it___construct , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , rewind , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , valid , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , key , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , current , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , next , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , getDepth , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , getSubIterator , arginfo_recursive_it_getSubIterator , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , getInnerIterator , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , beginChildren , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , endChildren , NULL , ZEND_ACC_PUBLIC )
{ NULL , NULL , NULL }
} ;
2003-12-02 07:18:05 +00:00
# if MBO_0
static int spl_dual_it_gets_implemented ( zend_class_entry * interface , zend_class_entry * class_type TSRMLS_DC )
{
2004-03-08 18:05:41 +00:00
class_type - > iterator_funcs . zf_valid = NULL ;
2003-12-02 07:18:05 +00:00
class_type - > iterator_funcs . zf_current = NULL ;
class_type - > iterator_funcs . zf_key = NULL ;
class_type - > iterator_funcs . zf_next = NULL ;
class_type - > iterator_funcs . zf_rewind = NULL ;
if ( ! class_type - > iterator_funcs . funcs ) {
class_type - > iterator_funcs . funcs = & zend_interface_iterator_funcs_iterator ;
}
return SUCCESS ;
}
# endif
2004-10-30 19:12:14 +00:00
static union _zend_function * spl_dual_it_get_method ( zval * * object_ptr , char * method , int method_len TSRMLS_DC )
2003-12-08 08:39:18 +00:00
{
union _zend_function * function_handler ;
spl_dual_it_object * intern ;
2004-10-30 19:12:14 +00:00
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( * object_ptr TSRMLS_CC ) ;
2003-12-08 08:39:18 +00:00
2004-10-30 19:12:14 +00:00
function_handler = std_object_handlers . get_method ( object_ptr , method , method_len TSRMLS_CC ) ;
2003-12-08 08:39:18 +00:00
if ( ! function_handler ) {
if ( zend_hash_find ( & intern - > inner . ce - > function_table , method , method_len + 1 , ( void * * ) & function_handler ) = = FAILURE ) {
if ( Z_OBJ_HT_P ( intern - > inner . zobject ) - > get_method ) {
2004-10-30 19:12:14 +00:00
* object_ptr = intern - > inner . zobject ;
function_handler = Z_OBJ_HT_P ( * object_ptr ) - > get_method ( object_ptr , method , method_len TSRMLS_CC ) ;
2003-12-08 08:39:18 +00:00
}
}
}
return function_handler ;
}
# if MBO_0
int spl_dual_it_call_method ( char * method , INTERNAL_FUNCTION_PARAMETERS )
{
zval * * * func_params , func ;
zval * retval_ptr ;
int arg_count ;
int current = 0 ;
int success ;
void * * p ;
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
ZVAL_STRING ( & func , method , 0 ) ;
if ( ! zend_is_callable ( & func , 0 , & method ) ) {
php_error_docref ( NULL TSRMLS_CC , E_ERROR , " Method %s::%s() does not exist " , intern - > inner . ce - > name , method ) ;
return FAILURE ;
}
2003-12-06 19:21:02 +00:00
2003-12-08 08:39:18 +00:00
p = EG ( argument_stack ) . top_element - 2 ;
arg_count = ( ulong ) * p ;
func_params = safe_emalloc ( sizeof ( zval * * ) , arg_count , 0 ) ;
current = 0 ;
while ( arg_count - - > 0 ) {
func_params [ current ] = ( zval * * ) p - ( arg_count - current ) ;
current + + ;
}
if ( call_user_function_ex ( EG ( function_table ) , NULL , & func , & retval_ptr , arg_count , func_params , 0 , NULL TSRMLS_CC ) = = SUCCESS & & retval_ptr ) {
RETURN_ZVAL ( retval_ptr , 0 , 1 ) ;
success = SUCCESS ;
} else {
php_error_docref ( NULL TSRMLS_CC , E_ERROR , " Unable to call %s::%s() " , intern - > inner . ce - > name , method ) ;
success = FAILURE ;
}
efree ( func_params ) ;
return success ;
}
# endif
2004-10-31 18:43:00 +00:00
static INLINE int spl_dual_it_fetch ( spl_dual_it_object * intern , int check_more TSRMLS_DC ) ;
2003-12-08 08:39:18 +00:00
static INLINE spl_dual_it_object * spl_dual_it_construct ( INTERNAL_FUNCTION_PARAMETERS , zend_class_entry * ce_inner , dual_it_type dit_type )
2003-12-02 07:18:05 +00:00
{
zval * zobject ;
spl_dual_it_object * intern ;
2004-11-11 19:36:27 +00:00
php_set_error_handling ( EH_THROW , spl_ce_InvalidArgumentException TSRMLS_CC ) ;
2003-12-02 07:18:05 +00:00
2003-12-06 19:21:02 +00:00
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
2003-12-08 08:39:18 +00:00
intern - > dit_type = dit_type ;
2003-12-06 19:21:02 +00:00
switch ( dit_type ) {
2003-12-08 08:39:18 +00:00
case DIT_LimitIterator : {
2004-05-18 20:39:35 +00:00
intern - > u . limit . offset = 0 ; /* start at beginning */
2003-12-06 19:21:02 +00:00
intern - > u . limit . count = - 1 ; /* get all */
2004-05-18 20:39:35 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " O|ll " , & zobject , ce_inner , & intern - > u . limit . offset , & intern - > u . limit . count ) = = FAILURE ) {
2003-12-06 19:21:02 +00:00
php_set_error_handling ( EH_NORMAL , NULL TSRMLS_CC ) ;
return NULL ;
}
if ( intern - > u . limit . offset < 0 ) {
php_set_error_handling ( EH_NORMAL , NULL TSRMLS_CC ) ;
2004-11-01 17:39:59 +00:00
zend_throw_exception ( spl_ce_OutOfRangeException , " Parameter offset must be > 0 " , 0 TSRMLS_CC ) ;
2003-12-06 19:21:02 +00:00
return NULL ;
}
if ( intern - > u . limit . count < 0 & & intern - > u . limit . count ! = - 1 ) {
php_set_error_handling ( EH_NORMAL , NULL TSRMLS_CC ) ;
2004-11-01 17:39:59 +00:00
zend_throw_exception ( spl_ce_OutOfRangeException , " Parameter count must either be -1 or a value greater than or equal 0 " , 0 TSRMLS_CC ) ;
2003-12-06 19:21:02 +00:00
return NULL ;
}
break ;
}
2003-12-08 08:39:18 +00:00
case DIT_CachingIterator :
case DIT_CachingRecursiveIterator : {
long flags = CIT_CALL_TOSTRING ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " O|l " , & zobject , ce_inner , & flags ) = = FAILURE ) {
php_set_error_handling ( EH_NORMAL , NULL TSRMLS_CC ) ;
return NULL ;
}
intern - > u . caching . flags | = flags & CIT_PUBLIC ;
break ;
}
2004-10-31 18:43:00 +00:00
case DIT_IteratorIterator : {
zend_class_entry * ce ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " O " , & zobject , ce_inner ) = = FAILURE ) {
php_set_error_handling ( EH_NORMAL , NULL TSRMLS_CC ) ;
return NULL ;
}
ce = Z_OBJCE_P ( zobject ) ;
if ( ! instanceof_function ( ce , zend_ce_iterator TSRMLS_CC ) ) {
if ( instanceof_function ( ce , zend_ce_aggregate TSRMLS_CC ) ) {
zval * retval ;
zobject = zend_call_method_with_0_params ( & zobject , ce , & ce - > iterator_funcs . zf_new_iterator , " getiterator " , & retval ) ;
}
}
break ;
}
2004-11-01 00:26:59 +00:00
case DIT_AppendIterator :
spl_instantiate ( spl_ce_ArrayIterator , & intern - > u . append . zarrayit , 1 TSRMLS_CC ) ;
zend_call_method_with_0_params ( & intern - > u . append . zarrayit , spl_ce_ArrayIterator , & spl_ce_ArrayIterator - > constructor , " __construct " , NULL ) ;
intern - > u . append . iterator = spl_ce_ArrayIterator - > get_iterator ( spl_ce_ArrayIterator , intern - > u . append . zarrayit TSRMLS_CC ) ;
php_set_error_handling ( EH_NORMAL , NULL TSRMLS_CC ) ;
return intern ;
2003-12-06 19:21:02 +00:00
default :
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " O " , & zobject , ce_inner ) = = FAILURE ) {
php_set_error_handling ( EH_NORMAL , NULL TSRMLS_CC ) ;
return NULL ;
}
break ;
2003-12-02 07:18:05 +00:00
}
2004-11-11 19:36:27 +00:00
php_set_error_handling ( EH_THROW , zend_exception_get_default ( ) TSRMLS_CC ) ;
2003-12-02 07:18:05 +00:00
zobject - > refcount + + ;
intern - > inner . zobject = zobject ;
intern - > inner . ce = Z_OBJCE_P ( zobject ) ;
intern - > inner . object = zend_object_store_get_object ( zobject TSRMLS_CC ) ;
intern - > inner . iterator = intern - > inner . ce - > get_iterator ( intern - > inner . ce , zobject TSRMLS_CC ) ;
php_set_error_handling ( EH_NORMAL , NULL TSRMLS_CC ) ;
2003-12-06 19:21:02 +00:00
return intern ;
2003-12-02 07:18:05 +00:00
}
2004-10-30 10:18:10 +00:00
/* {{{ proto FilterIterator::__construct(Iterator it)
2004-05-06 09:01:31 +00:00
Create an Iterator from another iterator */
2003-12-06 19:21:02 +00:00
SPL_METHOD ( dual_it , __construct )
2003-12-02 07:18:05 +00:00
{
2003-12-08 08:39:18 +00:00
spl_dual_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , zend_ce_iterator , DIT_Default ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-02 07:18:05 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto Iterator FilterIterator::getInnerIterator()
proto Iterator CachingIterator : : getInnerIterator ( )
proto Iterator LimitIterator : : getInnerIterator ( )
proto Iterator ParentIterator : : getInnerIterator ( )
Get the inner iterator */
2004-03-09 17:35:18 +00:00
SPL_METHOD ( dual_it , getInnerIterator )
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
if ( intern - > inner . zobject ) {
2004-04-14 23:26:56 +00:00
RETVAL_ZVAL ( intern - > inner . zobject , 1 , 0 ) ;
2004-03-09 17:35:18 +00:00
} else {
RETURN_NULL ( ) ;
}
2004-05-06 09:01:31 +00:00
} /* }}} */
2004-03-09 17:35:18 +00:00
2004-07-28 22:53:10 +00:00
static INLINE void spl_dual_it_require ( spl_dual_it_object * intern TSRMLS_DC )
{
if ( ! intern - > inner . iterator ) {
php_error_docref ( NULL TSRMLS_CC , E_ERROR , " The inner constructor wasn't initialized with an iterator instance " ) ;
}
}
2003-12-08 08:39:18 +00:00
static INLINE void spl_dual_it_free ( spl_dual_it_object * intern TSRMLS_DC )
2003-12-02 07:18:05 +00:00
{
2004-04-27 17:12:11 +00:00
if ( intern - > inner . iterator & & intern - > inner . iterator - > funcs - > invalidate_current ) {
2004-04-27 15:41:26 +00:00
intern - > inner . iterator - > funcs - > invalidate_current ( intern - > inner . iterator TSRMLS_CC ) ;
}
2003-12-10 10:19:43 +00:00
if ( intern - > current . data ) {
zval_ptr_dtor ( & intern - > current . data ) ;
2003-12-02 07:18:05 +00:00
intern - > current . data = NULL ;
}
if ( intern - > current . str_key ) {
efree ( intern - > current . str_key ) ;
intern - > current . str_key = NULL ;
}
2003-12-08 08:39:18 +00:00
if ( intern - > dit_type = = DIT_CachingIterator | | intern - > dit_type = = DIT_CachingRecursiveIterator ) {
if ( intern - > u . caching . zstr ) {
zval_ptr_dtor ( & intern - > u . caching . zstr ) ;
intern - > u . caching . zstr = NULL ;
}
if ( intern - > u . caching . zchildren ) {
zval_ptr_dtor ( & intern - > u . caching . zchildren ) ;
intern - > u . caching . zchildren = NULL ;
}
}
2003-12-02 07:18:05 +00:00
}
2003-12-08 08:39:18 +00:00
static INLINE void spl_dual_it_rewind ( spl_dual_it_object * intern TSRMLS_DC )
2003-12-02 07:18:05 +00:00
{
spl_dual_it_free ( intern TSRMLS_CC ) ;
2003-12-06 19:21:02 +00:00
intern - > current . pos = 0 ;
2003-12-02 07:18:05 +00:00
if ( intern - > inner . iterator - > funcs - > rewind ) {
intern - > inner . iterator - > funcs - > rewind ( intern - > inner . iterator TSRMLS_CC ) ;
}
}
2004-03-08 18:05:41 +00:00
static INLINE int spl_dual_it_valid ( spl_dual_it_object * intern TSRMLS_DC )
2003-12-02 07:18:05 +00:00
{
/* FAILURE / SUCCESS */
2004-03-08 18:05:41 +00:00
return intern - > inner . iterator - > funcs - > valid ( intern - > inner . iterator TSRMLS_CC ) ;
2003-12-02 07:18:05 +00:00
}
2003-12-10 10:19:43 +00:00
static INLINE int spl_dual_it_fetch ( spl_dual_it_object * intern , int check_more TSRMLS_DC )
2003-12-02 07:18:05 +00:00
{
2003-12-10 10:19:43 +00:00
zval * * data ;
2003-12-02 07:18:05 +00:00
spl_dual_it_free ( intern TSRMLS_CC ) ;
2004-03-08 18:05:41 +00:00
if ( ! check_more | | spl_dual_it_valid ( intern TSRMLS_CC ) = = SUCCESS ) {
2003-12-10 10:19:43 +00:00
intern - > inner . iterator - > funcs - > get_current_data ( intern - > inner . iterator , & data TSRMLS_CC ) ;
intern - > current . data = * data ;
intern - > current . data - > refcount + + ;
2003-12-06 19:21:02 +00:00
if ( intern - > inner . iterator - > funcs - > get_current_key ) {
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 ) ;
} else {
intern - > current . key_type = HASH_KEY_IS_LONG ;
intern - > current . int_key = intern - > current . pos ;
}
2003-12-10 10:19:43 +00:00
return SUCCESS ;
2003-12-06 19:21:02 +00:00
}
2003-12-10 10:19:43 +00:00
return FAILURE ;
2003-12-02 07:18:05 +00:00
}
2003-12-08 08:39:18 +00:00
static INLINE void spl_dual_it_next ( spl_dual_it_object * intern , int do_free TSRMLS_DC )
2003-12-02 07:18:05 +00:00
{
2003-12-08 08:39:18 +00:00
if ( do_free ) {
spl_dual_it_free ( intern TSRMLS_CC ) ;
2004-07-28 22:53:10 +00:00
} else {
spl_dual_it_require ( intern TSRMLS_CC ) ;
2003-12-08 08:39:18 +00:00
}
2003-12-06 19:21:02 +00:00
intern - > inner . iterator - > funcs - > move_forward ( intern - > inner . iterator TSRMLS_CC ) ;
intern - > current . pos + + ;
2003-12-02 07:18:05 +00:00
}
2004-05-06 09:01:31 +00:00
/* {{{ proto void ParentIterator::rewind()
2004-10-31 18:43:00 +00:00
proto void IteratorIterator : : rewind ( )
2004-05-06 09:01:31 +00:00
Rewind the iterator
*/
2003-12-06 19:21:02 +00:00
SPL_METHOD ( dual_it , rewind )
2003-12-02 07:18:05 +00:00
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
spl_dual_it_rewind ( intern TSRMLS_CC ) ;
2003-12-08 08:39:18 +00:00
spl_dual_it_fetch ( intern , 1 TSRMLS_CC ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-02 07:18:05 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto boolean FilterIterator::valid()
proto boolean ParentIterator : : valid ( )
2004-10-31 18:43:00 +00:00
proto boolean IteratorIterator : : valid ( )
proto boolean NoRewindIterator : : valid ( )
2004-05-06 09:01:31 +00:00
Check whether the current element is valid */
2004-03-08 17:33:31 +00:00
SPL_METHOD ( dual_it , valid )
2003-12-02 07:18:05 +00:00
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
RETURN_BOOL ( intern - > current . data ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-02 07:18:05 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto mixed FilterIterator::key()
proto mixed CachingIterator : : key ( )
proto mixed LimitIterator : : key ( )
proto mixed ParentIterator : : key ( )
2004-10-31 18:43:00 +00:00
proto mixed IteratorIterator : : key ( )
proto mixed NoRewindIterator : : key ( )
2004-11-01 00:26:59 +00:00
proto mixed AppendIterator : : key ( )
2004-05-06 09:01:31 +00:00
Get the current key */
2003-12-06 19:21:02 +00:00
SPL_METHOD ( dual_it , key )
2003-12-02 07:18:05 +00:00
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
if ( intern - > current . data ) {
2004-04-25 11:14:11 +00:00
if ( intern - > current . key_type = = HASH_KEY_IS_STRING ) {
RETURN_STRINGL ( intern - > current . str_key , intern - > current . str_key_len - 1 , 1 ) ;
2003-12-02 07:18:05 +00:00
} else {
RETURN_LONG ( intern - > current . int_key ) ;
}
}
RETURN_NULL ( ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-02 07:18:05 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto mixed FilterIterator::current()
proto mixed CachingIterator : : current ( )
proto mixed LimitIterator : : current ( )
proto mixed ParentIterator : : current ( )
2004-10-31 18:43:00 +00:00
proto mixed IteratorIterator : : current ( )
proto mixed NoRewindIterator : : current ( )
2004-11-01 00:26:59 +00:00
proto mixed AppendIterator : : current ( )
2004-05-06 09:01:31 +00:00
Get the current element value */
2003-12-06 19:21:02 +00:00
SPL_METHOD ( dual_it , current )
2003-12-02 07:18:05 +00:00
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
if ( intern - > current . data ) {
2003-12-10 10:19:43 +00:00
RETVAL_ZVAL ( intern - > current . data , 1 , 0 ) ;
2003-12-02 07:18:05 +00:00
} else {
RETURN_NULL ( ) ;
}
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-02 07:18:05 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto void ParentIterator::next()
2004-10-31 18:43:00 +00:00
proto void IteratorIterator : : next ( )
proto void NoRewindIterator : : next ( )
2004-05-06 09:01:31 +00:00
Move the iterator forward */
2003-12-06 19:21:02 +00:00
SPL_METHOD ( dual_it , next )
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
2003-12-08 08:39:18 +00:00
spl_dual_it_next ( intern , 1 TSRMLS_CC ) ;
spl_dual_it_fetch ( intern , 1 TSRMLS_CC ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-06 19:21:02 +00:00
2003-12-10 10:19:43 +00:00
static INLINE void spl_filter_it_fetch ( zval * zthis , spl_dual_it_object * intern TSRMLS_DC )
2003-12-06 19:21:02 +00:00
{
zval * retval ;
2003-12-10 10:19:43 +00:00
while ( spl_dual_it_fetch ( intern , 1 TSRMLS_CC ) = = SUCCESS ) {
zend_call_method_with_0_params ( & zthis , intern - > std . ce , NULL , " accept " , & retval ) ;
2004-04-27 17:12:11 +00:00
if ( retval ) {
if ( zend_is_true ( retval ) ) {
zval_ptr_dtor ( & retval ) ;
return ;
}
2003-12-06 19:21:02 +00:00
zval_ptr_dtor ( & retval ) ;
}
intern - > inner . iterator - > funcs - > move_forward ( intern - > inner . iterator TSRMLS_CC ) ;
}
spl_dual_it_free ( intern TSRMLS_CC ) ;
}
2003-12-10 10:19:43 +00:00
static INLINE void spl_filter_it_rewind ( zval * zthis , spl_dual_it_object * intern TSRMLS_DC )
{
spl_dual_it_rewind ( intern TSRMLS_CC ) ;
spl_filter_it_fetch ( zthis , intern TSRMLS_CC ) ;
}
static INLINE void spl_filter_it_next ( zval * zthis , spl_dual_it_object * intern TSRMLS_DC )
{
spl_dual_it_next ( intern , 1 TSRMLS_CC ) ;
spl_filter_it_fetch ( zthis , intern TSRMLS_CC ) ;
}
2004-05-06 09:01:31 +00:00
/* {{{ proto void FilterIterator::rewind()
Rewind the iterator */
2003-12-06 19:21:02 +00:00
SPL_METHOD ( FilterIterator , rewind )
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
2003-12-10 10:19:43 +00:00
spl_filter_it_rewind ( getThis ( ) , intern TSRMLS_CC ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-06 19:21:02 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto void FilterIterator::next()
Move the iterator forward */
2003-12-02 07:18:05 +00:00
SPL_METHOD ( FilterIterator , next )
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
2003-12-10 10:19:43 +00:00
spl_filter_it_next ( getThis ( ) , intern TSRMLS_CC ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-02 07:18:05 +00:00
2004-10-30 10:18:10 +00:00
/* {{{ proto ParentIterator::__construct(RecursiveIterator it)
2004-05-06 09:01:31 +00:00
Create a ParentIterator from a RecursiveIterator */
2003-12-02 07:18:05 +00:00
SPL_METHOD ( ParentIterator , __construct )
{
2003-12-08 08:39:18 +00:00
spl_dual_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , spl_ce_RecursiveIterator , DIT_Default ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-02 07:18:05 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto boolean ParentIterator::hasChildren()
Check whether the inner iterator ' s current element has children */
2003-12-02 07:18:05 +00:00
SPL_METHOD ( ParentIterator , hasChildren )
{
spl_dual_it_object * intern ;
zval * retval ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
zend_call_method_with_0_params ( & intern - > inner . zobject , intern - > inner . ce , NULL , " haschildren " , & retval ) ;
RETURN_ZVAL ( retval , 0 , 1 ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-02 07:18:05 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto ParentIterator ParentIterator::getChildren()
Return the inner iterator ' s children contained in a ParentIterator */
2003-12-02 07:18:05 +00:00
SPL_METHOD ( ParentIterator , getChildren )
{
spl_dual_it_object * intern ;
zval * retval ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
zend_call_method_with_0_params ( & intern - > inner . zobject , intern - > inner . ce , NULL , " getchildren " , & retval ) ;
spl_instantiate_arg_ex1 ( spl_ce_ParentIterator , & return_value , 0 , retval TSRMLS_CC ) ;
zval_ptr_dtor ( & retval ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-02 07:18:05 +00:00
2004-02-04 12:45:47 +00:00
/* {{{ spl_dual_it_free_storage */
static INLINE void spl_dual_it_free_storage ( void * _object TSRMLS_DC )
2003-12-02 07:18:05 +00:00
{
spl_dual_it_object * object = ( spl_dual_it_object * ) _object ;
spl_dual_it_free ( object TSRMLS_CC ) ;
2003-12-06 19:21:02 +00:00
if ( object - > inner . iterator ) {
object - > inner . iterator - > funcs - > dtor ( object - > inner . iterator TSRMLS_CC ) ;
}
2003-12-02 07:18:05 +00:00
2003-12-10 10:19:43 +00:00
if ( object - > inner . zobject ) {
zval_ptr_dtor ( & object - > inner . zobject ) ;
}
2004-11-01 00:26:59 +00:00
if ( object - > dit_type = = DIT_AppendIterator ) {
object - > u . append . iterator - > funcs - > dtor ( object - > u . append . iterator TSRMLS_CC ) ;
zval_ptr_dtor ( & object - > u . append . zarrayit ) ;
}
2003-12-10 10:19:43 +00:00
2003-12-02 07:18:05 +00:00
zend_hash_destroy ( object - > std . properties ) ;
FREE_HASHTABLE ( object - > std . properties ) ;
efree ( object ) ;
}
/* }}} */
2003-12-08 08:39:18 +00:00
/* {{{ spl_dual_it_new */
static zend_object_value spl_dual_it_new ( zend_class_entry * class_type TSRMLS_DC )
2003-12-02 07:18:05 +00:00
{
zend_object_value retval ;
spl_dual_it_object * intern ;
zval * tmp ;
intern = emalloc ( sizeof ( spl_dual_it_object ) ) ;
memset ( intern , 0 , sizeof ( spl_dual_it_object ) ) ;
intern - > std . ce = class_type ;
ALLOC_HASHTABLE ( intern - > std . properties ) ;
zend_hash_init ( intern - > std . properties , 0 , NULL , ZVAL_PTR_DTOR , 0 ) ;
zend_hash_copy ( intern - > std . properties , & class_type - > default_properties , ( copy_ctor_func_t ) zval_add_ref , ( void * ) & tmp , sizeof ( zval * ) ) ;
2004-02-04 12:45:47 +00:00
retval . handle = zend_objects_store_put ( intern , NULL , ( zend_objects_free_object_storage_t ) spl_dual_it_free_storage , NULL TSRMLS_CC ) ;
2003-12-08 08:39:18 +00:00
retval . handlers = & spl_handlers_dual_it ;
2003-11-09 14:05:36 +00:00
return retval ;
}
/* }}} */
2003-12-02 07:18:05 +00:00
static
ZEND_BEGIN_ARG_INFO ( arginfo_filter_it___construct , 0 )
2004-03-28 17:04:11 +00:00
ZEND_ARG_OBJ_INFO ( 0 , iterator , Iterator , 0 )
2003-12-02 07:18:05 +00:00
ZEND_END_ARG_INFO ( ) ;
static zend_function_entry spl_funcs_FilterIterator [ ] = {
2004-03-09 17:35:18 +00:00
SPL_ME ( dual_it , __construct , arginfo_filter_it___construct , ZEND_ACC_PUBLIC )
SPL_ME ( FilterIterator , rewind , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , valid , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , key , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , current , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( FilterIterator , next , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , getInnerIterator , NULL , ZEND_ACC_PUBLIC )
2003-12-02 07:18:05 +00:00
SPL_ABSTRACT_ME ( FilterIterator , accept , NULL )
{ NULL , NULL , NULL }
} ;
static
ZEND_BEGIN_ARG_INFO ( arginfo_parent_it___construct , 0 )
2004-03-28 17:04:11 +00:00
ZEND_ARG_OBJ_INFO ( 0 , iterator , Iterator , 0 )
2003-12-02 07:18:05 +00:00
ZEND_END_ARG_INFO ( ) ;
static zend_function_entry spl_funcs_ParentIterator [ ] = {
2004-03-09 17:35:18 +00:00
SPL_ME ( ParentIterator , __construct , arginfo_parent_it___construct , ZEND_ACC_PUBLIC )
SPL_MA ( ParentIterator , accept , ParentIterator , hasChildren , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( ParentIterator , hasChildren , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( ParentIterator , getChildren , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , getInnerIterator , NULL , ZEND_ACC_PUBLIC )
2003-12-02 07:18:05 +00:00
{ NULL , NULL , NULL }
2003-12-06 19:21:02 +00:00
} ;
2004-03-08 18:05:41 +00:00
static INLINE int spl_limit_it_valid ( spl_dual_it_object * intern TSRMLS_DC )
2004-01-28 22:59:03 +00:00
{
/* FAILURE / SUCCESS */
if ( intern - > u . limit . count ! = - 1 & & intern - > current . pos > = intern - > u . limit . offset + intern - > u . limit . count ) {
return FAILURE ;
} else {
2004-03-08 18:05:41 +00:00
return spl_dual_it_valid ( intern TSRMLS_CC ) ;
2004-01-28 22:59:03 +00:00
}
}
2003-12-08 08:39:18 +00:00
static INLINE void spl_limit_it_seek ( spl_dual_it_object * intern , long pos TSRMLS_DC )
2003-12-06 19:21:02 +00:00
{
2004-01-26 23:59:50 +00:00
zval * zpos ;
2003-12-06 19:21:02 +00:00
spl_dual_it_free ( intern TSRMLS_CC ) ;
if ( pos < intern - > u . limit . offset ) {
2004-11-01 17:39:59 +00:00
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 ) ;
2003-12-06 19:21:02 +00:00
return ;
}
if ( pos > intern - > u . limit . offset + intern - > u . limit . count & & intern - > u . limit . count ! = - 1 ) {
2004-11-01 17:39:59 +00:00
zend_throw_exception_ex ( spl_ce_OutOfBoundsException , 0 TSRMLS_CC , " Cannot seek to %ld which is behind offest %ld plus count %ld " , pos , intern - > u . limit . offset , intern - > u . limit . count ) ;
2003-12-06 19:21:02 +00:00
return ;
}
if ( instanceof_function ( intern - > inner . ce , spl_ce_SeekableIterator TSRMLS_CC ) ) {
2004-01-26 23:59:50 +00:00
MAKE_STD_ZVAL ( zpos ) ;
ZVAL_LONG ( zpos , pos ) ;
2004-04-27 15:41:26 +00:00
spl_dual_it_free ( intern TSRMLS_CC ) ;
2004-01-26 23:59:50 +00:00
zend_call_method_with_1_params ( & intern - > inner . zobject , intern - > inner . ce , NULL , " seek " , NULL , zpos ) ;
zval_ptr_dtor ( & zpos ) ;
2003-12-06 19:21:02 +00:00
intern - > current . pos = pos ;
2004-03-08 18:05:41 +00:00
if ( spl_limit_it_valid ( intern TSRMLS_CC ) = = SUCCESS ) {
2004-01-28 22:59:03 +00:00
spl_dual_it_fetch ( intern , 0 TSRMLS_CC ) ;
}
2003-12-06 19:21:02 +00:00
} else {
/* emulate the forward seek, by next() calls */
/* a back ward seek is done by a previous rewind() */
if ( pos < intern - > current . pos ) {
spl_dual_it_rewind ( intern TSRMLS_CC ) ;
}
2004-03-08 18:05:41 +00:00
while ( pos > intern - > current . pos & & spl_dual_it_valid ( intern TSRMLS_CC ) = = SUCCESS ) {
2003-12-08 08:39:18 +00:00
spl_dual_it_next ( intern , 1 TSRMLS_CC ) ;
2003-12-06 19:21:02 +00:00
}
2004-03-08 18:05:41 +00:00
if ( spl_dual_it_valid ( intern TSRMLS_CC ) = = SUCCESS ) {
2003-12-08 08:39:18 +00:00
spl_dual_it_fetch ( intern , 1 TSRMLS_CC ) ;
2003-12-06 19:21:02 +00:00
}
}
}
2004-10-30 10:18:10 +00:00
/* {{{ proto LimitIterator::__construct(Iterator it [, int offset, int count])
2004-05-06 09:01:31 +00:00
Construct a LimitIterator from an Iterator with a given starting offset and optionally a maximum count */
2003-12-06 19:21:02 +00:00
SPL_METHOD ( LimitIterator , __construct )
{
2003-12-08 08:39:18 +00:00
spl_dual_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , zend_ce_iterator , DIT_LimitIterator ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-06 19:21:02 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto void LimitIterator::rewind()
Rewind the iterator to the specified starting offset */
2003-12-06 19:21:02 +00:00
SPL_METHOD ( LimitIterator , rewind )
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
spl_dual_it_rewind ( intern TSRMLS_CC ) ;
spl_limit_it_seek ( intern , intern - > u . limit . offset TSRMLS_CC ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-06 19:21:02 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto boolean LimitIterator::valid()
Check whether the current element is valid */
2004-03-08 17:33:31 +00:00
SPL_METHOD ( LimitIterator , valid )
2003-12-06 19:21:02 +00:00
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
2004-03-08 18:05:41 +00:00
/* RETURN_BOOL(spl_limit_it_valid(intern TSRMLS_CC) == SUCCESS);*/
2003-12-06 19:21:02 +00:00
RETURN_BOOL ( ( intern - > u . limit . count = = - 1 | | intern - > current . pos < intern - > u . limit . offset + intern - > u . limit . count ) & & intern - > current . data ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-06 19:21:02 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto void LimitIterator::next()
Move the iterator forward */
2004-01-28 22:59:03 +00:00
SPL_METHOD ( LimitIterator , next )
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
spl_dual_it_next ( intern , 1 TSRMLS_CC ) ;
if ( intern - > u . limit . count = = - 1 | | intern - > current . pos < intern - > u . limit . offset + intern - > u . limit . count ) {
spl_dual_it_fetch ( intern , 1 TSRMLS_CC ) ;
}
2004-05-06 09:01:31 +00:00
} /* }}} */
2004-01-28 22:59:03 +00:00
2004-10-30 10:18:10 +00:00
/* {{{ proto void LimitIterator::seek(int position)
2004-05-06 09:01:31 +00:00
Seek to the given position */
2003-12-06 19:21:02 +00:00
SPL_METHOD ( LimitIterator , seek )
{
spl_dual_it_object * intern ;
long pos ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " l " , & pos ) = = FAILURE ) {
return ;
}
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
spl_limit_it_seek ( intern , pos TSRMLS_CC ) ;
RETURN_LONG ( intern - > current . pos ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-06 19:21:02 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto int LimitIterator::getPosition()
Return the current position */
2003-12-06 19:21:02 +00:00
SPL_METHOD ( LimitIterator , getPosition )
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
RETURN_LONG ( intern - > current . pos ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-06 19:21:02 +00:00
static
ZEND_BEGIN_ARG_INFO ( arginfo_seekable_it_seek , 0 )
ZEND_ARG_INFO ( 0 , position )
ZEND_END_ARG_INFO ( ) ;
static zend_function_entry spl_funcs_SeekableIterator [ ] = {
SPL_ABSTRACT_ME ( SeekableIterator , seek , arginfo_seekable_it_seek )
{ NULL , NULL , NULL }
} ;
static
ZEND_BEGIN_ARG_INFO ( arginfo_limit_it___construct , 0 )
2004-03-28 17:04:11 +00:00
ZEND_ARG_OBJ_INFO ( 0 , iterator , Iterator , 0 )
2003-12-06 19:21:02 +00:00
ZEND_ARG_INFO ( 0 , offset )
ZEND_ARG_INFO ( 0 , count )
2003-12-02 07:18:05 +00:00
ZEND_END_ARG_INFO ( ) ;
2003-12-06 19:21:02 +00:00
static
ZEND_BEGIN_ARG_INFO ( arginfo_limit_it_seek , 0 )
ZEND_ARG_INFO ( 0 , position )
ZEND_END_ARG_INFO ( ) ;
static zend_function_entry spl_funcs_LimitIterator [ ] = {
2004-03-09 17:35:18 +00:00
SPL_ME ( LimitIterator , __construct , arginfo_limit_it___construct , ZEND_ACC_PUBLIC )
SPL_ME ( LimitIterator , rewind , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( LimitIterator , valid , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , key , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , current , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( LimitIterator , next , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( LimitIterator , seek , arginfo_limit_it_seek , ZEND_ACC_PUBLIC )
SPL_ME ( LimitIterator , getPosition , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , getInnerIterator , NULL , ZEND_ACC_PUBLIC )
2003-12-06 19:21:02 +00:00
{ NULL , NULL , NULL }
} ;
2004-03-08 18:05:41 +00:00
static INLINE int spl_caching_it_valid ( spl_dual_it_object * intern TSRMLS_DC )
2003-12-08 08:39:18 +00:00
{
2004-03-08 18:05:41 +00:00
return intern - > u . caching . flags & CIT_VALID ? SUCCESS : FAILURE ;
2003-12-08 08:39:18 +00:00
}
static INLINE int spl_caching_it_has_next ( spl_dual_it_object * intern TSRMLS_DC )
{
2004-03-08 18:05:41 +00:00
return spl_dual_it_valid ( intern TSRMLS_CC ) ;
2003-12-08 08:39:18 +00:00
}
static INLINE void spl_caching_it_next ( spl_dual_it_object * intern TSRMLS_DC )
{
2003-12-10 10:19:43 +00:00
if ( spl_dual_it_fetch ( intern , 1 TSRMLS_CC ) = = SUCCESS ) {
2004-03-08 18:05:41 +00:00
intern - > u . caching . flags | = CIT_VALID ;
2003-12-08 08:39:18 +00:00
if ( intern - > dit_type = = DIT_CachingRecursiveIterator ) {
zval * retval , * zchildren , zflags ;
zend_call_method_with_0_params ( & intern - > inner . zobject , intern - > inner . ce , NULL , " haschildren " , & retval ) ;
if ( zend_is_true ( retval ) ) {
zend_call_method_with_0_params ( & intern - > inner . zobject , intern - > inner . ce , NULL , " getchildren " , & zchildren ) ;
if ( EG ( exception ) & & intern - > u . caching . flags & CIT_CATCH_GET_CHILD ) {
zval_ptr_dtor ( & EG ( exception ) ) ;
EG ( exception ) = NULL ;
if ( zchildren ) {
zval_ptr_dtor ( & zchildren ) ;
}
} else {
INIT_PZVAL ( & zflags ) ;
ZVAL_LONG ( & zflags , intern - > u . caching . flags & CIT_PUBLIC ) ;
spl_instantiate_arg_ex2 ( spl_ce_CachingRecursiveIterator , & intern - > u . caching . zchildren , 1 , zchildren , & zflags TSRMLS_CC ) ;
zval_ptr_dtor ( & zchildren ) ;
}
}
zval_ptr_dtor ( & retval ) ;
}
if ( intern - > u . caching . flags & CIT_CALL_TOSTRING ) {
2004-04-08 22:46:43 +00:00
if ( Z_TYPE_P ( intern - > current . data ) = = IS_OBJECT ) {
zval expr_copy ;
if ( intern - > current . data - > value . obj . handlers - > cast_object & &
intern - > current . data - > value . obj . handlers - > cast_object ( intern - > current . data , & expr_copy , IS_STRING , 0 TSRMLS_CC ) = = SUCCESS )
{
ALLOC_ZVAL ( intern - > u . caching . zstr ) ;
* intern - > u . caching . zstr = expr_copy ;
INIT_PZVAL ( intern - > u . caching . zstr ) ;
zval_copy_ctor ( intern - > u . caching . zstr ) ;
zval_dtor ( & expr_copy ) ;
} else {
zend_class_entry * ce_data = spl_get_class_entry ( intern - > current . data TSRMLS_CC ) ;
if ( ce_data & & zend_hash_exists ( & ce_data - > function_table , " __tostring " , sizeof ( " __tostring " ) ) ) {
zend_call_method_with_0_params ( & intern - > current . data , ce_data , NULL , " __tostring " , & intern - > u . caching . zstr ) ;
} else {
ALLOC_ZVAL ( intern - > u . caching . zstr ) ;
* intern - > u . caching . zstr = * intern - > current . data ;
zval_copy_ctor ( intern - > u . caching . zstr ) ;
INIT_PZVAL ( intern - > u . caching . zstr ) ;
convert_to_string ( intern - > u . caching . zstr ) ;
}
}
2003-12-08 08:39:18 +00:00
} else {
2004-04-08 22:46:43 +00:00
/* This version requires zend_make_printable_zval() being able to
* call __toString ( ) .
*/
int use_copy ;
zval expr_copy ;
2004-03-17 19:58:32 +00:00
ALLOC_ZVAL ( intern - > u . caching . zstr ) ;
2004-04-08 22:46:43 +00:00
* intern - > u . caching . zstr = * intern - > current . data ;
zend_make_printable_zval ( intern - > u . caching . zstr , & expr_copy , & use_copy ) ;
if ( use_copy ) {
* intern - > u . caching . zstr = expr_copy ;
INIT_PZVAL ( intern - > u . caching . zstr ) ;
zval_copy_ctor ( intern - > u . caching . zstr ) ;
zval_dtor ( & expr_copy ) ;
2004-03-17 19:58:32 +00:00
} else {
zval_copy_ctor ( intern - > u . caching . zstr ) ;
}
}
2003-12-08 08:39:18 +00:00
}
spl_dual_it_next ( intern , 0 TSRMLS_CC ) ;
} else {
2004-03-08 18:05:41 +00:00
intern - > u . caching . flags & = ~ CIT_VALID ;
2003-12-08 08:39:18 +00:00
}
}
static INLINE void spl_caching_it_rewind ( spl_dual_it_object * intern TSRMLS_DC )
{
spl_dual_it_rewind ( intern TSRMLS_CC ) ;
spl_caching_it_next ( intern TSRMLS_CC ) ;
}
2004-10-30 10:18:10 +00:00
/* {{{ proto CachingIterator::__construct(Iterator it [, flags = CIT_CALL_TOSTRING])
2004-05-06 09:01:31 +00:00
Construct a CachingIterator from an Iterator */
2003-12-08 08:39:18 +00:00
SPL_METHOD ( CachingIterator , __construct )
{
spl_dual_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , zend_ce_iterator , DIT_CachingIterator ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-08 08:39:18 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto void CachingIterator::rewind()
Rewind the iterator */
2003-12-08 08:39:18 +00:00
SPL_METHOD ( CachingIterator , rewind )
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
spl_caching_it_rewind ( intern TSRMLS_CC ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-08 08:39:18 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto boolean CachingIterator::valid()
Check whether the current element is valid */
2004-03-08 17:33:31 +00:00
SPL_METHOD ( CachingIterator , valid )
2003-12-08 08:39:18 +00:00
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
2004-03-08 18:05:41 +00:00
RETURN_BOOL ( spl_caching_it_valid ( intern TSRMLS_CC ) = = SUCCESS ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-08 08:39:18 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto void CachingIterator::next()
Move the iterator forward */
2003-12-08 08:39:18 +00:00
SPL_METHOD ( CachingIterator , next )
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
spl_caching_it_next ( intern TSRMLS_CC ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-08 08:39:18 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto boolean CachingIterator::hasNext()
2004-12-29 13:53:40 +00:00
Check whether the inner iterator has a valid next element */
2003-12-08 08:39:18 +00:00
SPL_METHOD ( CachingIterator , hasNext )
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
RETURN_BOOL ( spl_caching_it_has_next ( intern TSRMLS_CC ) = = SUCCESS ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-08 08:39:18 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto string CachingIterator::__toString()
2004-12-29 16:11:42 +00:00
Return the string representation of the current element */
2003-12-08 08:39:18 +00:00
SPL_METHOD ( CachingIterator , __toString )
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
if ( ! ( intern - > u . caching . flags & CIT_CALL_TOSTRING ) ) {
2004-11-01 17:39:59 +00:00
zend_throw_exception_ex ( spl_ce_BadMethodCallException , 0 TSRMLS_CC , " %s does not fetch string value (see CachingIterator::__construct) " , Z_OBJCE_P ( getThis ( ) ) - > name ) ;
2003-12-08 08:39:18 +00:00
}
if ( intern - > u . caching . zstr ) {
RETURN_STRINGL ( Z_STRVAL_P ( intern - > u . caching . zstr ) , Z_STRLEN_P ( intern - > u . caching . zstr ) , 1 ) ;
} else {
RETURN_NULL ( ) ;
}
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-08 08:39:18 +00:00
static
ZEND_BEGIN_ARG_INFO ( arginfo_caching_it___construct , 0 )
2004-03-28 17:04:11 +00:00
ZEND_ARG_OBJ_INFO ( 0 , iterator , Iterator , 0 )
2004-10-31 18:43:00 +00:00
ZEND_ARG_INFO ( 0 , flags )
2003-12-08 08:39:18 +00:00
ZEND_END_ARG_INFO ( ) ;
static zend_function_entry spl_funcs_CachingIterator [ ] = {
2004-03-09 17:35:18 +00:00
SPL_ME ( CachingIterator , __construct , arginfo_caching_it___construct , ZEND_ACC_PUBLIC )
SPL_ME ( CachingIterator , rewind , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( CachingIterator , valid , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , key , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , current , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( CachingIterator , next , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( CachingIterator , hasNext , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( CachingIterator , __toString , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , getInnerIterator , NULL , ZEND_ACC_PUBLIC )
2003-12-08 08:39:18 +00:00
{ NULL , NULL , NULL }
} ;
2004-10-30 10:18:10 +00:00
/* {{{ proto CachingRecursiveIterator::__construct(RecursiveIterator it [, flags = CIT_CALL_TOSTRING])
2004-05-06 09:01:31 +00:00
Create an iterator from a RecursiveIterator */
2003-12-08 08:39:18 +00:00
SPL_METHOD ( CachingRecursiveIterator , __construct )
{
spl_dual_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , spl_ce_RecursiveIterator , DIT_CachingRecursiveIterator ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-08 08:39:18 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto bolean CachingRecursiveIterator::hasChildren()
2004-12-29 13:53:40 +00:00
Check whether the current element of the inner iterator has children */
2003-12-08 08:39:18 +00:00
SPL_METHOD ( CachingRecursiveIterator , hasChildren )
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
RETURN_BOOL ( intern - > u . caching . zchildren ) ;
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-08 08:39:18 +00:00
2004-05-06 09:01:31 +00:00
/* {{{ proto CachingRecursiveIterator CachingRecursiveIterator::getChildren()
2004-12-29 16:11:42 +00:00
Return the inner iterator ' s children as a CachingRecursiveIterator */
2003-12-08 08:39:18 +00:00
SPL_METHOD ( CachingRecursiveIterator , getChildren )
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
if ( intern - > u . caching . zchildren ) {
RETURN_ZVAL ( intern - > u . caching . zchildren , 1 , 0 ) ;
} else {
RETURN_NULL ( ) ;
}
2004-05-06 09:01:31 +00:00
} /* }}} */
2003-12-08 08:39:18 +00:00
static
2004-02-25 14:58:47 +00:00
ZEND_BEGIN_ARG_INFO_EX ( arginfo_caching_rec_it___construct , 0 , ZEND_RETURN_REFERENCE_AGNOSTIC , 2 )
2004-03-28 17:04:11 +00:00
ZEND_ARG_OBJ_INFO ( 0 , iterator , Iterator , 0 )
2004-10-31 18:43:00 +00:00
ZEND_ARG_INFO ( 0 , flags )
2003-12-08 08:39:18 +00:00
ZEND_END_ARG_INFO ( ) ;
static zend_function_entry spl_funcs_CachingRecursiveIterator [ ] = {
SPL_ME ( CachingRecursiveIterator , __construct , arginfo_caching_rec_it___construct , ZEND_ACC_PUBLIC )
SPL_ME ( CachingRecursiveIterator , hasChildren , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( CachingRecursiveIterator , getChildren , NULL , ZEND_ACC_PUBLIC )
{ NULL , NULL , NULL }
} ;
2004-10-31 18:43:00 +00:00
/* {{{ proto IteratorIterator::__construct(Traversable it)
Create an iterator from anything that is traversable */
SPL_METHOD ( IteratorIterator , __construct )
{
spl_dual_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , zend_ce_traversable , DIT_IteratorIterator ) ;
} /* }}} */
static
ZEND_BEGIN_ARG_INFO ( arginfo_iterator_it___construct , 0 )
ZEND_ARG_OBJ_INFO ( 0 , iterator , Traversable , 0 )
ZEND_END_ARG_INFO ( ) ;
static zend_function_entry spl_funcs_IteratorIterator [ ] = {
SPL_ME ( IteratorIterator , __construct , arginfo_iterator_it___construct , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , rewind , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , valid , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , key , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , current , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , next , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , getInnerIterator , NULL , ZEND_ACC_PUBLIC )
{ NULL , NULL , NULL }
} ;
/* {{{ proto NoRewindIterator::__construct(Iterator it)
Create an iterator from another iterator */
SPL_METHOD ( NoRewindIterator , __construct )
{
spl_dual_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , zend_ce_iterator , DIT_NoRewindIterator ) ;
} /* }}} */
2004-11-01 00:26:59 +00:00
/* {{{ proto void NoRewindIterator::rewind()
Prevent a call to inner iterators rewind ( ) */
2004-10-31 18:43:00 +00:00
SPL_METHOD ( NoRewindIterator , rewind )
2004-11-01 00:26:59 +00:00
{
/* nothing to do */
} /* }}} */
/* {{{ proto void NoRewindIterator::valid()
Return inner iterators valid ( ) */
SPL_METHOD ( NoRewindIterator , valid )
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
RETURN_BOOL ( intern - > inner . iterator - > funcs - > valid ( intern - > inner . iterator TSRMLS_CC ) = = SUCCESS ) ;
} /* }}} */
/* {{{ proto mixed NoRewindIterator::key()
Return inner iterators key ( ) */
SPL_METHOD ( NoRewindIterator , key )
2004-10-31 18:43:00 +00:00
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
2004-11-01 00:26:59 +00:00
if ( intern - > inner . iterator - > funcs - > get_current_key ) {
char * str_key ;
uint str_key_len ;
ulong int_key ;
if ( intern - > inner . iterator - > funcs - > get_current_key ( intern - > inner . iterator , & str_key , & str_key_len , & int_key TSRMLS_CC ) = = HASH_KEY_IS_LONG ) {
RETURN_LONG ( int_key ) ;
} else {
RETURN_STRINGL ( str_key , str_key_len - 1 , 0 ) ;
}
} else {
RETURN_NULL ( ) ;
}
} /* }}} */
/* {{{ proto mixed NoRewindIterator::current()
Return inner iterators current ( ) */
SPL_METHOD ( NoRewindIterator , current )
{
spl_dual_it_object * intern ;
zval * * data ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
intern - > inner . iterator - > funcs - > get_current_data ( intern - > inner . iterator , & data TSRMLS_CC ) ;
RETURN_ZVAL ( * data , 1 , 0 ) ;
} /* }}} */
/* {{{ proto void NoRewindIterator::next()
Return inner iterators next ( ) */
SPL_METHOD ( NoRewindIterator , next )
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
intern - > inner . iterator - > funcs - > move_forward ( intern - > inner . iterator TSRMLS_CC ) ;
2004-10-31 18:43:00 +00:00
} /* }}} */
static
ZEND_BEGIN_ARG_INFO ( arginfo_norewind_it___construct , 0 )
ZEND_ARG_OBJ_INFO ( 0 , iterator , Iterator , 0 )
ZEND_END_ARG_INFO ( ) ;
static zend_function_entry spl_funcs_NoRewindIterator [ ] = {
SPL_ME ( NoRewindIterator , __construct , arginfo_norewind_it___construct , ZEND_ACC_PUBLIC )
SPL_ME ( NoRewindIterator , rewind , NULL , ZEND_ACC_PUBLIC )
2004-11-01 00:26:59 +00:00
SPL_ME ( NoRewindIterator , valid , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( NoRewindIterator , key , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( NoRewindIterator , current , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( NoRewindIterator , next , NULL , ZEND_ACC_PUBLIC )
2004-10-31 18:43:00 +00:00
SPL_ME ( dual_it , getInnerIterator , NULL , ZEND_ACC_PUBLIC )
{ NULL , NULL , NULL }
} ;
2004-10-31 19:49:18 +00:00
/* {{{ proto InfiniteIterator::__construct(Iterator it)
Create an iterator from another iterator */
SPL_METHOD ( InfiniteIterator , __construct )
{
spl_dual_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , zend_ce_iterator , DIT_InfiniteIterator ) ;
} /* }}} */
/* {{{ proto InfiniteIterator::next()
Prevent a call to inner iterators rewind ( ) ( internally the current data will be fetched if valid ( ) ) */
SPL_METHOD ( InfiniteIterator , next )
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
spl_dual_it_next ( intern , 1 TSRMLS_CC ) ;
if ( spl_dual_it_valid ( intern TSRMLS_CC ) = = SUCCESS ) {
spl_dual_it_fetch ( intern , 0 TSRMLS_CC ) ;
} else {
spl_dual_it_rewind ( intern TSRMLS_CC ) ;
if ( spl_dual_it_valid ( intern TSRMLS_CC ) = = SUCCESS ) {
spl_dual_it_fetch ( intern , 0 TSRMLS_CC ) ;
}
}
} /* }}} */
static zend_function_entry spl_funcs_InfiniteIterator [ ] = {
SPL_ME ( InfiniteIterator , __construct , arginfo_norewind_it___construct , ZEND_ACC_PUBLIC )
SPL_ME ( InfiniteIterator , next , NULL , ZEND_ACC_PUBLIC )
2004-11-03 01:16:10 +00:00
{ NULL , NULL , NULL }
2004-10-31 19:49:18 +00:00
} ;
2004-10-31 18:43:00 +00:00
2004-10-31 20:59:39 +00:00
/* {{{ proto EmptyIterator::rewind()
Does nothing */
SPL_METHOD ( EmptyIterator , rewind )
{
} /* }}} */
/* {{{ proto EmptyIterator::valid()
Return false */
SPL_METHOD ( EmptyIterator , valid )
{
RETURN_FALSE ;
} /* }}} */
/* {{{ proto EmptyIterator::key()
Throws exception */
SPL_METHOD ( EmptyIterator , key )
{
2004-11-01 17:39:59 +00:00
zend_throw_exception ( spl_ce_BadMethodCallException , " Accessing the key of an EmptyIterator " , 0 TSRMLS_CC ) ;
2004-10-31 20:59:39 +00:00
} /* }}} */
/* {{{ proto EmptyIterator::current()
Throws exception */
SPL_METHOD ( EmptyIterator , current )
{
2004-11-01 17:39:59 +00:00
zend_throw_exception ( spl_ce_BadMethodCallException , " Accessing the value of an EmptyIterator " , 0 TSRMLS_CC ) ;
2004-10-31 20:59:39 +00:00
} /* }}} */
/* {{{ proto EmptyIterator::next()
Does nothing */
SPL_METHOD ( EmptyIterator , next )
{
} /* }}} */
static zend_function_entry spl_funcs_EmptyIterator [ ] = {
SPL_ME ( EmptyIterator , rewind , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( EmptyIterator , valid , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( EmptyIterator , key , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( EmptyIterator , current , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( EmptyIterator , next , NULL , ZEND_ACC_PUBLIC )
2004-11-03 01:20:16 +00:00
{ NULL , NULL , NULL }
2004-10-31 20:59:39 +00:00
} ;
2004-11-01 00:26:59 +00:00
int spl_append_it_next_iterator ( spl_dual_it_object * intern TSRMLS_DC ) /* { { { */
{
spl_dual_it_free ( intern TSRMLS_CC ) ;
if ( intern - > inner . zobject ) {
zval_ptr_dtor ( & intern - > inner . zobject ) ;
intern - > inner . zobject = NULL ;
intern - > inner . ce = NULL ;
intern - > inner . object = NULL ;
intern - > inner . iterator = NULL ;
}
if ( intern - > u . append . iterator - > funcs - > valid ( intern - > u . append . iterator TSRMLS_CC ) = = SUCCESS ) {
zval * * it ;
intern - > u . append . iterator - > funcs - > get_current_data ( intern - > u . append . iterator , & it TSRMLS_CC ) ;
( * it ) - > refcount + + ;
intern - > inner . zobject = * it ;
intern - > inner . ce = Z_OBJCE_PP ( it ) ;
intern - > inner . object = zend_object_store_get_object ( * it TSRMLS_CC ) ;
intern - > inner . iterator = intern - > inner . ce - > get_iterator ( intern - > inner . ce , * it TSRMLS_CC ) ;
spl_dual_it_rewind ( intern TSRMLS_CC ) ;
intern - > u . append . iterator - > funcs - > move_forward ( intern - > u . append . iterator TSRMLS_CC ) ;
return SUCCESS ;
} else {
return FAILURE ;
}
} /* }}} */
void spl_append_it_fetch ( spl_dual_it_object * intern TSRMLS_DC ) /* { { { */
{
while ( spl_dual_it_valid ( intern TSRMLS_CC ) ! = SUCCESS ) {
if ( spl_append_it_next_iterator ( intern TSRMLS_CC ) ! = SUCCESS ) {
return ;
}
}
spl_dual_it_fetch ( intern , 0 TSRMLS_CC ) ;
} /* }}} */
void spl_append_it_next ( spl_dual_it_object * intern TSRMLS_DC ) /* { { { */
{
if ( spl_dual_it_valid ( intern TSRMLS_CC ) = = SUCCESS ) {
spl_dual_it_next ( intern , 1 TSRMLS_CC ) ;
}
spl_append_it_fetch ( intern TSRMLS_CC ) ;
} /* }}} */
/* {{{ proto AppendIterator::__construct()
Create an AppendIterator */
SPL_METHOD ( AppendIterator , __construct )
{
spl_dual_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , zend_ce_iterator , DIT_AppendIterator ) ;
} /* }}} */
/* {{{ proto void AppendIterator::append(Iterator it)
Append an iterator */
SPL_METHOD ( AppendIterator , append )
{
spl_dual_it_object * intern ;
zval * it ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " o " , & it , zend_ce_iterator ) = = FAILURE ) {
return ;
}
spl_array_iterator_append ( intern - > u . append . zarrayit , it TSRMLS_CC ) ;
if ( ! intern - > inner . iterator | | spl_dual_it_valid ( intern TSRMLS_CC ) ! = SUCCESS ) {
if ( intern - > u . append . iterator - > funcs - > valid ( intern - > u . append . iterator TSRMLS_CC ) ! = SUCCESS ) {
intern - > u . append . iterator - > funcs - > rewind ( intern - > u . append . iterator TSRMLS_CC ) ;
}
do {
spl_append_it_next_iterator ( intern TSRMLS_CC ) ;
} while ( intern - > inner . zobject ! = it ) ;
spl_append_it_fetch ( intern TSRMLS_CC ) ;
}
} /* }}} */
/* {{{ proto void AppendIterator::rewind()
Rewind to the first iterator and rewind the first iterator , too */
SPL_METHOD ( AppendIterator , rewind )
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
intern - > u . append . iterator - > funcs - > rewind ( intern - > u . append . iterator TSRMLS_CC ) ;
if ( spl_append_it_next_iterator ( intern TSRMLS_CC ) = = SUCCESS ) {
spl_append_it_fetch ( intern TSRMLS_CC ) ;
}
} /* }}} */
/* {{{ proto boolean AppendIterator::valid()
Check if the current state is valid */
SPL_METHOD ( AppendIterator , valid )
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
RETURN_BOOL ( intern - > current . data ) ;
} /* }}} */
/* {{{ proto AppendIterator::next()
Forward to next element */
SPL_METHOD ( AppendIterator , next )
{
spl_dual_it_object * intern ;
intern = ( spl_dual_it_object * ) zend_object_store_get_object ( getThis ( ) TSRMLS_CC ) ;
spl_append_it_next ( intern TSRMLS_CC ) ;
} /* }}} */
static
ZEND_BEGIN_ARG_INFO ( arginfo_append_it_append , 0 )
ZEND_ARG_OBJ_INFO ( 0 , iterator , Iterator , 0 )
ZEND_END_ARG_INFO ( ) ;
static zend_function_entry spl_funcs_AppendIterator [ ] = {
SPL_ME ( AppendIterator , __construct , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( AppendIterator , append , arginfo_append_it_append , ZEND_ACC_PUBLIC )
SPL_ME ( AppendIterator , rewind , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( AppendIterator , valid , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , key , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , current , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( AppendIterator , next , NULL , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , getInnerIterator , NULL , ZEND_ACC_PUBLIC )
2004-11-03 01:20:16 +00:00
{ NULL , NULL , NULL }
2004-11-01 00:26:59 +00:00
} ;
2004-10-30 10:18:10 +00:00
/* {{{ array iterator_to_array(IteratorAggregate it)
2004-10-07 23:08:19 +00:00
Copy the iterator into an array */
PHP_FUNCTION ( iterator_to_array )
{
zval * obj , * * data ;
zend_object_iterator * iter ;
char * str_key ;
uint str_key_len ;
ulong int_key ;
int key_type ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " O " , & obj , zend_ce_aggregate ) = = FAILURE ) {
RETURN_FALSE ;
}
array_init ( return_value ) ;
iter = Z_OBJCE_P ( obj ) - > get_iterator ( Z_OBJCE_P ( obj ) , obj TSRMLS_CC ) ;
iter - > funcs - > rewind ( iter TSRMLS_CC ) ;
while ( iter - > funcs - > valid ( iter TSRMLS_CC ) = = SUCCESS ) {
key_type = iter - > funcs - > get_current_key ( iter , & str_key , & str_key_len , & int_key TSRMLS_CC ) ;
iter - > funcs - > get_current_data ( iter , & data TSRMLS_CC ) ;
( * data ) - > refcount + + ;
switch ( key_type ) {
case HASH_KEY_IS_STRING :
add_assoc_zval_ex ( return_value , str_key , str_key_len , * data ) ;
efree ( str_key ) ;
break ;
case HASH_KEY_IS_LONG :
add_index_zval ( return_value , int_key , * data ) ;
break ;
}
iter - > funcs - > move_forward ( iter TSRMLS_CC ) ;
}
iter - > funcs - > dtor ( iter TSRMLS_CC ) ;
}
/* }}} */
2004-10-30 10:18:10 +00:00
/* {{{ int iterator_count(IteratorAggregate it)
2004-10-07 23:08:19 +00:00
Count the elements in an iterator */
PHP_FUNCTION ( iterator_count )
{
zval * obj ;
zend_object_iterator * iter ;
long count = 0 ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " O " , & obj , zend_ce_aggregate ) = = FAILURE ) {
RETURN_FALSE ;
}
iter = Z_OBJCE_P ( obj ) - > get_iterator ( Z_OBJCE_P ( obj ) , obj TSRMLS_CC ) ;
iter - > funcs - > rewind ( iter TSRMLS_CC ) ;
while ( iter - > funcs - > valid ( iter TSRMLS_CC ) = = SUCCESS ) {
count + + ;
iter - > funcs - > move_forward ( iter TSRMLS_CC ) ;
}
iter - > funcs - > dtor ( iter TSRMLS_CC ) ;
RETURN_LONG ( count ) ;
}
/* }}} */
2004-10-29 20:12:57 +00:00
static zend_function_entry spl_funcs_OuterIterator [ ] = {
SPL_ABSTRACT_ME ( OuterIterator , getInnerIterator , NULL )
{ NULL , NULL , NULL }
} ;
2003-11-09 14:05:36 +00:00
/* {{{ PHP_MINIT_FUNCTION(spl_iterators)
*/
PHP_MINIT_FUNCTION ( spl_iterators )
{
REGISTER_SPL_INTERFACE ( RecursiveIterator ) ;
2003-12-08 08:39:18 +00:00
REGISTER_SPL_ITERATOR ( RecursiveIterator ) ;
REGISTER_SPL_STD_CLASS_EX ( RecursiveIteratorIterator , spl_RecursiveIteratorIterator_new , spl_funcs_RecursiveIteratorIterator ) ;
REGISTER_SPL_ITERATOR ( RecursiveIteratorIterator ) ;
2003-11-09 14:05:36 +00:00
2003-12-08 08:39:18 +00:00
memcpy ( & spl_handlers_rec_it_it , zend_get_std_object_handlers ( ) , sizeof ( zend_object_handlers ) ) ;
2004-10-31 19:05:19 +00:00
spl_handlers_rec_it_it . get_method = spl_recursive_it_get_method ;
2003-12-08 08:39:18 +00:00
spl_handlers_rec_it_it . clone_obj = NULL ;
2003-12-02 07:18:05 +00:00
2003-12-08 08:39:18 +00:00
memcpy ( & spl_handlers_dual_it , zend_get_std_object_handlers ( ) , sizeof ( zend_object_handlers ) ) ;
spl_handlers_dual_it . get_method = spl_dual_it_get_method ;
/*spl_handlers_dual_it.call_method = spl_dual_it_call_method;*/
spl_handlers_dual_it . clone_obj = NULL ;
2003-11-09 14:05:36 +00:00
spl_ce_RecursiveIteratorIterator - > get_iterator = spl_recursive_it_get_iterator ;
spl_ce_RecursiveIteratorIterator - > iterator_funcs . funcs = & spl_recursive_it_iterator_funcs ;
2003-11-11 00:25:26 +00:00
REGISTER_LONG_CONSTANT ( " RIT_LEAVES_ONLY " , ( long ) RIT_LEAVES_ONLY , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " RIT_SELF_FIRST " , ( long ) RIT_SELF_FIRST , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " RIT_CHILD_FIRST " , ( long ) RIT_CHILD_FIRST , CONST_CS | CONST_PERSISTENT ) ;
2003-12-02 07:18:05 +00:00
2003-12-08 08:39:18 +00:00
REGISTER_SPL_STD_CLASS_EX ( FilterIterator , spl_dual_it_new , spl_funcs_FilterIterator ) ;
REGISTER_SPL_ITERATOR ( FilterIterator ) ;
2004-03-09 16:38:37 +00:00
spl_ce_FilterIterator - > ce_flags | = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS ;
2003-12-02 07:18:05 +00:00
2003-12-08 08:39:18 +00:00
REGISTER_SPL_SUB_CLASS_EX ( ParentIterator , FilterIterator , spl_dual_it_new , spl_funcs_ParentIterator ) ;
REGISTER_SPL_IMPLEMENTS ( ParentIterator , RecursiveIterator ) ;
2003-12-02 07:18:05 +00:00
2003-12-06 19:21:02 +00:00
REGISTER_SPL_INTERFACE ( SeekableIterator ) ;
2003-12-08 08:39:18 +00:00
REGISTER_SPL_ITERATOR ( SeekableIterator ) ;
REGISTER_SPL_STD_CLASS_EX ( LimitIterator , spl_dual_it_new , spl_funcs_LimitIterator ) ;
REGISTER_SPL_ITERATOR ( LimitIterator ) ;
REGISTER_SPL_STD_CLASS_EX ( CachingIterator , spl_dual_it_new , spl_funcs_CachingIterator ) ;
REGISTER_SPL_ITERATOR ( CachingIterator ) ;
2003-12-06 19:21:02 +00:00
2003-12-08 08:39:18 +00:00
REGISTER_LONG_CONSTANT ( " CIT_CALL_TOSTRING " , ( long ) CIT_CALL_TOSTRING , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " CIT_CATCH_GET_CHILD " , ( long ) CIT_CATCH_GET_CHILD , CONST_CS | CONST_PERSISTENT ) ;
2003-12-06 19:21:02 +00:00
2003-12-08 08:39:18 +00:00
REGISTER_SPL_SUB_CLASS_EX ( CachingRecursiveIterator , CachingIterator , spl_dual_it_new , spl_funcs_CachingRecursiveIterator ) ;
REGISTER_SPL_IMPLEMENTS ( CachingRecursiveIterator , RecursiveIterator ) ;
2004-10-29 20:12:57 +00:00
2004-10-31 18:43:00 +00:00
REGISTER_SPL_STD_CLASS_EX ( IteratorIterator , spl_dual_it_new , spl_funcs_IteratorIterator ) ;
REGISTER_SPL_ITERATOR ( IteratorIterator ) ;
REGISTER_SPL_STD_CLASS_EX ( NoRewindIterator , spl_dual_it_new , spl_funcs_NoRewindIterator ) ;
REGISTER_SPL_ITERATOR ( NoRewindIterator ) ;
2004-10-29 20:12:57 +00:00
REGISTER_SPL_INTERFACE ( OuterIterator ) ;
REGISTER_SPL_ITERATOR ( OuterIterator ) ;
2004-11-01 00:26:59 +00:00
REGISTER_SPL_STD_CLASS_EX ( AppendIterator , spl_dual_it_new , spl_funcs_AppendIterator ) ;
2004-10-29 20:12:57 +00:00
REGISTER_SPL_IMPLEMENTS ( RecursiveIteratorIterator , OuterIterator ) ;
REGISTER_SPL_IMPLEMENTS ( CachingIterator , OuterIterator ) ;
REGISTER_SPL_IMPLEMENTS ( FilterIterator , OuterIterator ) ;
REGISTER_SPL_IMPLEMENTS ( LimitIterator , OuterIterator ) ;
2004-10-31 18:43:00 +00:00
REGISTER_SPL_IMPLEMENTS ( IteratorIterator , OuterIterator ) ;
REGISTER_SPL_IMPLEMENTS ( NoRewindIterator , OuterIterator ) ;
2004-11-01 00:26:59 +00:00
REGISTER_SPL_IMPLEMENTS ( AppendIterator , OuterIterator ) ;
2004-10-29 20:12:57 +00:00
2004-10-31 19:49:18 +00:00
REGISTER_SPL_SUB_CLASS_EX ( InfiniteIterator , IteratorIterator , spl_dual_it_new , spl_funcs_InfiniteIterator ) ;
2004-10-31 20:59:39 +00:00
REGISTER_SPL_STD_CLASS_EX ( EmptyIterator , NULL , spl_funcs_EmptyIterator ) ;
REGISTER_SPL_ITERATOR ( EmptyIterator ) ;
2004-10-31 19:49:18 +00:00
2003-11-09 14:05:36 +00:00
return SUCCESS ;
}
/* }}} */
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* End :
* vim600 : fdm = marker
* vim : noet sw = 4 ts = 4
*/