Skip to content

Commit ce8374b

Browse files
committed
wip
1 parent a3c04c3 commit ce8374b

File tree

4 files changed

+70
-58
lines changed

4 files changed

+70
-58
lines changed

ext/bcmath/bcmath.c

Lines changed: 66 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,6 @@ PHP_FUNCTION(bcscale)
768768

769769
static zend_class_entry *bc_num_ce;
770770
static zend_object_handlers bc_num_obj_handlers;
771-
#define IS_BC_NUM(zval) (Z_TYPE_P(zval) == IS_OBJECT && instanceof_function(Z_OBJCE_P(zval), bc_num_ce))
772771

773772
static inline bc_num_obj *bc_num_obj_from_obj(zend_object *obj) {
774773
return (bc_num_obj*)((char*)(obj) - XtOffsetOf(bc_num_obj, std));
@@ -787,6 +786,7 @@ static zend_object *bc_num_create_obj(zend_class_entry *ce)
787786
zend_object_std_init(&intern->std, ce);
788787
object_properties_init(&intern->std, ce);
789788
rebuild_object_properties(&intern->std);
789+
intern->num = NULL;
790790

791791
return &intern->std;
792792
}
@@ -796,39 +796,39 @@ static zend_object *bc_num_create_obj(zend_class_entry *ce)
796796
static void bc_num_free_obj(zend_object *object)
797797
{
798798
bc_num_obj *intern = bc_num_obj_from_obj(object);
799-
if (intern->bc_num) {
800-
bc_free_num(&intern->bc_num);
799+
if (intern->num) {
800+
bc_free_num(&intern->num);
801801
}
802-
efree(intern->bc_num);
802+
intern->num = NULL;
803803
zend_object_std_dtor(&intern->std);
804804
}
805805
/* }}} */
806806

807807
/* {{{ bc_num_obj_handlers.clone_obj */
808808
static zend_object *bc_num_clone_obj(zend_object *object)
809809
{
810-
bc_num_obj *old_obj = bc_num_obj_from_obj(object);
811-
bc_num_obj *new_obj = bc_num_obj_from_obj(bc_num_create_obj(old_obj->std.ce));
810+
bc_num_obj *original = bc_num_obj_from_obj(object);
811+
bc_num_obj *clone = bc_num_obj_from_obj(bc_num_create_obj(original->std.ce));
812812

813-
zend_objects_clone_members(&new_obj->std, &old_obj->std);
814-
new_obj->bc_num = bc_copy_num(old_obj->bc_num);
813+
zend_objects_clone_members(&clone->std, &original->std);
814+
clone->num = bc_copy_num(original->num);
815815

816-
return &new_obj->std;
816+
return &clone->std;
817817
}
818818
/* }}} */
819819

820-
static zend_result convert_zval_to_bc_num(zval *zv, bc_num *num, bool *should_free)
820+
static zend_result convert_zval_to_bc_num(zval *zv, bc_num *num)
821821
{
822-
*should_free = false;
822+
bc_num tmp;
823823

824824
switch (Z_TYPE_P(zv)) {
825825
case IS_LONG:
826826
case IS_STRING:
827827
{
828828
zend_string *str = zval_get_string(zv);
829-
bc_init_num(num);
830-
*should_free = true;
831-
if (!bc_str2num(num, ZSTR_VAL(str), 0)) {
829+
bc_init_num(&tmp);
830+
if (!bc_str2num(&tmp, ZSTR_VAL(str), 0)) {
831+
bc_free_num(&tmp);
832832
zend_string_release(str);
833833
return FAILURE;
834834
}
@@ -837,48 +837,46 @@ static zend_result convert_zval_to_bc_num(zval *zv, bc_num *num, bool *should_fr
837837
break;
838838
case IS_OBJECT:
839839
if (instanceof_function(Z_OBJCE_P(zv), bc_num_ce)) {
840-
*num = bc_num_obj_from_zval(zv)->bc_num;
840+
tmp = bc_num_obj_from_zval(zv)->num;
841841
} else {
842842
zend_argument_type_error(0, "must be of type int, string, or BcNum, %s given", zend_zval_value_name(zv));
843843
return FAILURE;
844844
}
845845
break;
846846
}
847847

848+
*num = tmp;
848849
return SUCCESS;
849850
}
850851

851852
static zend_result bc_num_calculation(zval *result, zval *op1, zval *op2, bc_num_calculation_type type, bool is_operator)
852853
{
853-
bc_num num1, num2;
854+
bc_num num1 = NULL, num2 = NULL, result_num = NULL;
854855
bc_num_obj *result_obj;
855-
bool should_free1, should_free2, should_free_result = false;
856856

857-
if (convert_zval_to_bc_num(op1, &num1, &should_free1) == FAILURE || convert_zval_to_bc_num(op2, &num2, &should_free2) == FAILURE) {
857+
if (convert_zval_to_bc_num(op1, &num1) == FAILURE || convert_zval_to_bc_num(op2, &num2) == FAILURE) {
858858
goto cleanup;
859859
}
860860

861-
result_obj = bc_num_obj_from_obj(bc_num_create_obj(bc_num_ce));
862-
bc_init_num(&result_obj->bc_num);
863-
should_free_result = true;
861+
bc_init_num(&result_num);
864862

865863
size_t scale = MAX(num1->n_scale, num2->n_scale);
866864

867865
switch (type) {
868866
case BC_NUM_ADD:
869-
bc_add(num1, num2, &result_obj->bc_num, scale);
867+
bc_add(num1, num2, &result_num, scale);
870868
break;
871869
case BC_NUM_SUB:
872-
bc_sub(num1, num2, &result_obj->bc_num, scale);
870+
bc_sub(num1, num2, &result_num, scale);
873871
break;
874872
case BC_NUM_MUL:
875-
bc_multiply(num1, num2, &result_obj->bc_num, scale);
873+
bc_multiply(num1, num2, &result_num, scale);
876874
break;
877875
case BC_NUM_DIV:
878-
bc_divide(num1, num2, &result_obj->bc_num, scale);
876+
bc_divide(num1, num2, &result_num, scale);
879877
break;
880878
case BC_NUM_MOD:
881-
bc_modulo(num1, num2, &result_obj->bc_num, scale);
879+
bc_modulo(num1, num2, &result_num, scale);
882880
break;
883881
case BC_NUM_POW:
884882
{
@@ -887,32 +885,34 @@ static zend_result bc_num_calculation(zval *result, zval *op1, zval *op2, bc_num
887885
zend_argument_value_error(is_operator ? 0 : 1, "exponent is too large");
888886
goto cleanup;
889887
}
890-
bc_raise(num1, bc_num2long(num2), &result_obj->bc_num, scale);
888+
bc_raise(num1, bc_num2long(num2), &result_num, scale);
891889
}
892890
break;
893891
EMPTY_SWITCH_DEFAULT_CASE()
894892
}
895893

896-
if (should_free1) {
894+
if (num1 && Z_TYPE_P(op1) != IS_OBJECT) {
897895
bc_free_num(&num1);
898896
}
899-
if (should_free2) {
897+
if (num2 && Z_TYPE_P(op2) != IS_OBJECT) {
900898
bc_free_num(&num2);
901899
}
902900

903-
result_obj->bc_num->n_scale = scale;
901+
result_num->n_scale = scale;
902+
result_obj = bc_num_obj_from_obj(bc_num_create_obj(bc_num_ce));
903+
result_obj->num = result_num;
904904
ZVAL_OBJ(result, &result_obj->std);
905905
return SUCCESS;
906906

907907
cleanup:
908-
if (should_free1) {
908+
if (num1 && Z_TYPE_P(op1) != IS_OBJECT) {
909909
bc_free_num(&num1);
910910
}
911-
if (should_free2) {
911+
if (num2 && Z_TYPE_P(op2) != IS_OBJECT) {
912912
bc_free_num(&num2);
913913
}
914-
if (should_free_result) {
915-
bc_free_num(&result_obj->bc_num);
914+
if (result_num) {
915+
bc_free_num(&result_num);
916916
}
917917
return FAILURE;
918918
}
@@ -952,23 +952,20 @@ static int bc_num_do_operation(uint8_t opcode, zval *result, zval *op1, zval *op
952952
/* {{{ bc_num_obj_handlers.compare */
953953
static int bc_num_compare(zval *z1, zval *z2)
954954
{
955-
bc_num_obj *obj1;
956-
bc_num_obj *obj2;
957-
958955
ZEND_COMPARE_OBJECTS_FALLBACK(z1, z2);
959956

960-
obj1 = bc_num_obj_from_zval(z1);
961-
obj2 = bc_num_obj_from_zval(z2);
957+
bc_num_obj *intern1 = bc_num_obj_from_zval(z1);
958+
bc_num_obj *intern2 = bc_num_obj_from_zval(z2);
962959

963-
return bc_compare(obj1->bc_num, obj2->bc_num);
960+
return bc_compare(intern1->num, intern2->num);
964961
}
965962
/* }}} */
966963

967964
/* {{{ bc_num_obj_handlers.get_properties_for */
968965
static HashTable *bc_num_get_properties_for(zend_object *object, zend_prop_purpose purpose)
969966
{
970967
HashTable *props;
971-
bc_num_obj *bc_num_obj;
968+
bc_num_obj *intern;
972969

973970
switch (purpose) {
974971
case ZEND_PROP_PURPOSE_DEBUG:
@@ -982,12 +979,12 @@ static HashTable *bc_num_get_properties_for(zend_object *object, zend_prop_purpo
982979
}
983980

984981
zval zv;
985-
bc_num_obj = bc_num_obj_from_obj(object);
982+
intern = bc_num_obj_from_obj(object);
986983
props = zend_array_dup(zend_std_get_properties(object));
987984

988-
ZVAL_STR(&zv, bc_num2str(bc_num_obj->bc_num));
985+
ZVAL_STR(&zv, bc_num2str(intern->num));
989986
zend_hash_str_update(props, "num", sizeof("num")-1, &zv);
990-
ZVAL_LONG(&zv, bc_num_obj->bc_num->n_scale);
987+
ZVAL_LONG(&zv, intern->num->n_scale);
991988
zend_hash_str_update(props, "scale", sizeof("scale")-1, &zv);
992989

993990
return props;
@@ -1022,17 +1019,22 @@ static void bc_num_register_class(void)
10221019
/* {{{ Creates new BcNum */
10231020
PHP_METHOD(BcNum, __construct)
10241021
{
1025-
zend_string *num_str;
1022+
zend_string *num_str, *num_str_tmp;
1023+
zend_long num_l;
10261024
zend_long scale_param;
10271025
bool scale_param_is_null = 1;
10281026
int scale;
10291027

10301028
ZEND_PARSE_PARAMETERS_START(1, 2)
1031-
Z_PARAM_STR(num_str)
1029+
Z_PARAM_STR_OR_LONG(num_str, num_l)
10321030
Z_PARAM_OPTIONAL
10331031
Z_PARAM_LONG_OR_NULL(scale_param, scale_param_is_null)
10341032
ZEND_PARSE_PARAMETERS_END();
10351033

1034+
if (!num_str) {
1035+
num_str_tmp = zend_long_to_str(num_l);
1036+
}
1037+
10361038
if (scale_param_is_null) {
10371039
scale = BCG(bc_precision);
10381040
} else if (scale_param < 0 || scale_param > INT_MAX) {
@@ -1042,22 +1044,32 @@ PHP_METHOD(BcNum, __construct)
10421044
scale = (int) scale_param;
10431045
}
10441046

1045-
bc_num_obj *obj = bc_num_obj_from_zval(ZEND_THIS);
1046-
bc_init_num(&obj->bc_num);
1047+
bc_num_obj *intern = bc_num_obj_from_zval(ZEND_THIS);
10471048

1048-
if (php_str2num(&obj->bc_num, ZSTR_VAL(num_str)) == FAILURE) {
1049+
bc_num num;
1050+
bc_init_num(&num);
1051+
1052+
if (php_str2num(&num, ZSTR_VAL(num_str ?: num_str_tmp)) == FAILURE) {
10491053
zend_argument_value_error(1, "is not well-formed");
1050-
bc_free_num(&obj->bc_num);
1054+
bc_free_num(&num);
1055+
if (num_str_tmp) {
1056+
zend_string_release(num_str_tmp);
1057+
}
10511058
RETURN_THROWS();
10521059
}
10531060

1054-
if (obj->bc_num->n_scale < scale) {
1055-
char *nptr = (char *) (obj->bc_num->n_value + obj->bc_num->n_len + obj->bc_num->n_scale);
1056-
for (int count = scale - obj->bc_num->n_scale; count > 0; count--) {
1061+
if (num_str_tmp) {
1062+
zend_string_release(num_str_tmp);
1063+
}
1064+
1065+
if (num->n_scale < scale) {
1066+
char *nptr = (char *) (num->n_value + num->n_len + num->n_scale);
1067+
for (int count = scale - num->n_scale; count > 0; count--) {
10571068
*nptr++ = 0;
10581069
}
10591070
}
1060-
obj->bc_num->n_scale = scale;
1071+
num->n_scale = scale;
1072+
intern->num = num;
10611073
}
10621074
/* }}} */
10631075

ext/bcmath/bcmath.stub.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ function bcround(string $num, int $precision = 0, int $mode = PHP_ROUND_HALF_UP)
4141

4242
class BcNum
4343
{
44-
public function __construct(string $num, ?int $scale = null) {}
44+
public function __construct(string|int $num, ?int $scale = null) {}
4545

4646
//public static function getGlobalScale(): int {}
4747

ext/bcmath/bcmath_arginfo.h

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/bcmath/php_bcmath.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ ZEND_EXTERN_MODULE_GLOBALS(bcmath)
4444

4545
typedef struct _bc_num_obj {
4646
zend_object std;
47-
bc_num bc_num;
47+
bc_num num;
4848
} bc_num_obj;
4949

5050
typedef enum {

0 commit comments

Comments
 (0)