oj 3.13.14 → 3.13.22
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
}
|