diff options
author | Andrei Zmievski <andrei@php.net> | 2006-10-11 18:37:31 +0000 |
---|---|---|
committer | Andrei Zmievski <andrei@php.net> | 2006-10-11 18:37:31 +0000 |
commit | 97d0372249ffb1fc54e3626781bc012dfcaabb77 (patch) | |
tree | c898e0994645d121cb49187e66227f66e60ddea8 | |
parent | 104c8286622c0613b4b20ea550259b5946c04f48 (diff) | |
download | php-git-97d0372249ffb1fc54e3626781bc012dfcaabb77.tar.gz |
Extend zend_fcall_info_args functions. (Patch from Mike Wallner)
-rw-r--r-- | Zend/zend_API.c | 83 | ||||
-rw-r--r-- | Zend/zend_API.h | 9 |
2 files changed, 72 insertions, 20 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 9491c6f3e8..3ebede95a5 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -777,7 +777,7 @@ static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **sp break; } - if (zend_fcall_info_init(*arg, fci, fcc TSRMLS_CC) == SUCCESS) { + if (zend_fcall_info_init(*arg, fci, fcc, NULL TSRMLS_CC) == SUCCESS) { break; } else { return "valid callback"; @@ -2744,13 +2744,13 @@ ZEND_API zend_bool zend_make_callable(zval *callable, zval *callable_name TSRMLS } -ZEND_API int zend_fcall_info_init(zval *callable, zend_fcall_info *fci, zend_fcall_info_cache *fcc TSRMLS_DC) +ZEND_API int zend_fcall_info_init(zval *callable, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval *callable_name TSRMLS_DC) { zend_class_entry *ce; zend_function *func; zval **obj; - if (!zend_is_callable_ex(callable, IS_CALLABLE_STRICT, NULL, &ce, &func, &obj TSRMLS_CC)) { + if (!zend_is_callable_ex(callable, IS_CALLABLE_STRICT, callable_name, &ce, &func, &obj TSRMLS_CC)) { return FAILURE; } @@ -2772,20 +2772,41 @@ ZEND_API int zend_fcall_info_init(zval *callable, zend_fcall_info *fci, zend_fca return SUCCESS; } - -ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC) +static inline void zend_fcall_info_args_clear(zend_fcall_info *fci, int free_mem) { - HashPosition pos; - zval **arg, ***params; - if (fci->params) { while (fci->param_count) { zval_ptr_dtor(fci->params[--fci->param_count]); } - efree(fci->params); + if (free_mem) { + efree(fci->params); + fci->params = NULL; + } } - fci->params = NULL; fci->param_count = 0; +} + +static inline void zend_fcall_info_args_save(zend_fcall_info *fci, int *param_count, zval ****params) +{ + *param_count = fci->param_count; + *params = fci->params; + fci->param_count = 0; + fci->params = NULL; +} + +static inline void zend_fcall_info_args_restore(zend_fcall_info *fci, int param_count, zval ***params) +{ + zend_fcall_info_args_clear(fci, 1); + fci->param_count = param_count; + fci->params = params; +} + +ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC) +{ + HashPosition pos; + zval **arg, ***params; + + zend_fcall_info_args_clear(fci, !args); if (!args) { return SUCCESS; @@ -2796,18 +2817,45 @@ ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC) } fci->param_count = zend_hash_num_elements(Z_ARRVAL_P(args)); - fci->params = params = (zval***)safe_emalloc(sizeof(zval**), fci->param_count, 0); + fci->params = params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **)); zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(args), &pos); - - while (zend_hash_get_current_data_ex(Z_ARRVAL_P(args), (void **) &arg, &pos) == SUCCESS) { + while (zend_hash_get_current_data_ex(Z_ARRVAL_P(args), (void *) &arg, &pos) == SUCCESS) { *params++ = arg; - (*arg)->refcount++; + ZVAL_ADDREF(*arg); zend_hash_move_forward_ex(Z_ARRVAL_P(args), &pos); } + return SUCCESS; } +ZEND_API int zend_fcall_info_argn(zend_fcall_info *fci TSRMLS_DC, int argc, ...) +{ + int i; + zval **arg; + va_list argv; + + if (argc < 0) { + return FAILURE; + } + + zend_fcall_info_args_clear(fci, !argc); + + if (argc) { + fci->param_count = argc; + fci->params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **)); + + va_start(argv, argc); + for (i = 0; i < argc; ++i) { + arg = va_arg(argv, zval **); + ZVAL_ADDREF(*arg); + fci->params[i] = arg; + } + va_end(argv); + } + + return SUCCESS; +} ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval **retval_ptr_ptr, zval *args TSRMLS_DC) { @@ -2816,8 +2864,7 @@ ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *f fci->retval_ptr_ptr = retval_ptr_ptr ? retval_ptr_ptr : &retval; if (args) { - org_params = fci->params; - org_count = fci->param_count; + zend_fcall_info_args_save(fci, &org_count, &org_params); zend_fcall_info_args(fci, args TSRMLS_CC); } result = zend_call_function(fci, fcc TSRMLS_CC); @@ -2826,9 +2873,7 @@ ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *f zval_ptr_dtor(&retval); } if (args) { - zend_fcall_info_args(fci, NULL TSRMLS_CC); - fci->params = org_params; - fci->param_count = org_count; + zend_fcall_info_args_restore(fci, org_count, org_params); } return result; } diff --git a/Zend/zend_API.h b/Zend/zend_API.h index d3121a1e06..8922f3899e 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -1373,14 +1373,21 @@ ZEND_API extern zend_fcall_info_cache empty_fcall_info_cache; * In order to pass parameters the following members need to be set: * fci->param_count = 0; * fci->params = NULL; + * The callable_name argument may be NULL. */ -ZEND_API int zend_fcall_info_init(zval *callable, zend_fcall_info *fci, zend_fcall_info_cache *fcc TSRMLS_DC); +ZEND_API int zend_fcall_info_init(zval *callable, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval *callable_name TSRMLS_DC); /** Set or clear the arguments in the zend_call_info struct taking care of * refcount. If args is NULL and arguments are set then those are cleared. */ ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC); +/** Set arguments in the zend_fcall_info struct taking care of refcount. + * If argc is 0 the arguments which are set will be cleared, else pass + * a variable amount of zval** arguments. + */ +ZEND_API int zend_fcall_info_argn(zend_fcall_info *fci TSRMLS_DC, int argc, ...); + /** Call a function using information created by zend_fcall_info_init()/args(). * If args is given then those replace the arguement info in fci is temporarily. */ |