oj 3.6.13 → 3.7.0
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/dump.c +31 -1
- data/ext/oj/dump_compat.c +15 -1
- data/ext/oj/mimic_json.c +2 -0
- data/ext/oj/oj.c +33 -0
- data/ext/oj/oj.h +2 -0
- data/lib/oj/version.rb +1 -1
- data/pages/Modes.md +1 -0
- data/pages/Options.md +5 -2
- data/test/test_integer_range.rb +73 -0
- data/test/test_various.rb +1 -0
- data/test/tests.rb +1 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6defd3e51327c7d866dabb9caf8580c67996b5bd251d9613ec883f186cea522
|
4
|
+
data.tar.gz: 22a9278def6a95047eb280edd38a0be67872e263a9da259f4bdd5b3ab43f400a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e0da261cf964ecd359e1ea539715c39ebc740fe8fb716b274c65e4b47a52a55033b6011f90b8a09948582df85d0fa0d942ae422b0cafd61cce34d2c0b6046519
|
7
|
+
data.tar.gz: 88c99360a4de1367247d76a8aff7e34f75744f58c2b64465fc3fcb90858c33902ae0c2d3aeaf1a04fe03ce29890cf44f314c6666d1cd9487c4b3355c01e71f58
|
data/ext/oj/dump.c
CHANGED
@@ -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
|
|
data/ext/oj/dump_compat.c
CHANGED
@@ -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
|
-
|
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
|
|
data/ext/oj/mimic_json.c
CHANGED
data/ext/oj/oj.c
CHANGED
@@ -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);
|
data/ext/oj/oj.h
CHANGED
@@ -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
|
data/lib/oj/version.rb
CHANGED
data/pages/Modes.md
CHANGED
@@ -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 | - | - | - | - | - | - | |
|
data/pages/Options.md
CHANGED
@@ -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
|
+
|
data/test/test_various.rb
CHANGED
data/test/tests.rb
CHANGED
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.
|
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-
|
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.
|
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
|