oj 3.8.0 → 3.10.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/README.md +2 -2
- data/ext/oj/custom.c +61 -36
- data/ext/oj/dump.c +9 -12
- data/ext/oj/dump_compat.c +6 -9
- data/ext/oj/dump_object.c +14 -9
- data/ext/oj/extconf.rb +1 -0
- data/ext/oj/mimic_json.c +4 -2
- data/ext/oj/object.c +8 -5
- data/ext/oj/oj.c +47 -30
- data/ext/oj/oj.h +6 -4
- data/ext/oj/parse.c +15 -2
- data/ext/oj/parse.h +1 -0
- data/ext/oj/rails.c +9 -2
- data/ext/oj/resolve.c +3 -3
- data/ext/oj/sparse.c +4 -0
- data/ext/oj/util.c +5 -5
- data/ext/oj/val_stack.c +9 -9
- data/ext/oj/val_stack.h +9 -9
- data/lib/oj/json.rb +1 -1
- data/lib/oj/version.rb +1 -1
- data/pages/Options.md +4 -0
- data/pages/Rails.md +21 -21
- data/test/activesupport5/abstract_unit.rb +45 -0
- data/test/activesupport5/decoding_test.rb +68 -60
- data/test/activesupport5/encoding_test.rb +111 -96
- data/test/activesupport5/encoding_test_cases.rb +33 -25
- data/test/activesupport5/test_helper.rb +43 -21
- data/test/activesupport5/time_zone_test_helpers.rb +18 -3
- data/test/activesupport6/abstract_unit.rb +44 -0
- data/test/activesupport6/decoding_test.rb +133 -0
- data/test/activesupport6/encoding_test.rb +507 -0
- data/test/activesupport6/encoding_test_cases.rb +98 -0
- data/test/activesupport6/test_common.rb +17 -0
- data/test/activesupport6/test_helper.rb +163 -0
- data/test/activesupport6/time_zone_test_helpers.rb +39 -0
- data/test/bar.rb +8 -11
- data/test/baz.rb +16 -0
- data/test/test_compat.rb +0 -7
- data/test/test_custom.rb +6 -2
- data/test/test_integer_range.rb +1 -2
- data/test/test_object.rb +4 -3
- data/test/test_strict.rb +24 -1
- data/test/test_various.rb +41 -62
- metadata +20 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 62a52be7754c5ef34c3006fb28fa918cb18f23c26ffa94e8daedf05396bbe0fb
|
4
|
+
data.tar.gz: 9cf9cfab00cf1e28f8b42c6d3e88ee6a2a785093cc024c558eeceb25eaf39cd1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 931cf30643fc1be050ec4f3c0c69f85b643b073e7bd5d16c5c8a5431c8d3701ae73fc5b68311246f2db993fa1c3e40b6169978f10b377a947cc937a7d26afd6e
|
7
|
+
data.tar.gz: 779d173d00513d830f825cc9e0f51a5a066beece8fe9289d1face779c34210d6f7506e8e8af380fc5f2d3c2dd727b46f14cc985d4a2867e3a71fb1de4217361a
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# [](http://www.ohler.com/oj) gem
|
2
2
|
|
3
|
-
[](http://travis-ci.org/ohler55/oj?branch=master) [](https://ci.appveyor.com/project/ohler55/oj)   [](https://dependabot.com/compatibility-score.html?dependency-name=oj&package-manager=bundler&version-scheme=semver) [](https://tidelift.com/subscription/pkg/rubygems-oj?utm_source=rubygems-oj&utm_medium=referral&utm_campaign=readme)
|
3
|
+
[](http://travis-ci.org/ohler55/oj?branch=master) [](https://ci.appveyor.com/project/ohler55/oj)   [](https://dependabot.com/compatibility-score.html?dependency-name=oj&package-manager=bundler&version-scheme=semver) [](https://tidelift.com/subscription/pkg/rubygems-oj?utm_source=rubygems-oj&utm_medium=referral&utm_campaign=readme)
|
4
4
|
|
5
5
|
A *fast* JSON parser and Object marshaller as a Ruby gem.
|
6
6
|
|
@@ -42,7 +42,7 @@ gem 'oj'
|
|
42
42
|
|
43
43
|
## Support
|
44
44
|
|
45
|
-
[Get supported Oj with a Tidelift Subscription.](https://tidelift.com/subscription/pkg/rubygems-oj?utm_source=rubygems-oj&utm_medium=referral&utm_campaign=readme)
|
45
|
+
[Get supported Oj with a Tidelift Subscription.](https://tidelift.com/subscription/pkg/rubygems-oj?utm_source=rubygems-oj&utm_medium=referral&utm_campaign=readme) Security updates are [supported](https://tidelift.com/security).
|
46
46
|
|
47
47
|
## Further Reading
|
48
48
|
|
data/ext/oj/custom.c
CHANGED
@@ -32,6 +32,13 @@ dump_obj_str(VALUE obj, int depth, Out out) {
|
|
32
32
|
oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
|
33
33
|
}
|
34
34
|
|
35
|
+
static void
|
36
|
+
dump_obj_as_str(VALUE obj, int depth, Out out) {
|
37
|
+
volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
|
38
|
+
const char *str = rb_string_value_ptr((VALUE*)&rstr);
|
39
|
+
|
40
|
+
oj_dump_cstr(str, RSTRING_LEN(rstr), 0, 0, out);
|
41
|
+
}
|
35
42
|
|
36
43
|
static void
|
37
44
|
bigdecimal_dump(VALUE obj, int depth, Out out) {
|
@@ -57,19 +64,23 @@ static ID imag_id = 0;
|
|
57
64
|
|
58
65
|
static void
|
59
66
|
complex_dump(VALUE obj, int depth, Out out) {
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
67
|
+
if (NULL != out->opts->create_id) {
|
68
|
+
struct _attr attrs[] = {
|
69
|
+
{ "real", 4, Qnil },
|
70
|
+
{ "imag", 4, Qnil },
|
71
|
+
{ NULL, 0, Qnil },
|
72
|
+
};
|
73
|
+
if (0 == real_id) {
|
74
|
+
real_id = rb_intern("real");
|
75
|
+
imag_id = rb_intern("imag");
|
76
|
+
}
|
77
|
+
attrs[0].value = rb_funcall(obj, real_id, 0);
|
78
|
+
attrs[1].value = rb_funcall(obj, imag_id, 0);
|
71
79
|
|
72
|
-
|
80
|
+
oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
|
81
|
+
} else {
|
82
|
+
dump_obj_as_str(obj, depth, out);
|
83
|
+
}
|
73
84
|
}
|
74
85
|
|
75
86
|
static VALUE
|
@@ -193,17 +204,21 @@ openstruct_load(VALUE clas, VALUE args) {
|
|
193
204
|
|
194
205
|
static void
|
195
206
|
range_dump(VALUE obj, int depth, Out out) {
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
207
|
+
if (NULL != out->opts->create_id) {
|
208
|
+
struct _attr attrs[] = {
|
209
|
+
{ "begin", 5, Qnil },
|
210
|
+
{ "end", 3, Qnil },
|
211
|
+
{ "exclude", 7, Qnil },
|
212
|
+
{ NULL, 0, Qnil },
|
213
|
+
};
|
214
|
+
attrs[0].value = rb_funcall(obj, oj_begin_id, 0);
|
215
|
+
attrs[1].value = rb_funcall(obj, oj_end_id, 0);
|
216
|
+
attrs[2].value = rb_funcall(obj, oj_exclude_end_id, 0);
|
205
217
|
|
206
|
-
|
218
|
+
oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
|
219
|
+
} else {
|
220
|
+
dump_obj_as_str(obj, depth, out);
|
221
|
+
}
|
207
222
|
}
|
208
223
|
|
209
224
|
static VALUE
|
@@ -222,19 +237,23 @@ static ID denominator_id = 0;
|
|
222
237
|
|
223
238
|
static void
|
224
239
|
rational_dump(VALUE obj, int depth, Out out) {
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
240
|
+
if (NULL != out->opts->create_id) {
|
241
|
+
struct _attr attrs[] = {
|
242
|
+
{ "numerator", 9, Qnil },
|
243
|
+
{ "denominator", 11, Qnil },
|
244
|
+
{ NULL, 0, Qnil },
|
245
|
+
};
|
246
|
+
if (0 == numerator_id) {
|
247
|
+
numerator_id = rb_intern("numerator");
|
248
|
+
denominator_id = rb_intern("denominator");
|
249
|
+
}
|
250
|
+
attrs[0].value = rb_funcall(obj, numerator_id, 0);
|
251
|
+
attrs[1].value = rb_funcall(obj, denominator_id, 0);
|
236
252
|
|
237
|
-
|
253
|
+
oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
|
254
|
+
} else {
|
255
|
+
dump_obj_as_str(obj, depth, out);
|
256
|
+
}
|
238
257
|
}
|
239
258
|
|
240
259
|
static VALUE
|
@@ -590,6 +609,8 @@ dump_attr_cb(ID key, VALUE value, Out out) {
|
|
590
609
|
// the key name is NULL. Not an empty string but NULL.
|
591
610
|
if (NULL == attr) {
|
592
611
|
attr = "";
|
612
|
+
} else if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
|
613
|
+
return ST_CONTINUE;
|
593
614
|
}
|
594
615
|
if (0 == strcmp("bt", attr) || 0 == strcmp("mesg", attr)) {
|
595
616
|
return ST_CONTINUE;
|
@@ -874,7 +895,11 @@ dump_data(VALUE obj, int depth, Out out, bool as_ok) {
|
|
874
895
|
|
875
896
|
static void
|
876
897
|
dump_regexp(VALUE obj, int depth, Out out, bool as_ok) {
|
877
|
-
|
898
|
+
if (NULL != out->opts->create_id) {
|
899
|
+
dump_obj_str(obj, depth, out);
|
900
|
+
} else {
|
901
|
+
dump_obj_as_str(obj, depth, out);
|
902
|
+
}
|
878
903
|
}
|
879
904
|
|
880
905
|
static void
|
@@ -1046,7 +1071,7 @@ hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) {
|
|
1046
1071
|
oj_set_obj_ivar(parent, kval, rval);
|
1047
1072
|
break;
|
1048
1073
|
case T_HASH:
|
1049
|
-
if (4 == parent->klen && NULL != parent->key && rb_cTime == parent->clas && 0 == strncmp("time", parent->key, 4)) {
|
1074
|
+
if (4 == parent->klen && NULL != parent->key && rb_cTime == parent->clas && 0 != ni->div && 0 == strncmp("time", parent->key, 4)) {
|
1050
1075
|
int64_t nsec = ni->num * 1000000000LL / ni->div;
|
1051
1076
|
|
1052
1077
|
if (ni->neg) {
|
data/ext/oj/dump.c
CHANGED
@@ -548,7 +548,7 @@ oj_dump_xml_time(VALUE obj, Out out) {
|
|
548
548
|
tzhour = (int)(tzsecs / 3600);
|
549
549
|
tzmin = (int)(tzsecs / 60) - (tzhour * 60);
|
550
550
|
}
|
551
|
-
if (0 == nsec || 0 == out->opts->sec_prec) {
|
551
|
+
if ((0 == nsec && !out->opts->sec_prec_set) || 0 == out->opts->sec_prec) {
|
552
552
|
if (0 == tzsecs && rb_funcall2(obj, oj_utcq_id, 0, 0)) {
|
553
553
|
sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02dZ", ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec);
|
554
554
|
oj_dump_cstr(buf, 20, 0, 0, out);
|
@@ -1023,8 +1023,8 @@ oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1023
1023
|
int neg = 0;
|
1024
1024
|
bool dump_as_string = false;
|
1025
1025
|
|
1026
|
-
if (out->opts->
|
1027
|
-
(out->opts->
|
1026
|
+
if (out->opts->int_range_max != 0 && out->opts->int_range_min != 0 &&
|
1027
|
+
(out->opts->int_range_max < num || out->opts->int_range_min > num)) {
|
1028
1028
|
dump_as_string = true;
|
1029
1029
|
}
|
1030
1030
|
if (0 > num) {
|
@@ -1062,23 +1062,20 @@ void
|
|
1062
1062
|
oj_dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
|
1063
1063
|
volatile VALUE rs = rb_big2str(obj, 10);
|
1064
1064
|
int cnt = (int)RSTRING_LEN(rs);
|
1065
|
-
|
1065
|
+
bool dump_as_string = false;
|
1066
1066
|
|
1067
|
-
|
1067
|
+
if (out->opts->int_range_max != 0 || out->opts->int_range_min != 0) { // Bignum cannot be inside of Fixnum range
|
1068
1068
|
dump_as_string = true;
|
1069
1069
|
assure_size(out, cnt + 2);
|
1070
1070
|
*out->cur++ = '"';
|
1071
|
-
|
1071
|
+
} else {
|
1072
1072
|
assure_size(out, cnt);
|
1073
|
-
|
1074
|
-
|
1073
|
+
}
|
1075
1074
|
memcpy(out->cur, rb_string_value_ptr((VALUE*)&rs), cnt);
|
1076
1075
|
out->cur += cnt;
|
1077
|
-
|
1078
|
-
if(dump_as_string) {
|
1076
|
+
if (dump_as_string) {
|
1079
1077
|
*out->cur++ = '"';
|
1080
|
-
|
1081
|
-
|
1078
|
+
}
|
1082
1079
|
*out->cur = '\0';
|
1083
1080
|
}
|
1084
1081
|
|
data/ext/oj/dump_compat.c
CHANGED
@@ -870,7 +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
|
-
|
873
|
+
bool dump_as_string = false;
|
874
874
|
|
875
875
|
if (use_bignum_alt) {
|
876
876
|
rs = rb_big2str(obj, 10);
|
@@ -880,21 +880,18 @@ dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
880
880
|
rb_check_type(rs, T_STRING);
|
881
881
|
cnt = (int)RSTRING_LEN(rs);
|
882
882
|
|
883
|
-
|
883
|
+
if (out->opts->int_range_min != 0 || out->opts->int_range_max != 0) {
|
884
884
|
dump_as_string = true; // Bignum cannot be inside of Fixnum range
|
885
885
|
assure_size(out, cnt + 2);
|
886
886
|
*out->cur++ = '"';
|
887
|
-
|
887
|
+
} else {
|
888
888
|
assure_size(out, cnt);
|
889
|
-
|
890
|
-
|
889
|
+
}
|
891
890
|
memcpy(out->cur, rb_string_value_ptr((VALUE*)&rs), cnt);
|
892
891
|
out->cur += cnt;
|
893
|
-
|
894
|
-
if(dump_as_string) {
|
892
|
+
if (dump_as_string) {
|
895
893
|
*out->cur++ = '"';
|
896
|
-
|
897
|
-
|
894
|
+
}
|
898
895
|
*out->cur = '\0';
|
899
896
|
}
|
900
897
|
|
data/ext/oj/dump_object.c
CHANGED
@@ -56,7 +56,7 @@ dump_data(VALUE obj, int depth, Out out, bool as_ok) {
|
|
56
56
|
}
|
57
57
|
} else {
|
58
58
|
long id = oj_check_circular(obj, out);
|
59
|
-
|
59
|
+
|
60
60
|
if (0 <= id) {
|
61
61
|
dump_obj_attrs(obj, clas, id, depth, out);
|
62
62
|
}
|
@@ -72,7 +72,7 @@ dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
|
|
72
72
|
volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
|
73
73
|
const char *str = rb_string_value_ptr((VALUE*)&rstr);
|
74
74
|
int len = (int)RSTRING_LEN(rstr);
|
75
|
-
|
75
|
+
|
76
76
|
if (0 == strcasecmp("Infinity", str)) {
|
77
77
|
str = oj_nan_str(obj, out->opts->dump_opts.nan_dump, out->opts->mode, true, &len);
|
78
78
|
oj_dump_raw(str, len, out);
|
@@ -280,7 +280,7 @@ hash_cb(VALUE key, VALUE value, Out out) {
|
|
280
280
|
}
|
281
281
|
out->depth = depth;
|
282
282
|
*out->cur++ = ',';
|
283
|
-
|
283
|
+
|
284
284
|
return ST_CONTINUE;
|
285
285
|
}
|
286
286
|
|
@@ -363,6 +363,8 @@ dump_attr_cb(ID key, VALUE value, Out out) {
|
|
363
363
|
// the key name is NULL. Not an empty string but NULL.
|
364
364
|
if (NULL == attr) {
|
365
365
|
attr = "";
|
366
|
+
} else if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
|
367
|
+
return ST_CONTINUE;
|
366
368
|
}
|
367
369
|
if (0 == strcmp("bt", attr) || 0 == strcmp("mesg", attr)) {
|
368
370
|
return ST_CONTINUE;
|
@@ -384,7 +386,7 @@ dump_attr_cb(ID key, VALUE value, Out out) {
|
|
384
386
|
oj_dump_obj_val(value, depth, out);
|
385
387
|
out->depth = depth;
|
386
388
|
*out->cur++ = ',';
|
387
|
-
|
389
|
+
|
388
390
|
return ST_CONTINUE;
|
389
391
|
}
|
390
392
|
#endif
|
@@ -424,7 +426,7 @@ dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
|
|
424
426
|
v = rb_funcall(obj, *odd->attrs, 0);
|
425
427
|
if (Qundef == v || T_STRING != rb_type(v)) {
|
426
428
|
rb_raise(rb_eEncodingError, "Invalid type for raw JSON.");
|
427
|
-
} else {
|
429
|
+
} else {
|
428
430
|
const char *s = rb_string_value_ptr((VALUE*)&v);
|
429
431
|
int len = (int)RSTRING_LEN(v);
|
430
432
|
const char *name = rb_id2name(*odd->attrs);
|
@@ -460,7 +462,7 @@ dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
|
|
460
462
|
char *n;
|
461
463
|
char *end;
|
462
464
|
ID i;
|
463
|
-
|
465
|
+
|
464
466
|
if (sizeof(nbuf) <= nlen) {
|
465
467
|
if (NULL == (n2 = strdup(name))) {
|
466
468
|
rb_raise(rb_eNoMemError, "for attribute name.");
|
@@ -610,9 +612,12 @@ dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out) {
|
|
610
612
|
size = d2 * out->indent + 1;
|
611
613
|
for (i = cnt; 0 < i; i--, np++) {
|
612
614
|
VALUE value;
|
613
|
-
|
615
|
+
|
614
616
|
vid = rb_to_id(*np);
|
615
617
|
attr = rb_id2name(vid);
|
618
|
+
if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
|
619
|
+
return ST_CONTINUE;
|
620
|
+
}
|
616
621
|
value = rb_ivar_get(obj, vid);
|
617
622
|
|
618
623
|
if (oj_dump_ignore(out->opts, value)) {
|
@@ -739,7 +744,7 @@ dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
|
|
739
744
|
#else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
|
740
745
|
cnt = (int)RSTRUCT_LEN(obj);
|
741
746
|
#endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
|
742
|
-
|
747
|
+
|
743
748
|
for (i = 0; i < cnt; i++) {
|
744
749
|
v = RSTRUCT_GET(obj, i);
|
745
750
|
if (oj_dump_ignore(out->opts, v)) {
|
@@ -812,7 +817,7 @@ static DumpFunc obj_funcs[] = {
|
|
812
817
|
void
|
813
818
|
oj_dump_obj_val(VALUE obj, int depth, Out out) {
|
814
819
|
int type = rb_type(obj);
|
815
|
-
|
820
|
+
|
816
821
|
if (Yes == out->opts->trace) {
|
817
822
|
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
|
818
823
|
}
|
data/ext/oj/extconf.rb
CHANGED
data/ext/oj/mimic_json.c
CHANGED
@@ -690,8 +690,10 @@ static struct _options mimic_object_to_json_options = {
|
|
690
690
|
No, // allow_nan
|
691
691
|
No, // trace
|
692
692
|
No, // safe
|
693
|
-
|
694
|
-
|
693
|
+
false, // sec_prec_set
|
694
|
+
No, // ignore_under
|
695
|
+
0, // int_range_min
|
696
|
+
0, // int_range_max
|
695
697
|
oj_json_class,// create_id
|
696
698
|
10, // create_id_len
|
697
699
|
3, // sec_prec
|
data/ext/oj/object.c
CHANGED
@@ -276,7 +276,10 @@ hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) {
|
|
276
276
|
if (2 == kval->klen) {
|
277
277
|
switch (kval->key[1]) {
|
278
278
|
case 't': // time as a float
|
279
|
-
{
|
279
|
+
if (0 == ni->div || 9 < ni->di) {
|
280
|
+
rb_raise(rb_eArgError, "Invalid time decimal representation.");
|
281
|
+
//parent->val = rb_time_nano_new(0, 0);
|
282
|
+
} else {
|
280
283
|
int64_t nsec = ni->num * 1000000000LL / ni->div;
|
281
284
|
|
282
285
|
if (ni->neg) {
|
@@ -407,7 +410,7 @@ oj_set_obj_ivar(Val parent, Val kval, VALUE value) {
|
|
407
410
|
ID var_id;
|
408
411
|
ID *slot;
|
409
412
|
|
410
|
-
#
|
413
|
+
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
411
414
|
pthread_mutex_lock(&oj_cache_mutex);
|
412
415
|
#else
|
413
416
|
rb_mutex_lock(oj_cache_mutex);
|
@@ -441,7 +444,7 @@ oj_set_obj_ivar(Val parent, Val kval, VALUE value) {
|
|
441
444
|
}
|
442
445
|
*slot = var_id;
|
443
446
|
}
|
444
|
-
#
|
447
|
+
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
445
448
|
pthread_mutex_unlock(&oj_cache_mutex);
|
446
449
|
#else
|
447
450
|
rb_mutex_unlock(oj_cache_mutex);
|
@@ -665,7 +668,7 @@ end_hash(ParseInfo pi) {
|
|
665
668
|
static void
|
666
669
|
array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
667
670
|
volatile VALUE rval = Qnil;
|
668
|
-
|
671
|
+
|
669
672
|
if (3 <= len && 0 != pi->circ_array) {
|
670
673
|
if ('i' == str[1]) {
|
671
674
|
long i = read_long(str + 2, len - 2);
|
@@ -694,7 +697,7 @@ array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
|
694
697
|
static void
|
695
698
|
array_append_num(ParseInfo pi, NumInfo ni) {
|
696
699
|
volatile VALUE rval = oj_num_as_value(ni);
|
697
|
-
|
700
|
+
|
698
701
|
rb_ary_push(stack_peek(&pi->stack)->val, rval);
|
699
702
|
if (Yes == pi->options.trace) {
|
700
703
|
oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
|
data/ext/oj/oj.c
CHANGED
@@ -119,6 +119,7 @@ static VALUE float_prec_sym;
|
|
119
119
|
static VALUE float_sym;
|
120
120
|
static VALUE huge_sym;
|
121
121
|
static VALUE ignore_sym;
|
122
|
+
static VALUE ignore_under_sym;
|
122
123
|
static VALUE json_sym;
|
123
124
|
static VALUE match_string_sym;
|
124
125
|
static VALUE mode_sym;
|
@@ -149,7 +150,7 @@ static VALUE xss_safe_sym;
|
|
149
150
|
|
150
151
|
rb_encoding *oj_utf8_encoding = 0;
|
151
152
|
|
152
|
-
#
|
153
|
+
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
153
154
|
pthread_mutex_t oj_cache_mutex;
|
154
155
|
#else
|
155
156
|
VALUE oj_cache_mutex = Qnil;
|
@@ -181,8 +182,10 @@ struct _options oj_default_options = {
|
|
181
182
|
Yes, // allow_nan
|
182
183
|
No, // trace
|
183
184
|
No, // safe
|
184
|
-
|
185
|
-
|
185
|
+
false, // sec_prec_set
|
186
|
+
No, // ignore_under
|
187
|
+
0, // int_range_min
|
188
|
+
0, // int_range_max
|
186
189
|
oj_json_class, // create_id
|
187
190
|
10, // create_id_len
|
188
191
|
9, // sec_prec
|
@@ -251,6 +254,7 @@ struct _options oj_default_options = {
|
|
251
254
|
* - *:array_class* [_Class_|_nil_] Class to use instead of Array on load
|
252
255
|
* - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted
|
253
256
|
* - *:ignore* [_nil_|Array] either nil or an Array of classes to ignore when dumping
|
257
|
+
* - *:ignore_under* [Boolean] if true then attributes that start with _ are ignored when dumping in object or custom mode.
|
254
258
|
* - *:integer_range* [_Range_] Dump integers outside range as strings.
|
255
259
|
* - *:trace* [_true,_|_false_] Trace all load and dump calls, default is false (trace is off)
|
256
260
|
* - *:safe* [_true,_|_false_] Safe mimic breaks JSON mimic to be safer, default is false (safe is off)
|
@@ -286,6 +290,7 @@ get_def_opts(VALUE self) {
|
|
286
290
|
rb_hash_aset(opts, oj_trace_sym, (Yes == oj_default_options.trace) ? Qtrue : ((No == oj_default_options.trace) ? Qfalse : Qnil));
|
287
291
|
rb_hash_aset(opts, oj_safe_sym, (Yes == oj_default_options.safe) ? Qtrue : ((No == oj_default_options.safe) ? Qfalse : Qnil));
|
288
292
|
rb_hash_aset(opts, float_prec_sym, INT2FIX(oj_default_options.float_prec));
|
293
|
+
rb_hash_aset(opts, ignore_under_sym, (Yes == oj_default_options.ignore_under) ? Qtrue : ((No == oj_default_options.ignore_under) ? Qfalse : Qnil));
|
289
294
|
switch (oj_default_options.mode) {
|
290
295
|
case StrictMode: rb_hash_aset(opts, mode_sym, strict_sym); break;
|
291
296
|
case CompatMode: rb_hash_aset(opts, mode_sym, compat_sym); break;
|
@@ -297,16 +302,16 @@ get_def_opts(VALUE self) {
|
|
297
302
|
default: rb_hash_aset(opts, mode_sym, object_sym); break;
|
298
303
|
}
|
299
304
|
|
300
|
-
if (oj_default_options.
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
else {
|
309
|
-
|
305
|
+
if (oj_default_options.int_range_max != 0 || oj_default_options.int_range_min != 0) {
|
306
|
+
VALUE range = rb_obj_alloc(rb_cRange);
|
307
|
+
VALUE min = LONG2FIX(oj_default_options.int_range_min);
|
308
|
+
VALUE max = LONG2FIX(oj_default_options.int_range_max);
|
309
|
+
|
310
|
+
rb_ivar_set(range, oj_begin_id, min);
|
311
|
+
rb_ivar_set(range, oj_end_id, max);
|
312
|
+
rb_hash_aset(opts, integer_range_sym, range);
|
313
|
+
} else {
|
314
|
+
rb_hash_aset(opts, integer_range_sym, Qnil);
|
310
315
|
}
|
311
316
|
switch (oj_default_options.escape_mode) {
|
312
317
|
case NLEsc: rb_hash_aset(opts, escape_mode_sym, newline_sym); break;
|
@@ -329,7 +334,7 @@ get_def_opts(VALUE self) {
|
|
329
334
|
case AutoDec:
|
330
335
|
default: rb_hash_aset(opts, bigdecimal_load_sym, auto_sym); break;
|
331
336
|
}
|
332
|
-
rb_hash_aset(opts, create_id_sym, (
|
337
|
+
rb_hash_aset(opts, create_id_sym, (NULL == oj_default_options.create_id) ? Qnil : rb_str_new2(oj_default_options.create_id));
|
333
338
|
rb_hash_aset(opts, oj_space_sym, (0 == oj_default_options.dump_opts.after_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.after_sep));
|
334
339
|
rb_hash_aset(opts, oj_space_before_sym, (0 == oj_default_options.dump_opts.before_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.before_sep));
|
335
340
|
rb_hash_aset(opts, oj_object_nl_sym, (0 == oj_default_options.dump_opts.hash_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.hash_nl));
|
@@ -398,6 +403,7 @@ get_def_opts(VALUE self) {
|
|
398
403
|
* - *:array_class* [_Class_|_nil_] Class to use instead of Array on load.
|
399
404
|
* - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted.
|
400
405
|
* - *:ignore* [_nil_|Array] either nil or an Array of classes to ignore when dumping
|
406
|
+
* - *:ignore_under* [_Boolean_] if true then attributes that start with _ are ignored when dumping in object or custom mode.
|
401
407
|
* - *:integer_range* [_Range_] Dump integers outside range as strings.
|
402
408
|
* - *:trace* [_Boolean_] turn trace on or off.
|
403
409
|
* - *:safe* [_Boolean_] turn safe mimic on or off.
|
@@ -431,6 +437,7 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
431
437
|
{ oj_allow_nan_sym, &copts->allow_nan },
|
432
438
|
{ oj_trace_sym, &copts->trace },
|
433
439
|
{ oj_safe_sym, &copts->safe },
|
440
|
+
{ ignore_under_sym, &copts->ignore_under },
|
434
441
|
{ oj_create_additions_sym, &copts->create_ok },
|
435
442
|
{ Qnil, 0 }
|
436
443
|
};
|
@@ -506,8 +513,12 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
506
513
|
n = NUM2INT(v);
|
507
514
|
if (0 > n) {
|
508
515
|
n = 0;
|
516
|
+
copts->sec_prec_set = false;
|
509
517
|
} else if (9 < n) {
|
510
518
|
n = 9;
|
519
|
+
copts->sec_prec_set = true;
|
520
|
+
} else {
|
521
|
+
copts->sec_prec_set = true;
|
511
522
|
}
|
512
523
|
copts->sec_prec = n;
|
513
524
|
}
|
@@ -738,19 +749,19 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
738
749
|
}
|
739
750
|
}
|
740
751
|
if (Qnil != (v = rb_hash_lookup(ropts, integer_range_sym))) {
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
752
|
+
if (TYPE(v) == T_STRUCT && rb_obj_class(v) == rb_cRange) {
|
753
|
+
VALUE min = rb_funcall(v, oj_begin_id, 0);
|
754
|
+
VALUE max = rb_funcall(v, oj_end_id, 0);
|
755
|
+
|
756
|
+
if (TYPE(min) != T_FIXNUM || TYPE(max) != T_FIXNUM) {
|
757
|
+
rb_raise(rb_eArgError, ":integer_range range bounds is not Fixnum.");
|
758
|
+
}
|
759
|
+
|
760
|
+
copts->int_range_min = FIX2LONG(min);
|
761
|
+
copts->int_range_max = FIX2LONG(max);
|
762
|
+
} else if (Qfalse != v) {
|
763
|
+
rb_raise(rb_eArgError, ":integer_range must be a range of Fixnum.");
|
764
|
+
}
|
754
765
|
}
|
755
766
|
}
|
756
767
|
|
@@ -954,11 +965,13 @@ load_file(int argc, VALUE *argv, VALUE self) {
|
|
954
965
|
}
|
955
966
|
switch (mode) {
|
956
967
|
case StrictMode:
|
968
|
+
case NullMode:
|
957
969
|
oj_set_strict_callbacks(&pi);
|
958
970
|
return oj_pi_sparse(argc, argv, &pi, fd);
|
959
|
-
case NullMode:
|
960
|
-
case CompatMode:
|
961
971
|
case CustomMode:
|
972
|
+
oj_set_custom_callbacks(&pi);
|
973
|
+
return oj_pi_sparse(argc, argv, &pi, fd);
|
974
|
+
case CompatMode:
|
962
975
|
case RailsMode:
|
963
976
|
oj_set_compat_callbacks(&pi);
|
964
977
|
return oj_pi_sparse(argc, argv, &pi, fd);
|
@@ -1052,6 +1065,9 @@ dump(int argc, VALUE *argv, VALUE self) {
|
|
1052
1065
|
if (2 == argc) {
|
1053
1066
|
oj_parse_options(argv[1], &copts);
|
1054
1067
|
}
|
1068
|
+
if (CompatMode == copts.mode && copts.escape_mode != ASCIIEsc) {
|
1069
|
+
copts.escape_mode = JSONEsc;
|
1070
|
+
}
|
1055
1071
|
out.buf = buf;
|
1056
1072
|
out.end = buf + sizeof(buf) - 10;
|
1057
1073
|
out.allocated = false;
|
@@ -1640,6 +1656,7 @@ Init_oj() {
|
|
1640
1656
|
float_sym = ID2SYM(rb_intern("float")); rb_gc_register_address(&float_sym);
|
1641
1657
|
huge_sym = ID2SYM(rb_intern("huge")); rb_gc_register_address(&huge_sym);
|
1642
1658
|
ignore_sym = ID2SYM(rb_intern("ignore")); rb_gc_register_address(&ignore_sym);
|
1659
|
+
ignore_under_sym = ID2SYM(rb_intern("ignore_under")); rb_gc_register_address(&ignore_under_sym);
|
1643
1660
|
json_sym = ID2SYM(rb_intern("json")); rb_gc_register_address(&json_sym);
|
1644
1661
|
match_string_sym = ID2SYM(rb_intern("match_string")); rb_gc_register_address(&match_string_sym);
|
1645
1662
|
mode_sym = ID2SYM(rb_intern("mode")); rb_gc_register_address(&mode_sym);
|
@@ -1692,7 +1709,7 @@ Init_oj() {
|
|
1692
1709
|
oj_odd_init();
|
1693
1710
|
oj_mimic_rails_init();
|
1694
1711
|
|
1695
|
-
#
|
1712
|
+
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
1696
1713
|
if (0 != (err = pthread_mutex_init(&oj_cache_mutex, 0))) {
|
1697
1714
|
rb_raise(rb_eException, "failed to initialize a mutex. %s", strerror(err));
|
1698
1715
|
}
|