diff options
author | Peter Kokot <peterkokot@gmail.com> | 2019-04-21 15:33:20 +0200 |
---|---|---|
committer | Peter Kokot <peterkokot@gmail.com> | 2019-04-21 15:33:20 +0200 |
commit | 1c94aac89e0d7dfbd5efc15ec1862214b22603d1 (patch) | |
tree | d03f294d1354b121d5f8bf0daa681f92c750bed1 /docs/parameter-parsing-api.md | |
parent | 80f3c69ae925b09068b0642306a8a14a42c7d25c (diff) | |
download | php-git-1c94aac89e0d7dfbd5efc15ec1862214b22603d1.tar.gz |
[ci skip] Fix CS in Markdown files
Checked and quickfixed with Markdown linter
- 80 columns line width (~)
- code highlighting
- ...
Some most obvious outdated content updated a bit more.
Diffstat (limited to 'docs/parameter-parsing-api.md')
-rw-r--r-- | docs/parameter-parsing-api.md | 210 |
1 files changed, 106 insertions, 104 deletions
diff --git a/docs/parameter-parsing-api.md b/docs/parameter-parsing-api.md index f65c19a723..d4d24b1dbf 100644 --- a/docs/parameter-parsing-api.md +++ b/docs/parameter-parsing-api.md @@ -1,133 +1,140 @@ -Fast Parameter Parsing API -========================== +# Fast Parameter Parsing API -In PHP 7, a "Fast Parameter Parsing API" was introduced. See +In PHP 7, a "Fast Parameter Parsing API" was introduced. See +[RFC](https://wiki.php.net/rfc/fast_zpp). - https://wiki.php.net/rfc/fast_zpp +This API uses inlining to improve applications performance compared with the +`zend_parse_parameters()` function described below. -This API uses inlining to improve applications performance compared -with the zend_parse_parameters() function described below. +## Parameter parsing functions +Borrowing from Python's example, there is a set of functions that given the +string of type specifiers, can parse the input parameters and store the results +in the user specified variables. This avoids using `IS_*` checks and +`convert_to_*` conversions. The functions also check for the appropriate number +of parameters, and try to output meaningful error messages. -Parameter parsing functions -=========================== +## Prototypes -Borrowing from Python's example, there is a set of functions that -given the string of type specifiers, can parse the input parameters -and store the results in the user specified variables. This avoids -using IS_* checks and convert_to_* conversions. The functions also -check for the appropriate number of parameters, and try to output -meaningful error messages. - - -Prototypes ----------- +```c /* Implemented. */ int zend_parse_parameters(int num_args, char *type_spec, ...); int zend_parse_parameters_ex(int flags, int num_args, char *type_spec, ...); +``` -The zend_parse_parameters() function takes the number of parameters -passed to the extension function, the type specifier string, and the -list of pointers to variables to store the results in. The _ex() version -also takes 'flags' argument -- current only ZEND_PARSE_PARAMS_QUIET can -be used as 'flags' to specify that the function should operate quietly -and not output any error messages. +The `zend_parse_parameters()` function takes the number of parameters passed to +the extension function, the type specifier string, and the list of pointers to +variables to store the results in. The _ex() version also takes 'flags' argument +-- current only `ZEND_PARSE_PARAMS_QUIET` can be used as 'flags' to specify that +the function should operate quietly and not output any error messages. -Both functions return SUCCESS or FAILURE depending on the result. +Both functions return `SUCCESS` or `FAILURE` depending on the result. -The auto-conversions are performed as necessary. Arrays, objects, and -resources cannot be auto-converted. +The auto-conversions are performed as necessary. Arrays, objects, and resources +cannot be auto-converted. PHP 5.3 includes a new function (actually implemented as macro): +```c int zend_parse_parameters_none(); +``` -This returns SUCCESS if no argument has been passed to the function, -FAILURE otherwise. +This returns `SUCCESS` if no argument has been passed to the function, `FAILURE` +otherwise. PHP 5.5 includes a new function: +```c int zend_parse_parameter(int flags, int arg_num, zval **arg, const char *spec, ...); +``` -This function behaves like zend_parse_parameters_ex() except that instead of +This function behaves like `zend_parse_parameters_ex()` except that instead of reading the arguments from the stack, it receives a single zval to convert (passed with double indirection). The passed zval may be changed in place as part of the conversion process. -See also https://wiki.php.net/rfc/zpp_improv#expose_zend_parse_arg_as_zend_parse_parameter - - -Type specifiers ---------------- - The following list shows the type specifier, its meaning and the parameter - types that need to be passed by address. All passed parameters are set - if the PHP parameter is non optional and untouched if optional and the - parameter is not present. The only exception is O where the zend_class_entry* - has to be provided on input and is used to verify the PHP parameter is an - instance of that class. - - a - array (zval*) - A - array or object (zval*) - b - boolean (zend_bool) - C - class (zend_class_entry*) - d - double (double) - f - function or array containing php method call info (returned as - zend_fcall_info and zend_fcall_info_cache) - h - array (returned as HashTable*) - H - array or HASH_OF(object) (returned as HashTable*) - l - long (zend_long) - L - long, limits out-of-range numbers to LONG_MAX/LONG_MIN (zend_long, ZEND_LONG_MAX/ZEND_LONG_MIN) - o - object of any type (zval*) - O - object of specific type given by class entry (zval*, zend_class_entry) - p - valid path (string without null bytes in the middle) and its length (char*, size_t) - P - valid path (string without null bytes in the middle) as zend_string (zend_string*) - r - resource (zval*) - s - string (with possible null bytes) and its length (char*, size_t) - S - string (with possible null bytes) as zend_string (zend_string*) - z - the actual zval (zval*) - * - variable arguments list (0 or more) - + - variable arguments list (1 or more) - - The following characters also have a meaning in the specifier string: - | - indicates that the remaining parameters are optional, they - should be initialized to default values by the extension since they - will not be touched by the parsing function if they are not - passed to it. - / - use SEPARATE_ZVAL_IF_NOT_REF() on the parameter it follows - ! - the parameter it follows can be of specified type or NULL. If NULL is - passed and the output for such type is a pointer, then the output - pointer is set to a native NULL pointer. - For 'b', 'l' and 'd', an extra argument of type zend_bool* must be - passed after the corresponding bool*, zend_long* or double* arguments, - respectively. A non-zero value will be written to the zend_bool if a - PHP NULL is passed. - - -Note on 64bit compatibility ---------------------------- -Please note that since version 7 PHP uses zend_long as integer type and -zend_string with size_t as length, so make sure you pass zend_longs to "l" -and size_t to strings length (i.e. for "s" you need to pass char * and size_t), -not the other way round! +See also +[Expose zend_parse_arg() as zend_parse_parameter()](https://wiki.php.net/rfc/zpp_improv#expose_zend_parse_arg_as_zend_parse_parameter). + +## Type specifiers + +The following list shows the type specifier, its meaning and the parameter types +that need to be passed by address. All passed parameters are set if the PHP +parameter is non optional and untouched if optional and the parameter is not +present. The only exception is O where the zend_class_entry* has to be provided +on input and is used to verify the PHP parameter is an instance of that class. + +```txt +a - array (zval*) +A - array or object (zval*) +b - boolean (zend_bool) +C - class (zend_class_entry*) +d - double (double) +f - function or array containing php method call info (returned as + zend_fcall_info and zend_fcall_info_cache) +h - array (returned as HashTable*) +H - array or HASH_OF(object) (returned as HashTable*) +l - long (zend_long) +L - long, limits out-of-range numbers to LONG_MAX/LONG_MIN (zend_long, ZEND_LONG_MAX/ZEND_LONG_MIN) +o - object of any type (zval*) +O - object of specific type given by class entry (zval*, zend_class_entry) +p - valid path (string without null bytes in the middle) and its length (char*, size_t) +P - valid path (string without null bytes in the middle) as zend_string (zend_string*) +r - resource (zval*) +s - string (with possible null bytes) and its length (char*, size_t) +S - string (with possible null bytes) as zend_string (zend_string*) +z - the actual zval (zval*) +* - variable arguments list (0 or more) ++ - variable arguments list (1 or more) +``` + +The following characters also have a meaning in the specifier string: + +* `|` - indicates that the remaining parameters are optional, they should be + initialized to default values by the extension since they will not be touched + by the parsing function if they are not passed to it. +* `/` - use SEPARATE_ZVAL_IF_NOT_REF() on the parameter it follows +* `!` - the parameter it follows can be of specified type or NULL. If NULL is + passed and the output for such type is a pointer, then the output pointer is + set to a native NULL pointer. For 'b', 'l' and 'd', an extra argument of type + zend_bool* must be passed after the corresponding bool*, zend_long* or + double* arguments, respectively. A non-zero value will be written to the + zend_bool if a PHP NULL is passed. + +## Note on 64bit compatibility + +Please note that since version 7 PHP uses `zend_long` as integer type and +`zend_string` with `size_t` as length, so make sure you pass `zend_long`s to "l" +and `size_t` to strings length (i.e. for "s" you need to pass char `*` and +`size_t`), not the other way round! Both mistakes might cause memory corruptions and segfaults: -1) - char *str; - long str_len; /* XXX THIS IS WRONG!! Use size_t instead. */ - zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str, &str_len) -2) - int num; /* XXX THIS IS WRONG!! Use zend_long instead. */ - zend_parse_parameters(ZEND_NUM_ARGS(), "l", &num) +* 1 + +```c +char *str; +long str_len; /* XXX THIS IS WRONG!! Use size_t instead. */ +zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str, &str_len) +``` + +* 2 + +```c +int num; /* XXX THIS IS WRONG!! Use zend_long instead. */ +zend_parse_parameters(ZEND_NUM_ARGS(), "l", &num) +``` -If you're in doubt, use check_parameters.php script to the parameters -and their types (it can be found in ./scripts/dev/ directory of PHP sources): +If you're in doubt, use check_parameters.php script to the parameters and their +types (it can be found in `./scripts/dev/` directory of PHP sources): -# php ./scripts/dev/check_parameters.php /path/to/your/sources/ +```bash +php ./scripts/dev/check_parameters.php /path/to/your/sources/ +``` +## Examples -Examples --------- +```c /* Gets a long, a string and its length, and a zval */ zend_long l; char *s; @@ -138,7 +145,6 @@ if (zend_parse_parameters(ZEND_NUM_ARGS(), "lsz", return; } - /* Gets an object of class specified by my_ce, and an optional double. */ zval *obj; double d = 0.5; @@ -148,7 +154,6 @@ if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|d", return; } - /* Gets an object or null, and an array. If null is passed for object, obj will be set to NULL. */ zval *obj; @@ -158,7 +163,6 @@ if (zend_parse_parameters(ZEND_NUM_ARGS(), "o!a", return; } - /* Gets a separated array which can also be null. */ zval *arr; if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/!", @@ -171,7 +175,7 @@ zend_long l1, l2, l3; char *s; /* * The function expects a pointer to a size_t in this case, not a long - * or any other type. If you specify a type which is larger + * or any other type. If you specify a type which is larger * than a 'size_t', the upper bits might not be initialized * properly, leading to random crashes on platforms like * Tru64 or Linux/Alpha. @@ -190,13 +194,11 @@ if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), return; } - /* Function that accepts only varargs (0 or more) */ int i, num_varargs; zval *varargs = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "*", &varargs, &num_varargs) == FAILURE) { return; } @@ -209,7 +211,6 @@ if (varargs) { efree(varargs); } - /* Function that accepts a string, followed by varargs (1 or more) */ char *str; @@ -243,3 +244,4 @@ for (i = 0; i < num_varargs; i++) { if (zend_parse_parameters_none() == FAILURE) { return; } +``` |