2003-11-09 22:05:36 +08:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2014-09-20 00:33:14 +08:00
| PHP Version 7 |
2003-11-09 22:05:36 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2017-01-02 23:30:12 +08:00
| Copyright ( c ) 1997 - 2017 The PHP Group |
2003-11-09 22:05:36 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2006-01-01 20:51:34 +08:00
| This source file is subject to version 3.01 of the PHP license , |
2003-11-09 22:05:36 +08:00
| that is bundled with this package in the file LICENSE , and is |
| available through the world - wide - web at the following url : |
2006-01-01 20:51:34 +08:00
| http : //www.php.net/license/3_01.txt |
2003-11-09 22:05:36 +08:00
| 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-21 04:59:45 +08:00
/* $Id$ */
2003-11-09 22:05:36 +08:00
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include "php.h"
# include "php_ini.h"
# include "ext/standard/info.h"
2004-02-12 18:43:27 +08:00
# include "zend_exceptions.h"
2003-11-09 22:05:36 +08:00
# include "zend_interfaces.h"
# include "php_spl.h"
# include "spl_functions.h"
# include "spl_engine.h"
# include "spl_iterators.h"
2003-12-02 15:18:05 +08:00
# include "spl_directory.h"
2004-11-01 08:26:59 +08:00
# include "spl_array.h"
2004-11-02 01:39:59 +08:00
# include "spl_exceptions.h"
2014-09-21 04:42:02 +08:00
# include "zend_smart_str.h"
2003-11-09 22:05:36 +08:00
2006-04-13 21:21:43 +08:00
# ifdef accept
# undef accept
# endif
2004-11-02 04:57:23 +08:00
PHPAPI zend_class_entry * spl_ce_RecursiveIterator ;
PHPAPI zend_class_entry * spl_ce_RecursiveIteratorIterator ;
PHPAPI zend_class_entry * spl_ce_FilterIterator ;
2011-03-28 04:13:27 +08:00
PHPAPI zend_class_entry * spl_ce_CallbackFilterIterator ;
2005-09-15 11:33:04 +08:00
PHPAPI zend_class_entry * spl_ce_RecursiveFilterIterator ;
2011-03-28 04:13:27 +08:00
PHPAPI zend_class_entry * spl_ce_RecursiveCallbackFilterIterator ;
2004-11-02 04:57:23 +08:00
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 ;
2005-09-19 01:15:04 +08:00
PHPAPI zend_class_entry * spl_ce_RecursiveCachingIterator ;
2004-11-02 04:57:23 +08:00
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 ;
2006-05-11 00:50:57 +08:00
PHPAPI zend_class_entry * spl_ce_RegexIterator ;
PHPAPI zend_class_entry * spl_ce_RecursiveRegexIterator ;
2008-07-19 23:49:21 +08:00
PHPAPI zend_class_entry * spl_ce_RecursiveTreeIterator ;
2003-11-09 22:05:36 +08:00
2009-07-05 04:31:27 +08:00
ZEND_BEGIN_ARG_INFO ( arginfo_recursive_it_void , 0 )
ZEND_END_ARG_INFO ( )
2007-09-28 02:00:48 +08:00
const zend_function_entry spl_funcs_RecursiveIterator [ ] = {
2009-07-05 04:31:27 +08:00
SPL_ABSTRACT_ME ( RecursiveIterator , hasChildren , arginfo_recursive_it_void )
SPL_ABSTRACT_ME ( RecursiveIterator , getChildren , arginfo_recursive_it_void )
2011-07-25 19:35:02 +08:00
PHP_FE_END
2003-11-09 22:05:36 +08:00
} ;
2003-11-11 08:25:26 +08:00
typedef enum {
RIT_LEAVES_ONLY = 0 ,
RIT_SELF_FIRST = 1 ,
RIT_CHILD_FIRST = 2
} RecursiveIteratorMode ;
2005-07-29 05:09:02 +08:00
# define RIT_CATCH_GET_CHILD CIT_CATCH_GET_CHILD
2005-07-28 06:19:01 +08:00
2008-07-19 23:49:21 +08:00
typedef enum {
RTIT_BYPASS_CURRENT = 4 ,
RTIT_BYPASS_KEY = 8
} RecursiveTreeIteratorFlags ;
2003-11-11 08:25:26 +08:00
typedef enum {
RS_NEXT = 0 ,
RS_TEST = 1 ,
RS_SELF = 2 ,
RS_CHILD = 3 ,
RS_START = 4
} RecursiveIteratorState ;
2003-11-09 22:05:36 +08:00
typedef struct _spl_sub_iterator {
zend_object_iterator * iterator ;
2014-02-12 22:15:08 +08:00
zval zobject ;
2003-11-09 22:05:36 +08:00
zend_class_entry * ce ;
2003-11-11 08:25:26 +08:00
RecursiveIteratorState state ;
2003-11-09 22:05:36 +08:00
} spl_sub_iterator ;
typedef struct _spl_recursive_it_object {
spl_sub_iterator * iterators ;
int level ;
2003-11-11 08:25:26 +08:00
RecursiveIteratorMode mode ;
2005-07-28 06:19:01 +08:00
int flags ;
2005-10-06 05:59:13 +08:00
int max_depth ;
zend_bool in_iteration ;
zend_function * beginIteration ;
zend_function * endIteration ;
2005-03-13 07:03:33 +08:00
zend_function * callHasChildren ;
zend_function * callGetChildren ;
2004-11-02 07:02:10 +08:00
zend_function * beginChildren ;
zend_function * endChildren ;
2005-09-15 11:33:04 +08:00
zend_function * nextElement ;
2004-11-02 07:02:10 +08:00
zend_class_entry * ce ;
2008-07-19 23:49:21 +08:00
smart_str prefix [ 6 ] ;
2012-05-21 21:30:24 +08:00
smart_str postfix [ 1 ] ;
2014-03-15 16:33:31 +08:00
zend_object std ;
2003-11-09 22:05:36 +08:00
} spl_recursive_it_object ;
typedef struct _spl_recursive_it_iterator {
zend_object_iterator intern ;
} spl_recursive_it_iterator ;
2003-12-08 16:39:18 +08:00
static zend_object_handlers spl_handlers_rec_it_it ;
static zend_object_handlers spl_handlers_dual_it ;
2003-11-09 22:05:36 +08:00
2014-03-15 16:33:31 +08:00
static inline spl_recursive_it_object * spl_recursive_it_from_obj ( zend_object * obj ) /* { { { */ {
return ( spl_recursive_it_object * ) ( ( char * ) ( obj ) - XtOffsetOf ( spl_recursive_it_object , std ) ) ;
}
/* }}} */
# define Z_SPLRECURSIVE_IT_P(zv) spl_recursive_it_from_obj(Z_OBJ_P((zv)))
# define SPL_FETCH_AND_CHECK_DUAL_IT(var, objzval) \
do { \
spl_dual_it_object * it = Z_SPLDUAL_IT_P ( objzval ) ; \
if ( it - > dit_type = = DIT_Unknown ) { \
2014-12-14 06:06:14 +08:00
zend_throw_exception_ex ( spl_ce_LogicException , 0 , \
2014-03-15 16:33:31 +08:00
" The object is in an invalid state as the parent constructor was not called " ) ; \
return ; \
} \
( var ) = it ; \
2011-10-30 07:17:18 +08:00
} while ( 0 )
2014-08-04 17:56:27 +08:00
# define SPL_FETCH_SUB_ELEMENT(var, object, element) \
2011-10-30 07:17:18 +08:00
do { \
2014-08-04 17:56:27 +08:00
if ( ! ( object ) - > iterators ) { \
2014-12-14 06:06:14 +08:00
zend_throw_exception_ex ( spl_ce_LogicException , 0 , \
2011-10-30 07:17:18 +08:00
" The object is in an invalid state as the parent constructor was not called " ) ; \
return ; \
} \
2014-08-04 17:56:27 +08:00
( var ) = ( object ) - > iterators [ ( object ) - > level ] . element ; \
2011-10-30 07:17:18 +08:00
} while ( 0 )
2014-08-04 17:56:27 +08:00
# define SPL_FETCH_SUB_ELEMENT_ADDR(var, object, element) \
2014-07-27 09:00:16 +08:00
do { \
if ( ! ( object ) - > iterators ) { \
2014-12-14 06:06:14 +08:00
zend_throw_exception_ex ( spl_ce_LogicException , 0 , \
2014-07-27 09:00:16 +08:00
" The object is in an invalid state as the parent constructor was not called " ) ; \
return ; \
} \
2014-08-04 17:56:27 +08:00
( var ) = & ( object ) - > iterators [ ( object ) - > level ] . element ; \
2014-07-27 09:00:16 +08:00
} while ( 0 )
# define SPL_FETCH_SUB_ITERATOR(var, object) SPL_FETCH_SUB_ELEMENT(var, object, iterator)
2014-12-14 06:06:14 +08:00
static void spl_recursive_it_dtor ( zend_object_iterator * _iter )
2003-11-09 22:05:36 +08:00
{
spl_recursive_it_iterator * iter = ( spl_recursive_it_iterator * ) _iter ;
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = Z_SPLRECURSIVE_IT_P ( & iter - > intern . data ) ;
2003-11-09 22:05:36 +08:00
zend_object_iterator * sub_iter ;
2010-07-08 05:55:17 +08:00
while ( object - > level > 0 ) {
2016-11-02 12:11:30 +08:00
if ( ! Z_ISUNDEF ( object - > iterators [ object - > level ] . zobject ) ) {
sub_iter = object - > iterators [ object - > level ] . iterator ;
zend_iterator_dtor ( sub_iter ) ;
zval_ptr_dtor ( & object - > iterators [ object - > level ] . zobject ) ;
}
object - > level - - ;
2003-11-09 22:05:36 +08:00
}
2005-10-06 05:59:13 +08:00
object - > iterators = erealloc ( object - > iterators , sizeof ( spl_sub_iterator ) ) ;
2003-11-09 22:05:36 +08:00
object - > level = 0 ;
2014-02-27 19:19:02 +08:00
zval_ptr_dtor ( & iter - > intern . data ) ;
2003-11-09 22:05:36 +08:00
}
2010-07-08 05:55:17 +08:00
2014-12-14 06:06:14 +08:00
static int spl_recursive_it_valid_ex ( spl_recursive_it_object * object , zval * zthis )
2003-11-09 22:05:36 +08:00
{
zend_object_iterator * sub_iter ;
int level = object - > level ;
2014-07-27 09:00:16 +08:00
if ( ! object - > iterators ) {
return FAILURE ;
}
2003-11-09 22:05:36 +08:00
while ( level > = 0 ) {
sub_iter = object - > iterators [ level ] . iterator ;
2014-12-14 06:06:14 +08:00
if ( sub_iter - > funcs - > valid ( sub_iter ) = = SUCCESS ) {
2003-11-09 22:05:36 +08:00
return SUCCESS ;
}
level - - ;
}
2005-10-06 05:59:13 +08:00
if ( object - > endIteration & & object - > in_iteration ) {
2014-02-12 22:15:08 +08:00
zend_call_method_with_0_params ( zthis , object - > ce , & object - > endIteration , " endIteration " , NULL ) ;
2005-10-06 05:59:13 +08:00
}
object - > in_iteration = 0 ;
2003-11-09 22:05:36 +08:00
return FAILURE ;
}
2014-12-14 06:06:14 +08:00
static int spl_recursive_it_valid ( zend_object_iterator * iter )
2003-11-09 22:05:36 +08:00
{
2014-12-14 06:06:14 +08:00
return spl_recursive_it_valid_ex ( Z_SPLRECURSIVE_IT_P ( & iter - > data ) , & iter - > data ) ;
2003-11-09 22:05:36 +08:00
}
2014-12-14 06:06:14 +08:00
static zval * spl_recursive_it_get_current_data ( zend_object_iterator * iter )
2003-11-09 22:05:36 +08:00
{
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = Z_SPLRECURSIVE_IT_P ( & iter - > data ) ;
2014-02-27 19:19:02 +08:00
zend_object_iterator * sub_iter = object - > iterators [ object - > level ] . iterator ;
2015-01-03 17:22:58 +08:00
2014-12-14 06:06:14 +08:00
return sub_iter - > funcs - > get_current_data ( sub_iter ) ;
2003-11-09 22:05:36 +08:00
}
2014-12-14 06:06:14 +08:00
static void spl_recursive_it_get_current_key ( zend_object_iterator * iter , zval * key )
2003-11-09 22:05:36 +08:00
{
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = Z_SPLRECURSIVE_IT_P ( & iter - > data ) ;
2014-02-27 19:19:02 +08:00
zend_object_iterator * sub_iter = object - > iterators [ object - > level ] . iterator ;
2003-11-09 22:05:36 +08:00
if ( sub_iter - > funcs - > get_current_key ) {
2014-12-14 06:06:14 +08:00
sub_iter - > funcs - > get_current_key ( sub_iter , key ) ;
2003-11-09 22:05:36 +08:00
} else {
2014-08-26 01:24:55 +08:00
ZVAL_LONG ( key , iter - > index ) ;
2003-11-09 22:05:36 +08:00
}
}
2014-12-14 06:06:14 +08:00
static void spl_recursive_it_move_forward_ex ( spl_recursive_it_object * object , zval * zthis )
2003-11-09 22:05:36 +08:00
{
zend_object_iterator * iterator ;
zval * zobject ;
zend_class_entry * ce ;
2014-02-12 22:15:08 +08:00
zval retval , child ;
2003-11-09 22:05:36 +08:00
zend_object_iterator * sub_iter ;
2005-03-07 06:57:05 +08:00
int has_children ;
2003-11-09 22:05:36 +08:00
2014-07-27 09:00:16 +08:00
SPL_FETCH_SUB_ITERATOR ( iterator , object ) ;
2005-03-07 07:07:43 +08:00
while ( ! EG ( exception ) ) {
2003-11-11 08:25:26 +08:00
next_step :
2003-11-09 22:05:36 +08:00
iterator = object - > iterators [ object - > level ] . iterator ;
2003-11-11 08:25:26 +08:00
switch ( object - > iterators [ object - > level ] . state ) {
case RS_NEXT :
2014-12-14 06:06:14 +08:00
iterator - > funcs - > move_forward ( iterator ) ;
2006-05-22 02:13:37 +08:00
if ( EG ( exception ) ) {
if ( ! ( object - > flags & RIT_CATCH_GET_CHILD ) ) {
return ;
} else {
2014-12-14 06:06:14 +08:00
zend_clear_exception ( ) ;
2006-05-22 02:13:37 +08:00
}
}
2011-08-13 06:20:35 +08:00
/* fall through */
2003-11-11 08:25:26 +08:00
case RS_START :
2014-12-14 06:06:14 +08:00
if ( iterator - > funcs - > valid ( iterator ) = = FAILURE ) {
2003-11-11 08:25:26 +08:00
break ;
}
2015-01-03 17:22:58 +08:00
object - > iterators [ object - > level ] . state = RS_TEST ;
2003-11-11 08:25:26 +08:00
/* break; */
case RS_TEST :
ce = object - > iterators [ object - > level ] . ce ;
2014-02-12 22:15:08 +08:00
zobject = & object - > iterators [ object - > level ] . zobject ;
2005-03-13 07:03:33 +08:00
if ( object - > callHasChildren ) {
2014-02-12 22:15:08 +08:00
zend_call_method_with_0_params ( zthis , object - > ce , & object - > callHasChildren , " callHasChildren " , & retval ) ;
2005-03-13 07:03:33 +08:00
} else {
2014-02-12 22:15:08 +08:00
zend_call_method_with_0_params ( zobject , ce , NULL , " haschildren " , & retval ) ;
2005-03-13 07:03:33 +08:00
}
2006-05-22 02:13:37 +08:00
if ( EG ( exception ) ) {
if ( ! ( object - > flags & RIT_CATCH_GET_CHILD ) ) {
object - > iterators [ object - > level ] . state = RS_NEXT ;
return ;
} else {
2014-12-14 06:06:14 +08:00
zend_clear_exception ( ) ;
2006-05-22 02:13:37 +08:00
}
}
2014-02-12 22:15:08 +08:00
if ( Z_TYPE ( retval ) ! = IS_UNDEF ) {
2014-12-14 06:06:14 +08:00
has_children = zend_is_true ( & retval ) ;
2014-02-13 02:51:19 +08:00
zval_ptr_dtor ( & retval ) ;
2005-03-07 06:57:05 +08:00
if ( has_children ) {
2005-10-06 05:59:13 +08:00
if ( object - > max_depth = = - 1 | | object - > max_depth > object - > level ) {
2005-12-22 08:37:07 +08:00
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 ;
}
2005-10-06 05:59:13 +08:00
} else {
/* do not recurse into */
if ( object - > mode = = RIT_LEAVES_ONLY ) {
/* this is not a leave, so skip it */
object - > iterators [ object - > level ] . state = RS_NEXT ;
goto next_step ;
}
}
2003-11-11 08:25:26 +08:00
}
}
2005-09-15 11:33:04 +08:00
if ( object - > nextElement ) {
2014-02-12 22:15:08 +08:00
zend_call_method_with_0_params ( zthis , object - > ce , & object - > nextElement , " nextelement " , NULL ) ;
2005-09-15 11:33:04 +08:00
}
2003-11-11 08:25:26 +08:00
object - > iterators [ object - > level ] . state = RS_NEXT ;
2006-05-22 02:13:37 +08:00
if ( EG ( exception ) ) {
if ( ! ( object - > flags & RIT_CATCH_GET_CHILD ) ) {
return ;
} else {
2014-12-14 06:06:14 +08:00
zend_clear_exception ( ) ;
2006-05-22 02:13:37 +08:00
}
}
2003-11-11 08:25:26 +08:00
return /* self */ ;
case RS_SELF :
2005-09-15 11:33:04 +08:00
if ( object - > nextElement & & ( object - > mode = = RIT_SELF_FIRST | | object - > mode = = RIT_CHILD_FIRST ) ) {
2014-02-12 22:15:08 +08:00
zend_call_method_with_0_params ( zthis , object - > ce , & object - > nextElement , " nextelement " , NULL ) ;
2005-09-15 11:33:04 +08:00
}
2003-11-11 08:25:26 +08:00
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 ;
2014-02-12 22:15:08 +08:00
zobject = & object - > iterators [ object - > level ] . zobject ;
2005-03-13 07:03:33 +08:00
if ( object - > callGetChildren ) {
2014-02-12 22:15:08 +08:00
zend_call_method_with_0_params ( zthis , object - > ce , & object - > callGetChildren , " callGetChildren " , & child ) ;
2005-03-13 07:03:33 +08:00
} else {
2014-02-12 22:15:08 +08:00
zend_call_method_with_0_params ( zobject , ce , NULL , " getchildren " , & child ) ;
2005-03-13 07:03:33 +08:00
}
2005-07-28 06:19:01 +08:00
if ( EG ( exception ) ) {
if ( ! ( object - > flags & RIT_CATCH_GET_CHILD ) ) {
return ;
} else {
2014-12-14 06:06:14 +08:00
zend_clear_exception ( ) ;
2014-02-13 02:51:19 +08:00
zval_ptr_dtor ( & child ) ;
2005-07-28 06:19:01 +08:00
object - > iterators [ object - > level ] . state = RS_NEXT ;
goto next_step ;
}
}
2015-01-03 17:22:58 +08:00
if ( Z_TYPE ( child ) = = IS_UNDEF | | Z_TYPE ( child ) ! = IS_OBJECT | |
2014-12-14 06:06:14 +08:00
! ( ( ce = Z_OBJCE ( child ) ) & & instanceof_function ( ce , spl_ce_RecursiveIterator ) ) ) {
2014-02-13 02:51:19 +08:00
zval_ptr_dtor ( & child ) ;
2014-12-14 06:06:14 +08:00
zend_throw_exception ( spl_ce_UnexpectedValueException , " Objects returned by RecursiveIterator::getChildren() must implement RecursiveIterator " , 0 ) ;
2003-11-09 22:05:36 +08:00
return ;
2015-01-03 17:22:58 +08:00
}
2014-02-12 22:15:08 +08:00
2003-11-11 08:25:26 +08: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 22:05:36 +08:00
object - > iterators = erealloc ( object - > iterators , sizeof ( spl_sub_iterator ) * ( + + object - > level + 1 ) ) ;
2014-12-14 06:06:14 +08:00
sub_iter = ce - > get_iterator ( ce , & child , 0 ) ;
2014-03-22 04:00:20 +08:00
ZVAL_COPY_VALUE ( & object - > iterators [ object - > level ] . zobject , & child ) ;
2003-11-09 22:05:36 +08:00
object - > iterators [ object - > level ] . iterator = sub_iter ;
object - > iterators [ object - > level ] . ce = ce ;
2003-11-11 08:25:26 +08:00
object - > iterators [ object - > level ] . state = RS_START ;
2003-12-02 15:18:05 +08:00
if ( sub_iter - > funcs - > rewind ) {
2014-12-14 06:06:14 +08:00
sub_iter - > funcs - > rewind ( sub_iter ) ;
2003-12-02 15:18:05 +08:00
}
2005-03-13 07:03:33 +08:00
if ( object - > beginChildren ) {
2014-02-12 22:15:08 +08:00
zend_call_method_with_0_params ( zthis , object - > ce , & object - > beginChildren , " beginchildren " , NULL ) ;
2006-05-22 02:13:37 +08:00
if ( EG ( exception ) ) {
if ( ! ( object - > flags & RIT_CATCH_GET_CHILD ) ) {
return ;
} else {
2014-12-14 06:06:14 +08:00
zend_clear_exception ( ) ;
2006-05-22 02:13:37 +08:00
}
}
2004-11-02 07:16:43 +08:00
}
2003-11-11 08:25:26 +08:00
goto next_step ;
2003-11-09 22:05:36 +08:00
}
/* no more elements */
if ( object - > level > 0 ) {
2005-03-13 07:03:33 +08:00
if ( object - > endChildren ) {
2014-02-12 22:15:08 +08:00
zend_call_method_with_0_params ( zthis , object - > ce , & object - > endChildren , " endchildren " , NULL ) ;
2006-05-22 02:13:37 +08:00
if ( EG ( exception ) ) {
if ( ! ( object - > flags & RIT_CATCH_GET_CHILD ) ) {
return ;
} else {
2014-12-14 06:06:14 +08:00
zend_clear_exception ( ) ;
2006-05-22 02:13:37 +08:00
}
}
2004-11-02 07:16:43 +08:00
}
2015-07-07 21:25:28 +08:00
if ( object - > level > 0 ) {
2016-11-02 12:11:30 +08:00
zval garbage ;
ZVAL_COPY_VALUE ( & garbage , & object - > iterators [ object - > level ] . zobject ) ;
ZVAL_UNDEF ( & object - > iterators [ object - > level ] . zobject ) ;
zval_ptr_dtor ( & garbage ) ;
2015-07-07 21:28:51 +08:00
zend_iterator_dtor ( iterator ) ;
2015-07-07 21:25:28 +08:00
object - > level - - ;
}
2003-11-09 22:05:36 +08:00
} else {
return ; /* done completeley */
}
}
}
2014-12-14 06:06:14 +08:00
static void spl_recursive_it_rewind_ex ( spl_recursive_it_object * object , zval * zthis )
2003-11-09 22:05:36 +08:00
{
2014-03-15 16:33:31 +08:00
zend_object_iterator * sub_iter ;
2015-01-03 17:22:58 +08:00
2014-07-27 09:00:16 +08:00
SPL_FETCH_SUB_ITERATOR ( sub_iter , object ) ;
2003-11-09 22:05:36 +08:00
while ( object - > level ) {
sub_iter = object - > iterators [ object - > level ] . iterator ;
2014-12-14 06:06:14 +08:00
zend_iterator_dtor ( sub_iter ) ;
2014-02-13 02:51:19 +08:00
zval_ptr_dtor ( & object - > iterators [ object - > level - - ] . zobject ) ;
2006-05-22 02:13:37 +08:00
if ( ! EG ( exception ) & & ( ! object - > endChildren | | object - > endChildren - > common . scope ! = spl_ce_RecursiveIteratorIterator ) ) {
2014-02-12 22:15:08 +08:00
zend_call_method_with_0_params ( zthis , object - > ce , & object - > endChildren , " endchildren " , NULL ) ;
2004-11-02 07:16:43 +08:00
}
2003-11-09 22:05:36 +08:00
}
2005-12-06 03:54:47 +08:00
object - > iterators = erealloc ( object - > iterators , sizeof ( spl_sub_iterator ) ) ;
2003-11-11 08:25:26 +08:00
object - > iterators [ 0 ] . state = RS_START ;
2003-11-09 22:05:36 +08:00
sub_iter = object - > iterators [ 0 ] . iterator ;
if ( sub_iter - > funcs - > rewind ) {
2014-12-14 06:06:14 +08:00
sub_iter - > funcs - > rewind ( sub_iter ) ;
2003-11-09 22:05:36 +08:00
}
2006-05-22 02:13:37 +08:00
if ( ! EG ( exception ) & & object - > beginIteration & & ! object - > in_iteration ) {
2014-02-12 22:15:08 +08:00
zend_call_method_with_0_params ( zthis , object - > ce , & object - > beginIteration , " beginIteration " , NULL ) ;
2005-10-06 05:59:13 +08:00
}
object - > in_iteration = 1 ;
2014-12-14 06:06:14 +08:00
spl_recursive_it_move_forward_ex ( object , zthis ) ;
2003-11-09 22:05:36 +08:00
}
2014-12-14 06:06:14 +08:00
static void spl_recursive_it_move_forward ( zend_object_iterator * iter )
2003-11-09 22:05:36 +08:00
{
2014-12-14 06:06:14 +08:00
spl_recursive_it_move_forward_ex ( Z_SPLRECURSIVE_IT_P ( & iter - > data ) , & iter - > data ) ;
2003-11-09 22:05:36 +08:00
}
2014-12-14 06:06:14 +08:00
static void spl_recursive_it_rewind ( zend_object_iterator * iter )
2003-11-09 22:05:36 +08:00
{
2014-12-14 06:06:14 +08:00
spl_recursive_it_rewind_ex ( Z_SPLRECURSIVE_IT_P ( & iter - > data ) , & iter - > data ) ;
2003-11-09 22:05:36 +08:00
}
2014-12-14 06:06:14 +08:00
static zend_object_iterator * spl_recursive_it_get_iterator ( zend_class_entry * ce , zval * zobject , int by_ref )
2003-11-09 22:05:36 +08:00
{
2006-05-10 08:03:38 +08:00
spl_recursive_it_iterator * iterator ;
2014-02-27 19:19:02 +08:00
spl_recursive_it_object * object ;
2006-05-10 08:03:38 +08:00
if ( by_ref ) {
zend_error ( E_ERROR , " An iterator cannot be used with foreach by reference " ) ;
}
iterator = emalloc ( sizeof ( spl_recursive_it_iterator ) ) ;
2015-01-03 17:22:58 +08:00
object = Z_SPLRECURSIVE_IT_P ( zobject ) ;
2011-10-30 07:17:18 +08:00
if ( object - > iterators = = NULL ) {
zend_error ( E_ERROR , " The object to be iterated is in an invalid state: "
" the parent constructor has not been called " ) ;
}
2003-11-09 22:05:36 +08:00
2014-12-14 06:06:14 +08:00
zend_iterator_init ( ( zend_object_iterator * ) iterator ) ;
2015-01-03 17:22:58 +08:00
2014-02-27 19:19:02 +08:00
ZVAL_COPY ( & iterator - > intern . data , zobject ) ;
2003-11-09 22:05:36 +08:00
iterator - > intern . funcs = ce - > iterator_funcs . funcs ;
return ( zend_object_iterator * ) iterator ;
}
zend_object_iterator_funcs spl_recursive_it_iterator_funcs = {
spl_recursive_it_dtor ,
2004-03-09 02:05:41 +08:00
spl_recursive_it_valid ,
2003-11-09 22:05:36 +08:00
spl_recursive_it_get_current_data ,
spl_recursive_it_get_current_key ,
spl_recursive_it_move_forward ,
2016-06-22 05:40:50 +08:00
spl_recursive_it_rewind ,
NULL
2003-11-09 22:05:36 +08:00
} ;
2008-07-20 03:24:07 +08:00
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 )
2003-11-09 22:05:36 +08:00
{
2014-02-28 15:03:43 +08:00
zval * object = getThis ( ) ;
spl_recursive_it_object * intern ;
zval * iterator ;
zend_class_entry * ce_iterator ;
2014-08-26 01:24:55 +08:00
zend_long mode , flags ;
2014-02-28 15:03:43 +08:00
zend_error_handling error_handling ;
2015-04-16 01:49:50 +08:00
zval caching_it , aggregate_retval ;
2003-11-09 22:05:36 +08:00
2014-12-14 06:06:14 +08:00
zend_replace_error_handling ( EH_THROW , spl_ce_InvalidArgumentException , & error_handling ) ;
2003-11-09 22:05:36 +08:00
2014-02-28 15:03:43 +08:00
switch ( rit_type ) {
2008-07-19 23:49:21 +08:00
case RIT_RecursiveTreeIterator : {
2015-01-15 08:14:43 +08:00
zval caching_it_flags , * user_caching_it_flags = NULL ;
2008-07-19 23:49:21 +08:00
mode = RIT_SELF_FIRST ;
flags = RTIT_BYPASS_KEY ;
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters_ex ( ZEND_PARSE_PARAMS_QUIET , ZEND_NUM_ARGS ( ) , " o|lzl " , & iterator , & flags , & user_caching_it_flags , & mode ) = = SUCCESS ) {
if ( instanceof_function ( Z_OBJCE_P ( iterator ) , zend_ce_aggregate ) ) {
2015-04-16 01:49:50 +08:00
zend_call_method_with_0_params ( iterator , Z_OBJCE_P ( iterator ) , & Z_OBJCE_P ( iterator ) - > iterator_funcs . zf_new_iterator , " getiterator " , & aggregate_retval ) ;
iterator = & aggregate_retval ;
} else {
Z_ADDREF_P ( iterator ) ;
2008-07-19 23:49:21 +08:00
}
if ( user_caching_it_flags ) {
2015-06-12 17:33:23 +08:00
ZVAL_COPY ( & caching_it_flags , user_caching_it_flags ) ;
2008-07-19 23:49:21 +08:00
} else {
2014-08-26 01:24:55 +08:00
ZVAL_LONG ( & caching_it_flags , CIT_CATCH_GET_CHILD ) ;
2008-07-19 23:49:21 +08:00
}
2014-12-14 06:06:14 +08:00
spl_instantiate_arg_ex2 ( spl_ce_RecursiveCachingIterator , & caching_it , iterator , & caching_it_flags ) ;
2014-02-13 02:51:19 +08:00
zval_ptr_dtor ( & caching_it_flags ) ;
2015-04-16 01:49:50 +08:00
zval_ptr_dtor ( iterator ) ;
2014-03-22 06:40:41 +08:00
iterator = & caching_it ;
2008-07-19 23:49:21 +08:00
} else {
iterator = NULL ;
}
break ;
}
case RIT_RecursiveIteratorIterator :
default : {
mode = RIT_LEAVES_ONLY ;
flags = 0 ;
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters_ex ( ZEND_PARSE_PARAMS_QUIET , ZEND_NUM_ARGS ( ) , " o|ll " , & iterator , & mode , & flags ) = = SUCCESS ) {
if ( instanceof_function ( Z_OBJCE_P ( iterator ) , zend_ce_aggregate ) ) {
2015-04-16 01:49:50 +08:00
zend_call_method_with_0_params ( iterator , Z_OBJCE_P ( iterator ) , & Z_OBJCE_P ( iterator ) - > iterator_funcs . zf_new_iterator , " getiterator " , & aggregate_retval ) ;
iterator = & aggregate_retval ;
} else {
Z_ADDREF_P ( iterator ) ;
2008-07-19 23:49:21 +08:00
}
} else {
iterator = NULL ;
}
break ;
2004-11-08 21:44:34 +08:00
}
}
2014-12-14 06:06:14 +08:00
if ( ! iterator | | ! instanceof_function ( Z_OBJCE_P ( iterator ) , spl_ce_RecursiveIterator ) ) {
2015-04-16 01:49:50 +08:00
if ( iterator ) {
2014-02-12 22:15:08 +08:00
zval_ptr_dtor ( iterator ) ;
2005-12-22 08:35:37 +08:00
}
2014-12-14 06:06:14 +08:00
zend_throw_exception ( spl_ce_InvalidArgumentException , " An instance of RecursiveIterator or IteratorAggregate creating it is required " , 0 ) ;
zend_restore_error_handling ( & error_handling ) ;
2003-11-09 22:05:36 +08:00
return ;
}
2014-03-15 16:33:31 +08:00
intern = Z_SPLRECURSIVE_IT_P ( object ) ;
2003-11-09 22:05:36 +08:00
intern - > iterators = emalloc ( sizeof ( spl_sub_iterator ) ) ;
intern - > level = 0 ;
2005-07-29 05:09:02 +08:00
intern - > mode = mode ;
2014-10-29 20:46:58 +08:00
intern - > flags = ( int ) flags ;
2005-10-06 05:59:13 +08:00
intern - > max_depth = - 1 ;
intern - > in_iteration = 0 ;
2004-11-02 07:02:10 +08:00
intern - > ce = Z_OBJCE_P ( object ) ;
2005-10-06 05:59:13 +08:00
2014-02-12 22:15:08 +08:00
intern - > beginIteration = zend_hash_str_find_ptr ( & intern - > ce - > function_table , " beginiteration " , sizeof ( " beginiteration " ) - 1 ) ;
2008-07-19 23:49:21 +08:00
if ( intern - > beginIteration - > common . scope = = ce_base ) {
2005-10-06 05:59:13 +08:00
intern - > beginIteration = NULL ;
}
2014-02-12 22:15:08 +08:00
intern - > endIteration = zend_hash_str_find_ptr ( & intern - > ce - > function_table , " enditeration " , sizeof ( " enditeration " ) - 1 ) ;
2008-07-19 23:49:21 +08:00
if ( intern - > endIteration - > common . scope = = ce_base ) {
2005-10-06 05:59:13 +08:00
intern - > endIteration = NULL ;
}
2014-02-12 22:15:08 +08:00
intern - > callHasChildren = zend_hash_str_find_ptr ( & intern - > ce - > function_table , " callhaschildren " , sizeof ( " callHasChildren " ) - 1 ) ;
2008-07-19 23:49:21 +08:00
if ( intern - > callHasChildren - > common . scope = = ce_base ) {
2005-03-13 07:03:33 +08:00
intern - > callHasChildren = NULL ;
}
2014-02-12 22:15:08 +08:00
intern - > callGetChildren = zend_hash_str_find_ptr ( & intern - > ce - > function_table , " callgetchildren " , sizeof ( " callGetChildren " ) - 1 ) ;
2008-07-19 23:49:21 +08:00
if ( intern - > callGetChildren - > common . scope = = ce_base ) {
2005-03-13 07:03:33 +08:00
intern - > callGetChildren = NULL ;
}
2014-02-12 22:15:08 +08:00
intern - > beginChildren = zend_hash_str_find_ptr ( & intern - > ce - > function_table , " beginchildren " , sizeof ( " beginchildren " ) - 1 ) ;
2008-07-19 23:49:21 +08:00
if ( intern - > beginChildren - > common . scope = = ce_base ) {
2005-03-13 07:03:33 +08:00
intern - > beginChildren = NULL ;
}
2014-02-12 22:15:08 +08:00
intern - > endChildren = zend_hash_str_find_ptr ( & intern - > ce - > function_table , " endchildren " , sizeof ( " endchildren " ) - 1 ) ;
2008-07-19 23:49:21 +08:00
if ( intern - > endChildren - > common . scope = = ce_base ) {
2005-03-13 07:03:33 +08:00
intern - > endChildren = NULL ;
}
2014-02-12 22:15:08 +08:00
intern - > nextElement = zend_hash_str_find_ptr ( & intern - > ce - > function_table , " nextelement " , sizeof ( " nextElement " ) - 1 ) ;
2008-07-19 23:49:21 +08:00
if ( intern - > nextElement - > common . scope = = ce_base ) {
2005-09-15 11:33:04 +08:00
intern - > nextElement = NULL ;
}
2014-02-28 15:03:43 +08:00
2003-11-09 22:05:36 +08:00
ce_iterator = Z_OBJCE_P ( iterator ) ; /* respect inheritance, don't use spl_ce_RecursiveIterator */
2014-12-14 06:06:14 +08:00
intern - > iterators [ 0 ] . iterator = ce_iterator - > get_iterator ( ce_iterator , iterator , 0 ) ;
2015-04-16 01:49:50 +08:00
ZVAL_COPY_VALUE ( & intern - > iterators [ 0 ] . zobject , iterator ) ;
2003-11-09 22:05:36 +08:00
intern - > iterators [ 0 ] . ce = ce_iterator ;
2003-11-11 08:25:26 +08:00
intern - > iterators [ 0 ] . state = RS_START ;
2003-11-09 22:05:36 +08:00
2014-12-14 06:06:14 +08:00
zend_restore_error_handling ( & error_handling ) ;
2010-07-08 05:55:17 +08:00
if ( EG ( exception ) ) {
zend_object_iterator * sub_iter ;
while ( intern - > level > = 0 ) {
sub_iter = intern - > iterators [ intern - > level ] . iterator ;
2014-12-14 06:06:14 +08:00
zend_iterator_dtor ( sub_iter ) ;
2014-02-13 02:51:19 +08:00
zval_ptr_dtor ( & intern - > iterators [ intern - > level - - ] . zobject ) ;
2010-07-08 05:55:17 +08:00
}
efree ( intern - > iterators ) ;
intern - > iterators = NULL ;
}
2008-07-19 23:49:21 +08:00
}
/* {{{ proto void RecursiveIteratorIterator::__construct(RecursiveIterator|IteratorAggregate it [, int mode = RIT_LEAVES_ONLY [, int flags = 0]]) throws InvalidArgumentException
Creates a RecursiveIteratorIterator from a RecursiveIterator . */
SPL_METHOD ( RecursiveIteratorIterator , __construct )
{
2008-07-20 03:45:55 +08:00
spl_recursive_it_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , spl_ce_RecursiveIteratorIterator , zend_ce_iterator , RIT_RecursiveIteratorIterator ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-11-09 22:05:36 +08:00
2004-05-06 17:01:31 +08:00
/* {{{ proto void RecursiveIteratorIterator::rewind()
Rewind the iterator to the first element of the top level inner iterator . */
2003-11-09 22:05:36 +08:00
SPL_METHOD ( RecursiveIteratorIterator , rewind )
{
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = Z_SPLRECURSIVE_IT_P ( getThis ( ) ) ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2003-11-09 22:05:36 +08:00
2014-12-14 06:06:14 +08:00
spl_recursive_it_rewind_ex ( object , getThis ( ) ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-11-09 22:05:36 +08:00
2006-03-06 17:50:44 +08:00
/* {{{ proto bool RecursiveIteratorIterator::valid()
2004-05-06 17:01:31 +08:00
Check whether the current position is valid */
2004-03-09 01:33:31 +08:00
SPL_METHOD ( RecursiveIteratorIterator , valid )
2003-11-09 22:05:36 +08:00
{
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = Z_SPLRECURSIVE_IT_P ( getThis ( ) ) ;
2014-07-27 09:00:16 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2003-11-09 22:05:36 +08:00
2014-12-14 06:06:14 +08:00
RETURN_BOOL ( spl_recursive_it_valid_ex ( object , getThis ( ) ) = = SUCCESS ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-11-09 22:05:36 +08:00
2004-05-06 17:01:31 +08:00
/* {{{ proto mixed RecursiveIteratorIterator::key()
Access the current key */
2003-11-09 22:05:36 +08:00
SPL_METHOD ( RecursiveIteratorIterator , key )
{
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = Z_SPLRECURSIVE_IT_P ( getThis ( ) ) ;
2014-07-27 09:00:16 +08:00
zend_object_iterator * iterator ;
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2003-11-09 22:05:36 +08:00
2014-07-27 09:00:16 +08:00
SPL_FETCH_SUB_ITERATOR ( iterator , object ) ;
2003-11-09 22:05:36 +08:00
if ( iterator - > funcs - > get_current_key ) {
2014-12-14 06:06:14 +08:00
iterator - > funcs - > get_current_key ( iterator , return_value ) ;
2003-11-09 22:05:36 +08:00
} else {
RETURN_NULL ( ) ;
}
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-11-09 22:05:36 +08:00
2004-05-06 17:01:31 +08:00
/* {{{ proto mixed RecursiveIteratorIterator::current()
Access the current element value */
2003-11-09 22:05:36 +08:00
SPL_METHOD ( RecursiveIteratorIterator , current )
{
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = Z_SPLRECURSIVE_IT_P ( getThis ( ) ) ;
2014-07-27 09:00:16 +08:00
zend_object_iterator * iterator ;
2014-02-12 22:15:08 +08:00
zval * data ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2003-11-09 22:05:36 +08:00
2014-07-27 09:00:16 +08:00
SPL_FETCH_SUB_ITERATOR ( iterator , object ) ;
2014-12-14 06:06:14 +08:00
data = iterator - > funcs - > get_current_data ( iterator ) ;
2014-02-12 22:15:08 +08:00
if ( data ) {
2015-07-01 07:05:21 +08:00
ZVAL_DEREF ( data ) ;
ZVAL_COPY ( return_value , data ) ;
2009-05-10 03:45:26 +08:00
}
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-11-09 22:05:36 +08:00
2004-05-06 17:01:31 +08:00
/* {{{ proto void RecursiveIteratorIterator::next()
Move forward to the next element */
2003-11-09 22:05:36 +08:00
SPL_METHOD ( RecursiveIteratorIterator , next )
{
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = Z_SPLRECURSIVE_IT_P ( getThis ( ) ) ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2003-11-09 22:05:36 +08:00
2014-12-14 06:06:14 +08:00
spl_recursive_it_move_forward_ex ( object , getThis ( ) ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-11-09 22:05:36 +08:00
2004-05-06 17:01:31 +08:00
/* {{{ proto int RecursiveIteratorIterator::getDepth()
Get the current depth of the recursive iteration */
2003-11-23 04:49:15 +08:00
SPL_METHOD ( RecursiveIteratorIterator , getDepth )
2003-11-09 22:05:36 +08:00
{
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = Z_SPLRECURSIVE_IT_P ( getThis ( ) ) ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2015-01-03 17:22:58 +08:00
2014-08-26 01:24:55 +08:00
RETURN_LONG ( object - > level ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-11-09 22:05:36 +08:00
2004-10-30 04:12:57 +08:00
/* {{{ proto RecursiveIterator RecursiveIteratorIterator::getSubIterator([int level])
The current active sub iterator or the iterator at specified level */
2003-11-19 06:14:19 +08:00
SPL_METHOD ( RecursiveIteratorIterator , getSubIterator )
{
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = Z_SPLRECURSIVE_IT_P ( getThis ( ) ) ;
2014-08-26 01:24:55 +08:00
zend_long level = object - > level ;
2015-07-01 07:05:21 +08:00
zval * value ;
2015-01-03 17:22:58 +08:00
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " |l " , & level ) = = FAILURE ) {
2003-11-19 06:14:19 +08:00
return ;
}
if ( level < 0 | | level > object - > level ) {
RETURN_NULL ( ) ;
}
2014-07-27 09:00:16 +08:00
if ( ! object - > iterators ) {
2014-12-14 06:06:14 +08:00
zend_throw_exception_ex ( spl_ce_LogicException , 0 ,
2014-07-27 09:00:16 +08:00
" The object is in an invalid state as the parent constructor was not called " ) ;
return ;
}
2015-07-01 07:05:21 +08:00
value = & object - > iterators [ level ] . zobject ;
ZVAL_DEREF ( value ) ;
ZVAL_COPY ( return_value , value ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-11-19 06:14:19 +08:00
2004-10-30 04:12:57 +08:00
/* {{{ proto RecursiveIterator RecursiveIteratorIterator::getInnerIterator()
The current active sub iterator */
SPL_METHOD ( RecursiveIteratorIterator , getInnerIterator )
{
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = Z_SPLRECURSIVE_IT_P ( getThis ( ) ) ;
2014-07-27 09:00:16 +08:00
zval * zobject ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2014-07-27 09:00:16 +08:00
2014-08-04 17:56:27 +08:00
SPL_FETCH_SUB_ELEMENT_ADDR ( zobject , object , zobject ) ;
2014-07-27 09:00:16 +08:00
2015-07-01 07:05:21 +08:00
ZVAL_DEREF ( zobject ) ;
ZVAL_COPY ( return_value , zobject ) ;
2004-10-30 04:12:57 +08:00
} /* }}} */
2005-10-06 05:59:13 +08:00
/* {{{ proto RecursiveIterator RecursiveIteratorIterator::beginIteration()
Called when iteration begins ( after first rewind ( ) call ) */
SPL_METHOD ( RecursiveIteratorIterator , beginIteration )
{
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2005-10-06 05:59:13 +08:00
/* nothing to do */
} /* }}} */
/* {{{ proto RecursiveIterator RecursiveIteratorIterator::endIteration()
Called when iteration ends ( when valid ( ) first returns false */
SPL_METHOD ( RecursiveIteratorIterator , endIteration )
{
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2005-10-06 05:59:13 +08:00
/* nothing to do */
} /* }}} */
2005-03-13 07:03:33 +08:00
/* {{{ proto bool RecursiveIteratorIterator::callHasChildren()
Called for each element to test whether it has children */
SPL_METHOD ( RecursiveIteratorIterator , callHasChildren )
{
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = Z_SPLRECURSIVE_IT_P ( getThis ( ) ) ;
2014-07-27 09:00:16 +08:00
zend_class_entry * ce ;
2014-02-12 22:15:08 +08:00
zval * zobject ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2005-03-13 07:03:33 +08:00
2014-07-27 09:00:16 +08:00
if ( ! object - > iterators ) {
RETURN_NULL ( ) ;
}
SPL_FETCH_SUB_ELEMENT ( ce , object , ce ) ;
2014-02-12 22:15:08 +08:00
zobject = & object - > iterators [ object - > level ] . zobject ;
if ( Z_TYPE_P ( zobject ) = = IS_UNDEF ) {
2005-03-13 07:03:33 +08:00
RETURN_FALSE ;
} else {
2014-02-12 22:15:08 +08:00
zend_call_method_with_0_params ( zobject , ce , NULL , " haschildren " , return_value ) ;
if ( Z_TYPE_P ( return_value ) = = IS_UNDEF ) {
2006-05-22 02:13:37 +08:00
RETURN_FALSE ;
}
2005-03-13 07:03:33 +08:00
}
} /* }}} */
/* {{{ proto RecursiveIterator RecursiveIteratorIterator::callGetChildren()
Return children of current element */
SPL_METHOD ( RecursiveIteratorIterator , callGetChildren )
{
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = Z_SPLRECURSIVE_IT_P ( getThis ( ) ) ;
2014-07-27 09:00:16 +08:00
zend_class_entry * ce ;
2014-02-12 22:15:08 +08:00
zval * zobject ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2005-03-13 07:03:33 +08:00
2014-07-27 09:00:16 +08:00
SPL_FETCH_SUB_ELEMENT ( ce , object , ce ) ;
2014-02-12 22:15:08 +08:00
zobject = & object - > iterators [ object - > level ] . zobject ;
if ( Z_TYPE_P ( zobject ) = = IS_UNDEF ) {
2005-03-13 07:03:33 +08:00
return ;
} else {
2014-02-12 22:15:08 +08:00
zend_call_method_with_0_params ( zobject , ce , NULL , " getchildren " , return_value ) ;
if ( Z_TYPE_P ( return_value ) = = IS_UNDEF ) {
RETURN_NULL ( ) ;
2015-01-03 17:22:58 +08:00
}
2005-03-13 07:03:33 +08:00
}
} /* }}} */
2006-03-06 17:50:44 +08:00
/* {{{ proto void RecursiveIteratorIterator::beginChildren()
2004-11-02 06:54:12 +08:00
Called when recursing one level down */
SPL_METHOD ( RecursiveIteratorIterator , beginChildren )
{
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2004-11-02 06:54:12 +08:00
/* nothing to do */
} /* }}} */
2006-03-06 17:50:44 +08:00
/* {{{ proto void RecursiveIteratorIterator::endChildren()
2004-11-02 06:54:12 +08:00
Called when end recursing one level */
SPL_METHOD ( RecursiveIteratorIterator , endChildren )
{
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2004-11-02 06:54:12 +08:00
/* nothing to do */
} /* }}} */
2006-03-06 17:50:44 +08:00
/* {{{ proto void RecursiveIteratorIterator::nextElement()
2005-09-15 11:33:04 +08:00
Called when the next element is available */
SPL_METHOD ( RecursiveIteratorIterator , nextElement )
{
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2005-09-15 11:33:04 +08:00
/* nothing to do */
} /* }}} */
2006-03-06 17:50:44 +08:00
/* {{{ proto void RecursiveIteratorIterator::setMaxDepth([$max_depth = -1])
2005-10-06 05:59:13 +08:00
Set the maximum allowed depth ( or any depth if pmax_depth = - 1 ] */
SPL_METHOD ( RecursiveIteratorIterator , setMaxDepth )
{
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = Z_SPLRECURSIVE_IT_P ( getThis ( ) ) ;
2014-08-26 01:24:55 +08:00
zend_long max_depth = - 1 ;
2015-01-03 17:22:58 +08:00
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " |l " , & max_depth ) = = FAILURE ) {
2005-10-06 05:59:13 +08:00
return ;
}
if ( max_depth < - 1 ) {
2014-12-14 06:06:14 +08:00
zend_throw_exception ( spl_ce_OutOfRangeException , " Parameter max_depth must be >= -1 " , 0 ) ;
2005-10-06 05:59:13 +08:00
return ;
2014-10-29 20:46:58 +08:00
} else if ( max_depth > INT_MAX ) {
max_depth = INT_MAX ;
2005-10-06 05:59:13 +08:00
}
2014-10-29 20:46:58 +08:00
object - > max_depth = ( int ) max_depth ;
2005-10-06 05:59:13 +08:00
} /* }}} */
2006-03-06 17:50:44 +08:00
/* {{{ proto int|false RecursiveIteratorIterator::getMaxDepth()
2005-10-06 05:59:13 +08:00
Return the maximum accepted depth or false if any depth is allowed */
SPL_METHOD ( RecursiveIteratorIterator , getMaxDepth )
{
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = Z_SPLRECURSIVE_IT_P ( getThis ( ) ) ;
2005-10-06 05:59:13 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2015-01-03 17:22:58 +08:00
2005-10-06 05:59:13 +08:00
if ( object - > max_depth = = - 1 ) {
RETURN_FALSE ;
} else {
2014-08-26 01:24:55 +08:00
RETURN_LONG ( object - > max_depth ) ;
2005-10-06 05:59:13 +08:00
}
} /* }}} */
2014-12-14 06:06:14 +08:00
static union _zend_function * spl_recursive_it_get_method ( zend_object * * zobject , zend_string * method , const zval * key )
2004-11-01 03:05:19 +08:00
{
union _zend_function * function_handler ;
2014-03-28 06:11:22 +08:00
spl_recursive_it_object * object = spl_recursive_it_from_obj ( * zobject ) ;
2014-08-26 01:24:55 +08:00
zend_long level = object - > level ;
2008-03-12 21:34:47 +08:00
zval * zobj ;
if ( ! object - > iterators ) {
2015-06-30 09:05:24 +08:00
php_error_docref ( NULL , E_ERROR , " The %s instance wasn't initialized properly " , ZSTR_VAL ( ( * zobject ) - > ce - > name ) ) ;
2008-03-12 21:34:47 +08:00
}
2014-02-12 22:15:08 +08:00
zobj = & object - > iterators [ level ] . zobject ;
2008-03-12 21:34:47 +08:00
2014-12-14 06:06:14 +08:00
function_handler = std_object_handlers . get_method ( zobject , method , key ) ;
2004-11-01 03:05:19 +08:00
if ( ! function_handler ) {
2014-02-12 22:15:08 +08:00
if ( ( function_handler = zend_hash_find_ptr ( & Z_OBJCE_P ( zobj ) - > function_table , method ) ) = = NULL ) {
2004-11-01 03:05:19 +08:00
if ( Z_OBJ_HT_P ( zobj ) - > get_method ) {
2014-03-28 06:11:22 +08:00
* zobject = Z_OBJ_P ( zobj ) ;
2014-12-14 06:06:14 +08:00
function_handler = ( * zobject ) - > handlers - > get_method ( zobject , method , key ) ;
2004-11-01 03:05:19 +08:00
}
2014-06-01 19:41:01 +08:00
} else {
2014-06-01 22:29:41 +08:00
* zobject = Z_OBJ_P ( zobj ) ;
2004-11-01 03:05:19 +08:00
}
}
return function_handler ;
}
2003-12-08 16:39:18 +08:00
/* {{{ spl_RecursiveIteratorIterator_dtor */
2014-12-14 06:06:14 +08:00
static void spl_RecursiveIteratorIterator_dtor ( zend_object * _object )
2003-11-09 22:05:36 +08:00
{
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = spl_recursive_it_from_obj ( _object ) ;
zend_object_iterator * sub_iter ;
2003-11-09 22:05:36 +08:00
2010-07-08 05:55:17 +08:00
/* call standard dtor */
2014-12-14 06:06:14 +08:00
zend_objects_destroy_object ( _object ) ;
2010-07-08 05:55:17 +08:00
2003-11-09 22:05:36 +08:00
if ( object - > iterators ) {
while ( object - > level > = 0 ) {
sub_iter = object - > iterators [ object - > level ] . iterator ;
2014-12-14 06:06:14 +08:00
zend_iterator_dtor ( sub_iter ) ;
2014-02-13 02:51:19 +08:00
zval_ptr_dtor ( & object - > iterators [ object - > level - - ] . zobject ) ;
2003-11-09 22:05:36 +08:00
}
efree ( object - > iterators ) ;
2005-10-06 05:59:13 +08:00
object - > iterators = NULL ;
2003-11-09 22:05:36 +08:00
}
2010-07-08 05:55:17 +08:00
}
/* }}} */
/* {{{ spl_RecursiveIteratorIterator_free_storage */
2014-12-14 06:06:14 +08:00
static void spl_RecursiveIteratorIterator_free_storage ( zend_object * _object )
2010-07-08 05:55:17 +08:00
{
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = spl_recursive_it_from_obj ( _object ) ;
2003-11-09 22:05:36 +08:00
2015-03-11 05:57:28 +08:00
if ( object - > iterators ) {
efree ( object - > iterators ) ;
object - > iterators = NULL ;
2017-08-01 18:59:19 +08:00
object - > level = 0 ;
2015-03-11 05:57:28 +08:00
}
2014-12-14 06:06:14 +08:00
zend_object_std_dtor ( & object - > std ) ;
2008-07-19 23:49:21 +08:00
smart_str_free ( & object - > prefix [ 0 ] ) ;
smart_str_free ( & object - > prefix [ 1 ] ) ;
smart_str_free ( & object - > prefix [ 2 ] ) ;
smart_str_free ( & object - > prefix [ 3 ] ) ;
smart_str_free ( & object - > prefix [ 4 ] ) ;
smart_str_free ( & object - > prefix [ 5 ] ) ;
2003-11-09 22:05:36 +08:00
2012-05-21 21:30:24 +08:00
smart_str_free ( & object - > postfix [ 0 ] ) ;
2003-11-09 22:05:36 +08:00
}
/* }}} */
2008-07-19 23:49:21 +08:00
/* {{{ spl_RecursiveIteratorIterator_new_ex */
2014-12-14 06:06:14 +08:00
static zend_object * spl_RecursiveIteratorIterator_new_ex ( zend_class_entry * class_type , int init_prefix )
2003-11-09 22:05:36 +08:00
{
spl_recursive_it_object * intern ;
2015-02-04 20:24:13 +08:00
intern = ecalloc ( 1 , sizeof ( spl_recursive_it_object ) + zend_object_properties_size ( class_type ) ) ;
2003-11-09 22:05:36 +08:00
2008-07-19 23:49:21 +08:00
if ( init_prefix ) {
smart_str_appendl ( & intern - > prefix [ 0 ] , " " , 0 ) ;
smart_str_appendl ( & intern - > prefix [ 1 ] , " | " , 2 ) ;
smart_str_appendl ( & intern - > prefix [ 2 ] , " " , 2 ) ;
smart_str_appendl ( & intern - > prefix [ 3 ] , " |- " , 2 ) ;
smart_str_appendl ( & intern - > prefix [ 4 ] , " \\ - " , 2 ) ;
smart_str_appendl ( & intern - > prefix [ 5 ] , " " , 0 ) ;
2012-05-21 21:30:24 +08:00
smart_str_appendl ( & intern - > postfix [ 0 ] , " " , 0 ) ;
2008-07-19 23:49:21 +08:00
}
2014-12-14 06:06:14 +08:00
zend_object_std_init ( & intern - > std , class_type ) ;
2010-05-24 22:11:39 +08:00
object_properties_init ( & intern - > std , class_type ) ;
2003-11-09 22:05:36 +08:00
2014-02-12 22:15:08 +08:00
intern - > std . handlers = & spl_handlers_rec_it_it ;
return & intern - > std ;
2003-12-02 15:18:05 +08:00
}
/* }}} */
2008-07-19 23:49:21 +08:00
/* {{{ spl_RecursiveIteratorIterator_new */
2014-12-14 06:06:14 +08:00
static zend_object * spl_RecursiveIteratorIterator_new ( zend_class_entry * class_type )
2008-07-19 23:49:21 +08:00
{
2014-12-14 06:06:14 +08:00
return spl_RecursiveIteratorIterator_new_ex ( class_type , 0 ) ;
2008-07-19 23:49:21 +08:00
}
/* }}} */
/* {{{ spl_RecursiveTreeIterator_new */
2014-12-14 06:06:14 +08:00
static zend_object * spl_RecursiveTreeIterator_new ( zend_class_entry * class_type )
2008-07-19 23:49:21 +08:00
{
2014-12-14 06:06:14 +08:00
return spl_RecursiveIteratorIterator_new_ex ( class_type , 1 ) ;
2008-07-19 23:49:21 +08:00
}
/* }}} */
2015-01-03 17:22:58 +08:00
ZEND_BEGIN_ARG_INFO_EX ( arginfo_recursive_it___construct , 0 , 0 , 1 )
2004-11-08 21:44:34 +08:00
ZEND_ARG_OBJ_INFO ( 0 , iterator , Traversable , 0 )
2004-11-02 06:54:12 +08:00
ZEND_ARG_INFO ( 0 , mode )
2006-11-07 07:20:11 +08:00
ZEND_ARG_INFO ( 0 , flags )
2004-11-02 06:54:12 +08:00
ZEND_END_ARG_INFO ( ) ;
2006-11-07 07:20:11 +08:00
ZEND_BEGIN_ARG_INFO_EX ( arginfo_recursive_it_getSubIterator , 0 , 0 , 0 )
2004-11-02 06:54:12 +08:00
ZEND_ARG_INFO ( 0 , level )
ZEND_END_ARG_INFO ( ) ;
2006-11-07 07:20:11 +08:00
ZEND_BEGIN_ARG_INFO_EX ( arginfo_recursive_it_setMaxDepth , 0 , 0 , 0 )
2005-10-06 05:59:13 +08:00
ZEND_ARG_INFO ( 0 , max_depth )
ZEND_END_ARG_INFO ( ) ;
2007-09-28 02:00:48 +08:00
static const zend_function_entry spl_funcs_RecursiveIteratorIterator [ ] = {
2005-10-06 05:59:13 +08:00
SPL_ME ( RecursiveIteratorIterator , __construct , arginfo_recursive_it___construct , ZEND_ACC_PUBLIC )
2009-07-05 04:31:27 +08:00
SPL_ME ( RecursiveIteratorIterator , rewind , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , valid , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , key , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , current , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , next , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , getDepth , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2005-03-13 07:03:33 +08:00
SPL_ME ( RecursiveIteratorIterator , getSubIterator , arginfo_recursive_it_getSubIterator , ZEND_ACC_PUBLIC )
2009-07-05 04:31:27 +08:00
SPL_ME ( RecursiveIteratorIterator , getInnerIterator , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , beginIteration , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , endIteration , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , callHasChildren , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , callGetChildren , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , beginChildren , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , endChildren , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , nextElement , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2005-10-06 05:59:13 +08:00
SPL_ME ( RecursiveIteratorIterator , setMaxDepth , arginfo_recursive_it_setMaxDepth , ZEND_ACC_PUBLIC )
2009-07-05 04:31:27 +08:00
SPL_ME ( RecursiveIteratorIterator , getMaxDepth , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2011-07-25 19:35:02 +08:00
PHP_FE_END
2004-11-02 06:54:12 +08:00
} ;
2014-12-14 06:06:14 +08:00
static void spl_recursive_tree_iterator_get_prefix ( spl_recursive_it_object * object , zval * return_value )
2008-07-19 23:49:21 +08:00
{
smart_str str = { 0 } ;
2014-02-12 22:15:08 +08:00
zval has_next ;
2008-07-19 23:49:21 +08:00
int level ;
2015-06-30 09:05:24 +08:00
smart_str_appendl ( & str , ZSTR_VAL ( object - > prefix [ 0 ] . s ) , ZSTR_LEN ( object - > prefix [ 0 ] . s ) ) ;
2015-01-03 17:22:58 +08:00
2008-07-19 23:49:21 +08:00
for ( level = 0 ; level < object - > level ; + + level ) {
zend_call_method_with_0_params ( & object - > iterators [ level ] . zobject , object - > iterators [ level ] . ce , NULL , " hasnext " , & has_next ) ;
2014-02-12 22:15:08 +08:00
if ( Z_TYPE ( has_next ) ! = IS_UNDEF ) {
2014-04-30 22:32:42 +08:00
if ( Z_TYPE ( has_next ) = = IS_TRUE ) {
2015-06-30 09:05:24 +08:00
smart_str_appendl ( & str , ZSTR_VAL ( object - > prefix [ 1 ] . s ) , ZSTR_LEN ( object - > prefix [ 1 ] . s ) ) ;
2008-07-19 23:49:21 +08:00
} else {
2015-06-30 09:05:24 +08:00
smart_str_appendl ( & str , ZSTR_VAL ( object - > prefix [ 2 ] . s ) , ZSTR_LEN ( object - > prefix [ 2 ] . s ) ) ;
2008-07-19 23:49:21 +08:00
}
2014-02-13 02:51:19 +08:00
zval_ptr_dtor ( & has_next ) ;
2008-07-19 23:49:21 +08:00
}
}
zend_call_method_with_0_params ( & object - > iterators [ level ] . zobject , object - > iterators [ level ] . ce , NULL , " hasnext " , & has_next ) ;
2014-02-12 22:15:08 +08:00
if ( Z_TYPE ( has_next ) ! = IS_UNDEF ) {
2014-04-30 22:32:42 +08:00
if ( Z_TYPE ( has_next ) = = IS_TRUE ) {
2015-06-30 09:05:24 +08:00
smart_str_appendl ( & str , ZSTR_VAL ( object - > prefix [ 3 ] . s ) , ZSTR_LEN ( object - > prefix [ 3 ] . s ) ) ;
2008-07-19 23:49:21 +08:00
} else {
2015-06-30 09:05:24 +08:00
smart_str_appendl ( & str , ZSTR_VAL ( object - > prefix [ 4 ] . s ) , ZSTR_LEN ( object - > prefix [ 4 ] . s ) ) ;
2008-07-19 23:49:21 +08:00
}
2014-02-13 02:51:19 +08:00
zval_ptr_dtor ( & has_next ) ;
2008-07-19 23:49:21 +08:00
}
2015-06-30 09:05:24 +08:00
smart_str_appendl ( & str , ZSTR_VAL ( object - > prefix [ 5 ] . s ) , ZSTR_LEN ( object - > prefix [ 5 ] . s ) ) ;
2008-07-19 23:49:21 +08:00
smart_str_0 ( & str ) ;
2015-03-12 21:53:51 +08:00
RETURN_NEW_STR ( str . s ) ;
2008-07-19 23:49:21 +08:00
}
2014-12-14 06:06:14 +08:00
static void spl_recursive_tree_iterator_get_entry ( spl_recursive_it_object * object , zval * return_value )
2008-07-19 23:49:21 +08:00
{
zend_object_iterator * iterator = object - > iterators [ object - > level ] . iterator ;
2014-02-12 22:15:08 +08:00
zval * data ;
2008-08-09 06:07:07 +08:00
zend_error_handling error_handling ;
2008-07-19 23:49:21 +08:00
2014-12-14 06:06:14 +08:00
data = iterator - > funcs - > get_current_data ( iterator ) ;
2008-07-19 23:49:21 +08:00
2015-04-03 00:52:32 +08:00
/* Replace exception handling so the catchable fatal error that is thrown when a class
* without __toString is converted to string is converted into an exception . */
2014-12-14 06:06:14 +08:00
zend_replace_error_handling ( EH_THROW , spl_ce_UnexpectedValueException , & error_handling ) ;
2014-02-12 22:15:08 +08:00
if ( data ) {
2015-06-17 01:55:33 +08:00
ZVAL_DEREF ( data ) ;
if ( Z_TYPE_P ( data ) = = IS_ARRAY ) {
2014-02-12 22:15:08 +08:00
ZVAL_STRINGL ( return_value , " Array " , sizeof ( " Array " ) - 1 ) ;
2013-06-09 22:24:48 +08:00
} else {
2015-06-17 01:55:33 +08:00
ZVAL_COPY ( return_value , data ) ;
convert_to_string ( return_value ) ;
2013-06-09 22:24:48 +08:00
}
2008-07-29 19:50:05 +08:00
}
2014-12-14 06:06:14 +08:00
zend_restore_error_handling ( & error_handling ) ;
2008-07-19 23:49:21 +08:00
}
2014-12-14 06:06:14 +08:00
static void spl_recursive_tree_iterator_get_postfix ( spl_recursive_it_object * object , zval * return_value )
2008-07-19 23:49:21 +08:00
{
2014-02-18 17:42:46 +08:00
RETVAL_STR ( object - > postfix [ 0 ] . s ) ;
Z_ADDREF_P ( return_value ) ;
2008-07-19 23:49:21 +08:00
}
/* {{{ 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
RecursiveIteratorIterator to generate ASCII graphic trees for the entries in a RecursiveIterator */
SPL_METHOD ( RecursiveTreeIterator , __construct )
{
2008-07-20 03:45:55 +08:00
spl_recursive_it_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , spl_ce_RecursiveTreeIterator , zend_ce_iterator , RIT_RecursiveTreeIterator ) ;
2008-07-19 23:49:21 +08:00
} /* }}} */
2010-11-15 02:40:08 +08:00
/* {{{ proto void RecursiveTreeIterator::setPrefixPart(int part, string prefix) throws OutOfRangeException
2008-07-19 23:49:21 +08:00
Sets prefix parts as used in getPrefix ( ) */
SPL_METHOD ( RecursiveTreeIterator , setPrefixPart )
{
2014-08-26 01:24:55 +08:00
zend_long part ;
2008-07-19 23:49:21 +08:00
char * prefix ;
2014-08-27 21:31:48 +08:00
size_t prefix_len ;
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = Z_SPLRECURSIVE_IT_P ( getThis ( ) ) ;
2015-01-03 17:22:58 +08:00
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " ls " , & part , & prefix , & prefix_len ) = = FAILURE ) {
2008-07-19 23:49:21 +08:00
return ;
}
2014-02-12 22:15:08 +08:00
2008-07-19 23:49:21 +08:00
if ( 0 > part | | part > 5 ) {
2014-12-14 06:06:14 +08:00
zend_throw_exception_ex ( spl_ce_OutOfRangeException , 0 , " Use RecursiveTreeIterator::PREFIX_* constant " ) ;
2008-07-19 23:49:21 +08:00
return ;
}
2015-01-03 17:22:58 +08:00
2008-07-19 23:49:21 +08:00
smart_str_free ( & object - > prefix [ part ] ) ;
smart_str_appendl ( & object - > prefix [ part ] , prefix , prefix_len ) ;
} /* }}} */
/* {{{ proto string RecursiveTreeIterator::getPrefix()
Returns the string to place in front of current element */
SPL_METHOD ( RecursiveTreeIterator , getPrefix )
{
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = Z_SPLRECURSIVE_IT_P ( getThis ( ) ) ;
2008-07-19 23:49:21 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2014-07-27 09:00:16 +08:00
if ( ! object - > iterators ) {
2014-12-14 06:06:14 +08:00
zend_throw_exception_ex ( spl_ce_LogicException , 0 ,
2014-07-27 09:00:16 +08:00
" The object is in an invalid state as the parent constructor was not called " ) ;
return ;
2015-01-03 17:22:58 +08:00
}
2014-12-14 06:06:14 +08:00
spl_recursive_tree_iterator_get_prefix ( object , return_value ) ;
2008-07-19 23:49:21 +08:00
} /* }}} */
2012-05-21 21:30:24 +08:00
/* {{{ proto void RecursiveTreeIterator::setPostfix(string prefix)
Sets postfix as used in getPostfix ( ) */
SPL_METHOD ( RecursiveTreeIterator , setPostfix )
{
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = Z_SPLRECURSIVE_IT_P ( getThis ( ) ) ;
2012-05-21 21:30:24 +08:00
char * postfix ;
2014-08-27 21:31:48 +08:00
size_t postfix_len ;
2012-05-21 21:30:24 +08:00
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " s " , & postfix , & postfix_len ) = = FAILURE ) {
2012-05-21 21:30:24 +08:00
return ;
}
smart_str_free ( & object - > postfix [ 0 ] ) ;
smart_str_appendl ( & object - > postfix [ 0 ] , postfix , postfix_len ) ;
} /* }}} */
2008-07-19 23:49:21 +08:00
/* {{{ proto string RecursiveTreeIterator::getEntry()
Returns the string presentation built for current element */
SPL_METHOD ( RecursiveTreeIterator , getEntry )
{
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = Z_SPLRECURSIVE_IT_P ( getThis ( ) ) ;
2008-07-19 23:49:21 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2014-07-27 09:00:16 +08:00
if ( ! object - > iterators ) {
2014-12-14 06:06:14 +08:00
zend_throw_exception_ex ( spl_ce_LogicException , 0 ,
2014-07-27 09:00:16 +08:00
" The object is in an invalid state as the parent constructor was not called " ) ;
return ;
}
2015-01-03 17:22:58 +08:00
2014-12-14 06:06:14 +08:00
spl_recursive_tree_iterator_get_entry ( object , return_value ) ;
2008-07-19 23:49:21 +08:00
} /* }}} */
/* {{{ proto string RecursiveTreeIterator::getPostfix()
Returns the string to place after the current element */
SPL_METHOD ( RecursiveTreeIterator , getPostfix )
{
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = Z_SPLRECURSIVE_IT_P ( getThis ( ) ) ;
2008-07-19 23:49:21 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2014-07-27 09:00:16 +08:00
if ( ! object - > iterators ) {
2014-12-14 06:06:14 +08:00
zend_throw_exception_ex ( spl_ce_LogicException , 0 ,
2014-07-27 09:00:16 +08:00
" The object is in an invalid state as the parent constructor was not called " ) ;
return ;
}
2015-01-03 17:22:58 +08:00
2014-12-14 06:06:14 +08:00
spl_recursive_tree_iterator_get_postfix ( object , return_value ) ;
2008-07-19 23:49:21 +08:00
} /* }}} */
/* {{{ proto mixed RecursiveTreeIterator::current()
Returns the current element prefixed and postfixed */
SPL_METHOD ( RecursiveTreeIterator , current )
{
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = Z_SPLRECURSIVE_IT_P ( getThis ( ) ) ;
2008-07-19 23:49:21 +08:00
zval prefix , entry , postfix ;
2014-03-16 15:45:45 +08:00
char * ptr ;
zend_string * str ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2008-07-19 23:49:21 +08:00
2014-07-27 09:00:16 +08:00
if ( ! object - > iterators ) {
2014-12-14 06:06:14 +08:00
zend_throw_exception_ex ( spl_ce_LogicException , 0 ,
2014-07-27 09:00:16 +08:00
" The object is in an invalid state as the parent constructor was not called " ) ;
return ;
2015-01-03 17:22:58 +08:00
}
2014-07-27 09:00:16 +08:00
2008-07-19 23:49:21 +08:00
if ( object - > flags & RTIT_BYPASS_CURRENT ) {
zend_object_iterator * iterator = object - > iterators [ object - > level ] . iterator ;
2014-02-12 22:15:08 +08:00
zval * data ;
2008-07-19 23:49:21 +08:00
2014-07-27 09:00:16 +08:00
SPL_FETCH_SUB_ITERATOR ( iterator , object ) ;
2014-12-14 06:06:14 +08:00
data = iterator - > funcs - > get_current_data ( iterator ) ;
2014-02-12 22:15:08 +08:00
if ( data ) {
2015-07-01 07:05:21 +08:00
ZVAL_DEREF ( data ) ;
ZVAL_COPY ( return_value , data ) ;
return ;
2009-05-10 03:35:09 +08:00
} else {
RETURN_NULL ( ) ;
}
2008-07-19 23:49:21 +08:00
}
2014-02-13 03:54:04 +08:00
ZVAL_NULL ( & prefix ) ;
ZVAL_NULL ( & entry ) ;
2014-12-14 06:06:14 +08:00
spl_recursive_tree_iterator_get_prefix ( object , & prefix ) ;
spl_recursive_tree_iterator_get_entry ( object , & entry ) ;
2013-06-09 22:24:48 +08:00
if ( Z_TYPE ( entry ) ! = IS_STRING ) {
2014-03-16 15:45:45 +08:00
zval_ptr_dtor ( & prefix ) ;
zval_ptr_dtor ( & entry ) ;
2013-06-09 22:24:48 +08:00
RETURN_NULL ( ) ;
}
2014-12-14 06:06:14 +08:00
spl_recursive_tree_iterator_get_postfix ( object , & postfix ) ;
2008-07-19 23:49:21 +08:00
2014-08-26 01:24:55 +08:00
str = zend_string_alloc ( Z_STRLEN ( prefix ) + Z_STRLEN ( entry ) + Z_STRLEN ( postfix ) , 0 ) ;
2015-06-30 09:05:24 +08:00
ptr = ZSTR_VAL ( str ) ;
2008-07-19 23:49:21 +08:00
2014-08-26 01:24:55 +08:00
memcpy ( ptr , Z_STRVAL ( prefix ) , Z_STRLEN ( prefix ) ) ;
ptr + = Z_STRLEN ( prefix ) ;
memcpy ( ptr , Z_STRVAL ( entry ) , Z_STRLEN ( entry ) ) ;
ptr + = Z_STRLEN ( entry ) ;
memcpy ( ptr , Z_STRVAL ( postfix ) , Z_STRLEN ( postfix ) ) ;
ptr + = Z_STRLEN ( postfix ) ;
2008-07-19 23:49:21 +08:00
* ptr = 0 ;
2014-03-16 15:45:45 +08:00
zval_ptr_dtor ( & prefix ) ;
zval_ptr_dtor ( & entry ) ;
zval_ptr_dtor ( & postfix ) ;
2008-07-19 23:49:21 +08:00
2014-04-03 19:26:23 +08:00
RETURN_NEW_STR ( str ) ;
2008-07-19 23:49:21 +08:00
} /* }}} */
/* {{{ proto mixed RecursiveTreeIterator::key()
Returns the current key prefixed and postfixed */
SPL_METHOD ( RecursiveTreeIterator , key )
{
2014-03-15 16:33:31 +08:00
spl_recursive_it_object * object = Z_SPLRECURSIVE_IT_P ( getThis ( ) ) ;
2014-07-27 09:00:16 +08:00
zend_object_iterator * iterator ;
2008-07-19 23:49:21 +08:00
zval prefix , key , postfix , key_copy ;
2014-03-16 15:45:45 +08:00
char * ptr ;
zend_string * str ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2008-07-19 23:49:21 +08:00
2014-07-27 09:00:16 +08:00
SPL_FETCH_SUB_ITERATOR ( iterator , object ) ;
2008-07-19 23:49:21 +08:00
if ( iterator - > funcs - > get_current_key ) {
2014-12-14 06:06:14 +08:00
iterator - > funcs - > get_current_key ( iterator , & key ) ;
2008-07-19 23:49:21 +08:00
} else {
ZVAL_NULL ( & key ) ;
}
if ( object - > flags & RTIT_BYPASS_KEY ) {
2015-06-12 17:33:23 +08:00
RETVAL_ZVAL ( & key , 1 , 1 ) ;
2008-07-19 23:49:21 +08:00
return ;
}
if ( Z_TYPE ( key ) ! = IS_STRING ) {
2014-12-14 06:06:14 +08:00
if ( zend_make_printable_zval ( & key , & key_copy ) ) {
2008-07-19 23:49:21 +08:00
key = key_copy ;
}
}
2014-12-14 06:06:14 +08:00
spl_recursive_tree_iterator_get_prefix ( object , & prefix ) ;
spl_recursive_tree_iterator_get_postfix ( object , & postfix ) ;
2008-07-19 23:49:21 +08:00
2014-08-26 01:24:55 +08:00
str = zend_string_alloc ( Z_STRLEN ( prefix ) + Z_STRLEN ( key ) + Z_STRLEN ( postfix ) , 0 ) ;
2015-06-30 09:05:24 +08:00
ptr = ZSTR_VAL ( str ) ;
2008-07-19 23:49:21 +08:00
2014-08-26 01:24:55 +08:00
memcpy ( ptr , Z_STRVAL ( prefix ) , Z_STRLEN ( prefix ) ) ;
ptr + = Z_STRLEN ( prefix ) ;
memcpy ( ptr , Z_STRVAL ( key ) , Z_STRLEN ( key ) ) ;
ptr + = Z_STRLEN ( key ) ;
memcpy ( ptr , Z_STRVAL ( postfix ) , Z_STRLEN ( postfix ) ) ;
ptr + = Z_STRLEN ( postfix ) ;
2008-07-19 23:49:21 +08:00
* ptr = 0 ;
2014-03-16 15:45:45 +08:00
zval_ptr_dtor ( & prefix ) ;
zval_ptr_dtor ( & key ) ;
zval_ptr_dtor ( & postfix ) ;
2008-07-19 23:49:21 +08:00
2014-04-03 19:26:23 +08:00
RETURN_NEW_STR ( str ) ;
2008-07-19 23:49:21 +08:00
} /* }}} */
2015-01-03 17:22:58 +08:00
ZEND_BEGIN_ARG_INFO_EX ( arginfo_recursive_tree_it___construct , 0 , 0 , 1 )
2008-07-19 23:49:21 +08:00
ZEND_ARG_OBJ_INFO ( 0 , iterator , Traversable , 0 )
ZEND_ARG_INFO ( 0 , flags )
ZEND_ARG_INFO ( 0 , caching_it_flags )
ZEND_ARG_INFO ( 0 , mode )
ZEND_END_ARG_INFO ( ) ;
ZEND_BEGIN_ARG_INFO_EX ( arginfo_recursive_tree_it_setPrefixPart , 0 , 0 , 2 )
ZEND_ARG_INFO ( 0 , part )
ZEND_ARG_INFO ( 0 , value )
ZEND_END_ARG_INFO ( ) ;
static const zend_function_entry spl_funcs_RecursiveTreeIterator [ ] = {
SPL_ME ( RecursiveTreeIterator , __construct , arginfo_recursive_tree_it___construct , ZEND_ACC_PUBLIC )
2009-07-05 04:31:27 +08:00
SPL_ME ( RecursiveIteratorIterator , rewind , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , valid , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveTreeIterator , key , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveTreeIterator , current , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , next , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , beginIteration , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , endIteration , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , callHasChildren , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , callGetChildren , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , beginChildren , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , endChildren , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveIteratorIterator , nextElement , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveTreeIterator , getPrefix , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2008-07-19 23:49:21 +08:00
SPL_ME ( RecursiveTreeIterator , setPrefixPart , arginfo_recursive_tree_it_setPrefixPart , ZEND_ACC_PUBLIC )
2009-07-05 04:31:27 +08:00
SPL_ME ( RecursiveTreeIterator , getEntry , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2012-05-21 21:30:24 +08:00
SPL_ME ( RecursiveTreeIterator , setPostfix , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2009-07-05 04:31:27 +08:00
SPL_ME ( RecursiveTreeIterator , getPostfix , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2011-07-25 19:35:02 +08:00
PHP_FE_END
2008-07-19 23:49:21 +08:00
} ;
2003-12-02 15:18:05 +08:00
# if MBO_0
2014-12-14 06:06:14 +08:00
static int spl_dual_it_gets_implemented ( zend_class_entry * interface , zend_class_entry * class_type )
2003-12-02 15:18:05 +08:00
{
2004-03-09 02:05:41 +08:00
class_type - > iterator_funcs . zf_valid = NULL ;
2003-12-02 15:18:05 +08: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
2014-12-14 06:06:14 +08:00
static union _zend_function * spl_dual_it_get_method ( zend_object * * object , zend_string * method , const zval * key )
2003-12-08 16:39:18 +08:00
{
union _zend_function * function_handler ;
spl_dual_it_object * intern ;
2014-03-28 06:11:22 +08:00
intern = spl_dual_it_from_obj ( * object ) ;
2003-12-08 16:39:18 +08:00
2014-12-14 06:06:14 +08:00
function_handler = std_object_handlers . get_method ( object , method , key ) ;
2009-10-24 00:47:35 +08:00
if ( ! function_handler & & intern - > inner . ce ) {
2014-02-12 22:15:08 +08:00
if ( ( function_handler = zend_hash_find_ptr ( & intern - > inner . ce - > function_table , method ) ) = = NULL ) {
2014-02-28 15:03:43 +08:00
if ( Z_OBJ_HT ( intern - > inner . zobject ) - > get_method ) {
2014-03-28 06:11:22 +08:00
* object = Z_OBJ ( intern - > inner . zobject ) ;
2014-12-14 06:06:14 +08:00
function_handler = ( * object ) - > handlers - > get_method ( object , method , key ) ;
2003-12-08 16:39:18 +08:00
}
2012-07-21 22:45:16 +08:00
} else {
2014-03-28 06:11:22 +08:00
* object = Z_OBJ ( intern - > inner . zobject ) ;
2003-12-08 16:39:18 +08:00
}
}
return function_handler ;
}
# if MBO_0
int spl_dual_it_call_method ( char * method , INTERNAL_FUNCTION_PARAMETERS )
{
zval * * * func_params , func ;
2014-02-12 22:15:08 +08:00
zval retval ;
2003-12-08 16:39:18 +08:00
int arg_count ;
int current = 0 ;
int success ;
void * * p ;
spl_dual_it_object * intern ;
2014-03-15 16:33:31 +08:00
intern = Z_SPLDUAL_IT_P ( getThis ( ) ) ;
2003-12-08 16:39:18 +08:00
ZVAL_STRING ( & func , method , 0 ) ;
2003-12-07 03:21:02 +08:00
2003-12-08 16:39:18 +08:00
p = EG ( argument_stack ) . top_element - 2 ;
2014-08-26 01:24:55 +08:00
arg_count = ( zend_ulong ) * p ;
2003-12-08 16:39:18 +08:00
func_params = safe_emalloc ( sizeof ( zval * * ) , arg_count , 0 ) ;
current = 0 ;
while ( arg_count - - > 0 ) {
func_params [ current ] = ( zval * * ) p - ( arg_count - current ) ;
current + + ;
}
2008-01-10 18:11:33 +08:00
arg_count = current ; /* restore */
2003-12-08 16:39:18 +08:00
2015-01-03 17:22:58 +08:00
if ( call_user_function_ex ( EG ( function_table ) , NULL , & func , & retval , arg_count , func_params , 0 , NULL ) = = SUCCESS & & Z_TYPE ( retval ) ! = IS_UNDEF ) {
2014-02-12 22:15:08 +08:00
RETURN_ZVAL ( & retval , 0 , 0 ) ;
2015-01-03 17:22:58 +08:00
2003-12-08 16:39:18 +08:00
success = SUCCESS ;
} else {
2016-06-12 01:07:28 +08:00
zend_throw_error ( NULL , " Unable to call %s::%s() " , intern - > inner . ce - > name , method ) ;
2003-12-08 16:39:18 +08:00
success = FAILURE ;
}
2015-01-03 17:22:58 +08:00
efree ( func_params ) ;
2003-12-08 16:39:18 +08:00
return success ;
}
# endif
2011-10-30 07:17:18 +08:00
# define SPL_CHECK_CTOR(intern, classname) \
if ( intern - > dit_type = = DIT_Unknown ) { \
2014-12-14 06:06:14 +08:00
zend_throw_exception_ex ( spl_ce_BadMethodCallException , 0 , " Classes derived from %s must call %s::__construct() " , \
2015-06-30 09:05:24 +08:00
ZSTR_VAL ( ( spl_ce_ # # classname ) - > name ) , ZSTR_VAL ( ( spl_ce_ # # classname ) - > name ) ) ; \
2011-10-30 07:17:18 +08:00
return ; \
}
# define APPENDIT_CHECK_CTOR(intern) SPL_CHECK_CTOR(intern, AppendIterator)
2014-12-14 06:06:14 +08:00
static inline int spl_dual_it_fetch ( spl_dual_it_object * intern , int check_more ) ;
2004-11-01 02:43:00 +08:00
2014-10-29 20:46:58 +08:00
static inline int spl_cit_check_flags ( zend_long flags )
2006-05-19 05:42:58 +08:00
{
2014-10-29 20:46:58 +08:00
zend_long cnt = 0 ;
2006-05-19 05:42:58 +08:00
cnt + = ( flags & CIT_CALL_TOSTRING ) ? 1 : 0 ;
cnt + = ( flags & CIT_TOSTRING_USE_KEY ) ? 1 : 0 ;
cnt + = ( flags & CIT_TOSTRING_USE_CURRENT ) ? 1 : 0 ;
cnt + = ( flags & CIT_TOSTRING_USE_INNER ) ? 1 : 0 ;
2015-01-03 17:22:58 +08:00
2006-05-19 05:42:58 +08:00
return cnt < = 1 ? SUCCESS : FAILURE ;
}
2006-03-06 01:39:49 +08:00
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 )
2003-12-02 15:18:05 +08:00
{
2014-02-13 03:54:04 +08:00
zval * zobject , retval ;
2003-12-02 15:18:05 +08:00
spl_dual_it_object * intern ;
2006-02-06 19:28:41 +08:00
zend_class_entry * ce = NULL ;
2005-12-19 08:32:51 +08:00
int inc_refcount = 1 ;
2008-11-19 10:00:53 +08:00
zend_error_handling error_handling ;
2003-12-02 15:18:05 +08:00
2014-03-15 16:33:31 +08:00
intern = Z_SPLDUAL_IT_P ( getThis ( ) ) ;
2015-01-03 17:22:58 +08:00
2006-03-06 01:39:49 +08:00
if ( intern - > dit_type ! = DIT_Unknown ) {
2015-06-30 09:05:24 +08:00
zend_throw_exception_ex ( spl_ce_BadMethodCallException , 0 , " %s::getIterator() must be called exactly once per instance " , ZSTR_VAL ( ce_base - > name ) ) ;
2006-03-06 01:39:49 +08:00
return NULL ;
}
2003-12-08 16:39:18 +08:00
intern - > dit_type = dit_type ;
2003-12-07 03:21:02 +08:00
switch ( dit_type ) {
2003-12-08 16:39:18 +08:00
case DIT_LimitIterator : {
2004-05-19 04:39:35 +08:00
intern - > u . limit . offset = 0 ; /* start at beginning */
2003-12-07 03:21:02 +08:00
intern - > u . limit . count = - 1 ; /* get all */
2015-04-03 00:52:32 +08:00
if ( zend_parse_parameters_throw ( ZEND_NUM_ARGS ( ) , " O|ll " , & zobject , ce_inner , & intern - > u . limit . offset , & intern - > u . limit . count ) = = FAILURE ) {
2003-12-07 03:21:02 +08:00
return NULL ;
}
if ( intern - > u . limit . offset < 0 ) {
2014-12-14 06:06:14 +08:00
zend_throw_exception ( spl_ce_OutOfRangeException , " Parameter offset must be >= 0 " , 0 ) ;
2003-12-07 03:21:02 +08:00
return NULL ;
}
if ( intern - > u . limit . count < 0 & & intern - > u . limit . count ! = - 1 ) {
2014-12-14 06:06:14 +08:00
zend_throw_exception ( spl_ce_OutOfRangeException , " Parameter count must either be -1 or a value greater than or equal 0 " , 0 ) ;
2003-12-07 03:21:02 +08:00
return NULL ;
}
break ;
}
2003-12-08 16:39:18 +08:00
case DIT_CachingIterator :
2005-09-19 01:15:04 +08:00
case DIT_RecursiveCachingIterator : {
2014-08-26 01:24:55 +08:00
zend_long flags = CIT_CALL_TOSTRING ;
2015-04-03 00:52:32 +08:00
if ( zend_parse_parameters_throw ( ZEND_NUM_ARGS ( ) , " O|l " , & zobject , ce_inner , & flags ) = = FAILURE ) {
2003-12-08 16:39:18 +08:00
return NULL ;
}
2006-05-19 05:42:58 +08:00
if ( spl_cit_check_flags ( flags ) ! = SUCCESS ) {
2014-12-14 06:06:14 +08:00
zend_throw_exception ( spl_ce_InvalidArgumentException , " Flags must contain only one of CALL_TOSTRING, TOSTRING_USE_KEY, TOSTRING_USE_CURRENT, TOSTRING_USE_INNER " , 0 ) ;
2005-10-04 00:05:08 +08:00
return NULL ;
}
2003-12-08 16:39:18 +08:00
intern - > u . caching . flags | = flags & CIT_PUBLIC ;
2014-02-13 03:54:04 +08:00
array_init ( & intern - > u . caching . zcache ) ;
2003-12-08 16:39:18 +08:00
break ;
}
2004-11-01 02:43:00 +08:00
case DIT_IteratorIterator : {
2014-02-13 03:54:04 +08:00
zend_class_entry * ce_cast ;
2014-02-12 22:15:08 +08:00
zend_string * class_name ;
2004-11-01 02:43:00 +08:00
2015-04-03 00:52:32 +08:00
if ( zend_parse_parameters_throw ( ZEND_NUM_ARGS ( ) , " O|S " , & zobject , ce_inner , & class_name ) = = FAILURE ) {
2004-11-01 02:43:00 +08:00
return NULL ;
}
ce = Z_OBJCE_P ( zobject ) ;
2014-12-14 06:06:14 +08:00
if ( ! instanceof_function ( ce , zend_ce_iterator ) ) {
2005-02-23 09:03:16 +08:00
if ( ZEND_NUM_ARGS ( ) > 1 ) {
2014-12-14 06:06:14 +08:00
if ( ! ( ce_cast = zend_lookup_class ( class_name ) )
| | ! instanceof_function ( ce , ce_cast )
2014-02-13 03:54:04 +08:00
| | ! ce_cast - > get_iterator
2005-02-23 09:03:16 +08:00
) {
2014-12-14 06:06:14 +08:00
zend_throw_exception ( spl_ce_LogicException , " Class to downcast to not found or not base class or does not implement Traversable " , 0 ) ;
2005-02-23 09:03:16 +08:00
return NULL ;
}
2014-02-13 03:54:04 +08:00
ce = ce_cast ;
2005-02-23 09:03:16 +08:00
}
2014-12-14 06:06:14 +08:00
if ( instanceof_function ( ce , zend_ce_aggregate ) ) {
2014-02-13 03:54:04 +08:00
zend_call_method_with_0_params ( zobject , ce , & ce - > iterator_funcs . zf_new_iterator , " getiterator " , & retval ) ;
2006-05-22 02:13:37 +08:00
if ( EG ( exception ) ) {
2014-02-13 03:54:04 +08:00
zval_ptr_dtor ( & retval ) ;
2006-05-22 02:13:37 +08:00
return NULL ;
}
2014-12-14 06:06:14 +08:00
if ( Z_TYPE ( retval ) ! = IS_OBJECT | | ! instanceof_function ( Z_OBJCE ( retval ) , zend_ce_traversable ) ) {
2015-06-30 09:05:24 +08:00
zend_throw_exception_ex ( spl_ce_LogicException , 0 , " %s::getIterator() must return an object that implements Traversable " , ZSTR_VAL ( ce - > name ) ) ;
2005-12-19 08:45:28 +08:00
return NULL ;
}
2014-03-22 05:13:15 +08:00
zobject = & retval ;
2005-03-01 18:05:12 +08:00
ce = Z_OBJCE_P ( zobject ) ;
2014-03-22 05:13:15 +08:00
inc_refcount = 0 ;
2004-11-01 02:43:00 +08:00
}
}
break ;
}
2004-11-01 08:26:59 +08:00
case DIT_AppendIterator :
2015-04-03 00:52:32 +08:00
zend_replace_error_handling ( EH_THROW , spl_ce_InvalidArgumentException , & error_handling ) ;
2014-12-14 06:06:14 +08:00
spl_instantiate ( spl_ce_ArrayIterator , & intern - > u . append . zarrayit ) ;
2004-11-01 08:26:59 +08:00
zend_call_method_with_0_params ( & intern - > u . append . zarrayit , spl_ce_ArrayIterator , & spl_ce_ArrayIterator - > constructor , " __construct " , NULL ) ;
2014-12-14 06:06:14 +08:00
intern - > u . append . iterator = spl_ce_ArrayIterator - > get_iterator ( spl_ce_ArrayIterator , & intern - > u . append . zarrayit , 0 ) ;
zend_restore_error_handling ( & error_handling ) ;
2004-11-01 08:26:59 +08:00
return intern ;
2006-05-10 08:03:38 +08:00
# if HAVE_PCRE || HAVE_BUNDLED_PCRE
2006-05-11 00:50:57 +08:00
case DIT_RegexIterator :
case DIT_RecursiveRegexIterator : {
2014-02-13 03:54:04 +08:00
zend_string * regex ;
2014-08-26 01:24:55 +08:00
zend_long mode = REGIT_MODE_MATCH ;
2006-05-10 08:03:38 +08:00
2006-07-21 06:54:21 +08:00
intern - > u . regex . use_flags = ZEND_NUM_ARGS ( ) > = 5 ;
2006-05-10 08:03:38 +08:00
intern - > u . regex . flags = 0 ;
2006-07-17 05:12:32 +08:00
intern - > u . regex . preg_flags = 0 ;
2015-04-03 00:52:32 +08:00
if ( zend_parse_parameters_throw ( ZEND_NUM_ARGS ( ) , " OS|lll " , & zobject , ce_inner , & regex , & mode , & intern - > u . regex . flags , & intern - > u . regex . preg_flags ) = = FAILURE ) {
2006-05-10 08:03:38 +08:00
return NULL ;
}
2006-07-17 05:12:32 +08:00
if ( mode < 0 | | mode > = REGIT_MODE_MAX ) {
2016-06-21 21:00:37 +08:00
zend_throw_exception_ex ( spl_ce_InvalidArgumentException , 0 , " Illegal mode " ZEND_LONG_FMT , mode ) ;
2006-07-17 05:12:32 +08:00
return NULL ;
}
intern - > u . regex . mode = mode ;
2014-08-26 01:24:55 +08:00
intern - > u . regex . regex = zend_string_copy ( regex ) ;
2015-04-03 00:52:32 +08:00
zend_replace_error_handling ( EH_THROW , spl_ce_InvalidArgumentException , & error_handling ) ;
2014-12-14 06:06:14 +08:00
intern - > u . regex . pce = pcre_get_compiled_regex_cache ( regex ) ;
2015-04-03 00:52:32 +08:00
zend_restore_error_handling ( & error_handling ) ;
2006-11-03 22:11:23 +08:00
if ( intern - > u . regex . pce = = NULL ) {
/* pcre_get_compiled_regex_cache has already sent error */
return NULL ;
}
2006-05-10 08:03:38 +08:00
intern - > u . regex . pce - > refcount + + ;
2006-11-03 22:11:23 +08:00
break ;
2006-05-10 08:03:38 +08:00
}
# endif
2011-03-28 04:13:27 +08:00
case DIT_CallbackFilterIterator :
case DIT_RecursiveCallbackFilterIterator : {
_spl_cbfilter_it_intern * cfi = emalloc ( sizeof ( * cfi ) ) ;
2014-03-28 06:11:22 +08:00
cfi - > fci . object = NULL ;
2015-04-03 00:52:32 +08:00
if ( zend_parse_parameters_throw ( ZEND_NUM_ARGS ( ) , " Of " , & zobject , ce_inner , & cfi - > fci , & cfi - > fcc ) = = FAILURE ) {
2011-03-28 04:13:27 +08:00
efree ( cfi ) ;
return NULL ;
}
2014-03-15 22:13:55 +08:00
if ( Z_REFCOUNTED_P ( & cfi - > fci . function_name ) ) {
Z_ADDREF ( cfi - > fci . function_name ) ;
}
2014-03-28 06:11:22 +08:00
cfi - > object = cfi - > fcc . object ;
2014-04-02 18:34:44 +08:00
if ( cfi - > object ) GC_REFCOUNT ( cfi - > object ) + + ;
2011-03-28 04:13:27 +08:00
intern - > u . cbfilter = cfi ;
break ;
}
2003-12-07 03:21:02 +08:00
default :
2015-04-03 00:52:32 +08:00
if ( zend_parse_parameters_throw ( ZEND_NUM_ARGS ( ) , " O " , & zobject , ce_inner ) = = FAILURE ) {
2003-12-07 03:21:02 +08:00
return NULL ;
}
break ;
2003-12-02 15:18:05 +08:00
}
2005-12-19 08:32:51 +08:00
if ( inc_refcount ) {
2014-02-28 15:03:43 +08:00
ZVAL_COPY ( & intern - > inner . zobject , zobject ) ;
} else {
ZVAL_COPY_VALUE ( & intern - > inner . zobject , zobject ) ;
2005-12-19 08:32:51 +08:00
}
2014-02-28 15:03:43 +08:00
2005-02-23 09:03:16 +08:00
intern - > inner . ce = dit_type = = DIT_IteratorIterator ? ce : Z_OBJCE_P ( zobject ) ;
2014-02-28 13:59:07 +08:00
intern - > inner . object = Z_OBJ_P ( zobject ) ;
2014-12-14 06:06:14 +08:00
intern - > inner . iterator = intern - > inner . ce - > get_iterator ( intern - > inner . ce , zobject , 0 ) ;
2003-12-02 15:18:05 +08:00
2003-12-07 03:21:02 +08:00
return intern ;
2003-12-02 15:18:05 +08:00
}
2015-01-03 17:22:58 +08:00
/* {{{ proto void FilterIterator::__construct(Iterator it)
2004-05-06 17:01:31 +08:00
Create an Iterator from another iterator */
2006-03-06 01:39:49 +08:00
SPL_METHOD ( FilterIterator , __construct )
2003-12-02 15:18:05 +08:00
{
2006-03-06 01:39:49 +08:00
spl_dual_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , spl_ce_FilterIterator , zend_ce_iterator , DIT_FilterIterator ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-12-02 15:18:05 +08:00
2015-06-24 05:46:07 +08:00
/* {{{ proto void CallbackFilterIterator::__construct(Iterator it, callback func)
2011-03-28 04:13:27 +08:00
Create an Iterator from another iterator */
SPL_METHOD ( CallbackFilterIterator , __construct )
{
spl_dual_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , spl_ce_CallbackFilterIterator , zend_ce_iterator , DIT_CallbackFilterIterator ) ;
} /* }}} */
2015-01-03 17:22:58 +08:00
/* {{{ proto Iterator FilterIterator::getInnerIterator()
2004-05-06 17:01:31 +08:00
proto Iterator CachingIterator : : getInnerIterator ( )
proto Iterator LimitIterator : : getInnerIterator ( )
proto Iterator ParentIterator : : getInnerIterator ( )
Get the inner iterator */
2004-03-10 01:35:18 +08:00
SPL_METHOD ( dual_it , getInnerIterator )
{
spl_dual_it_object * intern ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2015-01-03 17:22:58 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2004-03-10 01:35:18 +08:00
2014-05-03 16:06:27 +08:00
if ( ! Z_ISUNDEF ( intern - > inner . zobject ) ) {
2015-07-01 07:05:21 +08:00
zval * value = & intern - > inner . zobject ;
ZVAL_DEREF ( value ) ;
ZVAL_COPY ( return_value , value ) ;
2004-03-10 01:35:18 +08:00
} else {
RETURN_NULL ( ) ;
}
2004-05-06 17:01:31 +08:00
} /* }}} */
2004-03-10 01:35:18 +08:00
2014-12-14 06:06:14 +08:00
static inline void spl_dual_it_free ( spl_dual_it_object * intern )
2003-12-02 15:18:05 +08:00
{
2004-04-28 01:12:11 +08:00
if ( intern - > inner . iterator & & intern - > inner . iterator - > funcs - > invalidate_current ) {
2014-12-14 06:06:14 +08:00
intern - > inner . iterator - > funcs - > invalidate_current ( intern - > inner . iterator ) ;
2004-04-27 23:41:26 +08:00
}
2014-02-13 03:54:04 +08:00
if ( Z_TYPE ( intern - > current . data ) ! = IS_UNDEF ) {
2003-12-10 18:19:43 +08:00
zval_ptr_dtor ( & intern - > current . data ) ;
2014-02-13 03:54:04 +08:00
ZVAL_UNDEF ( & intern - > current . data ) ;
2003-12-02 15:18:05 +08:00
}
2014-02-13 03:54:04 +08:00
if ( Z_TYPE ( intern - > current . key ) ! = IS_UNDEF ) {
2013-02-17 02:13:36 +08:00
zval_ptr_dtor ( & intern - > current . key ) ;
2014-02-13 03:54:04 +08:00
ZVAL_UNDEF ( & intern - > current . key ) ;
2003-12-02 15:18:05 +08:00
}
2005-09-19 01:15:04 +08:00
if ( intern - > dit_type = = DIT_CachingIterator | | intern - > dit_type = = DIT_RecursiveCachingIterator ) {
2014-03-15 16:33:31 +08:00
if ( Z_TYPE ( intern - > u . caching . zstr ) ! = IS_UNDEF ) {
2003-12-08 16:39:18 +08:00
zval_ptr_dtor ( & intern - > u . caching . zstr ) ;
2014-02-13 03:54:04 +08:00
ZVAL_UNDEF ( & intern - > u . caching . zstr ) ;
2003-12-08 16:39:18 +08:00
}
2014-02-13 03:54:04 +08:00
if ( Z_TYPE ( intern - > u . caching . zchildren ) ! = IS_UNDEF ) {
2003-12-08 16:39:18 +08:00
zval_ptr_dtor ( & intern - > u . caching . zchildren ) ;
2014-02-13 03:54:04 +08:00
ZVAL_UNDEF ( & intern - > u . caching . zchildren ) ;
2003-12-08 16:39:18 +08:00
}
}
2003-12-02 15:18:05 +08:00
}
2014-12-14 06:06:14 +08:00
static inline void spl_dual_it_rewind ( spl_dual_it_object * intern )
2003-12-02 15:18:05 +08:00
{
2014-12-14 06:06:14 +08:00
spl_dual_it_free ( intern ) ;
2003-12-07 03:21:02 +08:00
intern - > current . pos = 0 ;
2016-07-27 08:34:16 +08:00
if ( intern - > inner . iterator & & intern - > inner . iterator - > funcs - > rewind ) {
2014-12-14 06:06:14 +08:00
intern - > inner . iterator - > funcs - > rewind ( intern - > inner . iterator ) ;
2003-12-02 15:18:05 +08:00
}
}
2014-12-14 06:06:14 +08:00
static inline int spl_dual_it_valid ( spl_dual_it_object * intern )
2003-12-02 15:18:05 +08:00
{
2008-09-10 03:44:15 +08:00
if ( ! intern - > inner . iterator ) {
return FAILURE ;
}
2003-12-02 15:18:05 +08:00
/* FAILURE / SUCCESS */
2014-12-14 06:06:14 +08:00
return intern - > inner . iterator - > funcs - > valid ( intern - > inner . iterator ) ;
2003-12-02 15:18:05 +08:00
}
2014-12-14 06:06:14 +08:00
static inline int spl_dual_it_fetch ( spl_dual_it_object * intern , int check_more )
2003-12-02 15:18:05 +08:00
{
2014-02-13 03:54:04 +08:00
zval * data ;
2003-12-10 18:19:43 +08:00
2014-12-14 06:06:14 +08:00
spl_dual_it_free ( intern ) ;
if ( ! check_more | | spl_dual_it_valid ( intern ) = = SUCCESS ) {
data = intern - > inner . iterator - > funcs - > get_current_data ( intern - > inner . iterator ) ;
2014-02-13 03:54:04 +08:00
if ( data ) {
ZVAL_COPY ( & intern - > current . data , data ) ;
2007-10-18 12:41:39 +08:00
}
2013-02-17 02:13:36 +08:00
2003-12-07 03:21:02 +08:00
if ( intern - > inner . iterator - > funcs - > get_current_key ) {
2014-12-14 06:06:14 +08:00
intern - > inner . iterator - > funcs - > get_current_key ( intern - > inner . iterator , & intern - > current . key ) ;
2013-02-17 02:13:36 +08:00
if ( EG ( exception ) ) {
zval_ptr_dtor ( & intern - > current . key ) ;
2014-02-13 03:54:04 +08:00
ZVAL_UNDEF ( & intern - > current . key ) ;
2013-02-17 02:13:36 +08:00
}
2003-12-07 03:21:02 +08:00
} else {
2014-08-26 01:24:55 +08:00
ZVAL_LONG ( & intern - > current . key , intern - > current . pos ) ;
2003-12-07 03:21:02 +08:00
}
2007-10-18 12:41:39 +08:00
return EG ( exception ) ? FAILURE : SUCCESS ;
2003-12-07 03:21:02 +08:00
}
2003-12-10 18:19:43 +08:00
return FAILURE ;
2003-12-02 15:18:05 +08:00
}
2014-12-14 06:06:14 +08:00
static inline void spl_dual_it_next ( spl_dual_it_object * intern , int do_free )
2003-12-02 15:18:05 +08:00
{
2003-12-08 16:39:18 +08:00
if ( do_free ) {
2014-12-14 06:06:14 +08:00
spl_dual_it_free ( intern ) ;
2015-07-05 15:37:49 +08:00
} else if ( ! intern - > inner . iterator ) {
2016-06-12 01:07:28 +08:00
zend_throw_error ( NULL , " The inner constructor wasn't initialized with an iterator instance " ) ;
2015-07-05 15:37:49 +08:00
return ;
2003-12-08 16:39:18 +08:00
}
2014-12-14 06:06:14 +08:00
intern - > inner . iterator - > funcs - > move_forward ( intern - > inner . iterator ) ;
2003-12-07 03:21:02 +08:00
intern - > current . pos + + ;
2003-12-02 15:18:05 +08:00
}
2004-05-06 17:01:31 +08:00
/* {{{ proto void ParentIterator::rewind()
2004-11-01 02:43:00 +08:00
proto void IteratorIterator : : rewind ( )
2004-05-06 17:01:31 +08:00
Rewind the iterator
*/
2003-12-07 03:21:02 +08:00
SPL_METHOD ( dual_it , rewind )
2003-12-02 15:18:05 +08:00
{
spl_dual_it_object * intern ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2015-01-03 17:22:58 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2015-01-03 17:22:58 +08:00
2014-12-14 06:06:14 +08:00
spl_dual_it_rewind ( intern ) ;
spl_dual_it_fetch ( intern , 1 ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-12-02 15:18:05 +08:00
2006-03-06 17:50:44 +08:00
/* {{{ proto bool FilterIterator::valid()
proto bool ParentIterator : : valid ( )
proto bool IteratorIterator : : valid ( )
proto bool NoRewindIterator : : valid ( )
2004-05-06 17:01:31 +08:00
Check whether the current element is valid */
2004-03-09 01:33:31 +08:00
SPL_METHOD ( dual_it , valid )
2003-12-02 15:18:05 +08:00
{
spl_dual_it_object * intern ;
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2015-01-03 17:22:58 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2003-12-02 15:18:05 +08:00
2014-02-13 03:54:04 +08:00
RETURN_BOOL ( Z_TYPE ( intern - > current . data ) ! = IS_UNDEF ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-12-02 15:18:05 +08:00
2004-05-06 17:01:31 +08:00
/* {{{ proto mixed FilterIterator::key()
proto mixed CachingIterator : : key ( )
proto mixed LimitIterator : : key ( )
proto mixed ParentIterator : : key ( )
2004-11-01 02:43:00 +08:00
proto mixed IteratorIterator : : key ( )
proto mixed NoRewindIterator : : key ( )
2004-11-01 08:26:59 +08:00
proto mixed AppendIterator : : key ( )
2004-05-06 17:01:31 +08:00
Get the current key */
2003-12-07 03:21:02 +08:00
SPL_METHOD ( dual_it , key )
2003-12-02 15:18:05 +08:00
{
spl_dual_it_object * intern ;
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2015-01-03 17:22:58 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2003-12-02 15:18:05 +08:00
2014-02-13 03:54:04 +08:00
if ( Z_TYPE ( intern - > current . key ) ! = IS_UNDEF ) {
2015-07-01 07:05:21 +08:00
zval * value = & intern - > current . key ;
ZVAL_DEREF ( value ) ;
ZVAL_COPY ( return_value , value ) ;
} else {
RETURN_NULL ( ) ;
2003-12-02 15:18:05 +08:00
}
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-12-02 15:18:05 +08:00
2004-05-06 17:01:31 +08:00
/* {{{ proto mixed FilterIterator::current()
proto mixed CachingIterator : : current ( )
proto mixed LimitIterator : : current ( )
proto mixed ParentIterator : : current ( )
2004-11-01 02:43:00 +08:00
proto mixed IteratorIterator : : current ( )
proto mixed NoRewindIterator : : current ( )
2004-11-01 08:26:59 +08:00
proto mixed AppendIterator : : current ( )
2004-05-06 17:01:31 +08:00
Get the current element value */
2003-12-07 03:21:02 +08:00
SPL_METHOD ( dual_it , current )
2003-12-02 15:18:05 +08:00
{
spl_dual_it_object * intern ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2003-12-02 15:18:05 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2003-12-02 15:18:05 +08:00
2014-02-13 03:54:04 +08:00
if ( Z_TYPE ( intern - > current . data ) ! = IS_UNDEF ) {
2015-07-01 07:05:21 +08:00
zval * value = & intern - > current . data ;
ZVAL_DEREF ( value ) ;
ZVAL_COPY ( return_value , value ) ;
2003-12-02 15:18:05 +08:00
} else {
RETURN_NULL ( ) ;
}
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-12-02 15:18:05 +08:00
2004-05-06 17:01:31 +08:00
/* {{{ proto void ParentIterator::next()
2004-11-01 02:43:00 +08:00
proto void IteratorIterator : : next ( )
proto void NoRewindIterator : : next ( )
2004-05-06 17:01:31 +08:00
Move the iterator forward */
2003-12-07 03:21:02 +08:00
SPL_METHOD ( dual_it , next )
{
spl_dual_it_object * intern ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2003-12-07 03:21:02 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2003-12-07 03:21:02 +08:00
2014-12-14 06:06:14 +08:00
spl_dual_it_next ( intern , 1 ) ;
spl_dual_it_fetch ( intern , 1 ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-12-07 03:21:02 +08:00
2014-12-14 06:06:14 +08:00
static inline void spl_filter_it_fetch ( zval * zthis , spl_dual_it_object * intern )
2003-12-07 03:21:02 +08:00
{
2014-02-13 03:54:04 +08:00
zval retval ;
2003-12-07 03:21:02 +08:00
2014-12-14 06:06:14 +08:00
while ( spl_dual_it_fetch ( intern , 1 ) = = SUCCESS ) {
2014-02-13 03:54:04 +08:00
zend_call_method_with_0_params ( zthis , intern - > std . ce , NULL , " accept " , & retval ) ;
if ( Z_TYPE ( retval ) ! = IS_UNDEF ) {
2014-12-14 06:06:14 +08:00
if ( zend_is_true ( & retval ) ) {
2004-04-28 01:12:11 +08:00
zval_ptr_dtor ( & retval ) ;
return ;
}
2003-12-07 03:21:02 +08:00
zval_ptr_dtor ( & retval ) ;
}
2006-05-16 16:21:08 +08:00
if ( EG ( exception ) ) {
return ;
}
2014-12-14 06:06:14 +08:00
intern - > inner . iterator - > funcs - > move_forward ( intern - > inner . iterator ) ;
2003-12-07 03:21:02 +08:00
}
2014-12-14 06:06:14 +08:00
spl_dual_it_free ( intern ) ;
2003-12-07 03:21:02 +08:00
}
2014-12-14 06:06:14 +08:00
static inline void spl_filter_it_rewind ( zval * zthis , spl_dual_it_object * intern )
2003-12-10 18:19:43 +08:00
{
2014-12-14 06:06:14 +08:00
spl_dual_it_rewind ( intern ) ;
spl_filter_it_fetch ( zthis , intern ) ;
2003-12-10 18:19:43 +08:00
}
2014-12-14 06:06:14 +08:00
static inline void spl_filter_it_next ( zval * zthis , spl_dual_it_object * intern )
2003-12-10 18:19:43 +08:00
{
2014-12-14 06:06:14 +08:00
spl_dual_it_next ( intern , 1 ) ;
spl_filter_it_fetch ( zthis , intern ) ;
2003-12-10 18:19:43 +08:00
}
2004-05-06 17:01:31 +08:00
/* {{{ proto void FilterIterator::rewind()
Rewind the iterator */
2003-12-07 03:21:02 +08:00
SPL_METHOD ( FilterIterator , rewind )
{
spl_dual_it_object * intern ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2003-12-07 03:21:02 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2014-12-14 06:06:14 +08:00
spl_filter_it_rewind ( getThis ( ) , intern ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-12-07 03:21:02 +08:00
2004-05-06 17:01:31 +08:00
/* {{{ proto void FilterIterator::next()
Move the iterator forward */
2003-12-02 15:18:05 +08:00
SPL_METHOD ( FilterIterator , next )
{
spl_dual_it_object * intern ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2003-12-02 15:18:05 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2014-12-14 06:06:14 +08:00
spl_filter_it_next ( getThis ( ) , intern ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-12-02 15:18:05 +08:00
2015-06-24 05:46:07 +08:00
/* {{{ proto void RecursiveCallbackFilterIterator::__construct(RecursiveIterator it, callback func)
2011-03-28 04:13:27 +08:00
Create a RecursiveCallbackFilterIterator from a RecursiveIterator */
SPL_METHOD ( RecursiveCallbackFilterIterator , __construct )
{
spl_dual_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , spl_ce_RecursiveCallbackFilterIterator , spl_ce_RecursiveIterator , DIT_RecursiveCallbackFilterIterator ) ;
} /* }}} */
2006-03-06 17:50:44 +08:00
/* {{{ proto void RecursiveFilterIterator::__construct(RecursiveIterator it)
2005-09-15 11:33:04 +08:00
Create a RecursiveFilterIterator from a RecursiveIterator */
SPL_METHOD ( RecursiveFilterIterator , __construct )
{
2006-03-06 01:39:49 +08:00
spl_dual_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , spl_ce_RecursiveFilterIterator , spl_ce_RecursiveIterator , DIT_RecursiveFilterIterator ) ;
2005-09-15 11:33:04 +08:00
} /* }}} */
2006-03-06 17:50:44 +08:00
/* {{{ proto bool RecursiveFilterIterator::hasChildren()
2005-09-15 11:33:04 +08:00
Check whether the inner iterator ' s current element has children */
SPL_METHOD ( RecursiveFilterIterator , hasChildren )
{
spl_dual_it_object * intern ;
2014-02-13 03:54:04 +08:00
zval retval ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2005-09-15 11:33:04 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2005-09-15 11:33:04 +08:00
2014-02-28 15:03:43 +08:00
zend_call_method_with_0_params ( & intern - > inner . zobject , intern - > inner . ce , NULL , " haschildren " , & retval ) ;
2014-02-13 03:54:04 +08:00
if ( Z_TYPE ( retval ) ! = IS_UNDEF ) {
RETURN_ZVAL ( & retval , 0 , 1 ) ;
2006-05-22 02:13:37 +08:00
} else {
RETURN_FALSE ;
}
2005-09-15 11:33:04 +08:00
} /* }}} */
/* {{{ proto RecursiveFilterIterator RecursiveFilterIterator::getChildren()
Return the inner iterator ' s children contained in a RecursiveFilterIterator */
SPL_METHOD ( RecursiveFilterIterator , getChildren )
{
spl_dual_it_object * intern ;
2014-02-13 03:54:04 +08:00
zval retval ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2005-09-15 11:33:04 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2005-09-15 11:33:04 +08:00
2014-02-28 15:03:43 +08:00
zend_call_method_with_0_params ( & intern - > inner . zobject , intern - > inner . ce , NULL , " getchildren " , & retval ) ;
2014-02-13 03:54:04 +08:00
if ( ! EG ( exception ) & & Z_TYPE ( retval ) ! = IS_UNDEF ) {
2014-12-14 06:06:14 +08:00
spl_instantiate_arg_ex1 ( Z_OBJCE_P ( getThis ( ) ) , return_value , & retval ) ;
2006-05-22 02:13:37 +08:00
}
2014-02-13 03:54:04 +08:00
zval_ptr_dtor ( & retval ) ;
2005-09-15 11:33:04 +08:00
} /* }}} */
2011-03-28 04:13:27 +08:00
/* {{{ proto RecursiveCallbackFilterIterator RecursiveCallbackFilterIterator::getChildren()
Return the inner iterator ' s children contained in a RecursiveCallbackFilterIterator */
SPL_METHOD ( RecursiveCallbackFilterIterator , getChildren )
{
spl_dual_it_object * intern ;
2014-02-13 03:54:04 +08:00
zval retval ;
2015-01-03 17:22:58 +08:00
2011-03-28 04:13:27 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2014-07-27 09:00:16 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2011-03-28 04:13:27 +08:00
2014-02-28 15:03:43 +08:00
zend_call_method_with_0_params ( & intern - > inner . zobject , intern - > inner . ce , NULL , " getchildren " , & retval ) ;
2014-02-13 03:54:04 +08:00
if ( ! EG ( exception ) & & Z_TYPE ( retval ) ! = IS_UNDEF ) {
2014-12-14 06:06:14 +08:00
spl_instantiate_arg_ex2 ( Z_OBJCE_P ( getThis ( ) ) , return_value , & retval , & intern - > u . cbfilter - > fci . function_name ) ;
2011-03-28 04:13:27 +08:00
}
2014-02-13 03:54:04 +08:00
zval_ptr_dtor ( & retval ) ;
2011-03-28 04:13:27 +08:00
} /* }}} */
2006-03-06 17:50:44 +08:00
/* {{{ proto void ParentIterator::__construct(RecursiveIterator it)
2004-05-06 17:01:31 +08:00
Create a ParentIterator from a RecursiveIterator */
2003-12-02 15:18:05 +08:00
SPL_METHOD ( ParentIterator , __construct )
{
2006-03-06 01:39:49 +08:00
spl_dual_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , spl_ce_ParentIterator , spl_ce_RecursiveIterator , DIT_ParentIterator ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-12-02 15:18:05 +08:00
2006-05-10 08:03:38 +08:00
# if HAVE_PCRE || HAVE_BUNDLED_PCRE
2015-01-03 17:22:58 +08:00
/* {{{ proto void RegexIterator::__construct(Iterator it, string regex [, int mode [, int flags [, int preg_flags]]])
2006-05-11 00:50:57 +08:00
Create an RegexIterator from another iterator and a regular expression */
SPL_METHOD ( RegexIterator , __construct )
2006-05-10 08:03:38 +08:00
{
2006-05-11 00:50:57 +08:00
spl_dual_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , spl_ce_RegexIterator , zend_ce_iterator , DIT_RegexIterator ) ;
2006-05-10 08:03:38 +08:00
} /* }}} */
2011-03-28 04:13:27 +08:00
/* {{{ proto bool CallbackFilterIterator::accept()
Calls the callback with the current value , the current key and the inner iterator as arguments */
SPL_METHOD ( CallbackFilterIterator , accept )
{
2014-03-15 16:33:31 +08:00
spl_dual_it_object * intern = Z_SPLDUAL_IT_P ( getThis ( ) ) ;
2011-03-28 04:13:27 +08:00
zend_fcall_info * fci = & intern - > u . cbfilter - > fci ;
zend_fcall_info_cache * fcc = & intern - > u . cbfilter - > fcc ;
2014-02-13 03:54:04 +08:00
zval params [ 3 ] ;
2011-03-28 04:13:27 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2014-02-13 03:54:04 +08:00
if ( Z_TYPE ( intern - > current . data ) = = IS_UNDEF | | Z_TYPE ( intern - > current . key ) = = IS_UNDEF ) {
2011-03-28 04:13:27 +08:00
RETURN_FALSE ;
}
2014-02-13 03:54:04 +08:00
ZVAL_COPY_VALUE ( & params [ 0 ] , & intern - > current . data ) ;
ZVAL_COPY_VALUE ( & params [ 1 ] , & intern - > current . key ) ;
2014-02-28 15:03:43 +08:00
ZVAL_COPY_VALUE ( & params [ 2 ] , & intern - > inner . zobject ) ;
2011-03-28 04:13:27 +08:00
2016-04-19 10:59:10 +08:00
fci - > retval = return_value ;
2011-03-28 04:13:27 +08:00
fci - > param_count = 3 ;
fci - > params = params ;
fci - > no_separation = 0 ;
2016-04-19 10:59:10 +08:00
if ( zend_call_function ( fci , fcc ) ! = SUCCESS | | Z_ISUNDEF_P ( return_value ) ) {
2011-03-28 04:13:27 +08:00
RETURN_FALSE ;
}
2016-04-19 10:59:10 +08:00
2011-03-28 04:13:27 +08:00
if ( EG ( exception ) ) {
2016-04-19 10:59:10 +08:00
RETURN_NULL ( ) ;
2011-03-28 04:13:27 +08:00
}
2016-04-19 10:59:10 +08:00
/* zend_call_function may change args to IS_REF */
ZVAL_COPY_VALUE ( & intern - > current . data , & params [ 0 ] ) ;
ZVAL_COPY_VALUE ( & intern - > current . key , & params [ 1 ] ) ;
2011-03-28 04:13:27 +08:00
}
/* }}} */
2006-05-11 00:50:57 +08:00
/* {{{ proto bool RegexIterator::accept()
2006-05-10 08:03:38 +08:00
Match ( string ) current ( ) against regular expression */
2006-05-11 00:50:57 +08:00
SPL_METHOD ( RegexIterator , accept )
2006-05-10 08:03:38 +08:00
{
2011-10-30 07:17:18 +08:00
spl_dual_it_object * intern ;
2015-02-10 18:30:25 +08:00
zend_string * result , * subject ;
int count = 0 ;
zval zcount , * replacement , tmp_replacement , rv ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2015-01-03 17:22:58 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2015-01-03 17:22:58 +08:00
2014-02-13 03:54:04 +08:00
if ( Z_TYPE ( intern - > current . data ) = = IS_UNDEF ) {
2008-09-22 21:09:09 +08:00
RETURN_FALSE ;
}
2014-10-06 09:40:39 +08:00
2006-05-10 08:03:38 +08:00
if ( intern - > u . regex . flags & REGIT_USE_KEY ) {
2015-02-10 18:30:25 +08:00
subject = zval_get_string ( & intern - > current . key ) ;
2006-05-10 08:03:38 +08:00
} else {
2016-09-22 18:48:38 +08:00
if ( Z_TYPE ( intern - > current . data ) = = IS_ARRAY ) {
2016-09-20 00:42:07 +08:00
RETURN_FALSE ;
}
2015-02-10 18:30:25 +08:00
subject = zval_get_string ( & intern - > current . data ) ;
2013-02-17 02:13:36 +08:00
}
2006-07-17 05:12:32 +08:00
switch ( intern - > u . regex . mode )
{
2014-03-15 16:33:31 +08:00
case REGIT_MODE_MAX : /* won't happen but makes compiler happy */
case REGIT_MODE_MATCH :
2015-11-06 11:37:17 +08:00
# ifdef PCRE_EXTRA_MARK
if ( intern - > u . regex . pce - > extra ) {
intern - > u . regex . pce - > extra - > flags & = ~ PCRE_EXTRA_MARK ;
}
# endif
2015-06-30 09:05:24 +08:00
count = pcre_exec ( intern - > u . regex . pce - > re , intern - > u . regex . pce - > extra , ZSTR_VAL ( subject ) , ZSTR_LEN ( subject ) , 0 , 0 , NULL , 0 ) ;
2014-03-15 16:33:31 +08:00
RETVAL_BOOL ( count > = 0 ) ;
break ;
case REGIT_MODE_ALL_MATCHES :
case REGIT_MODE_GET_MATCH :
2006-07-21 06:54:21 +08:00
zval_ptr_dtor ( & intern - > current . data ) ;
2014-03-15 16:33:31 +08:00
ZVAL_UNDEF ( & intern - > current . data ) ;
2015-06-30 09:05:24 +08:00
php_pcre_match_impl ( intern - > u . regex . pce , ZSTR_VAL ( subject ) , ZSTR_LEN ( subject ) , & zcount ,
2014-12-14 06:06:14 +08:00
& intern - > current . data , intern - > u . regex . mode = = REGIT_MODE_ALL_MATCHES , intern - > u . regex . use_flags , intern - > u . regex . preg_flags , 0 ) ;
2014-10-14 23:00:17 +08:00
RETVAL_BOOL ( Z_LVAL ( zcount ) > 0 ) ;
2014-03-15 16:33:31 +08:00
break ;
2011-09-12 21:21:57 +08:00
2014-03-15 16:33:31 +08:00
case REGIT_MODE_SPLIT :
zval_ptr_dtor ( & intern - > current . data ) ;
ZVAL_UNDEF ( & intern - > current . data ) ;
2017-06-28 05:43:55 +08:00
php_pcre_split_impl ( intern - > u . regex . pce , subject , & intern - > current . data , - 1 , intern - > u . regex . preg_flags ) ;
2014-03-15 16:33:31 +08:00
count = zend_hash_num_elements ( Z_ARRVAL ( intern - > current . data ) ) ;
RETVAL_BOOL ( count > 1 ) ;
break ;
case REGIT_MODE_REPLACE :
2015-01-22 16:50:42 +08:00
replacement = zend_read_property ( intern - > std . ce , getThis ( ) , " replacement " , sizeof ( " replacement " ) - 1 , 1 , & rv ) ;
2014-03-15 16:33:31 +08:00
if ( Z_TYPE_P ( replacement ) ! = IS_STRING ) {
2015-06-12 01:41:43 +08:00
ZVAL_COPY ( & tmp_replacement , replacement ) ;
2014-03-15 16:33:31 +08:00
convert_to_string ( & tmp_replacement ) ;
replacement = & tmp_replacement ;
}
2017-06-07 18:50:16 +08:00
result = php_pcre_replace_impl ( intern - > u . regex . pce , subject , ZSTR_VAL ( subject ) , ZSTR_LEN ( subject ) , Z_STR_P ( replacement ) , - 1 , & count ) ;
2015-01-03 17:22:58 +08:00
2014-03-15 16:33:31 +08:00
if ( intern - > u . regex . flags & REGIT_USE_KEY ) {
zval_ptr_dtor ( & intern - > current . key ) ;
2014-03-16 08:44:07 +08:00
ZVAL_STR ( & intern - > current . key , result ) ;
2014-03-15 16:33:31 +08:00
} else {
zval_ptr_dtor ( & intern - > current . data ) ;
2014-03-16 08:44:07 +08:00
ZVAL_STR ( & intern - > current . data , result ) ;
2014-03-15 16:33:31 +08:00
}
if ( replacement = = & tmp_replacement ) {
2015-06-12 17:33:23 +08:00
zval_ptr_dtor ( replacement ) ;
2014-03-15 16:33:31 +08:00
}
RETVAL_BOOL ( count > 0 ) ;
2006-05-10 08:03:38 +08:00
}
2007-05-11 08:15:25 +08:00
if ( intern - > u . regex . flags & REGIT_INVERTED ) {
2014-04-30 22:32:42 +08:00
RETVAL_BOOL ( Z_TYPE_P ( return_value ) ! = IS_TRUE ) ;
2007-05-11 08:15:25 +08:00
}
2015-02-10 18:30:25 +08:00
zend_string_release ( subject ) ;
2006-05-10 08:03:38 +08:00
} /* }}} */
2011-01-06 10:32:02 +08:00
/* {{{ proto string RegexIterator::getRegex()
Returns current regular expression */
SPL_METHOD ( RegexIterator , getRegex )
{
2014-03-15 16:33:31 +08:00
spl_dual_it_object * intern = Z_SPLDUAL_IT_P ( getThis ( ) ) ;
2011-01-06 10:32:02 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2015-03-12 21:53:51 +08:00
RETURN_STR_COPY ( intern - > u . regex . regex ) ;
2011-01-06 10:32:02 +08:00
} /* }}} */
2006-07-22 04:14:31 +08:00
/* {{{ proto bool RegexIterator::getMode()
Returns current operation mode */
SPL_METHOD ( RegexIterator , getMode )
{
2011-10-30 07:17:18 +08:00
spl_dual_it_object * intern ;
2006-07-22 04:14:31 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2015-01-03 17:22:58 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2015-01-03 17:22:58 +08:00
2014-08-26 01:24:55 +08:00
RETURN_LONG ( intern - > u . regex . mode ) ;
2006-07-22 04:14:31 +08:00
} /* }}} */
/* {{{ proto bool RegexIterator::setMode(int new_mode)
Set new operation mode */
SPL_METHOD ( RegexIterator , setMode )
{
2011-10-30 07:17:18 +08:00
spl_dual_it_object * intern ;
2014-08-26 01:24:55 +08:00
zend_long mode ;
2006-07-22 04:14:31 +08:00
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " l " , & mode ) = = FAILURE ) {
2006-07-22 04:14:31 +08:00
return ;
}
if ( mode < 0 | | mode > = REGIT_MODE_MAX ) {
2016-06-21 21:00:37 +08:00
zend_throw_exception_ex ( spl_ce_InvalidArgumentException , 0 , " Illegal mode " ZEND_LONG_FMT , mode ) ;
2006-11-07 23:19:11 +08:00
return ; /* NULL */
2006-07-22 04:14:31 +08:00
}
2015-01-03 17:22:58 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2006-07-22 04:14:31 +08:00
intern - > u . regex . mode = mode ;
} /* }}} */
/* {{{ proto bool RegexIterator::getFlags()
Returns current operation flags */
SPL_METHOD ( RegexIterator , getFlags )
{
2011-10-30 07:17:18 +08:00
spl_dual_it_object * intern ;
2006-07-22 04:14:31 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2015-01-03 17:22:58 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2015-01-03 17:22:58 +08:00
2014-08-26 01:24:55 +08:00
RETURN_LONG ( intern - > u . regex . flags ) ;
2006-07-22 04:14:31 +08:00
} /* }}} */
/* {{{ proto bool RegexIterator::setFlags(int new_flags)
Set operation flags */
SPL_METHOD ( RegexIterator , setFlags )
{
2011-10-30 07:17:18 +08:00
spl_dual_it_object * intern ;
2014-08-26 01:24:55 +08:00
zend_long flags ;
2006-07-22 04:14:31 +08:00
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " l " , & flags ) = = FAILURE ) {
2006-07-22 04:14:31 +08:00
return ;
}
2015-01-03 17:22:58 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2006-07-22 04:14:31 +08:00
intern - > u . regex . flags = flags ;
} /* }}} */
/* {{{ proto bool RegexIterator::getFlags()
Returns current PREG flags ( if in use or NULL ) */
SPL_METHOD ( RegexIterator , getPregFlags )
{
2011-10-30 07:17:18 +08:00
spl_dual_it_object * intern ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2015-01-03 17:22:58 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2006-07-22 04:14:31 +08:00
if ( intern - > u . regex . use_flags ) {
2014-08-26 01:24:55 +08:00
RETURN_LONG ( intern - > u . regex . preg_flags ) ;
2006-07-22 04:14:31 +08:00
} else {
return ;
}
} /* }}} */
2006-11-07 07:20:11 +08:00
/* {{{ proto bool RegexIterator::setPregFlags(int new_flags)
2006-07-22 04:14:31 +08:00
Set PREG flags */
SPL_METHOD ( RegexIterator , setPregFlags )
{
2011-10-30 07:17:18 +08:00
spl_dual_it_object * intern ;
2014-08-26 01:24:55 +08:00
zend_long preg_flags ;
2006-07-22 04:14:31 +08:00
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " l " , & preg_flags ) = = FAILURE ) {
2006-07-22 04:14:31 +08:00
return ;
}
2015-01-03 17:22:58 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2006-07-22 04:14:31 +08:00
intern - > u . regex . preg_flags = preg_flags ;
intern - > u . regex . use_flags = 1 ;
} /* }}} */
2015-01-03 17:22:58 +08:00
/* {{{ proto void RecursiveRegexIterator::__construct(RecursiveIterator it, string regex [, int mode [, int flags [, int preg_flags]]])
2006-05-11 00:50:57 +08:00
Create an RecursiveRegexIterator from another recursive iterator and a regular expression */
SPL_METHOD ( RecursiveRegexIterator , __construct )
2006-05-10 08:03:38 +08:00
{
2006-05-11 00:50:57 +08:00
spl_dual_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , spl_ce_RecursiveRegexIterator , spl_ce_RecursiveIterator , DIT_RecursiveRegexIterator ) ;
2006-05-10 08:03:38 +08:00
} /* }}} */
2006-05-22 02:13:37 +08:00
/* {{{ proto RecursiveRegexIterator RecursiveRegexIterator::getChildren()
Return the inner iterator ' s children contained in a RecursiveRegexIterator */
SPL_METHOD ( RecursiveRegexIterator , getChildren )
{
spl_dual_it_object * intern ;
2014-10-14 23:00:17 +08:00
zval retval ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2006-05-22 02:13:37 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2006-05-22 02:13:37 +08:00
2014-02-28 15:03:43 +08:00
zend_call_method_with_0_params ( & intern - > inner . zobject , intern - > inner . ce , NULL , " getchildren " , & retval ) ;
2006-05-22 02:13:37 +08:00
if ( ! EG ( exception ) ) {
2014-10-14 23:00:17 +08:00
zval args [ 5 ] ;
ZVAL_COPY ( & args [ 0 ] , & retval ) ;
ZVAL_STR_COPY ( & args [ 1 ] , intern - > u . regex . regex ) ;
ZVAL_LONG ( & args [ 2 ] , intern - > u . regex . mode ) ;
ZVAL_LONG ( & args [ 3 ] , intern - > u . regex . flags ) ;
ZVAL_LONG ( & args [ 4 ] , intern - > u . regex . preg_flags ) ;
2014-12-14 06:06:14 +08:00
spl_instantiate_arg_n ( Z_OBJCE_P ( getThis ( ) ) , return_value , 5 , args ) ;
2014-10-14 23:00:17 +08:00
2015-04-16 02:01:16 +08:00
zval_ptr_dtor ( & args [ 0 ] ) ;
2014-10-14 23:00:17 +08:00
zval_ptr_dtor ( & args [ 1 ] ) ;
2006-05-22 02:13:37 +08:00
}
2014-02-13 03:54:04 +08:00
zval_ptr_dtor ( & retval ) ;
2006-05-22 02:13:37 +08:00
} /* }}} */
2014-10-06 09:40:39 +08:00
SPL_METHOD ( RecursiveRegexIterator , accept )
{
spl_dual_it_object * intern ;
2015-01-03 17:22:58 +08:00
2014-10-06 09:40:39 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2015-01-03 17:22:58 +08:00
2014-10-06 09:40:39 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2015-01-03 17:22:58 +08:00
2014-10-14 23:00:17 +08:00
if ( Z_TYPE ( intern - > current . data ) = = IS_UNDEF ) {
2014-10-06 09:40:39 +08:00
RETURN_FALSE ;
2014-10-14 23:00:17 +08:00
} else if ( Z_TYPE ( intern - > current . data ) = = IS_ARRAY ) {
RETURN_BOOL ( zend_hash_num_elements ( Z_ARRVAL ( intern - > current . data ) ) > 0 ) ;
2014-10-06 09:40:39 +08:00
}
2014-10-14 23:00:17 +08:00
zend_call_method_with_0_params ( getThis ( ) , spl_ce_RegexIterator , NULL , " accept " , return_value ) ;
2014-10-06 09:40:39 +08:00
}
2006-05-10 08:03:38 +08:00
# endif
2010-07-08 05:55:17 +08:00
/* {{{ spl_dual_it_dtor */
2014-12-14 06:06:14 +08:00
static void spl_dual_it_dtor ( zend_object * _object )
2003-12-02 15:18:05 +08:00
{
2014-03-15 16:33:31 +08:00
spl_dual_it_object * object = spl_dual_it_from_obj ( _object ) ;
2003-12-02 15:18:05 +08:00
2010-07-08 05:55:17 +08:00
/* call standard dtor */
2014-12-14 06:06:14 +08:00
zend_objects_destroy_object ( _object ) ;
2010-07-08 05:55:17 +08:00
2014-12-14 06:06:14 +08:00
spl_dual_it_free ( object ) ;
2003-12-02 15:18:05 +08:00
2003-12-07 03:21:02 +08:00
if ( object - > inner . iterator ) {
2014-12-14 06:06:14 +08:00
zend_iterator_dtor ( object - > inner . iterator ) ;
2003-12-07 03:21:02 +08:00
}
2010-07-08 05:55:17 +08:00
}
/* }}} */
/* {{{ spl_dual_it_free_storage */
2014-12-14 06:06:14 +08:00
static void spl_dual_it_free_storage ( zend_object * _object )
2010-07-08 05:55:17 +08:00
{
2014-03-15 16:33:31 +08:00
spl_dual_it_object * object = spl_dual_it_from_obj ( _object ) ;
2010-07-08 05:55:17 +08:00
2003-12-02 15:18:05 +08:00
2014-05-03 16:06:27 +08:00
if ( ! Z_ISUNDEF ( object - > inner . zobject ) ) {
2014-02-28 15:03:43 +08:00
zval_ptr_dtor ( & object - > inner . zobject ) ;
2003-12-10 18:19:43 +08:00
}
2015-01-03 17:22:58 +08:00
2004-11-01 08:26:59 +08:00
if ( object - > dit_type = = DIT_AppendIterator ) {
2014-12-14 06:06:14 +08:00
zend_iterator_dtor ( object - > u . append . iterator ) ;
2014-02-13 03:54:04 +08:00
if ( Z_TYPE ( object - > u . append . zarrayit ) ! = IS_UNDEF ) {
2006-05-10 08:03:38 +08:00
zval_ptr_dtor ( & object - > u . append . zarrayit ) ;
}
2004-11-01 08:26:59 +08:00
}
2003-12-10 18:19:43 +08:00
2006-05-10 08:03:38 +08:00
if ( object - > dit_type = = DIT_CachingIterator | | object - > dit_type = = DIT_RecursiveCachingIterator ) {
2015-09-25 03:39:59 +08:00
zval_ptr_dtor ( & object - > u . caching . zcache ) ;
2006-05-10 08:03:38 +08:00
}
# if HAVE_PCRE || HAVE_BUNDLED_PCRE
2006-05-11 00:50:57 +08:00
if ( object - > dit_type = = DIT_RegexIterator | | object - > dit_type = = DIT_RecursiveRegexIterator ) {
2006-05-10 08:03:38 +08:00
if ( object - > u . regex . pce ) {
object - > u . regex . pce - > refcount - - ;
}
2006-05-22 02:13:37 +08:00
if ( object - > u . regex . regex ) {
2014-08-26 01:24:55 +08:00
zend_string_release ( object - > u . regex . regex ) ;
2006-05-22 02:13:37 +08:00
}
2006-05-10 08:03:38 +08:00
}
# endif
2011-03-28 04:13:27 +08:00
if ( object - > dit_type = = DIT_CallbackFilterIterator | | object - > dit_type = = DIT_RecursiveCallbackFilterIterator ) {
if ( object - > u . cbfilter ) {
2014-02-28 17:12:53 +08:00
_spl_cbfilter_it_intern * cbfilter = object - > u . cbfilter ;
object - > u . cbfilter = NULL ;
zval_ptr_dtor ( & cbfilter - > fci . function_name ) ;
2014-03-28 06:11:22 +08:00
if ( cbfilter - > fci . object ) {
OBJ_RELEASE ( cbfilter - > fci . object ) ;
2011-03-28 04:13:27 +08:00
}
2014-02-28 17:12:53 +08:00
efree ( cbfilter ) ;
2011-03-28 04:13:27 +08:00
}
}
2014-12-14 06:06:14 +08:00
zend_object_std_dtor ( & object - > std ) ;
2003-12-02 15:18:05 +08:00
}
/* }}} */
2003-12-08 16:39:18 +08:00
/* {{{ spl_dual_it_new */
2014-12-14 06:06:14 +08:00
static zend_object * spl_dual_it_new ( zend_class_entry * class_type )
2003-12-02 15:18:05 +08:00
{
spl_dual_it_object * intern ;
2015-02-04 20:24:13 +08:00
intern = ecalloc ( 1 , sizeof ( spl_dual_it_object ) + zend_object_properties_size ( class_type ) ) ;
2006-03-06 01:39:49 +08:00
intern - > dit_type = DIT_Unknown ;
2003-12-02 15:18:05 +08:00
2014-12-14 06:06:14 +08:00
zend_object_std_init ( & intern - > std , class_type ) ;
2010-05-24 22:11:39 +08:00
object_properties_init ( & intern - > std , class_type ) ;
2003-12-02 15:18:05 +08:00
2014-02-12 22:15:08 +08:00
intern - > std . handlers = & spl_handlers_dual_it ;
return & intern - > std ;
2003-11-09 22:05:36 +08:00
}
/* }}} */
2015-01-03 17:22:58 +08:00
ZEND_BEGIN_ARG_INFO ( arginfo_filter_it___construct , 0 )
2004-03-29 01:04:11 +08:00
ZEND_ARG_OBJ_INFO ( 0 , iterator , Iterator , 0 )
2003-12-02 15:18:05 +08:00
ZEND_END_ARG_INFO ( ) ;
2007-09-28 02:00:48 +08:00
static const zend_function_entry spl_funcs_FilterIterator [ ] = {
2006-03-06 01:39:49 +08:00
SPL_ME ( FilterIterator , __construct , arginfo_filter_it___construct , ZEND_ACC_PUBLIC )
2009-07-05 04:31:27 +08:00
SPL_ME ( FilterIterator , rewind , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , valid , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , key , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , current , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( FilterIterator , next , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , getInnerIterator , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ABSTRACT_ME ( FilterIterator , accept , arginfo_recursive_it_void )
2011-07-25 19:35:02 +08:00
PHP_FE_END
2003-12-02 15:18:05 +08:00
} ;
2015-01-03 17:22:58 +08:00
ZEND_BEGIN_ARG_INFO ( arginfo_callback_filter_it___construct , 0 )
2011-03-28 04:13:27 +08:00
ZEND_ARG_OBJ_INFO ( 0 , iterator , Iterator , 0 )
ZEND_ARG_INFO ( 0 , callback )
ZEND_END_ARG_INFO ( ) ;
static const zend_function_entry spl_funcs_CallbackFilterIterator [ ] = {
SPL_ME ( CallbackFilterIterator , __construct , arginfo_callback_filter_it___construct , ZEND_ACC_PUBLIC )
SPL_ME ( CallbackFilterIterator , accept , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2011-07-25 19:35:02 +08:00
PHP_FE_END
2011-03-28 04:13:27 +08:00
} ;
2015-01-03 17:22:58 +08:00
ZEND_BEGIN_ARG_INFO ( arginfo_recursive_callback_filter_it___construct , 0 )
2011-03-28 04:13:27 +08:00
ZEND_ARG_OBJ_INFO ( 0 , iterator , RecursiveIterator , 0 )
ZEND_ARG_INFO ( 0 , callback )
ZEND_END_ARG_INFO ( ) ;
static const zend_function_entry spl_funcs_RecursiveCallbackFilterIterator [ ] = {
SPL_ME ( RecursiveCallbackFilterIterator , __construct , arginfo_recursive_callback_filter_it___construct , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveFilterIterator , hasChildren , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveCallbackFilterIterator , getChildren , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2011-07-25 19:35:02 +08:00
PHP_FE_END
2011-03-28 04:13:27 +08:00
} ;
2015-01-03 17:22:58 +08:00
ZEND_BEGIN_ARG_INFO ( arginfo_parent_it___construct , 0 )
2005-09-15 11:33:04 +08:00
ZEND_ARG_OBJ_INFO ( 0 , iterator , RecursiveIterator , 0 )
2003-12-02 15:18:05 +08:00
ZEND_END_ARG_INFO ( ) ;
2007-09-28 02:00:48 +08:00
static const zend_function_entry spl_funcs_RecursiveFilterIterator [ ] = {
2005-09-15 11:33:04 +08:00
SPL_ME ( RecursiveFilterIterator , __construct , arginfo_parent_it___construct , ZEND_ACC_PUBLIC )
2009-07-05 04:31:27 +08:00
SPL_ME ( RecursiveFilterIterator , hasChildren , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveFilterIterator , getChildren , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2011-07-25 19:35:02 +08:00
PHP_FE_END
2005-09-15 11:33:04 +08:00
} ;
2007-09-28 02:00:48 +08:00
static const zend_function_entry spl_funcs_ParentIterator [ ] = {
2004-03-10 01:35:18 +08:00
SPL_ME ( ParentIterator , __construct , arginfo_parent_it___construct , ZEND_ACC_PUBLIC )
2009-07-05 04:31:27 +08:00
SPL_MA ( ParentIterator , accept , RecursiveFilterIterator , hasChildren , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2011-07-25 19:35:02 +08:00
PHP_FE_END
2003-12-07 03:21:02 +08:00
} ;
2006-05-10 08:03:38 +08:00
# if HAVE_PCRE || HAVE_BUNDLED_PCRE
2015-01-03 17:22:58 +08:00
ZEND_BEGIN_ARG_INFO_EX ( arginfo_regex_it___construct , 0 , 0 , 2 )
2006-05-10 08:03:38 +08:00
ZEND_ARG_OBJ_INFO ( 0 , iterator , Iterator , 0 )
ZEND_ARG_INFO ( 0 , regex )
2006-07-17 05:12:32 +08:00
ZEND_ARG_INFO ( 0 , mode )
2006-07-21 06:54:21 +08:00
ZEND_ARG_INFO ( 0 , flags )
2006-07-17 05:12:32 +08:00
ZEND_ARG_INFO ( 0 , preg_flags )
2006-05-10 08:03:38 +08:00
ZEND_END_ARG_INFO ( ) ;
2015-01-03 17:22:58 +08:00
ZEND_BEGIN_ARG_INFO_EX ( arginfo_regex_it_set_mode , 0 , 0 , 1 )
2006-07-22 04:14:31 +08:00
ZEND_ARG_INFO ( 0 , mode )
ZEND_END_ARG_INFO ( ) ;
2015-01-03 17:22:58 +08:00
ZEND_BEGIN_ARG_INFO_EX ( arginfo_regex_it_set_flags , 0 , 0 , 1 )
2006-07-22 04:14:31 +08:00
ZEND_ARG_INFO ( 0 , flags )
ZEND_END_ARG_INFO ( ) ;
2015-01-03 17:22:58 +08:00
ZEND_BEGIN_ARG_INFO_EX ( arginfo_regex_it_set_preg_flags , 0 , 0 , 1 )
2006-07-22 04:14:31 +08:00
ZEND_ARG_INFO ( 0 , preg_flags )
ZEND_END_ARG_INFO ( ) ;
2007-09-28 02:00:48 +08:00
static const zend_function_entry spl_funcs_RegexIterator [ ] = {
2006-07-22 04:14:31 +08:00
SPL_ME ( RegexIterator , __construct , arginfo_regex_it___construct , ZEND_ACC_PUBLIC )
2009-07-05 04:31:27 +08:00
SPL_ME ( RegexIterator , accept , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RegexIterator , getMode , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2006-07-22 04:14:31 +08:00
SPL_ME ( RegexIterator , setMode , arginfo_regex_it_set_mode , ZEND_ACC_PUBLIC )
2009-07-05 04:31:27 +08:00
SPL_ME ( RegexIterator , getFlags , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2006-07-22 04:14:31 +08:00
SPL_ME ( RegexIterator , setFlags , arginfo_regex_it_set_flags , ZEND_ACC_PUBLIC )
2009-07-05 04:31:27 +08:00
SPL_ME ( RegexIterator , getPregFlags , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2006-07-22 04:14:31 +08:00
SPL_ME ( RegexIterator , setPregFlags , arginfo_regex_it_set_preg_flags , ZEND_ACC_PUBLIC )
2011-01-06 10:32:02 +08:00
SPL_ME ( RegexIterator , getRegex , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2011-07-25 19:35:02 +08:00
PHP_FE_END
2006-05-10 08:03:38 +08:00
} ;
2015-01-03 17:22:58 +08:00
ZEND_BEGIN_ARG_INFO_EX ( arginfo_rec_regex_it___construct , 0 , 0 , 2 )
2006-05-10 08:03:38 +08:00
ZEND_ARG_OBJ_INFO ( 0 , iterator , RecursiveIterator , 0 )
ZEND_ARG_INFO ( 0 , regex )
2006-07-22 05:26:11 +08:00
ZEND_ARG_INFO ( 0 , mode )
2006-05-10 08:03:38 +08:00
ZEND_ARG_INFO ( 0 , flags )
2006-07-22 05:26:11 +08:00
ZEND_ARG_INFO ( 0 , preg_flags )
2006-05-10 08:03:38 +08:00
ZEND_END_ARG_INFO ( ) ;
2007-09-28 02:00:48 +08:00
static const zend_function_entry spl_funcs_RecursiveRegexIterator [ ] = {
2007-03-04 22:01:06 +08:00
SPL_ME ( RecursiveRegexIterator , __construct , arginfo_rec_regex_it___construct , ZEND_ACC_PUBLIC )
2014-10-06 09:40:39 +08:00
SPL_ME ( RecursiveRegexIterator , accept , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2009-07-05 04:31:27 +08:00
SPL_ME ( RecursiveFilterIterator , hasChildren , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveRegexIterator , getChildren , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2011-07-25 19:35:02 +08:00
PHP_FE_END
2006-05-10 08:03:38 +08:00
} ;
# endif
2014-12-14 06:06:14 +08:00
static inline int spl_limit_it_valid ( spl_dual_it_object * intern )
2004-01-29 06:59:03 +08:00
{
/* FAILURE / SUCCESS */
if ( intern - > u . limit . count ! = - 1 & & intern - > current . pos > = intern - > u . limit . offset + intern - > u . limit . count ) {
return FAILURE ;
} else {
2014-12-14 06:06:14 +08:00
return spl_dual_it_valid ( intern ) ;
2004-01-29 06:59:03 +08:00
}
}
2014-12-14 06:06:14 +08:00
static inline void spl_limit_it_seek ( spl_dual_it_object * intern , zend_long pos )
2003-12-07 03:21:02 +08:00
{
2014-02-13 03:54:04 +08:00
zval zpos ;
2003-12-07 03:21:02 +08:00
2014-12-14 06:06:14 +08:00
spl_dual_it_free ( intern ) ;
2003-12-07 03:21:02 +08:00
if ( pos < intern - > u . limit . offset ) {
2016-06-21 21:00:37 +08:00
zend_throw_exception_ex ( spl_ce_OutOfBoundsException , 0 , " Cannot seek to " ZEND_LONG_FMT " which is below the offset " ZEND_LONG_FMT , pos , intern - > u . limit . offset ) ;
2003-12-07 03:21:02 +08:00
return ;
}
2006-03-06 01:39:49 +08:00
if ( pos > = intern - > u . limit . offset + intern - > u . limit . count & & intern - > u . limit . count ! = - 1 ) {
2016-06-21 21:00:37 +08:00
zend_throw_exception_ex ( spl_ce_OutOfBoundsException , 0 , " Cannot seek to " ZEND_LONG_FMT " which is behind offset " ZEND_LONG_FMT " plus count " ZEND_LONG_FMT , pos , intern - > u . limit . offset , intern - > u . limit . count ) ;
2003-12-07 03:21:02 +08:00
return ;
}
2014-12-14 06:06:14 +08:00
if ( pos ! = intern - > current . pos & & instanceof_function ( intern - > inner . ce , spl_ce_SeekableIterator ) ) {
2014-08-26 01:24:55 +08:00
ZVAL_LONG ( & zpos , pos ) ;
2014-12-14 06:06:14 +08:00
spl_dual_it_free ( intern ) ;
2014-02-28 15:03:43 +08:00
zend_call_method_with_1_params ( & intern - > inner . zobject , intern - > inner . ce , NULL , " seek " , NULL , & zpos ) ;
2004-01-27 07:59:50 +08:00
zval_ptr_dtor ( & zpos ) ;
2006-05-22 02:13:37 +08:00
if ( ! EG ( exception ) ) {
intern - > current . pos = pos ;
2014-12-14 06:06:14 +08:00
if ( spl_limit_it_valid ( intern ) = = SUCCESS ) {
spl_dual_it_fetch ( intern , 0 ) ;
2006-05-22 02:13:37 +08:00
}
2004-01-29 06:59:03 +08:00
}
2003-12-07 03:21:02 +08:00
} else {
/* emulate the forward seek, by next() calls */
/* a back ward seek is done by a previous rewind() */
if ( pos < intern - > current . pos ) {
2014-12-14 06:06:14 +08:00
spl_dual_it_rewind ( intern ) ;
2003-12-07 03:21:02 +08:00
}
2014-12-14 06:06:14 +08:00
while ( pos > intern - > current . pos & & spl_dual_it_valid ( intern ) = = SUCCESS ) {
spl_dual_it_next ( intern , 1 ) ;
2003-12-07 03:21:02 +08:00
}
2014-12-14 06:06:14 +08:00
if ( spl_dual_it_valid ( intern ) = = SUCCESS ) {
spl_dual_it_fetch ( intern , 1 ) ;
2003-12-07 03:21:02 +08:00
}
}
}
2004-10-30 18:18:10 +08:00
/* {{{ proto LimitIterator::__construct(Iterator it [, int offset, int count])
2004-05-06 17:01:31 +08:00
Construct a LimitIterator from an Iterator with a given starting offset and optionally a maximum count */
2003-12-07 03:21:02 +08:00
SPL_METHOD ( LimitIterator , __construct )
{
2006-03-06 01:39:49 +08:00
spl_dual_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , spl_ce_LimitIterator , zend_ce_iterator , DIT_LimitIterator ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-12-07 03:21:02 +08:00
2015-01-03 17:22:58 +08:00
/* {{{ proto void LimitIterator::rewind()
2004-05-06 17:01:31 +08:00
Rewind the iterator to the specified starting offset */
2003-12-07 03:21:02 +08:00
SPL_METHOD ( LimitIterator , rewind )
{
spl_dual_it_object * intern ;
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2014-12-14 06:06:14 +08:00
spl_dual_it_rewind ( intern ) ;
spl_limit_it_seek ( intern , intern - > u . limit . offset ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-12-07 03:21:02 +08:00
2006-03-06 17:50:44 +08:00
/* {{{ proto bool LimitIterator::valid()
2004-05-06 17:01:31 +08:00
Check whether the current element is valid */
2004-03-09 01:33:31 +08:00
SPL_METHOD ( LimitIterator , valid )
2003-12-07 03:21:02 +08:00
{
spl_dual_it_object * intern ;
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2003-12-07 03:21:02 +08:00
2014-12-14 06:06:14 +08:00
/* RETURN_BOOL(spl_limit_it_valid(intern) == SUCCESS);*/
2014-02-13 03:54:04 +08:00
RETURN_BOOL ( ( intern - > u . limit . count = = - 1 | | intern - > current . pos < intern - > u . limit . offset + intern - > u . limit . count ) & & Z_TYPE ( intern - > current . data ) ! = IS_UNDEF ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-12-07 03:21:02 +08:00
2004-05-06 17:01:31 +08:00
/* {{{ proto void LimitIterator::next()
Move the iterator forward */
2004-01-29 06:59:03 +08:00
SPL_METHOD ( LimitIterator , next )
{
spl_dual_it_object * intern ;
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2004-01-29 06:59:03 +08:00
2014-12-14 06:06:14 +08:00
spl_dual_it_next ( intern , 1 ) ;
2004-01-29 06:59:03 +08:00
if ( intern - > u . limit . count = = - 1 | | intern - > current . pos < intern - > u . limit . offset + intern - > u . limit . count ) {
2014-12-14 06:06:14 +08:00
spl_dual_it_fetch ( intern , 1 ) ;
2004-01-29 06:59:03 +08:00
}
2004-05-06 17:01:31 +08:00
} /* }}} */
2004-01-29 06:59:03 +08:00
2004-10-30 18:18:10 +08:00
/* {{{ proto void LimitIterator::seek(int position)
2004-05-06 17:01:31 +08:00
Seek to the given position */
2003-12-07 03:21:02 +08:00
SPL_METHOD ( LimitIterator , seek )
{
spl_dual_it_object * intern ;
2014-08-26 01:24:55 +08:00
zend_long pos ;
2003-12-07 03:21:02 +08:00
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " l " , & pos ) = = FAILURE ) {
2003-12-07 03:21:02 +08:00
return ;
}
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2014-12-14 06:06:14 +08:00
spl_limit_it_seek ( intern , pos ) ;
2014-08-26 01:24:55 +08:00
RETURN_LONG ( intern - > current . pos ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-12-07 03:21:02 +08:00
2004-05-06 17:01:31 +08:00
/* {{{ proto int LimitIterator::getPosition()
Return the current position */
2003-12-07 03:21:02 +08:00
SPL_METHOD ( LimitIterator , getPosition )
{
spl_dual_it_object * intern ;
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2014-08-26 01:24:55 +08:00
RETURN_LONG ( intern - > current . pos ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-12-07 03:21:02 +08:00
2015-01-03 17:22:58 +08:00
ZEND_BEGIN_ARG_INFO ( arginfo_seekable_it_seek , 0 )
2003-12-07 03:21:02 +08:00
ZEND_ARG_INFO ( 0 , position )
ZEND_END_ARG_INFO ( ) ;
2007-09-28 02:00:48 +08:00
static const zend_function_entry spl_funcs_SeekableIterator [ ] = {
2003-12-07 03:21:02 +08:00
SPL_ABSTRACT_ME ( SeekableIterator , seek , arginfo_seekable_it_seek )
2011-07-25 19:35:02 +08:00
PHP_FE_END
2003-12-07 03:21:02 +08:00
} ;
2015-01-03 17:22:58 +08:00
ZEND_BEGIN_ARG_INFO_EX ( arginfo_limit_it___construct , 0 , 0 , 1 )
2004-03-29 01:04:11 +08:00
ZEND_ARG_OBJ_INFO ( 0 , iterator , Iterator , 0 )
2003-12-07 03:21:02 +08:00
ZEND_ARG_INFO ( 0 , offset )
ZEND_ARG_INFO ( 0 , count )
2003-12-02 15:18:05 +08:00
ZEND_END_ARG_INFO ( ) ;
2015-01-03 17:22:58 +08:00
ZEND_BEGIN_ARG_INFO ( arginfo_limit_it_seek , 0 )
2003-12-07 03:21:02 +08:00
ZEND_ARG_INFO ( 0 , position )
ZEND_END_ARG_INFO ( ) ;
2007-09-28 02:00:48 +08:00
static const zend_function_entry spl_funcs_LimitIterator [ ] = {
2004-03-10 01:35:18 +08:00
SPL_ME ( LimitIterator , __construct , arginfo_limit_it___construct , ZEND_ACC_PUBLIC )
2009-07-05 04:31:27 +08:00
SPL_ME ( LimitIterator , rewind , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( LimitIterator , valid , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , key , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , current , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( LimitIterator , next , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2004-03-10 01:35:18 +08:00
SPL_ME ( LimitIterator , seek , arginfo_limit_it_seek , ZEND_ACC_PUBLIC )
2009-07-05 04:31:27 +08:00
SPL_ME ( LimitIterator , getPosition , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , getInnerIterator , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2011-07-25 19:35:02 +08:00
PHP_FE_END
2003-12-07 03:21:02 +08:00
} ;
2014-12-14 06:06:14 +08:00
static inline int spl_caching_it_valid ( spl_dual_it_object * intern )
2003-12-08 16:39:18 +08:00
{
2004-03-09 02:05:41 +08:00
return intern - > u . caching . flags & CIT_VALID ? SUCCESS : FAILURE ;
2003-12-08 16:39:18 +08:00
}
2014-12-14 06:06:14 +08:00
static inline int spl_caching_it_has_next ( spl_dual_it_object * intern )
2003-12-08 16:39:18 +08:00
{
2014-12-14 06:06:14 +08:00
return spl_dual_it_valid ( intern ) ;
2003-12-08 16:39:18 +08:00
}
2014-12-14 06:06:14 +08:00
static inline void spl_caching_it_next ( spl_dual_it_object * intern )
2003-12-08 16:39:18 +08:00
{
2014-12-14 06:06:14 +08:00
if ( spl_dual_it_fetch ( intern , 1 ) = = SUCCESS ) {
2004-03-09 02:05:41 +08:00
intern - > u . caching . flags | = CIT_VALID ;
2006-05-10 08:03:38 +08:00
/* Full cache ? */
if ( intern - > u . caching . flags & CIT_FULL_CACHE ) {
2014-02-13 03:54:04 +08:00
zval * key = & intern - > current . key ;
2015-07-01 07:05:21 +08:00
zval * data = & intern - > current . data ;
2015-01-03 17:22:58 +08:00
2015-07-01 07:05:21 +08:00
ZVAL_DEREF ( data ) ;
Z_TRY_ADDREF_P ( data ) ;
2015-09-25 03:39:59 +08:00
array_set_zval_key ( Z_ARRVAL ( intern - > u . caching . zcache ) , key , data ) ;
2015-07-01 07:05:21 +08:00
zval_ptr_dtor ( data ) ;
2006-05-10 08:03:38 +08:00
}
/* Recursion ? */
2005-09-19 01:15:04 +08:00
if ( intern - > dit_type = = DIT_RecursiveCachingIterator ) {
2014-02-13 03:54:04 +08:00
zval retval , zchildren , zflags ;
2014-02-28 15:03:43 +08:00
zend_call_method_with_0_params ( & intern - > inner . zobject , intern - > inner . ce , NULL , " haschildren " , & retval ) ;
2006-05-22 02:13:37 +08:00
if ( EG ( exception ) ) {
2014-02-13 02:51:19 +08:00
zval_ptr_dtor ( & retval ) ;
2006-05-22 02:13:37 +08:00
if ( intern - > u . caching . flags & CIT_CATCH_GET_CHILD ) {
2014-12-14 06:06:14 +08:00
zend_clear_exception ( ) ;
2006-05-22 02:13:37 +08:00
} else {
return ;
}
} else {
2014-12-14 06:06:14 +08:00
if ( zend_is_true ( & retval ) ) {
2014-02-28 15:03:43 +08:00
zend_call_method_with_0_params ( & intern - > inner . zobject , intern - > inner . ce , NULL , " getchildren " , & zchildren ) ;
2006-05-22 02:13:37 +08:00
if ( EG ( exception ) ) {
2014-02-13 02:51:19 +08:00
zval_ptr_dtor ( & zchildren ) ;
2006-05-22 02:13:37 +08:00
if ( intern - > u . caching . flags & CIT_CATCH_GET_CHILD ) {
2014-12-14 06:06:14 +08:00
zend_clear_exception ( ) ;
2006-05-22 02:13:37 +08:00
} else {
2014-02-13 02:51:19 +08:00
zval_ptr_dtor ( & retval ) ;
2006-05-22 02:13:37 +08:00
return ;
}
} else {
2014-08-26 01:24:55 +08:00
ZVAL_LONG ( & zflags , intern - > u . caching . flags & CIT_PUBLIC ) ;
2014-12-14 06:06:14 +08:00
spl_instantiate_arg_ex2 ( spl_ce_RecursiveCachingIterator , & intern - > u . caching . zchildren , & zchildren , & zflags ) ;
2003-12-08 16:39:18 +08:00
zval_ptr_dtor ( & zchildren ) ;
}
2006-05-22 02:13:37 +08:00
}
zval_ptr_dtor ( & retval ) ;
if ( EG ( exception ) ) {
2006-05-16 16:21:08 +08:00
if ( intern - > u . caching . flags & CIT_CATCH_GET_CHILD ) {
2014-12-14 06:06:14 +08:00
zend_clear_exception ( ) ;
2006-05-19 05:42:58 +08:00
} else {
return ;
2006-05-16 16:21:08 +08:00
}
2003-12-08 16:39:18 +08:00
}
}
}
2006-05-19 05:42:58 +08:00
if ( intern - > u . caching . flags & ( CIT_TOSTRING_USE_INNER | CIT_CALL_TOSTRING ) ) {
int use_copy ;
zval expr_copy ;
if ( intern - > u . caching . flags & CIT_TOSTRING_USE_INNER ) {
2014-02-28 15:03:43 +08:00
ZVAL_COPY_VALUE ( & intern - > u . caching . zstr , & intern - > inner . zobject ) ;
2003-12-08 16:39:18 +08:00
} else {
2014-02-13 03:54:04 +08:00
ZVAL_COPY_VALUE ( & intern - > u . caching . zstr , & intern - > current . data ) ;
2006-05-19 05:42:58 +08:00
}
2014-12-14 06:06:14 +08:00
use_copy = zend_make_printable_zval ( & intern - > u . caching . zstr , & expr_copy ) ;
2006-05-19 05:42:58 +08:00
if ( use_copy ) {
2014-08-13 23:43:34 +08:00
ZVAL_COPY_VALUE ( & intern - > u . caching . zstr , & expr_copy ) ;
2014-03-15 22:23:09 +08:00
} else if ( Z_REFCOUNTED ( intern - > u . caching . zstr ) ) {
2014-03-15 16:33:31 +08:00
Z_ADDREF ( intern - > u . caching . zstr ) ;
2004-03-18 03:58:32 +08:00
}
2003-12-08 16:39:18 +08:00
}
2015-01-03 17:22:58 +08:00
spl_dual_it_next ( intern , 0 ) ;
2003-12-08 16:39:18 +08:00
} else {
2004-03-09 02:05:41 +08:00
intern - > u . caching . flags & = ~ CIT_VALID ;
2003-12-08 16:39:18 +08:00
}
}
2014-12-14 06:06:14 +08:00
static inline void spl_caching_it_rewind ( spl_dual_it_object * intern )
2003-12-08 16:39:18 +08:00
{
2014-12-14 06:06:14 +08:00
spl_dual_it_rewind ( intern ) ;
2015-09-25 03:39:59 +08:00
zend_hash_clean ( Z_ARRVAL ( intern - > u . caching . zcache ) ) ;
2014-12-14 06:06:14 +08:00
spl_caching_it_next ( intern ) ;
2003-12-08 16:39:18 +08:00
}
2006-03-06 17:50:44 +08:00
/* {{{ proto void CachingIterator::__construct(Iterator it [, flags = CIT_CALL_TOSTRING])
2004-05-06 17:01:31 +08:00
Construct a CachingIterator from an Iterator */
2003-12-08 16:39:18 +08:00
SPL_METHOD ( CachingIterator , __construct )
{
2006-03-06 01:39:49 +08:00
spl_dual_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , spl_ce_CachingIterator , zend_ce_iterator , DIT_CachingIterator ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-12-08 16:39:18 +08:00
2004-05-06 17:01:31 +08:00
/* {{{ proto void CachingIterator::rewind()
Rewind the iterator */
2003-12-08 16:39:18 +08:00
SPL_METHOD ( CachingIterator , rewind )
{
spl_dual_it_object * intern ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2003-12-08 16:39:18 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2003-12-08 16:39:18 +08:00
2014-12-14 06:06:14 +08:00
spl_caching_it_rewind ( intern ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-12-08 16:39:18 +08:00
2006-03-06 17:50:44 +08:00
/* {{{ proto bool CachingIterator::valid()
2004-05-06 17:01:31 +08:00
Check whether the current element is valid */
2004-03-09 01:33:31 +08:00
SPL_METHOD ( CachingIterator , valid )
2003-12-08 16:39:18 +08:00
{
spl_dual_it_object * intern ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2003-12-08 16:39:18 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2003-12-08 16:39:18 +08:00
2014-12-14 06:06:14 +08:00
RETURN_BOOL ( spl_caching_it_valid ( intern ) = = SUCCESS ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-12-08 16:39:18 +08:00
2004-05-06 17:01:31 +08:00
/* {{{ proto void CachingIterator::next()
Move the iterator forward */
2003-12-08 16:39:18 +08:00
SPL_METHOD ( CachingIterator , next )
{
spl_dual_it_object * intern ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2003-12-08 16:39:18 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2003-12-08 16:39:18 +08:00
2014-12-14 06:06:14 +08:00
spl_caching_it_next ( intern ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-12-08 16:39:18 +08:00
2006-03-06 17:50:44 +08:00
/* {{{ proto bool CachingIterator::hasNext()
2004-12-29 21:53:40 +08:00
Check whether the inner iterator has a valid next element */
2003-12-08 16:39:18 +08:00
SPL_METHOD ( CachingIterator , hasNext )
{
spl_dual_it_object * intern ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2003-12-08 16:39:18 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2003-12-08 16:39:18 +08:00
2014-12-14 06:06:14 +08:00
RETURN_BOOL ( spl_caching_it_has_next ( intern ) = = SUCCESS ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-12-08 16:39:18 +08:00
2004-05-06 17:01:31 +08:00
/* {{{ proto string CachingIterator::__toString()
2004-12-30 00:11:42 +08:00
Return the string representation of the current element */
2003-12-08 16:39:18 +08:00
SPL_METHOD ( CachingIterator , __toString )
{
spl_dual_it_object * intern ;
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2003-12-08 16:39:18 +08:00
2006-05-19 05:42:58 +08:00
if ( ! ( intern - > u . caching . flags & ( CIT_CALL_TOSTRING | CIT_TOSTRING_USE_KEY | CIT_TOSTRING_USE_CURRENT | CIT_TOSTRING_USE_INNER ) ) ) {
2015-06-30 09:05:24 +08:00
zend_throw_exception_ex ( spl_ce_BadMethodCallException , 0 , " %s does not fetch string value (see CachingIterator::__construct) " , ZSTR_VAL ( Z_OBJCE_P ( getThis ( ) ) - > name ) ) ;
2009-01-20 08:43:25 +08:00
return ;
2003-12-08 16:39:18 +08:00
}
2005-10-04 00:05:08 +08:00
if ( intern - > u . caching . flags & CIT_TOSTRING_USE_KEY ) {
2015-06-12 01:41:43 +08:00
ZVAL_COPY ( return_value , & intern - > current . key ) ;
2013-02-17 02:13:36 +08:00
convert_to_string ( return_value ) ;
return ;
2005-10-04 00:05:08 +08:00
} else if ( intern - > u . caching . flags & CIT_TOSTRING_USE_CURRENT ) {
2015-06-12 01:41:43 +08:00
ZVAL_COPY ( return_value , & intern - > current . data ) ;
2006-05-19 05:42:58 +08:00
convert_to_string ( return_value ) ;
2005-10-04 00:05:08 +08:00
return ;
}
2014-02-13 03:54:04 +08:00
if ( Z_TYPE ( intern - > u . caching . zstr ) = = IS_STRING ) {
2015-03-12 21:53:51 +08:00
RETURN_STR_COPY ( Z_STR_P ( & intern - > u . caching . zstr ) ) ;
2003-12-08 16:39:18 +08:00
} else {
2016-10-13 14:08:30 +08:00
RETURN_EMPTY_STRING ( ) ;
2003-12-08 16:39:18 +08:00
}
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-12-08 16:39:18 +08:00
2006-05-10 08:03:38 +08:00
/* {{{ proto void CachingIterator::offsetSet(mixed index, mixed newval)
Set given index in cache */
SPL_METHOD ( CachingIterator , offsetSet )
{
spl_dual_it_object * intern ;
2014-02-13 03:54:04 +08:00
zend_string * key ;
2006-05-10 08:03:38 +08:00
zval * value ;
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2006-05-10 08:03:38 +08:00
if ( ! ( intern - > u . caching . flags & CIT_FULL_CACHE ) ) {
2015-06-30 09:05:24 +08:00
zend_throw_exception_ex ( spl_ce_BadMethodCallException , 0 , " %s does not use a full cache (see CachingIterator::__construct) " , ZSTR_VAL ( Z_OBJCE_P ( getThis ( ) ) - > name ) ) ;
2009-01-20 08:43:25 +08:00
return ;
2006-05-10 08:03:38 +08:00
}
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " Sz " , & key , & value ) = = FAILURE ) {
2006-05-10 08:03:38 +08:00
return ;
}
2014-03-15 16:33:31 +08:00
if ( Z_REFCOUNTED_P ( value ) ) {
Z_ADDREF_P ( value ) ;
}
2015-09-25 03:39:59 +08:00
zend_symtable_update ( Z_ARRVAL ( intern - > u . caching . zcache ) , key , value ) ;
2006-05-10 08:03:38 +08:00
}
/* }}} */
/* {{{ proto string CachingIterator::offsetGet(mixed index)
Return the internal cache if used */
SPL_METHOD ( CachingIterator , offsetGet )
{
spl_dual_it_object * intern ;
2014-02-13 03:54:04 +08:00
zend_string * key ;
zval * value ;
2006-05-10 08:03:38 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2006-05-10 08:03:38 +08:00
if ( ! ( intern - > u . caching . flags & CIT_FULL_CACHE ) ) {
2015-06-30 09:05:24 +08:00
zend_throw_exception_ex ( spl_ce_BadMethodCallException , 0 , " %s does not use a full cache (see CachingIterator::__construct) " , ZSTR_VAL ( Z_OBJCE_P ( getThis ( ) ) - > name ) ) ;
2009-01-20 08:43:25 +08:00
return ;
2006-05-10 08:03:38 +08:00
}
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " S " , & key ) = = FAILURE ) {
2006-05-10 08:03:38 +08:00
return ;
}
2015-09-25 03:39:59 +08:00
if ( ( value = zend_symtable_find ( Z_ARRVAL ( intern - > u . caching . zcache ) , key ) ) = = NULL ) {
2015-06-30 09:05:24 +08:00
zend_error ( E_NOTICE , " Undefined index: %s " , ZSTR_VAL ( key ) ) ;
2006-05-10 08:03:38 +08:00
return ;
}
2015-01-03 17:22:58 +08:00
2015-07-01 07:05:21 +08:00
ZVAL_DEREF ( value ) ;
ZVAL_COPY ( return_value , value ) ;
2006-05-10 08:03:38 +08:00
}
/* }}} */
/* {{{ proto void CachingIterator::offsetUnset(mixed index)
Unset given index in cache */
SPL_METHOD ( CachingIterator , offsetUnset )
{
spl_dual_it_object * intern ;
2014-02-13 03:54:04 +08:00
zend_string * key ;
2006-05-10 08:03:38 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2006-05-10 08:03:38 +08:00
if ( ! ( intern - > u . caching . flags & CIT_FULL_CACHE ) ) {
2015-06-30 09:05:24 +08:00
zend_throw_exception_ex ( spl_ce_BadMethodCallException , 0 , " %s does not use a full cache (see CachingIterator::__construct) " , ZSTR_VAL ( Z_OBJCE_P ( getThis ( ) ) - > name ) ) ;
2009-01-20 08:43:25 +08:00
return ;
2006-05-10 08:03:38 +08:00
}
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " S " , & key ) = = FAILURE ) {
2006-05-10 08:03:38 +08:00
return ;
}
2015-09-25 03:39:59 +08:00
zend_symtable_del ( Z_ARRVAL ( intern - > u . caching . zcache ) , key ) ;
2006-05-10 08:03:38 +08:00
}
/* }}} */
/* {{{ proto bool CachingIterator::offsetExists(mixed index)
Return whether the requested index exists */
SPL_METHOD ( CachingIterator , offsetExists )
{
spl_dual_it_object * intern ;
2014-02-13 03:54:04 +08:00
zend_string * key ;
2015-01-03 17:22:58 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2006-05-10 08:03:38 +08:00
if ( ! ( intern - > u . caching . flags & CIT_FULL_CACHE ) ) {
2015-06-30 09:05:24 +08:00
zend_throw_exception_ex ( spl_ce_BadMethodCallException , 0 , " %s does not use a full cache (see CachingIterator::__construct) " , ZSTR_VAL ( Z_OBJCE_P ( getThis ( ) ) - > name ) ) ;
2009-01-20 08:43:25 +08:00
return ;
2006-05-10 08:03:38 +08:00
}
2015-01-03 17:22:58 +08:00
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " S " , & key ) = = FAILURE ) {
2006-05-10 08:03:38 +08:00
return ;
}
2015-09-25 03:39:59 +08:00
RETURN_BOOL ( zend_symtable_exists ( Z_ARRVAL ( intern - > u . caching . zcache ) , key ) ) ;
2006-05-10 08:03:38 +08:00
}
/* }}} */
2006-05-22 02:13:37 +08:00
/* {{{ proto bool CachingIterator::getCache()
Return the cache */
SPL_METHOD ( CachingIterator , getCache )
{
spl_dual_it_object * intern ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2015-01-03 17:22:58 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2006-05-22 02:13:37 +08:00
if ( ! ( intern - > u . caching . flags & CIT_FULL_CACHE ) ) {
2016-06-21 21:00:37 +08:00
zend_throw_exception_ex ( spl_ce_BadMethodCallException , 0 , " %s does not use a full cache (see CachingIterator::__construct) " , ZSTR_VAL ( Z_OBJCE_P ( getThis ( ) ) - > name ) ) ;
2006-05-22 02:13:37 +08:00
return ;
}
2015-09-25 03:39:59 +08:00
ZVAL_COPY ( return_value , & intern - > u . caching . zcache ) ;
2006-05-22 02:13:37 +08:00
}
/* }}} */
2006-05-10 08:03:38 +08:00
/* {{{ proto int CachingIterator::getFlags()
Return the internal flags */
SPL_METHOD ( CachingIterator , getFlags )
{
spl_dual_it_object * intern ;
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2015-01-03 17:22:58 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2006-05-10 08:03:38 +08:00
2014-08-26 01:24:55 +08:00
RETURN_LONG ( intern - > u . caching . flags ) ;
2006-05-10 08:03:38 +08:00
}
/* }}} */
2006-11-07 07:20:11 +08:00
/* {{{ proto void CachingIterator::setFlags(int flags)
2006-05-10 08:03:38 +08:00
Set the internal flags */
SPL_METHOD ( CachingIterator , setFlags )
{
spl_dual_it_object * intern ;
2014-08-26 01:24:55 +08:00
zend_long flags ;
2006-05-10 08:03:38 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2006-05-10 08:03:38 +08:00
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " l " , & flags ) = = FAILURE ) {
2006-05-10 08:03:38 +08:00
return ;
}
2006-05-19 05:42:58 +08:00
if ( spl_cit_check_flags ( flags ) ! = SUCCESS ) {
2014-12-14 06:06:14 +08:00
zend_throw_exception ( spl_ce_InvalidArgumentException , " Flags must contain only one of CALL_TOSTRING, TOSTRING_USE_KEY, TOSTRING_USE_CURRENT, TOSTRING_USE_INNER " , 0 ) ;
2006-05-10 08:03:38 +08:00
return ;
}
2006-05-19 05:42:58 +08:00
if ( ( intern - > u . caching . flags & CIT_CALL_TOSTRING ) ! = 0 & & ( flags & CIT_CALL_TOSTRING ) = = 0 ) {
2014-12-14 06:06:14 +08:00
zend_throw_exception ( spl_ce_InvalidArgumentException , " Unsetting flag CALL_TO_STRING is not possible " , 0 ) ;
2006-05-10 08:03:38 +08:00
return ;
}
2006-05-19 05:42:58 +08:00
if ( ( intern - > u . caching . flags & CIT_TOSTRING_USE_INNER ) ! = 0 & & ( flags & CIT_TOSTRING_USE_INNER ) = = 0 ) {
2014-12-14 06:06:14 +08:00
zend_throw_exception ( spl_ce_InvalidArgumentException , " Unsetting flag TOSTRING_USE_INNER is not possible " , 0 ) ;
2006-05-19 05:42:58 +08:00
return ;
}
2011-02-21 00:09:50 +08:00
if ( ( flags & CIT_FULL_CACHE ) ! = 0 & & ( intern - > u . caching . flags & CIT_FULL_CACHE ) = = 0 ) {
2006-05-10 08:03:38 +08:00
/* clear on (re)enable */
2015-09-25 03:39:59 +08:00
zend_hash_clean ( Z_ARRVAL ( intern - > u . caching . zcache ) ) ;
2006-05-10 08:03:38 +08:00
}
intern - > u . caching . flags = ( intern - > u . caching . flags & ~ CIT_PUBLIC ) | ( flags & CIT_PUBLIC ) ;
}
/* }}} */
2007-02-20 00:18:24 +08:00
/* {{{ proto void CachingIterator::count()
Number of cached elements */
SPL_METHOD ( CachingIterator , count )
{
spl_dual_it_object * intern ;
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2015-01-03 17:22:58 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2007-02-20 00:18:24 +08:00
if ( ! ( intern - > u . caching . flags & CIT_FULL_CACHE ) ) {
2016-06-21 21:00:37 +08:00
zend_throw_exception_ex ( spl_ce_BadMethodCallException , 0 , " %s does not use a full cache (see CachingIterator::__construct) " , ZSTR_VAL ( Z_OBJCE_P ( getThis ( ) ) - > name ) ) ;
2007-02-20 00:18:24 +08:00
return ;
}
2015-09-25 03:39:59 +08:00
RETURN_LONG ( zend_hash_num_elements ( Z_ARRVAL ( intern - > u . caching . zcache ) ) ) ;
2007-02-20 00:18:24 +08:00
}
/* }}} */
2015-01-03 17:22:58 +08:00
ZEND_BEGIN_ARG_INFO_EX ( arginfo_caching_it___construct , 0 , 0 , 1 )
2004-03-29 01:04:11 +08:00
ZEND_ARG_OBJ_INFO ( 0 , iterator , Iterator , 0 )
2004-11-01 02:43:00 +08:00
ZEND_ARG_INFO ( 0 , flags )
2003-12-08 16:39:18 +08:00
ZEND_END_ARG_INFO ( ) ;
2015-01-03 17:22:58 +08:00
ZEND_BEGIN_ARG_INFO ( arginfo_caching_it_setFlags , 0 )
2006-05-10 08:03:38 +08:00
ZEND_ARG_INFO ( 0 , flags )
ZEND_END_ARG_INFO ( ) ;
2006-11-07 07:20:11 +08:00
ZEND_BEGIN_ARG_INFO ( arginfo_caching_it_offsetGet , 0 )
2006-05-10 08:03:38 +08:00
ZEND_ARG_INFO ( 0 , index )
ZEND_END_ARG_INFO ( ) ;
2006-11-07 07:20:11 +08:00
ZEND_BEGIN_ARG_INFO ( arginfo_caching_it_offsetSet , 0 )
2006-05-10 08:03:38 +08:00
ZEND_ARG_INFO ( 0 , index )
ZEND_ARG_INFO ( 0 , newval )
ZEND_END_ARG_INFO ( ) ;
2007-09-28 02:00:48 +08:00
static const zend_function_entry spl_funcs_CachingIterator [ ] = {
2004-03-10 01:35:18 +08:00
SPL_ME ( CachingIterator , __construct , arginfo_caching_it___construct , ZEND_ACC_PUBLIC )
2009-07-05 04:31:27 +08:00
SPL_ME ( CachingIterator , rewind , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( CachingIterator , valid , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , key , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , current , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( CachingIterator , next , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( CachingIterator , hasNext , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( CachingIterator , __toString , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , getInnerIterator , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( CachingIterator , getFlags , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2006-05-10 08:03:38 +08:00
SPL_ME ( CachingIterator , setFlags , arginfo_caching_it_setFlags , ZEND_ACC_PUBLIC )
SPL_ME ( CachingIterator , offsetGet , arginfo_caching_it_offsetGet , ZEND_ACC_PUBLIC )
SPL_ME ( CachingIterator , offsetSet , arginfo_caching_it_offsetSet , ZEND_ACC_PUBLIC )
SPL_ME ( CachingIterator , offsetUnset , arginfo_caching_it_offsetGet , ZEND_ACC_PUBLIC )
SPL_ME ( CachingIterator , offsetExists , arginfo_caching_it_offsetGet , ZEND_ACC_PUBLIC )
2009-07-05 04:31:27 +08:00
SPL_ME ( CachingIterator , getCache , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( CachingIterator , count , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2011-07-25 19:35:02 +08:00
PHP_FE_END
2003-12-08 16:39:18 +08:00
} ;
2006-03-06 17:50:44 +08:00
/* {{{ proto void RecursiveCachingIterator::__construct(RecursiveIterator it [, flags = CIT_CALL_TOSTRING])
2004-05-06 17:01:31 +08:00
Create an iterator from a RecursiveIterator */
2005-09-19 01:15:04 +08:00
SPL_METHOD ( RecursiveCachingIterator , __construct )
2003-12-08 16:39:18 +08:00
{
2006-03-06 01:39:49 +08:00
spl_dual_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , spl_ce_RecursiveCachingIterator , spl_ce_RecursiveIterator , DIT_RecursiveCachingIterator ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-12-08 16:39:18 +08:00
2006-03-06 17:50:44 +08:00
/* {{{ proto bool RecursiveCachingIterator::hasChildren()
2004-12-29 21:53:40 +08:00
Check whether the current element of the inner iterator has children */
2005-09-19 01:15:04 +08:00
SPL_METHOD ( RecursiveCachingIterator , hasChildren )
2003-12-08 16:39:18 +08:00
{
spl_dual_it_object * intern ;
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2015-01-03 17:22:58 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2003-12-08 16:39:18 +08:00
2014-02-13 03:54:04 +08:00
RETURN_BOOL ( Z_TYPE ( intern - > u . caching . zchildren ) ! = IS_UNDEF ) ;
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-12-08 16:39:18 +08:00
2005-09-19 01:15:04 +08:00
/* {{{ proto RecursiveCachingIterator RecursiveCachingIterator::getChildren()
Return the inner iterator ' s children as a RecursiveCachingIterator */
SPL_METHOD ( RecursiveCachingIterator , getChildren )
2003-12-08 16:39:18 +08:00
{
spl_dual_it_object * intern ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2003-12-08 16:39:18 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2003-12-08 16:39:18 +08:00
2014-02-13 03:54:04 +08:00
if ( Z_TYPE ( intern - > u . caching . zchildren ) ! = IS_UNDEF ) {
2015-07-01 07:05:21 +08:00
zval * value = & intern - > u . caching . zchildren ;
ZVAL_DEREF ( value ) ;
ZVAL_COPY ( return_value , value ) ;
2003-12-08 16:39:18 +08:00
} else {
RETURN_NULL ( ) ;
}
2004-05-06 17:01:31 +08:00
} /* }}} */
2003-12-08 16:39:18 +08:00
2015-01-03 17:22:58 +08:00
ZEND_BEGIN_ARG_INFO_EX ( arginfo_caching_rec_it___construct , 0 , ZEND_RETURN_VALUE , 1 )
2004-03-29 01:04:11 +08:00
ZEND_ARG_OBJ_INFO ( 0 , iterator , Iterator , 0 )
2004-11-01 02:43:00 +08:00
ZEND_ARG_INFO ( 0 , flags )
2003-12-08 16:39:18 +08:00
ZEND_END_ARG_INFO ( ) ;
2007-09-28 02:00:48 +08:00
static const zend_function_entry spl_funcs_RecursiveCachingIterator [ ] = {
2005-09-19 01:15:04 +08:00
SPL_ME ( RecursiveCachingIterator , __construct , arginfo_caching_rec_it___construct , ZEND_ACC_PUBLIC )
2009-07-05 04:31:27 +08:00
SPL_ME ( RecursiveCachingIterator , hasChildren , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( RecursiveCachingIterator , getChildren , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2011-07-25 19:35:02 +08:00
PHP_FE_END
2003-12-08 16:39:18 +08:00
} ;
2006-03-06 17:50:44 +08:00
/* {{{ proto void IteratorIterator::__construct(Traversable it)
2004-11-01 02:43:00 +08:00
Create an iterator from anything that is traversable */
SPL_METHOD ( IteratorIterator , __construct )
{
2006-03-06 01:39:49 +08:00
spl_dual_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , spl_ce_IteratorIterator , zend_ce_traversable , DIT_IteratorIterator ) ;
2004-11-01 02:43:00 +08:00
} /* }}} */
2015-01-03 17:22:58 +08:00
ZEND_BEGIN_ARG_INFO ( arginfo_iterator_it___construct , 0 )
2004-11-01 02:43:00 +08:00
ZEND_ARG_OBJ_INFO ( 0 , iterator , Traversable , 0 )
ZEND_END_ARG_INFO ( ) ;
2007-09-28 02:00:48 +08:00
static const zend_function_entry spl_funcs_IteratorIterator [ ] = {
2004-11-01 02:43:00 +08:00
SPL_ME ( IteratorIterator , __construct , arginfo_iterator_it___construct , ZEND_ACC_PUBLIC )
2009-07-05 04:31:27 +08:00
SPL_ME ( dual_it , rewind , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , valid , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , key , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , current , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , next , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , getInnerIterator , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2011-07-25 19:35:02 +08:00
PHP_FE_END
2004-11-01 02:43:00 +08:00
} ;
2006-03-06 17:50:44 +08:00
/* {{{ proto void NoRewindIterator::__construct(Iterator it)
2004-11-01 02:43:00 +08:00
Create an iterator from another iterator */
SPL_METHOD ( NoRewindIterator , __construct )
{
2006-03-06 01:39:49 +08:00
spl_dual_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , spl_ce_NoRewindIterator , zend_ce_iterator , DIT_NoRewindIterator ) ;
2004-11-01 02:43:00 +08:00
} /* }}} */
2004-11-01 08:26:59 +08:00
/* {{{ proto void NoRewindIterator::rewind()
Prevent a call to inner iterators rewind ( ) */
2004-11-01 02:43:00 +08:00
SPL_METHOD ( NoRewindIterator , rewind )
2004-11-01 08:26:59 +08:00
{
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2004-11-01 08:26:59 +08:00
/* nothing to do */
} /* }}} */
2006-03-06 17:50:44 +08:00
/* {{{ proto bool NoRewindIterator::valid()
2004-11-01 08:26:59 +08:00
Return inner iterators valid ( ) */
SPL_METHOD ( NoRewindIterator , valid )
{
spl_dual_it_object * intern ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2004-11-01 08:26:59 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2014-12-14 06:06:14 +08:00
RETURN_BOOL ( intern - > inner . iterator - > funcs - > valid ( intern - > inner . iterator ) = = SUCCESS ) ;
2004-11-01 08:26:59 +08:00
} /* }}} */
/* {{{ proto mixed NoRewindIterator::key()
Return inner iterators key ( ) */
SPL_METHOD ( NoRewindIterator , key )
2004-11-01 02:43:00 +08:00
{
spl_dual_it_object * intern ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2004-11-01 02:43:00 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2004-11-01 02:43:00 +08:00
2004-11-01 08:26:59 +08:00
if ( intern - > inner . iterator - > funcs - > get_current_key ) {
2014-12-14 06:06:14 +08:00
intern - > inner . iterator - > funcs - > get_current_key ( intern - > inner . iterator , return_value ) ;
2004-11-01 08:26:59 +08:00
} else {
RETURN_NULL ( ) ;
}
} /* }}} */
/* {{{ proto mixed NoRewindIterator::current()
Return inner iterators current ( ) */
SPL_METHOD ( NoRewindIterator , current )
{
spl_dual_it_object * intern ;
2014-02-13 03:54:04 +08:00
zval * data ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2004-11-01 08:26:59 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2014-12-14 06:06:14 +08:00
data = intern - > inner . iterator - > funcs - > get_current_data ( intern - > inner . iterator ) ;
2014-02-13 03:54:04 +08:00
if ( data ) {
2015-07-01 07:05:21 +08:00
ZVAL_DEREF ( data ) ;
ZVAL_COPY ( return_value , data ) ;
2009-05-10 03:35:09 +08:00
}
2004-11-01 08:26:59 +08:00
} /* }}} */
/* {{{ proto void NoRewindIterator::next()
Return inner iterators next ( ) */
SPL_METHOD ( NoRewindIterator , next )
{
spl_dual_it_object * intern ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2004-11-01 08:26:59 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2014-12-14 06:06:14 +08:00
intern - > inner . iterator - > funcs - > move_forward ( intern - > inner . iterator ) ;
2004-11-01 02:43:00 +08:00
} /* }}} */
2015-01-03 17:22:58 +08:00
ZEND_BEGIN_ARG_INFO ( arginfo_norewind_it___construct , 0 )
2004-11-01 02:43:00 +08:00
ZEND_ARG_OBJ_INFO ( 0 , iterator , Iterator , 0 )
ZEND_END_ARG_INFO ( ) ;
2007-09-28 02:00:48 +08:00
static const zend_function_entry spl_funcs_NoRewindIterator [ ] = {
2004-11-01 02:43:00 +08:00
SPL_ME ( NoRewindIterator , __construct , arginfo_norewind_it___construct , ZEND_ACC_PUBLIC )
2009-07-05 04:31:27 +08:00
SPL_ME ( NoRewindIterator , rewind , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( NoRewindIterator , valid , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( NoRewindIterator , key , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( NoRewindIterator , current , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( NoRewindIterator , next , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , getInnerIterator , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2011-07-25 19:35:02 +08:00
PHP_FE_END
2004-11-01 02:43:00 +08:00
} ;
2006-03-06 17:50:44 +08:00
/* {{{ proto void InfiniteIterator::__construct(Iterator it)
2004-11-01 03:49:18 +08:00
Create an iterator from another iterator */
SPL_METHOD ( InfiniteIterator , __construct )
{
2006-03-06 01:39:49 +08:00
spl_dual_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , spl_ce_InfiniteIterator , zend_ce_iterator , DIT_InfiniteIterator ) ;
2004-11-01 03:49:18 +08:00
} /* }}} */
2006-03-06 17:50:44 +08:00
/* {{{ proto void InfiniteIterator::next()
2004-11-01 03:49:18 +08:00
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 ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2004-11-01 03:49:18 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2004-11-01 03:49:18 +08:00
2014-12-14 06:06:14 +08:00
spl_dual_it_next ( intern , 1 ) ;
if ( spl_dual_it_valid ( intern ) = = SUCCESS ) {
spl_dual_it_fetch ( intern , 0 ) ;
2004-11-01 03:49:18 +08:00
} else {
2014-12-14 06:06:14 +08:00
spl_dual_it_rewind ( intern ) ;
if ( spl_dual_it_valid ( intern ) = = SUCCESS ) {
spl_dual_it_fetch ( intern , 0 ) ;
2004-11-01 03:49:18 +08:00
}
}
} /* }}} */
2007-09-28 02:00:48 +08:00
static const zend_function_entry spl_funcs_InfiniteIterator [ ] = {
2004-11-01 03:49:18 +08:00
SPL_ME ( InfiniteIterator , __construct , arginfo_norewind_it___construct , ZEND_ACC_PUBLIC )
2009-07-05 04:31:27 +08:00
SPL_ME ( InfiniteIterator , next , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2011-07-25 19:35:02 +08:00
PHP_FE_END
2004-11-01 03:49:18 +08:00
} ;
2004-11-01 02:43:00 +08:00
2006-03-06 17:50:44 +08:00
/* {{{ proto void EmptyIterator::rewind()
2004-11-01 04:59:39 +08:00
Does nothing */
SPL_METHOD ( EmptyIterator , rewind )
{
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2004-11-01 04:59:39 +08:00
} /* }}} */
2006-03-06 17:50:44 +08:00
/* {{{ proto false EmptyIterator::valid()
2004-11-01 04:59:39 +08:00
Return false */
SPL_METHOD ( EmptyIterator , valid )
{
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2004-11-01 04:59:39 +08:00
RETURN_FALSE ;
} /* }}} */
2006-03-06 17:50:44 +08:00
/* {{{ proto void EmptyIterator::key()
Throws exception BadMethodCallException */
2004-11-01 04:59:39 +08:00
SPL_METHOD ( EmptyIterator , key )
{
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2014-12-14 06:06:14 +08:00
zend_throw_exception ( spl_ce_BadMethodCallException , " Accessing the key of an EmptyIterator " , 0 ) ;
2004-11-01 04:59:39 +08:00
} /* }}} */
2006-03-06 17:50:44 +08:00
/* {{{ proto void EmptyIterator::current()
Throws exception BadMethodCallException */
2004-11-01 04:59:39 +08:00
SPL_METHOD ( EmptyIterator , current )
{
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2014-12-14 06:06:14 +08:00
zend_throw_exception ( spl_ce_BadMethodCallException , " Accessing the value of an EmptyIterator " , 0 ) ;
2004-11-01 04:59:39 +08:00
} /* }}} */
2006-03-06 17:50:44 +08:00
/* {{{ proto void EmptyIterator::next()
2004-11-01 04:59:39 +08:00
Does nothing */
SPL_METHOD ( EmptyIterator , next )
{
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2004-11-01 04:59:39 +08:00
} /* }}} */
2007-09-28 02:00:48 +08:00
static const zend_function_entry spl_funcs_EmptyIterator [ ] = {
2009-07-05 04:31:27 +08:00
SPL_ME ( EmptyIterator , rewind , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( EmptyIterator , valid , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( EmptyIterator , key , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( EmptyIterator , current , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( EmptyIterator , next , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2011-07-25 19:35:02 +08:00
PHP_FE_END
2004-11-01 04:59:39 +08:00
} ;
2014-12-14 06:06:14 +08:00
int spl_append_it_next_iterator ( spl_dual_it_object * intern ) /* { { { */
2004-11-01 08:26:59 +08:00
{
2014-12-14 06:06:14 +08:00
spl_dual_it_free ( intern ) ;
2004-11-01 08:26:59 +08:00
2014-05-03 16:06:27 +08:00
if ( ! Z_ISUNDEF ( intern - > inner . zobject ) ) {
2014-02-28 15:03:43 +08:00
zval_ptr_dtor ( & intern - > inner . zobject ) ;
ZVAL_UNDEF ( & intern - > inner . zobject ) ;
2004-11-01 08:26:59 +08:00
intern - > inner . ce = NULL ;
2005-12-22 08:06:38 +08:00
if ( intern - > inner . iterator ) {
2014-12-14 06:06:14 +08:00
zend_iterator_dtor ( intern - > inner . iterator ) ;
2005-12-22 08:06:38 +08:00
intern - > inner . iterator = NULL ;
}
2004-11-01 08:26:59 +08:00
}
2014-12-14 06:06:14 +08:00
if ( intern - > u . append . iterator - > funcs - > valid ( intern - > u . append . iterator ) = = SUCCESS ) {
2014-02-12 22:15:08 +08:00
zval * it ;
2004-11-01 08:26:59 +08:00
2014-12-14 06:06:14 +08:00
it = intern - > u . append . iterator - > funcs - > get_current_data ( intern - > u . append . iterator ) ;
2014-02-28 15:03:43 +08:00
ZVAL_COPY ( & intern - > inner . zobject , it ) ;
2014-02-12 22:15:08 +08:00
intern - > inner . ce = Z_OBJCE_P ( it ) ;
2014-12-14 06:06:14 +08:00
intern - > inner . iterator = intern - > inner . ce - > get_iterator ( intern - > inner . ce , it , 0 ) ;
spl_dual_it_rewind ( intern ) ;
2004-11-01 08:26:59 +08:00
return SUCCESS ;
} else {
return FAILURE ;
}
} /* }}} */
2014-12-14 06:06:14 +08:00
void spl_append_it_fetch ( spl_dual_it_object * intern ) /* { { { */
2004-11-01 08:26:59 +08:00
{
2014-12-14 06:06:14 +08:00
while ( spl_dual_it_valid ( intern ) ! = SUCCESS ) {
intern - > u . append . iterator - > funcs - > move_forward ( intern - > u . append . iterator ) ;
if ( spl_append_it_next_iterator ( intern ) ! = SUCCESS ) {
2004-11-01 08:26:59 +08:00
return ;
}
}
2014-12-14 06:06:14 +08:00
spl_dual_it_fetch ( intern , 0 ) ;
2004-11-01 08:26:59 +08:00
} /* }}} */
2014-12-14 06:06:14 +08:00
void spl_append_it_next ( spl_dual_it_object * intern ) /* { { { */
2004-11-01 08:26:59 +08:00
{
2014-12-14 06:06:14 +08:00
if ( spl_dual_it_valid ( intern ) = = SUCCESS ) {
spl_dual_it_next ( intern , 1 ) ;
2004-11-01 08:26:59 +08:00
}
2014-12-14 06:06:14 +08:00
spl_append_it_fetch ( intern ) ;
2004-11-01 08:26:59 +08:00
} /* }}} */
2006-03-06 17:50:44 +08:00
/* {{{ proto void AppendIterator::__construct()
2004-11-01 08:26:59 +08:00
Create an AppendIterator */
SPL_METHOD ( AppendIterator , __construct )
{
2006-03-06 01:39:49 +08:00
spl_dual_it_construct ( INTERNAL_FUNCTION_PARAM_PASSTHRU , spl_ce_AppendIterator , zend_ce_iterator , DIT_AppendIterator ) ;
2004-11-01 08:26:59 +08:00
} /* }}} */
/* {{{ proto void AppendIterator::append(Iterator it)
Append an iterator */
SPL_METHOD ( AppendIterator , append )
{
2017-09-05 03:20:49 +08:00
spl_dual_it_object * intern ;
2004-11-01 08:26:59 +08:00
zval * it ;
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2004-11-01 08:26:59 +08:00
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters_ex ( ZEND_PARSE_PARAMS_QUIET , ZEND_NUM_ARGS ( ) , " O " , & it , zend_ce_iterator ) = = FAILURE ) {
2004-11-01 08:26:59 +08:00
return ;
}
2017-09-11 02:11:58 +08:00
if ( intern - > u . append . iterator - > funcs - > valid ( intern - > u . append . iterator ) = = SUCCESS & & spl_dual_it_valid ( intern ) ! = SUCCESS ) {
2017-04-30 13:33:53 +08:00
spl_array_iterator_append ( & intern - > u . append . zarrayit , it ) ;
intern - > u . append . iterator - > funcs - > move_forward ( intern - > u . append . iterator ) ;
} else {
spl_array_iterator_append ( & intern - > u . append . zarrayit , it ) ;
}
2004-11-01 08:26:59 +08:00
2014-12-14 06:06:14 +08:00
if ( ! intern - > inner . iterator | | spl_dual_it_valid ( intern ) ! = SUCCESS ) {
if ( intern - > u . append . iterator - > funcs - > valid ( intern - > u . append . iterator ) ! = SUCCESS ) {
intern - > u . append . iterator - > funcs - > rewind ( intern - > u . append . iterator ) ;
2004-11-01 08:26:59 +08:00
}
do {
2014-12-14 06:06:14 +08:00
spl_append_it_next_iterator ( intern ) ;
2014-02-28 17:12:53 +08:00
} while ( Z_OBJ ( intern - > inner . zobject ) ! = Z_OBJ_P ( it ) ) ;
2014-12-14 06:06:14 +08:00
spl_append_it_fetch ( intern ) ;
2004-11-01 08:26:59 +08:00
}
} /* }}} */
/* {{{ proto void AppendIterator::rewind()
Rewind to the first iterator and rewind the first iterator , too */
SPL_METHOD ( AppendIterator , rewind )
{
spl_dual_it_object * intern ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2004-11-01 08:26:59 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2015-01-03 17:22:58 +08:00
2014-12-14 06:06:14 +08:00
intern - > u . append . iterator - > funcs - > rewind ( intern - > u . append . iterator ) ;
if ( spl_append_it_next_iterator ( intern ) = = SUCCESS ) {
spl_append_it_fetch ( intern ) ;
2004-11-01 08:26:59 +08:00
}
} /* }}} */
2006-03-06 17:50:44 +08:00
/* {{{ proto bool AppendIterator::valid()
2004-11-01 08:26:59 +08:00
Check if the current state is valid */
SPL_METHOD ( AppendIterator , valid )
{
spl_dual_it_object * intern ;
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2015-01-03 17:22:58 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2004-11-01 08:26:59 +08:00
2014-02-13 03:54:04 +08:00
RETURN_BOOL ( Z_TYPE ( intern - > current . data ) ! = IS_UNDEF ) ;
2004-11-01 08:26:59 +08:00
} /* }}} */
2006-03-06 17:50:44 +08:00
/* {{{ proto void AppendIterator::next()
2004-11-01 08:26:59 +08:00
Forward to next element */
SPL_METHOD ( AppendIterator , next )
{
spl_dual_it_object * intern ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2004-11-01 08:26:59 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2015-01-03 17:22:58 +08:00
2014-12-14 06:06:14 +08:00
spl_append_it_next ( intern ) ;
2004-11-01 08:26:59 +08:00
} /* }}} */
2006-05-10 08:03:38 +08:00
/* {{{ proto int AppendIterator::getIteratorIndex()
Get index of iterator */
SPL_METHOD ( AppendIterator , getIteratorIndex )
{
spl_dual_it_object * intern ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2006-05-10 08:03:38 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
APPENDIT_CHECK_CTOR ( intern ) ;
2014-12-14 06:06:14 +08:00
spl_array_iterator_key ( & intern - > u . append . zarrayit , return_value ) ;
2006-05-10 08:03:38 +08:00
} /* }}} */
/* {{{ proto ArrayIterator AppendIterator::getArrayIterator()
Get access to inner ArrayIterator */
SPL_METHOD ( AppendIterator , getArrayIterator )
{
spl_dual_it_object * intern ;
2015-07-01 07:05:21 +08:00
zval * value ;
2015-01-03 17:22:58 +08:00
2010-11-15 02:40:08 +08:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2006-05-10 08:03:38 +08:00
2011-10-30 07:17:18 +08:00
SPL_FETCH_AND_CHECK_DUAL_IT ( intern , getThis ( ) ) ;
2015-07-01 07:05:21 +08:00
value = & intern - > u . append . zarrayit ;
ZVAL_DEREF ( value ) ;
ZVAL_COPY ( return_value , value ) ;
2006-05-10 08:03:38 +08:00
} /* }}} */
2015-01-03 17:22:58 +08:00
ZEND_BEGIN_ARG_INFO ( arginfo_append_it_append , 0 )
2004-11-01 08:26:59 +08:00
ZEND_ARG_OBJ_INFO ( 0 , iterator , Iterator , 0 )
ZEND_END_ARG_INFO ( ) ;
2007-09-28 02:00:48 +08:00
static const zend_function_entry spl_funcs_AppendIterator [ ] = {
2009-07-05 04:31:27 +08:00
SPL_ME ( AppendIterator , __construct , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2004-11-01 08:26:59 +08:00
SPL_ME ( AppendIterator , append , arginfo_append_it_append , ZEND_ACC_PUBLIC )
2009-07-05 04:31:27 +08:00
SPL_ME ( AppendIterator , rewind , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( AppendIterator , valid , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , key , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , current , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( AppendIterator , next , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( dual_it , getInnerIterator , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( AppendIterator , getIteratorIndex , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
SPL_ME ( AppendIterator , getArrayIterator , arginfo_recursive_it_void , ZEND_ACC_PUBLIC )
2011-07-25 19:35:02 +08:00
PHP_FE_END
2004-11-01 08:26:59 +08:00
} ;
2014-12-14 06:06:14 +08:00
PHPAPI int spl_iterator_apply ( zval * obj , spl_iterator_apply_func_t apply_func , void * puser )
2004-10-08 07:08:19 +08:00
{
zend_object_iterator * iter ;
2006-05-21 05:01:42 +08:00
zend_class_entry * ce = Z_OBJCE_P ( obj ) ;
2004-10-08 07:08:19 +08:00
2014-12-14 06:06:14 +08:00
iter = ce - > get_iterator ( ce , obj , 0 ) ;
2006-05-21 05:01:42 +08:00
if ( EG ( exception ) ) {
goto done ;
2004-10-08 07:08:19 +08:00
}
2011-06-28 19:09:06 +08:00
iter - > index = 0 ;
2006-01-02 03:48:11 +08:00
if ( iter - > funcs - > rewind ) {
2014-12-14 06:06:14 +08:00
iter - > funcs - > rewind ( iter ) ;
2006-05-21 05:01:42 +08:00
if ( EG ( exception ) ) {
goto done ;
}
2006-01-02 03:48:11 +08:00
}
2006-05-21 05:01:42 +08:00
2014-12-14 06:06:14 +08:00
while ( iter - > funcs - > valid ( iter ) = = SUCCESS ) {
2006-05-12 17:42:56 +08:00
if ( EG ( exception ) ) {
2006-05-21 05:01:42 +08:00
goto done ;
2006-05-12 17:42:56 +08:00
}
2014-12-14 06:06:14 +08:00
if ( apply_func ( iter , puser ) = = ZEND_HASH_APPLY_STOP | | EG ( exception ) ) {
2006-05-21 05:01:42 +08:00
goto done ;
2004-10-08 07:08:19 +08:00
}
2011-06-28 19:09:06 +08:00
iter - > index + + ;
2014-12-14 06:06:14 +08:00
iter - > funcs - > move_forward ( iter ) ;
2006-05-12 17:42:56 +08:00
if ( EG ( exception ) ) {
2006-05-21 05:01:42 +08:00
goto done ;
2006-05-12 17:42:56 +08:00
}
2004-10-08 07:08:19 +08:00
}
2006-05-21 05:01:42 +08:00
done :
2010-07-03 03:17:45 +08:00
if ( iter ) {
2014-12-14 06:06:14 +08:00
zend_iterator_dtor ( iter ) ;
2010-07-03 03:17:45 +08:00
}
2006-05-21 05:01:42 +08:00
return EG ( exception ) ? FAILURE : SUCCESS ;
}
/* }}} */
2014-12-14 06:06:14 +08:00
static int spl_iterator_to_array_apply ( zend_object_iterator * iter , void * puser ) /* { { { */
2006-05-21 05:01:42 +08:00
{
2014-02-13 03:54:04 +08:00
zval * data , * return_value = ( zval * ) puser ;
2006-05-21 05:01:42 +08:00
2014-12-14 06:06:14 +08:00
data = iter - > funcs - > get_current_data ( iter ) ;
2006-05-12 17:42:56 +08:00
if ( EG ( exception ) ) {
2006-05-21 05:01:42 +08:00
return ZEND_HASH_APPLY_STOP ;
}
2014-02-13 03:54:04 +08:00
if ( data = = NULL ) {
2009-05-10 03:35:09 +08:00
return ZEND_HASH_APPLY_STOP ;
}
2006-05-21 05:01:42 +08:00
if ( iter - > funcs - > get_current_key ) {
2013-02-17 02:13:36 +08:00
zval key ;
2014-12-14 06:06:14 +08:00
iter - > funcs - > get_current_key ( iter , & key ) ;
2006-05-21 05:01:42 +08:00
if ( EG ( exception ) ) {
return ZEND_HASH_APPLY_STOP ;
}
2014-12-14 06:06:14 +08:00
array_set_zval_key ( Z_ARRVAL_P ( return_value ) , & key , data ) ;
2015-06-12 17:33:23 +08:00
zval_ptr_dtor ( & key ) ;
2006-05-21 05:01:42 +08:00
} else {
2014-06-28 20:53:32 +08:00
Z_TRY_ADDREF_P ( data ) ;
2014-02-13 03:54:04 +08:00
add_next_index_zval ( return_value , data ) ;
2006-05-21 05:01:42 +08:00
}
return ZEND_HASH_APPLY_KEEP ;
}
/* }}} */
2014-12-14 06:06:14 +08:00
static int spl_iterator_to_values_apply ( zend_object_iterator * iter , void * puser ) /* { { { */
2006-11-21 03:58:01 +08:00
{
2014-02-13 03:54:04 +08:00
zval * data , * return_value = ( zval * ) puser ;
2006-11-21 03:58:01 +08:00
2014-12-14 06:06:14 +08:00
data = iter - > funcs - > get_current_data ( iter ) ;
2006-11-21 03:58:01 +08:00
if ( EG ( exception ) ) {
return ZEND_HASH_APPLY_STOP ;
}
2014-02-13 03:54:04 +08:00
if ( data = = NULL ) {
2009-05-10 03:35:09 +08:00
return ZEND_HASH_APPLY_STOP ;
}
2014-03-15 19:16:07 +08:00
if ( Z_REFCOUNTED_P ( data ) ) {
Z_ADDREF_P ( data ) ;
}
2014-02-13 03:54:04 +08:00
add_next_index_zval ( return_value , data ) ;
2006-11-21 03:58:01 +08:00
return ZEND_HASH_APPLY_KEEP ;
}
/* }}} */
2015-01-03 17:22:58 +08:00
/* {{{ proto array iterator_to_array(Traversable it [, bool use_keys = true])
2006-05-21 05:01:42 +08:00
Copy the iterator into an array */
PHP_FUNCTION ( iterator_to_array )
{
2006-06-07 17:44:42 +08:00
zval * obj ;
2006-11-21 03:58:01 +08:00
zend_bool use_keys = 1 ;
2006-05-21 05:01:42 +08:00
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " O|b " , & obj , zend_ce_traversable , & use_keys ) = = FAILURE ) {
2006-05-21 05:01:42 +08:00
RETURN_FALSE ;
2006-05-12 17:42:56 +08:00
}
2006-05-21 05:01:42 +08:00
array_init ( return_value ) ;
2006-11-21 03:58:01 +08:00
2014-12-14 06:06:14 +08:00
if ( spl_iterator_apply ( obj , use_keys ? spl_iterator_to_array_apply : spl_iterator_to_values_apply , ( void * ) return_value ) ! = SUCCESS ) {
2015-06-12 17:33:23 +08:00
zval_ptr_dtor ( return_value ) ;
2006-05-21 05:01:42 +08:00
RETURN_NULL ( ) ;
}
2006-11-21 03:58:01 +08:00
} /* }}} */
2006-05-21 05:01:42 +08:00
2014-12-14 06:06:14 +08:00
static int spl_iterator_count_apply ( zend_object_iterator * iter , void * puser ) /* { { { */
2006-05-21 05:01:42 +08:00
{
2014-08-26 01:24:55 +08:00
( * ( zend_long * ) puser ) + + ;
2006-05-21 05:01:42 +08:00
return ZEND_HASH_APPLY_KEEP ;
2004-10-08 07:08:19 +08:00
}
/* }}} */
2015-01-03 17:22:58 +08:00
/* {{{ proto int iterator_count(Traversable it)
2004-10-08 07:08:19 +08:00
Count the elements in an iterator */
PHP_FUNCTION ( iterator_count )
{
2006-06-07 17:44:42 +08:00
zval * obj ;
2014-08-26 01:24:55 +08:00
zend_long count = 0 ;
2004-10-08 07:08:19 +08:00
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " O " , & obj , zend_ce_traversable ) = = FAILURE ) {
2004-10-08 07:08:19 +08:00
RETURN_FALSE ;
}
2015-01-03 17:22:58 +08:00
2014-12-14 06:06:14 +08:00
if ( spl_iterator_apply ( obj , spl_iterator_count_apply , ( void * ) & count ) = = SUCCESS ) {
2014-08-26 01:24:55 +08:00
RETURN_LONG ( count ) ;
2006-01-02 03:55:27 +08:00
}
2004-10-08 07:08:19 +08:00
}
/* }}} */
2006-06-07 17:44:42 +08:00
typedef struct {
zval * obj ;
zval * args ;
2014-08-26 01:24:55 +08:00
zend_long count ;
2006-06-07 17:44:42 +08:00
zend_fcall_info fci ;
zend_fcall_info_cache fcc ;
} spl_iterator_apply_info ;
2014-12-14 06:06:14 +08:00
static int spl_iterator_func_apply ( zend_object_iterator * iter , void * puser ) /* { { { */
2006-06-07 17:44:42 +08:00
{
2014-02-12 22:15:08 +08:00
zval retval ;
2006-06-07 17:44:42 +08:00
spl_iterator_apply_info * apply_info = ( spl_iterator_apply_info * ) puser ;
int result ;
apply_info - > count + + ;
2014-12-14 06:06:14 +08:00
zend_fcall_info_call ( & apply_info - > fci , & apply_info - > fcc , & retval , NULL ) ;
2014-02-12 22:15:08 +08:00
if ( Z_TYPE ( retval ) ! = IS_UNDEF ) {
2014-12-14 06:06:14 +08:00
result = zend_is_true ( & retval ) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_STOP ;
2014-02-13 02:51:19 +08:00
zval_ptr_dtor ( & retval ) ;
2006-06-07 17:44:42 +08:00
} else {
result = ZEND_HASH_APPLY_STOP ;
}
return result ;
}
/* }}} */
/* {{{ proto int iterator_apply(Traversable it, mixed function [, mixed params])
Calls a function for every element in an iterator */
PHP_FUNCTION ( iterator_apply )
{
spl_iterator_apply_info apply_info ;
apply_info . args = NULL ;
2014-12-14 06:06:14 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " Of|a! " , & apply_info . obj , zend_ce_traversable , & apply_info . fci , & apply_info . fcc , & apply_info . args ) = = FAILURE ) {
2006-06-07 17:44:42 +08:00
return ;
}
apply_info . count = 0 ;
2014-12-14 06:06:14 +08:00
zend_fcall_info_args ( & apply_info . fci , apply_info . args ) ;
if ( spl_iterator_apply ( apply_info . obj , spl_iterator_func_apply , ( void * ) & apply_info ) = = SUCCESS ) {
2014-08-26 01:24:55 +08:00
RETVAL_LONG ( apply_info . count ) ;
2006-06-07 17:44:42 +08:00
} else {
RETVAL_FALSE ;
}
2014-12-14 06:06:14 +08:00
zend_fcall_info_args ( & apply_info . fci , NULL ) ;
2006-06-07 17:44:42 +08:00
}
/* }}} */
2007-09-28 02:00:48 +08:00
static const zend_function_entry spl_funcs_OuterIterator [ ] = {
2009-07-05 04:31:27 +08:00
SPL_ABSTRACT_ME ( OuterIterator , getInnerIterator , arginfo_recursive_it_void )
2011-07-25 19:35:02 +08:00
PHP_FE_END
2004-10-30 04:12:57 +08:00
} ;
2003-11-09 22:05:36 +08:00
/* {{{ PHP_MINIT_FUNCTION(spl_iterators)
*/
PHP_MINIT_FUNCTION ( spl_iterators )
{
REGISTER_SPL_INTERFACE ( RecursiveIterator ) ;
2003-12-08 16:39:18 +08:00
REGISTER_SPL_ITERATOR ( RecursiveIterator ) ;
REGISTER_SPL_STD_CLASS_EX ( RecursiveIteratorIterator , spl_RecursiveIteratorIterator_new , spl_funcs_RecursiveIteratorIterator ) ;
REGISTER_SPL_ITERATOR ( RecursiveIteratorIterator ) ;
2003-11-09 22:05:36 +08:00
2003-12-08 16:39:18 +08:00
memcpy ( & spl_handlers_rec_it_it , zend_get_std_object_handlers ( ) , sizeof ( zend_object_handlers ) ) ;
2014-04-09 05:50:15 +08:00
spl_handlers_rec_it_it . offset = XtOffsetOf ( spl_recursive_it_object , std ) ;
2004-11-01 03:05:19 +08:00
spl_handlers_rec_it_it . get_method = spl_recursive_it_get_method ;
2003-12-08 16:39:18 +08:00
spl_handlers_rec_it_it . clone_obj = NULL ;
2014-02-12 22:15:08 +08:00
spl_handlers_rec_it_it . dtor_obj = spl_RecursiveIteratorIterator_dtor ;
spl_handlers_rec_it_it . free_obj = spl_RecursiveIteratorIterator_free_storage ;
2003-12-02 15:18:05 +08:00
2003-12-08 16:39:18 +08:00
memcpy ( & spl_handlers_dual_it , zend_get_std_object_handlers ( ) , sizeof ( zend_object_handlers ) ) ;
2014-04-09 05:50:15 +08:00
spl_handlers_dual_it . offset = XtOffsetOf ( spl_dual_it_object , std ) ;
2003-12-08 16:39:18 +08:00
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 ;
2014-02-12 22:15:08 +08:00
spl_handlers_dual_it . dtor_obj = spl_dual_it_dtor ;
spl_handlers_dual_it . free_obj = spl_dual_it_free_storage ;
2015-01-03 17:22:58 +08:00
2003-11-09 22:05:36 +08:00
spl_ce_RecursiveIteratorIterator - > get_iterator = spl_recursive_it_get_iterator ;
spl_ce_RecursiveIteratorIterator - > iterator_funcs . funcs = & spl_recursive_it_iterator_funcs ;
2014-08-26 01:24:55 +08:00
REGISTER_SPL_CLASS_CONST_LONG ( RecursiveIteratorIterator , " LEAVES_ONLY " , RIT_LEAVES_ONLY ) ;
REGISTER_SPL_CLASS_CONST_LONG ( RecursiveIteratorIterator , " SELF_FIRST " , RIT_SELF_FIRST ) ;
REGISTER_SPL_CLASS_CONST_LONG ( RecursiveIteratorIterator , " CHILD_FIRST " , RIT_CHILD_FIRST ) ;
REGISTER_SPL_CLASS_CONST_LONG ( RecursiveIteratorIterator , " CATCH_GET_CHILD " , RIT_CATCH_GET_CHILD ) ;
2003-12-02 15:18:05 +08:00
2006-03-26 10:25:03 +08:00
REGISTER_SPL_INTERFACE ( OuterIterator ) ;
REGISTER_SPL_ITERATOR ( OuterIterator ) ;
REGISTER_SPL_STD_CLASS_EX ( IteratorIterator , spl_dual_it_new , spl_funcs_IteratorIterator ) ;
REGISTER_SPL_ITERATOR ( IteratorIterator ) ;
2006-07-22 05:26:11 +08:00
REGISTER_SPL_IMPLEMENTS ( IteratorIterator , OuterIterator ) ;
2006-03-26 10:25:03 +08:00
REGISTER_SPL_SUB_CLASS_EX ( FilterIterator , IteratorIterator , spl_dual_it_new , spl_funcs_FilterIterator ) ;
2004-03-10 00:38:37 +08:00
spl_ce_FilterIterator - > ce_flags | = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS ;
2003-12-02 15:18:05 +08:00
2005-09-15 11:33:04 +08:00
REGISTER_SPL_SUB_CLASS_EX ( RecursiveFilterIterator , FilterIterator , spl_dual_it_new , spl_funcs_RecursiveFilterIterator ) ;
REGISTER_SPL_IMPLEMENTS ( RecursiveFilterIterator , RecursiveIterator ) ;
2011-03-28 04:13:27 +08:00
REGISTER_SPL_SUB_CLASS_EX ( CallbackFilterIterator , FilterIterator , spl_dual_it_new , spl_funcs_CallbackFilterIterator ) ;
REGISTER_SPL_SUB_CLASS_EX ( RecursiveCallbackFilterIterator , CallbackFilterIterator , spl_dual_it_new , spl_funcs_RecursiveCallbackFilterIterator ) ;
REGISTER_SPL_IMPLEMENTS ( RecursiveCallbackFilterIterator , RecursiveIterator ) ;
2005-09-15 11:33:04 +08:00
REGISTER_SPL_SUB_CLASS_EX ( ParentIterator , RecursiveFilterIterator , spl_dual_it_new , spl_funcs_ParentIterator ) ;
2003-12-02 15:18:05 +08:00
2003-12-07 03:21:02 +08:00
REGISTER_SPL_INTERFACE ( SeekableIterator ) ;
2003-12-08 16:39:18 +08:00
REGISTER_SPL_ITERATOR ( SeekableIterator ) ;
2006-03-26 10:25:03 +08:00
REGISTER_SPL_SUB_CLASS_EX ( LimitIterator , IteratorIterator , spl_dual_it_new , spl_funcs_LimitIterator ) ;
2003-12-08 16:39:18 +08:00
2006-03-26 10:25:03 +08:00
REGISTER_SPL_SUB_CLASS_EX ( CachingIterator , IteratorIterator , spl_dual_it_new , spl_funcs_CachingIterator ) ;
2006-05-10 08:03:38 +08:00
REGISTER_SPL_IMPLEMENTS ( CachingIterator , ArrayAccess ) ;
2007-02-20 00:18:24 +08:00
REGISTER_SPL_IMPLEMENTS ( CachingIterator , Countable ) ;
2003-12-07 03:21:02 +08:00
2015-01-03 17:22:58 +08:00
REGISTER_SPL_CLASS_CONST_LONG ( CachingIterator , " CALL_TOSTRING " , CIT_CALL_TOSTRING ) ;
REGISTER_SPL_CLASS_CONST_LONG ( CachingIterator , " CATCH_GET_CHILD " , CIT_CATCH_GET_CHILD ) ;
2014-08-26 01:24:55 +08:00
REGISTER_SPL_CLASS_CONST_LONG ( CachingIterator , " TOSTRING_USE_KEY " , CIT_TOSTRING_USE_KEY ) ;
REGISTER_SPL_CLASS_CONST_LONG ( CachingIterator , " TOSTRING_USE_CURRENT " , CIT_TOSTRING_USE_CURRENT ) ;
REGISTER_SPL_CLASS_CONST_LONG ( CachingIterator , " TOSTRING_USE_INNER " , CIT_TOSTRING_USE_INNER ) ;
2015-01-03 17:22:58 +08:00
REGISTER_SPL_CLASS_CONST_LONG ( CachingIterator , " FULL_CACHE " , CIT_FULL_CACHE ) ;
2003-12-07 03:21:02 +08:00
2005-09-19 01:15:04 +08:00
REGISTER_SPL_SUB_CLASS_EX ( RecursiveCachingIterator , CachingIterator , spl_dual_it_new , spl_funcs_RecursiveCachingIterator ) ;
REGISTER_SPL_IMPLEMENTS ( RecursiveCachingIterator , RecursiveIterator ) ;
2015-01-03 17:22:58 +08:00
2006-03-26 10:25:03 +08:00
REGISTER_SPL_SUB_CLASS_EX ( NoRewindIterator , IteratorIterator , spl_dual_it_new , spl_funcs_NoRewindIterator ) ;
2004-10-30 04:12:57 +08:00
2006-03-26 10:25:03 +08:00
REGISTER_SPL_SUB_CLASS_EX ( AppendIterator , IteratorIterator , spl_dual_it_new , spl_funcs_AppendIterator ) ;
2004-11-01 08:26:59 +08:00
2004-10-30 04:12:57 +08:00
REGISTER_SPL_IMPLEMENTS ( RecursiveIteratorIterator , OuterIterator ) ;
2006-05-10 08:03:38 +08:00
2004-11-01 03:49:18 +08:00
REGISTER_SPL_SUB_CLASS_EX ( InfiniteIterator , IteratorIterator , spl_dual_it_new , spl_funcs_InfiniteIterator ) ;
2006-05-10 08:03:38 +08:00
# if HAVE_PCRE || HAVE_BUNDLED_PCRE
2006-05-11 00:50:57 +08:00
REGISTER_SPL_SUB_CLASS_EX ( RegexIterator , FilterIterator , spl_dual_it_new , spl_funcs_RegexIterator ) ;
2014-08-26 01:24:55 +08:00
REGISTER_SPL_CLASS_CONST_LONG ( RegexIterator , " USE_KEY " , REGIT_USE_KEY ) ;
REGISTER_SPL_CLASS_CONST_LONG ( RegexIterator , " INVERT_MATCH " , REGIT_INVERTED ) ;
REGISTER_SPL_CLASS_CONST_LONG ( RegexIterator , " MATCH " , REGIT_MODE_MATCH ) ;
REGISTER_SPL_CLASS_CONST_LONG ( RegexIterator , " GET_MATCH " , REGIT_MODE_GET_MATCH ) ;
REGISTER_SPL_CLASS_CONST_LONG ( RegexIterator , " ALL_MATCHES " , REGIT_MODE_ALL_MATCHES ) ;
REGISTER_SPL_CLASS_CONST_LONG ( RegexIterator , " SPLIT " , REGIT_MODE_SPLIT ) ;
REGISTER_SPL_CLASS_CONST_LONG ( RegexIterator , " REPLACE " , REGIT_MODE_REPLACE ) ;
2006-07-21 06:54:21 +08:00
REGISTER_SPL_PROPERTY ( RegexIterator , " replacement " , 0 ) ;
2006-05-11 00:50:57 +08:00
REGISTER_SPL_SUB_CLASS_EX ( RecursiveRegexIterator , RegexIterator , spl_dual_it_new , spl_funcs_RecursiveRegexIterator ) ;
REGISTER_SPL_IMPLEMENTS ( RecursiveRegexIterator , RecursiveIterator ) ;
2006-05-10 08:03:38 +08:00
# else
2006-05-11 00:50:57 +08:00
spl_ce_RegexIterator = NULL ;
spl_ce_RecursiveRegexIterator = NULL ;
2006-05-10 08:03:38 +08:00
# endif
2004-11-01 04:59:39 +08:00
REGISTER_SPL_STD_CLASS_EX ( EmptyIterator , NULL , spl_funcs_EmptyIterator ) ;
REGISTER_SPL_ITERATOR ( EmptyIterator ) ;
2004-11-01 03:49:18 +08:00
2008-07-19 23:49:21 +08:00
REGISTER_SPL_SUB_CLASS_EX ( RecursiveTreeIterator , RecursiveIteratorIterator , spl_RecursiveTreeIterator_new , spl_funcs_RecursiveTreeIterator ) ;
2014-08-26 01:24:55 +08:00
REGISTER_SPL_CLASS_CONST_LONG ( RecursiveTreeIterator , " BYPASS_CURRENT " , RTIT_BYPASS_CURRENT ) ;
REGISTER_SPL_CLASS_CONST_LONG ( RecursiveTreeIterator , " BYPASS_KEY " , RTIT_BYPASS_KEY ) ;
REGISTER_SPL_CLASS_CONST_LONG ( RecursiveTreeIterator , " PREFIX_LEFT " , 0 ) ;
REGISTER_SPL_CLASS_CONST_LONG ( RecursiveTreeIterator , " PREFIX_MID_HAS_NEXT " , 1 ) ;
REGISTER_SPL_CLASS_CONST_LONG ( RecursiveTreeIterator , " PREFIX_MID_LAST " , 2 ) ;
REGISTER_SPL_CLASS_CONST_LONG ( RecursiveTreeIterator , " PREFIX_END_HAS_NEXT " , 3 ) ;
REGISTER_SPL_CLASS_CONST_LONG ( RecursiveTreeIterator , " PREFIX_END_LAST " , 4 ) ;
REGISTER_SPL_CLASS_CONST_LONG ( RecursiveTreeIterator , " PREFIX_RIGHT " , 5 ) ;
2008-07-19 23:49:21 +08:00
2003-11-09 22:05:36 +08:00
return SUCCESS ;
}
/* }}} */
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* End :
* vim600 : fdm = marker
* vim : noet sw = 4 ts = 4
*/