mirror of
https://github.com/php/php-src.git
synced 2024-11-27 20:03:40 +08:00
128 lines
3.8 KiB
Plaintext
128 lines
3.8 KiB
Plaintext
New parameter parsing functions
|
|
===============================
|
|
|
|
It should be easier to parse input parameters to an extension function.
|
|
Hence, borrowing from Python's example, there are now 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 most
|
|
of the IS_* checks and convert_to_* conversions. The functions also
|
|
check for the appropriate number of parameters, and try to output
|
|
meaningful error messages.
|
|
|
|
|
|
Prototypes
|
|
----------
|
|
/* Implemented. */
|
|
int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...);
|
|
int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, 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.
|
|
|
|
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.
|
|
|
|
|
|
Type specifiers
|
|
---------------
|
|
l - long
|
|
d - double
|
|
s - string (with possible null bytes) and its length
|
|
b - boolean, stored in zend_bool
|
|
r - resource (stored in zval)
|
|
a - array
|
|
o - object (of any type)
|
|
O - object (of specific type, specified by class entry)
|
|
z - the actual zval
|
|
|
|
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 (only applies
|
|
to 'a', 'o', 'O', 'r', and 'z'). If NULL is passed, the results
|
|
pointer is set to NULL as well.
|
|
|
|
Examples
|
|
--------
|
|
/* Gets a long, a string and its length, and a zval */
|
|
long l;
|
|
char *s;
|
|
int s_len;
|
|
zval *param;
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lsz",
|
|
&l, &s, &s_len, ¶m) == FAILURE) {
|
|
return;
|
|
}
|
|
|
|
|
|
/* Gets an object of class specified by my_ce, and an optional double. */
|
|
zval *obj;
|
|
double d = 0.5;
|
|
zend_class_entry my_ce;
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|d",
|
|
&obj, my_ce, &d) == FAILURE) {
|
|
return;
|
|
}
|
|
|
|
|
|
/* Gets an object or null, and an array.
|
|
If null is passed for object, obj will be set to NULL. */
|
|
zval *obj;
|
|
zval *arr;
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o!a",
|
|
&obj, &arr) == FAILURE) {
|
|
return;
|
|
}
|
|
|
|
|
|
/* Gets a separated array which can also be null. */
|
|
zval *arr;
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/!",
|
|
&arr) == FAILURE) {
|
|
return;
|
|
}
|
|
|
|
|
|
/* Get only the first three parameters (useful for varargs functions). */
|
|
zval *z;
|
|
zend_bool b;
|
|
zval *r;
|
|
if (zend_parse_parameters(3 TSRMLS_CC, "zbr!",
|
|
&z, &b, &r) == FAILURE) {
|
|
return;
|
|
}
|
|
|
|
|
|
/* Get either a set of 3 longs or a string. */
|
|
long l1, l2, l3;
|
|
char *s;
|
|
/*
|
|
* The function expects a pointer to a integer in this case, not a long
|
|
* or any other type. If you specify a type which is larger
|
|
* than a 'int', the upper bits might not be initialized
|
|
* properly, leading to random crashes on platforms like
|
|
* Tru64 or Linux/Alpha.
|
|
*/
|
|
int length;
|
|
|
|
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
|
|
"lll", &l1, &l2, &l3) == SUCCESS) {
|
|
/* manipulate longs */
|
|
} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
|
|
"s", &s, &length) == SUCCESS) {
|
|
/* manipulate string */
|
|
} else {
|
|
/* output error */
|
|
|
|
return;
|
|
}
|