oj 3.16.0 → 3.17.3
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 +107 -0
- data/README.md +0 -16
- data/ext/oj/cache.c +4 -2
- data/ext/oj/cache.h +3 -2
- data/ext/oj/compat.c +3 -3
- data/ext/oj/custom.c +17 -11
- data/ext/oj/dump.c +624 -90
- data/ext/oj/dump.h +9 -2
- data/ext/oj/dump_compat.c +15 -9
- data/ext/oj/dump_leaf.c +1 -1
- data/ext/oj/dump_object.c +32 -17
- data/ext/oj/dump_strict.c +20 -14
- data/ext/oj/extconf.rb +11 -9
- data/ext/oj/fast.c +50 -32
- data/ext/oj/intern.c +24 -7
- data/ext/oj/mimic_json.c +17 -11
- data/ext/oj/object.c +21 -13
- data/ext/oj/oj.c +387 -140
- data/ext/oj/oj.h +59 -55
- data/ext/oj/parse.c +248 -47
- data/ext/oj/parser.c +179 -89
- data/ext/oj/parser.h +4 -2
- data/ext/oj/rails.c +64 -42
- data/ext/oj/reader.c +1 -1
- data/ext/oj/rxclass.c +1 -1
- data/ext/oj/rxclass.h +1 -1
- data/ext/oj/safe.c +230 -0
- data/ext/oj/safe.h +79 -0
- data/ext/oj/saj.c +15 -10
- data/ext/oj/scp.c +3 -6
- data/ext/oj/simd.h +219 -0
- data/ext/oj/sparse.c +6 -3
- data/ext/oj/stream_writer.c +38 -28
- data/ext/oj/strict.c +2 -4
- data/ext/oj/string_writer.c +54 -22
- data/ext/oj/usual.c +57 -35
- data/ext/oj/usual.h +1 -0
- data/ext/oj/val_stack.c +13 -2
- data/ext/oj/wab.c +5 -4
- data/lib/oj/mimic.rb +1 -5
- data/lib/oj/schandler.rb +5 -4
- data/lib/oj/version.rb +1 -1
- data/pages/Encoding.md +1 -1
- metadata +36 -100
- data/test/_test_active.rb +0 -75
- data/test/_test_active_mimic.rb +0 -95
- data/test/_test_mimic_rails.rb +0 -123
- data/test/activerecord/result_test.rb +0 -31
- data/test/activesupport6/abstract_unit.rb +0 -44
- data/test/activesupport6/decoding_test.rb +0 -133
- data/test/activesupport6/encoding_test.rb +0 -507
- data/test/activesupport6/encoding_test_cases.rb +0 -98
- data/test/activesupport6/test_common.rb +0 -17
- data/test/activesupport6/test_helper.rb +0 -163
- data/test/activesupport6/time_zone_test_helpers.rb +0 -39
- data/test/activesupport7/abstract_unit.rb +0 -49
- data/test/activesupport7/decoding_test.rb +0 -125
- data/test/activesupport7/encoding_test.rb +0 -486
- data/test/activesupport7/encoding_test_cases.rb +0 -104
- data/test/activesupport7/time_zone_test_helpers.rb +0 -47
- data/test/files.rb +0 -29
- data/test/foo.rb +0 -14
- data/test/helper.rb +0 -39
- data/test/isolated/shared.rb +0 -309
- data/test/isolated/test_mimic_after.rb +0 -13
- data/test/isolated/test_mimic_alone.rb +0 -12
- data/test/isolated/test_mimic_as_json.rb +0 -45
- data/test/isolated/test_mimic_before.rb +0 -13
- data/test/isolated/test_mimic_define.rb +0 -28
- data/test/isolated/test_mimic_rails_after.rb +0 -22
- data/test/isolated/test_mimic_rails_before.rb +0 -21
- data/test/isolated/test_mimic_redefine.rb +0 -15
- data/test/json_gem/json_addition_test.rb +0 -216
- data/test/json_gem/json_common_interface_test.rb +0 -155
- data/test/json_gem/json_encoding_test.rb +0 -107
- data/test/json_gem/json_ext_parser_test.rb +0 -21
- data/test/json_gem/json_fixtures_test.rb +0 -36
- data/test/json_gem/json_generator_test.rb +0 -407
- data/test/json_gem/json_generic_object_test.rb +0 -90
- data/test/json_gem/json_parser_test.rb +0 -477
- data/test/json_gem/json_string_matching_test.rb +0 -42
- data/test/json_gem/test_helper.rb +0 -30
- data/test/mem.rb +0 -34
- data/test/perf.rb +0 -102
- data/test/perf_compat.rb +0 -128
- data/test/perf_dump.rb +0 -50
- data/test/perf_fast.rb +0 -162
- data/test/perf_file.rb +0 -62
- data/test/perf_object.rb +0 -134
- data/test/perf_once.rb +0 -59
- data/test/perf_parser.rb +0 -183
- data/test/perf_saj.rb +0 -101
- data/test/perf_scp.rb +0 -140
- data/test/perf_simple.rb +0 -289
- data/test/perf_strict.rb +0 -137
- data/test/perf_wab.rb +0 -129
- data/test/prec.rb +0 -23
- data/test/sample/change.rb +0 -13
- data/test/sample/dir.rb +0 -18
- data/test/sample/doc.rb +0 -35
- data/test/sample/file.rb +0 -47
- data/test/sample/group.rb +0 -15
- data/test/sample/hasprops.rb +0 -15
- data/test/sample/layer.rb +0 -11
- data/test/sample/line.rb +0 -20
- data/test/sample/oval.rb +0 -10
- data/test/sample/rect.rb +0 -9
- data/test/sample/shape.rb +0 -34
- data/test/sample/text.rb +0 -19
- data/test/sample.rb +0 -54
- data/test/sample_json.rb +0 -37
- data/test/test_compat.rb +0 -567
- data/test/test_custom.rb +0 -554
- data/test/test_debian.rb +0 -50
- data/test/test_fast.rb +0 -526
- data/test/test_file.rb +0 -250
- data/test/test_gc.rb +0 -60
- data/test/test_generate.rb +0 -21
- data/test/test_hash.rb +0 -39
- data/test/test_integer_range.rb +0 -72
- data/test/test_null.rb +0 -376
- data/test/test_object.rb +0 -1016
- data/test/test_parser.rb +0 -11
- data/test/test_parser_debug.rb +0 -27
- data/test/test_parser_saj.rb +0 -337
- data/test/test_parser_usual.rb +0 -217
- data/test/test_rails.rb +0 -35
- data/test/test_saj.rb +0 -188
- data/test/test_scp.rb +0 -431
- data/test/test_strict.rb +0 -431
- data/test/test_various.rb +0 -801
- data/test/test_wab.rb +0 -311
- data/test/test_writer.rb +0 -380
- data/test/tests.rb +0 -33
- data/test/tests_mimic.rb +0 -23
- data/test/tests_mimic_addition.rb +0 -16
data/ext/oj/parser.c
CHANGED
|
@@ -75,7 +75,7 @@ enum {
|
|
|
75
75
|
|
|
76
76
|
/*
|
|
77
77
|
0123456789abcdef0123456789abcdef */
|
|
78
|
-
static const char value_map[
|
|
78
|
+
static const char value_map[258] = "\
|
|
79
79
|
X........ab..a..................\
|
|
80
80
|
a.i..........f..ghhhhhhhhh......\
|
|
81
81
|
...........................k.m..\
|
|
@@ -85,7 +85,7 @@ a.i..........f..ghhhhhhhhh......\
|
|
|
85
85
|
................................\
|
|
86
86
|
................................v";
|
|
87
87
|
|
|
88
|
-
static const char null_map[
|
|
88
|
+
static const char null_map[258] = "\
|
|
89
89
|
................................\
|
|
90
90
|
............o...................\
|
|
91
91
|
................................\
|
|
@@ -95,7 +95,7 @@ static const char null_map[257] = "\
|
|
|
95
95
|
................................\
|
|
96
96
|
................................N";
|
|
97
97
|
|
|
98
|
-
static const char true_map[
|
|
98
|
+
static const char true_map[258] = "\
|
|
99
99
|
................................\
|
|
100
100
|
............o...................\
|
|
101
101
|
................................\
|
|
@@ -105,7 +105,7 @@ static const char true_map[257] = "\
|
|
|
105
105
|
................................\
|
|
106
106
|
................................T";
|
|
107
107
|
|
|
108
|
-
static const char false_map[
|
|
108
|
+
static const char false_map[258] = "\
|
|
109
109
|
................................\
|
|
110
110
|
............o...................\
|
|
111
111
|
................................\
|
|
@@ -115,7 +115,7 @@ static const char false_map[257] = "\
|
|
|
115
115
|
................................\
|
|
116
116
|
................................F";
|
|
117
117
|
|
|
118
|
-
static const char comma_map[
|
|
118
|
+
static const char comma_map[258] = "\
|
|
119
119
|
.........ab..a..................\
|
|
120
120
|
a.i..........f..ghhhhhhhhh......\
|
|
121
121
|
...........................k....\
|
|
@@ -125,7 +125,7 @@ a.i..........f..ghhhhhhhhh......\
|
|
|
125
125
|
................................\
|
|
126
126
|
................................,";
|
|
127
127
|
|
|
128
|
-
static const char after_map[
|
|
128
|
+
static const char after_map[258] = "\
|
|
129
129
|
X........ab..a..................\
|
|
130
130
|
a...........o...................\
|
|
131
131
|
.............................m..\
|
|
@@ -135,7 +135,7 @@ a...........o...................\
|
|
|
135
135
|
................................\
|
|
136
136
|
................................a";
|
|
137
137
|
|
|
138
|
-
static const char key1_map[
|
|
138
|
+
static const char key1_map[258] = "\
|
|
139
139
|
.........ab..a..................\
|
|
140
140
|
a.p.............................\
|
|
141
141
|
................................\
|
|
@@ -145,7 +145,7 @@ a.p.............................\
|
|
|
145
145
|
................................\
|
|
146
146
|
................................K";
|
|
147
147
|
|
|
148
|
-
static const char key_map[
|
|
148
|
+
static const char key_map[258] = "\
|
|
149
149
|
.........ab..a..................\
|
|
150
150
|
a.p.............................\
|
|
151
151
|
................................\
|
|
@@ -155,7 +155,7 @@ a.p.............................\
|
|
|
155
155
|
................................\
|
|
156
156
|
................................k";
|
|
157
157
|
|
|
158
|
-
static const char colon_map[
|
|
158
|
+
static const char colon_map[258] = "\
|
|
159
159
|
.........ab..a..................\
|
|
160
160
|
a.........................q.....\
|
|
161
161
|
................................\
|
|
@@ -165,7 +165,7 @@ a.........................q.....\
|
|
|
165
165
|
................................\
|
|
166
166
|
................................:";
|
|
167
167
|
|
|
168
|
-
static const char neg_map[
|
|
168
|
+
static const char neg_map[258] = "\
|
|
169
169
|
................................\
|
|
170
170
|
................O---------......\
|
|
171
171
|
................................\
|
|
@@ -175,7 +175,7 @@ static const char neg_map[257] = "\
|
|
|
175
175
|
................................\
|
|
176
176
|
................................-";
|
|
177
177
|
|
|
178
|
-
static const char zero_map[
|
|
178
|
+
static const char zero_map[258] = "\
|
|
179
179
|
.........rs..r..................\
|
|
180
180
|
r...........u.t.................\
|
|
181
181
|
.............................H..\
|
|
@@ -185,7 +185,7 @@ r...........u.t.................\
|
|
|
185
185
|
................................\
|
|
186
186
|
................................0";
|
|
187
187
|
|
|
188
|
-
static const char digit_map[
|
|
188
|
+
static const char digit_map[258] = "\
|
|
189
189
|
.........rs..r..................\
|
|
190
190
|
r...........u.t.NNNNNNNNNN......\
|
|
191
191
|
.....w.......................H..\
|
|
@@ -195,7 +195,7 @@ r...........u.t.NNNNNNNNNN......\
|
|
|
195
195
|
................................\
|
|
196
196
|
................................d";
|
|
197
197
|
|
|
198
|
-
static const char dot_map[
|
|
198
|
+
static const char dot_map[258] = "\
|
|
199
199
|
................................\
|
|
200
200
|
................vvvvvvvvvv......\
|
|
201
201
|
................................\
|
|
@@ -205,7 +205,7 @@ static const char dot_map[257] = "\
|
|
|
205
205
|
................................\
|
|
206
206
|
.................................";
|
|
207
207
|
|
|
208
|
-
static const char frac_map[
|
|
208
|
+
static const char frac_map[258] = "\
|
|
209
209
|
.........rs..r..................\
|
|
210
210
|
r...........u...vvvvvvvvvv......\
|
|
211
211
|
.....w.......................H..\
|
|
@@ -215,7 +215,7 @@ r...........u...vvvvvvvvvv......\
|
|
|
215
215
|
................................\
|
|
216
216
|
................................f";
|
|
217
217
|
|
|
218
|
-
static const char exp_sign_map[
|
|
218
|
+
static const char exp_sign_map[258] = "\
|
|
219
219
|
................................\
|
|
220
220
|
...........x.x..yyyyyyyyyy......\
|
|
221
221
|
................................\
|
|
@@ -225,7 +225,7 @@ static const char exp_sign_map[257] = "\
|
|
|
225
225
|
................................\
|
|
226
226
|
................................x";
|
|
227
227
|
|
|
228
|
-
static const char exp_zero_map[
|
|
228
|
+
static const char exp_zero_map[258] = "\
|
|
229
229
|
................................\
|
|
230
230
|
................yyyyyyyyyy......\
|
|
231
231
|
................................\
|
|
@@ -235,7 +235,7 @@ static const char exp_zero_map[257] = "\
|
|
|
235
235
|
................................\
|
|
236
236
|
................................z";
|
|
237
237
|
|
|
238
|
-
static const char exp_map[
|
|
238
|
+
static const char exp_map[258] = "\
|
|
239
239
|
.........rs..r..................\
|
|
240
240
|
r...........u...yyyyyyyyyy......\
|
|
241
241
|
.............................H..\
|
|
@@ -245,7 +245,7 @@ r...........u...yyyyyyyyyy......\
|
|
|
245
245
|
................................\
|
|
246
246
|
................................X";
|
|
247
247
|
|
|
248
|
-
static const char big_digit_map[
|
|
248
|
+
static const char big_digit_map[258] = "\
|
|
249
249
|
.........rs..r..................\
|
|
250
250
|
r...........u.D.CCCCCCCCCC......\
|
|
251
251
|
.....J.......................H..\
|
|
@@ -255,7 +255,7 @@ r...........u.D.CCCCCCCCCC......\
|
|
|
255
255
|
................................\
|
|
256
256
|
................................D";
|
|
257
257
|
|
|
258
|
-
static const char big_dot_map[
|
|
258
|
+
static const char big_dot_map[258] = "\
|
|
259
259
|
................................\
|
|
260
260
|
................IIIIIIIIII......\
|
|
261
261
|
................................\
|
|
@@ -265,7 +265,7 @@ static const char big_dot_map[257] = "\
|
|
|
265
265
|
................................\
|
|
266
266
|
................................o";
|
|
267
267
|
|
|
268
|
-
static const char big_frac_map[
|
|
268
|
+
static const char big_frac_map[258] = "\
|
|
269
269
|
.........rs..r..................\
|
|
270
270
|
r...........u...IIIIIIIIII......\
|
|
271
271
|
.....J.......................H..\
|
|
@@ -275,7 +275,7 @@ r...........u...IIIIIIIIII......\
|
|
|
275
275
|
................................\
|
|
276
276
|
................................g";
|
|
277
277
|
|
|
278
|
-
static const char big_exp_sign_map[
|
|
278
|
+
static const char big_exp_sign_map[258] = "\
|
|
279
279
|
................................\
|
|
280
280
|
...........K.K..LLLLLLLLLL......\
|
|
281
281
|
................................\
|
|
@@ -285,7 +285,7 @@ static const char big_exp_sign_map[257] = "\
|
|
|
285
285
|
................................\
|
|
286
286
|
................................B";
|
|
287
287
|
|
|
288
|
-
static const char big_exp_zero_map[
|
|
288
|
+
static const char big_exp_zero_map[258] = "\
|
|
289
289
|
................................\
|
|
290
290
|
................LLLLLLLLLL......\
|
|
291
291
|
................................\
|
|
@@ -295,7 +295,7 @@ static const char big_exp_zero_map[257] = "\
|
|
|
295
295
|
................................\
|
|
296
296
|
................................Z";
|
|
297
297
|
|
|
298
|
-
static const char big_exp_map[
|
|
298
|
+
static const char big_exp_map[258] = "\
|
|
299
299
|
.........rs..r..................\
|
|
300
300
|
r...........u...LLLLLLLLLL......\
|
|
301
301
|
.............................H..\
|
|
@@ -305,7 +305,7 @@ r...........u...LLLLLLLLLL......\
|
|
|
305
305
|
................................\
|
|
306
306
|
................................Y";
|
|
307
307
|
|
|
308
|
-
static const char string_map[
|
|
308
|
+
static const char string_map[258] = "\
|
|
309
309
|
................................\
|
|
310
310
|
RRzRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
|
|
311
311
|
RRRRRRRRRRRRRRRRRRRRRRRRRRRRARRR\
|
|
@@ -315,7 +315,7 @@ RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
|
|
|
315
315
|
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\
|
|
316
316
|
PPPPPPPPPPPPPPPPQQQQQQQQ........s";
|
|
317
317
|
|
|
318
|
-
static const char esc_map[
|
|
318
|
+
static const char esc_map[258] = "\
|
|
319
319
|
................................\
|
|
320
320
|
..B............B................\
|
|
321
321
|
............................B...\
|
|
@@ -325,7 +325,7 @@ static const char esc_map[257] = "\
|
|
|
325
325
|
................................\
|
|
326
326
|
................................~";
|
|
327
327
|
|
|
328
|
-
static const char esc_byte_map[
|
|
328
|
+
static const char esc_byte_map[258] = "\
|
|
329
329
|
................................\
|
|
330
330
|
..\"............/................\
|
|
331
331
|
............................\\...\
|
|
@@ -335,7 +335,7 @@ static const char esc_byte_map[257] = "\
|
|
|
335
335
|
................................\
|
|
336
336
|
................................b";
|
|
337
337
|
|
|
338
|
-
static const char u_map[
|
|
338
|
+
static const char u_map[258] = "\
|
|
339
339
|
................................\
|
|
340
340
|
................EEEEEEEEEE......\
|
|
341
341
|
.EEEEEE.........................\
|
|
@@ -345,7 +345,7 @@ static const char u_map[257] = "\
|
|
|
345
345
|
................................\
|
|
346
346
|
................................u";
|
|
347
347
|
|
|
348
|
-
static const char utf_map[
|
|
348
|
+
static const char utf_map[258] = "\
|
|
349
349
|
................................\
|
|
350
350
|
................................\
|
|
351
351
|
................................\
|
|
@@ -355,7 +355,7 @@ SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS\
|
|
|
355
355
|
................................\
|
|
356
356
|
................................8";
|
|
357
357
|
|
|
358
|
-
static const char space_map[
|
|
358
|
+
static const char space_map[258] = "\
|
|
359
359
|
.........ab..a..................\
|
|
360
360
|
a...............................\
|
|
361
361
|
................................\
|
|
@@ -365,7 +365,7 @@ a...............................\
|
|
|
365
365
|
................................\
|
|
366
366
|
................................S";
|
|
367
367
|
|
|
368
|
-
static const char trail_map[
|
|
368
|
+
static const char trail_map[258] = "\
|
|
369
369
|
.........ab..a..................\
|
|
370
370
|
a...............................\
|
|
371
371
|
................................\
|
|
@@ -375,7 +375,7 @@ a...............................\
|
|
|
375
375
|
................................\
|
|
376
376
|
................................R";
|
|
377
377
|
|
|
378
|
-
static const byte hex_map[
|
|
378
|
+
static const byte hex_map[257] = "\
|
|
379
379
|
................................\
|
|
380
380
|
................\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09......\
|
|
381
381
|
.\x0a\x0b\x0c\x0d\x0e\x0f.........................\
|
|
@@ -594,7 +594,7 @@ static void big_change(ojParser p) {
|
|
|
594
594
|
}
|
|
595
595
|
}
|
|
596
596
|
|
|
597
|
-
static void parse(ojParser p, const byte *json) {
|
|
597
|
+
static void parse(ojParser p, const byte *json, bool more) {
|
|
598
598
|
const byte *start;
|
|
599
599
|
const byte *b = json;
|
|
600
600
|
int i;
|
|
@@ -635,6 +635,9 @@ static void parse(ojParser p, const byte *json) {
|
|
|
635
635
|
if ('"' == *b) {
|
|
636
636
|
p->map = colon_map;
|
|
637
637
|
break;
|
|
638
|
+
} else if ('\0' == *b && !more) {
|
|
639
|
+
parse_error(p, "quoted string not terminated");
|
|
640
|
+
break;
|
|
638
641
|
}
|
|
639
642
|
b--;
|
|
640
643
|
p->map = string_map;
|
|
@@ -659,6 +662,9 @@ static void parse(ojParser p, const byte *json) {
|
|
|
659
662
|
p->funcs[p->stack[p->depth]].add_str(p);
|
|
660
663
|
p->map = (0 == p->depth) ? value_map : after_map;
|
|
661
664
|
break;
|
|
665
|
+
} else if ('\0' == *b && !more) {
|
|
666
|
+
parse_error(p, "quoted string not terminated");
|
|
667
|
+
break;
|
|
662
668
|
}
|
|
663
669
|
b--;
|
|
664
670
|
p->map = string_map;
|
|
@@ -668,6 +674,10 @@ static void parse(ojParser p, const byte *json) {
|
|
|
668
674
|
p->cur = b - json;
|
|
669
675
|
p->funcs[p->stack[p->depth]].open_object(p);
|
|
670
676
|
p->depth++;
|
|
677
|
+
if ((int)sizeof(p->stack) <= p->depth) {
|
|
678
|
+
parse_error(p, "too deeply nested");
|
|
679
|
+
break;
|
|
680
|
+
}
|
|
671
681
|
p->stack[p->depth] = OBJECT_FUN;
|
|
672
682
|
p->map = key1_map;
|
|
673
683
|
break;
|
|
@@ -690,6 +700,10 @@ static void parse(ojParser p, const byte *json) {
|
|
|
690
700
|
p->cur = b - json;
|
|
691
701
|
p->funcs[p->stack[p->depth]].open_array(p);
|
|
692
702
|
p->depth++;
|
|
703
|
+
if ((int)sizeof(p->stack) <= p->depth) {
|
|
704
|
+
parse_error(p, "too deeply nested");
|
|
705
|
+
break;
|
|
706
|
+
}
|
|
693
707
|
p->stack[p->depth] = ARRAY_FUN;
|
|
694
708
|
p->map = value_map;
|
|
695
709
|
break;
|
|
@@ -1114,9 +1128,6 @@ static void parse(ojParser p, const byte *json) {
|
|
|
1114
1128
|
p->map = trail_map;
|
|
1115
1129
|
}
|
|
1116
1130
|
}
|
|
1117
|
-
if (0 < p->depth) {
|
|
1118
|
-
parse_error(p, "parse error, not closed");
|
|
1119
|
-
}
|
|
1120
1131
|
if (0 == p->depth) {
|
|
1121
1132
|
switch (p->map[256]) {
|
|
1122
1133
|
case '0':
|
|
@@ -1164,10 +1175,23 @@ static void parser_mark(void *ptr) {
|
|
|
1164
1175
|
}
|
|
1165
1176
|
}
|
|
1166
1177
|
|
|
1178
|
+
const rb_data_type_t oj_parser_type = {
|
|
1179
|
+
"Oj/parser",
|
|
1180
|
+
{
|
|
1181
|
+
parser_mark,
|
|
1182
|
+
parser_free,
|
|
1183
|
+
NULL,
|
|
1184
|
+
},
|
|
1185
|
+
0,
|
|
1186
|
+
0,
|
|
1187
|
+
};
|
|
1188
|
+
|
|
1167
1189
|
extern void oj_set_parser_validator(ojParser p);
|
|
1168
1190
|
extern void oj_set_parser_saj(ojParser p);
|
|
1169
1191
|
extern void oj_set_parser_usual(ojParser p);
|
|
1170
1192
|
extern void oj_set_parser_debug(ojParser p);
|
|
1193
|
+
extern void oj_set_parser_safe(ojParser p, VALUE options);
|
|
1194
|
+
extern void oj_safe_init(VALUE parser_class);
|
|
1171
1195
|
|
|
1172
1196
|
static int opt_cb(VALUE rkey, VALUE value, VALUE ptr) {
|
|
1173
1197
|
ojParser p = (ojParser)ptr;
|
|
@@ -1255,7 +1279,7 @@ static VALUE parser_new(int argc, VALUE *argv, VALUE self) {
|
|
|
1255
1279
|
rb_hash_foreach(ropts, opt_cb, (VALUE)p);
|
|
1256
1280
|
}
|
|
1257
1281
|
}
|
|
1258
|
-
return
|
|
1282
|
+
return TypedData_Wrap_Struct(parser_class, &oj_parser_type, p);
|
|
1259
1283
|
}
|
|
1260
1284
|
|
|
1261
1285
|
// Create a new parser without setting the delegate. The parser is
|
|
@@ -1275,7 +1299,7 @@ VALUE oj_parser_new(void) {
|
|
|
1275
1299
|
buf_init(&p->buf);
|
|
1276
1300
|
p->map = value_map;
|
|
1277
1301
|
|
|
1278
|
-
return
|
|
1302
|
+
return TypedData_Wrap_Struct(parser_class, &oj_parser_type, p);
|
|
1279
1303
|
}
|
|
1280
1304
|
|
|
1281
1305
|
// Set set the options from a hash (ropts).
|
|
@@ -1294,53 +1318,41 @@ void oj_parser_set_option(ojParser p, VALUE ropts) {
|
|
|
1294
1318
|
* - no options
|
|
1295
1319
|
*
|
|
1296
1320
|
* - *:saj*
|
|
1297
|
-
* -
|
|
1298
|
-
* -
|
|
1299
|
-
* -
|
|
1300
|
-
* that length are cached.
|
|
1301
|
-
* - _cache_strings_ returns the value of the _cache_strings_ integer value.
|
|
1302
|
-
* - _handler=_ sets the SAJ handler
|
|
1303
|
-
* - _handler_ returns the SAJ handler
|
|
1321
|
+
* - _cache_keys_ is a flag indicating hash keys should be cached.
|
|
1322
|
+
* - _cache_strings_ is a positive integer less than 35. Strings shorter than that length are cached.
|
|
1323
|
+
* - _handler_ is the SAJ handler
|
|
1304
1324
|
*
|
|
1305
1325
|
* - *:usual*
|
|
1306
|
-
* -
|
|
1307
|
-
* -
|
|
1308
|
-
* -
|
|
1309
|
-
*
|
|
1310
|
-
* -
|
|
1311
|
-
*
|
|
1312
|
-
*
|
|
1313
|
-
*
|
|
1314
|
-
*
|
|
1315
|
-
*
|
|
1316
|
-
*
|
|
1317
|
-
*
|
|
1318
|
-
*
|
|
1319
|
-
*
|
|
1320
|
-
*
|
|
1321
|
-
*
|
|
1322
|
-
* _:
|
|
1323
|
-
*
|
|
1324
|
-
*
|
|
1325
|
-
*
|
|
1326
|
-
* -
|
|
1327
|
-
* ignored on parsing in favor of creating an instance and populating directly.
|
|
1328
|
-
* - _missing_class_ return the value of the _missing_class_ indicator.
|
|
1329
|
-
* - _missing_class=_ sets the value of the _missing_class_ flag. Valid values are _:auto_ which creates any missing
|
|
1330
|
-
* classes on parse, :ignore which ignores and continues as a Hash (default), and :raise which raises an exception if
|
|
1331
|
-
* the class is not found.
|
|
1332
|
-
* - _omit_null=_ sets the _omit_null_ flag. If true then null values in a map or object are omitted from the
|
|
1333
|
-
* resulting Hash or Object.
|
|
1334
|
-
* - _omit_null_ returns the value of the _omit_null_ flag.
|
|
1335
|
-
* - _symbol_keys=_ sets the flag that indicates Hash keys should be parsed to Symbols versus Strings.
|
|
1336
|
-
* - _symbol_keys_ returns the value of the _symbol_keys_ flag.
|
|
1326
|
+
* - _cache_keys_ is a flag indicating hash keys should be cached.
|
|
1327
|
+
* - _cache_strings_ is a positive integer less than 35. Strings shorter than that length are cached.
|
|
1328
|
+
* - _cache_expunge_ dictates when the cache will be expunged where 0 never expunges,
|
|
1329
|
+
* 1 expunges slowly, 2 expunges faster, and 3 or higher expunges agressively.
|
|
1330
|
+
* - _capacity_ is the capacity of the parser's internal stack. The parser grows automatically
|
|
1331
|
+
* but can be updated directly with this call.
|
|
1332
|
+
* - _create_id_ if non-nil is the key that is used to specify the type of object to create
|
|
1333
|
+
* when parsing. Parsed JSON objects that include the specified element use the element
|
|
1334
|
+
* value as the name of the class to create an object from instead of a Hash.
|
|
1335
|
+
* - _decimal_ is the approach to how decimals are parsed. If _:auto_ then
|
|
1336
|
+
* the decimals with significant digits are 16 or less are Floats and long
|
|
1337
|
+
* ones are BigDecimal. _:ruby_ uses a call to Ruby to convert a string to a Float.
|
|
1338
|
+
* _:float_ always generates a Float. _:bigdecimal_ always results in a BigDecimal.
|
|
1339
|
+
* - _ignore_json_create_ is a flag that when set the class json_create method is
|
|
1340
|
+
* ignored on parsing in favor of creating an instance and populating directly.
|
|
1341
|
+
* - _missing_class_ is an indicator that determines how unknown class names are handled.
|
|
1342
|
+
* Valid values are _:auto_ which creates any missing classes on parse, :ignore which ignores
|
|
1343
|
+
* and continues as a Hash (default), and :raise which raises an exception if the class is not found.
|
|
1344
|
+
* - _omit_null_ is a flag that if true then null values in a map or object are omitted
|
|
1345
|
+
* from the resulting Hash or Object.
|
|
1346
|
+
* - _symbol_keys_ is a flag that indicates Hash keys should be parsed to Symbols versus Strings.
|
|
1337
1347
|
*/
|
|
1338
1348
|
static VALUE parser_missing(int argc, VALUE *argv, VALUE self) {
|
|
1339
|
-
ojParser p
|
|
1349
|
+
ojParser p;
|
|
1340
1350
|
const char *key = NULL;
|
|
1341
1351
|
volatile VALUE rkey = *argv;
|
|
1342
1352
|
volatile VALUE rv = Qnil;
|
|
1343
1353
|
|
|
1354
|
+
TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
|
|
1355
|
+
|
|
1344
1356
|
#if HAVE_RB_EXT_RACTOR_SAFE
|
|
1345
1357
|
// This doesn't seem to do anything.
|
|
1346
1358
|
rb_ext_ractor_safe(true);
|
|
@@ -1358,6 +1370,34 @@ static VALUE parser_missing(int argc, VALUE *argv, VALUE self) {
|
|
|
1358
1370
|
return p->option(p, key, rv);
|
|
1359
1371
|
}
|
|
1360
1372
|
|
|
1373
|
+
static void validate_primitives_are_complete(ojParser p) {
|
|
1374
|
+
if (0 >= p->ri) {
|
|
1375
|
+
return;
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1378
|
+
switch (p->map[256]) {
|
|
1379
|
+
case 'N': parse_error(p, "expected null"); break;
|
|
1380
|
+
case 'F': parse_error(p, "expected false"); break;
|
|
1381
|
+
case 'T': parse_error(p, "expected true"); break;
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
static void validate_non_primitives_are_complete(ojParser p) {
|
|
1386
|
+
if (0 >= p->depth) {
|
|
1387
|
+
return;
|
|
1388
|
+
}
|
|
1389
|
+
if (OBJECT_FUN == p->stack[p->depth]) {
|
|
1390
|
+
parse_error(p, "Object is not closed");
|
|
1391
|
+
} else {
|
|
1392
|
+
parse_error(p, "Array is not closed");
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
static void validate_document_end(ojParser p) {
|
|
1397
|
+
validate_primitives_are_complete(p);
|
|
1398
|
+
validate_non_primitives_are_complete(p);
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1361
1401
|
/* Document-method: parse(json)
|
|
1362
1402
|
* call-seq: parse(json)
|
|
1363
1403
|
*
|
|
@@ -1366,12 +1406,21 @@ static VALUE parser_missing(int argc, VALUE *argv, VALUE self) {
|
|
|
1366
1406
|
* Returns the result according to the delegate of the parser.
|
|
1367
1407
|
*/
|
|
1368
1408
|
static VALUE parser_parse(VALUE self, VALUE json) {
|
|
1369
|
-
ojParser p
|
|
1370
|
-
|
|
1409
|
+
ojParser p;
|
|
1410
|
+
int frozen = OBJ_FROZEN(json);
|
|
1411
|
+
const byte *ptr;
|
|
1412
|
+
|
|
1413
|
+
if (!frozen) {
|
|
1414
|
+
rb_str_freeze(json);
|
|
1415
|
+
}
|
|
1416
|
+
ptr = (const byte *)StringValuePtr(json);
|
|
1417
|
+
|
|
1418
|
+
TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
|
|
1371
1419
|
|
|
1372
1420
|
parser_reset(p);
|
|
1373
1421
|
p->start(p);
|
|
1374
|
-
parse(p, ptr);
|
|
1422
|
+
parse(p, ptr, false);
|
|
1423
|
+
validate_document_end(p);
|
|
1375
1424
|
|
|
1376
1425
|
return p->result(p);
|
|
1377
1426
|
}
|
|
@@ -1382,14 +1431,22 @@ static VALUE load_rescue(VALUE self, VALUE x) {
|
|
|
1382
1431
|
}
|
|
1383
1432
|
|
|
1384
1433
|
static VALUE load(VALUE self) {
|
|
1385
|
-
ojParser p
|
|
1434
|
+
ojParser p;
|
|
1386
1435
|
volatile VALUE rbuf = rb_str_new2("");
|
|
1387
1436
|
|
|
1437
|
+
TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
|
|
1438
|
+
|
|
1388
1439
|
p->start(p);
|
|
1389
1440
|
while (true) {
|
|
1390
1441
|
rb_funcall(p->reader, oj_readpartial_id, 2, INT2NUM(16385), rbuf);
|
|
1391
1442
|
if (0 < RSTRING_LEN(rbuf)) {
|
|
1392
|
-
parse(p, (byte *)StringValuePtr(rbuf));
|
|
1443
|
+
parse(p, (byte *)StringValuePtr(rbuf), true);
|
|
1444
|
+
}
|
|
1445
|
+
if (Qtrue == rb_funcall(p->reader, oj_eofq_id, 0)) {
|
|
1446
|
+
if (0 < p->depth) {
|
|
1447
|
+
parse_error(p, "parse error, not closed");
|
|
1448
|
+
}
|
|
1449
|
+
break;
|
|
1393
1450
|
}
|
|
1394
1451
|
}
|
|
1395
1452
|
return Qtrue;
|
|
@@ -1403,7 +1460,9 @@ static VALUE load(VALUE self) {
|
|
|
1403
1460
|
* Returns the result according to the delegate of the parser.
|
|
1404
1461
|
*/
|
|
1405
1462
|
static VALUE parser_load(VALUE self, VALUE reader) {
|
|
1406
|
-
ojParser p
|
|
1463
|
+
ojParser p;
|
|
1464
|
+
|
|
1465
|
+
TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
|
|
1407
1466
|
|
|
1408
1467
|
parser_reset(p);
|
|
1409
1468
|
p->reader = reader;
|
|
@@ -1420,10 +1479,12 @@ static VALUE parser_load(VALUE self, VALUE reader) {
|
|
|
1420
1479
|
* Returns the result according to the delegate of the parser.
|
|
1421
1480
|
*/
|
|
1422
1481
|
static VALUE parser_file(VALUE self, VALUE filename) {
|
|
1423
|
-
ojParser p
|
|
1482
|
+
ojParser p;
|
|
1424
1483
|
const char *path;
|
|
1425
1484
|
int fd;
|
|
1426
1485
|
|
|
1486
|
+
TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
|
|
1487
|
+
|
|
1427
1488
|
path = StringValuePtr(filename);
|
|
1428
1489
|
|
|
1429
1490
|
parser_reset(p);
|
|
@@ -1449,7 +1510,7 @@ static VALUE parser_file(VALUE self, VALUE filename) {
|
|
|
1449
1510
|
while (true) {
|
|
1450
1511
|
if (0 < (rsize = read(fd, buf, size))) {
|
|
1451
1512
|
buf[rsize] = '\0';
|
|
1452
|
-
parse(p, buf);
|
|
1513
|
+
parse(p, buf, true);
|
|
1453
1514
|
}
|
|
1454
1515
|
if (rsize <= 0) {
|
|
1455
1516
|
if (0 != rsize) {
|
|
@@ -1467,7 +1528,9 @@ static VALUE parser_file(VALUE self, VALUE filename) {
|
|
|
1467
1528
|
* Returns the current state of the just_one [_Boolean_] option.
|
|
1468
1529
|
*/
|
|
1469
1530
|
static VALUE parser_just_one(VALUE self) {
|
|
1470
|
-
ojParser p
|
|
1531
|
+
ojParser p;
|
|
1532
|
+
|
|
1533
|
+
TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
|
|
1471
1534
|
|
|
1472
1535
|
return p->just_one ? Qtrue : Qfalse;
|
|
1473
1536
|
}
|
|
@@ -1481,7 +1544,9 @@ static VALUE parser_just_one(VALUE self) {
|
|
|
1481
1544
|
* Returns the current state of the just_one [_Boolean_] option.
|
|
1482
1545
|
*/
|
|
1483
1546
|
static VALUE parser_just_one_set(VALUE self, VALUE v) {
|
|
1484
|
-
ojParser p
|
|
1547
|
+
ojParser p;
|
|
1548
|
+
|
|
1549
|
+
TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
|
|
1485
1550
|
|
|
1486
1551
|
p->just_one = (Qtrue == v);
|
|
1487
1552
|
|
|
@@ -1505,7 +1570,7 @@ static VALUE parser_usual(VALUE self) {
|
|
|
1505
1570
|
buf_init(&p->buf);
|
|
1506
1571
|
p->map = value_map;
|
|
1507
1572
|
oj_set_parser_usual(p);
|
|
1508
|
-
usual_parser =
|
|
1573
|
+
usual_parser = TypedData_Wrap_Struct(parser_class, &oj_parser_type, p);
|
|
1509
1574
|
rb_gc_register_address(&usual_parser);
|
|
1510
1575
|
}
|
|
1511
1576
|
return usual_parser;
|
|
@@ -1528,7 +1593,7 @@ static VALUE parser_saj(VALUE self) {
|
|
|
1528
1593
|
buf_init(&p->buf);
|
|
1529
1594
|
p->map = value_map;
|
|
1530
1595
|
oj_set_parser_saj(p);
|
|
1531
|
-
saj_parser =
|
|
1596
|
+
saj_parser = TypedData_Wrap_Struct(parser_class, &oj_parser_type, p);
|
|
1532
1597
|
rb_gc_register_address(&saj_parser);
|
|
1533
1598
|
}
|
|
1534
1599
|
return saj_parser;
|
|
@@ -1550,12 +1615,34 @@ static VALUE parser_validate(VALUE self) {
|
|
|
1550
1615
|
buf_init(&p->buf);
|
|
1551
1616
|
p->map = value_map;
|
|
1552
1617
|
oj_set_parser_validator(p);
|
|
1553
|
-
validate_parser =
|
|
1618
|
+
validate_parser = TypedData_Wrap_Struct(parser_class, &oj_parser_type, p);
|
|
1554
1619
|
rb_gc_register_address(&validate_parser);
|
|
1555
1620
|
}
|
|
1556
1621
|
return validate_parser;
|
|
1557
1622
|
}
|
|
1558
1623
|
|
|
1624
|
+
static VALUE parser_safe(int argc, VALUE *argv, VALUE self) {
|
|
1625
|
+
VALUE options;
|
|
1626
|
+
|
|
1627
|
+
if (1 == argc) {
|
|
1628
|
+
options = argv[0];
|
|
1629
|
+
|
|
1630
|
+
Check_Type(options, T_HASH);
|
|
1631
|
+
} else {
|
|
1632
|
+
options = rb_hash_new();
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
ojParser p = OJ_R_ALLOC(struct _ojParser);
|
|
1636
|
+
|
|
1637
|
+
memset(p, 0, sizeof(struct _ojParser));
|
|
1638
|
+
buf_init(&p->key);
|
|
1639
|
+
buf_init(&p->buf);
|
|
1640
|
+
p->map = value_map;
|
|
1641
|
+
oj_set_parser_safe(p, options);
|
|
1642
|
+
|
|
1643
|
+
return TypedData_Wrap_Struct(parser_class, &oj_parser_type, p);
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1559
1646
|
/* Document-class: Oj::Parser
|
|
1560
1647
|
*
|
|
1561
1648
|
* A reusable parser that makes use of named delegates to determine the
|
|
@@ -1583,4 +1670,7 @@ void oj_parser_init(void) {
|
|
|
1583
1670
|
rb_define_module_function(parser_class, "usual", parser_usual, 0);
|
|
1584
1671
|
rb_define_module_function(parser_class, "saj", parser_saj, 0);
|
|
1585
1672
|
rb_define_module_function(parser_class, "validate", parser_validate, 0);
|
|
1673
|
+
rb_define_module_function(parser_class, "safe", parser_safe, -1);
|
|
1674
|
+
|
|
1675
|
+
oj_safe_init(parser_class);
|
|
1586
1676
|
}
|
data/ext/oj/parser.h
CHANGED
|
@@ -32,9 +32,9 @@ typedef struct _num {
|
|
|
32
32
|
long double dub;
|
|
33
33
|
int64_t fixnum; // holds all digits
|
|
34
34
|
uint32_t len;
|
|
35
|
-
int16_t div;
|
|
35
|
+
int16_t div; // 10^div
|
|
36
36
|
int16_t exp;
|
|
37
|
-
uint8_t shift;
|
|
37
|
+
uint8_t shift; // shift of fixnum to get decimal
|
|
38
38
|
bool neg;
|
|
39
39
|
bool exp_neg;
|
|
40
40
|
// for numbers as strings, reuse buf
|
|
@@ -42,6 +42,8 @@ typedef struct _num {
|
|
|
42
42
|
|
|
43
43
|
struct _ojParser;
|
|
44
44
|
|
|
45
|
+
extern const rb_data_type_t oj_parser_type;
|
|
46
|
+
|
|
45
47
|
typedef struct _funcs {
|
|
46
48
|
void (*add_null)(struct _ojParser *p);
|
|
47
49
|
void (*add_true)(struct _ojParser *p);
|