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 +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
|