oj 3.6.13 → 3.7.0

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: 1f5fd9fac91126f270714362850b976b7f4cf1102462aab26c2f4f65f457a905
4
- data.tar.gz: e2e200e2ec9e76f073206c084c1a7e45592710e0fbb43a5ba4f9593af74ff583
3
+ metadata.gz: e6defd3e51327c7d866dabb9caf8580c67996b5bd251d9613ec883f186cea522
4
+ data.tar.gz: 22a9278def6a95047eb280edd38a0be67872e263a9da259f4bdd5b3ab43f400a
5
5
  SHA512:
6
- metadata.gz: 3b5f0e4bede1f60d010a51e32141c6b864f92abe17fbe12d310e805ce16b8ef67483cf51dee0914f6a29f54556817d91ed2ffa5dccb64cbd8468c68de0d50f83
7
- data.tar.gz: 390a4c2953392485757949aee885fb82b3c54b456f659ba672ae7b8da0b45bee484eb3b7c3ee0ef31a01dd33fe0bac8e877d01c91649c197970defe3e7727399
6
+ metadata.gz: e0da261cf964ecd359e1ea539715c39ebc740fe8fb716b274c65e4b47a52a55033b6011f90b8a09948582df85d0fa0d942ae422b0cafd61cce34d2c0b6046519
7
+ data.tar.gz: 88c99360a4de1367247d76a8aff7e34f75744f58c2b64465fc3fcb90858c33902ae0c2d3aeaf1a04fe03ce29890cf44f314c6666d1cd9487c4b3355c01e71f58
@@ -993,12 +993,24 @@ oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
993
993
  char *b = buf + sizeof(buf) - 1;
994
994
  long long num = rb_num2ll(obj);
995
995
  int neg = 0;
996
+ bool dump_as_string = false;
997
+
998
+ if (out->opts->integer_range_max != 0 && out->opts->integer_range_min != 0 &&
999
+ (out->opts->integer_range_max < num || out->opts->integer_range_min > num)) {
1000
+ dump_as_string = true;
1001
+ }
996
1002
 
997
1003
  if (0 > num) {
998
1004
  neg = 1;
999
1005
  num = -num;
1000
1006
  }
1007
+
1001
1008
  *b-- = '\0';
1009
+
1010
+ if (dump_as_string) {
1011
+ *b-- = '"';
1012
+ }
1013
+
1002
1014
  if (0 < num) {
1003
1015
  for (; 0 < num; num /= 10, b--) {
1004
1016
  *b = (num % 10) + '0';
@@ -1011,6 +1023,11 @@ oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
1011
1023
  } else {
1012
1024
  *b = '0';
1013
1025
  }
1026
+
1027
+ if (dump_as_string) {
1028
+ *--b = '"';
1029
+ }
1030
+
1014
1031
  assure_size(out, (sizeof(buf) - (b - buf)));
1015
1032
  for (; '\0' != *b; b++) {
1016
1033
  *out->cur++ = *b;
@@ -1022,10 +1039,23 @@ void
1022
1039
  oj_dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
1023
1040
  volatile VALUE rs = rb_big2str(obj, 10);
1024
1041
  int cnt = (int)RSTRING_LEN(rs);
1042
+ bool dump_as_string = false;
1043
+
1044
+ if (out->opts->integer_range_max != 0 || out->opts->integer_range_min != 0) { // Bignum cannot be inside of Fixnum range
1045
+ dump_as_string = true;
1046
+ assure_size(out, cnt + 2);
1047
+ *out->cur++ = '"';
1048
+ } else {
1049
+ assure_size(out, cnt);
1050
+ }
1025
1051
 
1026
- assure_size(out, cnt);
1027
1052
  memcpy(out->cur, rb_string_value_ptr((VALUE*)&rs), cnt);
1028
1053
  out->cur += cnt;
1054
+
1055
+ if(dump_as_string) {
1056
+ *out->cur++ = '"';
1057
+ }
1058
+
1029
1059
  *out->cur = '\0';
1030
1060
  }
1031
1061
 
@@ -870,6 +870,7 @@ dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
870
870
  // this must use to_s to pass the json gem unit tests.
871
871
  volatile VALUE rs;
872
872
  int cnt;
873
+ bool dump_as_string = false;
873
874
 
874
875
  if (use_bignum_alt) {
875
876
  rs = rb_big2str(obj, 10);
@@ -878,9 +879,22 @@ dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
878
879
  }
879
880
  rb_check_type(rs, T_STRING);
880
881
  cnt = (int)RSTRING_LEN(rs);
881
- assure_size(out, cnt);
882
+
883
+ if (out->opts->integer_range_min != 0 || out->opts->integer_range_max != 0) {
884
+ dump_as_string = true; // Bignum cannot be inside of Fixnum range
885
+ assure_size(out, cnt + 2);
886
+ *out->cur++ = '"';
887
+ } else {
888
+ assure_size(out, cnt);
889
+ }
890
+
882
891
  memcpy(out->cur, rb_string_value_ptr((VALUE*)&rs), cnt);
883
892
  out->cur += cnt;
893
+
894
+ if(dump_as_string) {
895
+ *out->cur++ = '"';
896
+ }
897
+
884
898
  *out->cur = '\0';
885
899
  }
886
900
 
@@ -686,6 +686,8 @@ static struct _Options mimic_object_to_json_options = {
686
686
  No, // create_ok
687
687
  No, // allow_nan
688
688
  No, // trace
689
+ 0, // integer_range_min
690
+ 0, // integer_range_max
689
691
  oj_json_class,// create_id
690
692
  10, // create_id_len
691
693
  3, // sec_prec
@@ -116,6 +116,7 @@ static VALUE create_id_sym;
116
116
  static VALUE custom_sym;
117
117
  static VALUE empty_string_sym;
118
118
  static VALUE escape_mode_sym;
119
+ static VALUE integer_range_sym;
119
120
  static VALUE float_prec_sym;
120
121
  static VALUE float_sym;
121
122
  static VALUE huge_sym;
@@ -183,6 +184,8 @@ struct _Options oj_default_options = {
183
184
  No, // create_ok
184
185
  Yes, // allow_nan
185
186
  No, // trace
187
+ 0, // integer_range_min
188
+ 0, // integer_range_max
186
189
  oj_json_class, // create_id
187
190
  10, // create_id_len
188
191
  9, // sec_prec
@@ -250,6 +253,7 @@ struct _Options oj_default_options = {
250
253
  * - *:array_class* [_Class_|_nil_] Class to use instead of Array on load
251
254
  * - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted
252
255
  * - *:ignore* [_nil_|Array] either nil or an Array of classes to ignore when dumping
256
+ * - *:integer_range* [_Range_] Dump integers outside range as strings.
253
257
  * - *:trace* [_true,_|_false_] Trace all load and dump calls, default is false (trace is off)
254
258
  *
255
259
  * Return [_Hash_] all current option settings.
@@ -291,6 +295,18 @@ get_def_opts(VALUE self) {
291
295
  case WabMode: rb_hash_aset(opts, mode_sym, wab_sym); break;
292
296
  default: rb_hash_aset(opts, mode_sym, object_sym); break;
293
297
  }
298
+
299
+ if (oj_default_options.integer_range_max != 0 || oj_default_options.integer_range_min != 0) {
300
+ VALUE range = rb_obj_alloc(rb_cRange);
301
+ VALUE min = LONG2FIX(oj_default_options.integer_range_min);
302
+ VALUE max = LONG2FIX(oj_default_options.integer_range_max);
303
+ rb_ivar_set(range, oj_begin_id, min);
304
+ rb_ivar_set(range, oj_end_id, max);
305
+ rb_hash_aset(opts, integer_range_sym, range);
306
+ }
307
+ else {
308
+ rb_hash_aset(opts, integer_range_sym, Qnil);
309
+ }
294
310
  switch (oj_default_options.escape_mode) {
295
311
  case NLEsc: rb_hash_aset(opts, escape_mode_sym, newline_sym); break;
296
312
  case JSONEsc: rb_hash_aset(opts, escape_mode_sym, json_sym); break;
@@ -380,6 +396,7 @@ get_def_opts(VALUE self) {
380
396
  * - *:array_class* [_Class_|_nil_] Class to use instead of Array on load.
381
397
  * - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted.
382
398
  * - *:ignore* [_nil_|Array] either nil or an Array of classes to ignore when dumping
399
+ * - *:integer_range* [_Range_] Dump integers outside range as strings.
383
400
  * - *:trace* [_Boolean_] turn trace on or off.
384
401
  */
385
402
  static VALUE
@@ -715,6 +732,21 @@ oj_parse_options(VALUE ropts, Options copts) {
715
732
  }
716
733
  }
717
734
  }
735
+ if (Qnil != (v = rb_hash_lookup(ropts, integer_range_sym))) {
736
+ if (TYPE(v) == T_STRUCT && rb_obj_class(v) == rb_cRange) {
737
+ VALUE min = rb_funcall(v, oj_begin_id, 0);
738
+ VALUE max = rb_funcall(v, oj_end_id, 0);
739
+
740
+ if (TYPE(min) != T_FIXNUM || TYPE(max) != T_FIXNUM) {
741
+ rb_raise(rb_eArgError, ":integer_range range bounds is not Fixnum.");
742
+ }
743
+
744
+ copts->integer_range_min = FIX2LONG(min);
745
+ copts->integer_range_max = FIX2LONG(max);
746
+ } else if (Qfalse != v) {
747
+ rb_raise(rb_eArgError, ":integer_range must be a range of Fixnum.");
748
+ }
749
+ }
718
750
  }
719
751
 
720
752
  static int
@@ -1645,6 +1677,7 @@ Init_oj() {
1645
1677
  custom_sym = ID2SYM(rb_intern("custom")); rb_gc_register_address(&custom_sym);
1646
1678
  empty_string_sym = ID2SYM(rb_intern("empty_string")); rb_gc_register_address(&empty_string_sym);
1647
1679
  escape_mode_sym = ID2SYM(rb_intern("escape_mode")); rb_gc_register_address(&escape_mode_sym);
1680
+ integer_range_sym = ID2SYM(rb_intern("integer_range")); rb_gc_register_address(&integer_range_sym);
1648
1681
  float_prec_sym = ID2SYM(rb_intern("float_precision")); rb_gc_register_address(&float_prec_sym);
1649
1682
  float_sym = ID2SYM(rb_intern("float")); rb_gc_register_address(&float_sym);
1650
1683
  huge_sym = ID2SYM(rb_intern("huge")); rb_gc_register_address(&huge_sym);
@@ -153,6 +153,8 @@ typedef struct _Options {
153
153
  char create_ok; // YesNo allow create_id
154
154
  char allow_nan; // YEsyNo for parsing only
155
155
  char trace; // YesNo
156
+ int64_t integer_range_min; // dump numbers outside range as string
157
+ int64_t integer_range_max;
156
158
  const char *create_id; // 0 or string
157
159
  size_t create_id_len; // length of create_id
158
160
  int sec_prec; // second precision when dumping time
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Oj
3
3
  # Current version of the module.
4
- VERSION = '3.6.13'
4
+ VERSION = '3.7.0'
5
5
  end
@@ -107,6 +107,7 @@ information.
107
107
  | :ignore | Array | | | | | x | x | |
108
108
  | :indent | Integer | x | x | 3 | 4 | x | x | x |
109
109
  | :indent_str | String | | | x | x | | x | |
110
+ | :integer_range | Range | x | x | x | x | x | x | x |
110
111
  | :match_string | Hash | | | x | x | | x | |
111
112
  | :max_nesting | Fixnum | 4 | 4 | x | | 5 | 4 | |
112
113
  | :mode | Symbol | - | - | - | - | - | - | |
@@ -147,6 +147,11 @@ Indentation for each element when dumping. The default is an empty
147
147
  string. Primarily intended for json gem compatibility. Using just indent as an
148
148
  integer gives better performance.
149
149
 
150
+ ### :integer_range [Range]
151
+
152
+ Dump integers outside range as strings.
153
+ Note: range bounds must be Fixnum.
154
+
150
155
  ### :match_string
151
156
 
152
157
  Provides a means to detect strings that should be used to create non-String
@@ -259,5 +264,3 @@ the :compat and :rails mode.
259
264
  Call `to_json()` methods on dump, default is false. The option is ignored in
260
265
  the :compat and :rails mode.
261
266
 
262
-
263
-
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ $: << File.dirname(__FILE__)
5
+ $oj_dir = File.dirname(File.expand_path(File.dirname(__FILE__)))
6
+ %w(lib ext).each do |dir|
7
+ $: << File.join($oj_dir, dir)
8
+ end
9
+
10
+ require 'minitest'
11
+ require 'minitest/autorun'
12
+ require 'oj'
13
+
14
+ class IntegerRangeTest < Minitest::Test
15
+ def setup
16
+ @default_options = Oj.default_options
17
+ # in null mode other options other than the number formats are not used.
18
+ Oj.default_options = { :mode => :null }
19
+ end
20
+
21
+ def teardown
22
+ Oj.default_options = @default_options
23
+ end
24
+
25
+ def test_range
26
+ test = {s: 0, s2: -1, s3: 1, u: -2, u2: 2, u3: 9007199254740993}
27
+ exp = '{"s":0,"s2":-1,"s3":1,"u":"-2","u2":"2","u3":"9007199254740993"}'
28
+ assert_equal(exp, Oj.dump(test, integer_range: (-1..1)))
29
+ end
30
+
31
+ def test_bignum
32
+ test = {u: -10000000000000000000, u2: 10000000000000000000}
33
+ exp = '{"u":"-10000000000000000000","u2":"10000000000000000000"}'
34
+ assert_equal(exp, Oj.dump(test, integer_range: (-1..1)))
35
+ end
36
+
37
+ def test_valid_modes
38
+ test = {safe: 0, unsafe: 9007199254740993}
39
+ exp = '{"safe":0,"unsafe":"9007199254740993"}'
40
+
41
+ [:strict, :null, :compat, :rails, :custom].each do |mode|
42
+ assert_equal(exp, Oj.dump(test, mode: mode, integer_range: (-1..1)), "Invalid mode #{mode}")
43
+ end
44
+
45
+ exp = '{":safe":0,":unsafe":"9007199254740993"}'
46
+ [:object].each do |mode|
47
+ assert_equal(exp, Oj.dump(test, mode: mode, integer_range: (-1..1)), "Invalid mode #{mode}")
48
+ end
49
+ end
50
+
51
+ def test_modes_without_opt
52
+ test = {safe:0, unsafe: 10000000000000000000}
53
+ exp = '{"safe":0,"unsafe":10000000000000000000}'
54
+
55
+ [:strict, :null, :compat, :rails, :custom].each do |mode|
56
+ assert_equal(exp, Oj.dump(test, mode: mode), "Invalid mode #{mode}")
57
+ end
58
+
59
+ exp = '{":safe":0,":unsafe":10000000000000000000}'
60
+ [:object].each do |mode|
61
+ assert_equal(exp, Oj.dump(test, mode: mode), "Invalid mode #{mode}")
62
+ end
63
+ end
64
+
65
+ def test_accept_nil_and_false
66
+ test = {safe:0, unsafe: 10000000000000000000}
67
+ exp = '{"safe":0,"unsafe":10000000000000000000}'
68
+
69
+ assert_equal(exp, Oj.dump(test, integer_range: nil))
70
+ assert_equal(exp, Oj.dump(test, integer_range: false))
71
+ end
72
+ end
73
+
@@ -154,6 +154,7 @@ class Juice < Minitest::Test
154
154
  :hash_class=>Hash,
155
155
  :omit_nil=>false,
156
156
  :allow_nan=>true,
157
+ :integer_range=>nil,
157
158
  :array_class=>Array,
158
159
  :ignore=>nil,
159
160
  :trace=>true,
@@ -21,3 +21,4 @@ require 'test_strict'
21
21
  require 'test_various'
22
22
  require 'test_wab'
23
23
  require 'test_writer'
24
+ require 'test_integer_range'
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.6.13
4
+ version: 3.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Ohler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-10-25 00:00:00.000000000 Z
11
+ date: 2018-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -230,6 +230,7 @@ files:
230
230
  - test/test_file.rb
231
231
  - test/test_gc.rb
232
232
  - test/test_hash.rb
233
+ - test/test_integer_range.rb
233
234
  - test/test_null.rb
234
235
  - test/test_object.rb
235
236
  - test/test_saj.rb
@@ -271,7 +272,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
271
272
  version: '0'
272
273
  requirements: []
273
274
  rubyforge_project:
274
- rubygems_version: 2.7.7
275
+ rubygems_version: 2.7.6
275
276
  signing_key:
276
277
  specification_version: 4
277
278
  summary: A fast JSON parser and serializer.
@@ -284,6 +285,7 @@ test_files:
284
285
  - test/test_compat.rb
285
286
  - test/test_custom.rb
286
287
  - test/perf_scp.rb
288
+ - test/test_integer_range.rb
287
289
  - test/test_gc.rb
288
290
  - test/sample.rb
289
291
  - test/json_gem/json_string_matching_test.rb