2003-10-23 04:04:48 +08:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Zend Engine |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2015-01-15 23:27:30 +08:00
| Copyright ( c ) 1998 - 2015 Zend Technologies Ltd . ( http : //www.zend.com) |
2003-10-23 04:04:48 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| This source file is subject to version 2.00 of the Zend license , |
2015-01-03 17:22:58 +08:00
| that is bundled with this package in the file LICENSE , and is |
2003-10-23 04:04:48 +08:00
| available through the world - wide - web at the following url : |
| http : //www.zend.com/license/2_00.txt. |
| If you did not receive a copy of the Zend license and are unable to |
| obtain it through the world - wide - web , please send a note to |
| license @ zend . com so we can mail you a copy immediately . |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Authors : Marcus Boerger < helly @ php . net > |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
/* $Id$ */
# include "zend.h"
# include "zend_API.h"
# include "zend_interfaces.h"
2005-01-25 18:40:51 +08:00
# include "zend_exceptions.h"
2003-10-23 04:04:48 +08:00
2004-03-28 22:32:32 +08:00
ZEND_API zend_class_entry * zend_ce_traversable ;
ZEND_API zend_class_entry * zend_ce_aggregate ;
ZEND_API zend_class_entry * zend_ce_iterator ;
ZEND_API zend_class_entry * zend_ce_arrayaccess ;
2005-03-19 09:11:48 +08:00
ZEND_API zend_class_entry * zend_ce_serializable ;
2003-10-23 04:04:48 +08:00
2006-05-10 07:53:23 +08:00
/* {{{ zend_call_method
2003-10-23 04:04:48 +08:00
Only returns the returned zval if retval_ptr ! = NULL */
2014-12-14 06:06:14 +08:00
ZEND_API zval * zend_call_method ( zval * object , zend_class_entry * obj_ce , zend_function * * fn_proxy , const char * function_name , size_t function_name_len , zval * retval_ptr , int param_count , zval * arg1 , zval * arg2 )
2003-10-23 04:04:48 +08:00
{
int result ;
zend_fcall_info fci ;
2014-02-10 14:04:30 +08:00
zval retval ;
2005-03-02 07:41:49 +08:00
HashTable * function_table ;
2003-10-23 04:04:48 +08:00
2014-02-10 14:04:30 +08:00
zval params [ 2 ] ;
2003-10-23 04:04:48 +08:00
2014-02-19 16:03:01 +08:00
if ( param_count > 0 ) {
ZVAL_COPY_VALUE ( & params [ 0 ] , arg1 ) ;
}
if ( param_count > 1 ) {
ZVAL_COPY_VALUE ( & params [ 1 ] , arg2 ) ;
}
2003-10-23 04:04:48 +08:00
fci . size = sizeof ( fci ) ;
/*fci.function_table = NULL; will be read form zend_class_entry of object if needed */
2014-03-28 06:11:22 +08:00
fci . object = ( object & & Z_TYPE_P ( object ) = = IS_OBJECT ) ? Z_OBJ_P ( object ) : NULL ;
2014-02-10 14:04:30 +08:00
ZVAL_STRINGL ( & fci . function_name , function_name , function_name_len ) ;
fci . retval = retval_ptr ? retval_ptr : & retval ;
2003-10-23 04:04:48 +08:00
fci . param_count = param_count ;
fci . params = params ;
fci . no_separation = 1 ;
fci . symbol_table = NULL ;
if ( ! fn_proxy & & ! obj_ce ) {
/* no interest in caching and no information already present that is
* needed later inside zend_call_function . */
2014-02-10 14:04:30 +08:00
fci . function_table = ! object ? EG ( function_table ) : NULL ;
2014-12-14 06:06:14 +08:00
result = zend_call_function ( & fci , NULL ) ;
2014-02-21 16:56:23 +08:00
zval_ptr_dtor ( & fci . function_name ) ;
2003-10-23 04:04:48 +08:00
} else {
zend_fcall_info_cache fcic ;
fcic . initialized = 1 ;
if ( ! obj_ce ) {
2014-02-10 14:04:30 +08:00
obj_ce = object ? Z_OBJCE_P ( object ) : NULL ;
2005-03-02 07:41:49 +08:00
}
if ( obj_ce ) {
function_table = & obj_ce - > function_table ;
} else {
function_table = EG ( function_table ) ;
2003-10-23 04:04:48 +08:00
}
if ( ! fn_proxy | | ! * fn_proxy ) {
2014-02-10 14:04:30 +08:00
if ( ( fcic . function_handler = zend_hash_find_ptr ( function_table , Z_STR ( fci . function_name ) ) ) = = NULL ) {
2003-10-23 04:04:48 +08:00
/* error at c-level */
2015-06-30 18:59:27 +08:00
zend_error_noreturn ( E_CORE_ERROR , " Couldn't find implementation for method %s%s%s " , obj_ce ? ZSTR_VAL ( obj_ce - > name ) : " " , obj_ce ? " :: " : " " , function_name ) ;
2003-10-23 04:04:48 +08:00
}
if ( fn_proxy ) {
* fn_proxy = fcic . function_handler ;
}
} else {
fcic . function_handler = * fn_proxy ;
}
fcic . calling_scope = obj_ce ;
2014-02-10 14:04:30 +08:00
if ( object ) {
fcic . called_scope = Z_OBJCE_P ( object ) ;
2009-03-25 18:39:26 +08:00
} else {
2015-04-23 17:16:37 +08:00
zend_class_entry * called_scope = zend_get_called_scope ( EG ( current_execute_data ) ) ;
if ( obj_ce & &
( ! called_scope | |
! instanceof_function ( called_scope , obj_ce ) ) ) {
fcic . called_scope = obj_ce ;
} else {
fcic . called_scope = called_scope ;
}
2009-03-25 18:39:26 +08:00
}
2014-03-28 06:11:22 +08:00
fcic . object = object ? Z_OBJ_P ( object ) : NULL ;
2014-12-14 06:06:14 +08:00
result = zend_call_function ( & fci , & fcic ) ;
2014-02-21 16:56:23 +08:00
zval_ptr_dtor ( & fci . function_name ) ;
2003-10-23 04:04:48 +08:00
}
if ( result = = FAILURE ) {
/* error at c-level */
if ( ! obj_ce ) {
2014-02-10 14:04:30 +08:00
obj_ce = object ? Z_OBJCE_P ( object ) : NULL ;
2003-10-23 04:04:48 +08:00
}
2006-08-28 18:27:58 +08:00
if ( ! EG ( exception ) ) {
2015-06-30 18:59:27 +08:00
zend_error_noreturn ( E_CORE_ERROR , " Couldn't execute method %s%s%s " , obj_ce ? ZSTR_VAL ( obj_ce - > name ) : " " , obj_ce ? " :: " : " " , function_name ) ;
2006-08-28 18:27:58 +08:00
}
2003-10-23 04:04:48 +08:00
}
2014-03-20 21:03:32 +08:00
/* copy arguments back, they might be changed by references */
2014-04-17 01:31:32 +08:00
if ( param_count > 0 & & Z_ISREF ( params [ 0 ] ) & & ! Z_ISREF_P ( arg1 ) ) {
2014-03-20 21:03:32 +08:00
ZVAL_COPY_VALUE ( arg1 , & params [ 0 ] ) ;
}
2014-04-17 01:31:32 +08:00
if ( param_count > 1 & & Z_ISREF ( params [ 1 ] ) & & ! Z_ISREF_P ( arg2 ) ) {
2014-03-20 21:03:32 +08:00
ZVAL_COPY_VALUE ( arg2 , & params [ 1 ] ) ;
}
2014-02-10 14:04:30 +08:00
if ( ! retval_ptr ) {
zval_ptr_dtor ( & retval ) ;
2003-10-23 04:04:48 +08:00
return NULL ;
}
2014-02-10 14:04:30 +08:00
return retval_ptr ;
2003-10-23 04:04:48 +08:00
}
/* }}} */
/* iterator interface, c-level functions used by engine */
2004-01-27 06:33:52 +08:00
/* {{{ zend_user_it_new_iterator */
2014-12-14 06:06:14 +08:00
ZEND_API void zend_user_it_new_iterator ( zend_class_entry * ce , zval * object , zval * retval )
2003-10-23 04:04:48 +08:00
{
2014-02-26 20:28:04 +08:00
zend_call_method_with_0_params ( object , ce , & ce - > iterator_funcs . zf_new_iterator , " getiterator " , retval ) ;
2003-10-23 04:04:48 +08:00
}
/* }}} */
2012-05-03 18:37:19 +08:00
/* {{{ zend_user_it_invalidate_current */
2014-12-14 06:06:14 +08:00
ZEND_API void zend_user_it_invalidate_current ( zend_object_iterator * _iter )
2004-01-27 06:33:52 +08:00
{
zend_user_iterator * iter = ( zend_user_iterator * ) _iter ;
2014-05-03 16:06:27 +08:00
if ( ! Z_ISUNDEF ( iter - > value ) ) {
2014-02-27 19:19:02 +08:00
zval_ptr_dtor ( & iter - > value ) ;
ZVAL_UNDEF ( & iter - > value ) ;
2004-01-27 06:33:52 +08:00
}
}
/* }}} */
/* {{{ zend_user_it_dtor */
2014-12-14 06:06:14 +08:00
static void zend_user_it_dtor ( zend_object_iterator * _iter )
2003-10-23 04:04:48 +08:00
{
zend_user_iterator * iter = ( zend_user_iterator * ) _iter ;
2014-02-27 19:19:02 +08:00
zval * object = & iter - > it . data ;
2003-10-23 04:04:48 +08:00
2014-12-14 06:06:14 +08:00
zend_user_it_invalidate_current ( _iter ) ;
2014-02-10 14:04:30 +08:00
zval_ptr_dtor ( object ) ;
2003-10-23 04:04:48 +08:00
}
/* }}} */
2004-03-09 02:05:41 +08:00
/* {{{ zend_user_it_valid */
2014-12-14 06:06:14 +08:00
ZEND_API int zend_user_it_valid ( zend_object_iterator * _iter )
2003-10-23 04:04:48 +08:00
{
2003-11-05 06:07:59 +08:00
if ( _iter ) {
zend_user_iterator * iter = ( zend_user_iterator * ) _iter ;
2014-02-27 19:19:02 +08:00
zval * object = & iter - > it . data ;
2014-02-10 14:04:30 +08:00
zval more ;
2003-11-05 06:07:59 +08:00
int result ;
2006-05-10 07:53:23 +08:00
2014-02-10 14:04:30 +08:00
zend_call_method_with_0_params ( object , iter - > ce , & iter - > ce - > iterator_funcs . zf_valid , " valid " , & more ) ;
if ( Z_TYPE ( more ) ! = IS_UNDEF ) {
2014-12-14 06:06:14 +08:00
result = i_zend_is_true ( & more ) ;
2003-11-18 08:01:34 +08:00
zval_ptr_dtor ( & more ) ;
2003-11-05 06:07:59 +08:00
return result ? SUCCESS : FAILURE ;
}
}
return FAILURE ;
2003-10-23 04:04:48 +08:00
}
/* }}} */
2004-01-27 06:33:52 +08:00
/* {{{ zend_user_it_get_current_data */
2014-12-14 06:06:14 +08:00
ZEND_API zval * zend_user_it_get_current_data ( zend_object_iterator * _iter )
2003-10-23 04:04:48 +08:00
{
zend_user_iterator * iter = ( zend_user_iterator * ) _iter ;
2014-02-27 19:19:02 +08:00
zval * object = & iter - > it . data ;
2003-10-23 04:04:48 +08:00
2014-05-03 16:06:27 +08:00
if ( Z_ISUNDEF ( iter - > value ) ) {
2014-02-27 19:19:02 +08:00
zend_call_method_with_0_params ( object , iter - > ce , & iter - > ce - > iterator_funcs . zf_current , " current " , & iter - > value ) ;
2015-01-03 17:22:58 +08:00
}
2014-02-27 19:19:02 +08:00
return & iter - > value ;
2003-10-23 04:04:48 +08:00
}
/* }}} */
2004-01-27 06:33:52 +08:00
/* {{{ zend_user_it_get_current_key_default */
2003-10-23 04:04:48 +08:00
#if 0
2014-12-14 06:06:14 +08:00
static int zend_user_it_get_current_key_default ( zend_object_iterator * _iter , char * * str_key , uint * str_key_len , ulong * int_key )
2003-10-23 04:04:48 +08:00
{
2003-11-11 00:13:38 +08:00
* int_key = _iter - > index ;
2014-08-26 01:24:55 +08:00
return HASH_KEY_IS_LONG ;
2003-10-23 04:04:48 +08:00
}
# endif
/* }}} */
2004-01-27 06:33:52 +08:00
/* {{{ zend_user_it_get_current_key */
2014-12-14 06:06:14 +08:00
ZEND_API void zend_user_it_get_current_key ( zend_object_iterator * _iter , zval * key )
2003-10-23 04:04:48 +08:00
{
zend_user_iterator * iter = ( zend_user_iterator * ) _iter ;
2014-02-27 19:19:02 +08:00
zval * object = & iter - > it . data ;
2014-02-10 14:04:30 +08:00
zval retval ;
2003-10-23 04:04:48 +08:00
2014-02-10 14:04:30 +08:00
zend_call_method_with_0_params ( object , iter - > ce , & iter - > ce - > iterator_funcs . zf_key , " key " , & retval ) ;
2003-10-23 04:04:48 +08:00
2014-02-10 14:04:30 +08:00
if ( Z_TYPE ( retval ) ! = IS_UNDEF ) {
ZVAL_ZVAL ( key , & retval , 1 , 1 ) ;
2013-02-17 02:13:36 +08:00
} else {
if ( ! EG ( exception ) ) {
2015-06-30 18:59:27 +08:00
zend_error ( E_WARNING , " Nothing returned from %s::key() " , ZSTR_VAL ( iter - > ce - > name ) ) ;
2005-07-20 03:46:21 +08:00
}
2006-05-12 05:07:39 +08:00
2014-08-26 01:24:55 +08:00
ZVAL_LONG ( key , 0 ) ;
2003-10-23 04:04:48 +08:00
}
}
2014-02-27 19:19:02 +08:00
/* }}} */
2003-10-23 04:04:48 +08:00
2004-01-27 06:33:52 +08:00
/* {{{ zend_user_it_move_forward */
2014-12-14 06:06:14 +08:00
ZEND_API void zend_user_it_move_forward ( zend_object_iterator * _iter )
2003-10-23 04:04:48 +08:00
{
zend_user_iterator * iter = ( zend_user_iterator * ) _iter ;
2014-02-27 19:19:02 +08:00
zval * object = & iter - > it . data ;
2003-10-23 04:04:48 +08:00
2014-12-14 06:06:14 +08:00
zend_user_it_invalidate_current ( _iter ) ;
2014-02-10 14:04:30 +08:00
zend_call_method_with_0_params ( object , iter - > ce , & iter - > ce - > iterator_funcs . zf_next , " next " , NULL ) ;
2003-10-23 04:04:48 +08:00
}
/* }}} */
2004-01-27 06:33:52 +08:00
/* {{{ zend_user_it_rewind */
2014-12-14 06:06:14 +08:00
ZEND_API void zend_user_it_rewind ( zend_object_iterator * _iter )
2003-10-23 04:04:48 +08:00
{
zend_user_iterator * iter = ( zend_user_iterator * ) _iter ;
2014-02-27 19:19:02 +08:00
zval * object = & iter - > it . data ;
2003-10-23 04:04:48 +08:00
2014-12-14 06:06:14 +08:00
zend_user_it_invalidate_current ( _iter ) ;
2014-02-10 14:04:30 +08:00
zend_call_method_with_0_params ( object , iter - > ce , & iter - > ce - > iterator_funcs . zf_rewind , " rewind " , NULL ) ;
2003-10-23 04:04:48 +08:00
}
/* }}} */
zend_object_iterator_funcs zend_interface_iterator_funcs_iterator = {
2004-01-27 06:33:52 +08:00
zend_user_it_dtor ,
2004-03-09 02:05:41 +08:00
zend_user_it_valid ,
2004-01-27 06:33:52 +08:00
zend_user_it_get_current_data ,
zend_user_it_get_current_key ,
zend_user_it_move_forward ,
2004-04-27 23:38:07 +08:00
zend_user_it_rewind ,
zend_user_it_invalidate_current
2003-10-23 04:04:48 +08:00
} ;
2004-01-27 06:33:52 +08:00
/* {{{ zend_user_it_get_iterator */
2014-12-14 06:06:14 +08:00
static zend_object_iterator * zend_user_it_get_iterator ( zend_class_entry * ce , zval * object , int by_ref )
2003-10-23 04:04:48 +08:00
{
2006-05-10 07:53:23 +08:00
zend_user_iterator * iterator ;
if ( by_ref ) {
2015-07-08 01:10:22 +08:00
zend_throw_error ( NULL , " An iterator cannot be used with foreach by reference " ) ;
2015-04-02 19:19:52 +08:00
return NULL ;
2006-05-10 07:53:23 +08:00
}
iterator = emalloc ( sizeof ( zend_user_iterator ) ) ;
2003-10-23 04:04:48 +08:00
2014-12-14 06:06:14 +08:00
zend_iterator_init ( ( zend_object_iterator * ) iterator ) ;
2014-02-26 19:01:08 +08:00
2014-02-27 19:19:02 +08:00
ZVAL_COPY ( & iterator - > it . data , object ) ;
2003-10-23 04:04:48 +08:00
iterator - > it . funcs = ce - > iterator_funcs . funcs ;
iterator - > ce = Z_OBJCE_P ( object ) ;
2014-02-27 19:19:02 +08:00
ZVAL_UNDEF ( & iterator - > value ) ;
2003-10-23 04:04:48 +08:00
return ( zend_object_iterator * ) iterator ;
}
/* }}} */
2004-01-27 06:33:52 +08:00
/* {{{ zend_user_it_get_new_iterator */
2014-12-14 06:06:14 +08:00
ZEND_API zend_object_iterator * zend_user_it_get_new_iterator ( zend_class_entry * ce , zval * object , int by_ref )
2003-10-23 04:04:48 +08:00
{
2014-02-26 20:28:04 +08:00
zval iterator ;
2003-11-18 08:18:48 +08:00
zend_object_iterator * new_iterator ;
2014-05-13 20:04:53 +08:00
zend_class_entry * ce_it ;
2003-10-23 04:04:48 +08:00
2014-12-14 06:06:14 +08:00
zend_user_it_new_iterator ( ce , object , & iterator ) ;
2014-10-09 19:58:14 +08:00
ce_it = ( Z_TYPE ( iterator ) = = IS_OBJECT ) ? Z_OBJCE ( iterator ) : NULL ;
2003-11-13 16:23:49 +08:00
2014-02-26 20:28:04 +08:00
if ( ! ce_it | | ! ce_it - > get_iterator | | ( ce_it - > get_iterator = = zend_user_it_get_new_iterator & & Z_OBJ ( iterator ) = = Z_OBJ_P ( object ) ) ) {
2006-05-10 07:53:23 +08:00
if ( ! EG ( exception ) ) {
2015-06-30 18:59:27 +08:00
zend_throw_exception_ex ( NULL , 0 , " Objects returned by %s::getIterator() must be traversable or implement interface Iterator " , ce ? ZSTR_VAL ( ce - > name ) : ZSTR_VAL ( Z_OBJCE_P ( object ) - > name ) ) ;
2005-01-25 03:18:37 +08:00
}
2014-02-26 20:28:04 +08:00
zval_ptr_dtor ( & iterator ) ;
2003-10-23 04:04:48 +08:00
return NULL ;
}
2006-05-10 07:53:23 +08:00
2014-12-14 06:06:14 +08:00
new_iterator = ce_it - > get_iterator ( ce_it , & iterator , by_ref ) ;
2014-02-26 20:28:04 +08:00
zval_ptr_dtor ( & iterator ) ;
2003-11-18 08:18:48 +08:00
return new_iterator ;
2003-10-23 04:04:48 +08:00
}
/* }}} */
/* {{{ zend_implement_traversable */
2014-12-14 06:06:14 +08:00
static int zend_implement_traversable ( zend_class_entry * interface , zend_class_entry * class_type )
2003-10-23 04:04:48 +08:00
{
/* check that class_type is traversable at c-level or implements at least one of 'aggregate' and 'Iterator' */
2014-08-26 01:28:33 +08:00
uint32_t i ;
2003-10-23 04:04:48 +08:00
2004-01-18 00:50:54 +08:00
if ( class_type - > get_iterator | | ( class_type - > parent & & class_type - > parent - > get_iterator ) ) {
2003-10-23 04:04:48 +08:00
return SUCCESS ;
2004-03-10 00:38:37 +08:00
}
2003-10-23 04:04:48 +08:00
for ( i = 0 ; i < class_type - > num_interfaces ; i + + ) {
if ( class_type - > interfaces [ i ] = = zend_ce_aggregate | | class_type - > interfaces [ i ] = = zend_ce_iterator ) {
return SUCCESS ;
}
}
2015-04-01 18:32:23 +08:00
zend_error_noreturn ( E_CORE_ERROR , " Class %s must implement interface %s as part of either %s or %s " ,
2015-06-30 18:59:27 +08:00
ZSTR_VAL ( class_type - > name ) ,
ZSTR_VAL ( zend_ce_traversable - > name ) ,
ZSTR_VAL ( zend_ce_iterator - > name ) ,
ZSTR_VAL ( zend_ce_aggregate - > name ) ) ;
2003-10-23 04:04:48 +08:00
return FAILURE ;
}
/* }}} */
/* {{{ zend_implement_aggregate */
2014-12-14 06:06:14 +08:00
static int zend_implement_aggregate ( zend_class_entry * interface , zend_class_entry * class_type )
2003-10-23 04:04:48 +08:00
{
2014-09-15 22:14:37 +08:00
uint32_t i ;
int t = - 1 ;
2005-02-23 09:09:10 +08:00
2003-10-29 02:46:37 +08:00
if ( class_type - > get_iterator ) {
if ( class_type - > type = = ZEND_INTERNAL_CLASS ) {
/* inheritance ensures the class has necessary userland methods */
return SUCCESS ;
2004-01-27 06:33:52 +08:00
} else if ( class_type - > get_iterator ! = zend_user_it_get_new_iterator ) {
2005-02-23 09:09:10 +08:00
/* c-level get_iterator cannot be changed (exception being only Traversable is implmented) */
if ( class_type - > num_interfaces ) {
2006-05-10 07:53:23 +08:00
for ( i = 0 ; i < class_type - > num_interfaces ; i + + ) {
2005-02-23 09:09:10 +08:00
if ( class_type - > interfaces [ i ] = = zend_ce_iterator ) {
2015-04-01 18:32:23 +08:00
zend_error_noreturn ( E_ERROR , " Class %s cannot implement both %s and %s at the same time " ,
2015-06-30 18:59:27 +08:00
ZSTR_VAL ( class_type - > name ) ,
ZSTR_VAL ( interface - > name ) ,
ZSTR_VAL ( zend_ce_iterator - > name ) ) ;
2005-02-23 09:09:10 +08:00
return FAILURE ;
}
if ( class_type - > interfaces [ i ] = = zend_ce_traversable ) {
t = i ;
}
}
}
if ( t = = - 1 ) {
return FAILURE ;
}
2003-10-29 02:46:37 +08:00
}
2003-10-23 04:04:48 +08:00
}
class_type - > iterator_funcs . zf_new_iterator = NULL ;
2004-01-27 06:33:52 +08:00
class_type - > get_iterator = zend_user_it_get_new_iterator ;
2003-10-23 04:04:48 +08:00
return SUCCESS ;
}
/* }}} */
/* {{{ zend_implement_iterator */
2014-12-14 06:06:14 +08:00
static int zend_implement_iterator ( zend_class_entry * interface , zend_class_entry * class_type )
2003-10-23 04:04:48 +08:00
{
2004-01-27 06:33:52 +08:00
if ( class_type - > get_iterator & & class_type - > get_iterator ! = zend_user_it_get_iterator ) {
2003-10-29 02:46:37 +08:00
if ( class_type - > type = = ZEND_INTERNAL_CLASS ) {
/* inheritance ensures the class has the necessary userland methods */
return SUCCESS ;
2010-02-01 21:45:57 +08:00
} else {
2003-10-29 02:46:37 +08:00
/* c-level get_iterator cannot be changed */
2010-02-01 21:45:57 +08:00
if ( class_type - > get_iterator = = zend_user_it_get_new_iterator ) {
2015-04-01 18:32:23 +08:00
zend_error_noreturn ( E_ERROR , " Class %s cannot implement both %s and %s at the same time " ,
2015-06-30 18:59:27 +08:00
ZSTR_VAL ( class_type - > name ) ,
ZSTR_VAL ( interface - > name ) ,
ZSTR_VAL ( zend_ce_aggregate - > name ) ) ;
2010-02-01 21:45:57 +08:00
}
2003-10-29 02:46:37 +08:00
return FAILURE ;
}
2003-10-23 04:04:48 +08:00
}
2004-01-27 06:33:52 +08:00
class_type - > get_iterator = zend_user_it_get_iterator ;
2004-03-09 02:05:41 +08:00
class_type - > iterator_funcs . zf_valid = NULL ;
2003-10-23 04:04:48 +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 ;
}
/* }}} */
2003-11-25 04:57:54 +08:00
/* {{{ zend_implement_arrayaccess */
2014-12-14 06:06:14 +08:00
static int zend_implement_arrayaccess ( zend_class_entry * interface , zend_class_entry * class_type )
2003-11-25 04:57:54 +08:00
{
2004-01-27 06:33:52 +08:00
#if 0
/* get ht from ce */
if ( ht - > read_dimension ! = zend_std_read_dimension
| | ht - > write_dimension ! = zend_std_write_dimension
| | ht - > has_dimension ! = zend_std_has_dimension
| | ht - > unset_dimension ! = zend_std_unset_dimension ) {
return FAILURE ;
}
# endif
2003-11-25 04:57:54 +08:00
return SUCCESS ;
}
/* }}}*/
2005-03-08 06:23:14 +08:00
/* {{{ zend_user_serialize */
2014-12-14 06:06:14 +08:00
ZEND_API int zend_user_serialize ( zval * object , unsigned char * * buffer , size_t * buf_len , zend_serialize_data * data )
2005-03-08 06:23:14 +08:00
{
zend_class_entry * ce = Z_OBJCE_P ( object ) ;
2014-02-10 14:04:30 +08:00
zval retval ;
2005-03-08 06:23:14 +08:00
int result ;
2014-02-10 14:04:30 +08:00
zend_call_method_with_0_params ( object , ce , & ce - > serialize_func , " serialize " , & retval ) ;
2005-03-08 06:23:14 +08:00
2014-02-10 14:04:30 +08:00
if ( Z_TYPE ( retval ) = = IS_UNDEF | | EG ( exception ) ) {
2005-03-08 06:23:14 +08:00
result = FAILURE ;
} else {
2014-02-10 14:04:30 +08:00
switch ( Z_TYPE ( retval ) ) {
2005-03-08 06:23:14 +08:00
case IS_NULL :
/* we could also make this '*buf_len = 0' but this allows to skip variables */
2005-04-05 17:16:27 +08:00
zval_ptr_dtor ( & retval ) ;
return FAILURE ;
2005-03-08 06:23:14 +08:00
case IS_STRING :
2014-08-26 01:24:55 +08:00
* buffer = ( unsigned char * ) estrndup ( Z_STRVAL ( retval ) , Z_STRLEN ( retval ) ) ;
* buf_len = Z_STRLEN ( retval ) ;
2005-03-08 06:23:14 +08:00
result = SUCCESS ;
break ;
default : /* failure */
result = FAILURE ;
break ;
}
zval_ptr_dtor ( & retval ) ;
}
2013-03-09 23:08:14 +08:00
if ( result = = FAILURE & & ! EG ( exception ) ) {
2015-06-30 18:59:27 +08:00
zend_throw_exception_ex ( NULL , 0 , " %s::serialize() must return a string or NULL " , ZSTR_VAL ( ce - > name ) ) ;
2005-03-08 06:23:14 +08:00
}
return result ;
}
/* }}} */
/* {{{ zend_user_unserialize */
2014-12-14 06:06:14 +08:00
ZEND_API int zend_user_unserialize ( zval * object , zend_class_entry * ce , const unsigned char * buf , size_t buf_len , zend_unserialize_data * data )
2005-03-08 06:23:14 +08:00
{
2014-02-10 14:04:30 +08:00
zval zdata ;
2005-03-08 06:23:14 +08:00
2015-04-02 07:05:25 +08:00
if ( UNEXPECTED ( object_init_ex ( object , ce ) ! = SUCCESS ) ) {
return FAILURE ;
}
2006-05-10 07:53:23 +08:00
2014-02-10 14:04:30 +08:00
ZVAL_STRINGL ( & zdata , ( char * ) buf , buf_len ) ;
2005-03-08 06:23:14 +08:00
2014-02-10 14:04:30 +08:00
zend_call_method_with_1_params ( object , ce , & ce - > unserialize_func , " unserialize " , NULL , & zdata ) ;
2006-05-10 07:53:23 +08:00
2005-03-08 06:23:14 +08:00
zval_ptr_dtor ( & zdata ) ;
2006-05-10 07:53:23 +08:00
2005-03-08 06:23:14 +08:00
if ( EG ( exception ) ) {
return FAILURE ;
} else {
return SUCCESS ;
}
}
/* }}} */
2014-12-14 06:06:14 +08:00
ZEND_API int zend_class_serialize_deny ( zval * object , unsigned char * * buffer , size_t * buf_len , zend_serialize_data * data ) /* { { { */
2008-12-22 22:11:49 +08:00
{
zend_class_entry * ce = Z_OBJCE_P ( object ) ;
2015-06-30 18:59:27 +08:00
zend_throw_exception_ex ( NULL , 0 , " Serialization of '%s' is not allowed " , ZSTR_VAL ( ce - > name ) ) ;
2008-12-22 22:11:49 +08:00
return FAILURE ;
}
/* }}} */
2014-12-14 06:06:14 +08:00
ZEND_API int zend_class_unserialize_deny ( zval * object , zend_class_entry * ce , const unsigned char * buf , size_t buf_len , zend_unserialize_data * data ) /* { { { */
2008-12-22 22:11:49 +08:00
{
2015-06-30 18:59:27 +08:00
zend_throw_exception_ex ( NULL , 0 , " Unserialization of '%s' is not allowed " , ZSTR_VAL ( ce - > name ) ) ;
2008-12-22 22:11:49 +08:00
return FAILURE ;
}
/* }}} */
2005-03-19 09:11:48 +08:00
/* {{{ zend_implement_serializable */
2014-12-14 06:06:14 +08:00
static int zend_implement_serializable ( zend_class_entry * interface , zend_class_entry * class_type )
2005-03-08 06:23:14 +08:00
{
2008-08-25 02:22:33 +08:00
if ( class_type - > parent
& & ( class_type - > parent - > serialize | | class_type - > parent - > unserialize )
2014-12-14 06:06:14 +08:00
& & ! instanceof_function_ex ( class_type - > parent , zend_ce_serializable , 1 ) ) {
2005-03-08 06:23:14 +08:00
return FAILURE ;
}
2008-08-25 02:22:33 +08:00
if ( ! class_type - > serialize ) {
class_type - > serialize = zend_user_serialize ;
}
if ( ! class_type - > unserialize ) {
class_type - > unserialize = zend_user_unserialize ;
}
2005-03-08 06:23:14 +08:00
return SUCCESS ;
}
/* }}}*/
2003-10-23 04:04:48 +08:00
/* {{{ function tables */
2007-09-28 02:00:48 +08:00
const zend_function_entry zend_funcs_aggregate [ ] = {
2003-10-23 04:04:48 +08:00
ZEND_ABSTRACT_ME ( iterator , getIterator , NULL )
2014-12-13 02:57:34 +08:00
ZEND_FE_END
2003-10-23 04:04:48 +08:00
} ;
2007-09-28 02:00:48 +08:00
const zend_function_entry zend_funcs_iterator [ ] = {
2003-10-23 04:04:48 +08:00
ZEND_ABSTRACT_ME ( iterator , current , NULL )
ZEND_ABSTRACT_ME ( iterator , next , NULL )
ZEND_ABSTRACT_ME ( iterator , key , NULL )
2004-03-09 01:33:31 +08:00
ZEND_ABSTRACT_ME ( iterator , valid , NULL )
2003-11-11 00:13:38 +08:00
ZEND_ABSTRACT_ME ( iterator , rewind , NULL )
2014-12-13 02:57:34 +08:00
ZEND_FE_END
2003-10-23 04:04:48 +08:00
} ;
2007-09-28 02:00:48 +08:00
const zend_function_entry * zend_funcs_traversable = NULL ;
2003-11-25 04:57:54 +08:00
2005-03-14 00:34:37 +08:00
ZEND_BEGIN_ARG_INFO_EX ( arginfo_arrayaccess_offset , 0 , 0 , 1 )
2003-11-25 04:57:54 +08:00
ZEND_ARG_INFO ( 0 , offset )
2007-05-31 00:32:02 +08:00
ZEND_END_ARG_INFO ( )
2003-11-25 04:57:54 +08:00
2005-03-14 00:34:37 +08:00
ZEND_BEGIN_ARG_INFO_EX ( arginfo_arrayaccess_offset_get , 0 , 0 , 1 ) /* actually this should be return by ref but atm cannot be */
ZEND_ARG_INFO ( 0 , offset )
2007-05-31 00:32:02 +08:00
ZEND_END_ARG_INFO ( )
2005-03-14 00:34:37 +08:00
2006-05-10 07:53:23 +08:00
ZEND_BEGIN_ARG_INFO_EX ( arginfo_arrayaccess_offset_value , 0 , 0 , 2 )
2003-11-25 04:57:54 +08:00
ZEND_ARG_INFO ( 0 , offset )
ZEND_ARG_INFO ( 0 , value )
2007-05-31 00:32:02 +08:00
ZEND_END_ARG_INFO ( )
2003-11-25 04:57:54 +08:00
2007-09-28 02:00:48 +08:00
const zend_function_entry zend_funcs_arrayaccess [ ] = {
2003-11-25 04:57:54 +08:00
ZEND_ABSTRACT_ME ( arrayaccess , offsetExists , arginfo_arrayaccess_offset )
2005-03-14 00:34:37 +08:00
ZEND_ABSTRACT_ME ( arrayaccess , offsetGet , arginfo_arrayaccess_offset_get )
2003-11-25 04:57:54 +08:00
ZEND_ABSTRACT_ME ( arrayaccess , offsetSet , arginfo_arrayaccess_offset_value )
ZEND_ABSTRACT_ME ( arrayaccess , offsetUnset , arginfo_arrayaccess_offset )
2014-12-13 02:57:34 +08:00
ZEND_FE_END
2003-11-25 04:57:54 +08:00
} ;
2005-03-19 09:11:48 +08:00
ZEND_BEGIN_ARG_INFO ( arginfo_serializable_serialize , 0 )
2005-03-08 06:23:14 +08:00
ZEND_ARG_INFO ( 0 , serialized )
2007-05-31 00:32:02 +08:00
ZEND_END_ARG_INFO ( )
2005-03-08 06:23:14 +08:00
2007-09-28 02:00:48 +08:00
const zend_function_entry zend_funcs_serializable [ ] = {
2005-03-19 09:11:48 +08:00
ZEND_ABSTRACT_ME ( serializable , serialize , NULL )
2006-05-10 07:53:23 +08:00
ZEND_FENTRY ( unserialize , NULL , arginfo_serializable_serialize , ZEND_ACC_PUBLIC | ZEND_ACC_ABSTRACT | ZEND_ACC_CTOR )
2014-12-13 02:57:34 +08:00
ZEND_FE_END
2005-03-08 06:23:14 +08:00
} ;
2003-10-23 04:04:48 +08:00
/* }}} */
/* {{{ zend_register_interfaces */
2014-12-14 06:06:14 +08:00
ZEND_API void zend_register_interfaces ( void )
2003-10-23 04:04:48 +08:00
{
2015-06-18 02:46:27 +08:00
REGISTER_MAGIC_INTERFACE ( traversable , Traversable ) ;
2003-10-23 04:04:48 +08:00
2015-06-18 02:46:27 +08:00
REGISTER_MAGIC_INTERFACE ( aggregate , IteratorAggregate ) ;
REGISTER_MAGIC_IMPLEMENT ( aggregate , traversable ) ;
2003-10-23 04:04:48 +08:00
2015-06-18 02:46:27 +08:00
REGISTER_MAGIC_INTERFACE ( iterator , Iterator ) ;
REGISTER_MAGIC_IMPLEMENT ( iterator , traversable ) ;
2006-05-10 07:53:23 +08:00
2015-06-18 02:46:27 +08:00
REGISTER_MAGIC_INTERFACE ( arrayaccess , ArrayAccess ) ;
2015-05-17 04:30:59 +08:00
2015-06-18 02:46:27 +08:00
REGISTER_MAGIC_INTERFACE ( serializable , Serializable ) ;
2003-10-23 04:04:48 +08:00
}
/* }}} */
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* indent - tabs - mode : t
* End :
*/