json 1.8.3 → 2.5.1
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 +5 -5
- data/{CHANGES → CHANGES.md} +241 -90
- data/Gemfile +10 -6
- data/{COPYING-json-jruby → LICENSE} +5 -6
- data/{README.rdoc → README.md} +201 -134
- data/VERSION +1 -1
- data/ext/json/ext/fbuffer/fbuffer.h +0 -3
- data/ext/json/ext/generator/generator.c +264 -104
- data/ext/json/ext/generator/generator.h +12 -4
- data/ext/json/ext/parser/extconf.rb +28 -0
- data/ext/json/ext/parser/parser.c +425 -462
- data/ext/json/ext/parser/parser.h +5 -5
- data/ext/json/ext/parser/parser.rl +181 -181
- data/ext/json/extconf.rb +1 -1
- data/json.gemspec +0 -0
- data/lib/json.rb +550 -29
- data/lib/json/add/bigdecimal.rb +3 -2
- data/lib/json/add/complex.rb +4 -4
- data/lib/json/add/core.rb +1 -0
- data/lib/json/add/date.rb +1 -1
- data/lib/json/add/date_time.rb +1 -1
- data/lib/json/add/exception.rb +1 -1
- data/lib/json/add/ostruct.rb +3 -3
- data/lib/json/add/range.rb +1 -1
- data/lib/json/add/rational.rb +3 -3
- data/lib/json/add/regexp.rb +3 -3
- data/lib/json/add/set.rb +29 -0
- data/lib/json/add/struct.rb +1 -1
- data/lib/json/add/symbol.rb +1 -1
- data/lib/json/add/time.rb +1 -1
- data/lib/json/common.rb +381 -162
- data/lib/json/ext.rb +0 -6
- data/lib/json/generic_object.rb +5 -4
- data/lib/json/pure.rb +2 -8
- data/lib/json/pure/generator.rb +83 -126
- data/lib/json/pure/parser.rb +62 -84
- data/lib/json/version.rb +2 -1
- data/tests/fixtures/fail29.json +1 -0
- data/tests/fixtures/fail30.json +1 -0
- data/tests/fixtures/fail31.json +1 -0
- data/tests/fixtures/fail32.json +1 -0
- data/tests/fixtures/obsolete_fail1.json +1 -0
- data/tests/{test_json_addition.rb → json_addition_test.rb} +28 -25
- data/tests/json_common_interface_test.rb +169 -0
- data/tests/json_encoding_test.rb +107 -0
- data/tests/json_ext_parser_test.rb +15 -0
- data/tests/{test_json_fixtures.rb → json_fixtures_test.rb} +13 -8
- data/tests/{test_json_generate.rb → json_generator_test.rb} +109 -47
- data/tests/{test_json_generic_object.rb → json_generic_object_test.rb} +15 -8
- data/tests/json_parser_test.rb +497 -0
- data/tests/json_string_matching_test.rb +38 -0
- data/tests/lib/core_assertions.rb +763 -0
- data/tests/lib/envutil.rb +365 -0
- data/tests/lib/find_executable.rb +22 -0
- data/tests/lib/helper.rb +4 -0
- data/tests/ractor_test.rb +30 -0
- data/tests/test_helper.rb +17 -0
- metadata +48 -76
- data/.gitignore +0 -16
- data/.travis.yml +0 -26
- data/COPYING +0 -58
- data/GPL +0 -340
- data/README-json-jruby.markdown +0 -33
- data/Rakefile +0 -412
- data/TODO +0 -1
- data/data/example.json +0 -1
- data/data/index.html +0 -38
- data/data/prototype.js +0 -4184
- data/diagrams/.keep +0 -0
- data/install.rb +0 -23
- data/java/src/json/ext/ByteListTranscoder.java +0 -167
- data/java/src/json/ext/Generator.java +0 -444
- data/java/src/json/ext/GeneratorMethods.java +0 -232
- data/java/src/json/ext/GeneratorService.java +0 -43
- data/java/src/json/ext/GeneratorState.java +0 -543
- data/java/src/json/ext/OptionsReader.java +0 -114
- data/java/src/json/ext/Parser.java +0 -2645
- data/java/src/json/ext/Parser.rl +0 -969
- data/java/src/json/ext/ParserService.java +0 -35
- data/java/src/json/ext/RuntimeInfo.java +0 -121
- data/java/src/json/ext/StringDecoder.java +0 -167
- data/java/src/json/ext/StringEncoder.java +0 -106
- data/java/src/json/ext/Utils.java +0 -89
- data/json-java.gemspec +0 -23
- data/json_pure.gemspec +0 -40
- data/tests/fixtures/fail1.json +0 -1
- data/tests/setup_variant.rb +0 -11
- data/tests/test_json.rb +0 -553
- data/tests/test_json_encoding.rb +0 -65
- data/tests/test_json_string_matching.rb +0 -39
- data/tests/test_json_unicode.rb +0 -72
- data/tools/fuzz.rb +0 -139
- data/tools/server.rb +0 -62
@@ -34,13 +34,13 @@ typedef struct JSON_ParserStruct {
|
|
34
34
|
char *memo;
|
35
35
|
VALUE create_id;
|
36
36
|
int max_nesting;
|
37
|
-
int current_nesting;
|
38
37
|
int allow_nan;
|
39
38
|
int parsing_name;
|
40
39
|
int symbolize_names;
|
41
|
-
int
|
40
|
+
int freeze;
|
42
41
|
VALUE object_class;
|
43
42
|
VALUE array_class;
|
43
|
+
VALUE decimal_class;
|
44
44
|
int create_additions;
|
45
45
|
VALUE match_string;
|
46
46
|
FBuffer *fbuffer;
|
@@ -58,11 +58,11 @@ typedef struct JSON_ParserStruct {
|
|
58
58
|
|
59
59
|
static UTF32 unescape_unicode(const unsigned char *p);
|
60
60
|
static int convert_UTF32_to_UTF8(char *buf, UTF32 ch);
|
61
|
-
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result);
|
62
|
-
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result);
|
61
|
+
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
|
62
|
+
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
|
63
63
|
static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result);
|
64
64
|
static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result);
|
65
|
-
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result);
|
65
|
+
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
|
66
66
|
static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd);
|
67
67
|
static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result);
|
68
68
|
static VALUE convert_encoding(VALUE source);
|
@@ -1,9 +1,31 @@
|
|
1
1
|
#include "../fbuffer/fbuffer.h"
|
2
2
|
#include "parser.h"
|
3
3
|
|
4
|
+
#if defined HAVE_RUBY_ENCODING_H
|
5
|
+
# define EXC_ENCODING rb_utf8_encoding(),
|
6
|
+
# ifndef HAVE_RB_ENC_RAISE
|
7
|
+
static void
|
8
|
+
enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
|
9
|
+
{
|
10
|
+
va_list args;
|
11
|
+
VALUE mesg;
|
12
|
+
|
13
|
+
va_start(args, fmt);
|
14
|
+
mesg = rb_enc_vsprintf(enc, fmt, args);
|
15
|
+
va_end(args);
|
16
|
+
|
17
|
+
rb_exc_raise(rb_exc_new3(exc, mesg));
|
18
|
+
}
|
19
|
+
# define rb_enc_raise enc_raise
|
20
|
+
# endif
|
21
|
+
#else
|
22
|
+
# define EXC_ENCODING /* nothing */
|
23
|
+
# define rb_enc_raise rb_raise
|
24
|
+
#endif
|
25
|
+
|
4
26
|
/* unicode */
|
5
27
|
|
6
|
-
static const char digit_values[256] = {
|
28
|
+
static const signed char digit_values[256] = {
|
7
29
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
8
30
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
9
31
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1,
|
@@ -22,7 +44,7 @@ static const char digit_values[256] = {
|
|
22
44
|
|
23
45
|
static UTF32 unescape_unicode(const unsigned char *p)
|
24
46
|
{
|
25
|
-
char b;
|
47
|
+
signed char b;
|
26
48
|
UTF32 result = 0;
|
27
49
|
b = digit_values[p[0]];
|
28
50
|
if (b < 0) return UNI_REPLACEMENT_CHAR;
|
@@ -65,21 +87,14 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
|
|
65
87
|
return len;
|
66
88
|
}
|
67
89
|
|
68
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
69
|
-
static VALUE CEncoding_ASCII_8BIT, CEncoding_UTF_8, CEncoding_UTF_16BE,
|
70
|
-
CEncoding_UTF_16LE, CEncoding_UTF_32BE, CEncoding_UTF_32LE;
|
71
|
-
static ID i_encoding, i_encode;
|
72
|
-
#else
|
73
|
-
static ID i_iconv;
|
74
|
-
#endif
|
75
|
-
|
76
90
|
static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
|
77
91
|
static VALUE CNaN, CInfinity, CMinusInfinity;
|
78
92
|
|
79
93
|
static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
80
|
-
i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
|
81
|
-
i_object_class, i_array_class,
|
82
|
-
i_match_string, i_aset, i_aref,
|
94
|
+
i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
|
95
|
+
i_object_class, i_array_class, i_decimal_class, i_key_p,
|
96
|
+
i_deep_const_get, i_match, i_match_string, i_aset, i_aref,
|
97
|
+
i_leftshift, i_new, i_try_convert, i_freeze, i_uminus;
|
83
98
|
|
84
99
|
%%{
|
85
100
|
machine JSON_common;
|
@@ -117,11 +132,12 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
|
117
132
|
|
118
133
|
action parse_value {
|
119
134
|
VALUE v = Qnil;
|
120
|
-
char *np = JSON_parse_value(json, fpc, pe, &v);
|
135
|
+
char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
|
121
136
|
if (np == NULL) {
|
122
137
|
fhold; fbreak;
|
123
138
|
} else {
|
124
139
|
if (NIL_P(json->object_class)) {
|
140
|
+
OBJ_FREEZE(last_name);
|
125
141
|
rb_hash_aset(*result, last_name, v);
|
126
142
|
} else {
|
127
143
|
rb_funcall(*result, i_aset, 2, last_name, v);
|
@@ -150,14 +166,14 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
|
150
166
|
) @exit;
|
151
167
|
}%%
|
152
168
|
|
153
|
-
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
169
|
+
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
|
154
170
|
{
|
155
171
|
int cs = EVIL;
|
156
172
|
VALUE last_name = Qnil;
|
157
173
|
VALUE object_class = json->object_class;
|
158
174
|
|
159
|
-
if (json->max_nesting &&
|
160
|
-
rb_raise(eNestingError, "nesting of %d is too deep",
|
175
|
+
if (json->max_nesting && current_nesting > json->max_nesting) {
|
176
|
+
rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
|
161
177
|
}
|
162
178
|
|
163
179
|
*result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class);
|
@@ -206,14 +222,14 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
206
222
|
if (json->allow_nan) {
|
207
223
|
*result = CNaN;
|
208
224
|
} else {
|
209
|
-
|
225
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2);
|
210
226
|
}
|
211
227
|
}
|
212
228
|
action parse_infinity {
|
213
229
|
if (json->allow_nan) {
|
214
230
|
*result = CInfinity;
|
215
231
|
} else {
|
216
|
-
|
232
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8);
|
217
233
|
}
|
218
234
|
}
|
219
235
|
action parse_string {
|
@@ -223,13 +239,13 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
223
239
|
|
224
240
|
action parse_number {
|
225
241
|
char *np;
|
226
|
-
if(pe > fpc +
|
242
|
+
if(pe > fpc + 8 && !strncmp(MinusInfinity, fpc, 9)) {
|
227
243
|
if (json->allow_nan) {
|
228
244
|
*result = CMinusInfinity;
|
229
245
|
fexec p + 10;
|
230
246
|
fhold; fbreak;
|
231
247
|
} else {
|
232
|
-
|
248
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
233
249
|
}
|
234
250
|
}
|
235
251
|
np = JSON_parse_float(json, fpc, pe, result);
|
@@ -241,23 +257,19 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
241
257
|
|
242
258
|
action parse_array {
|
243
259
|
char *np;
|
244
|
-
json
|
245
|
-
np = JSON_parse_array(json, fpc, pe, result);
|
246
|
-
json->current_nesting--;
|
260
|
+
np = JSON_parse_array(json, fpc, pe, result, current_nesting + 1);
|
247
261
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
248
262
|
}
|
249
263
|
|
250
264
|
action parse_object {
|
251
265
|
char *np;
|
252
|
-
json
|
253
|
-
np = JSON_parse_object(json, fpc, pe, result);
|
254
|
-
json->current_nesting--;
|
266
|
+
np = JSON_parse_object(json, fpc, pe, result, current_nesting + 1);
|
255
267
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
256
268
|
}
|
257
269
|
|
258
270
|
action exit { fhold; fbreak; }
|
259
271
|
|
260
|
-
main := (
|
272
|
+
main := ignore* (
|
261
273
|
Vnull @parse_null |
|
262
274
|
Vfalse @parse_false |
|
263
275
|
Vtrue @parse_true |
|
@@ -267,16 +279,20 @@ main := (
|
|
267
279
|
begin_string >parse_string |
|
268
280
|
begin_array >parse_array |
|
269
281
|
begin_object >parse_object
|
270
|
-
) %*exit;
|
282
|
+
) ignore* %*exit;
|
271
283
|
}%%
|
272
284
|
|
273
|
-
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
285
|
+
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
|
274
286
|
{
|
275
287
|
int cs = EVIL;
|
276
288
|
|
277
289
|
%% write init;
|
278
290
|
%% write exec;
|
279
291
|
|
292
|
+
if (json->freeze) {
|
293
|
+
OBJ_FREEZE(*result);
|
294
|
+
}
|
295
|
+
|
280
296
|
if (cs >= JSON_value_first_final) {
|
281
297
|
return p;
|
282
298
|
} else {
|
@@ -337,11 +353,46 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
337
353
|
%% write exec;
|
338
354
|
|
339
355
|
if (cs >= JSON_float_first_final) {
|
356
|
+
VALUE mod = Qnil;
|
357
|
+
ID method_id = 0;
|
358
|
+
if (rb_respond_to(json->decimal_class, i_try_convert)) {
|
359
|
+
mod = json->decimal_class;
|
360
|
+
method_id = i_try_convert;
|
361
|
+
} else if (rb_respond_to(json->decimal_class, i_new)) {
|
362
|
+
mod = json->decimal_class;
|
363
|
+
method_id = i_new;
|
364
|
+
} else if (RB_TYPE_P(json->decimal_class, T_CLASS)) {
|
365
|
+
VALUE name = rb_class_name(json->decimal_class);
|
366
|
+
const char *name_cstr = RSTRING_PTR(name);
|
367
|
+
const char *last_colon = strrchr(name_cstr, ':');
|
368
|
+
if (last_colon) {
|
369
|
+
const char *mod_path_end = last_colon - 1;
|
370
|
+
VALUE mod_path = rb_str_substr(name, 0, mod_path_end - name_cstr);
|
371
|
+
mod = rb_path_to_class(mod_path);
|
372
|
+
|
373
|
+
const char *method_name_beg = last_colon + 1;
|
374
|
+
long before_len = method_name_beg - name_cstr;
|
375
|
+
long len = RSTRING_LEN(name) - before_len;
|
376
|
+
VALUE method_name = rb_str_substr(name, before_len, len);
|
377
|
+
method_id = SYM2ID(rb_str_intern(method_name));
|
378
|
+
} else {
|
379
|
+
mod = rb_mKernel;
|
380
|
+
method_id = SYM2ID(rb_str_intern(name));
|
381
|
+
}
|
382
|
+
}
|
383
|
+
|
340
384
|
long len = p - json->memo;
|
341
385
|
fbuffer_clear(json->fbuffer);
|
342
386
|
fbuffer_append(json->fbuffer, json->memo, len);
|
343
387
|
fbuffer_append_char(json->fbuffer, '\0');
|
344
|
-
|
388
|
+
|
389
|
+
if (method_id) {
|
390
|
+
VALUE text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
|
391
|
+
*result = rb_funcallv(mod, method_id, 1, &text);
|
392
|
+
} else {
|
393
|
+
*result = DBL2NUM(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
|
394
|
+
}
|
395
|
+
|
345
396
|
return p + 1;
|
346
397
|
} else {
|
347
398
|
return NULL;
|
@@ -357,7 +408,7 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
357
408
|
|
358
409
|
action parse_value {
|
359
410
|
VALUE v = Qnil;
|
360
|
-
char *np = JSON_parse_value(json, fpc, pe, &v);
|
411
|
+
char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
|
361
412
|
if (np == NULL) {
|
362
413
|
fhold; fbreak;
|
363
414
|
} else {
|
@@ -380,13 +431,13 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
380
431
|
end_array @exit;
|
381
432
|
}%%
|
382
433
|
|
383
|
-
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
434
|
+
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
|
384
435
|
{
|
385
436
|
int cs = EVIL;
|
386
437
|
VALUE array_class = json->array_class;
|
387
438
|
|
388
|
-
if (json->max_nesting &&
|
389
|
-
rb_raise(eNestingError, "nesting of %d is too deep",
|
439
|
+
if (json->max_nesting && current_nesting > json->max_nesting) {
|
440
|
+
rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
|
390
441
|
}
|
391
442
|
*result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
|
392
443
|
|
@@ -396,7 +447,7 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
396
447
|
if(cs >= JSON_array_first_final) {
|
397
448
|
return p + 1;
|
398
449
|
} else {
|
399
|
-
|
450
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
400
451
|
return NULL;
|
401
452
|
}
|
402
453
|
}
|
@@ -436,13 +487,21 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
|
|
436
487
|
break;
|
437
488
|
case 'u':
|
438
489
|
if (pe > stringEnd - 4) {
|
439
|
-
|
490
|
+
rb_enc_raise(
|
491
|
+
EXC_ENCODING eParserError,
|
492
|
+
"%u: incomplete unicode character escape sequence at '%s'", __LINE__, p
|
493
|
+
);
|
440
494
|
} else {
|
441
495
|
UTF32 ch = unescape_unicode((unsigned char *) ++pe);
|
442
496
|
pe += 3;
|
443
497
|
if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
|
444
498
|
pe++;
|
445
|
-
if (pe > stringEnd - 6)
|
499
|
+
if (pe > stringEnd - 6) {
|
500
|
+
rb_enc_raise(
|
501
|
+
EXC_ENCODING eParserError,
|
502
|
+
"%u: incomplete surrogate pair at '%s'", __LINE__, p
|
503
|
+
);
|
504
|
+
}
|
446
505
|
if (pe[0] == '\\' && pe[1] == 'u') {
|
447
506
|
UTF32 sur = unescape_unicode((unsigned char *) pe + 2);
|
448
507
|
ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16)
|
@@ -528,6 +587,23 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
528
587
|
|
529
588
|
if (json->symbolize_names && json->parsing_name) {
|
530
589
|
*result = rb_str_intern(*result);
|
590
|
+
} else if (RB_TYPE_P(*result, T_STRING)) {
|
591
|
+
# if STR_UMINUS_DEDUPE_FROZEN
|
592
|
+
if (json->freeze) {
|
593
|
+
// Starting from MRI 2.8 it is preferable to freeze the string
|
594
|
+
// before deduplication so that it can be interned directly
|
595
|
+
// otherwise it would be duplicated first which is wasteful.
|
596
|
+
*result = rb_funcall(rb_str_freeze(*result), i_uminus, 0);
|
597
|
+
}
|
598
|
+
# elif STR_UMINUS_DEDUPE
|
599
|
+
if (json->freeze) {
|
600
|
+
// MRI 2.5 and older do not deduplicate strings that are already
|
601
|
+
// frozen.
|
602
|
+
*result = rb_funcall(*result, i_uminus, 0);
|
603
|
+
}
|
604
|
+
# else
|
605
|
+
rb_str_resize(*result, RSTRING_LEN(*result));
|
606
|
+
# endif
|
531
607
|
}
|
532
608
|
if (cs >= JSON_string_first_final) {
|
533
609
|
return p + 1;
|
@@ -550,41 +626,16 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
550
626
|
|
551
627
|
static VALUE convert_encoding(VALUE source)
|
552
628
|
{
|
553
|
-
char *ptr = RSTRING_PTR(source);
|
554
|
-
long len = RSTRING_LEN(source);
|
555
|
-
if (len < 2) {
|
556
|
-
rb_raise(eParserError, "A JSON text must at least contain two octets!");
|
557
|
-
}
|
558
629
|
#ifdef HAVE_RUBY_ENCODING_H
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_32BE);
|
564
|
-
} else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
|
565
|
-
source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_16BE);
|
566
|
-
} else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
|
567
|
-
source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_32LE);
|
568
|
-
} else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
|
569
|
-
source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_16LE);
|
570
|
-
} else {
|
571
|
-
source = rb_str_dup(source);
|
572
|
-
FORCE_UTF8(source);
|
573
|
-
}
|
574
|
-
} else {
|
575
|
-
source = rb_funcall(source, i_encode, 1, CEncoding_UTF_8);
|
576
|
-
}
|
577
|
-
}
|
578
|
-
#else
|
579
|
-
if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
|
580
|
-
source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-32be"), source);
|
581
|
-
} else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
|
582
|
-
source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-16be"), source);
|
583
|
-
} else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
|
584
|
-
source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-32le"), source);
|
585
|
-
} else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
|
586
|
-
source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-16le"), source);
|
630
|
+
rb_encoding *enc = rb_enc_get(source);
|
631
|
+
if (enc == rb_ascii8bit_encoding()) {
|
632
|
+
if (OBJ_FROZEN(source)) {
|
633
|
+
source = rb_str_dup(source);
|
587
634
|
}
|
635
|
+
FORCE_UTF8(source);
|
636
|
+
} else {
|
637
|
+
source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding());
|
638
|
+
}
|
588
639
|
#endif
|
589
640
|
return source;
|
590
641
|
}
|
@@ -607,8 +658,9 @@ static VALUE convert_encoding(VALUE source)
|
|
607
658
|
* defiance of RFC 4627 to be parsed by the Parser. This option defaults to
|
608
659
|
* false.
|
609
660
|
* * *symbolize_names*: If set to true, returns symbols for the names
|
610
|
-
* (keys) in a JSON object. Otherwise strings are returned, which is
|
611
|
-
* the default.
|
661
|
+
* (keys) in a JSON object. Otherwise strings are returned, which is
|
662
|
+
* also the default. It's not possible to use this option in
|
663
|
+
* conjunction with the *create_additions* option.
|
612
664
|
* * *create_additions*: If set to false, the Parser doesn't create
|
613
665
|
* additions even if a matching class and create_id was found. This option
|
614
666
|
* defaults to false.
|
@@ -623,12 +675,18 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
623
675
|
if (json->Vsource) {
|
624
676
|
rb_raise(rb_eTypeError, "already initialized instance");
|
625
677
|
}
|
678
|
+
#ifdef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
|
679
|
+
rb_scan_args(argc, argv, "1:", &source, &opts);
|
680
|
+
#else
|
626
681
|
rb_scan_args(argc, argv, "11", &source, &opts);
|
682
|
+
#endif
|
627
683
|
if (!NIL_P(opts)) {
|
684
|
+
#ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
|
628
685
|
opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
|
629
686
|
if (NIL_P(opts)) {
|
630
687
|
rb_raise(rb_eArgError, "opts needs to be like a hash");
|
631
688
|
} else {
|
689
|
+
#endif
|
632
690
|
VALUE tmp = ID2SYM(i_max_nesting);
|
633
691
|
if (option_given_p(opts, tmp)) {
|
634
692
|
VALUE max_nesting = rb_hash_aref(opts, tmp);
|
@@ -653,12 +711,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
653
711
|
} else {
|
654
712
|
json->symbolize_names = 0;
|
655
713
|
}
|
656
|
-
tmp = ID2SYM(
|
714
|
+
tmp = ID2SYM(i_freeze);
|
657
715
|
if (option_given_p(opts, tmp)) {
|
658
|
-
|
659
|
-
json->quirks_mode = RTEST(quirks_mode) ? 1 : 0;
|
716
|
+
json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
|
660
717
|
} else {
|
661
|
-
json->
|
718
|
+
json->freeze = 0;
|
662
719
|
}
|
663
720
|
tmp = ID2SYM(i_create_additions);
|
664
721
|
if (option_given_p(opts, tmp)) {
|
@@ -666,6 +723,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
666
723
|
} else {
|
667
724
|
json->create_additions = 0;
|
668
725
|
}
|
726
|
+
if (json->symbolize_names && json->create_additions) {
|
727
|
+
rb_raise(rb_eArgError,
|
728
|
+
"options :symbolize_names and :create_additions cannot be "
|
729
|
+
" used in conjunction");
|
730
|
+
}
|
669
731
|
tmp = ID2SYM(i_create_id);
|
670
732
|
if (option_given_p(opts, tmp)) {
|
671
733
|
json->create_id = rb_hash_aref(opts, tmp);
|
@@ -684,6 +746,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
684
746
|
} else {
|
685
747
|
json->array_class = Qnil;
|
686
748
|
}
|
749
|
+
tmp = ID2SYM(i_decimal_class);
|
750
|
+
if (option_given_p(opts, tmp)) {
|
751
|
+
json->decimal_class = rb_hash_aref(opts, tmp);
|
752
|
+
} else {
|
753
|
+
json->decimal_class = Qnil;
|
754
|
+
}
|
687
755
|
tmp = ID2SYM(i_match_string);
|
688
756
|
if (option_given_p(opts, tmp)) {
|
689
757
|
VALUE match_string = rb_hash_aref(opts, tmp);
|
@@ -691,20 +759,19 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
691
759
|
} else {
|
692
760
|
json->match_string = Qnil;
|
693
761
|
}
|
762
|
+
#ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
|
694
763
|
}
|
764
|
+
#endif
|
695
765
|
} else {
|
696
766
|
json->max_nesting = 100;
|
697
767
|
json->allow_nan = 0;
|
698
|
-
json->create_additions =
|
768
|
+
json->create_additions = 0;
|
699
769
|
json->create_id = rb_funcall(mJSON, i_create_id, 0);
|
700
770
|
json->object_class = Qnil;
|
701
771
|
json->array_class = Qnil;
|
772
|
+
json->decimal_class = Qnil;
|
702
773
|
}
|
703
|
-
source =
|
704
|
-
if (!json->quirks_mode) {
|
705
|
-
source = convert_encoding(StringValue(source));
|
706
|
-
}
|
707
|
-
json->current_nesting = 0;
|
774
|
+
source = convert_encoding(StringValue(source));
|
708
775
|
StringValue(source);
|
709
776
|
json->len = RSTRING_LEN(source);
|
710
777
|
json->source = RSTRING_PTR(source);;
|
@@ -719,56 +786,8 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
719
786
|
|
720
787
|
include JSON_common;
|
721
788
|
|
722
|
-
action parse_object {
|
723
|
-
char *np;
|
724
|
-
json->current_nesting = 1;
|
725
|
-
np = JSON_parse_object(json, fpc, pe, &result);
|
726
|
-
if (np == NULL) { fhold; fbreak; } else fexec np;
|
727
|
-
}
|
728
|
-
|
729
|
-
action parse_array {
|
730
|
-
char *np;
|
731
|
-
json->current_nesting = 1;
|
732
|
-
np = JSON_parse_array(json, fpc, pe, &result);
|
733
|
-
if (np == NULL) { fhold; fbreak; } else fexec np;
|
734
|
-
}
|
735
|
-
|
736
|
-
main := ignore* (
|
737
|
-
begin_object >parse_object |
|
738
|
-
begin_array >parse_array
|
739
|
-
) ignore*;
|
740
|
-
}%%
|
741
|
-
|
742
|
-
static VALUE cParser_parse_strict(VALUE self)
|
743
|
-
{
|
744
|
-
char *p, *pe;
|
745
|
-
int cs = EVIL;
|
746
|
-
VALUE result = Qnil;
|
747
|
-
GET_PARSER;
|
748
|
-
|
749
|
-
%% write init;
|
750
|
-
p = json->source;
|
751
|
-
pe = p + json->len;
|
752
|
-
%% write exec;
|
753
|
-
|
754
|
-
if (cs >= JSON_first_final && p == pe) {
|
755
|
-
return result;
|
756
|
-
} else {
|
757
|
-
rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
758
|
-
return Qnil;
|
759
|
-
}
|
760
|
-
}
|
761
|
-
|
762
|
-
|
763
|
-
%%{
|
764
|
-
machine JSON_quirks_mode;
|
765
|
-
|
766
|
-
write data;
|
767
|
-
|
768
|
-
include JSON_common;
|
769
|
-
|
770
789
|
action parse_value {
|
771
|
-
char *np = JSON_parse_value(json, fpc, pe, &result);
|
790
|
+
char *np = JSON_parse_value(json, fpc, pe, &result, 0);
|
772
791
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
773
792
|
}
|
774
793
|
|
@@ -777,26 +796,6 @@ static VALUE cParser_parse_strict(VALUE self)
|
|
777
796
|
) ignore*;
|
778
797
|
}%%
|
779
798
|
|
780
|
-
static VALUE cParser_parse_quirks_mode(VALUE self)
|
781
|
-
{
|
782
|
-
char *p, *pe;
|
783
|
-
int cs = EVIL;
|
784
|
-
VALUE result = Qnil;
|
785
|
-
GET_PARSER;
|
786
|
-
|
787
|
-
%% write init;
|
788
|
-
p = json->source;
|
789
|
-
pe = p + json->len;
|
790
|
-
%% write exec;
|
791
|
-
|
792
|
-
if (cs >= JSON_quirks_mode_first_final && p == pe) {
|
793
|
-
return result;
|
794
|
-
} else {
|
795
|
-
rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
796
|
-
return Qnil;
|
797
|
-
}
|
798
|
-
}
|
799
|
-
|
800
799
|
/*
|
801
800
|
* call-seq: parse()
|
802
801
|
*
|
@@ -805,12 +804,21 @@ static VALUE cParser_parse_quirks_mode(VALUE self)
|
|
805
804
|
*/
|
806
805
|
static VALUE cParser_parse(VALUE self)
|
807
806
|
{
|
807
|
+
char *p, *pe;
|
808
|
+
int cs = EVIL;
|
809
|
+
VALUE result = Qnil;
|
808
810
|
GET_PARSER;
|
809
811
|
|
810
|
-
|
811
|
-
|
812
|
+
%% write init;
|
813
|
+
p = json->source;
|
814
|
+
pe = p + json->len;
|
815
|
+
%% write exec;
|
816
|
+
|
817
|
+
if (cs >= JSON_first_final && p == pe) {
|
818
|
+
return result;
|
812
819
|
} else {
|
813
|
-
|
820
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
821
|
+
return Qnil;
|
814
822
|
}
|
815
823
|
}
|
816
824
|
|
@@ -821,6 +829,7 @@ static void JSON_mark(void *ptr)
|
|
821
829
|
rb_gc_mark_maybe(json->create_id);
|
822
830
|
rb_gc_mark_maybe(json->object_class);
|
823
831
|
rb_gc_mark_maybe(json->array_class);
|
832
|
+
rb_gc_mark_maybe(json->decimal_class);
|
824
833
|
rb_gc_mark_maybe(json->match_string);
|
825
834
|
}
|
826
835
|
|
@@ -868,35 +877,34 @@ static VALUE cParser_source(VALUE self)
|
|
868
877
|
return rb_str_dup(json->Vsource);
|
869
878
|
}
|
870
879
|
|
871
|
-
/*
|
872
|
-
* call-seq: quirks_mode?()
|
873
|
-
*
|
874
|
-
* Returns a true, if this parser is in quirks_mode, false otherwise.
|
875
|
-
*/
|
876
|
-
static VALUE cParser_quirks_mode_p(VALUE self)
|
877
|
-
{
|
878
|
-
GET_PARSER;
|
879
|
-
return json->quirks_mode ? Qtrue : Qfalse;
|
880
|
-
}
|
881
|
-
|
882
|
-
|
883
880
|
void Init_parser(void)
|
884
881
|
{
|
882
|
+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
883
|
+
rb_ext_ractor_safe(true);
|
884
|
+
#endif
|
885
|
+
|
886
|
+
#undef rb_intern
|
885
887
|
rb_require("json/common");
|
886
888
|
mJSON = rb_define_module("JSON");
|
887
889
|
mExt = rb_define_module_under(mJSON, "Ext");
|
888
890
|
cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
|
889
891
|
eParserError = rb_path2class("JSON::ParserError");
|
890
892
|
eNestingError = rb_path2class("JSON::NestingError");
|
893
|
+
rb_gc_register_mark_object(eParserError);
|
894
|
+
rb_gc_register_mark_object(eNestingError);
|
891
895
|
rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
|
892
896
|
rb_define_method(cParser, "initialize", cParser_initialize, -1);
|
893
897
|
rb_define_method(cParser, "parse", cParser_parse, 0);
|
894
898
|
rb_define_method(cParser, "source", cParser_source, 0);
|
895
|
-
rb_define_method(cParser, "quirks_mode?", cParser_quirks_mode_p, 0);
|
896
899
|
|
897
900
|
CNaN = rb_const_get(mJSON, rb_intern("NaN"));
|
901
|
+
rb_gc_register_mark_object(CNaN);
|
902
|
+
|
898
903
|
CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
|
904
|
+
rb_gc_register_mark_object(CInfinity);
|
905
|
+
|
899
906
|
CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
|
907
|
+
rb_gc_register_mark_object(CMinusInfinity);
|
900
908
|
|
901
909
|
i_json_creatable_p = rb_intern("json_creatable?");
|
902
910
|
i_json_create = rb_intern("json_create");
|
@@ -906,9 +914,9 @@ void Init_parser(void)
|
|
906
914
|
i_max_nesting = rb_intern("max_nesting");
|
907
915
|
i_allow_nan = rb_intern("allow_nan");
|
908
916
|
i_symbolize_names = rb_intern("symbolize_names");
|
909
|
-
i_quirks_mode = rb_intern("quirks_mode");
|
910
917
|
i_object_class = rb_intern("object_class");
|
911
918
|
i_array_class = rb_intern("array_class");
|
919
|
+
i_decimal_class = rb_intern("decimal_class");
|
912
920
|
i_match = rb_intern("match");
|
913
921
|
i_match_string = rb_intern("match_string");
|
914
922
|
i_key_p = rb_intern("key?");
|
@@ -916,18 +924,10 @@ void Init_parser(void)
|
|
916
924
|
i_aset = rb_intern("[]=");
|
917
925
|
i_aref = rb_intern("[]");
|
918
926
|
i_leftshift = rb_intern("<<");
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
CEncoding_UTF_32BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32be"));
|
924
|
-
CEncoding_UTF_32LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32le"));
|
925
|
-
CEncoding_ASCII_8BIT = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("ascii-8bit"));
|
926
|
-
i_encoding = rb_intern("encoding");
|
927
|
-
i_encode = rb_intern("encode");
|
928
|
-
#else
|
929
|
-
i_iconv = rb_intern("iconv");
|
930
|
-
#endif
|
927
|
+
i_new = rb_intern("new");
|
928
|
+
i_try_convert = rb_intern("try_convert");
|
929
|
+
i_freeze = rb_intern("freeze");
|
930
|
+
i_uminus = rb_intern("-@");
|
931
931
|
}
|
932
932
|
|
933
933
|
/*
|