oj 3.13.13 → 3.13.16
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/CHANGELOG.md +12 -0
- data/ext/oj/compat.c +10 -10
- data/ext/oj/custom.c +6 -6
- data/ext/oj/dump.c +22 -12
- data/ext/oj/dump_compat.c +0 -5
- data/ext/oj/dump_object.c +2 -57
- data/ext/oj/extconf.rb +5 -4
- data/ext/oj/mimic_json.c +19 -9
- data/ext/oj/object.c +9 -9
- data/ext/oj/oj.c +17 -3
- data/ext/oj/oj.h +1 -1
- data/ext/oj/parse.c +50 -15
- data/ext/oj/parser.c +32 -4
- data/ext/oj/parser.h +1 -0
- data/ext/oj/rails.c +0 -5
- data/ext/oj/saj2.c +299 -45
- data/ext/oj/sparse.c +4 -0
- data/ext/oj/strict.c +13 -13
- data/ext/oj/wab.c +13 -18
- data/lib/oj/saj.rb +20 -6
- data/lib/oj/version.rb +1 -1
- data/test/activesupport7/abstract_unit.rb +49 -0
- data/test/activesupport7/decoding_test.rb +125 -0
- data/test/activesupport7/encoding_test.rb +486 -0
- data/test/activesupport7/encoding_test_cases.rb +104 -0
- data/test/activesupport7/time_zone_test_helpers.rb +47 -0
- data/test/bar.rb +8 -1
- data/test/json_gem/json_generator_test.rb +2 -0
- data/test/json_gem/json_parser_test.rb +7 -0
- data/test/test_compat.rb +16 -0
- data/test/test_file.rb +18 -0
- data/test/test_parser_saj.rb +55 -2
- data/test/test_various.rb +6 -0
- metadata +8 -116
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d07b4081b5dda88146594adba591542d11106f1c1eadcf7c56e38358d0ee0af3
|
4
|
+
data.tar.gz: 6bdc82c3812f45a8ae9d72ec0b2f43ee223d95ac250399fc8dae8daf34cd3b49
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4358aa15b7956a5b577163e43fbdc0512212a218124878ceedc2932483f27acabed2d2b92eb888c8e54601f4f4aaf3dce3b959a36effbea989e7e7ea8956d1c1
|
7
|
+
data.tar.gz: 1e1710bce62aadfbcc1196357d2e692892b75cc18c982fb6f53c2e35782d9bd2256cb3b6ab98951691430f23e8c2d8db26987a95dcba29f87b472729613b8d2d
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 3.13.16 - 2022-07-06
|
4
|
+
|
5
|
+
- Added line and column as optional arguments to the Oj::Parser.saj parser.
|
6
|
+
|
7
|
+
## 3.13.15 - 2022-07-03
|
8
|
+
|
9
|
+
- Fixed issue dumping NaN value in object mode.
|
10
|
+
|
11
|
+
## 3.13.14 - 2022-06-03
|
12
|
+
|
13
|
+
- Double fclose() due to bad merger fixed by tonobo.
|
14
|
+
|
3
15
|
## 3.13.13 - 2022-05-20
|
4
16
|
|
5
17
|
- Fixed flooding stdout with debug output when dumping.
|
data/ext/oj/compat.c
CHANGED
@@ -54,7 +54,7 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c
|
|
54
54
|
} else {
|
55
55
|
rb_hash_aset(parent->val, rkey, rstr);
|
56
56
|
}
|
57
|
-
if (Yes == pi->options.trace) {
|
57
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
58
58
|
oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
|
59
59
|
}
|
60
60
|
}
|
@@ -68,7 +68,7 @@ static VALUE start_hash(ParseInfo pi) {
|
|
68
68
|
} else {
|
69
69
|
h = rb_hash_new();
|
70
70
|
}
|
71
|
-
if (Yes == pi->options.trace) {
|
71
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
72
72
|
oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
|
73
73
|
}
|
74
74
|
return h;
|
@@ -93,7 +93,7 @@ static void end_hash(struct _parseInfo *pi) {
|
|
93
93
|
parent->classname = 0;
|
94
94
|
}
|
95
95
|
}
|
96
|
-
if (Yes == pi->options.trace) {
|
96
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
97
97
|
oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
|
98
98
|
}
|
99
99
|
}
|
@@ -110,14 +110,14 @@ static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig
|
|
110
110
|
}
|
111
111
|
}
|
112
112
|
pi->stack.head->val = rstr;
|
113
|
-
if (Yes == pi->options.trace) {
|
113
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
114
114
|
oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, rstr);
|
115
115
|
}
|
116
116
|
}
|
117
117
|
|
118
118
|
static void add_num(ParseInfo pi, NumInfo ni) {
|
119
119
|
pi->stack.head->val = oj_num_as_value(ni);
|
120
|
-
if (Yes == pi->options.trace) {
|
120
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
121
121
|
oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, pi->stack.head->val);
|
122
122
|
}
|
123
123
|
}
|
@@ -138,7 +138,7 @@ static void hash_set_num(struct _parseInfo *pi, Val parent, NumInfo ni) {
|
|
138
138
|
} else {
|
139
139
|
rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), rval);
|
140
140
|
}
|
141
|
-
if (Yes == pi->options.trace) {
|
141
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
142
142
|
oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, rval);
|
143
143
|
}
|
144
144
|
}
|
@@ -157,7 +157,7 @@ static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
|
|
157
157
|
} else {
|
158
158
|
rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), value);
|
159
159
|
}
|
160
|
-
if (Yes == pi->options.trace) {
|
160
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
161
161
|
oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
|
162
162
|
}
|
163
163
|
}
|
@@ -166,7 +166,7 @@ static VALUE start_array(ParseInfo pi) {
|
|
166
166
|
if (Qnil != pi->options.array_class) {
|
167
167
|
return rb_class_new_instance(0, NULL, pi->options.array_class);
|
168
168
|
}
|
169
|
-
if (Yes == pi->options.trace) {
|
169
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
170
170
|
oj_trace_parse_in("start_array", pi, __FILE__, __LINE__);
|
171
171
|
}
|
172
172
|
return rb_ary_new();
|
@@ -184,7 +184,7 @@ static void array_append_num(ParseInfo pi, NumInfo ni) {
|
|
184
184
|
} else {
|
185
185
|
rb_ary_push(parent->val, rval);
|
186
186
|
}
|
187
|
-
if (Yes == pi->options.trace) {
|
187
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
188
188
|
oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
|
189
189
|
}
|
190
190
|
}
|
@@ -201,7 +201,7 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
|
|
201
201
|
}
|
202
202
|
}
|
203
203
|
rb_ary_push(stack_peek(&pi->stack)->val, rstr);
|
204
|
-
if (Yes == pi->options.trace) {
|
204
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
205
205
|
oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
|
206
206
|
}
|
207
207
|
}
|
data/ext/oj/custom.c
CHANGED
@@ -959,7 +959,7 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c
|
|
959
959
|
break;
|
960
960
|
default: break;
|
961
961
|
}
|
962
|
-
if (Yes == pi->options.trace) {
|
962
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
963
963
|
oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
|
964
964
|
}
|
965
965
|
}
|
@@ -978,7 +978,7 @@ static void end_hash(struct _parseInfo *pi) {
|
|
978
978
|
}
|
979
979
|
parent->clas = Qundef;
|
980
980
|
}
|
981
|
-
if (Yes == pi->options.trace) {
|
981
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
982
982
|
oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
|
983
983
|
}
|
984
984
|
}
|
@@ -1032,7 +1032,7 @@ static void hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) {
|
|
1032
1032
|
break;
|
1033
1033
|
default: break;
|
1034
1034
|
}
|
1035
|
-
if (Yes == pi->options.trace) {
|
1035
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
1036
1036
|
oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
|
1037
1037
|
}
|
1038
1038
|
}
|
@@ -1045,7 +1045,7 @@ static void hash_set_value(ParseInfo pi, Val kval, VALUE value) {
|
|
1045
1045
|
case T_HASH: rb_hash_aset(parent->val, oj_calc_hash_key(pi, kval), value); break;
|
1046
1046
|
default: break;
|
1047
1047
|
}
|
1048
|
-
if (Yes == pi->options.trace) {
|
1048
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
1049
1049
|
oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
|
1050
1050
|
}
|
1051
1051
|
}
|
@@ -1055,7 +1055,7 @@ static void array_append_num(ParseInfo pi, NumInfo ni) {
|
|
1055
1055
|
volatile VALUE rval = oj_num_as_value(ni);
|
1056
1056
|
|
1057
1057
|
rb_ary_push(parent->val, rval);
|
1058
|
-
if (Yes == pi->options.trace) {
|
1058
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
1059
1059
|
oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
|
1060
1060
|
}
|
1061
1061
|
}
|
@@ -1072,7 +1072,7 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
|
|
1072
1072
|
}
|
1073
1073
|
}
|
1074
1074
|
rb_ary_push(stack_peek(&pi->stack)->val, rstr);
|
1075
|
-
if (Yes == pi->options.trace) {
|
1075
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
1076
1076
|
oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
|
1077
1077
|
}
|
1078
1078
|
}
|
data/ext/oj/dump.c
CHANGED
@@ -32,6 +32,7 @@ static const char nan_val[] = NAN_VAL;
|
|
32
32
|
typedef unsigned long ulong;
|
33
33
|
|
34
34
|
static size_t hibit_friendly_size(const uint8_t *str, size_t len);
|
35
|
+
static size_t slash_friendly_size(const uint8_t *str, size_t len);
|
35
36
|
static size_t xss_friendly_size(const uint8_t *str, size_t len);
|
36
37
|
static size_t ascii_friendly_size(const uint8_t *str, size_t len);
|
37
38
|
|
@@ -59,6 +60,17 @@ static char hibit_friendly_chars[256] = "\
|
|
59
60
|
11111111111111111111111111111111\
|
60
61
|
11111111111111111111111111111111";
|
61
62
|
|
63
|
+
// JSON standard but escape forward slashes `/`
|
64
|
+
static char slash_friendly_chars[256] = "\
|
65
|
+
66666666222622666666666666666666\
|
66
|
+
11211111111111121111111111111111\
|
67
|
+
11111111111111111111111111112111\
|
68
|
+
11111111111111111111111111111111\
|
69
|
+
11111111111111111111111111111111\
|
70
|
+
11111111111111111111111111111111\
|
71
|
+
11111111111111111111111111111111\
|
72
|
+
11111111111111111111111111111111";
|
73
|
+
|
62
74
|
// High bit set characters are always encoded as unicode. Worse case is 3
|
63
75
|
// bytes per character in the output. That makes this conservative.
|
64
76
|
static char ascii_friendly_chars[256] = "\
|
@@ -143,6 +155,10 @@ inline static size_t hibit_friendly_size(const uint8_t *str, size_t len) {
|
|
143
155
|
return calculate_string_size(str, len, hibit_friendly_chars);
|
144
156
|
}
|
145
157
|
|
158
|
+
inline static size_t slash_friendly_size(const uint8_t *str, size_t len) {
|
159
|
+
return calculate_string_size(str, len, slash_friendly_chars);
|
160
|
+
}
|
161
|
+
|
146
162
|
inline static size_t ascii_friendly_size(const uint8_t *str, size_t len) {
|
147
163
|
return calculate_string_size(str, len, ascii_friendly_chars);
|
148
164
|
}
|
@@ -365,7 +381,6 @@ void oj_dump_time(VALUE obj, Out out, int withZone) {
|
|
365
381
|
long long sec;
|
366
382
|
long long nsec;
|
367
383
|
|
368
|
-
#ifdef HAVE_RB_TIME_TIMESPEC
|
369
384
|
// rb_time_timespec as well as rb_time_timeeval have a bug that causes an
|
370
385
|
// exception to be raised if a time is before 1970 on 32 bit systems so
|
371
386
|
// check the timespec size and use the ruby calls if a 32 bit system.
|
@@ -378,10 +393,6 @@ void oj_dump_time(VALUE obj, Out out, int withZone) {
|
|
378
393
|
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
379
394
|
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
380
395
|
}
|
381
|
-
#else
|
382
|
-
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
383
|
-
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
384
|
-
#endif
|
385
396
|
|
386
397
|
*b-- = '\0';
|
387
398
|
if (withZone) {
|
@@ -467,7 +478,6 @@ void oj_dump_xml_time(VALUE obj, Out out) {
|
|
467
478
|
int tzhour, tzmin;
|
468
479
|
char tzsign = '+';
|
469
480
|
|
470
|
-
#ifdef HAVE_RB_TIME_TIMESPEC
|
471
481
|
if (16 <= sizeof(struct timespec)) {
|
472
482
|
struct timespec ts = rb_time_timespec(obj);
|
473
483
|
|
@@ -477,10 +487,6 @@ void oj_dump_xml_time(VALUE obj, Out out) {
|
|
477
487
|
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
478
488
|
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
479
489
|
}
|
480
|
-
#else
|
481
|
-
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
482
|
-
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
483
|
-
#endif
|
484
490
|
|
485
491
|
assure_size(out, 36);
|
486
492
|
if (9 > out->opts->sec_prec) {
|
@@ -614,7 +620,6 @@ void oj_write_obj_to_file(VALUE obj, const char *path, Options copts) {
|
|
614
620
|
|
615
621
|
oj_out_free(&out);
|
616
622
|
|
617
|
-
fclose(f);
|
618
623
|
if (!ok) {
|
619
624
|
int err = ferror(f);
|
620
625
|
fclose(f);
|
@@ -757,6 +762,11 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
757
762
|
cmap = ascii_friendly_chars;
|
758
763
|
size = ascii_friendly_size((uint8_t *)str, cnt);
|
759
764
|
break;
|
765
|
+
case SlashEsc:
|
766
|
+
has_hi = true;
|
767
|
+
cmap = slash_friendly_chars;
|
768
|
+
size = slash_friendly_size((uint8_t *)str, cnt);
|
769
|
+
break;
|
760
770
|
case XSSEsc:
|
761
771
|
cmap = xss_friendly_chars;
|
762
772
|
size = xss_friendly_size((uint8_t *)str, cnt);
|
@@ -1131,7 +1141,7 @@ void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1131
1141
|
} else if (isnan(d)) {
|
1132
1142
|
if (ObjectMode == out->opts->mode) {
|
1133
1143
|
strcpy(buf, nan_val);
|
1134
|
-
cnt = sizeof(
|
1144
|
+
cnt = sizeof(nan_val) - 1;
|
1135
1145
|
} else {
|
1136
1146
|
NanDump nd = out->opts->dump_opts.nan_dump;
|
1137
1147
|
|
data/ext/oj/dump_compat.c
CHANGED
@@ -444,7 +444,6 @@ time_alt(VALUE obj, int depth, Out out) {
|
|
444
444
|
time_t sec;
|
445
445
|
long long nsec;
|
446
446
|
|
447
|
-
#ifdef HAVE_RB_TIME_TIMESPEC
|
448
447
|
if (16 <= sizeof(struct timespec)) {
|
449
448
|
struct timespec ts = rb_time_timespec(obj);
|
450
449
|
|
@@ -454,10 +453,6 @@ time_alt(VALUE obj, int depth, Out out) {
|
|
454
453
|
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
455
454
|
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
456
455
|
}
|
457
|
-
#else
|
458
|
-
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
459
|
-
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
460
|
-
#endif
|
461
456
|
|
462
457
|
attrs[0].num = sec;
|
463
458
|
attrs[1].num = nsec;
|
data/ext/oj/dump_object.c
CHANGED
@@ -315,7 +315,6 @@ static void dump_hash_class(VALUE obj, VALUE clas, int depth, Out out) {
|
|
315
315
|
*out->cur = '\0';
|
316
316
|
}
|
317
317
|
|
318
|
-
#ifdef HAVE_RB_IVAR_FOREACH
|
319
318
|
static int dump_attr_cb(ID key, VALUE value, VALUE ov) {
|
320
319
|
Out out = (Out)ov;
|
321
320
|
int depth = out->depth;
|
@@ -358,7 +357,6 @@ static int dump_attr_cb(ID key, VALUE value, VALUE ov) {
|
|
358
357
|
|
359
358
|
return ST_CONTINUE;
|
360
359
|
}
|
361
|
-
#endif
|
362
360
|
|
363
361
|
static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
|
364
362
|
dump_hash_class(obj, rb_obj_class(obj), depth, out);
|
@@ -510,19 +508,8 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
|
|
510
508
|
default: break;
|
511
509
|
}
|
512
510
|
{
|
513
|
-
int cnt;
|
514
|
-
|
515
|
-
cnt = (int)rb_ivar_count(obj);
|
516
|
-
#else
|
517
|
-
volatile VALUE vars = rb_funcall2(obj, oj_instance_variables_id, 0, 0);
|
518
|
-
VALUE * np = RARRAY_PTR(vars);
|
519
|
-
ID vid;
|
520
|
-
const char * attr;
|
521
|
-
int i;
|
522
|
-
int first = 1;
|
523
|
-
|
524
|
-
cnt = (int)RARRAY_LEN(vars);
|
525
|
-
#endif
|
511
|
+
int cnt = (int)rb_ivar_count(obj);
|
512
|
+
|
526
513
|
if (Qundef != clas && 0 < cnt) {
|
527
514
|
*out->cur++ = ',';
|
528
515
|
}
|
@@ -535,52 +522,10 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
|
|
535
522
|
}
|
536
523
|
}
|
537
524
|
out->depth = depth + 1;
|
538
|
-
#ifdef HAVE_RB_IVAR_FOREACH
|
539
525
|
rb_ivar_foreach(obj, dump_attr_cb, (VALUE)out);
|
540
526
|
if (',' == *(out->cur - 1)) {
|
541
527
|
out->cur--; // backup to overwrite last comma
|
542
528
|
}
|
543
|
-
#else
|
544
|
-
size = d2 * out->indent + 1;
|
545
|
-
for (i = cnt; 0 < i; i--, np++) {
|
546
|
-
VALUE value;
|
547
|
-
|
548
|
-
vid = rb_to_id(*np);
|
549
|
-
attr = rb_id2name(vid);
|
550
|
-
if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
|
551
|
-
continue;
|
552
|
-
}
|
553
|
-
value = rb_ivar_get(obj, vid);
|
554
|
-
|
555
|
-
if (dump_ignore(out->opts, value)) {
|
556
|
-
continue;
|
557
|
-
}
|
558
|
-
if (out->omit_nil && Qnil == value) {
|
559
|
-
continue;
|
560
|
-
}
|
561
|
-
if (first) {
|
562
|
-
first = 0;
|
563
|
-
} else {
|
564
|
-
*out->cur++ = ',';
|
565
|
-
}
|
566
|
-
assure_size(out, size);
|
567
|
-
fill_indent(out, d2);
|
568
|
-
if ('@' == *attr) {
|
569
|
-
attr++;
|
570
|
-
oj_dump_cstr(attr, strlen(attr), 0, 0, out);
|
571
|
-
} else {
|
572
|
-
char buf[32];
|
573
|
-
|
574
|
-
*buf = '~';
|
575
|
-
strncpy(buf + 1, attr, sizeof(buf) - 2);
|
576
|
-
buf[sizeof(buf) - 1] = '\0';
|
577
|
-
oj_dump_cstr(buf, strlen(attr) + 1, 0, 0, out);
|
578
|
-
}
|
579
|
-
*out->cur++ = ':';
|
580
|
-
oj_dump_obj_val(value, d2, out);
|
581
|
-
assure_size(out, 2);
|
582
|
-
}
|
583
|
-
#endif
|
584
529
|
if (rb_obj_is_kind_of(obj, rb_eException)) {
|
585
530
|
volatile VALUE rv;
|
586
531
|
|
data/ext/oj/extconf.rb
CHANGED
@@ -23,14 +23,10 @@ dflags = {
|
|
23
23
|
'RSTRUCT_LEN_RETURNS_INTEGER_OBJECT' => ('ruby' == type && '2' == version[0] && '4' == version[1] && '1' >= version[2]) ? 1 : 0,
|
24
24
|
}
|
25
25
|
|
26
|
-
have_func('rb_time_timespec')
|
27
|
-
have_func('rb_ivar_count')
|
28
|
-
have_func('rb_ivar_foreach')
|
29
26
|
# Support for compaction.
|
30
27
|
have_func('rb_gc_mark_movable')
|
31
28
|
have_func('stpcpy')
|
32
29
|
have_func('pthread_mutex_init')
|
33
|
-
have_func('rb_enc_associate')
|
34
30
|
have_func('rb_enc_interned_str')
|
35
31
|
have_func('rb_ext_ractor_safe', 'ruby.h')
|
36
32
|
# rb_hash_bulk_insert is deep down in a header not included in normal build and that seems to fool have_func.
|
@@ -38,6 +34,11 @@ have_func('rb_hash_bulk_insert', 'ruby.h') unless '2' == version[0] && '6' == ve
|
|
38
34
|
|
39
35
|
dflags['OJ_DEBUG'] = true unless ENV['OJ_DEBUG'].nil?
|
40
36
|
|
37
|
+
if try_cflags('-msse4.2')
|
38
|
+
$CPPFLAGS += ' -msse4.2'
|
39
|
+
dflags['OJ_USE_SSE4_2'] = 1
|
40
|
+
end
|
41
|
+
|
41
42
|
dflags.each do |k,v|
|
42
43
|
if v.nil?
|
43
44
|
$CPPFLAGS += " -D#{k}"
|
data/ext/oj/mimic_json.c
CHANGED
@@ -388,6 +388,10 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
|
388
388
|
VALUE active_hack[1];
|
389
389
|
|
390
390
|
if (Qundef == state_class) {
|
391
|
+
rb_warn(
|
392
|
+
"Oj::Rails.mimic_JSON was called implicitly. "
|
393
|
+
"Call it explicitly beforehand if you want to remove this warning."
|
394
|
+
);
|
391
395
|
oj_define_mimic_json(0, NULL, Qnil);
|
392
396
|
}
|
393
397
|
active_hack[0] = rb_funcall(state_class, oj_new_id, 0);
|
@@ -460,7 +464,7 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
|
|
460
464
|
if (0 == argc) {
|
461
465
|
rb_raise(rb_eArgError, "wrong number of arguments (0))");
|
462
466
|
}
|
463
|
-
if (1 == argc) {
|
467
|
+
if (1 == argc || Qnil == argv[1]) {
|
464
468
|
h = rb_hash_new();
|
465
469
|
} else {
|
466
470
|
h = argv[1];
|
@@ -481,6 +485,10 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
|
|
481
485
|
rb_hash_aset(h, oj_array_nl_sym, rb_str_new2("\n"));
|
482
486
|
}
|
483
487
|
if (Qundef == state_class) {
|
488
|
+
rb_warn(
|
489
|
+
"Oj::Rails.mimic_JSON was called implicitly. "
|
490
|
+
"Call it explicitly beforehand if you want to remove this warning."
|
491
|
+
);
|
484
492
|
oj_define_mimic_json(0, NULL, Qnil);
|
485
493
|
}
|
486
494
|
rargs[1] = rb_funcall(state_class, oj_new_id, 1, h);
|
@@ -536,14 +544,6 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE info) {
|
|
536
544
|
}
|
537
545
|
} else if (oj_decimal_class_sym == k) {
|
538
546
|
pi->options.compat_bigdec = (oj_bigdecimal_class == v);
|
539
|
-
} else if (oj_max_nesting_sym == k) {
|
540
|
-
if (Qtrue == v) {
|
541
|
-
pi->max_depth = 100;
|
542
|
-
} else if (Qfalse == v || Qnil == v) {
|
543
|
-
pi->max_depth = 0;
|
544
|
-
} else if (T_FIXNUM == rb_type(v)) {
|
545
|
-
pi->max_depth = NUM2INT(v);
|
546
|
-
}
|
547
547
|
}
|
548
548
|
return ST_CONTINUE;
|
549
549
|
}
|
@@ -573,11 +573,21 @@ static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
|
|
573
573
|
pi.max_depth = 100;
|
574
574
|
|
575
575
|
if (Qnil != ropts) {
|
576
|
+
VALUE v;
|
577
|
+
|
576
578
|
if (T_HASH != rb_type(ropts)) {
|
577
579
|
rb_raise(rb_eArgError, "options must be a hash.");
|
578
580
|
}
|
579
581
|
|
580
582
|
rb_hash_foreach(ropts, parse_options_cb, (VALUE)&pi);
|
583
|
+
v = rb_hash_lookup(ropts, oj_max_nesting_sym);
|
584
|
+
if (Qtrue == v) {
|
585
|
+
pi.max_depth = 100;
|
586
|
+
} else if (Qfalse == v || Qnil == v) {
|
587
|
+
pi.max_depth = 0;
|
588
|
+
} else if (T_FIXNUM == rb_type(v)) {
|
589
|
+
pi.max_depth = NUM2INT(v);
|
590
|
+
}
|
581
591
|
oj_parse_opt_match_string(&pi.options.str_rx, ropts);
|
582
592
|
if (Yes == pi.options.create_ok && Yes == pi.options.sym_key) {
|
583
593
|
rb_raise(rb_eArgError, ":symbolize_names and :create_additions can not both be true.");
|
data/ext/oj/object.c
CHANGED
@@ -445,7 +445,7 @@ WHICH_TYPE:
|
|
445
445
|
rb_class2name(rb_obj_class(parent->val)));
|
446
446
|
return;
|
447
447
|
}
|
448
|
-
if (Yes == pi->options.trace) {
|
448
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
449
449
|
oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
|
450
450
|
}
|
451
451
|
}
|
@@ -516,7 +516,7 @@ WHICH_TYPE:
|
|
516
516
|
rb_class2name(rb_obj_class(parent->val)));
|
517
517
|
return;
|
518
518
|
}
|
519
|
-
if (Yes == pi->options.trace) {
|
519
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
520
520
|
oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, rval);
|
521
521
|
}
|
522
522
|
}
|
@@ -602,13 +602,13 @@ WHICH_TYPE:
|
|
602
602
|
rb_class2name(rb_obj_class(parent->val)));
|
603
603
|
return;
|
604
604
|
}
|
605
|
-
if (Yes == pi->options.trace) {
|
605
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
606
606
|
oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, value);
|
607
607
|
}
|
608
608
|
}
|
609
609
|
|
610
610
|
static VALUE start_hash(ParseInfo pi) {
|
611
|
-
if (Yes == pi->options.trace) {
|
611
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
612
612
|
oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
|
613
613
|
}
|
614
614
|
return Qnil;
|
@@ -626,7 +626,7 @@ static void end_hash(ParseInfo pi) {
|
|
626
626
|
oj_odd_free(oa);
|
627
627
|
parent->odd_args = NULL;
|
628
628
|
}
|
629
|
-
if (Yes == pi->options.trace) {
|
629
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
630
630
|
oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
|
631
631
|
}
|
632
632
|
}
|
@@ -654,7 +654,7 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
|
|
654
654
|
}
|
655
655
|
rval = str_to_value(pi, str, len, orig);
|
656
656
|
rb_ary_push(stack_peek(&pi->stack)->val, rval);
|
657
|
-
if (Yes == pi->options.trace) {
|
657
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
658
658
|
oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rval);
|
659
659
|
}
|
660
660
|
}
|
@@ -663,21 +663,21 @@ static void array_append_num(ParseInfo pi, NumInfo ni) {
|
|
663
663
|
volatile VALUE rval = oj_num_as_value(ni);
|
664
664
|
|
665
665
|
rb_ary_push(stack_peek(&pi->stack)->val, rval);
|
666
|
-
if (Yes == pi->options.trace) {
|
666
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
667
667
|
oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
|
668
668
|
}
|
669
669
|
}
|
670
670
|
|
671
671
|
static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
672
672
|
pi->stack.head->val = str_to_value(pi, str, len, orig);
|
673
|
-
if (Yes == pi->options.trace) {
|
673
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
674
674
|
oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, pi->stack.head->val);
|
675
675
|
}
|
676
676
|
}
|
677
677
|
|
678
678
|
static void add_num(ParseInfo pi, NumInfo ni) {
|
679
679
|
pi->stack.head->val = oj_num_as_value(ni);
|
680
|
-
if (Yes == pi->options.trace) {
|
680
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
681
681
|
oj_trace_parse_call("add_num", pi, __FILE__, __LINE__, pi->stack.head->val);
|
682
682
|
}
|
683
683
|
}
|
data/ext/oj/oj.c
CHANGED
@@ -45,7 +45,6 @@ ID oj_hash_key_id;
|
|
45
45
|
ID oj_hash_set_id;
|
46
46
|
ID oj_hash_start_id;
|
47
47
|
ID oj_iconv_id;
|
48
|
-
ID oj_instance_variables_id;
|
49
48
|
ID oj_json_create_id;
|
50
49
|
ID oj_length_id;
|
51
50
|
ID oj_new_id;
|
@@ -137,6 +136,7 @@ static VALUE rails_sym;
|
|
137
136
|
static VALUE raise_sym;
|
138
137
|
static VALUE ruby_sym;
|
139
138
|
static VALUE sec_prec_sym;
|
139
|
+
static VALUE slash_sym;
|
140
140
|
static VALUE strict_sym;
|
141
141
|
static VALUE symbol_keys_sym;
|
142
142
|
static VALUE time_format_sym;
|
@@ -405,6 +405,7 @@ static VALUE get_def_opts(VALUE self) {
|
|
405
405
|
switch (oj_default_options.escape_mode) {
|
406
406
|
case NLEsc: rb_hash_aset(opts, escape_mode_sym, newline_sym); break;
|
407
407
|
case JSONEsc: rb_hash_aset(opts, escape_mode_sym, json_sym); break;
|
408
|
+
case SlashEsc: rb_hash_aset(opts, escape_mode_sym, slash_sym); break;
|
408
409
|
case XSSEsc: rb_hash_aset(opts, escape_mode_sym, xss_safe_sym); break;
|
409
410
|
case ASCIIEsc: rb_hash_aset(opts, escape_mode_sym, ascii_sym); break;
|
410
411
|
case JXEsc: rb_hash_aset(opts, escape_mode_sym, unicode_xss_sym); break;
|
@@ -734,6 +735,8 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
|
|
734
735
|
copts->escape_mode = NLEsc;
|
735
736
|
} else if (json_sym == v) {
|
736
737
|
copts->escape_mode = JSONEsc;
|
738
|
+
} else if (slash_sym == v) {
|
739
|
+
copts->escape_mode = SlashEsc;
|
737
740
|
} else if (xss_safe_sym == v) {
|
738
741
|
copts->escape_mode = XSSEsc;
|
739
742
|
} else if (ascii_sym == v) {
|
@@ -1148,7 +1151,17 @@ static VALUE load_file(int argc, VALUE *argv, VALUE self) {
|
|
1148
1151
|
}
|
1149
1152
|
}
|
1150
1153
|
path = StringValuePtr(*argv);
|
1151
|
-
|
1154
|
+
#ifdef _WIN32
|
1155
|
+
{
|
1156
|
+
WCHAR *wide_path;
|
1157
|
+
wide_path = rb_w32_mbstr_to_wstr(CP_UTF8, path, -1, NULL);
|
1158
|
+
fd = rb_w32_wopen(wide_path, O_RDONLY);
|
1159
|
+
free(wide_path);
|
1160
|
+
}
|
1161
|
+
#else
|
1162
|
+
fd = open(path, O_RDONLY);
|
1163
|
+
#endif
|
1164
|
+
if (0 == fd) {
|
1152
1165
|
rb_raise(rb_eIOError, "%s", strerror(errno));
|
1153
1166
|
}
|
1154
1167
|
switch (mode) {
|
@@ -1814,7 +1827,6 @@ void Init_oj(void) {
|
|
1814
1827
|
oj_hash_set_id = rb_intern("hash_set");
|
1815
1828
|
oj_hash_start_id = rb_intern("hash_start");
|
1816
1829
|
oj_iconv_id = rb_intern("iconv");
|
1817
|
-
oj_instance_variables_id = rb_intern("instance_variables");
|
1818
1830
|
oj_json_create_id = rb_intern("json_create");
|
1819
1831
|
oj_length_id = rb_intern("length");
|
1820
1832
|
oj_new_id = rb_intern("new");
|
@@ -1977,6 +1989,8 @@ void Init_oj(void) {
|
|
1977
1989
|
rb_gc_register_address(&ruby_sym);
|
1978
1990
|
sec_prec_sym = ID2SYM(rb_intern("second_precision"));
|
1979
1991
|
rb_gc_register_address(&sec_prec_sym);
|
1992
|
+
slash_sym = ID2SYM(rb_intern("slash"));
|
1993
|
+
rb_gc_register_address(&slash_sym);
|
1980
1994
|
strict_sym = ID2SYM(rb_intern("strict"));
|
1981
1995
|
rb_gc_register_address(&strict_sym);
|
1982
1996
|
symbol_keys_sym = ID2SYM(rb_intern("symbol_keys"));
|
data/ext/oj/oj.h
CHANGED
@@ -66,6 +66,7 @@ typedef enum { UnixTime = 'u', UnixZTime = 'z', XmlTime = 'x', RubyTime = 'r' }
|
|
66
66
|
typedef enum {
|
67
67
|
NLEsc = 'n',
|
68
68
|
JSONEsc = 'j',
|
69
|
+
SlashEsc = 's',
|
69
70
|
XSSEsc = 'x',
|
70
71
|
ASCIIEsc = 'a',
|
71
72
|
JXEsc = 'g', // json gem
|
@@ -346,7 +347,6 @@ extern ID oj_hash_key_id;
|
|
346
347
|
extern ID oj_hash_set_id;
|
347
348
|
extern ID oj_hash_start_id;
|
348
349
|
extern ID oj_iconv_id;
|
349
|
-
extern ID oj_instance_variables_id;
|
350
350
|
extern ID oj_json_create_id;
|
351
351
|
extern ID oj_length_id;
|
352
352
|
extern ID oj_new_id;
|