json 1.8.6 → 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} +234 -95
- data/Gemfile +10 -3
- data/LICENSE +56 -0
- data/README.md +187 -107
- data/VERSION +1 -1
- data/ext/json/ext/fbuffer/fbuffer.h +0 -3
- data/ext/json/ext/generator/generator.c +227 -101
- data/ext/json/ext/generator/generator.h +5 -8
- data/ext/json/ext/parser/extconf.rb +28 -0
- data/ext/json/ext/parser/parser.c +420 -481
- data/ext/json/ext/parser/parser.h +5 -5
- data/ext/json/ext/parser/parser.rl +148 -172
- 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 +73 -124
- 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} +98 -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 +43 -69
- data/.gitignore +0 -17
- data/.travis.yml +0 -18
- data/README-json-jruby.markdown +0 -33
- data/Rakefile +0 -402
- 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 -166
- data/java/src/json/ext/Generator.java +0 -446
- data/java/src/json/ext/GeneratorMethods.java +0 -231
- data/java/src/json/ext/GeneratorService.java +0 -42
- data/java/src/json/ext/GeneratorState.java +0 -542
- data/java/src/json/ext/OptionsReader.java +0 -113
- data/java/src/json/ext/Parser.java +0 -2644
- data/java/src/json/ext/Parser.rl +0 -968
- data/java/src/json/ext/ParserService.java +0 -34
- data/java/src/json/ext/RuntimeInfo.java +0 -120
- data/java/src/json/ext/StringDecoder.java +0 -166
- data/java/src/json/ext/StringEncoder.java +0 -111
- data/java/src/json/ext/Utils.java +0 -88
- data/json-java.gemspec +0 -38
- data/json_pure.gemspec +0 -37
- data/tests/fixtures/fail1.json +0 -1
- data/tests/setup_variant.rb +0 -11
- data/tests/test_json.rb +0 -519
- 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/diff.sh +0 -18
- 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);
|
@@ -2,7 +2,7 @@
|
|
2
2
|
#include "parser.h"
|
3
3
|
|
4
4
|
#if defined HAVE_RUBY_ENCODING_H
|
5
|
-
# define EXC_ENCODING
|
5
|
+
# define EXC_ENCODING rb_utf8_encoding(),
|
6
6
|
# ifndef HAVE_RB_ENC_RAISE
|
7
7
|
static void
|
8
8
|
enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
|
@@ -25,7 +25,7 @@ enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
|
|
25
25
|
|
26
26
|
/* unicode */
|
27
27
|
|
28
|
-
static const char digit_values[256] = {
|
28
|
+
static const signed char digit_values[256] = {
|
29
29
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
30
30
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
31
31
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1,
|
@@ -44,7 +44,7 @@ static const char digit_values[256] = {
|
|
44
44
|
|
45
45
|
static UTF32 unescape_unicode(const unsigned char *p)
|
46
46
|
{
|
47
|
-
char b;
|
47
|
+
signed char b;
|
48
48
|
UTF32 result = 0;
|
49
49
|
b = digit_values[p[0]];
|
50
50
|
if (b < 0) return UNI_REPLACEMENT_CHAR;
|
@@ -87,19 +87,14 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
|
|
87
87
|
return len;
|
88
88
|
}
|
89
89
|
|
90
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
91
|
-
static rb_encoding *UTF_8, *UTF_16BE, *UTF_16LE, *UTF_32BE, *UTF_32LE;
|
92
|
-
#else
|
93
|
-
static ID i_iconv;
|
94
|
-
#endif
|
95
|
-
|
96
90
|
static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
|
97
91
|
static VALUE CNaN, CInfinity, CMinusInfinity;
|
98
92
|
|
99
93
|
static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
100
|
-
i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
|
101
|
-
i_object_class, i_array_class,
|
102
|
-
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;
|
103
98
|
|
104
99
|
%%{
|
105
100
|
machine JSON_common;
|
@@ -137,11 +132,12 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
|
137
132
|
|
138
133
|
action parse_value {
|
139
134
|
VALUE v = Qnil;
|
140
|
-
char *np = JSON_parse_value(json, fpc, pe, &v);
|
135
|
+
char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
|
141
136
|
if (np == NULL) {
|
142
137
|
fhold; fbreak;
|
143
138
|
} else {
|
144
139
|
if (NIL_P(json->object_class)) {
|
140
|
+
OBJ_FREEZE(last_name);
|
145
141
|
rb_hash_aset(*result, last_name, v);
|
146
142
|
} else {
|
147
143
|
rb_funcall(*result, i_aset, 2, last_name, v);
|
@@ -170,14 +166,14 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
|
170
166
|
) @exit;
|
171
167
|
}%%
|
172
168
|
|
173
|
-
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)
|
174
170
|
{
|
175
171
|
int cs = EVIL;
|
176
172
|
VALUE last_name = Qnil;
|
177
173
|
VALUE object_class = json->object_class;
|
178
174
|
|
179
|
-
if (json->max_nesting &&
|
180
|
-
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);
|
181
177
|
}
|
182
178
|
|
183
179
|
*result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class);
|
@@ -243,7 +239,7 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
243
239
|
|
244
240
|
action parse_number {
|
245
241
|
char *np;
|
246
|
-
if(pe > fpc +
|
242
|
+
if(pe > fpc + 8 && !strncmp(MinusInfinity, fpc, 9)) {
|
247
243
|
if (json->allow_nan) {
|
248
244
|
*result = CMinusInfinity;
|
249
245
|
fexec p + 10;
|
@@ -261,23 +257,19 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
261
257
|
|
262
258
|
action parse_array {
|
263
259
|
char *np;
|
264
|
-
json
|
265
|
-
np = JSON_parse_array(json, fpc, pe, result);
|
266
|
-
json->current_nesting--;
|
260
|
+
np = JSON_parse_array(json, fpc, pe, result, current_nesting + 1);
|
267
261
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
268
262
|
}
|
269
263
|
|
270
264
|
action parse_object {
|
271
265
|
char *np;
|
272
|
-
json
|
273
|
-
np = JSON_parse_object(json, fpc, pe, result);
|
274
|
-
json->current_nesting--;
|
266
|
+
np = JSON_parse_object(json, fpc, pe, result, current_nesting + 1);
|
275
267
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
276
268
|
}
|
277
269
|
|
278
270
|
action exit { fhold; fbreak; }
|
279
271
|
|
280
|
-
main := (
|
272
|
+
main := ignore* (
|
281
273
|
Vnull @parse_null |
|
282
274
|
Vfalse @parse_false |
|
283
275
|
Vtrue @parse_true |
|
@@ -287,16 +279,20 @@ main := (
|
|
287
279
|
begin_string >parse_string |
|
288
280
|
begin_array >parse_array |
|
289
281
|
begin_object >parse_object
|
290
|
-
) %*exit;
|
282
|
+
) ignore* %*exit;
|
291
283
|
}%%
|
292
284
|
|
293
|
-
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)
|
294
286
|
{
|
295
287
|
int cs = EVIL;
|
296
288
|
|
297
289
|
%% write init;
|
298
290
|
%% write exec;
|
299
291
|
|
292
|
+
if (json->freeze) {
|
293
|
+
OBJ_FREEZE(*result);
|
294
|
+
}
|
295
|
+
|
300
296
|
if (cs >= JSON_value_first_final) {
|
301
297
|
return p;
|
302
298
|
} else {
|
@@ -357,11 +353,46 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
357
353
|
%% write exec;
|
358
354
|
|
359
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
|
+
|
360
384
|
long len = p - json->memo;
|
361
385
|
fbuffer_clear(json->fbuffer);
|
362
386
|
fbuffer_append(json->fbuffer, json->memo, len);
|
363
387
|
fbuffer_append_char(json->fbuffer, '\0');
|
364
|
-
|
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
|
+
|
365
396
|
return p + 1;
|
366
397
|
} else {
|
367
398
|
return NULL;
|
@@ -377,7 +408,7 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
377
408
|
|
378
409
|
action parse_value {
|
379
410
|
VALUE v = Qnil;
|
380
|
-
char *np = JSON_parse_value(json, fpc, pe, &v);
|
411
|
+
char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
|
381
412
|
if (np == NULL) {
|
382
413
|
fhold; fbreak;
|
383
414
|
} else {
|
@@ -400,13 +431,13 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
400
431
|
end_array @exit;
|
401
432
|
}%%
|
402
433
|
|
403
|
-
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)
|
404
435
|
{
|
405
436
|
int cs = EVIL;
|
406
437
|
VALUE array_class = json->array_class;
|
407
438
|
|
408
|
-
if (json->max_nesting &&
|
409
|
-
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);
|
410
441
|
}
|
411
442
|
*result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
|
412
443
|
|
@@ -456,13 +487,21 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
|
|
456
487
|
break;
|
457
488
|
case 'u':
|
458
489
|
if (pe > stringEnd - 4) {
|
459
|
-
|
490
|
+
rb_enc_raise(
|
491
|
+
EXC_ENCODING eParserError,
|
492
|
+
"%u: incomplete unicode character escape sequence at '%s'", __LINE__, p
|
493
|
+
);
|
460
494
|
} else {
|
461
495
|
UTF32 ch = unescape_unicode((unsigned char *) ++pe);
|
462
496
|
pe += 3;
|
463
497
|
if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
|
464
498
|
pe++;
|
465
|
-
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
|
+
}
|
466
505
|
if (pe[0] == '\\' && pe[1] == 'u') {
|
467
506
|
UTF32 sur = unescape_unicode((unsigned char *) pe + 2);
|
468
507
|
ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16)
|
@@ -548,6 +587,23 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
548
587
|
|
549
588
|
if (json->symbolize_names && json->parsing_name) {
|
550
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
|
551
607
|
}
|
552
608
|
if (cs >= JSON_string_first_final) {
|
553
609
|
return p + 1;
|
@@ -570,41 +626,16 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
570
626
|
|
571
627
|
static VALUE convert_encoding(VALUE source)
|
572
628
|
{
|
573
|
-
const char *ptr = RSTRING_PTR(source);
|
574
|
-
long len = RSTRING_LEN(source);
|
575
|
-
if (len < 2) {
|
576
|
-
rb_raise(eParserError, "A JSON text must at least contain two octets!");
|
577
|
-
}
|
578
629
|
#ifdef HAVE_RUBY_ENCODING_H
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
source = rb_str_conv_enc(source, UTF_32BE, rb_utf8_encoding());
|
584
|
-
} else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
|
585
|
-
source = rb_str_conv_enc(source, UTF_16BE, rb_utf8_encoding());
|
586
|
-
} else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
|
587
|
-
source = rb_str_conv_enc(source, UTF_32LE, rb_utf8_encoding());
|
588
|
-
} else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
|
589
|
-
source = rb_str_conv_enc(source, UTF_16LE, rb_utf8_encoding());
|
590
|
-
} else {
|
591
|
-
source = rb_str_dup(source);
|
592
|
-
FORCE_UTF8(source);
|
593
|
-
}
|
594
|
-
} else {
|
595
|
-
source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding());
|
596
|
-
}
|
597
|
-
}
|
598
|
-
#else
|
599
|
-
if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
|
600
|
-
source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-32be"), source);
|
601
|
-
} else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
|
602
|
-
source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-16be"), source);
|
603
|
-
} else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
|
604
|
-
source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-32le"), source);
|
605
|
-
} else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
|
606
|
-
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);
|
607
634
|
}
|
635
|
+
FORCE_UTF8(source);
|
636
|
+
} else {
|
637
|
+
source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding());
|
638
|
+
}
|
608
639
|
#endif
|
609
640
|
return source;
|
610
641
|
}
|
@@ -627,8 +658,9 @@ static VALUE convert_encoding(VALUE source)
|
|
627
658
|
* defiance of RFC 4627 to be parsed by the Parser. This option defaults to
|
628
659
|
* false.
|
629
660
|
* * *symbolize_names*: If set to true, returns symbols for the names
|
630
|
-
* (keys) in a JSON object. Otherwise strings are returned, which is
|
631
|
-
* 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.
|
632
664
|
* * *create_additions*: If set to false, the Parser doesn't create
|
633
665
|
* additions even if a matching class and create_id was found. This option
|
634
666
|
* defaults to false.
|
@@ -679,12 +711,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
679
711
|
} else {
|
680
712
|
json->symbolize_names = 0;
|
681
713
|
}
|
682
|
-
tmp = ID2SYM(
|
714
|
+
tmp = ID2SYM(i_freeze);
|
683
715
|
if (option_given_p(opts, tmp)) {
|
684
|
-
|
685
|
-
json->quirks_mode = RTEST(quirks_mode) ? 1 : 0;
|
716
|
+
json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
|
686
717
|
} else {
|
687
|
-
json->
|
718
|
+
json->freeze = 0;
|
688
719
|
}
|
689
720
|
tmp = ID2SYM(i_create_additions);
|
690
721
|
if (option_given_p(opts, tmp)) {
|
@@ -692,6 +723,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
692
723
|
} else {
|
693
724
|
json->create_additions = 0;
|
694
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
|
+
}
|
695
731
|
tmp = ID2SYM(i_create_id);
|
696
732
|
if (option_given_p(opts, tmp)) {
|
697
733
|
json->create_id = rb_hash_aref(opts, tmp);
|
@@ -710,6 +746,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
710
746
|
} else {
|
711
747
|
json->array_class = Qnil;
|
712
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
|
+
}
|
713
755
|
tmp = ID2SYM(i_match_string);
|
714
756
|
if (option_given_p(opts, tmp)) {
|
715
757
|
VALUE match_string = rb_hash_aref(opts, tmp);
|
@@ -723,16 +765,14 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
723
765
|
} else {
|
724
766
|
json->max_nesting = 100;
|
725
767
|
json->allow_nan = 0;
|
726
|
-
json->create_additions =
|
768
|
+
json->create_additions = 0;
|
727
769
|
json->create_id = rb_funcall(mJSON, i_create_id, 0);
|
728
770
|
json->object_class = Qnil;
|
729
771
|
json->array_class = Qnil;
|
772
|
+
json->decimal_class = Qnil;
|
730
773
|
}
|
774
|
+
source = convert_encoding(StringValue(source));
|
731
775
|
StringValue(source);
|
732
|
-
if (!json->quirks_mode) {
|
733
|
-
source = convert_encoding(source);
|
734
|
-
}
|
735
|
-
json->current_nesting = 0;
|
736
776
|
json->len = RSTRING_LEN(source);
|
737
777
|
json->source = RSTRING_PTR(source);;
|
738
778
|
json->Vsource = source;
|
@@ -746,56 +786,8 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
746
786
|
|
747
787
|
include JSON_common;
|
748
788
|
|
749
|
-
action parse_object {
|
750
|
-
char *np;
|
751
|
-
json->current_nesting = 1;
|
752
|
-
np = JSON_parse_object(json, fpc, pe, &result);
|
753
|
-
if (np == NULL) { fhold; fbreak; } else fexec np;
|
754
|
-
}
|
755
|
-
|
756
|
-
action parse_array {
|
757
|
-
char *np;
|
758
|
-
json->current_nesting = 1;
|
759
|
-
np = JSON_parse_array(json, fpc, pe, &result);
|
760
|
-
if (np == NULL) { fhold; fbreak; } else fexec np;
|
761
|
-
}
|
762
|
-
|
763
|
-
main := ignore* (
|
764
|
-
begin_object >parse_object |
|
765
|
-
begin_array >parse_array
|
766
|
-
) ignore*;
|
767
|
-
}%%
|
768
|
-
|
769
|
-
static VALUE cParser_parse_strict(VALUE self)
|
770
|
-
{
|
771
|
-
char *p, *pe;
|
772
|
-
int cs = EVIL;
|
773
|
-
VALUE result = Qnil;
|
774
|
-
GET_PARSER;
|
775
|
-
|
776
|
-
%% write init;
|
777
|
-
p = json->source;
|
778
|
-
pe = p + json->len;
|
779
|
-
%% write exec;
|
780
|
-
|
781
|
-
if (cs >= JSON_first_final && p == pe) {
|
782
|
-
return result;
|
783
|
-
} else {
|
784
|
-
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
785
|
-
return Qnil;
|
786
|
-
}
|
787
|
-
}
|
788
|
-
|
789
|
-
|
790
|
-
%%{
|
791
|
-
machine JSON_quirks_mode;
|
792
|
-
|
793
|
-
write data;
|
794
|
-
|
795
|
-
include JSON_common;
|
796
|
-
|
797
789
|
action parse_value {
|
798
|
-
char *np = JSON_parse_value(json, fpc, pe, &result);
|
790
|
+
char *np = JSON_parse_value(json, fpc, pe, &result, 0);
|
799
791
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
800
792
|
}
|
801
793
|
|
@@ -804,26 +796,6 @@ static VALUE cParser_parse_strict(VALUE self)
|
|
804
796
|
) ignore*;
|
805
797
|
}%%
|
806
798
|
|
807
|
-
static VALUE cParser_parse_quirks_mode(VALUE self)
|
808
|
-
{
|
809
|
-
char *p, *pe;
|
810
|
-
int cs = EVIL;
|
811
|
-
VALUE result = Qnil;
|
812
|
-
GET_PARSER;
|
813
|
-
|
814
|
-
%% write init;
|
815
|
-
p = json->source;
|
816
|
-
pe = p + json->len;
|
817
|
-
%% write exec;
|
818
|
-
|
819
|
-
if (cs >= JSON_quirks_mode_first_final && p == pe) {
|
820
|
-
return result;
|
821
|
-
} else {
|
822
|
-
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
823
|
-
return Qnil;
|
824
|
-
}
|
825
|
-
}
|
826
|
-
|
827
799
|
/*
|
828
800
|
* call-seq: parse()
|
829
801
|
*
|
@@ -832,12 +804,21 @@ static VALUE cParser_parse_quirks_mode(VALUE self)
|
|
832
804
|
*/
|
833
805
|
static VALUE cParser_parse(VALUE self)
|
834
806
|
{
|
807
|
+
char *p, *pe;
|
808
|
+
int cs = EVIL;
|
809
|
+
VALUE result = Qnil;
|
835
810
|
GET_PARSER;
|
836
811
|
|
837
|
-
|
838
|
-
|
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;
|
839
819
|
} else {
|
840
|
-
|
820
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
821
|
+
return Qnil;
|
841
822
|
}
|
842
823
|
}
|
843
824
|
|
@@ -848,6 +829,7 @@ static void JSON_mark(void *ptr)
|
|
848
829
|
rb_gc_mark_maybe(json->create_id);
|
849
830
|
rb_gc_mark_maybe(json->object_class);
|
850
831
|
rb_gc_mark_maybe(json->array_class);
|
832
|
+
rb_gc_mark_maybe(json->decimal_class);
|
851
833
|
rb_gc_mark_maybe(json->match_string);
|
852
834
|
}
|
853
835
|
|
@@ -895,35 +877,34 @@ static VALUE cParser_source(VALUE self)
|
|
895
877
|
return rb_str_dup(json->Vsource);
|
896
878
|
}
|
897
879
|
|
898
|
-
/*
|
899
|
-
* call-seq: quirks_mode?()
|
900
|
-
*
|
901
|
-
* Returns a true, if this parser is in quirks_mode, false otherwise.
|
902
|
-
*/
|
903
|
-
static VALUE cParser_quirks_mode_p(VALUE self)
|
904
|
-
{
|
905
|
-
GET_PARSER;
|
906
|
-
return json->quirks_mode ? Qtrue : Qfalse;
|
907
|
-
}
|
908
|
-
|
909
|
-
|
910
880
|
void Init_parser(void)
|
911
881
|
{
|
882
|
+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
883
|
+
rb_ext_ractor_safe(true);
|
884
|
+
#endif
|
885
|
+
|
886
|
+
#undef rb_intern
|
912
887
|
rb_require("json/common");
|
913
888
|
mJSON = rb_define_module("JSON");
|
914
889
|
mExt = rb_define_module_under(mJSON, "Ext");
|
915
890
|
cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
|
916
891
|
eParserError = rb_path2class("JSON::ParserError");
|
917
892
|
eNestingError = rb_path2class("JSON::NestingError");
|
893
|
+
rb_gc_register_mark_object(eParserError);
|
894
|
+
rb_gc_register_mark_object(eNestingError);
|
918
895
|
rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
|
919
896
|
rb_define_method(cParser, "initialize", cParser_initialize, -1);
|
920
897
|
rb_define_method(cParser, "parse", cParser_parse, 0);
|
921
898
|
rb_define_method(cParser, "source", cParser_source, 0);
|
922
|
-
rb_define_method(cParser, "quirks_mode?", cParser_quirks_mode_p, 0);
|
923
899
|
|
924
900
|
CNaN = rb_const_get(mJSON, rb_intern("NaN"));
|
901
|
+
rb_gc_register_mark_object(CNaN);
|
902
|
+
|
925
903
|
CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
|
904
|
+
rb_gc_register_mark_object(CInfinity);
|
905
|
+
|
926
906
|
CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
|
907
|
+
rb_gc_register_mark_object(CMinusInfinity);
|
927
908
|
|
928
909
|
i_json_creatable_p = rb_intern("json_creatable?");
|
929
910
|
i_json_create = rb_intern("json_create");
|
@@ -933,9 +914,9 @@ void Init_parser(void)
|
|
933
914
|
i_max_nesting = rb_intern("max_nesting");
|
934
915
|
i_allow_nan = rb_intern("allow_nan");
|
935
916
|
i_symbolize_names = rb_intern("symbolize_names");
|
936
|
-
i_quirks_mode = rb_intern("quirks_mode");
|
937
917
|
i_object_class = rb_intern("object_class");
|
938
918
|
i_array_class = rb_intern("array_class");
|
919
|
+
i_decimal_class = rb_intern("decimal_class");
|
939
920
|
i_match = rb_intern("match");
|
940
921
|
i_match_string = rb_intern("match_string");
|
941
922
|
i_key_p = rb_intern("key?");
|
@@ -943,15 +924,10 @@ void Init_parser(void)
|
|
943
924
|
i_aset = rb_intern("[]=");
|
944
925
|
i_aref = rb_intern("[]");
|
945
926
|
i_leftshift = rb_intern("<<");
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
UTF_32BE = rb_enc_find("utf-32be");
|
951
|
-
UTF_32LE = rb_enc_find("utf-32le");
|
952
|
-
#else
|
953
|
-
i_iconv = rb_intern("iconv");
|
954
|
-
#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("-@");
|
955
931
|
}
|
956
932
|
|
957
933
|
/*
|