json 1.8.6 → 2.6.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} +248 -98
- data/LICENSE +56 -0
- data/README.md +188 -108
- data/VERSION +1 -1
- data/ext/json/ext/fbuffer/fbuffer.h +0 -3
- data/ext/json/ext/generator/generator.c +227 -111
- data/ext/json/ext/generator/generator.h +5 -8
- data/ext/json/ext/parser/extconf.rb +29 -0
- data/ext/json/ext/parser/parser.c +3013 -1915
- data/ext/json/ext/parser/parser.h +10 -6
- data/ext/json/ext/parser/parser.rl +197 -183
- data/ext/json/extconf.rb +1 -1
- data/json.gemspec +0 -0
- 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/generator.rb +73 -124
- data/lib/json/pure/parser.rb +63 -85
- data/lib/json/pure.rb +2 -8
- data/lib/json/version.rb +2 -1
- data/lib/json.rb +550 -29
- metadata +20 -127
- data/.gitignore +0 -17
- data/.travis.yml +0 -18
- data/Gemfile +0 -7
- 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/lib/json/ext/.keep +0 -0
- data/tests/fixtures/fail1.json +0 -1
- data/tests/fixtures/fail10.json +0 -1
- data/tests/fixtures/fail11.json +0 -1
- data/tests/fixtures/fail12.json +0 -1
- data/tests/fixtures/fail13.json +0 -1
- data/tests/fixtures/fail14.json +0 -1
- data/tests/fixtures/fail18.json +0 -1
- data/tests/fixtures/fail19.json +0 -1
- data/tests/fixtures/fail2.json +0 -1
- data/tests/fixtures/fail20.json +0 -1
- data/tests/fixtures/fail21.json +0 -1
- data/tests/fixtures/fail22.json +0 -1
- data/tests/fixtures/fail23.json +0 -1
- data/tests/fixtures/fail24.json +0 -1
- data/tests/fixtures/fail25.json +0 -1
- data/tests/fixtures/fail27.json +0 -2
- data/tests/fixtures/fail28.json +0 -2
- data/tests/fixtures/fail3.json +0 -1
- data/tests/fixtures/fail4.json +0 -1
- data/tests/fixtures/fail5.json +0 -1
- data/tests/fixtures/fail6.json +0 -1
- data/tests/fixtures/fail7.json +0 -1
- data/tests/fixtures/fail8.json +0 -1
- data/tests/fixtures/fail9.json +0 -1
- data/tests/fixtures/pass1.json +0 -56
- data/tests/fixtures/pass15.json +0 -1
- data/tests/fixtures/pass16.json +0 -1
- data/tests/fixtures/pass17.json +0 -1
- data/tests/fixtures/pass2.json +0 -1
- data/tests/fixtures/pass26.json +0 -1
- data/tests/fixtures/pass3.json +0 -6
- data/tests/setup_variant.rb +0 -11
- data/tests/test_json.rb +0 -519
- data/tests/test_json_addition.rb +0 -196
- data/tests/test_json_encoding.rb +0 -65
- data/tests/test_json_fixtures.rb +0 -35
- data/tests/test_json_generate.rb +0 -348
- data/tests/test_json_generic_object.rb +0 -75
- 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
|
@@ -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
|
|
|
@@ -421,17 +452,29 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
|
421
452
|
}
|
|
422
453
|
}
|
|
423
454
|
|
|
424
|
-
static
|
|
455
|
+
static const size_t MAX_STACK_BUFFER_SIZE = 128;
|
|
456
|
+
static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int symbolize)
|
|
425
457
|
{
|
|
426
|
-
|
|
458
|
+
VALUE result = Qnil;
|
|
459
|
+
size_t bufferSize = stringEnd - string;
|
|
460
|
+
char *p = string, *pe = string, *unescape, *bufferStart, *buffer;
|
|
427
461
|
int unescape_len;
|
|
428
462
|
char buf[4];
|
|
429
463
|
|
|
464
|
+
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
|
|
465
|
+
bufferStart = buffer = ALLOC_N(char, bufferSize);
|
|
466
|
+
} else {
|
|
467
|
+
bufferStart = buffer = ALLOCA_N(char, bufferSize);
|
|
468
|
+
}
|
|
469
|
+
|
|
430
470
|
while (pe < stringEnd) {
|
|
431
471
|
if (*pe == '\\') {
|
|
432
472
|
unescape = (char *) "?";
|
|
433
473
|
unescape_len = 1;
|
|
434
|
-
if (pe > p)
|
|
474
|
+
if (pe > p) {
|
|
475
|
+
MEMCPY(buffer, p, char, pe - p);
|
|
476
|
+
buffer += pe - p;
|
|
477
|
+
}
|
|
435
478
|
switch (*++pe) {
|
|
436
479
|
case 'n':
|
|
437
480
|
unescape = (char *) "\n";
|
|
@@ -456,13 +499,27 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
|
|
|
456
499
|
break;
|
|
457
500
|
case 'u':
|
|
458
501
|
if (pe > stringEnd - 4) {
|
|
459
|
-
|
|
502
|
+
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
|
|
503
|
+
free(bufferStart);
|
|
504
|
+
}
|
|
505
|
+
rb_enc_raise(
|
|
506
|
+
EXC_ENCODING eParserError,
|
|
507
|
+
"%u: incomplete unicode character escape sequence at '%s'", __LINE__, p
|
|
508
|
+
);
|
|
460
509
|
} else {
|
|
461
510
|
UTF32 ch = unescape_unicode((unsigned char *) ++pe);
|
|
462
511
|
pe += 3;
|
|
463
512
|
if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
|
|
464
513
|
pe++;
|
|
465
|
-
if (pe > stringEnd - 6)
|
|
514
|
+
if (pe > stringEnd - 6) {
|
|
515
|
+
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
|
|
516
|
+
free(bufferStart);
|
|
517
|
+
}
|
|
518
|
+
rb_enc_raise(
|
|
519
|
+
EXC_ENCODING eParserError,
|
|
520
|
+
"%u: incomplete surrogate pair at '%s'", __LINE__, p
|
|
521
|
+
);
|
|
522
|
+
}
|
|
466
523
|
if (pe[0] == '\\' && pe[1] == 'u') {
|
|
467
524
|
UTF32 sur = unescape_unicode((unsigned char *) pe + 2);
|
|
468
525
|
ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16)
|
|
@@ -481,13 +538,55 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
|
|
|
481
538
|
p = pe;
|
|
482
539
|
continue;
|
|
483
540
|
}
|
|
484
|
-
|
|
541
|
+
MEMCPY(buffer, unescape, char, unescape_len);
|
|
542
|
+
buffer += unescape_len;
|
|
485
543
|
p = ++pe;
|
|
486
544
|
} else {
|
|
487
545
|
pe++;
|
|
488
546
|
}
|
|
489
547
|
}
|
|
490
|
-
|
|
548
|
+
|
|
549
|
+
if (pe > p) {
|
|
550
|
+
MEMCPY(buffer, p, char, pe - p);
|
|
551
|
+
buffer += pe - p;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
# ifdef HAVE_RB_ENC_INTERNED_STR
|
|
555
|
+
if (intern) {
|
|
556
|
+
result = rb_enc_interned_str(bufferStart, (long)(buffer - bufferStart), rb_utf8_encoding());
|
|
557
|
+
} else {
|
|
558
|
+
result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
|
|
559
|
+
}
|
|
560
|
+
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
|
|
561
|
+
free(bufferStart);
|
|
562
|
+
}
|
|
563
|
+
# else
|
|
564
|
+
result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
|
|
565
|
+
|
|
566
|
+
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
|
|
567
|
+
free(bufferStart);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
if (intern) {
|
|
571
|
+
# if STR_UMINUS_DEDUPE_FROZEN
|
|
572
|
+
// Starting from MRI 2.8 it is preferable to freeze the string
|
|
573
|
+
// before deduplication so that it can be interned directly
|
|
574
|
+
// otherwise it would be duplicated first which is wasteful.
|
|
575
|
+
result = rb_funcall(rb_str_freeze(result), i_uminus, 0);
|
|
576
|
+
# elif STR_UMINUS_DEDUPE
|
|
577
|
+
// MRI 2.5 and older do not deduplicate strings that are already
|
|
578
|
+
// frozen.
|
|
579
|
+
result = rb_funcall(result, i_uminus, 0);
|
|
580
|
+
# else
|
|
581
|
+
result = rb_str_freeze(result);
|
|
582
|
+
# endif
|
|
583
|
+
}
|
|
584
|
+
# endif
|
|
585
|
+
|
|
586
|
+
if (symbolize) {
|
|
587
|
+
result = rb_str_intern(result);
|
|
588
|
+
}
|
|
589
|
+
|
|
491
590
|
return result;
|
|
492
591
|
}
|
|
493
592
|
|
|
@@ -498,12 +597,11 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
|
|
|
498
597
|
write data;
|
|
499
598
|
|
|
500
599
|
action parse_string {
|
|
501
|
-
*result = json_string_unescape(
|
|
600
|
+
*result = json_string_unescape(json->memo + 1, p, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names);
|
|
502
601
|
if (NIL_P(*result)) {
|
|
503
602
|
fhold;
|
|
504
603
|
fbreak;
|
|
505
604
|
} else {
|
|
506
|
-
FORCE_UTF8(*result);
|
|
507
605
|
fexec p + 1;
|
|
508
606
|
}
|
|
509
607
|
}
|
|
@@ -530,7 +628,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
|
530
628
|
int cs = EVIL;
|
|
531
629
|
VALUE match_string;
|
|
532
630
|
|
|
533
|
-
*result = rb_str_buf_new(0);
|
|
534
631
|
%% write init;
|
|
535
632
|
json->memo = p;
|
|
536
633
|
%% write exec;
|
|
@@ -546,9 +643,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
|
546
643
|
}
|
|
547
644
|
}
|
|
548
645
|
|
|
549
|
-
if (json->symbolize_names && json->parsing_name) {
|
|
550
|
-
*result = rb_str_intern(*result);
|
|
551
|
-
}
|
|
552
646
|
if (cs >= JSON_string_first_final) {
|
|
553
647
|
return p + 1;
|
|
554
648
|
} else {
|
|
@@ -570,41 +664,16 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
|
570
664
|
|
|
571
665
|
static VALUE convert_encoding(VALUE source)
|
|
572
666
|
{
|
|
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
667
|
#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);
|
|
668
|
+
rb_encoding *enc = rb_enc_get(source);
|
|
669
|
+
if (enc == rb_ascii8bit_encoding()) {
|
|
670
|
+
if (OBJ_FROZEN(source)) {
|
|
671
|
+
source = rb_str_dup(source);
|
|
607
672
|
}
|
|
673
|
+
FORCE_UTF8(source);
|
|
674
|
+
} else {
|
|
675
|
+
source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding());
|
|
676
|
+
}
|
|
608
677
|
#endif
|
|
609
678
|
return source;
|
|
610
679
|
}
|
|
@@ -627,8 +696,9 @@ static VALUE convert_encoding(VALUE source)
|
|
|
627
696
|
* defiance of RFC 4627 to be parsed by the Parser. This option defaults to
|
|
628
697
|
* false.
|
|
629
698
|
* * *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.
|
|
699
|
+
* (keys) in a JSON object. Otherwise strings are returned, which is
|
|
700
|
+
* also the default. It's not possible to use this option in
|
|
701
|
+
* conjunction with the *create_additions* option.
|
|
632
702
|
* * *create_additions*: If set to false, the Parser doesn't create
|
|
633
703
|
* additions even if a matching class and create_id was found. This option
|
|
634
704
|
* defaults to false.
|
|
@@ -679,12 +749,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
679
749
|
} else {
|
|
680
750
|
json->symbolize_names = 0;
|
|
681
751
|
}
|
|
682
|
-
tmp = ID2SYM(
|
|
752
|
+
tmp = ID2SYM(i_freeze);
|
|
683
753
|
if (option_given_p(opts, tmp)) {
|
|
684
|
-
|
|
685
|
-
json->quirks_mode = RTEST(quirks_mode) ? 1 : 0;
|
|
754
|
+
json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
|
|
686
755
|
} else {
|
|
687
|
-
json->
|
|
756
|
+
json->freeze = 0;
|
|
688
757
|
}
|
|
689
758
|
tmp = ID2SYM(i_create_additions);
|
|
690
759
|
if (option_given_p(opts, tmp)) {
|
|
@@ -692,6 +761,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
692
761
|
} else {
|
|
693
762
|
json->create_additions = 0;
|
|
694
763
|
}
|
|
764
|
+
if (json->symbolize_names && json->create_additions) {
|
|
765
|
+
rb_raise(rb_eArgError,
|
|
766
|
+
"options :symbolize_names and :create_additions cannot be "
|
|
767
|
+
" used in conjunction");
|
|
768
|
+
}
|
|
695
769
|
tmp = ID2SYM(i_create_id);
|
|
696
770
|
if (option_given_p(opts, tmp)) {
|
|
697
771
|
json->create_id = rb_hash_aref(opts, tmp);
|
|
@@ -710,6 +784,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
710
784
|
} else {
|
|
711
785
|
json->array_class = Qnil;
|
|
712
786
|
}
|
|
787
|
+
tmp = ID2SYM(i_decimal_class);
|
|
788
|
+
if (option_given_p(opts, tmp)) {
|
|
789
|
+
json->decimal_class = rb_hash_aref(opts, tmp);
|
|
790
|
+
} else {
|
|
791
|
+
json->decimal_class = Qnil;
|
|
792
|
+
}
|
|
713
793
|
tmp = ID2SYM(i_match_string);
|
|
714
794
|
if (option_given_p(opts, tmp)) {
|
|
715
795
|
VALUE match_string = rb_hash_aref(opts, tmp);
|
|
@@ -723,16 +803,14 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
723
803
|
} else {
|
|
724
804
|
json->max_nesting = 100;
|
|
725
805
|
json->allow_nan = 0;
|
|
726
|
-
json->create_additions =
|
|
806
|
+
json->create_additions = 0;
|
|
727
807
|
json->create_id = rb_funcall(mJSON, i_create_id, 0);
|
|
728
808
|
json->object_class = Qnil;
|
|
729
809
|
json->array_class = Qnil;
|
|
810
|
+
json->decimal_class = Qnil;
|
|
730
811
|
}
|
|
812
|
+
source = convert_encoding(StringValue(source));
|
|
731
813
|
StringValue(source);
|
|
732
|
-
if (!json->quirks_mode) {
|
|
733
|
-
source = convert_encoding(source);
|
|
734
|
-
}
|
|
735
|
-
json->current_nesting = 0;
|
|
736
814
|
json->len = RSTRING_LEN(source);
|
|
737
815
|
json->source = RSTRING_PTR(source);;
|
|
738
816
|
json->Vsource = source;
|
|
@@ -746,56 +824,8 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
746
824
|
|
|
747
825
|
include JSON_common;
|
|
748
826
|
|
|
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
827
|
action parse_value {
|
|
798
|
-
char *np = JSON_parse_value(json, fpc, pe, &result);
|
|
828
|
+
char *np = JSON_parse_value(json, fpc, pe, &result, 0);
|
|
799
829
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
|
800
830
|
}
|
|
801
831
|
|
|
@@ -804,26 +834,6 @@ static VALUE cParser_parse_strict(VALUE self)
|
|
|
804
834
|
) ignore*;
|
|
805
835
|
}%%
|
|
806
836
|
|
|
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
837
|
/*
|
|
828
838
|
* call-seq: parse()
|
|
829
839
|
*
|
|
@@ -832,12 +842,21 @@ static VALUE cParser_parse_quirks_mode(VALUE self)
|
|
|
832
842
|
*/
|
|
833
843
|
static VALUE cParser_parse(VALUE self)
|
|
834
844
|
{
|
|
845
|
+
char *p, *pe;
|
|
846
|
+
int cs = EVIL;
|
|
847
|
+
VALUE result = Qnil;
|
|
835
848
|
GET_PARSER;
|
|
836
849
|
|
|
837
|
-
|
|
838
|
-
|
|
850
|
+
%% write init;
|
|
851
|
+
p = json->source;
|
|
852
|
+
pe = p + json->len;
|
|
853
|
+
%% write exec;
|
|
854
|
+
|
|
855
|
+
if (cs >= JSON_first_final && p == pe) {
|
|
856
|
+
return result;
|
|
839
857
|
} else {
|
|
840
|
-
|
|
858
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
|
859
|
+
return Qnil;
|
|
841
860
|
}
|
|
842
861
|
}
|
|
843
862
|
|
|
@@ -848,6 +867,7 @@ static void JSON_mark(void *ptr)
|
|
|
848
867
|
rb_gc_mark_maybe(json->create_id);
|
|
849
868
|
rb_gc_mark_maybe(json->object_class);
|
|
850
869
|
rb_gc_mark_maybe(json->array_class);
|
|
870
|
+
rb_gc_mark_maybe(json->decimal_class);
|
|
851
871
|
rb_gc_mark_maybe(json->match_string);
|
|
852
872
|
}
|
|
853
873
|
|
|
@@ -895,35 +915,34 @@ static VALUE cParser_source(VALUE self)
|
|
|
895
915
|
return rb_str_dup(json->Vsource);
|
|
896
916
|
}
|
|
897
917
|
|
|
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
918
|
void Init_parser(void)
|
|
911
919
|
{
|
|
920
|
+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
|
921
|
+
rb_ext_ractor_safe(true);
|
|
922
|
+
#endif
|
|
923
|
+
|
|
924
|
+
#undef rb_intern
|
|
912
925
|
rb_require("json/common");
|
|
913
926
|
mJSON = rb_define_module("JSON");
|
|
914
927
|
mExt = rb_define_module_under(mJSON, "Ext");
|
|
915
928
|
cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
|
|
916
929
|
eParserError = rb_path2class("JSON::ParserError");
|
|
917
930
|
eNestingError = rb_path2class("JSON::NestingError");
|
|
931
|
+
rb_gc_register_mark_object(eParserError);
|
|
932
|
+
rb_gc_register_mark_object(eNestingError);
|
|
918
933
|
rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
|
|
919
934
|
rb_define_method(cParser, "initialize", cParser_initialize, -1);
|
|
920
935
|
rb_define_method(cParser, "parse", cParser_parse, 0);
|
|
921
936
|
rb_define_method(cParser, "source", cParser_source, 0);
|
|
922
|
-
rb_define_method(cParser, "quirks_mode?", cParser_quirks_mode_p, 0);
|
|
923
937
|
|
|
924
938
|
CNaN = rb_const_get(mJSON, rb_intern("NaN"));
|
|
939
|
+
rb_gc_register_mark_object(CNaN);
|
|
940
|
+
|
|
925
941
|
CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
|
|
942
|
+
rb_gc_register_mark_object(CInfinity);
|
|
943
|
+
|
|
926
944
|
CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
|
|
945
|
+
rb_gc_register_mark_object(CMinusInfinity);
|
|
927
946
|
|
|
928
947
|
i_json_creatable_p = rb_intern("json_creatable?");
|
|
929
948
|
i_json_create = rb_intern("json_create");
|
|
@@ -933,9 +952,9 @@ void Init_parser(void)
|
|
|
933
952
|
i_max_nesting = rb_intern("max_nesting");
|
|
934
953
|
i_allow_nan = rb_intern("allow_nan");
|
|
935
954
|
i_symbolize_names = rb_intern("symbolize_names");
|
|
936
|
-
i_quirks_mode = rb_intern("quirks_mode");
|
|
937
955
|
i_object_class = rb_intern("object_class");
|
|
938
956
|
i_array_class = rb_intern("array_class");
|
|
957
|
+
i_decimal_class = rb_intern("decimal_class");
|
|
939
958
|
i_match = rb_intern("match");
|
|
940
959
|
i_match_string = rb_intern("match_string");
|
|
941
960
|
i_key_p = rb_intern("key?");
|
|
@@ -943,15 +962,10 @@ void Init_parser(void)
|
|
|
943
962
|
i_aset = rb_intern("[]=");
|
|
944
963
|
i_aref = rb_intern("[]");
|
|
945
964
|
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
|
|
965
|
+
i_new = rb_intern("new");
|
|
966
|
+
i_try_convert = rb_intern("try_convert");
|
|
967
|
+
i_freeze = rb_intern("freeze");
|
|
968
|
+
i_uminus = rb_intern("-@");
|
|
955
969
|
}
|
|
956
970
|
|
|
957
971
|
/*
|
data/ext/json/extconf.rb
CHANGED
data/json.gemspec
CHANGED
|
Binary file
|