oj 3.10.7 → 3.10.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 21e870cbb9a2f1c2b99efd6522ce9c284828865b922e299232e60abd4e916f7e
4
- data.tar.gz: d1d93c3d58b7ed858e1a4ea89698861485bbeeb19b01bc66e3e8890ab7d93583
3
+ metadata.gz: cb725babd05d3dadf33c86b0737e278f0f2eed8bb1792300dca74f5138a472a5
4
+ data.tar.gz: c60cd42eccaeea5937726f90225a611b19901ff4d133968e304de6f6d9077a31
5
5
  SHA512:
6
- metadata.gz: 7c5d6b2d7a7830b80ecc23436e50b0f42f53e82febe31ceb0168f440e5368ed323c19433894724beea83e7587013170b6a38be92b65b073d9881f8176a8d283b
7
- data.tar.gz: 1558090a4a1b066418b9f36064c845ab99e423246f26af8aff682e8f09b8cfce29531f6e677c6e4d8b16056406251b2fe54b463e4ddef121adced8c9d3c167b2
6
+ metadata.gz: 56791447ce08bbe3aca701ff0b50e17f70dbd2bae22bcc07fcdbe5216b9da7e976f6ee748bee83d12a2915148ddc83e99ac52203e9baa7a3e268023a808515e0
7
+ data.tar.gz: 9906af11fb4fd41f2a4d311d0c7e0a4d72c3947e53201fa745717f356d67cbc757ebcbbb341eff03f7d4c1cb1bb76da59d05b14e31119f098e1b398d8f164304
@@ -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->hasExp) {
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];
@@ -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->hasExp) {
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];
@@ -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);
@@ -77,7 +77,8 @@ typedef enum {
77
77
  typedef enum {
78
78
  BigDec = 'b',
79
79
  FloatDec = 'f',
80
- AutoDec = 'a'
80
+ AutoDec = 'a',
81
+ FastDec = 'F'
81
82
  } BigLoad;
82
83
 
83
84
  typedef enum {
@@ -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.hasExp = 0;
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.hasExp = 1;
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
- // Rounding sometimes cuts off the last digit even if there are only
811
- // 15 digits. This attempts to fix those few cases where this
812
- // occurs.
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
- d = (double)ld;
836
- d2 = d;
867
+ ld *= powl(10.0, x);
837
868
  }
838
- if (d != d2) {
839
- volatile VALUE bd = rb_str_new(ni->str, ni->len);
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
- if (ni->neg) {
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;
@@ -31,8 +31,9 @@ typedef struct _numInfo {
31
31
  int infinity;
32
32
  int nan;
33
33
  int neg;
34
- int hasExp;
34
+ int has_exp;
35
35
  int no_big;
36
+ int bigdec_load;
36
37
  } *NumInfo;
37
38
 
38
39
  typedef struct _parseInfo {
@@ -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.hasExp = 0;
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.hasExp = 1;
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");
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Oj
3
3
  # Current version of the module.
4
- VERSION = '3.10.7'
4
+ VERSION = '3.10.8'
5
5
  end
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env ruby -wW2
1
+ #!/usr/bin/env ruby
2
2
 
3
3
  if $0 == __FILE__
4
4
  $: << '.'
@@ -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.7
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-13 00:00:00.000000000 Z
11
+ date: 2020-07-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler