Sommaire
Gestion des arguments
Compter le nombre d'arguments
Lecture des arguments
L'ancienne technique de lecture des arguments (obsolète)
Cas des nombres variables de paramètres et des arguments optionnels
Accéder aux arguments
Cas des arguments passés par référence
Assurer la protection en écriture des autres paramètres
|
7.10.4 Cas des nombres variables de paramètres et des arguments optionnels
Si votre fonction est prévue pour accepter un nombre
variable de paramètres, les codes que nous avons présentés
ci-dessus sont parfois sous optimaux. You devez coder une ligne
qui appelle zend_get_parameters_ex
pour chaque nombre d'argument possible, ce qui est
fastidieux.
Dans ce cas, vous pouvez utiliser la fonction
zend_get_parameters_array_ex, qui prend un
nombre d'arguments à lire, et un tableau dans lequel stocker ces
valeurs :
zval **parameter_array[4]; /* lit le nombre d'arguments */ argument_count = ZEND_NUM_ARGS(); /* voit si il satisfait notre nombre minimum d'arguments (ici, 2 arguments) */ /* et notre nombre maximal d'arguments (ici, 4 arguments) */ if(argument_count < 2 || argument_count > 5) WRONG_PARAM_COUNT; /* le nombre d'arguments est correct, lisons maintenant les valeurs des arguments */ if(zend_get_parameters_array_ex(argument_count, parameter_array) != SUCCESS) WRONG_PARAM_COUNT;
Tout d'abord, le nombre d'argument passé est vérifié, pour
être sur qu'il soit dans l'intervalle de validité. Ensuite,
zend_get_parameters_array_ex est appelée pour
remplir le tableauparameter_array avec des pointeurs
valides vers les valeurs des arguments.
Une implémentation très habile peut être lue dans le code
C de gestion de fsockopen située dans
ext/standard/fsock.c
, comme illustré dans
<>. Ne vous inquiétez pas si
vous ne reconnaissez pas toutes les fonctions de ce code source :
nous allons les présenter sous peu.
Implémentation de la gestion du nombre variable de paramètres. |
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 accepte deux, trois, quatre ou cinq
paramètres. Après la déclaration obligatoire des variables,
la fonction vérifie si le nombre d'arguments passé est dans l'intervalle
autorisé. Puis, il utilise un mécanisme de fall-through
dans le switch() pour traiter progressivement
tous les arguments. La structure switch()
commence avec le nombre maximum d'arguments (ici, 5). Puis,
il traite automatiquement le cas de 4 arguments, puis trois.
Cela est fait en omettant la structure break
à chaque étage. Après avoir traité le dernier cas, il sort du
switch() et traite le cas du nombre minimum
d'arguments (ici 2).
Cette technique de cascade est une méthode très pratique
pour traiter le cas des nombres variables de paramètres.
|