Dealing with a Variable Number of Arguments/Optional Parameters
If your function is meant to accept a variable number of
arguments, the snippets just described are sometimes suboptimal
solutions_ You have to create a line calling
zend_get_parameters_ex() for every possible
number of arguments, which is often unsatisfying_
For this case, you can use the
function zend_get_parameters_array_ex(), which accepts the
number of parameters to retrieve and an array in which to store them:
zval **parameter_array[4];
/* get the number of arguments */
argument_count = ZEND_NUM_ARGS();
/* see if it satisfies our minimal request (2 arguments) */
/* and our maximal acceptance (4 arguments) */
if(argument_count < 2 || argument_count > 5)
WRONG_PARAM_COUNT;
/* argument count is correct, now retrieve arguments */
if(zend_get_parameters_array_ex(argument_count, parameter_array) != SUCCESS)
WRONG_PARAM_COUNT; |
First, the number of arguments is checked to make sure that it's in the accepted range_ After that,
zend_get_parameters_array_ex() is used to
fill
parameter_array with valid pointers to the argument
values_
A very clever implementation of this can be found in the code
handling PHP's fsockopen() located in
ext/standard/fsock_c, as shown in
Ejemplo 32_1_ Don't worry if you don't know all the functions used in this
source yet; we'll get to them shortly_
Ejemplo 32_1_ PHP's implementation of variable arguments in fsockopen()_ pval **args[5];
int *sock=emalloc(sizeof(int));
int *sockp;
int arg_count=ARG_COUNT(ht);
int socketd = _1;
unsigned char udp = 0;
struct timeval timeout = { 60, 0 };
unsigned short portno;
unsigned long conv;
char *key = NULL;
FLS_FETCH();
if (arg_count > 5 || arg_count < 2 || zend_get_parameters_array_ex(arg_count,args)==FAILURE) {
CLOSE_SOCK(1);
WRONG_PARAM_COUNT;
}
switch(arg_count) {
case 5:
convert_to_double_ex(args[4]);
conv = (unsigned long) (Z_DVAL_P(args[4]) * 1000000_0);
timeout_tv_sec = conv / 1000000;
timeout_tv_usec = conv % 1000000;
/* fall_through */
case 4:
if (!PZVAL_IS_REF(*args[3])) {
php_error(E_WARNING,"error string argument to fsockopen not passed by reference");
}
pval_copy_constructor(*args[3]);
ZVAL_EMPTY_STRING(*args[3]);
/* fall_through */
case 3:
if (!PZVAL_IS_REF(*args[2])) {
php_error(E_WARNING,"error argument to fsockopen not passed by reference");
return;
}
ZVAL_LONG(*args[2], 0);
break;
}
convert_to_string_ex(args[0]);
convert_to_long_ex(args[1]);
portno = (unsigned short) Z_LVAL_P(args[1]);
key = emalloc(Z_STRLEN_P(args[0]) + 10); |
|
fsockopen() accepts two, three, four, or five
parameters_ After the obligatory variable declarations, the
function checks for the correct range of arguments_ Then it uses a
fall_through mechanism in a switch() statement
to deal with all arguments_ The switch()
statement starts with the maximum number of arguments being passed
(five)_ After that, it automatically processes the case of four
arguments being passed, then three, by omitting the otherwise
obligatory break keyword in all stages_ After
having processed the last case, it exits the
switch() statement and does the minimal
argument processing needed if the function is invoked with only
two arguments_
This multiple_stage type of processing, similar to a stairway, allows
convenient processing of a variable number of arguments_