SommaireTelecharger la documentationChapitre suivantChapitre precedent  

  .: News :.: Edito :.: Scripts :.: Forum :.: Erreurs :.: Jobs :. 
 
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.


Chapitre précédentChapitre suivantAccueil nexen.net