Annotation of embedaddon/php/README.PARAMETER_PARSING_API, revision 1.1

1.1     ! misho       1: New parameter parsing functions
        !             2: ===============================
        !             3: 
        !             4: It should be easier to parse input parameters to an extension function.
        !             5: Hence, borrowing from Python's example, there are now a set of functions
        !             6: that given the string of type specifiers, can parse the input parameters
        !             7: and store the results in the user specified variables. This avoids most
        !             8: of the IS_* checks and convert_to_* conversions. The functions also
        !             9: check for the appropriate number of parameters, and try to output
        !            10: meaningful error messages.
        !            11: 
        !            12: 
        !            13: Prototypes
        !            14: ----------
        !            15: /* Implemented. */
        !            16: int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...);
        !            17: int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *type_spec, ...);
        !            18: 
        !            19: The zend_parse_parameters() function takes the number of parameters
        !            20: passed to the extension function, the type specifier string, and the
        !            21: list of pointers to variables to store the results in. The _ex() version
        !            22: also takes 'flags' argument -- current only ZEND_PARSE_PARAMS_QUIET can
        !            23: be used as 'flags' to specify that the function should operate quietly
        !            24: and not output any error messages.
        !            25: 
        !            26: Both functions return SUCCESS or FAILURE depending on the result.
        !            27: 
        !            28: The auto-conversions are performed as necessary. Arrays, objects, and
        !            29: resources cannot be auto-converted.
        !            30: 
        !            31: 
        !            32: Type specifiers
        !            33: ---------------
        !            34:  The following list shows the type specifier, its meaning and the parameter 
        !            35:  types that need to be passed by address. All passed paramaters are set
        !            36:  if the PHP parameter is non optional and untouched if optional and the 
        !            37:  parameter is not present. The only exception is O where the zend_class_entry*
        !            38:  has to be provided on input and is used to verify the PHP parameter is an 
        !            39:  instance of that class.
        !            40: 
        !            41:  a  - array (zval*)
        !            42:  A  - array or object (zval *)
        !            43:  b  - boolean (zend_bool)
        !            44:  C  - class (zend_class_entry*)
        !            45:  d  - double (double)
        !            46:  f  - function or array containing php method call info (returned as 
        !            47:       zend_fcall_info and zend_fcall_info_cache)
        !            48:  h  - array (returned as HashTable*)
        !            49:  H  - array or HASH_OF(object) (returned as HashTable*)
        !            50:  l  - long (long)
        !            51:  L  - long, limits out-of-range numbers to LONG_MAX/LONG_MIN (long)
        !            52:  o  - object of any type (zval*)
        !            53:  O  - object of specific type given by class entry (zval*, zend_class_entry)
        !            54:  r  - resource (zval*)
        !            55:  s  - string (with possible null bytes) and its length (char*, int)
        !            56:  z  - the actual zval (zval*)
        !            57:  Z  - the actual zval (zval**)
        !            58:  *  - variable arguments list (0 or more)
        !            59:  +  - variable arguments list (1 or more)
        !            60: 
        !            61:  The following characters also have a meaning in the specifier string:
        !            62:     | - indicates that the remaining parameters are optional, they
        !            63:         should be initialized to default values by the extension since they
        !            64:         will not be touched by the parsing function if they are not
        !            65:         passed to it.
        !            66:     / - use SEPARATE_ZVAL_IF_NOT_REF() on the parameter it follows
        !            67:     ! - the parameter it follows can be of specified type or NULL (applies
        !            68:                to all specifiers except for 'b', 'l', and 'd'). If NULL is passed, the
        !            69:                results pointer is set to NULL as well.
        !            70: 
        !            71: 
        !            72: Note on 64bit compatibility
        !            73: ---------------------------
        !            74: Please do not forget that int and long are two different things on 64bit 
        !            75: OSes (int is 4 bytes and long is 8 bytes), so make sure you pass longs to "l" 
        !            76: and ints to strings length (i.e. for "s" you need to pass char * and int), 
        !            77: not the other way round!
        !            78: Remember: "l" is the only case when you need to pass long (and that's why 
        !            79: it's "l", not "i" btw).
        !            80: 
        !            81: Both mistakes cause memory corruptions and segfaults on 64bit OSes:
        !            82: 1)
        !            83:   char *str;
        !            84:   long str_len; /* XXX THIS IS WRONG!! Use int instead. */
        !            85:   zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len)
        !            86: 
        !            87: 2)
        !            88:   int num; /* XXX THIS IS WRONG!! Use long instead. */
        !            89:   zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &num)
        !            90: 
        !            91: If you're in doubt, use check_parameters.php script to the parameters 
        !            92: and their types (it can be found in ./scripts/dev/ directory of PHP sources):
        !            93: 
        !            94: # php ./scripts/dev/check_parameters.php /path/to/your/sources/
        !            95: 
        !            96: 
        !            97: Examples
        !            98: --------
        !            99: /* Gets a long, a string and its length, and a zval */
        !           100: long l;
        !           101: char *s;
        !           102: int s_len;
        !           103: zval *param;
        !           104: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lsz",
        !           105:                           &l, &s, &s_len, &param) == FAILURE) {
        !           106:     return;
        !           107: }
        !           108: 
        !           109: 
        !           110: /* Gets an object of class specified by my_ce, and an optional double. */
        !           111: zval *obj;
        !           112: double d = 0.5;
        !           113: zend_class_entry *my_ce;
        !           114: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|d",
        !           115:                           &obj, my_ce, &d) == FAILURE) {
        !           116:     return;
        !           117: }
        !           118: 
        !           119: 
        !           120: /* Gets an object or null, and an array.
        !           121:    If null is passed for object, obj will be set to NULL. */
        !           122: zval *obj;
        !           123: zval *arr;
        !           124: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o!a",
        !           125:                           &obj, &arr) == FAILURE) {
        !           126:     return;
        !           127: }
        !           128: 
        !           129: 
        !           130: /* Gets a separated array which can also be null. */
        !           131: zval *arr;
        !           132: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/!",
        !           133:                           &arr) == FAILURE) {
        !           134:     return;
        !           135: }
        !           136: 
        !           137: /* Get either a set of 3 longs or a string. */
        !           138: long l1, l2, l3;
        !           139: char *s;
        !           140: /* 
        !           141:  * The function expects a pointer to a integer in this case, not a long
        !           142:  * or any other type.  If you specify a type which is larger
        !           143:  * than a 'int', the upper bits might not be initialized
        !           144:  * properly, leading to random crashes on platforms like
        !           145:  * Tru64 or Linux/Alpha.
        !           146:  */
        !           147: int length;
        !           148: 
        !           149: if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
        !           150:                              "lll", &l1, &l2, &l3) == SUCCESS) {
        !           151:     /* manipulate longs */
        !           152: } else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
        !           153:                                     "s", &s, &length) == SUCCESS) {
        !           154:     /* manipulate string */
        !           155: } else {
        !           156:     /* output error */
        !           157: 
        !           158:     return;
        !           159: }
        !           160: 
        !           161: 
        !           162: /* Function that accepts only varargs (0 or more) */
        !           163: 
        !           164: int i, num_varargs;
        !           165: zval ***varargs = NULL;
        !           166: 
        !           167: 
        !           168: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "*", &varargs, &num_varargs) == FAILURE) {
        !           169:     return;
        !           170: }
        !           171: 
        !           172: for (i = 0; i < num_varargs; i++) {
        !           173:     /* do something with varargs[i] */
        !           174: }
        !           175: 
        !           176: if (varargs) {
        !           177:     efree(varargs);
        !           178: }
        !           179: 
        !           180: 
        !           181: /* Function that accepts a string, followed by varargs (1 or more) */
        !           182: 
        !           183: char *str;
        !           184: int str_len;
        !           185: int i, num_varargs;
        !           186: zval ***varargs = NULL;
        !           187: 
        !           188: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s+", &str, &str_len, &varargs, &num_varargs) == FAILURE) {
        !           189:     return;
        !           190: }
        !           191: 
        !           192: for (i = 0; i < num_varargs; i++) {
        !           193:     /* do something with varargs[i] */
        !           194: }
        !           195: 
        !           196: if (varargs) {
        !           197:     efree(varargs);
        !           198: }
        !           199: 
        !           200: 
        !           201: /* Function that takes an array, followed by varargs, and ending with a long */
        !           202: long num;
        !           203: zval *array;
        !           204: int i, num_varargs;
        !           205: zval ***varargs = NULL;
        !           206: 
        !           207: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a*l", &array, &varargs, &num_varargs, &num) == FAILURE) {
        !           208:     return;
        !           209: }
        !           210: 
        !           211: for (i = 0; i < num_varargs; i++) {
        !           212:     /* do something with varargs[i] */
        !           213: }
        !           214: 
        !           215: if (varargs) {
        !           216:     efree(varargs);
        !           217: }
        !           218: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>