improve decimal context
authorMichael Wallner <mike@php.net>
Wed, 15 Dec 2021 15:27:20 +0000 (16:27 +0100)
committerMichael Wallner <mike@php.net>
Wed, 15 Dec 2021 15:27:20 +0000 (16:27 +0100)
ion.c
ion.stub.php
ion_arginfo.h
ion_private.h
tests/Decimal.phpt
tests/Decimal/Context.phpt
tests/Decimal/Context/__construct.phpt
tests/Decimal/__construct.phpt

diff --git a/ion.c b/ion.c
index 4af7609dc84281a2db189ae5ff872c0eeee6b616..cc2553d2871b39f46eb40e49e11d8a6315134296 100644 (file)
--- a/ion.c
+++ b/ion.c
@@ -138,14 +138,60 @@ ZEND_METHOD(ion_Decimal_Context, __construct)
        php_ion_decimal_ctx *obj = php_ion_obj(decimal_ctx, Z_OBJ_P(ZEND_THIS));
        PTR_CHECK(obj);
 
-       zend_long bits = 128;
+       zend_bool clamp;
+       zend_object *o_round = NULL;
+       zend_long digits, emax, emin, round;
+       ZEND_PARSE_PARAMETERS_START(5, 5)
+               Z_PARAM_LONG(digits)
+               Z_PARAM_LONG(emax)
+               Z_PARAM_LONG(emin)
+               Z_PARAM_OBJ_OF_CLASS_OR_LONG(o_round, ce_Decimal_Context_Rounding, round)
+               Z_PARAM_BOOL(clamp)
+       ZEND_PARSE_PARAMETERS_END();
+
+       if (o_round) {
+               round = Z_LVAL_P(zend_enum_fetch_case_value(o_round));
+       }
+       php_ion_decimal_ctx_init(&obj->ctx, digits, emax, emin, round, clamp);
+       php_ion_decimal_ctx_ctor(obj, o_round);
+}
+static inline void make_decimal_ctx(INTERNAL_FUNCTION_PARAMETERS, int kind)
+{
+       ZEND_PARSE_PARAMETERS_NONE();
+
+       object_init_ex(return_value, ce_Decimal_Context);
+       php_ion_decimal_ctx *obj = php_ion_obj(decimal_ctx, Z_OBJ_P(return_value));
+       decContextDefault(&obj->ctx, kind);
+       php_ion_decimal_ctx_ctor(obj, NULL);
+}
+ZEND_METHOD(ion_Decimal_Context, Dec32)
+{
+       make_decimal_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, DEC_INIT_DECIMAL32);
+}
+ZEND_METHOD(ion_Decimal_Context, Dec64)
+{
+       make_decimal_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, DEC_INIT_DECIMAL64);
+}
+ZEND_METHOD(ion_Decimal_Context, Dec128)
+{
+       make_decimal_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, DEC_INIT_DECIMAL128);
+}
+ZEND_METHOD(ion_Decimal_Context, DecMax)
+{
+       zend_object *o_round = NULL;
+       zend_long round = DEC_ROUND_HALF_EVEN;
        ZEND_PARSE_PARAMETERS_START(0, 1)
                Z_PARAM_OPTIONAL
-               Z_PARAM_LONG(bits)
+               Z_PARAM_OBJ_OF_CLASS_OR_LONG(o_round, ce_Decimal_Context_Rounding, round)
        ZEND_PARSE_PARAMETERS_END();
 
-       zend_update_property_long(obj->std.ce, &obj->std, ZEND_STRL("bits"), bits);
-       php_ion_decimal_ctx_ctor(obj);
+       if (o_round) {
+               round = Z_LVAL_P(zend_enum_fetch_case_value(o_round));
+       }
+       object_init_ex(return_value, ce_Decimal_Context);
+       php_ion_decimal_ctx *obj = php_ion_obj(decimal_ctx, Z_OBJ_P(return_value));
+       php_ion_decimal_ctx_init_max(&obj->ctx, round);
+       php_ion_decimal_ctx_ctor(obj, o_round);
 }
 ZEND_METHOD(ion_Decimal, __construct)
 {
@@ -166,7 +212,7 @@ ZEND_METHOD(ion_Decimal, __construct)
                zval zdc;
                object_init_ex(&zdc, ce_Decimal_Context);
                obj->ctx = Z_OBJ(zdc);
-               php_ion_decimal_ctx_ctor(php_ion_obj(decimal_ctx, obj->ctx));
+               php_ion_decimal_ctx_ctor(php_ion_obj(decimal_ctx, obj->ctx), NULL);
        }
 
        decContext *ctx = &php_ion_obj(decimal_ctx, obj->ctx)->ctx;
@@ -1453,59 +1499,63 @@ PHP_RSHUTDOWN_FUNCTION(ion)
 
 PHP_MINIT_FUNCTION(ion)
 {
-       decContextDefault(&g_dec_ctx, DEC_INIT_DECIMAL64);
-
-       ion_int_alloc(NULL, &g_ion_int_zend_max);
-       ion_int_from_long(g_ion_int_zend_max, ZEND_LONG_MAX);
-       g_ion_dec_zend_max.type = ION_DECIMAL_TYPE_QUAD;
-       ion_decimal_from_ion_int(&g_ion_dec_zend_max, &g_dec_ctx, g_ion_int_zend_max);
-
-       ion_int_alloc(NULL, &g_ion_int_zend_min);
-       ion_int_from_long(g_ion_int_zend_min, ZEND_LONG_MIN);
-       g_ion_dec_zend_min.type = ION_DECIMAL_TYPE_QUAD;
-       ion_decimal_from_ion_int(&g_ion_dec_zend_min, &g_dec_ctx, g_ion_int_zend_min);
+       // globals
+       php_ion_decimal_ctx_init_max(&g_dec_ctx, DEC_ROUND_HALF_EVEN);
+       php_ion_decimal_from_zend_long(&g_ion_dec_zend_max, &g_dec_ctx, ZEND_LONG_MAX);
+       php_ion_decimal_from_zend_long(&g_ion_dec_zend_min, &g_dec_ctx, ZEND_LONG_MIN);
 
+       // Annotation
        ce_Annotation = register_class_ion_Annotation();
 
-       php_ion_register(type, Type);
-       php_ion_register(symbol, Symbol);
-       php_ion_register(symbol_iloc, Symbol_ImportLocation);
-       php_ion_register(symbol_table, Symbol_Table);
-
-       ce_Symbol_System = register_class_ion_Symbol_System();
-       ce_Symbol_System_SID = register_class_ion_Symbol_System_SID();
-
+       // Collection
        ce_Collection = register_class_ion_Collection();
-       ce_LOB = register_class_ion_LOB();
 
+       // Decimal
        php_ion_register(decimal, Decimal);
        php_ion_register(decimal_ctx, Decimal_Context);
-       php_ion_register(timestamp, Timestamp, php_date_get_date_ce());
-       ce_Timestamp_Precision = register_class_ion_Timestamp_Precision();
-       php_ion_register(catalog, Catalog);
+       ce_Decimal_Context_Rounding = register_class_ion_Decimal_Context_Rounding();
 
-       ce_Reader = register_class_ion_Reader(spl_ce_RecursiveIterator);
+       // LOB
+       ce_LOB = register_class_ion_LOB();
 
+       // Reader
+       ce_Reader = register_class_ion_Reader(spl_ce_RecursiveIterator);
        php_ion_register(reader_options, Reader_Options);
        php_ion_register(reader, Reader_Reader, ce_Reader);
-
        ce_Reader_Buffer = register_class_ion_Reader_Buffer(ce_Reader);
        ce_Reader_Buffer_Reader = register_class_ion_Reader_Buffer_Reader(ce_Reader_Reader, ce_Reader_Buffer);
        ce_Reader_Stream = register_class_ion_Reader_Stream(ce_Reader);
        ce_Reader_Stream_Reader = register_class_ion_Reader_Stream_Reader(ce_Reader_Reader, ce_Reader_Stream);
 
-       ce_Writer = register_class_ion_Writer();
+       // Serializer
+       ce_Serializer = register_class_ion_Serializer();
+       php_ion_register(serializer_php, Serializer_PHP, ce_Serializer);
+
+       // Symbol
+       php_ion_register(symbol, Symbol);
+       php_ion_register(symbol_iloc, Symbol_ImportLocation);
+       php_ion_register(symbol_table, Symbol_Table);
+       ce_Symbol_System = register_class_ion_Symbol_System();
+       ce_Symbol_System_SID = register_class_ion_Symbol_System_SID();
+
+       // Timestamp
+       php_ion_register(timestamp, Timestamp, php_date_get_date_ce());
+       ce_Timestamp_Precision = register_class_ion_Timestamp_Precision();
+       php_ion_register(catalog, Catalog);
 
+       // Type
+       php_ion_register(type, Type);
+
+       // Writer
+       ce_Writer = register_class_ion_Writer();
        php_ion_register(writer_options, Writer_Options);
        php_ion_register(writer, Writer_Writer, ce_Writer);
-
        ce_Writer_Buffer = register_class_ion_Writer_Buffer(ce_Writer);
        ce_Writer_Buffer_Writer = register_class_ion_Writer_Buffer_Writer(ce_Writer_Writer, ce_Writer_Buffer);
        ce_Writer_Stream = register_class_ion_Writer_Stream(ce_Writer);
        ce_Writer_Stream_Writer = register_class_ion_Writer_Stream_Writer(ce_Writer_Writer, ce_Writer_Stream);
 
-       ce_Serializer = register_class_ion_Serializer();
-       php_ion_register(serializer_php, Serializer_PHP, ce_Serializer);
+       // Unserializer
        ce_Unserializer = register_class_ion_Unserializer();
        php_ion_register(unserializer_php, Unserializer_PHP, ce_Unserializer);
 
@@ -1514,8 +1564,6 @@ PHP_MINIT_FUNCTION(ion)
 
 PHP_MSHUTDOWN_FUNCTION(ion)
 {
-       ion_int_free(g_ion_int_zend_max);
-       ion_int_free(g_ion_int_zend_min);
        return SUCCESS;
 }
 PHP_MINFO_FUNCTION(ion)
index 4e85695c0cc1be2331fda935540258662cd4e698..e874b927018ee1fe210d0371f9ff80ba377cac0b 100644 (file)
@@ -110,11 +110,32 @@ class LOB {
     }
 }
 
+namespace ion\Decimal\Context;
+enum Rounding : int {
+    case Ceiling    = 0;
+    case Up         = 1;
+    case HalfUp     = 2;
+    case HalfEven   = 3;
+    case HalfDown   = 4;
+    case Down       = 5;
+    case Floor      = 6;
+    case Down05Up   = 7;
+}
+
 namespace ion\Decimal;
 class Context {
     public function __construct(
-        public readonly int $bits = 128
+        public readonly int $digits,
+        public readonly int $eMax,
+        public readonly int $eMin,
+        public readonly Context\Rounding|int $round,
+        public readonly bool $clamp,
     ) {}
+
+    public static function Dec32() : Context {}
+    public static function Dec64() : Context {}
+    public static function Dec128() : Context {}
+    public static function DecMax(Context\Rounding|int $round = Context\Rounding::HalfEven) : Context {}
 }
 
 namespace ion;
index ad2a80e72f66af89251b5db4fea0eb1ea008524a..187891b9e062f2b3b7b8de809c286e98a33250de 100644 (file)
@@ -1,5 +1,5 @@
 /* This is a generated file, edit the .stub.php file instead.
- * Stub hash: 4c467ccb7b924c30cc5471b9212f4bffe0b0ba31 */
+ * Stub hash: 3639336622da610f8866722b870d87563646465f */
 
 ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ion_serialize, 0, 1, IS_STRING, 0)
        ZEND_ARG_TYPE_INFO(0, data, IS_MIXED, 0)
@@ -36,8 +36,23 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ion_LOB___construct, 0, 0, 1)
        ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, type, ion\\Type, 0, "ion\\Type::CLob")
 ZEND_END_ARG_INFO()
 
-ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ion_Decimal_Context___construct, 0, 0, 0)
-       ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, bits, IS_LONG, 0, "128")
+ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ion_Decimal_Context___construct, 0, 0, 5)
+       ZEND_ARG_TYPE_INFO(0, digits, IS_LONG, 0)
+       ZEND_ARG_TYPE_INFO(0, eMax, IS_LONG, 0)
+       ZEND_ARG_TYPE_INFO(0, eMin, IS_LONG, 0)
+       ZEND_ARG_OBJ_TYPE_MASK(0, round, ion\\Decimal\\Context\\Rounding, MAY_BE_LONG, NULL)
+       ZEND_ARG_TYPE_INFO(0, clamp, _IS_BOOL, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_ion_Decimal_Context_Dec32, 0, 0, ion\\Decimal\\Context, 0)
+ZEND_END_ARG_INFO()
+
+#define arginfo_class_ion_Decimal_Context_Dec64 arginfo_class_ion_Decimal_Context_Dec32
+
+#define arginfo_class_ion_Decimal_Context_Dec128 arginfo_class_ion_Decimal_Context_Dec32
+
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_ion_Decimal_Context_DecMax, 0, 0, ion\\Decimal\\Context, 0)
+       ZEND_ARG_OBJ_TYPE_MASK(0, round, ion\\Decimal\\Context\\Rounding, MAY_BE_LONG, "ion\\Decimal\\Context\\Rounding::HalfEven")
 ZEND_END_ARG_INFO()
 
 ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ion_Decimal___construct, 0, 0, 1)
@@ -457,6 +472,10 @@ ZEND_METHOD(ion_Symbol, equals);
 ZEND_METHOD(ion_Symbol, __toString);
 ZEND_METHOD(ion_LOB, __construct);
 ZEND_METHOD(ion_Decimal_Context, __construct);
+ZEND_METHOD(ion_Decimal_Context, Dec32);
+ZEND_METHOD(ion_Decimal_Context, Dec64);
+ZEND_METHOD(ion_Decimal_Context, Dec128);
+ZEND_METHOD(ion_Decimal_Context, DecMax);
 ZEND_METHOD(ion_Decimal, __construct);
 ZEND_METHOD(ion_Decimal, equals);
 ZEND_METHOD(ion_Decimal, isInt);
@@ -605,8 +624,17 @@ static const zend_function_entry class_ion_LOB_methods[] = {
 };
 
 
+static const zend_function_entry class_ion_Decimal_Context_Rounding_methods[] = {
+       ZEND_FE_END
+};
+
+
 static const zend_function_entry class_ion_Decimal_Context_methods[] = {
        ZEND_ME(ion_Decimal_Context, __construct, arginfo_class_ion_Decimal_Context___construct, ZEND_ACC_PUBLIC)
+       ZEND_ME(ion_Decimal_Context, Dec32, arginfo_class_ion_Decimal_Context_Dec32, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+       ZEND_ME(ion_Decimal_Context, Dec64, arginfo_class_ion_Decimal_Context_Dec64, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+       ZEND_ME(ion_Decimal_Context, Dec128, arginfo_class_ion_Decimal_Context_Dec128, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+       ZEND_ME(ion_Decimal_Context, DecMax, arginfo_class_ion_Decimal_Context_DecMax, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
        ZEND_FE_END
 };
 
@@ -1185,6 +1213,45 @@ static zend_class_entry *register_class_ion_LOB(void)
        return class_entry;
 }
 
+static zend_class_entry *register_class_ion_Decimal_Context_Rounding(void)
+{
+       zend_class_entry *class_entry = zend_register_internal_enum("ion\\Decimal\\Context\\Rounding", IS_LONG, class_ion_Decimal_Context_Rounding_methods);
+
+       zval enum_case_Ceiling_value;
+       ZVAL_LONG(&enum_case_Ceiling_value, 0);
+       zend_enum_add_case_cstr(class_entry, "Ceiling", &enum_case_Ceiling_value);
+
+       zval enum_case_Up_value;
+       ZVAL_LONG(&enum_case_Up_value, 1);
+       zend_enum_add_case_cstr(class_entry, "Up", &enum_case_Up_value);
+
+       zval enum_case_HalfUp_value;
+       ZVAL_LONG(&enum_case_HalfUp_value, 2);
+       zend_enum_add_case_cstr(class_entry, "HalfUp", &enum_case_HalfUp_value);
+
+       zval enum_case_HalfEven_value;
+       ZVAL_LONG(&enum_case_HalfEven_value, 3);
+       zend_enum_add_case_cstr(class_entry, "HalfEven", &enum_case_HalfEven_value);
+
+       zval enum_case_HalfDown_value;
+       ZVAL_LONG(&enum_case_HalfDown_value, 4);
+       zend_enum_add_case_cstr(class_entry, "HalfDown", &enum_case_HalfDown_value);
+
+       zval enum_case_Down_value;
+       ZVAL_LONG(&enum_case_Down_value, 5);
+       zend_enum_add_case_cstr(class_entry, "Down", &enum_case_Down_value);
+
+       zval enum_case_Floor_value;
+       ZVAL_LONG(&enum_case_Floor_value, 6);
+       zend_enum_add_case_cstr(class_entry, "Floor", &enum_case_Floor_value);
+
+       zval enum_case_Down05Up_value;
+       ZVAL_LONG(&enum_case_Down05Up_value, 7);
+       zend_enum_add_case_cstr(class_entry, "Down05Up", &enum_case_Down05Up_value);
+
+       return class_entry;
+}
+
 static zend_class_entry *register_class_ion_Decimal_Context(void)
 {
        zend_class_entry ce, *class_entry;
@@ -1192,11 +1259,36 @@ static zend_class_entry *register_class_ion_Decimal_Context(void)
        INIT_NS_CLASS_ENTRY(ce, "ion\\Decimal", "Context", class_ion_Decimal_Context_methods);
        class_entry = zend_register_internal_class_ex(&ce, NULL);
 
-       zval property_bits_default_value;
-       ZVAL_UNDEF(&property_bits_default_value);
-       zend_string *property_bits_name = zend_string_init("bits", sizeof("bits") - 1, 1);
-       zend_declare_typed_property(class_entry, property_bits_name, &property_bits_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
-       zend_string_release(property_bits_name);
+       zval property_digits_default_value;
+       ZVAL_UNDEF(&property_digits_default_value);
+       zend_string *property_digits_name = zend_string_init("digits", sizeof("digits") - 1, 1);
+       zend_declare_typed_property(class_entry, property_digits_name, &property_digits_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
+       zend_string_release(property_digits_name);
+
+       zval property_eMax_default_value;
+       ZVAL_UNDEF(&property_eMax_default_value);
+       zend_string *property_eMax_name = zend_string_init("eMax", sizeof("eMax") - 1, 1);
+       zend_declare_typed_property(class_entry, property_eMax_name, &property_eMax_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
+       zend_string_release(property_eMax_name);
+
+       zval property_eMin_default_value;
+       ZVAL_UNDEF(&property_eMin_default_value);
+       zend_string *property_eMin_name = zend_string_init("eMin", sizeof("eMin") - 1, 1);
+       zend_declare_typed_property(class_entry, property_eMin_name, &property_eMin_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
+       zend_string_release(property_eMin_name);
+
+       zend_string *property_round_class_ion_Decimal_Context_Rounding = zend_string_init("ion\\Decimal\\Context\\Rounding", sizeof("ion\\Decimal\\Context\\Rounding")-1, 1);
+       zval property_round_default_value;
+       ZVAL_UNDEF(&property_round_default_value);
+       zend_string *property_round_name = zend_string_init("round", sizeof("round") - 1, 1);
+       zend_declare_typed_property(class_entry, property_round_name, &property_round_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_round_class_ion_Decimal_Context_Rounding, 0, MAY_BE_LONG));
+       zend_string_release(property_round_name);
+
+       zval property_clamp_default_value;
+       ZVAL_UNDEF(&property_clamp_default_value);
+       zend_string *property_clamp_name = zend_string_init("clamp", sizeof("clamp") - 1, 1);
+       zend_declare_typed_property(class_entry, property_clamp_name, &property_clamp_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL));
+       zend_string_release(property_clamp_name);
 
        return class_entry;
 }
index 84b50b933cc7684e265e8ea9d7431f855c791814..2f80d8467a5e215917fc6530607993db9908b8aa 100644 (file)
@@ -172,6 +172,7 @@ static zend_class_entry
        *ce_Collection,
        *ce_Decimal,
        *ce_Decimal_Context,
+       *ce_Decimal_Context_Rounding,
        *ce_LOB,
        *ce_Reader,
        *ce_Reader_Options,
@@ -395,25 +396,33 @@ typedef struct php_ion_decimal_ctx {
        zend_object std;
 } php_ion_decimal_ctx;
 
-static inline void php_ion_decimal_ctx_ctor(php_ion_decimal_ctx *obj) {
-       zval tmp, *zbits = zend_read_property(obj->std.ce, &obj->std, ZEND_STRL("bits"), 1, &tmp);
+#define php_ion_decimal_ctx_init_max(c, rounding) \
+       php_ion_decimal_ctx_init((c), DEC_MAX_DIGITS, DEC_MAX_EMAX, DEC_MIN_EMIN, (rounding), false)
+static inline void php_ion_decimal_ctx_init(decContext *ctx,
+               zend_long digits, zend_long emax, zend_long emin, zend_long round, zend_bool clamp)
+{
+       memset(ctx, 0, sizeof(*ctx));
+       ctx->digits = digits;
+       ctx->emax = emax;
+       ctx->emin = emin;
+       ctx->round = round;
+       ctx->clamp = clamp;
+}
 
-       int bits = 128;
-       if (zbits != &EG(uninitialized_zval)) {
-               bits = Z_LVAL_P(zbits);
-       } else {
-               zend_update_property_long(obj->std.ce, &obj->std, ZEND_STRL("bits"), bits);
+static inline void php_ion_decimal_ctx_ctor(php_ion_decimal_ctx *obj, zend_object *o_round)
+{
+       if (!obj->ctx.digits) {
+               php_ion_decimal_ctx_init_max(&obj->ctx, DEC_ROUND_HALF_EVEN);
        }
-       switch (bits) {
-       case 32:
-       case 64:
-       case 128:
-               decContextDefault(&obj->ctx, bits);
-               break;
-       default:
-               zend_throw_exception_ex(spl_ce_InvalidArgumentException, IERR_INVALID_ARG,
-                               "Decimal context only allows 32, 64 or 128 bits");
+       if (o_round) {
+               update_property_obj(&obj->std, ZEND_STRL("round"), o_round);
+       } else {
+               zend_update_property_long(obj->std.ce, &obj->std, ZEND_STRL("round"), obj->ctx.round);
        }
+       zend_update_property_long(obj->std.ce, &obj->std, ZEND_STRL("digits"), obj->ctx.digits);
+       zend_update_property_long(obj->std.ce, &obj->std, ZEND_STRL("eMax"), obj->ctx.emax);
+       zend_update_property_long(obj->std.ce, &obj->std, ZEND_STRL("eMin"), obj->ctx.emin);
+       zend_update_property_bool(obj->std.ce, &obj->std, ZEND_STRL("clamp"), obj->ctx.clamp);
 }
 
 php_ion_decl(decimal_ctx, Decimal_Context);
@@ -487,7 +496,7 @@ static inline void php_ion_decimal_ctor(php_ion_decimal *obj)
                zval zdc;
                object_init_ex(&zdc, ce_Decimal_Context);
                obj->ctx = Z_OBJ(zdc);
-               php_ion_decimal_ctx_ctor(php_ion_obj(decimal_ctx, obj->ctx));
+               php_ion_decimal_ctx_ctor(php_ion_obj(decimal_ctx, obj->ctx), NULL);
                GC_DELREF(obj->ctx);
        }
        update_property_obj(&obj->std, ZEND_STRL("context"), obj->ctx);
index e861cae112318acac64d0c50285652c63017025e..cd8b242e02fe1a073185295195514ee22bbe8f7d 100644 (file)
@@ -15,18 +15,34 @@ object(ion\Decimal)#%d (2) {
   ["number"]=>
   int(1)
   ["context"]=>
-  object(ion\Decimal\Context)#%d (1) {
-    ["bits"]=>
-    int(128)
+  object(ion\Decimal\Context)#%d (5) {
+    ["digits"]=>
+    int(999999999)
+    ["eMax"]=>
+    int(999999999)
+    ["eMin"]=>
+    int(-999999999)
+    ["round"]=>
+    int(3)
+    ["clamp"]=>
+    bool(false)
   }
 }
 object(ion\Decimal)#%d (2) {
   ["number"]=>
   string(4) "1.23"
   ["context"]=>
-  object(ion\Decimal\Context)#%d (1) {
-    ["bits"]=>
-    int(128)
+  object(ion\Decimal\Context)#%d (5) {
+    ["digits"]=>
+    int(999999999)
+    ["eMax"]=>
+    int(999999999)
+    ["eMin"]=>
+    int(-999999999)
+    ["round"]=>
+    int(3)
+    ["clamp"]=>
+    bool(false)
   }
 }
 DONE
index f2b2150634def72f3888b7ec7f31004d055e7cc0..a67ed075b4d0d5c2be4d96d77e204f17b5cea7da 100644 (file)
@@ -5,18 +5,60 @@ ion
 --FILE--
 TEST
 <?php
-var_dump(new ion\Decimal\Context);
-var_dump(new ion\Decimal\Context(32));
+var_dump(ion\Decimal\Context::Dec32());
+var_dump(ion\Decimal\Context::Dec64());
+var_dump(ion\Decimal\Context::Dec128());
+var_dump(ion\Decimal\Context::DecMax());
 ?>
 DONE
 --EXPECTF--
 TEST
-object(ion\Decimal\Context)#1 (1) {
-  ["bits"]=>
-  int(128)
+object(ion\Decimal\Context)#%d (5) {
+  ["digits"]=>
+  int(7)
+  ["eMax"]=>
+  int(96)
+  ["eMin"]=>
+  int(-95)
+  ["round"]=>
+  int(3)
+  ["clamp"]=>
+  bool(true)
 }
-object(ion\Decimal\Context)#1 (1) {
-  ["bits"]=>
-  int(32)
+object(ion\Decimal\Context)#%d (5) {
+  ["digits"]=>
+  int(16)
+  ["eMax"]=>
+  int(384)
+  ["eMin"]=>
+  int(-383)
+  ["round"]=>
+  int(3)
+  ["clamp"]=>
+  bool(true)
+}
+object(ion\Decimal\Context)#%d (5) {
+  ["digits"]=>
+  int(34)
+  ["eMax"]=>
+  int(6144)
+  ["eMin"]=>
+  int(-6143)
+  ["round"]=>
+  int(3)
+  ["clamp"]=>
+  bool(true)
+}
+object(ion\Decimal\Context)#%d (5) {
+  ["digits"]=>
+  int(999999999)
+  ["eMax"]=>
+  int(999999999)
+  ["eMin"]=>
+  int(-999999999)
+  ["round"]=>
+  int(3)
+  ["clamp"]=>
+  bool(false)
 }
 DONE
index 2a96406017f1a79cd485e8921c6eef86040ef1b7..088a85004c08fcc0e69b71c2324ea47795eee72c 100644 (file)
@@ -5,17 +5,22 @@ ion
 --FILE--
 TEST
 <?php
+
 use ion\Decimal\Context;
 
-new Context;
-new Context(32);
+new Context(1,2,3,4,true);
+try {
+       new Context(1,"bar",3,4,false);
+} catch (Throwable $e) {
+       echo $e->getMessage(), "\n";
+}
 try {
-       new Context(123);
+       new Context(false,false,false,false,false);
 } catch (Throwable $e) {
        echo $e->getMessage(), "\n";
 }
 try {
-       new Context("123");
+       new Context(1,2);
 } catch (Throwable $e) {
        echo $e->getMessage(), "\n";
 }
@@ -24,11 +29,17 @@ try {
 } catch (Throwable $e) {
        echo $e->getMessage(), "\n";
 }
+try {
+       new Context;
+} catch (Throwable $e) {
+       echo $e->getMessage(), "\n";
+}
 ?>
 DONE
 --EXPECTF--
 TEST
-Decimal context only allows 32, 64 or 128 bits
-Decimal context only allows 32, 64 or 128 bits
-ion\Decimal\Context::__construct(): Argument #1 ($bits) must be of type int, string given
+ion\Decimal\Context::__construct(): Argument #2 ($eMax) must be of type int, string given
+ion\Decimal\Context::__construct() expects exactly 5 arguments, 2 given
+ion\Decimal\Context::__construct() expects exactly 5 arguments, 1 given
+ion\Decimal\Context::__construct() expects exactly 5 arguments, 0 given
 DONE
index ee56e9f48a8351a5359bc4d30c3bff4dd1f08a61..5760251524cf2ca0a670a0c5de8f5e3907c0455f 100644 (file)
@@ -17,7 +17,7 @@ new Decimal("123");
 new Decimal(123.123);
 new Decimal("123.123");
 new Decimal(1, null);
-new Decimal(1, new Decimal\Context);
+new Decimal(1, Decimal\Context::Dec64());
 ?>
 DONE
 --EXPECTF--