oj 3.13.14 → 3.13.22
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 +32 -0
- data/README.md +2 -0
- data/ext/oj/buf.h +4 -0
- data/ext/oj/compat.c +10 -10
- data/ext/oj/custom.c +34 -53
- data/ext/oj/dump.c +24 -13
- data/ext/oj/dump_compat.c +5 -10
- data/ext/oj/dump_object.c +5 -60
- data/ext/oj/dump_strict.c +5 -5
- data/ext/oj/extconf.rb +5 -4
- data/ext/oj/fast.c +15 -13
- data/ext/oj/intern.c +6 -9
- data/ext/oj/introspect.c +96 -0
- data/ext/oj/mimic_json.c +18 -8
- data/ext/oj/object.c +42 -41
- data/ext/oj/oj.c +27 -4
- data/ext/oj/oj.h +4 -1
- data/ext/oj/parse.c +111 -76
- data/ext/oj/parse.h +2 -0
- data/ext/oj/parser.c +61 -4
- data/ext/oj/parser.h +12 -0
- data/ext/oj/rails.c +5 -10
- data/ext/oj/saj2.c +333 -85
- data/ext/oj/saj2.h +23 -0
- data/ext/oj/sparse.c +4 -0
- data/ext/oj/strict.c +13 -13
- data/ext/oj/usual.c +82 -129
- data/ext/oj/usual.h +68 -0
- data/ext/oj/val_stack.c +1 -1
- data/ext/oj/validate.c +21 -26
- data/ext/oj/wab.c +15 -20
- data/lib/oj/saj.rb +20 -6
- data/lib/oj/state.rb +1 -1
- data/lib/oj/version.rb +1 -1
- data/pages/Compatibility.md +1 -1
- data/test/bar.rb +3 -1
- data/test/helper.rb +8 -2
- data/test/json_gem/json_generator_test.rb +3 -4
- data/test/json_gem/json_parser_test.rb +8 -1
- data/test/json_gem/test_helper.rb +7 -3
- data/test/test_compat.rb +25 -0
- data/test/test_custom.rb +13 -2
- data/test/test_file.rb +23 -7
- data/test/test_gc.rb +11 -0
- data/test/test_object.rb +3 -10
- data/test/test_parser.rb +3 -19
- data/test/test_parser_debug.rb +27 -0
- data/test/test_parser_saj.rb +92 -2
- data/test/test_scp.rb +2 -4
- data/test/test_strict.rb +2 -0
- data/test/test_various.rb +8 -3
- data/test/test_wab.rb +2 -0
- data/test/tests.rb +9 -0
- data/test/tests_mimic.rb +9 -0
- data/test/tests_mimic_addition.rb +9 -0
- metadata +7 -107
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d90ba7b2698041767008afd20cef0dbd6ba1af0d97affa2253b12e199e6c528d
|
4
|
+
data.tar.gz: f9a8219f0b6f66ef0608136068d78cbc6c8b1ee765bfaa68eeb828cae1401fd8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e72d7030911b6609946437de78aaf4fa9003a598c77dca472c2998f9af6115436e817fb4c46ec0ead55cb1ccb0ba80298c2ab060fab9fe37d0ec825d0ec6e5e4
|
7
|
+
data.tar.gz: 4aacdb9f034a2548a3eb942b4a29fb66a9839a63770bd10d0b8b62d93d944070d78ee53ca26881f05108047cc9c120efb3a732048b0be51a608f144f2ad0a374
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,37 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 3.13.22 - 2022-11-01
|
4
|
+
|
5
|
+
- Reorganized Oj::Parser code to allow for parser extensions in C.
|
6
|
+
|
7
|
+
## 3.13.21 - 2022-08-19
|
8
|
+
|
9
|
+
- Bug parsing big numbers fixed in the SAJ parser.
|
10
|
+
|
11
|
+
## 3.13.20 - 2022-08-07
|
12
|
+
|
13
|
+
- SSE4 made optional with a `--with-sse42` flag to the compile.
|
14
|
+
|
15
|
+
## 3.13.19 - 2022-07-29
|
16
|
+
|
17
|
+
- TruffleRuby issues resolved.
|
18
|
+
|
19
|
+
## 3.13.18 - 2022-07-25
|
20
|
+
|
21
|
+
- Fixed SSE detection at run time.
|
22
|
+
|
23
|
+
## 3.13.17 - 2022-07-15
|
24
|
+
|
25
|
+
- Fixed Oj::Parser to detect unterminated arrays and objects.
|
26
|
+
|
27
|
+
## 3.13.16 - 2022-07-06
|
28
|
+
|
29
|
+
- Added line and column as optional arguments to the Oj::Parser.saj parser.
|
30
|
+
|
31
|
+
## 3.13.15 - 2022-07-03
|
32
|
+
|
33
|
+
- Fixed issue dumping NaN value in object mode.
|
34
|
+
|
3
35
|
## 3.13.14 - 2022-06-03
|
4
36
|
|
5
37
|
- Double fclose() due to bad merger fixed by tonobo.
|
data/README.md
CHANGED
@@ -109,6 +109,8 @@ Follow [@peterohler on Twitter](http://twitter.com/peterohler) for announcements
|
|
109
109
|
|
110
110
|
- *Agoo-C, a high performance C web server supporting GraphQL on GitHub*: https://github.com/ohler55/agoo-c
|
111
111
|
|
112
|
+
- *oj-introspect, an example of creating an Oj parser extension in C*: https://github.com/meinac/oj-introspect
|
113
|
+
|
112
114
|
#### Contributing
|
113
115
|
|
114
116
|
+ Provide a Pull Request off the `develop` branch.
|
data/ext/oj/buf.h
CHANGED
@@ -39,6 +39,10 @@ inline static const char *buf_str(Buf buf) {
|
|
39
39
|
}
|
40
40
|
|
41
41
|
inline static void buf_append_string(Buf buf, const char *s, size_t slen) {
|
42
|
+
if (0 == slen) {
|
43
|
+
return;
|
44
|
+
}
|
45
|
+
|
42
46
|
if (buf->end <= buf->tail + slen) {
|
43
47
|
size_t len = buf->end - buf->head;
|
44
48
|
size_t toff = buf->tail - buf->head;
|
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
@@ -31,14 +31,14 @@ static void dump_obj_str(VALUE obj, int depth, Out out) {
|
|
31
31
|
|
32
32
|
static void dump_obj_as_str(VALUE obj, int depth, Out out) {
|
33
33
|
volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
|
34
|
-
const char
|
34
|
+
const char *str = RSTRING_PTR(rstr);
|
35
35
|
|
36
36
|
oj_dump_cstr(str, RSTRING_LEN(rstr), 0, 0, out);
|
37
37
|
}
|
38
38
|
|
39
39
|
static void bigdecimal_dump(VALUE obj, int depth, Out out) {
|
40
40
|
volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
|
41
|
-
const char
|
41
|
+
const char *str = RSTRING_PTR(rstr);
|
42
42
|
int len = (int)RSTRING_LEN(rstr);
|
43
43
|
|
44
44
|
if (0 == strcasecmp("Infinity", str)) {
|
@@ -82,8 +82,7 @@ static VALUE complex_load(VALUE clas, VALUE args) {
|
|
82
82
|
real_id = rb_intern("real");
|
83
83
|
imag_id = rb_intern("imag");
|
84
84
|
}
|
85
|
-
return rb_complex_new(rb_hash_aref(args, rb_id2str(real_id)),
|
86
|
-
rb_hash_aref(args, rb_id2str(imag_id)));
|
85
|
+
return rb_complex_new(rb_hash_aref(args, rb_id2str(real_id)), rb_hash_aref(args, rb_id2str(imag_id)));
|
87
86
|
}
|
88
87
|
|
89
88
|
static void time_dump(VALUE obj, int depth, Out out) {
|
@@ -246,8 +245,7 @@ static VALUE rational_load(VALUE clas, VALUE args) {
|
|
246
245
|
numerator_id = rb_intern("numerator");
|
247
246
|
denominator_id = rb_intern("denominator");
|
248
247
|
}
|
249
|
-
return rb_rational_new(rb_hash_aref(args, rb_id2str(numerator_id)),
|
250
|
-
rb_hash_aref(args, rb_id2str(denominator_id)));
|
248
|
+
return rb_rational_new(rb_hash_aref(args, rb_id2str(numerator_id)), rb_hash_aref(args, rb_id2str(denominator_id)));
|
251
249
|
}
|
252
250
|
|
253
251
|
static VALUE regexp_load(VALUE clas, VALUE args) {
|
@@ -292,8 +290,7 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
292
290
|
assure_size(out, depth * out->indent + 1);
|
293
291
|
fill_indent(out, depth);
|
294
292
|
} else {
|
295
|
-
assure_size(out,
|
296
|
-
depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1);
|
293
|
+
assure_size(out, depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1);
|
297
294
|
if (0 < out->opts->dump_opts.hash_size) {
|
298
295
|
APPEND_CHARS(out->cur, out->opts->dump_opts.hash_nl, out->opts->dump_opts.hash_size);
|
299
296
|
}
|
@@ -352,9 +349,7 @@ static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
|
|
352
349
|
assure_size(out, depth * out->indent + 2);
|
353
350
|
fill_indent(out, depth);
|
354
351
|
} else {
|
355
|
-
assure_size(
|
356
|
-
out,
|
357
|
-
depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1);
|
352
|
+
assure_size(out, depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1);
|
358
353
|
if (0 < out->opts->dump_opts.hash_size) {
|
359
354
|
APPEND_CHARS(out->cur, out->opts->dump_opts.hash_nl, out->opts->dump_opts.hash_size);
|
360
355
|
}
|
@@ -372,10 +367,10 @@ static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
|
|
372
367
|
}
|
373
368
|
|
374
369
|
static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
|
375
|
-
ID
|
376
|
-
AttrGetFunc
|
370
|
+
ID *idp;
|
371
|
+
AttrGetFunc *fp;
|
377
372
|
volatile VALUE v;
|
378
|
-
const char
|
373
|
+
const char *name;
|
379
374
|
size_t size;
|
380
375
|
int d2 = depth + 1;
|
381
376
|
|
@@ -384,7 +379,7 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
|
|
384
379
|
if (NULL != out->opts->create_id && Yes == out->opts->create_ok) {
|
385
380
|
const char *classname = rb_class2name(clas);
|
386
381
|
int clen = (int)strlen(classname);
|
387
|
-
size_t
|
382
|
+
size_t sep_len = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
|
388
383
|
|
389
384
|
size = d2 * out->indent + 10 + clen + out->opts->create_id_len + sep_len;
|
390
385
|
assure_size(out, size);
|
@@ -481,10 +476,10 @@ static VALUE dump_common(VALUE obj, int depth, Out out) {
|
|
481
476
|
oj_dump_raw_json(obj, depth, out);
|
482
477
|
} else if (Yes == out->opts->to_json && rb_respond_to(obj, oj_to_json_id)) {
|
483
478
|
volatile VALUE rs;
|
484
|
-
const char
|
479
|
+
const char *s;
|
485
480
|
int len;
|
486
481
|
|
487
|
-
if (Yes == out->opts->trace) {
|
482
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
488
483
|
oj_trace("to_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyIn);
|
489
484
|
}
|
490
485
|
if (0 == rb_obj_method_arity(obj, oj_to_json_id)) {
|
@@ -492,7 +487,7 @@ static VALUE dump_common(VALUE obj, int depth, Out out) {
|
|
492
487
|
} else {
|
493
488
|
rs = rb_funcall2(obj, oj_to_json_id, out->argc, out->argv);
|
494
489
|
}
|
495
|
-
if (Yes == out->opts->trace) {
|
490
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
496
491
|
oj_trace("to_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyOut);
|
497
492
|
}
|
498
493
|
s = RSTRING_PTR(rs);
|
@@ -504,7 +499,7 @@ static VALUE dump_common(VALUE obj, int depth, Out out) {
|
|
504
499
|
} else if (Yes == out->opts->as_json && rb_respond_to(obj, oj_as_json_id)) {
|
505
500
|
volatile VALUE aj;
|
506
501
|
|
507
|
-
if (Yes == out->opts->trace) {
|
502
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
508
503
|
oj_trace("as_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyIn);
|
509
504
|
}
|
510
505
|
// Some classes elect to not take an options argument so check the arity
|
@@ -514,18 +509,14 @@ static VALUE dump_common(VALUE obj, int depth, Out out) {
|
|
514
509
|
} else {
|
515
510
|
aj = rb_funcall2(obj, oj_as_json_id, out->argc, out->argv);
|
516
511
|
}
|
517
|
-
if (Yes == out->opts->trace) {
|
512
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
518
513
|
oj_trace("as_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyOut);
|
519
514
|
}
|
520
515
|
// Catch the obvious brain damaged recursive dumping.
|
521
516
|
if (aj == obj) {
|
522
517
|
volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
|
523
518
|
|
524
|
-
oj_dump_cstr(RSTRING_PTR(rstr),
|
525
|
-
(int)RSTRING_LEN(rstr),
|
526
|
-
false,
|
527
|
-
false,
|
528
|
-
out);
|
519
|
+
oj_dump_cstr(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), false, false, out);
|
529
520
|
} else {
|
530
521
|
oj_dump_custom_val(aj, depth, out, true);
|
531
522
|
}
|
@@ -609,7 +600,7 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
|
|
609
600
|
assure_size(out, 2);
|
610
601
|
*out->cur++ = '{';
|
611
602
|
if (Qundef != clas && NULL != out->opts->create_id && Yes == out->opts->create_ok) {
|
612
|
-
size_t
|
603
|
+
size_t sep_len = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
|
613
604
|
const char *classname = rb_obj_classname(obj);
|
614
605
|
size_t len = strlen(classname);
|
615
606
|
|
@@ -885,7 +876,7 @@ static DumpFunc custom_funcs[] = {
|
|
885
876
|
void oj_dump_custom_val(VALUE obj, int depth, Out out, bool as_ok) {
|
886
877
|
int type = rb_type(obj);
|
887
878
|
|
888
|
-
if (Yes == out->opts->trace) {
|
879
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
889
880
|
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
|
890
881
|
}
|
891
882
|
if (MAX_DEPTH < depth) {
|
@@ -896,14 +887,14 @@ void oj_dump_custom_val(VALUE obj, int depth, Out out, bool as_ok) {
|
|
896
887
|
|
897
888
|
if (NULL != f) {
|
898
889
|
f(obj, depth, out, true);
|
899
|
-
if (Yes == out->opts->trace) {
|
890
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
900
891
|
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
|
901
892
|
}
|
902
893
|
return;
|
903
894
|
}
|
904
895
|
}
|
905
896
|
oj_dump_nil(Qnil, depth, out, false);
|
906
|
-
if (Yes == out->opts->trace) {
|
897
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
907
898
|
oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
|
908
899
|
}
|
909
900
|
}
|
@@ -911,7 +902,7 @@ void oj_dump_custom_val(VALUE obj, int depth, Out out, bool as_ok) {
|
|
911
902
|
///// load functions /////
|
912
903
|
|
913
904
|
static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
|
914
|
-
const char
|
905
|
+
const char *key = kval->key;
|
915
906
|
int klen = kval->klen;
|
916
907
|
Val parent = stack_peek(&pi->stack);
|
917
908
|
volatile VALUE rkey = kval->key_val;
|
@@ -928,14 +919,14 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c
|
|
928
919
|
}
|
929
920
|
}
|
930
921
|
} else {
|
931
|
-
|
932
|
-
//volatile VALUE rstr = rb_utf8_str_new(str, len);
|
922
|
+
volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
|
923
|
+
// volatile VALUE rstr = rb_utf8_str_new(str, len);
|
933
924
|
|
934
925
|
if (Qundef == rkey) {
|
935
926
|
if (Yes == pi->options.sym_key) {
|
936
927
|
rkey = ID2SYM(rb_intern3(key, klen, oj_utf8_encoding));
|
937
928
|
} else {
|
938
|
-
|
929
|
+
rkey = rb_utf8_str_new(key, klen);
|
939
930
|
}
|
940
931
|
}
|
941
932
|
if (Yes == pi->options.create_ok && NULL != pi->options.str_rx.head) {
|
@@ -959,7 +950,7 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c
|
|
959
950
|
break;
|
960
951
|
default: break;
|
961
952
|
}
|
962
|
-
if (Yes == pi->options.trace) {
|
953
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
963
954
|
oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
|
964
955
|
}
|
965
956
|
}
|
@@ -978,7 +969,7 @@ static void end_hash(struct _parseInfo *pi) {
|
|
978
969
|
}
|
979
970
|
parent->clas = Qundef;
|
980
971
|
}
|
981
|
-
if (Yes == pi->options.trace) {
|
972
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
982
973
|
oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
|
983
974
|
}
|
984
975
|
}
|
@@ -1008,20 +999,10 @@ static void hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) {
|
|
1008
999
|
// match the expected value.
|
1009
1000
|
parent->val = rb_funcall2(parent->val, oj_utc_id, 0, 0);
|
1010
1001
|
} else if (ni->has_exp) {
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
sec_as_time(t, &ti);
|
1016
|
-
|
1017
|
-
args[0] = LONG2NUM(ti.year);
|
1018
|
-
args[1] = LONG2NUM(ti.mon);
|
1019
|
-
args[2] = LONG2NUM(ti.day);
|
1020
|
-
args[3] = LONG2NUM(ti.hour);
|
1021
|
-
args[4] = LONG2NUM(ti.min);
|
1022
|
-
args[5] = rb_float_new((double)ti.sec + ((double)nsec + 0.5) / 1000000000.0);
|
1023
|
-
args[6] = LONG2NUM(ni->exp);
|
1024
|
-
parent->val = rb_funcall2(rb_cTime, oj_new_id, 7, args);
|
1002
|
+
struct timespec ts;
|
1003
|
+
ts.tv_sec = ni->i;
|
1004
|
+
ts.tv_nsec = nsec;
|
1005
|
+
parent->val = rb_time_timespec_new(&ts, (int)ni->exp);
|
1025
1006
|
} else {
|
1026
1007
|
parent->val = rb_time_nano_new(ni->i, (long)nsec);
|
1027
1008
|
}
|
@@ -1032,7 +1013,7 @@ static void hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) {
|
|
1032
1013
|
break;
|
1033
1014
|
default: break;
|
1034
1015
|
}
|
1035
|
-
if (Yes == pi->options.trace) {
|
1016
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
1036
1017
|
oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
|
1037
1018
|
}
|
1038
1019
|
}
|
@@ -1045,7 +1026,7 @@ static void hash_set_value(ParseInfo pi, Val kval, VALUE value) {
|
|
1045
1026
|
case T_HASH: rb_hash_aset(parent->val, oj_calc_hash_key(pi, kval), value); break;
|
1046
1027
|
default: break;
|
1047
1028
|
}
|
1048
|
-
if (Yes == pi->options.trace) {
|
1029
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
1049
1030
|
oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
|
1050
1031
|
}
|
1051
1032
|
}
|
@@ -1055,7 +1036,7 @@ static void array_append_num(ParseInfo pi, NumInfo ni) {
|
|
1055
1036
|
volatile VALUE rval = oj_num_as_value(ni);
|
1056
1037
|
|
1057
1038
|
rb_ary_push(parent->val, rval);
|
1058
|
-
if (Yes == pi->options.trace) {
|
1039
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
1059
1040
|
oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
|
1060
1041
|
}
|
1061
1042
|
}
|
@@ -1072,7 +1053,7 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
|
|
1072
1053
|
}
|
1073
1054
|
}
|
1074
1055
|
rb_ary_push(stack_peek(&pi->stack)->val, rstr);
|
1075
|
-
if (Yes == pi->options.trace) {
|
1056
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
1076
1057
|
oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
|
1077
1058
|
}
|
1078
1059
|
}
|
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) {
|
@@ -730,11 +736,11 @@ void oj_dump_raw_json(VALUE obj, int depth, Out out) {
|
|
730
736
|
} else {
|
731
737
|
volatile VALUE jv;
|
732
738
|
|
733
|
-
if (Yes == out->opts->trace) {
|
739
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
734
740
|
oj_trace("raw_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyIn);
|
735
741
|
}
|
736
742
|
jv = rb_funcall(obj, oj_raw_json_id, 2, RB_INT2NUM(depth), RB_INT2NUM(out->indent));
|
737
|
-
if (Yes == out->opts->trace) {
|
743
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
738
744
|
oj_trace("raw_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyOut);
|
739
745
|
}
|
740
746
|
oj_dump_raw(RSTRING_PTR(jv), (size_t)RSTRING_LEN(jv), out);
|
@@ -756,6 +762,11 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
756
762
|
cmap = ascii_friendly_chars;
|
757
763
|
size = ascii_friendly_size((uint8_t *)str, cnt);
|
758
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;
|
759
770
|
case XSSEsc:
|
760
771
|
cmap = xss_friendly_chars;
|
761
772
|
size = xss_friendly_size((uint8_t *)str, cnt);
|
@@ -1130,7 +1141,7 @@ void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1130
1141
|
} else if (isnan(d)) {
|
1131
1142
|
if (ObjectMode == out->opts->mode) {
|
1132
1143
|
strcpy(buf, nan_val);
|
1133
|
-
cnt = sizeof(
|
1144
|
+
cnt = sizeof(nan_val) - 1;
|
1134
1145
|
} else {
|
1135
1146
|
NanDump nd = out->opts->dump_opts.nan_dump;
|
1136
1147
|
|
data/ext/oj/dump_compat.c
CHANGED
@@ -109,7 +109,7 @@ dump_to_json(VALUE obj, Out out) {
|
|
109
109
|
const char *s;
|
110
110
|
int len;
|
111
111
|
|
112
|
-
if (Yes == out->opts->trace) {
|
112
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
113
113
|
oj_trace("to_json", obj, __FILE__, __LINE__, 0, TraceRubyIn);
|
114
114
|
}
|
115
115
|
if (0 == rb_obj_method_arity(obj, oj_to_json_id)) {
|
@@ -117,7 +117,7 @@ dump_to_json(VALUE obj, Out out) {
|
|
117
117
|
} else {
|
118
118
|
rs = rb_funcall2(obj, oj_to_json_id, out->argc, out->argv);
|
119
119
|
}
|
120
|
-
if (Yes == out->opts->trace) {
|
120
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
121
121
|
oj_trace("to_json", obj, __FILE__, __LINE__, 0, TraceRubyOut);
|
122
122
|
}
|
123
123
|
|
@@ -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;
|
@@ -898,7 +893,7 @@ void
|
|
898
893
|
oj_dump_compat_val(VALUE obj, int depth, Out out, bool as_ok) {
|
899
894
|
int type = rb_type(obj);
|
900
895
|
|
901
|
-
if (Yes == out->opts->trace) {
|
896
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
902
897
|
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
|
903
898
|
}
|
904
899
|
if (out->opts->dump_opts.max_depth <= depth) {
|
@@ -923,14 +918,14 @@ oj_dump_compat_val(VALUE obj, int depth, Out out, bool as_ok) {
|
|
923
918
|
|
924
919
|
if (NULL != f) {
|
925
920
|
f(obj, depth, out, as_ok);
|
926
|
-
if (Yes == out->opts->trace) {
|
921
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
927
922
|
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
|
928
923
|
}
|
929
924
|
return;
|
930
925
|
}
|
931
926
|
}
|
932
927
|
oj_dump_nil(Qnil, depth, out, false);
|
933
|
-
if (Yes == out->opts->trace) {
|
928
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
934
929
|
oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
|
935
930
|
}
|
936
931
|
}
|