oj 3.16.6 → 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 +81 -0
- data/README.md +0 -16
- data/ext/oj/compat.c +3 -3
- data/ext/oj/custom.c +17 -11
- data/ext/oj/dump.c +592 -81
- 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 +10 -7
- data/ext/oj/fast.c +40 -23
- data/ext/oj/intern.c +1 -1
- data/ext/oj/mimic_json.c +11 -7
- data/ext/oj/object.c +8 -8
- data/ext/oj/oj.c +256 -10
- data/ext/oj/oj.h +55 -52
- data/ext/oj/parse.c +243 -46
- data/ext/oj/parser.c +113 -37
- data/ext/oj/parser.h +2 -0
- data/ext/oj/rails.c +41 -36
- 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 +13 -8
- 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 +3 -13
- data/ext/oj/strict.c +2 -4
- data/ext/oj/string_writer.c +5 -7
- data/ext/oj/usual.c +20 -7
- data/ext/oj/wab.c +5 -4
- data/lib/oj/version.rb +1 -1
- data/pages/Encoding.md +1 -1
- metadata +22 -114
- 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 -542
- 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 -52
- data/test/activesupport7/decoding_test.rb +0 -125
- data/test/activesupport7/encoding_test.rb +0 -536
- 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 -26
- 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 -413
- 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 -555
- 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 -1030
- 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 -251
- 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 -441
- 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;
|
|
@@ -1161,7 +1175,7 @@ static void parser_mark(void *ptr) {
|
|
|
1161
1175
|
}
|
|
1162
1176
|
}
|
|
1163
1177
|
|
|
1164
|
-
|
|
1178
|
+
const rb_data_type_t oj_parser_type = {
|
|
1165
1179
|
"Oj/parser",
|
|
1166
1180
|
{
|
|
1167
1181
|
parser_mark,
|
|
@@ -1176,6 +1190,8 @@ extern void oj_set_parser_validator(ojParser p);
|
|
|
1176
1190
|
extern void oj_set_parser_saj(ojParser p);
|
|
1177
1191
|
extern void oj_set_parser_usual(ojParser p);
|
|
1178
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);
|
|
1179
1195
|
|
|
1180
1196
|
static int opt_cb(VALUE rkey, VALUE value, VALUE ptr) {
|
|
1181
1197
|
ojParser p = (ojParser)ptr;
|
|
@@ -1354,6 +1370,34 @@ static VALUE parser_missing(int argc, VALUE *argv, VALUE self) {
|
|
|
1354
1370
|
return p->option(p, key, rv);
|
|
1355
1371
|
}
|
|
1356
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
|
+
|
|
1357
1401
|
/* Document-method: parse(json)
|
|
1358
1402
|
* call-seq: parse(json)
|
|
1359
1403
|
*
|
|
@@ -1363,13 +1407,20 @@ static VALUE parser_missing(int argc, VALUE *argv, VALUE self) {
|
|
|
1363
1407
|
*/
|
|
1364
1408
|
static VALUE parser_parse(VALUE self, VALUE json) {
|
|
1365
1409
|
ojParser p;
|
|
1366
|
-
|
|
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);
|
|
1367
1417
|
|
|
1368
1418
|
TypedData_Get_Struct(self, struct _ojParser, &oj_parser_type, p);
|
|
1369
1419
|
|
|
1370
1420
|
parser_reset(p);
|
|
1371
1421
|
p->start(p);
|
|
1372
|
-
parse(p, ptr);
|
|
1422
|
+
parse(p, ptr, false);
|
|
1423
|
+
validate_document_end(p);
|
|
1373
1424
|
|
|
1374
1425
|
return p->result(p);
|
|
1375
1426
|
}
|
|
@@ -1389,7 +1440,7 @@ static VALUE load(VALUE self) {
|
|
|
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);
|
|
1393
1444
|
}
|
|
1394
1445
|
if (Qtrue == rb_funcall(p->reader, oj_eofq_id, 0)) {
|
|
1395
1446
|
if (0 < p->depth) {
|
|
@@ -1459,7 +1510,7 @@ static VALUE parser_file(VALUE self, VALUE filename) {
|
|
|
1459
1510
|
while (true) {
|
|
1460
1511
|
if (0 < (rsize = read(fd, buf, size))) {
|
|
1461
1512
|
buf[rsize] = '\0';
|
|
1462
|
-
parse(p, buf);
|
|
1513
|
+
parse(p, buf, true);
|
|
1463
1514
|
}
|
|
1464
1515
|
if (rsize <= 0) {
|
|
1465
1516
|
if (0 != rsize) {
|
|
@@ -1570,6 +1621,28 @@ static VALUE parser_validate(VALUE self) {
|
|
|
1570
1621
|
return validate_parser;
|
|
1571
1622
|
}
|
|
1572
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
|
+
|
|
1573
1646
|
/* Document-class: Oj::Parser
|
|
1574
1647
|
*
|
|
1575
1648
|
* A reusable parser that makes use of named delegates to determine the
|
|
@@ -1597,4 +1670,7 @@ void oj_parser_init(void) {
|
|
|
1597
1670
|
rb_define_module_function(parser_class, "usual", parser_usual, 0);
|
|
1598
1671
|
rb_define_module_function(parser_class, "saj", parser_saj, 0);
|
|
1599
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);
|
|
1600
1676
|
}
|
data/ext/oj/parser.h
CHANGED
data/ext/oj/rails.c
CHANGED
|
@@ -140,7 +140,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
140
140
|
volatile VALUE v;
|
|
141
141
|
int cnt;
|
|
142
142
|
int i;
|
|
143
|
-
|
|
143
|
+
size_t len;
|
|
144
144
|
const char *name;
|
|
145
145
|
|
|
146
146
|
#ifdef RSTRUCT_LEN
|
|
@@ -161,7 +161,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
161
161
|
volatile VALUE s = rb_sym2str(RARRAY_AREF(ma, i));
|
|
162
162
|
|
|
163
163
|
name = RSTRING_PTR(s);
|
|
164
|
-
len =
|
|
164
|
+
len = RSTRING_LEN(s);
|
|
165
165
|
assure_size(out, size + sep_len + 6);
|
|
166
166
|
if (0 < i) {
|
|
167
167
|
*out->cur++ = ',';
|
|
@@ -205,11 +205,11 @@ static void dump_bigdecimal(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
205
205
|
if ('I' == *str || 'N' == *str || ('-' == *str && 'I' == str[1])) {
|
|
206
206
|
oj_dump_nil(Qnil, depth, out, false);
|
|
207
207
|
} else if (out->opts->int_range_max != 0 || out->opts->int_range_min != 0) {
|
|
208
|
-
oj_dump_cstr(str,
|
|
208
|
+
oj_dump_cstr(str, RSTRING_LEN(rstr), 0, 0, out);
|
|
209
209
|
} else if (Yes == out->opts->bigdec_as_num) {
|
|
210
|
-
oj_dump_raw(str,
|
|
210
|
+
oj_dump_raw(str, RSTRING_LEN(rstr), out);
|
|
211
211
|
} else {
|
|
212
|
-
oj_dump_cstr(str,
|
|
212
|
+
oj_dump_cstr(str, RSTRING_LEN(rstr), 0, 0, out);
|
|
213
213
|
}
|
|
214
214
|
}
|
|
215
215
|
|
|
@@ -330,14 +330,14 @@ static void dump_timewithzone(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
330
330
|
static void dump_to_s(VALUE obj, int depth, Out out, bool as_ok) {
|
|
331
331
|
volatile VALUE rstr = oj_safe_string_convert(obj);
|
|
332
332
|
|
|
333
|
-
oj_dump_cstr(RSTRING_PTR(rstr),
|
|
333
|
+
oj_dump_cstr(RSTRING_PTR(rstr), RSTRING_LEN(rstr), 0, 0, out);
|
|
334
334
|
}
|
|
335
335
|
|
|
336
336
|
static ID parameters_id = 0;
|
|
337
337
|
|
|
338
338
|
typedef struct _strLen {
|
|
339
339
|
const char *str;
|
|
340
|
-
|
|
340
|
+
size_t len;
|
|
341
341
|
} *StrLen;
|
|
342
342
|
|
|
343
343
|
static void dump_actioncontroller_parameters(VALUE obj, int depth, Out out, bool as_ok) {
|
|
@@ -352,10 +352,10 @@ static StrLen columns_array(VALUE rcols, int *ccnt) {
|
|
|
352
352
|
volatile VALUE v;
|
|
353
353
|
StrLen cp;
|
|
354
354
|
StrLen cols;
|
|
355
|
-
|
|
356
|
-
|
|
355
|
+
size_t i;
|
|
356
|
+
size_t cnt = RARRAY_LEN(rcols);
|
|
357
357
|
|
|
358
|
-
*ccnt = cnt;
|
|
358
|
+
*ccnt = (int)cnt;
|
|
359
359
|
cols = OJ_R_ALLOC_N(struct _strLen, cnt);
|
|
360
360
|
for (i = 0, cp = cols; i < cnt; i++, cp++) {
|
|
361
361
|
v = RARRAY_AREF(rcols, i);
|
|
@@ -363,7 +363,7 @@ static StrLen columns_array(VALUE rcols, int *ccnt) {
|
|
|
363
363
|
v = oj_safe_string_convert(v);
|
|
364
364
|
}
|
|
365
365
|
cp->str = StringValuePtr(v);
|
|
366
|
-
cp->len =
|
|
366
|
+
cp->len = RSTRING_LEN(v);
|
|
367
367
|
}
|
|
368
368
|
return cols;
|
|
369
369
|
}
|
|
@@ -424,7 +424,8 @@ static void dump_activerecord_result(VALUE obj, int depth, Out out, bool as_ok)
|
|
|
424
424
|
volatile VALUE rows;
|
|
425
425
|
StrLen cols;
|
|
426
426
|
int ccnt = 0;
|
|
427
|
-
|
|
427
|
+
size_t i;
|
|
428
|
+
size_t rcnt;
|
|
428
429
|
size_t size;
|
|
429
430
|
int d2 = depth + 1;
|
|
430
431
|
|
|
@@ -435,7 +436,7 @@ static void dump_activerecord_result(VALUE obj, int depth, Out out, bool as_ok)
|
|
|
435
436
|
out->argc = 0;
|
|
436
437
|
cols = columns_array(rb_ivar_get(obj, columns_id), &ccnt);
|
|
437
438
|
rows = rb_ivar_get(obj, rows_id);
|
|
438
|
-
rcnt =
|
|
439
|
+
rcnt = RARRAY_LEN(rows);
|
|
439
440
|
assure_size(out, 2);
|
|
440
441
|
*out->cur++ = '[';
|
|
441
442
|
if (out->opts->dump_opts.use) {
|
|
@@ -660,13 +661,15 @@ static VALUE encoder_new(int argc, VALUE *argv, VALUE self) {
|
|
|
660
661
|
Encoder e = OJ_R_ALLOC(struct _encoder);
|
|
661
662
|
|
|
662
663
|
e->opts = oj_default_options;
|
|
663
|
-
e->arg = Qnil;
|
|
664
664
|
copy_opts(&ropts, &e->ropts);
|
|
665
665
|
|
|
666
666
|
if (1 <= argc && Qnil != *argv) {
|
|
667
|
-
oj_parse_options(*argv, &e->opts);
|
|
668
667
|
e->arg = *argv;
|
|
668
|
+
} else {
|
|
669
|
+
e->arg = rb_hash_new();
|
|
669
670
|
}
|
|
671
|
+
oj_parse_options(e->arg, &e->opts);
|
|
672
|
+
|
|
670
673
|
return TypedData_Wrap_Struct(encoder_class, &oj_encoder_type, e);
|
|
671
674
|
}
|
|
672
675
|
|
|
@@ -917,7 +920,7 @@ static VALUE encode(VALUE obj, ROptTable ropts, Options opts, int argc, VALUE *a
|
|
|
917
920
|
if (Yes == copts.circular) {
|
|
918
921
|
oj_cache8_new(&out.circ_cache);
|
|
919
922
|
}
|
|
920
|
-
|
|
923
|
+
|
|
921
924
|
rb_protect(protect_dump, (VALUE)&oo, &line);
|
|
922
925
|
|
|
923
926
|
if (0 == line) {
|
|
@@ -933,8 +936,7 @@ static VALUE encode(VALUE obj, ROptTable ropts, Options opts, int argc, VALUE *a
|
|
|
933
936
|
if (0 == out.buf) {
|
|
934
937
|
rb_raise(rb_eNoMemError, "Not enough memory.");
|
|
935
938
|
}
|
|
936
|
-
rstr =
|
|
937
|
-
rstr = oj_encode(rstr);
|
|
939
|
+
rstr = rb_utf8_str_new_cstr(out.buf);
|
|
938
940
|
}
|
|
939
941
|
if (Yes == copts.circular) {
|
|
940
942
|
oj_cache8_delete(out.circ_cache);
|
|
@@ -1101,6 +1103,8 @@ static VALUE rails_set_decoder(VALUE self) {
|
|
|
1101
1103
|
} else {
|
|
1102
1104
|
json_error = rb_define_class_under(json, "JSONError", rb_eStandardError);
|
|
1103
1105
|
}
|
|
1106
|
+
|
|
1107
|
+
rb_global_variable(&oj_json_parser_error_class);
|
|
1104
1108
|
if (rb_const_defined_at(json, rb_intern("ParserError"))) {
|
|
1105
1109
|
oj_json_parser_error_class = rb_const_get(json, rb_intern("ParserError"));
|
|
1106
1110
|
} else {
|
|
@@ -1172,7 +1176,7 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
1172
1176
|
char buf[64];
|
|
1173
1177
|
char *b;
|
|
1174
1178
|
double d = rb_num2dbl(obj);
|
|
1175
|
-
|
|
1179
|
+
size_t cnt = 0;
|
|
1176
1180
|
|
|
1177
1181
|
if (0.0 == d) {
|
|
1178
1182
|
b = buf;
|
|
@@ -1193,7 +1197,7 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
1193
1197
|
volatile VALUE rstr = oj_safe_string_convert(obj);
|
|
1194
1198
|
|
|
1195
1199
|
strcpy(buf, RSTRING_PTR(rstr));
|
|
1196
|
-
cnt =
|
|
1200
|
+
cnt = RSTRING_LEN(rstr);
|
|
1197
1201
|
}
|
|
1198
1202
|
}
|
|
1199
1203
|
assure_size(out, cnt);
|
|
@@ -1205,7 +1209,8 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
1205
1209
|
|
|
1206
1210
|
static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
|
|
1207
1211
|
size_t size;
|
|
1208
|
-
|
|
1212
|
+
size_t i;
|
|
1213
|
+
size_t cnt;
|
|
1209
1214
|
int d2 = depth + 1;
|
|
1210
1215
|
|
|
1211
1216
|
if (Yes == out->opts->circular) {
|
|
@@ -1214,12 +1219,11 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
|
|
|
1214
1219
|
return;
|
|
1215
1220
|
}
|
|
1216
1221
|
}
|
|
1217
|
-
|
|
1218
|
-
if (as_ok && 0 < out->argc && rb_respond_to(a, oj_as_json_id)) {
|
|
1222
|
+
if (!oj_rails_array_opt && as_ok && rb_respond_to(a, oj_as_json_id)) {
|
|
1219
1223
|
dump_as_json(a, depth, out, false);
|
|
1220
1224
|
return;
|
|
1221
1225
|
}
|
|
1222
|
-
cnt =
|
|
1226
|
+
cnt = RARRAY_LEN(a);
|
|
1223
1227
|
*out->cur++ = '[';
|
|
1224
1228
|
size = 2;
|
|
1225
1229
|
assure_size(out, size);
|
|
@@ -1282,18 +1286,19 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
|
1282
1286
|
if (out->omit_nil && Qnil == value) {
|
|
1283
1287
|
return ST_CONTINUE;
|
|
1284
1288
|
}
|
|
1285
|
-
if (
|
|
1286
|
-
|
|
1287
|
-
|
|
1289
|
+
if (NULL != out->opts->dump_opts.only || NULL != out->opts->dump_opts.except) {
|
|
1290
|
+
if (oj_key_skip(key, out->opts->dump_opts.only, out->opts->dump_opts.except)) {
|
|
1291
|
+
return ST_CONTINUE;
|
|
1292
|
+
}
|
|
1288
1293
|
}
|
|
1289
1294
|
if (!out->opts->dump_opts.use) {
|
|
1290
1295
|
size = depth * out->indent + 1;
|
|
1291
1296
|
assure_size(out, size);
|
|
1292
1297
|
fill_indent(out, depth);
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1298
|
+
switch (rtype) {
|
|
1299
|
+
case T_STRING: oj_dump_str(key, 0, out, false); break;
|
|
1300
|
+
case T_SYMBOL: oj_dump_sym(key, 0, out, false); break;
|
|
1301
|
+
default: oj_dump_str(oj_safe_string_convert(key), 0, out, false); break;
|
|
1297
1302
|
}
|
|
1298
1303
|
*out->cur++ = ':';
|
|
1299
1304
|
} else {
|
|
@@ -1308,10 +1313,10 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
|
1308
1313
|
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
|
1309
1314
|
}
|
|
1310
1315
|
}
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1316
|
+
switch (rtype) {
|
|
1317
|
+
case T_STRING: oj_dump_str(key, 0, out, false); break;
|
|
1318
|
+
case T_SYMBOL: oj_dump_sym(key, 0, out, false); break;
|
|
1319
|
+
default: oj_dump_str(oj_safe_string_convert(key), 0, out, false); break;
|
|
1315
1320
|
}
|
|
1316
1321
|
size = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
|
|
1317
1322
|
assure_size(out, size);
|
|
@@ -1340,7 +1345,7 @@ static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
|
|
|
1340
1345
|
return;
|
|
1341
1346
|
}
|
|
1342
1347
|
}
|
|
1343
|
-
if (
|
|
1348
|
+
if (!oj_rails_hash_opt && as_ok && rb_respond_to(obj, oj_as_json_id)) {
|
|
1344
1349
|
dump_as_json(obj, depth, out, false);
|
|
1345
1350
|
return;
|
|
1346
1351
|
}
|
data/ext/oj/rxclass.c
CHANGED