From 9931f435a7c3b6c1f140f1fe03c225000dc661d6 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 5 Jan 2023 00:28:36 +0100 Subject: [PATCH] Implement GMP::__construct --- ext/gmp/gmp.c | 56 ++++++++++++++++++++++++++++++------ ext/gmp/gmp.stub.php | 2 ++ ext/gmp/gmp_arginfo.h | 9 +++++- ext/gmp/tests/construct.phpt | 51 ++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+), 9 deletions(-) create mode 100644 ext/gmp/tests/construct.phpt diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index 29974c63862f3..02eb30bacb730 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -862,6 +862,26 @@ static inline void _gmp_unary_opl(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_opl_t } /* }}} */ +static bool gmp_verify_base(zend_long base, uint32_t arg_num) +{ + if (base && (base < 2 || base > GMP_MAX_BASE)) { + zend_argument_value_error(arg_num, "must be between 2 and %d", GMP_MAX_BASE); + return false; + } + + return true; +} + +static zend_result gmp_initialize_number(mpz_ptr gmp_number, const zend_string *arg_str, zend_long arg_l, zend_long base) +{ + if (arg_str) { + return convert_zstr_to_gmp(gmp_number, arg_str, base, 1); + } + + mpz_set_si(gmp_number, arg_l); + return SUCCESS; +} + /* {{{ Initializes GMP number */ ZEND_FUNCTION(gmp_init) { @@ -876,18 +896,14 @@ ZEND_FUNCTION(gmp_init) Z_PARAM_LONG(base) ZEND_PARSE_PARAMETERS_END(); - if (base && (base < 2 || base > GMP_MAX_BASE)) { - zend_argument_value_error(2, "must be between 2 and %d", GMP_MAX_BASE); + if (!gmp_verify_base(base, 2)) { RETURN_THROWS(); } INIT_GMP_RETVAL(gmp_number); - if (arg_str) { - if (convert_zstr_to_gmp(gmp_number, arg_str, base, 1) == FAILURE) { - RETURN_THROWS(); - } - } else { - mpz_set_si(gmp_number, arg_l); + + if (gmp_initialize_number(gmp_number, arg_str, arg_l, base) == FAILURE) { + RETURN_THROWS(); } } /* }}} */ @@ -2021,6 +2037,30 @@ ZEND_FUNCTION(gmp_scan1) } /* }}} */ +ZEND_METHOD(GMP, __construct) +{ + zend_string *arg_str = NULL; + zend_long arg_l = 0; + zend_long base = 0; + + ZEND_PARSE_PARAMETERS_START(0, 2) + Z_PARAM_OPTIONAL + Z_PARAM_STR_OR_LONG(arg_str, arg_l) + Z_PARAM_LONG(base) + ZEND_PARSE_PARAMETERS_END(); + + if (!gmp_verify_base(base, 2)) { + RETURN_THROWS(); + } + + return_value = ZEND_THIS; + mpz_ptr gmp_number = GET_GMP_FROM_ZVAL(ZEND_THIS); + + if (gmp_initialize_number(gmp_number, arg_str, arg_l, base) == FAILURE) { + RETURN_THROWS(); + } +} + ZEND_METHOD(GMP, __serialize) { ZEND_PARSE_PARAMETERS_NONE(); diff --git a/ext/gmp/gmp.stub.php b/ext/gmp/gmp.stub.php index 664fc6ded264c..ff5b5afb4055b 100644 --- a/ext/gmp/gmp.stub.php +++ b/ext/gmp/gmp.stub.php @@ -59,6 +59,8 @@ class GMP { + public function __construct(int|string $num = 0, int $base = 0) {} + public function __serialize(): array {} public function __unserialize(array $data): void {} diff --git a/ext/gmp/gmp_arginfo.h b/ext/gmp/gmp_arginfo.h index c0e029f6fc396..e9a339f02a333 100644 --- a/ext/gmp/gmp_arginfo.h +++ b/ext/gmp/gmp_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 64a40a366b87a96a291de6a474e60c8d98d15da1 */ + * Stub hash: d52f82c7084a8122fe07c91eb6d4ab6030daa27d */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_gmp_init, 0, 1, GMP, 0) ZEND_ARG_TYPE_MASK(0, num, MAY_BE_LONG|MAY_BE_STRING, NULL) @@ -184,6 +184,11 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_gmp_binomial, 0, 2, GMP, 0) ZEND_ARG_TYPE_INFO(0, k, IS_LONG, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_GMP___construct, 0, 0, 0) + ZEND_ARG_TYPE_MASK(0, num, MAY_BE_LONG|MAY_BE_STRING, "0") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, base, IS_LONG, 0, "0") +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_GMP___serialize, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -242,6 +247,7 @@ ZEND_FUNCTION(gmp_popcount); ZEND_FUNCTION(gmp_hamdist); ZEND_FUNCTION(gmp_nextprime); ZEND_FUNCTION(gmp_binomial); +ZEND_METHOD(GMP, __construct); ZEND_METHOD(GMP, __serialize); ZEND_METHOD(GMP, __unserialize); @@ -303,6 +309,7 @@ static const zend_function_entry ext_functions[] = { static const zend_function_entry class_GMP_methods[] = { + ZEND_ME(GMP, __construct, arginfo_class_GMP___construct, ZEND_ACC_PUBLIC) ZEND_ME(GMP, __serialize, arginfo_class_GMP___serialize, ZEND_ACC_PUBLIC) ZEND_ME(GMP, __unserialize, arginfo_class_GMP___unserialize, ZEND_ACC_PUBLIC) ZEND_FE_END diff --git a/ext/gmp/tests/construct.phpt b/ext/gmp/tests/construct.phpt new file mode 100644 index 0000000000000..11c80b3d9ed82 --- /dev/null +++ b/ext/gmp/tests/construct.phpt @@ -0,0 +1,51 @@ +--TEST-- +Constructor for GMP +--EXTENSIONS-- +gmp +--FILE-- +getMessage() . "\n"; +} +try { + var_dump(new GMP("", 10)); +} catch (ValueError $e) { + echo $e->getMessage() . "\n"; +} +try { + var_dump(new GMP("hello")); +} catch (ValueError $e) { + echo $e->getMessage() . "\n"; +} +?> +--EXPECT-- +object(GMP)#1 (1) { + ["num"]=> + string(1) "0" +} +object(GMP)#1 (1) { + ["num"]=> + string(1) "0" +} +object(GMP)#1 (1) { + ["num"]=> + string(3) "123" +} +object(GMP)#1 (1) { + ["num"]=> + string(3) "170" +} +object(GMP)#1 (1) { + ["num"]=> + string(1) "6" +} +GMP::__construct(): Argument #2 ($base) must be between 2 and 62 +GMP::__construct(): Argument #1 ($num) is not an integer string +GMP::__construct(): Argument #1 ($num) is not an integer string