Merge branch 'PHP-5.5'

* PHP-5.5:
  Update README.PARAMETER_PARSING_API
  Export zend_parse_parameter()
  Expose zend_parse_arg() as zend_parse_parameter()
  zend_parse_parameters: allow ! for non pointers
This commit is contained in:
Gustavo Lopes 2013-01-16 23:37:42 +01:00
commit 979ca53734
3 changed files with 63 additions and 17 deletions

View File

@ -28,6 +28,17 @@ 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.
PHP 5.5 includes a new function:
int zend_parse_parameter(int flags, int arg_num TSRMLS_DC, zval **arg, const char *spec, ...);
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
---------------
@ -65,9 +76,13 @@ Type specifiers
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 (applies
to all specifiers except for 'b', 'l', and 'd'). If NULL is passed, the
results pointer is set to NULL as well.
! - 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*, long* or double* arguments,
respectively. A non-zero value will be written to the zend_bool iif a
PHP NULL is passed.
Note on 64bit compatibility

View File

@ -306,16 +306,14 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
{
const char *spec_walk = *spec;
char c = *spec_walk++;
int return_null = 0;
int check_null = 0;
/* scan through modifiers */
while (1) {
if (*spec_walk == '/') {
SEPARATE_ZVAL_IF_NOT_REF(arg);
} else if (*spec_walk == '!') {
if (Z_TYPE_PP(arg) == IS_NULL) {
return_null = 1;
}
check_null = 1;
} else {
break;
}
@ -327,6 +325,12 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'L':
{
long *p = va_arg(*va, long *);
if (check_null) {
zend_bool *p = va_arg(*va, zend_bool *);
*p = (Z_TYPE_PP(arg) == IS_NULL);
}
switch (Z_TYPE_PP(arg)) {
case IS_STRING:
{
@ -380,6 +384,12 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'd':
{
double *p = va_arg(*va, double *);
if (check_null) {
zend_bool *p = va_arg(*va, zend_bool *);
*p = (Z_TYPE_PP(arg) == IS_NULL);
}
switch (Z_TYPE_PP(arg)) {
case IS_STRING:
{
@ -418,7 +428,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
int *pl = va_arg(*va, int *);
switch (Z_TYPE_PP(arg)) {
case IS_NULL:
if (return_null) {
if (check_null) {
*p = NULL;
*pl = 0;
break;
@ -462,6 +472,12 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'b':
{
zend_bool *p = va_arg(*va, zend_bool *);
if (check_null) {
zend_bool *p = va_arg(*va, zend_bool *);
*p = (Z_TYPE_PP(arg) == IS_NULL);
}
switch (Z_TYPE_PP(arg)) {
case IS_NULL:
case IS_STRING:
@ -484,7 +500,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'r':
{
zval **p = va_arg(*va, zval **);
if (return_null) {
if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*p = NULL;
break;
}
@ -499,7 +515,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'a':
{
zval **p = va_arg(*va, zval **);
if (return_null) {
if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*p = NULL;
break;
}
@ -514,7 +530,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'h':
{
HashTable **p = va_arg(*va, HashTable **);
if (return_null) {
if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*p = NULL;
break;
}
@ -534,7 +550,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'o':
{
zval **p = va_arg(*va, zval **);
if (return_null) {
if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*p = NULL;
break;
}
@ -551,7 +567,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
zval **p = va_arg(*va, zval **);
zend_class_entry *ce = va_arg(*va, zend_class_entry *);
if (return_null) {
if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*p = NULL;
break;
}
@ -573,7 +589,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
zend_class_entry **lookup, **pce = va_arg(*va, zend_class_entry **);
zend_class_entry *ce_base = *pce;
if (return_null) {
if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*pce = NULL;
break;
}
@ -607,7 +623,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
zend_fcall_info_cache *fcc = va_arg(*va, zend_fcall_info_cache *);
char *is_callable_error = NULL;
if (return_null) {
if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
fci->size = 0;
fcc->initialized = 0;
break;
@ -637,7 +653,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'z':
{
zval **p = va_arg(*va, zval **);
if (return_null) {
if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*p = NULL;
} else {
*p = *arg;
@ -648,7 +664,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, con
case 'Z':
{
zval ***p = va_arg(*va, zval ***);
if (return_null) {
if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
*p = NULL;
} else {
*p = arg;
@ -697,6 +713,19 @@ static int zend_parse_arg(int arg_num, zval **arg, va_list *va, const char **spe
}
/* }}} */
ZEND_API int zend_parse_parameter(int flags, int arg_num TSRMLS_DC, zval **arg, const char *spec, ...)
{
va_list va;
int ret;
int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
va_start(va, spec);
ret = zend_parse_arg(arg_num, arg, &va, &spec, quiet TSRMLS_CC);
va_end(va);
return ret;
}
static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, int flags TSRMLS_DC) /* {{{ */
{
const char *spec_walk;

View File

@ -258,6 +258,8 @@ ZEND_API char *zend_zval_type_name(const zval *arg);
ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr, const char *type_spec, ...);
ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC, zval *this_ptr, const char *type_spec, ...);
ZEND_API int zend_parse_parameter(int flags, int arg_num TSRMLS_DC, zval **arg, const char *spec, ...);
/* End of parameter parsing API -- andrei */
ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC);