oj 3.9.0 → 3.10.2
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/compat.c +5 -5
- data/ext/oj/custom.c +7 -3
- data/ext/oj/dump.c +9 -12
- data/ext/oj/dump_compat.c +8 -10
- data/ext/oj/dump_object.c +18 -11
- data/ext/oj/dump_strict.c +6 -5
- data/ext/oj/extconf.rb +5 -0
- data/ext/oj/mimic_json.c +15 -3
- data/ext/oj/object.c +6 -2
- data/ext/oj/oj.c +47 -28
- data/ext/oj/oj.h +4 -2
- data/ext/oj/parse.c +22 -3
- data/ext/oj/parse.h +1 -0
- data/ext/oj/rails.c +38 -4
- data/ext/oj/sparse.c +5 -0
- data/ext/oj/util.c +5 -5
- data/ext/oj/wab.c +9 -9
- data/lib/oj/version.rb +1 -1
- data/pages/Rails.md +59 -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/foo.rb +39 -8
- data/test/test_compat.rb +0 -7
- data/test/test_custom.rb +25 -6
- data/test/test_integer_range.rb +1 -2
- data/test/test_object.rb +12 -3
- data/test/test_rails.rb +26 -0
- data/test/test_strict.rb +24 -1
- data/test/test_various.rb +41 -62
- data/test/tests.rb +1 -0
- metadata +23 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0569d0892b3b9d79f0edf0866d843adb9abc21046838be295164884edb930b61'
|
4
|
+
data.tar.gz: ff04edae94da97c911b19c93015035df9fb3ce89162c0afc1df036e0f675e65f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2d5a28e21b6c37bc5a11917512906c040cf8a0b038a07f23c0447a1705986fe98803191f6d2462e4f0ec67f7f3694cd9c61d0149d782f0a5e5f6b6d36a88d372
|
7
|
+
data.tar.gz: 789c0fdfe061476ee5e5c4bbe84519e7b1a6a015436e7fbe2cdb5f7922d6eef8de5914bd61488be4c297633e053f2a217630f7358796de9ba746aa6935466983
|
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/compat.c
CHANGED
@@ -65,7 +65,7 @@ hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *o
|
|
65
65
|
static VALUE
|
66
66
|
start_hash(ParseInfo pi) {
|
67
67
|
volatile VALUE h;
|
68
|
-
|
68
|
+
|
69
69
|
if (Qnil != pi->options.hash_class) {
|
70
70
|
h = rb_class_new_instance(0, NULL, pi->options.hash_class);
|
71
71
|
} else {
|
@@ -87,7 +87,7 @@ end_hash(struct _parseInfo *pi) {
|
|
87
87
|
clas = oj_name2class(pi, parent->classname, parent->clen, 0, rb_eArgError);
|
88
88
|
if (Qundef != clas) { // else an error
|
89
89
|
ID creatable = rb_intern("json_creatable?");
|
90
|
-
|
90
|
+
|
91
91
|
if (!rb_respond_to(clas, creatable) || Qtrue == rb_funcall(clas, creatable, 0)) {
|
92
92
|
parent->val = rb_funcall(clas, oj_json_create_id, 1, parent->val);
|
93
93
|
}
|
@@ -146,7 +146,7 @@ add_num(ParseInfo pi, NumInfo ni) {
|
|
146
146
|
static void
|
147
147
|
hash_set_num(struct _parseInfo *pi, Val parent, NumInfo ni) {
|
148
148
|
volatile VALUE rval = oj_num_as_value(ni);
|
149
|
-
|
149
|
+
|
150
150
|
if (!oj_use_hash_alt && rb_cHash != rb_obj_class(parent->val)) {
|
151
151
|
// The rb_hash_set would still work but the unit tests for the
|
152
152
|
// json gem require the less efficient []= method be called to set
|
@@ -192,7 +192,7 @@ static void
|
|
192
192
|
array_append_num(ParseInfo pi, NumInfo ni) {
|
193
193
|
Val parent = stack_peek(&pi->stack);
|
194
194
|
volatile VALUE rval = oj_num_as_value(ni);
|
195
|
-
|
195
|
+
|
196
196
|
if (!oj_use_array_alt && rb_cArray != rb_obj_class(parent->val)) {
|
197
197
|
// The rb_ary_push would still work but the unit tests for the json
|
198
198
|
// gem require the less efficient << method be called to push the
|
@@ -274,7 +274,7 @@ oj_compat_load(int argc, VALUE *argv, VALUE self) {
|
|
274
274
|
pi.options.nilnil = Yes;
|
275
275
|
pi.options.empty_string = Yes;
|
276
276
|
oj_set_compat_callbacks(&pi);
|
277
|
-
|
277
|
+
|
278
278
|
if (T_STRING == rb_type(*argv)) {
|
279
279
|
return oj_pi_parse(argc, argv, &pi, 0, 0, false);
|
280
280
|
} else {
|
data/ext/oj/custom.c
CHANGED
@@ -297,7 +297,8 @@ static struct _code codes[] = {
|
|
297
297
|
};
|
298
298
|
|
299
299
|
static int
|
300
|
-
hash_cb(VALUE key, VALUE value,
|
300
|
+
hash_cb(VALUE key, VALUE value, VALUE ov) {
|
301
|
+
Out out = (Out)ov;
|
301
302
|
int depth = out->depth;
|
302
303
|
|
303
304
|
if (oj_dump_ignore(out->opts, value)) {
|
@@ -592,7 +593,8 @@ dump_common(VALUE obj, int depth, Out out) {
|
|
592
593
|
}
|
593
594
|
|
594
595
|
static int
|
595
|
-
dump_attr_cb(ID key, VALUE value,
|
596
|
+
dump_attr_cb(ID key, VALUE value, VALUE ov) {
|
597
|
+
Out out = (Out)ov;
|
596
598
|
int depth = out->depth;
|
597
599
|
size_t size;
|
598
600
|
const char *attr;
|
@@ -609,6 +611,8 @@ dump_attr_cb(ID key, VALUE value, Out out) {
|
|
609
611
|
// the key name is NULL. Not an empty string but NULL.
|
610
612
|
if (NULL == attr) {
|
611
613
|
attr = "";
|
614
|
+
} else if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
|
615
|
+
return ST_CONTINUE;
|
612
616
|
}
|
613
617
|
if (0 == strcmp("bt", attr) || 0 == strcmp("mesg", attr)) {
|
614
618
|
return ST_CONTINUE;
|
@@ -1069,7 +1073,7 @@ hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) {
|
|
1069
1073
|
oj_set_obj_ivar(parent, kval, rval);
|
1070
1074
|
break;
|
1071
1075
|
case T_HASH:
|
1072
|
-
if (4 == parent->klen && NULL != parent->key && rb_cTime == parent->clas && 0 == strncmp("time", parent->key, 4)) {
|
1076
|
+
if (4 == parent->klen && NULL != parent->key && rb_cTime == parent->clas && 0 != ni->div && 0 == strncmp("time", parent->key, 4)) {
|
1073
1077
|
int64_t nsec = ni->num * 1000000000LL / ni->div;
|
1074
1078
|
|
1075
1079
|
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
@@ -648,7 +648,8 @@ dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
648
648
|
}
|
649
649
|
|
650
650
|
static int
|
651
|
-
hash_cb(VALUE key, VALUE value,
|
651
|
+
hash_cb(VALUE key, VALUE value, VALUE ov) {
|
652
|
+
Out out = (Out)ov;
|
652
653
|
int depth = out->depth;
|
653
654
|
|
654
655
|
if (out->omit_nil && Qnil == value) {
|
@@ -870,7 +871,7 @@ dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
870
871
|
// this must use to_s to pass the json gem unit tests.
|
871
872
|
volatile VALUE rs;
|
872
873
|
int cnt;
|
873
|
-
|
874
|
+
bool dump_as_string = false;
|
874
875
|
|
875
876
|
if (use_bignum_alt) {
|
876
877
|
rs = rb_big2str(obj, 10);
|
@@ -880,21 +881,18 @@ dump_bignum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
880
881
|
rb_check_type(rs, T_STRING);
|
881
882
|
cnt = (int)RSTRING_LEN(rs);
|
882
883
|
|
883
|
-
|
884
|
+
if (out->opts->int_range_min != 0 || out->opts->int_range_max != 0) {
|
884
885
|
dump_as_string = true; // Bignum cannot be inside of Fixnum range
|
885
886
|
assure_size(out, cnt + 2);
|
886
887
|
*out->cur++ = '"';
|
887
|
-
|
888
|
+
} else {
|
888
889
|
assure_size(out, cnt);
|
889
|
-
|
890
|
-
|
890
|
+
}
|
891
891
|
memcpy(out->cur, rb_string_value_ptr((VALUE*)&rs), cnt);
|
892
892
|
out->cur += cnt;
|
893
|
-
|
894
|
-
if(dump_as_string) {
|
893
|
+
if (dump_as_string) {
|
895
894
|
*out->cur++ = '"';
|
896
|
-
|
897
|
-
|
895
|
+
}
|
898
896
|
*out->cur = '\0';
|
899
897
|
}
|
900
898
|
|
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);
|
@@ -224,7 +224,8 @@ dump_sym(VALUE obj, int depth, Out out, bool as_ok) {
|
|
224
224
|
}
|
225
225
|
|
226
226
|
static int
|
227
|
-
hash_cb(VALUE key, VALUE value,
|
227
|
+
hash_cb(VALUE key, VALUE value, VALUE ov) {
|
228
|
+
Out out = (Out)ov;
|
228
229
|
int depth = out->depth;
|
229
230
|
long size = depth * out->indent + 1;
|
230
231
|
|
@@ -280,7 +281,7 @@ hash_cb(VALUE key, VALUE value, Out out) {
|
|
280
281
|
}
|
281
282
|
out->depth = depth;
|
282
283
|
*out->cur++ = ',';
|
283
|
-
|
284
|
+
|
284
285
|
return ST_CONTINUE;
|
285
286
|
}
|
286
287
|
|
@@ -348,7 +349,8 @@ dump_hash_class(VALUE obj, VALUE clas, int depth, Out out) {
|
|
348
349
|
|
349
350
|
#ifdef HAVE_RB_IVAR_FOREACH
|
350
351
|
static int
|
351
|
-
dump_attr_cb(ID key, VALUE value,
|
352
|
+
dump_attr_cb(ID key, VALUE value, VALUE ov) {
|
353
|
+
Out out = (Out)ov;
|
352
354
|
int depth = out->depth;
|
353
355
|
size_t size = depth * out->indent + 1;
|
354
356
|
const char *attr = rb_id2name(key);
|
@@ -363,6 +365,8 @@ dump_attr_cb(ID key, VALUE value, Out out) {
|
|
363
365
|
// the key name is NULL. Not an empty string but NULL.
|
364
366
|
if (NULL == attr) {
|
365
367
|
attr = "";
|
368
|
+
} else if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
|
369
|
+
return ST_CONTINUE;
|
366
370
|
}
|
367
371
|
if (0 == strcmp("bt", attr) || 0 == strcmp("mesg", attr)) {
|
368
372
|
return ST_CONTINUE;
|
@@ -384,7 +388,7 @@ dump_attr_cb(ID key, VALUE value, Out out) {
|
|
384
388
|
oj_dump_obj_val(value, depth, out);
|
385
389
|
out->depth = depth;
|
386
390
|
*out->cur++ = ',';
|
387
|
-
|
391
|
+
|
388
392
|
return ST_CONTINUE;
|
389
393
|
}
|
390
394
|
#endif
|
@@ -424,7 +428,7 @@ dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
|
|
424
428
|
v = rb_funcall(obj, *odd->attrs, 0);
|
425
429
|
if (Qundef == v || T_STRING != rb_type(v)) {
|
426
430
|
rb_raise(rb_eEncodingError, "Invalid type for raw JSON.");
|
427
|
-
} else {
|
431
|
+
} else {
|
428
432
|
const char *s = rb_string_value_ptr((VALUE*)&v);
|
429
433
|
int len = (int)RSTRING_LEN(v);
|
430
434
|
const char *name = rb_id2name(*odd->attrs);
|
@@ -460,7 +464,7 @@ dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
|
|
460
464
|
char *n;
|
461
465
|
char *end;
|
462
466
|
ID i;
|
463
|
-
|
467
|
+
|
464
468
|
if (sizeof(nbuf) <= nlen) {
|
465
469
|
if (NULL == (n2 = strdup(name))) {
|
466
470
|
rb_raise(rb_eNoMemError, "for attribute name.");
|
@@ -610,9 +614,12 @@ dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out) {
|
|
610
614
|
size = d2 * out->indent + 1;
|
611
615
|
for (i = cnt; 0 < i; i--, np++) {
|
612
616
|
VALUE value;
|
613
|
-
|
617
|
+
|
614
618
|
vid = rb_to_id(*np);
|
615
619
|
attr = rb_id2name(vid);
|
620
|
+
if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
|
621
|
+
return ST_CONTINUE;
|
622
|
+
}
|
616
623
|
value = rb_ivar_get(obj, vid);
|
617
624
|
|
618
625
|
if (oj_dump_ignore(out->opts, value)) {
|
@@ -739,7 +746,7 @@ dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
|
|
739
746
|
#else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
|
740
747
|
cnt = (int)RSTRUCT_LEN(obj);
|
741
748
|
#endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
|
742
|
-
|
749
|
+
|
743
750
|
for (i = 0; i < cnt; i++) {
|
744
751
|
v = RSTRUCT_GET(obj, i);
|
745
752
|
if (oj_dump_ignore(out->opts, v)) {
|
@@ -812,7 +819,7 @@ static DumpFunc obj_funcs[] = {
|
|
812
819
|
void
|
813
820
|
oj_dump_obj_val(VALUE obj, int depth, Out out) {
|
814
821
|
int type = rb_type(obj);
|
815
|
-
|
822
|
+
|
816
823
|
if (Yes == out->opts->trace) {
|
817
824
|
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
|
818
825
|
}
|
data/ext/oj/dump_strict.c
CHANGED
@@ -45,7 +45,7 @@ dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
45
45
|
cnt = 3;
|
46
46
|
} else {
|
47
47
|
NanDump nd = out->opts->dump_opts.nan_dump;
|
48
|
-
|
48
|
+
|
49
49
|
if (AutoNan == nd) {
|
50
50
|
nd = RaiseNan;
|
51
51
|
}
|
@@ -195,11 +195,12 @@ dump_array(VALUE a, int depth, Out out, bool as_ok) {
|
|
195
195
|
}
|
196
196
|
|
197
197
|
static int
|
198
|
-
hash_cb(VALUE key, VALUE value,
|
198
|
+
hash_cb(VALUE key, VALUE value, VALUE ov) {
|
199
|
+
Out out = (Out)ov;
|
199
200
|
int depth = out->depth;
|
200
201
|
long size;
|
201
202
|
int rtype = rb_type(key);
|
202
|
-
|
203
|
+
|
203
204
|
if (rtype != T_STRING && rtype != T_SYMBOL) {
|
204
205
|
rb_raise(rb_eTypeError, "In :strict and :null mode all Hash keys must be Strings or Symbols, not %s.\n", rb_class2name(rb_obj_class(key)));
|
205
206
|
}
|
@@ -359,7 +360,7 @@ static DumpFunc strict_funcs[] = {
|
|
359
360
|
void
|
360
361
|
oj_dump_strict_val(VALUE obj, int depth, Out out) {
|
361
362
|
int type = rb_type(obj);
|
362
|
-
|
363
|
+
|
363
364
|
if (Yes == out->opts->trace) {
|
364
365
|
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
|
365
366
|
}
|
@@ -408,7 +409,7 @@ static DumpFunc null_funcs[] = {
|
|
408
409
|
void
|
409
410
|
oj_dump_null_val(VALUE obj, int depth, Out out) {
|
410
411
|
int type = rb_type(obj);
|
411
|
-
|
412
|
+
|
412
413
|
if (Yes == out->opts->trace) {
|
413
414
|
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
|
414
415
|
}
|
data/ext/oj/extconf.rb
CHANGED
@@ -42,6 +42,11 @@ end
|
|
42
42
|
|
43
43
|
$CPPFLAGS += ' -Wall'
|
44
44
|
#puts "*** $CPPFLAGS: #{$CPPFLAGS}"
|
45
|
+
# Adding the __attribute__ flag only works with gcc compilers and even then it
|
46
|
+
# does not work to check args with varargs so just remove the check.
|
47
|
+
CONFIG['warnflags'].slice!(/ -Wsuggest-attribute=format/)
|
48
|
+
CONFIG['warnflags'].slice!(/ -Wdeclaration-after-statement/)
|
49
|
+
CONFIG['warnflags'].slice!(/ -Wmissing-noreturn/)
|
45
50
|
|
46
51
|
create_makefile(File.join(extension_name, extension_name))
|
47
52
|
|
data/ext/oj/mimic_json.c
CHANGED
@@ -199,6 +199,7 @@ mimic_dump(int argc, VALUE *argv, VALUE self) {
|
|
199
199
|
struct _out out;
|
200
200
|
struct _options copts = oj_default_options;
|
201
201
|
VALUE rstr;
|
202
|
+
VALUE active_hack[1];
|
202
203
|
|
203
204
|
copts.str_rx.head = NULL;
|
204
205
|
copts.str_rx.tail = NULL;
|
@@ -216,6 +217,7 @@ mimic_dump(int argc, VALUE *argv, VALUE self) {
|
|
216
217
|
*/
|
217
218
|
copts.dump_opts.max_depth = MAX_DEPTH; // when using dump there is no limit
|
218
219
|
out.omit_nil = copts.dump_opts.omit_nil;
|
220
|
+
|
219
221
|
if (2 <= argc) {
|
220
222
|
int limit;
|
221
223
|
|
@@ -230,7 +232,15 @@ mimic_dump(int argc, VALUE *argv, VALUE self) {
|
|
230
232
|
copts.dump_opts.max_depth = limit;
|
231
233
|
}
|
232
234
|
}
|
233
|
-
|
235
|
+
// ActiveSupport in active_support/core_ext/object/json.rb check the
|
236
|
+
// optional argument type to to_json and it the argument is a
|
237
|
+
// ::JSON::State it calls the JSON gem code otherwise it calls the active
|
238
|
+
// support encoder code. To make sure the desired branch is called a
|
239
|
+
// default ::JSON::State argument is passed in. Basically a hack to get
|
240
|
+
// around the active support hack so two wrongs make a right this time.
|
241
|
+
active_hack[0] = rb_funcall(state_class, oj_new_id, 0);
|
242
|
+
oj_dump_obj_to_json_using_params(*argv, &copts, &out, 1, active_hack);
|
243
|
+
|
234
244
|
if (0 == out.buf) {
|
235
245
|
rb_raise(rb_eNoMemError, "Not enough memory.");
|
236
246
|
}
|
@@ -690,8 +700,10 @@ static struct _options mimic_object_to_json_options = {
|
|
690
700
|
No, // allow_nan
|
691
701
|
No, // trace
|
692
702
|
No, // safe
|
693
|
-
|
694
|
-
|
703
|
+
false, // sec_prec_set
|
704
|
+
No, // ignore_under
|
705
|
+
0, // int_range_min
|
706
|
+
0, // int_range_max
|
695
707
|
oj_json_class,// create_id
|
696
708
|
10, // create_id_len
|
697
709
|
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) {
|
@@ -666,7 +669,8 @@ 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
|
+
// orig lets us know whether the string was ^r1 or \u005er1
|
673
|
+
if (3 <= len && 0 != pi->circ_array && '^' == orig[0] && 0 == rb_array_len(stack_peek(&pi->stack)->val)) {
|
670
674
|
if ('i' == str[1]) {
|
671
675
|
long i = read_long(str + 2, len - 2);
|
672
676
|
|
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;
|
@@ -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;
|
@@ -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,24 +749,26 @@ 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
|
|
757
768
|
static int
|
758
|
-
match_string_cb(VALUE key, VALUE value,
|
769
|
+
match_string_cb(VALUE key, VALUE value, VALUE rx) {
|
770
|
+
RxClass rc = (RxClass)rx;
|
771
|
+
|
759
772
|
if (T_CLASS != rb_type(value)) {
|
760
773
|
rb_raise(rb_eArgError, "for :match_string, the hash values must be a Class.");
|
761
774
|
}
|
@@ -954,11 +967,13 @@ load_file(int argc, VALUE *argv, VALUE self) {
|
|
954
967
|
}
|
955
968
|
switch (mode) {
|
956
969
|
case StrictMode:
|
970
|
+
case NullMode:
|
957
971
|
oj_set_strict_callbacks(&pi);
|
958
972
|
return oj_pi_sparse(argc, argv, &pi, fd);
|
959
|
-
case NullMode:
|
960
|
-
case CompatMode:
|
961
973
|
case CustomMode:
|
974
|
+
oj_set_custom_callbacks(&pi);
|
975
|
+
return oj_pi_sparse(argc, argv, &pi, fd);
|
976
|
+
case CompatMode:
|
962
977
|
case RailsMode:
|
963
978
|
oj_set_compat_callbacks(&pi);
|
964
979
|
return oj_pi_sparse(argc, argv, &pi, fd);
|
@@ -1052,6 +1067,9 @@ dump(int argc, VALUE *argv, VALUE self) {
|
|
1052
1067
|
if (2 == argc) {
|
1053
1068
|
oj_parse_options(argv[1], &copts);
|
1054
1069
|
}
|
1070
|
+
if (CompatMode == copts.mode && copts.escape_mode != ASCIIEsc) {
|
1071
|
+
copts.escape_mode = JSONEsc;
|
1072
|
+
}
|
1055
1073
|
out.buf = buf;
|
1056
1074
|
out.end = buf + sizeof(buf) - 10;
|
1057
1075
|
out.allocated = false;
|
@@ -1640,6 +1658,7 @@ Init_oj() {
|
|
1640
1658
|
float_sym = ID2SYM(rb_intern("float")); rb_gc_register_address(&float_sym);
|
1641
1659
|
huge_sym = ID2SYM(rb_intern("huge")); rb_gc_register_address(&huge_sym);
|
1642
1660
|
ignore_sym = ID2SYM(rb_intern("ignore")); rb_gc_register_address(&ignore_sym);
|
1661
|
+
ignore_under_sym = ID2SYM(rb_intern("ignore_under")); rb_gc_register_address(&ignore_under_sym);
|
1643
1662
|
json_sym = ID2SYM(rb_intern("json")); rb_gc_register_address(&json_sym);
|
1644
1663
|
match_string_sym = ID2SYM(rb_intern("match_string")); rb_gc_register_address(&match_string_sym);
|
1645
1664
|
mode_sym = ID2SYM(rb_intern("mode")); rb_gc_register_address(&mode_sym);
|