oj 3.10.7 → 3.10.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/oj/custom.c +1 -1
- data/ext/oj/object.c +1 -1
- data/ext/oj/oj.c +6 -1
- data/ext/oj/oj.h +2 -1
- data/ext/oj/parse.c +79 -43
- data/ext/oj/parse.h +2 -1
- data/ext/oj/sparse.c +7 -4
- data/lib/oj/version.rb +1 -1
- data/test/sample_json.rb +1 -1
- data/test/test_custom.rb +6 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb725babd05d3dadf33c86b0737e278f0f2eed8bb1792300dca74f5138a472a5
|
4
|
+
data.tar.gz: c60cd42eccaeea5937726f90225a611b19901ff4d133968e304de6f6d9077a31
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 56791447ce08bbe3aca701ff0b50e17f70dbd2bae22bcc07fcdbe5216b9da7e976f6ee748bee83d12a2915148ddc83e99ac52203e9baa7a3e268023a808515e0
|
7
|
+
data.tar.gz: 9906af11fb4fd41f2a4d311d0c7e0a4d72c3947e53201fa745717f356d67cbc757ebcbbb341eff03f7d4c1cb1bb76da59d05b14e31119f098e1b398d8f164304
|
data/ext/oj/custom.c
CHANGED
@@ -1089,7 +1089,7 @@ hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) {
|
|
1089
1089
|
// offset and then a conversion to UTC keeps makes the time
|
1090
1090
|
// match the expected value.
|
1091
1091
|
parent->val = rb_funcall2(parent->val, oj_utc_id, 0, 0);
|
1092
|
-
} else if (ni->
|
1092
|
+
} else if (ni->has_exp) {
|
1093
1093
|
int64_t t = (int64_t)(ni->i + ni->exp);
|
1094
1094
|
struct _timeInfo ti;
|
1095
1095
|
VALUE args[8];
|
data/ext/oj/object.c
CHANGED
@@ -295,7 +295,7 @@ hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) {
|
|
295
295
|
// offset and then a conversion to UTC keeps makes the time
|
296
296
|
// match the expected value.
|
297
297
|
parent->val = rb_funcall2(parent->val, oj_utc_id, 0, 0);
|
298
|
-
} else if (ni->
|
298
|
+
} else if (ni->has_exp) {
|
299
299
|
int64_t t = (int64_t)(ni->i + ni->exp);
|
300
300
|
struct _timeInfo ti;
|
301
301
|
VALUE args[8];
|
data/ext/oj/oj.c
CHANGED
@@ -115,6 +115,7 @@ static VALUE custom_sym;
|
|
115
115
|
static VALUE empty_string_sym;
|
116
116
|
static VALUE escape_mode_sym;
|
117
117
|
static VALUE integer_range_sym;
|
118
|
+
static VALUE fast_sym;
|
118
119
|
static VALUE float_prec_sym;
|
119
120
|
static VALUE float_sym;
|
120
121
|
static VALUE huge_sym;
|
@@ -230,7 +231,7 @@ struct _options oj_default_options = {
|
|
230
231
|
* - *:mode* [_:object_|_:strict_|_:compat_|_:null_|_:custom_|_:rails_|_:wab_] load and dump modes to use for JSON
|
231
232
|
* - *:time_format* [_:unix_|_:unix_zone_|_:xmlschema_|_:ruby_] time format when dumping
|
232
233
|
* - *:bigdecimal_as_decimal* [_Boolean_|_nil_] dump BigDecimal as a decimal number or as a String
|
233
|
-
* - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_] load decimals as BigDecimal instead of as a Float. :auto pick the most precise for the number of digits.
|
234
|
+
* - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_|_:fast_] load decimals as BigDecimal instead of as a Float. :auto pick the most precise for the number of digits. :float should be the same as ruby. :fast may require rounding but is must faster.
|
234
235
|
* - *:create_id* [_String_|_nil_] create id for json compatible object encoding, default is 'json_class'
|
235
236
|
* - *:create_additions* [_Boolean_|_nil_] if true allow creation of instances using create_id on load.
|
236
237
|
* - *:second_precision* [_Fixnum_|_nil_] number of digits after the decimal when dumping the seconds portion of time
|
@@ -331,6 +332,7 @@ get_def_opts(VALUE self) {
|
|
331
332
|
switch (oj_default_options.bigdec_load) {
|
332
333
|
case BigDec: rb_hash_aset(opts, bigdecimal_load_sym, bigdecimal_sym);break;
|
333
334
|
case FloatDec: rb_hash_aset(opts, bigdecimal_load_sym, float_sym); break;
|
335
|
+
case FastDec: rb_hash_aset(opts, bigdecimal_load_sym, fast_sym); break;
|
334
336
|
case AutoDec:
|
335
337
|
default: rb_hash_aset(opts, bigdecimal_load_sym, auto_sym); break;
|
336
338
|
}
|
@@ -574,6 +576,8 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
574
576
|
copts->bigdec_load = BigDec;
|
575
577
|
} else if (float_sym == v) {
|
576
578
|
copts->bigdec_load = FloatDec;
|
579
|
+
} else if (fast_sym == v) {
|
580
|
+
copts->bigdec_load = FastDec;
|
577
581
|
} else if (auto_sym == v || Qfalse == v) {
|
578
582
|
copts->bigdec_load = AutoDec;
|
579
583
|
} else {
|
@@ -1654,6 +1658,7 @@ Init_oj() {
|
|
1654
1658
|
empty_string_sym = ID2SYM(rb_intern("empty_string")); rb_gc_register_address(&empty_string_sym);
|
1655
1659
|
escape_mode_sym = ID2SYM(rb_intern("escape_mode")); rb_gc_register_address(&escape_mode_sym);
|
1656
1660
|
integer_range_sym = ID2SYM(rb_intern("integer_range")); rb_gc_register_address(&integer_range_sym);
|
1661
|
+
fast_sym = ID2SYM(rb_intern("fast")); rb_gc_register_address(&fast_sym);
|
1657
1662
|
float_prec_sym = ID2SYM(rb_intern("float_precision")); rb_gc_register_address(&float_prec_sym);
|
1658
1663
|
float_sym = ID2SYM(rb_intern("float")); rb_gc_register_address(&float_sym);
|
1659
1664
|
huge_sym = ID2SYM(rb_intern("huge")); rb_gc_register_address(&huge_sym);
|
data/ext/oj/oj.h
CHANGED
data/ext/oj/parse.c
CHANGED
@@ -393,8 +393,9 @@ read_num(ParseInfo pi) {
|
|
393
393
|
ni.infinity = 0;
|
394
394
|
ni.nan = 0;
|
395
395
|
ni.neg = 0;
|
396
|
-
ni.
|
397
|
-
ni.no_big = (FloatDec == pi->options.bigdec_load);
|
396
|
+
ni.has_exp = 0;
|
397
|
+
ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load);
|
398
|
+
ni.bigdec_load = pi->options.bigdec_load;
|
398
399
|
|
399
400
|
if ('-' == *pi->cur) {
|
400
401
|
pi->cur++;
|
@@ -488,7 +489,7 @@ read_num(ParseInfo pi) {
|
|
488
489
|
if ('e' == *pi->cur || 'E' == *pi->cur) {
|
489
490
|
int eneg = 0;
|
490
491
|
|
491
|
-
ni.
|
492
|
+
ni.has_exp = 1;
|
492
493
|
pi->cur++;
|
493
494
|
if ('-' == *pi->cur) {
|
494
495
|
pi->cur++;
|
@@ -759,6 +760,59 @@ parse_big_decimal(VALUE str) {
|
|
759
760
|
return rb_funcall(rb_cObject, oj_bigdecimal_id, 1, str);
|
760
761
|
}
|
761
762
|
|
763
|
+
static long double exp_plus[] = {
|
764
|
+
1.0,
|
765
|
+
1.0e1,
|
766
|
+
1.0e2,
|
767
|
+
1.0e3,
|
768
|
+
1.0e4,
|
769
|
+
1.0e5,
|
770
|
+
1.0e6,
|
771
|
+
1.0e7,
|
772
|
+
1.0e8,
|
773
|
+
1.0e9,
|
774
|
+
1.0e10,
|
775
|
+
1.0e11,
|
776
|
+
1.0e12,
|
777
|
+
1.0e13,
|
778
|
+
1.0e14,
|
779
|
+
1.0e15,
|
780
|
+
1.0e16,
|
781
|
+
1.0e17,
|
782
|
+
1.0e18,
|
783
|
+
1.0e19,
|
784
|
+
1.0e20,
|
785
|
+
1.0e21,
|
786
|
+
1.0e22,
|
787
|
+
1.0e23,
|
788
|
+
1.0e24,
|
789
|
+
1.0e25,
|
790
|
+
1.0e26,
|
791
|
+
1.0e27,
|
792
|
+
1.0e28,
|
793
|
+
1.0e29,
|
794
|
+
1.0e30,
|
795
|
+
1.0e31,
|
796
|
+
1.0e32,
|
797
|
+
1.0e33,
|
798
|
+
1.0e34,
|
799
|
+
1.0e35,
|
800
|
+
1.0e36,
|
801
|
+
1.0e37,
|
802
|
+
1.0e38,
|
803
|
+
1.0e39,
|
804
|
+
1.0e40,
|
805
|
+
1.0e41,
|
806
|
+
1.0e42,
|
807
|
+
1.0e43,
|
808
|
+
1.0e44,
|
809
|
+
1.0e45,
|
810
|
+
1.0e46,
|
811
|
+
1.0e47,
|
812
|
+
1.0e48,
|
813
|
+
1.0e49,
|
814
|
+
};
|
815
|
+
|
762
816
|
VALUE
|
763
817
|
oj_num_as_value(NumInfo ni) {
|
764
818
|
volatile VALUE rnum = Qnil;
|
@@ -771,7 +825,7 @@ oj_num_as_value(NumInfo ni) {
|
|
771
825
|
}
|
772
826
|
} else if (ni->nan) {
|
773
827
|
rnum = rb_float_new(0.0/0.0);
|
774
|
-
} else if (1 == ni->div && 0 == ni->exp) { // fixnum
|
828
|
+
} else if (1 == ni->div && 0 == ni->exp && !ni->has_exp) { // fixnum
|
775
829
|
if (ni->big) {
|
776
830
|
if (256 > ni->len) {
|
777
831
|
char buf[256];
|
@@ -802,53 +856,35 @@ oj_num_as_value(NumInfo ni) {
|
|
802
856
|
if (ni->no_big) {
|
803
857
|
rnum = rb_funcall(rnum, rb_intern("to_f"), 0);
|
804
858
|
}
|
805
|
-
} else {
|
806
|
-
// All these machinations are to get rounding to work better.
|
859
|
+
} else if (FastDec == ni->bigdec_load) {
|
807
860
|
long double ld = (long double)ni->i * (long double)ni->div + (long double)ni->num;
|
808
861
|
int x = (int)((int64_t)ni->exp - ni->di);
|
809
862
|
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
if ((long double)INT64_MAX > ld && (int64_t)ld != (ni->i * ni->div + ni->num)) {
|
814
|
-
volatile VALUE bd = rb_str_new(ni->str, ni->len);
|
815
|
-
|
816
|
-
rnum = rb_rescue2(parse_big_decimal, bd, rescue_big_decimal, bd, rb_eException, 0);
|
817
|
-
if (ni->no_big) {
|
818
|
-
rnum = rb_funcall(rnum, rb_intern("to_f"), 0);
|
819
|
-
}
|
820
|
-
} else {
|
821
|
-
double d;
|
822
|
-
double d2;
|
823
|
-
|
824
|
-
ld = roundl(ld);
|
825
|
-
// You would expect that staying with a long double would be
|
826
|
-
// more accurate but it fails to match what Ruby generates so
|
827
|
-
// drop down to a double.
|
828
|
-
if (0 < x) {
|
829
|
-
d = (double)(ld * powl(10.0, x));
|
830
|
-
d2 = (double)ld * pow(10.0, x);
|
831
|
-
} else if (0 > x) {
|
832
|
-
d = (double)(ld / powl(10.0, -x));
|
833
|
-
d2 = (double)ld / pow(10.0, -x);
|
863
|
+
if (0 < x) {
|
864
|
+
if (x < (int)(sizeof(exp_plus) / sizeof(*exp_plus))) {
|
865
|
+
ld *= exp_plus[x];
|
834
866
|
} else {
|
835
|
-
|
836
|
-
d2 = d;
|
867
|
+
ld *= powl(10.0, x);
|
837
868
|
}
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
rnum = rb_rescue2(parse_big_decimal, bd, rescue_big_decimal, bd, rb_eException, 0);
|
842
|
-
if (ni->no_big) {
|
843
|
-
rnum = rb_funcall(rnum, rb_intern("to_f"), 0);
|
844
|
-
}
|
869
|
+
} else if (x < 0) {
|
870
|
+
if (-x < (int)(sizeof(exp_plus) / sizeof(*exp_plus))) {
|
871
|
+
ld /= exp_plus[-x];
|
845
872
|
} else {
|
846
|
-
|
847
|
-
d = -d;
|
848
|
-
}
|
849
|
-
rnum = rb_float_new(d);
|
873
|
+
ld /= powl(10.0, -x);
|
850
874
|
}
|
851
875
|
}
|
876
|
+
if (ni->neg) {
|
877
|
+
ld = -ld;
|
878
|
+
}
|
879
|
+
rnum = rb_float_new((double)ld);
|
880
|
+
} else {
|
881
|
+
char *end;
|
882
|
+
double d = strtod(ni->str, &end);
|
883
|
+
|
884
|
+
if ((long)ni->len != (long)(end - ni->str)) {
|
885
|
+
rb_raise(oj_parse_error_class, "Invalid float");
|
886
|
+
}
|
887
|
+
rnum = rb_float_new(d);
|
852
888
|
}
|
853
889
|
}
|
854
890
|
return rnum;
|
data/ext/oj/parse.h
CHANGED
data/ext/oj/sparse.c
CHANGED
@@ -407,8 +407,9 @@ read_num(ParseInfo pi) {
|
|
407
407
|
ni.infinity = 0;
|
408
408
|
ni.nan = 0;
|
409
409
|
ni.neg = 0;
|
410
|
-
ni.
|
411
|
-
ni.no_big = (FloatDec == pi->options.bigdec_load);
|
410
|
+
ni.has_exp = 0;
|
411
|
+
ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load);
|
412
|
+
ni.bigdec_load = pi->options.bigdec_load;
|
412
413
|
|
413
414
|
c = reader_get(&pi->rd);
|
414
415
|
if ('-' == c) {
|
@@ -489,7 +490,7 @@ read_num(ParseInfo pi) {
|
|
489
490
|
if ('e' == c || 'E' == c) {
|
490
491
|
int eneg = 0;
|
491
492
|
|
492
|
-
ni.
|
493
|
+
ni.has_exp = 1;
|
493
494
|
c = reader_get(&pi->rd);
|
494
495
|
if ('-' == c) {
|
495
496
|
c = reader_get(&pi->rd);
|
@@ -548,7 +549,8 @@ read_nan(ParseInfo pi) {
|
|
548
549
|
ni.infinity = 0;
|
549
550
|
ni.nan = 1;
|
550
551
|
ni.neg = 0;
|
551
|
-
ni.no_big = (FloatDec == pi->options.bigdec_load);
|
552
|
+
ni.no_big = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load);
|
553
|
+
ni.bigdec_load = pi->options.bigdec_load;
|
552
554
|
|
553
555
|
if ('a' != reader_get(&pi->rd) ||
|
554
556
|
('N' != (c = reader_get(&pi->rd)) && 'n' != c)) {
|
@@ -746,6 +748,7 @@ oj_sparse2(ParseInfo pi) {
|
|
746
748
|
ni.nan = 1;
|
747
749
|
ni.neg = 0;
|
748
750
|
ni.no_big = (FloatDec == pi->options.bigdec_load);
|
751
|
+
ni.bigdec_load = pi->options.bigdec_load;
|
749
752
|
add_num_value(pi, &ni);
|
750
753
|
} else {
|
751
754
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid token");
|
data/lib/oj/version.rb
CHANGED
data/test/sample_json.rb
CHANGED
data/test/test_custom.rb
CHANGED
@@ -123,6 +123,12 @@ class CustomJuice < Minitest::Test
|
|
123
123
|
assert_equal(Float, f.class)
|
124
124
|
end
|
125
125
|
|
126
|
+
def test_float_parse_fast
|
127
|
+
f = Oj.load("12.123456789012345678", mode: :custom, bigdecimal_load: :fast);
|
128
|
+
assert_equal(Float, f.class)
|
129
|
+
assert_equal(12.123456789012346, f)
|
130
|
+
end
|
131
|
+
|
126
132
|
def test_nan_dump
|
127
133
|
assert_equal('null', Oj.dump(0/0.0, :nan => :null))
|
128
134
|
assert_equal('3.3e14159265358979323846', Oj.dump(0/0.0, :nan => :huge))
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oj
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.10.
|
4
|
+
version: 3.10.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Ohler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-07-
|
11
|
+
date: 2020-07-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|