Add number or str ZPP macros

This commit is contained in:
George Peter Banyard 2023-03-07 17:15:53 +00:00
parent 53829b7daf
commit 80e90ad7ba
No known key found for this signature in database
GPG key ID: 3306078E3194AEBD
6 changed files with 194 additions and 1 deletions

View file

@ -0,0 +1,74 @@
--TEST--
Test Z_PARAM_NUMBER_OR_STR() and Z_PARAM_NUMBER_OR_STR_OR_NULL
--EXTENSIONS--
zend_test
--FILE--
<?php
class Foo {}
class ToString {
public function __toString() {
return "ToString";
}
}
var_dump(zend_number_or_string("string"));
var_dump(zend_number_or_string(1));
var_dump(zend_number_or_string(5.5));
var_dump(zend_number_or_string(null));
var_dump(zend_number_or_string(false));
var_dump(zend_number_or_string(true));
var_dump(zend_number_or_string(new ToString()));
try {
zend_string_or_object([]);
} catch (TypeError $exception) {
echo $exception->getMessage() . "\n";
}
try {
zend_number_or_string(new Foo());
} catch (TypeError $exception) {
echo $exception->getMessage() . "\n";
}
var_dump(zend_number_or_string_or_null("string"));
var_dump(zend_number_or_string_or_null(1));
var_dump(zend_number_or_string_or_null(5.5));
var_dump(zend_number_or_string_or_null(null));
var_dump(zend_number_or_string_or_null(false));
var_dump(zend_number_or_string_or_null(true));
var_dump(zend_number_or_string_or_null(new ToString()));
try {
zend_number_or_string_or_null([]);
} catch (TypeError $exception) {
echo $exception->getMessage() . "\n";
}
try {
zend_number_or_string_or_null(new Foo());
} catch (TypeError $exception) {
echo $exception->getMessage() . "\n";
}
?>
--EXPECTF--
string(6) "string"
int(1)
float(5.5)
Deprecated: zend_number_or_string(): Passing null to parameter #1 ($param) of type string|int|float is deprecated in %s on line %d
int(0)
int(0)
int(1)
string(8) "ToString"
zend_string_or_object(): Argument #1 ($param) must be of type object|string, array given
zend_number_or_string(): Argument #1 ($param) must be of type string|int|float, Foo given
string(6) "string"
int(1)
float(5.5)
NULL
int(0)
int(1)
string(8) "ToString"
zend_number_or_string_or_null(): Argument #1 ($param) must be of type string|int|float|null, array given
zend_number_or_string_or_null(): Argument #1 ($param) must be of type string|int|float|null, Foo given

View file

@ -674,6 +674,36 @@ ZEND_API bool ZEND_FASTCALL zend_parse_arg_number_slow(zval *arg, zval **dest, u
} }
/* }}} */ /* }}} */
ZEND_API bool ZEND_FASTCALL zend_parse_arg_number_or_str_slow(zval *arg, zval **dest, uint32_t arg_num) /* {{{ */
{
if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
return false;
}
if (Z_TYPE_P(arg) < IS_TRUE) {
if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) && !zend_null_arg_deprecated("string|int|float", arg_num)) {
return false;
}
ZVAL_LONG(arg, 0);
} else if (Z_TYPE_P(arg) == IS_TRUE) {
ZVAL_LONG(arg, 1);
} else if (UNEXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
zend_object *zobj = Z_OBJ_P(arg);
zval obj;
if (zobj->handlers->cast_object(zobj, &obj, IS_STRING) == SUCCESS) {
OBJ_RELEASE(zobj);
ZVAL_COPY_VALUE(arg, &obj);
*dest = arg;
return true;
}
return false;
} else {
return false;
}
*dest = arg;
return true;
}
ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest, uint32_t arg_num) /* {{{ */ ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest, uint32_t arg_num) /* {{{ */
{ {
if (EXPECTED(Z_TYPE_P(arg) < IS_STRING)) { if (EXPECTED(Z_TYPE_P(arg) < IS_STRING)) {

View file

@ -1520,6 +1520,8 @@ static zend_always_inline zval *zend_try_array_init(zval *zv)
_(Z_EXPECTED_DOUBLE_OR_NULL, "of type ?float") \ _(Z_EXPECTED_DOUBLE_OR_NULL, "of type ?float") \
_(Z_EXPECTED_NUMBER, "of type int|float") \ _(Z_EXPECTED_NUMBER, "of type int|float") \
_(Z_EXPECTED_NUMBER_OR_NULL, "of type int|float|null") \ _(Z_EXPECTED_NUMBER_OR_NULL, "of type int|float|null") \
_(Z_EXPECTED_NUMBER_OR_STRING, "of type string|int|float") \
_(Z_EXPECTED_NUMBER_OR_STRING_OR_NULL, "of type string|int|float|null") \
_(Z_EXPECTED_ARRAY_OR_STRING, "of type array|string") \ _(Z_EXPECTED_ARRAY_OR_STRING, "of type array|string") \
_(Z_EXPECTED_ARRAY_OR_STRING_OR_NULL, "of type array|string|null") \ _(Z_EXPECTED_ARRAY_OR_STRING_OR_NULL, "of type array|string|null") \
_(Z_EXPECTED_STRING_OR_LONG, "of type string|int") \ _(Z_EXPECTED_STRING_OR_LONG, "of type string|int") \
@ -1891,6 +1893,20 @@ ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *
#define Z_PARAM_NUMBER(dest) \ #define Z_PARAM_NUMBER(dest) \
Z_PARAM_NUMBER_EX(dest, 0) Z_PARAM_NUMBER_EX(dest, 0)
#define Z_PARAM_NUMBER_OR_STR_EX(dest, check_null) \
Z_PARAM_PROLOGUE(0, 0); \
if (UNEXPECTED(!zend_parse_arg_number_or_str(_arg, &dest, check_null, _i))) { \
_expected_type = check_null ? Z_EXPECTED_NUMBER_OR_STRING_OR_NULL : Z_EXPECTED_NUMBER_OR_STRING; \
_error_code = ZPP_ERROR_WRONG_ARG; \
break; \
}
#define Z_PARAM_NUMBER_OR_STR(dest) \
Z_PARAM_NUMBER_OR_STR_EX(dest, false)
#define Z_PARAM_NUMBER_OR_STR_OR_NULL(dest) \
Z_PARAM_NUMBER_OR_STR_EX(dest, true)
/* old "o" */ /* old "o" */
#define Z_PARAM_OBJECT_EX(dest, check_null, deref) \ #define Z_PARAM_OBJECT_EX(dest, check_null, deref) \
Z_PARAM_PROLOGUE(deref, 0); \ Z_PARAM_PROLOGUE(deref, 0); \
@ -2145,6 +2161,7 @@ ZEND_API bool ZEND_FASTCALL zend_parse_arg_double_weak(const zval *arg, double *
ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_slow(zval *arg, zend_string **dest, uint32_t arg_num); ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_slow(zval *arg, zend_string **dest, uint32_t arg_num);
ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest, uint32_t arg_num); ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest, uint32_t arg_num);
ZEND_API bool ZEND_FASTCALL zend_parse_arg_number_slow(zval *arg, zval **dest, uint32_t arg_num); ZEND_API bool ZEND_FASTCALL zend_parse_arg_number_slow(zval *arg, zval **dest, uint32_t arg_num);
ZEND_API bool ZEND_FASTCALL zend_parse_arg_number_or_str_slow(zval *arg, zval **dest, uint32_t arg_num);
ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_or_long_slow(zval *arg, zend_string **dest_str, zend_long *dest_long, uint32_t arg_num); ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_or_long_slow(zval *arg, zend_string **dest_str, zend_long *dest_long, uint32_t arg_num);
static zend_always_inline bool zend_parse_arg_bool(const zval *arg, bool *dest, bool *is_null, bool check_null, uint32_t arg_num) static zend_always_inline bool zend_parse_arg_bool(const zval *arg, bool *dest, bool *is_null, bool check_null, uint32_t arg_num)
@ -2209,6 +2226,18 @@ static zend_always_inline bool zend_parse_arg_number(zval *arg, zval **dest, boo
return 1; return 1;
} }
static zend_always_inline bool zend_parse_arg_number_or_str(zval *arg, zval **dest, bool check_null, uint32_t arg_num)
{
if (EXPECTED(Z_TYPE_P(arg) == IS_LONG || Z_TYPE_P(arg) == IS_DOUBLE || Z_TYPE_P(arg) == IS_STRING)) {
*dest = arg;
} else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
*dest = NULL;
} else {
return zend_parse_arg_number_or_str_slow(arg, dest, arg_num);
}
return true;
}
static zend_always_inline bool zend_parse_arg_str(zval *arg, zend_string **dest, bool check_null, uint32_t arg_num) static zend_always_inline bool zend_parse_arg_str(zval *arg, zend_string **dest, bool check_null, uint32_t arg_num)
{ {
if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) { if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {

View file

@ -266,6 +266,50 @@ static ZEND_FUNCTION(zend_string_or_stdclass_or_null)
} }
} }
/* Tests Z_PARAM_NUMBER_OR_STR */
static ZEND_FUNCTION(zend_number_or_string)
{
zval *input;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_NUMBER_OR_STR(input)
ZEND_PARSE_PARAMETERS_END();
switch (Z_TYPE_P(input)) {
case IS_LONG:
RETURN_LONG(Z_LVAL_P(input));
case IS_DOUBLE:
RETURN_DOUBLE(Z_DVAL_P(input));
case IS_STRING:
RETURN_STR_COPY(Z_STR_P(input));
EMPTY_SWITCH_DEFAULT_CASE();
}
}
/* Tests Z_PARAM_NUMBER_OR_STR_OR_NULL */
static ZEND_FUNCTION(zend_number_or_string_or_null)
{
zval *input;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_NUMBER_OR_STR_OR_NULL(input)
ZEND_PARSE_PARAMETERS_END();
if (!input) {
RETURN_NULL();
}
switch (Z_TYPE_P(input)) {
case IS_LONG:
RETURN_LONG(Z_LVAL_P(input));
case IS_DOUBLE:
RETURN_DOUBLE(Z_DVAL_P(input));
case IS_STRING:
RETURN_STR_COPY(Z_STR_P(input));
EMPTY_SWITCH_DEFAULT_CASE();
}
}
static ZEND_FUNCTION(zend_weakmap_attach) static ZEND_FUNCTION(zend_weakmap_attach)
{ {
zval *value; zval *value;

View file

@ -162,6 +162,10 @@ namespace {
/** @param stdClass|string|null $param */ /** @param stdClass|string|null $param */
function zend_string_or_stdclass_or_null($param): stdClass|string|null {} function zend_string_or_stdclass_or_null($param): stdClass|string|null {}
function zend_number_or_string(string|int|float $param): string|int|float {}
function zend_number_or_string_or_null(string|int|float|null $param): string|int|float|null {}
function zend_iterable(iterable $arg1, ?iterable $arg2 = null): void {} function zend_iterable(iterable $arg1, ?iterable $arg2 = null): void {}
function zend_weakmap_attach(object $object, mixed $value): bool {} function zend_weakmap_attach(object $object, mixed $value): bool {}

View file

@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead. /* This is a generated file, edit the .stub.php file instead.
* Stub hash: 58ae12118458386ab204a2400966c25c833baeae */ * Stub hash: c526a3e961501a511b210eab38bb961ca61bb258 */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0)
ZEND_END_ARG_INFO() ZEND_END_ARG_INFO()
@ -56,6 +56,14 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_zend_string_or_stdclass_or_n
ZEND_ARG_INFO(0, param) ZEND_ARG_INFO(0, param)
ZEND_END_ARG_INFO() ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_zend_number_or_string, 0, 1, MAY_BE_STRING|MAY_BE_LONG|MAY_BE_DOUBLE)
ZEND_ARG_TYPE_MASK(0, param, MAY_BE_STRING|MAY_BE_LONG|MAY_BE_DOUBLE, NULL)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_zend_number_or_string_or_null, 0, 1, MAY_BE_STRING|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_NULL)
ZEND_ARG_TYPE_MASK(0, param, MAY_BE_STRING|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_NULL, NULL)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_iterable, 0, 1, IS_VOID, 0) ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_iterable, 0, 1, IS_VOID, 0)
ZEND_ARG_OBJ_TYPE_MASK(0, arg1, Traversable, MAY_BE_ARRAY, NULL) ZEND_ARG_OBJ_TYPE_MASK(0, arg1, Traversable, MAY_BE_ARRAY, NULL)
ZEND_ARG_OBJ_TYPE_MASK(0, arg2, Traversable, MAY_BE_ARRAY|MAY_BE_NULL, "null") ZEND_ARG_OBJ_TYPE_MASK(0, arg2, Traversable, MAY_BE_ARRAY|MAY_BE_NULL, "null")
@ -209,6 +217,8 @@ static ZEND_FUNCTION(zend_string_or_object);
static ZEND_FUNCTION(zend_string_or_object_or_null); static ZEND_FUNCTION(zend_string_or_object_or_null);
static ZEND_FUNCTION(zend_string_or_stdclass); static ZEND_FUNCTION(zend_string_or_stdclass);
static ZEND_FUNCTION(zend_string_or_stdclass_or_null); static ZEND_FUNCTION(zend_string_or_stdclass_or_null);
static ZEND_FUNCTION(zend_number_or_string);
static ZEND_FUNCTION(zend_number_or_string_or_null);
static ZEND_FUNCTION(zend_iterable); static ZEND_FUNCTION(zend_iterable);
static ZEND_FUNCTION(zend_weakmap_attach); static ZEND_FUNCTION(zend_weakmap_attach);
static ZEND_FUNCTION(zend_weakmap_remove); static ZEND_FUNCTION(zend_weakmap_remove);
@ -272,6 +282,8 @@ static const zend_function_entry ext_functions[] = {
ZEND_FE(zend_string_or_object_or_null, arginfo_zend_string_or_object_or_null) ZEND_FE(zend_string_or_object_or_null, arginfo_zend_string_or_object_or_null)
ZEND_FE(zend_string_or_stdclass, arginfo_zend_string_or_stdclass) ZEND_FE(zend_string_or_stdclass, arginfo_zend_string_or_stdclass)
ZEND_FE(zend_string_or_stdclass_or_null, arginfo_zend_string_or_stdclass_or_null) ZEND_FE(zend_string_or_stdclass_or_null, arginfo_zend_string_or_stdclass_or_null)
ZEND_FE(zend_number_or_string, arginfo_zend_number_or_string)
ZEND_FE(zend_number_or_string_or_null, arginfo_zend_number_or_string_or_null)
ZEND_FE(zend_iterable, arginfo_zend_iterable) ZEND_FE(zend_iterable, arginfo_zend_iterable)
ZEND_FE(zend_weakmap_attach, arginfo_zend_weakmap_attach) ZEND_FE(zend_weakmap_attach, arginfo_zend_weakmap_attach)
ZEND_FE(zend_weakmap_remove, arginfo_zend_weakmap_remove) ZEND_FE(zend_weakmap_remove, arginfo_zend_weakmap_remove)