Skip to content

Commit 60d8ab9

Browse files
committed
ext/gmp: Use new parsing mechanism in comparison operator overloading
This removes the last usages of the old GMP_FETCH API
1 parent 7858934 commit 60d8ab9

File tree

1 file changed

+16
-137
lines changed

1 file changed

+16
-137
lines changed

ext/gmp/gmp.c

Lines changed: 16 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,6 @@ PHP_GMP_API zend_class_entry *php_gmp_class_entry(void) {
8686
return gmp_ce;
8787
}
8888

89-
typedef struct _gmp_temp {
90-
mpz_t num;
91-
bool is_used;
92-
} gmp_temp_t;
93-
9489
#define GMP_MAX_BASE 62
9590

9691
#define GMP_51_OR_NEWER \
@@ -107,63 +102,8 @@ typedef struct _gmp_temp {
107102
#define GET_GMP_FROM_ZVAL(zval) \
108103
GET_GMP_OBJECT_FROM_OBJ(Z_OBJ_P(zval))->num
109104

110-
/* The FETCH_GMP_ZVAL_* family of macros is used to fetch a gmp number
111-
* (mpz_ptr) from a zval. If the zval is not a GMP instance, then we
112-
* try to convert the value to a temporary gmp number using convert_to_gmp.
113-
* This temporary number is stored in the temp argument, which is of type
114-
* gmp_temp_t. This temporary value needs to be freed lateron using the
115-
* FREE_GMP_TEMP macro.
116-
*
117-
* If the conversion to a gmp number fails, the macros RETURN_THROWS() due to TypeError.
118-
* The _DEP / _DEP_DEP variants additionally free the temporary values
119-
* passed in the last / last two arguments.
120-
*
121-
* If one zval can sometimes be fetched as a long you have to set the
122-
* is_used member of the corresponding gmp_temp_t value to 0, otherwise
123-
* the FREE_GMP_TEMP and *_DEP macros will not work properly.
124-
*
125-
* The three FETCH_GMP_ZVAL_* macros below are mostly copy & paste code
126-
* as I couldn't find a way to combine them.
127-
*/
128-
129-
#define FREE_GMP_TEMP(temp) \
130-
if (temp.is_used) { \
131-
mpz_clear(temp.num); \
132-
}
133-
134-
#define FETCH_GMP_ZVAL_DEP(gmpnumber, zval, temp, dep, arg_pos) \
135-
if (IS_GMP(zval)) { \
136-
gmpnumber = GET_GMP_FROM_ZVAL(zval); \
137-
temp.is_used = 0; \
138-
} else { \
139-
mpz_init(temp.num); \
140-
if (convert_to_gmp(temp.num, zval, 0, arg_pos) == FAILURE) { \
141-
mpz_clear(temp.num); \
142-
FREE_GMP_TEMP(dep); \
143-
RETURN_THROWS(); \
144-
} \
145-
temp.is_used = 1; \
146-
gmpnumber = temp.num; \
147-
}
148-
149-
#define FETCH_GMP_ZVAL(gmpnumber, zval, temp, arg_pos) \
150-
if (IS_GMP(zval)) { \
151-
gmpnumber = GET_GMP_FROM_ZVAL(zval); \
152-
temp.is_used = 0; \
153-
} else { \
154-
mpz_init(temp.num); \
155-
if (convert_to_gmp(temp.num, zval, 0, arg_pos) == FAILURE) { \
156-
mpz_clear(temp.num); \
157-
RETURN_THROWS(); \
158-
} \
159-
temp.is_used = 1; \
160-
gmpnumber = temp.num; \
161-
}
162-
163105
static void gmp_strval(zval *result, mpz_t gmpnum, int base);
164106
static zend_result convert_zstr_to_gmp(mpz_t gmp_number, const zend_string *val, zend_long base, uint32_t arg_pos);
165-
static zend_result convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, uint32_t arg_pos);
166-
static void gmp_cmp(zval *return_value, zval *a_arg, zval *b_arg, bool is_operator);
167107

168108
static bool gmp_zend_parse_arg_into_mpz_ex(
169109
zval *arg,
@@ -520,18 +460,24 @@ static zend_result gmp_do_operation(uint8_t opcode, zval *result, zval *op1, zva
520460

521461
static int gmp_compare(zval *op1, zval *op2) /* {{{ */
522462
{
523-
zval result;
524-
525-
gmp_cmp(&result, op1, op2, /* is_operator */ true);
463+
mpz_ptr gmp_op1, gmp_op2;
464+
bool status = false;
526465

527-
/* An error/exception occurs if one of the operands is not a numeric string
528-
* or an object which is different from GMP */
529-
if (EG(exception)) {
530-
return 1;
466+
status = gmp_zend_parse_arg_into_mpz_ex(op1, &gmp_op1, 1, true);
467+
if (!status) {
468+
if (!EG(exception)) {
469+
zend_type_error("Number must be of type GMP|string|int, %s given", zend_zval_value_name(op1));
470+
}
471+
return ZEND_UNCOMPARABLE;
472+
}
473+
status = gmp_zend_parse_arg_into_mpz_ex(op2, &gmp_op2, 2, true);
474+
if (!status) {
475+
if (!EG(exception)) {
476+
zend_type_error("Number must be of type GMP|string|int, %s given", zend_zval_value_name(op2));
477+
}
478+
return ZEND_UNCOMPARABLE;
531479
}
532-
/* result can only be a zend_long if gmp_cmp hasn't thrown an Error */
533-
ZEND_ASSERT(Z_TYPE(result) == IS_LONG);
534-
return Z_LVAL(result);
480+
return mpz_cmp(gmp_op1, gmp_op2);
535481
}
536482
/* }}} */
537483

@@ -715,44 +661,6 @@ static zend_result convert_zstr_to_gmp(mpz_t gmp_number, const zend_string *val,
715661
return SUCCESS;
716662
}
717663

718-
/* {{{ convert_to_gmp
719-
* Convert zval to be gmp number */
720-
static zend_result convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, uint32_t arg_pos)
721-
{
722-
switch (Z_TYPE_P(val)) {
723-
case IS_LONG:
724-
mpz_set_si(gmpnumber, Z_LVAL_P(val));
725-
return SUCCESS;
726-
case IS_STRING: {
727-
return convert_zstr_to_gmp(gmpnumber, Z_STR_P(val), base, arg_pos);
728-
}
729-
case IS_NULL:
730-
/* Just reject null for operator overloading */
731-
if (arg_pos == 0) {
732-
zend_type_error("Number must be of type GMP|string|int, %s given", zend_zval_type_name(val));
733-
return FAILURE;
734-
}
735-
ZEND_FALLTHROUGH;
736-
default: {
737-
zend_long lval;
738-
if (!zend_parse_arg_long_slow(val, &lval, arg_pos)) {
739-
if (arg_pos == 0) {
740-
zend_type_error(
741-
"Number must be of type GMP|string|int, %s given", zend_zval_value_name(val));
742-
} else {
743-
zend_argument_type_error(arg_pos,
744-
"must be of type GMP|string|int, %s given", zend_zval_value_name(val));
745-
}
746-
return FAILURE;
747-
}
748-
749-
mpz_set_si(gmpnumber, lval);
750-
return SUCCESS;
751-
}
752-
}
753-
}
754-
/* }}} */
755-
756664
static void gmp_strval(zval *result, mpz_t gmpnum, int base) /* {{{ */
757665
{
758666
size_t num_len;
@@ -784,35 +692,6 @@ static void gmp_strval(zval *result, mpz_t gmpnum, int base) /* {{{ */
784692
}
785693
/* }}} */
786694

787-
static void gmp_cmp(zval *return_value, zval *a_arg, zval *b_arg, bool is_operator) /* {{{ */
788-
{
789-
mpz_ptr gmpnum_a, gmpnum_b;
790-
gmp_temp_t temp_a, temp_b;
791-
bool use_si = 0;
792-
zend_long res;
793-
794-
FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, is_operator ? 0 : 1);
795-
796-
if (Z_TYPE_P(b_arg) == IS_LONG) {
797-
use_si = 1;
798-
temp_b.is_used = 0;
799-
} else {
800-
FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a, is_operator ? 0 : 2);
801-
}
802-
803-
if (use_si) {
804-
res = mpz_cmp_si(gmpnum_a, Z_LVAL_P(b_arg));
805-
} else {
806-
res = mpz_cmp(gmpnum_a, gmpnum_b);
807-
}
808-
809-
FREE_GMP_TEMP(temp_a);
810-
FREE_GMP_TEMP(temp_b);
811-
812-
RETURN_LONG(res);
813-
}
814-
/* }}} */
815-
816695
static bool gmp_verify_base(zend_long base, uint32_t arg_num)
817696
{
818697
if (base && (base < 2 || base > GMP_MAX_BASE)) {

0 commit comments

Comments
 (0)