Skip to content

Commit d8cea19

Browse files
committed
Refactor bc_raisemod() to get rid of Zend dependencies
This seperates the concerns of throwing exceptions back into the PHP_FUNCTION instead of being the responsability of the library
1 parent c67fd32 commit d8cea19

File tree

3 files changed

+51
-34
lines changed

3 files changed

+51
-34
lines changed

ext/bcmath/bcmath.c

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -420,15 +420,15 @@ PHP_FUNCTION(bcmod)
420420
/* {{{ Returns the value of an arbitrary precision number raised to the power of another reduced by a modulus */
421421
PHP_FUNCTION(bcpowmod)
422422
{
423-
zend_string *left, *right, *modulus;
423+
zend_string *base, *exponent, *modulus;
424424
zend_long scale_param;
425425
bool scale_param_is_null = 1;
426-
bc_num first, second, mod, result;
426+
bc_num bc_base, bc_expo, bc_modulus, result;
427427
int scale = BCG(bc_precision);
428428

429429
ZEND_PARSE_PARAMETERS_START(3, 4)
430-
Z_PARAM_STR(left)
431-
Z_PARAM_STR(right)
430+
Z_PARAM_STR(base)
431+
Z_PARAM_STR(exponent)
432432
Z_PARAM_STR(modulus)
433433
Z_PARAM_OPTIONAL
434434
Z_PARAM_LONG_OR_NULL(scale_param, scale_param_is_null)
@@ -443,34 +443,53 @@ PHP_FUNCTION(bcpowmod)
443443
scale = (int) scale_param;
444444
}
445445

446-
bc_init_num(&first);
447-
bc_init_num(&second);
448-
bc_init_num(&mod);
446+
bc_init_num(&bc_base);
447+
bc_init_num(&bc_expo);
448+
bc_init_num(&bc_modulus);
449449
bc_init_num(&result);
450450

451-
if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) {
451+
if (php_str2num(&bc_base, ZSTR_VAL(base)) == FAILURE) {
452452
zend_argument_value_error(1, "is not well-formed");
453453
goto cleanup;
454454
}
455455

456-
if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) {
456+
if (php_str2num(&bc_expo, ZSTR_VAL(exponent)) == FAILURE) {
457457
zend_argument_value_error(2, "is not well-formed");
458458
goto cleanup;
459459
}
460460

461-
if (php_str2num(&mod, ZSTR_VAL(modulus)) == FAILURE) {
461+
if (php_str2num(&bc_modulus, ZSTR_VAL(modulus)) == FAILURE) {
462462
zend_argument_value_error(3, "is not well-formed");
463463
goto cleanup;
464464
}
465465

466-
if (bc_raisemod(first, second, mod, &result, scale) == SUCCESS) {
467-
RETVAL_STR(bc_num2str_ex(result, scale));
466+
raise_mod_status status = bc_raisemod(bc_base, bc_expo, bc_modulus, &result, scale);
467+
switch (status) {
468+
case BASE_HAS_FRACTIONAL:
469+
zend_argument_value_error(1, "cannot have a fractional part");
470+
goto cleanup;
471+
case EXPO_HAS_FRACTIONAL:
472+
zend_argument_value_error(2, "cannot have a fractional part");
473+
goto cleanup;
474+
case EXPO_IS_NEGATIVE:
475+
zend_argument_value_error(2, "must be greater than or equal to 0");
476+
goto cleanup;
477+
case MOD_HAS_FRACTIONAL:
478+
zend_argument_value_error(3, "cannot have a fractional part");
479+
goto cleanup;
480+
case MOD_IS_ZERO:
481+
zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Modulo by zero");
482+
goto cleanup;
483+
case OK:
484+
RETVAL_STR(bc_num2str_ex(result, scale));
485+
break;
486+
EMPTY_SWITCH_DEFAULT_CASE();
468487
}
469488

470489
cleanup: {
471-
bc_free_num(&first);
472-
bc_free_num(&second);
473-
bc_free_num(&mod);
490+
bc_free_num(&bc_base);
491+
bc_free_num(&bc_expo);
492+
bc_free_num(&bc_modulus);
474493
bc_free_num(&result);
475494
};
476495
}

ext/bcmath/libbcmath/src/bcmath.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,16 @@ int bc_modulo(bc_num num1, bc_num num2, bc_num *resul, size_t scale);
124124

125125
int bc_divmod(bc_num num1, bc_num num2, bc_num *quo, bc_num *rem, size_t scale);
126126

127-
int bc_raisemod(bc_num base, bc_num expo, bc_num mo, bc_num *result, size_t scale);
127+
typedef enum {
128+
OK,
129+
BASE_HAS_FRACTIONAL,
130+
EXPO_HAS_FRACTIONAL,
131+
EXPO_IS_NEGATIVE,
132+
MOD_HAS_FRACTIONAL,
133+
MOD_IS_ZERO
134+
} raise_mod_status;
135+
136+
raise_mod_status bc_raisemod(bc_num base, bc_num expo, bc_num mod, bc_num *result, size_t scale);
128137

129138
void bc_raise(bc_num num1, bc_num num2, bc_num *resul, size_t scale);
130139

ext/bcmath/libbcmath/src/raisemod.c

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,43 +30,32 @@
3030
*************************************************************************/
3131

3232
#include "bcmath.h"
33-
#include "config.h"
34-
#include "zend_result.h"
35-
#include "zend_exceptions.h"
3633
#include <stddef.h>
3734

3835
/* Raise BASE to the EXPO power, reduced modulo MOD. The result is placed in RESULT. */
39-
zend_result bc_raisemod (bc_num base, bc_num expo, bc_num mod, bc_num *result, size_t scale)
36+
raise_mod_status bc_raisemod(bc_num base, bc_num expo, bc_num mod, bc_num *result, size_t scale)
4037
{
4138
bc_num power, exponent, modulus, parity, temp;
4239
size_t rscale;
4340

4441
/* Check the base for scale digits. */
4542
if (base->n_scale != 0) {
46-
/* 1st argument from PHP_FUNCTION(bcpowmod) */
47-
zend_argument_value_error(1, "cannot have a fractional part");
48-
return FAILURE;
43+
return BASE_HAS_FRACTIONAL;
4944
}
5045
/* Check the exponent for scale digits. */
5146
if (expo->n_scale != 0) {
52-
/* 2nd argument from PHP_FUNCTION(bcpowmod) */
53-
zend_argument_value_error(2, "cannot have a fractional part");
54-
return FAILURE;
47+
return EXPO_HAS_FRACTIONAL;
5548
}
5649
if (bc_is_neg(expo)) {
57-
zend_argument_value_error(2, "must be greater than or equal to 0");
58-
return FAILURE;
50+
return EXPO_IS_NEGATIVE;
5951
}
6052
/* Check the modulus for scale digits. */
6153
if (mod->n_scale != 0) {
62-
/* 3rd argument from PHP_FUNCTION(bcpowmod) */
63-
zend_argument_value_error(3, "cannot have a fractional part");
64-
return FAILURE;
54+
return MOD_HAS_FRACTIONAL;
6555
}
6656
/* Modulus cannot be 0 */
6757
if (bc_is_zero(mod)) {
68-
zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Modulo by zero");
69-
return FAILURE;
58+
return MOD_IS_ZERO;
7059
}
7160

7261
/* Set initial values. */
@@ -100,5 +89,5 @@ zend_result bc_raisemod (bc_num base, bc_num expo, bc_num mod, bc_num *result, s
10089
bc_free_num (result);
10190
bc_free_num (&parity);
10291
*result = temp;
103-
return SUCCESS; /* Everything is OK. */
92+
return OK;
10493
}

0 commit comments

Comments
 (0)