json 2.3.0 → 2.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES.md +71 -5
- data/README.md +19 -3
- data/VERSION +1 -1
- data/ext/json/ext/generator/generator.c +132 -23
- data/ext/json/ext/generator/generator.h +5 -2
- data/ext/json/ext/parser/extconf.rb +26 -0
- data/ext/json/ext/parser/parser.c +2979 -1768
- data/ext/json/ext/parser/parser.h +6 -1
- data/ext/json/ext/parser/parser.rl +128 -38
- data/ext/json/extconf.rb +1 -0
- data/json.gemspec +0 -0
- data/lib/json/add/complex.rb +0 -1
- data/lib/json/add/rational.rb +0 -1
- data/lib/json/common.rb +370 -123
- data/lib/json/pure/generator.rb +29 -9
- data/lib/json/pure/parser.rb +23 -5
- data/lib/json/version.rb +1 -1
- data/lib/json.rb +549 -29
- metadata +17 -109
- data/.gitignore +0 -18
- data/.travis.yml +0 -24
- data/Gemfile +0 -14
- data/README-json-jruby.md +0 -33
- data/Rakefile +0 -413
- 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 -466
- 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 -490
- data/java/src/json/ext/OptionsReader.java +0 -113
- data/java/src/json/ext/Parser.java +0 -2362
- data/java/src/json/ext/Parser.rl +0 -893
- data/java/src/json/ext/ParserService.java +0 -34
- data/java/src/json/ext/RuntimeInfo.java +0 -116
- 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 -37
- data/json_pure.gemspec +0 -38
- data/lib/json/ext/.keep +0 -0
- data/references/rfc7159.txt +0 -899
- 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/obsolete_fail1.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/json_addition_test.rb +0 -203
- data/tests/json_common_interface_test.rb +0 -126
- data/tests/json_encoding_test.rb +0 -107
- data/tests/json_ext_parser_test.rb +0 -15
- data/tests/json_fixtures_test.rb +0 -32
- data/tests/json_generator_test.rb +0 -421
- data/tests/json_generic_object_test.rb +0 -82
- data/tests/json_parser_test.rb +0 -472
- data/tests/json_string_matching_test.rb +0 -38
- data/tests/test_helper.rb +0 -17
- data/tools/diff.sh +0 -18
- data/tools/fuzz.rb +0 -131
- data/tools/server.rb +0 -62
|
@@ -13,6 +13,10 @@
|
|
|
13
13
|
#include "st.h"
|
|
14
14
|
#endif
|
|
15
15
|
|
|
16
|
+
#ifndef MAYBE_UNUSED
|
|
17
|
+
# define MAYBE_UNUSED(x) x
|
|
18
|
+
#endif
|
|
19
|
+
|
|
16
20
|
#define option_given_p(opts, key) RTEST(rb_funcall(opts, i_key_p, 1, key))
|
|
17
21
|
|
|
18
22
|
/* unicode */
|
|
@@ -37,6 +41,7 @@ typedef struct JSON_ParserStruct {
|
|
|
37
41
|
int allow_nan;
|
|
38
42
|
int parsing_name;
|
|
39
43
|
int symbolize_names;
|
|
44
|
+
int freeze;
|
|
40
45
|
VALUE object_class;
|
|
41
46
|
VALUE array_class;
|
|
42
47
|
VALUE decimal_class;
|
|
@@ -62,7 +67,7 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
|
62
67
|
static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result);
|
|
63
68
|
static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result);
|
|
64
69
|
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
|
|
65
|
-
static VALUE json_string_unescape(
|
|
70
|
+
static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int symbolize);
|
|
66
71
|
static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result);
|
|
67
72
|
static VALUE convert_encoding(VALUE source);
|
|
68
73
|
static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self);
|
|
@@ -89,13 +89,12 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
|
|
|
89
89
|
|
|
90
90
|
static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
|
|
91
91
|
static VALUE CNaN, CInfinity, CMinusInfinity;
|
|
92
|
-
static VALUE cBigDecimal = Qundef;
|
|
93
92
|
|
|
94
93
|
static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
|
95
94
|
i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
|
|
96
95
|
i_object_class, i_array_class, i_decimal_class, i_key_p,
|
|
97
96
|
i_deep_const_get, i_match, i_match_string, i_aset, i_aref,
|
|
98
|
-
i_leftshift, i_new,
|
|
97
|
+
i_leftshift, i_new, i_try_convert, i_freeze, i_uminus;
|
|
99
98
|
|
|
100
99
|
%%{
|
|
101
100
|
machine JSON_common;
|
|
@@ -138,6 +137,7 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
|
|
138
137
|
fhold; fbreak;
|
|
139
138
|
} else {
|
|
140
139
|
if (NIL_P(json->object_class)) {
|
|
140
|
+
OBJ_FREEZE(last_name);
|
|
141
141
|
rb_hash_aset(*result, last_name, v);
|
|
142
142
|
} else {
|
|
143
143
|
rb_funcall(*result, i_aset, 2, last_name, v);
|
|
@@ -289,6 +289,10 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
|
289
289
|
%% write init;
|
|
290
290
|
%% write exec;
|
|
291
291
|
|
|
292
|
+
if (json->freeze) {
|
|
293
|
+
OBJ_FREEZE(*result);
|
|
294
|
+
}
|
|
295
|
+
|
|
292
296
|
if (cs >= JSON_value_first_final) {
|
|
293
297
|
return p;
|
|
294
298
|
} else {
|
|
@@ -340,19 +344,6 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
|
|
|
340
344
|
) (^[0-9Ee.\-]? @exit );
|
|
341
345
|
}%%
|
|
342
346
|
|
|
343
|
-
static int is_bigdecimal_class(VALUE obj)
|
|
344
|
-
{
|
|
345
|
-
if (cBigDecimal == Qundef) {
|
|
346
|
-
if (rb_const_defined(rb_cObject, i_BigDecimal)) {
|
|
347
|
-
cBigDecimal = rb_const_get_at(rb_cObject, i_BigDecimal);
|
|
348
|
-
}
|
|
349
|
-
else {
|
|
350
|
-
return 0;
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
return obj == cBigDecimal;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
347
|
static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
|
357
348
|
{
|
|
358
349
|
int cs = EVIL;
|
|
@@ -362,21 +353,46 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
|
362
353
|
%% write exec;
|
|
363
354
|
|
|
364
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
|
+
|
|
365
384
|
long len = p - json->memo;
|
|
366
385
|
fbuffer_clear(json->fbuffer);
|
|
367
386
|
fbuffer_append(json->fbuffer, json->memo, len);
|
|
368
387
|
fbuffer_append_char(json->fbuffer, '\0');
|
|
369
|
-
|
|
370
|
-
|
|
388
|
+
|
|
389
|
+
if (method_id) {
|
|
390
|
+
VALUE text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
|
|
391
|
+
*result = rb_funcallv(mod, method_id, 1, &text);
|
|
371
392
|
} else {
|
|
372
|
-
|
|
373
|
-
text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
|
|
374
|
-
if (is_bigdecimal_class(json->decimal_class)) {
|
|
375
|
-
*result = rb_funcall(Qnil, i_BigDecimal, 1, text);
|
|
376
|
-
} else {
|
|
377
|
-
*result = rb_funcall(json->decimal_class, i_new, 1, text);
|
|
378
|
-
}
|
|
393
|
+
*result = DBL2NUM(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
|
|
379
394
|
}
|
|
395
|
+
|
|
380
396
|
return p + 1;
|
|
381
397
|
} else {
|
|
382
398
|
return NULL;
|
|
@@ -436,17 +452,37 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
|
436
452
|
}
|
|
437
453
|
}
|
|
438
454
|
|
|
439
|
-
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)
|
|
440
457
|
{
|
|
441
|
-
|
|
458
|
+
VALUE result = Qnil;
|
|
459
|
+
size_t bufferSize = stringEnd - string;
|
|
460
|
+
char *p = string, *pe = string, *unescape, *bufferStart, *buffer;
|
|
442
461
|
int unescape_len;
|
|
443
462
|
char buf[4];
|
|
444
463
|
|
|
464
|
+
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
|
|
465
|
+
# ifdef HAVE_RB_ENC_INTERNED_STR
|
|
466
|
+
bufferStart = buffer = ALLOC_N(char, bufferSize ? bufferSize : 1);
|
|
467
|
+
# else
|
|
468
|
+
bufferStart = buffer = ALLOC_N(char, bufferSize);
|
|
469
|
+
# endif
|
|
470
|
+
} else {
|
|
471
|
+
# ifdef HAVE_RB_ENC_INTERNED_STR
|
|
472
|
+
bufferStart = buffer = ALLOCA_N(char, bufferSize ? bufferSize : 1);
|
|
473
|
+
# else
|
|
474
|
+
bufferStart = buffer = ALLOCA_N(char, bufferSize);
|
|
475
|
+
# endif
|
|
476
|
+
}
|
|
477
|
+
|
|
445
478
|
while (pe < stringEnd) {
|
|
446
479
|
if (*pe == '\\') {
|
|
447
480
|
unescape = (char *) "?";
|
|
448
481
|
unescape_len = 1;
|
|
449
|
-
if (pe > p)
|
|
482
|
+
if (pe > p) {
|
|
483
|
+
MEMCPY(buffer, p, char, pe - p);
|
|
484
|
+
buffer += pe - p;
|
|
485
|
+
}
|
|
450
486
|
switch (*++pe) {
|
|
451
487
|
case 'n':
|
|
452
488
|
unescape = (char *) "\n";
|
|
@@ -471,6 +507,9 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
|
|
|
471
507
|
break;
|
|
472
508
|
case 'u':
|
|
473
509
|
if (pe > stringEnd - 4) {
|
|
510
|
+
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
|
|
511
|
+
free(bufferStart);
|
|
512
|
+
}
|
|
474
513
|
rb_enc_raise(
|
|
475
514
|
EXC_ENCODING eParserError,
|
|
476
515
|
"%u: incomplete unicode character escape sequence at '%s'", __LINE__, p
|
|
@@ -481,6 +520,9 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
|
|
|
481
520
|
if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
|
|
482
521
|
pe++;
|
|
483
522
|
if (pe > stringEnd - 6) {
|
|
523
|
+
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
|
|
524
|
+
free(bufferStart);
|
|
525
|
+
}
|
|
484
526
|
rb_enc_raise(
|
|
485
527
|
EXC_ENCODING eParserError,
|
|
486
528
|
"%u: incomplete surrogate pair at '%s'", __LINE__, p
|
|
@@ -504,13 +546,55 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
|
|
|
504
546
|
p = pe;
|
|
505
547
|
continue;
|
|
506
548
|
}
|
|
507
|
-
|
|
549
|
+
MEMCPY(buffer, unescape, char, unescape_len);
|
|
550
|
+
buffer += unescape_len;
|
|
508
551
|
p = ++pe;
|
|
509
552
|
} else {
|
|
510
553
|
pe++;
|
|
511
554
|
}
|
|
512
555
|
}
|
|
513
|
-
|
|
556
|
+
|
|
557
|
+
if (pe > p) {
|
|
558
|
+
MEMCPY(buffer, p, char, pe - p);
|
|
559
|
+
buffer += pe - p;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
# ifdef HAVE_RB_ENC_INTERNED_STR
|
|
563
|
+
if (intern) {
|
|
564
|
+
result = rb_enc_interned_str(bufferStart, (long)(buffer - bufferStart), rb_utf8_encoding());
|
|
565
|
+
} else {
|
|
566
|
+
result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
|
|
567
|
+
}
|
|
568
|
+
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
|
|
569
|
+
free(bufferStart);
|
|
570
|
+
}
|
|
571
|
+
# else
|
|
572
|
+
result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
|
|
573
|
+
|
|
574
|
+
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
|
|
575
|
+
free(bufferStart);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
if (intern) {
|
|
579
|
+
# if STR_UMINUS_DEDUPE_FROZEN
|
|
580
|
+
// Starting from MRI 2.8 it is preferable to freeze the string
|
|
581
|
+
// before deduplication so that it can be interned directly
|
|
582
|
+
// otherwise it would be duplicated first which is wasteful.
|
|
583
|
+
result = rb_funcall(rb_str_freeze(result), i_uminus, 0);
|
|
584
|
+
# elif STR_UMINUS_DEDUPE
|
|
585
|
+
// MRI 2.5 and older do not deduplicate strings that are already
|
|
586
|
+
// frozen.
|
|
587
|
+
result = rb_funcall(result, i_uminus, 0);
|
|
588
|
+
# else
|
|
589
|
+
result = rb_str_freeze(result);
|
|
590
|
+
# endif
|
|
591
|
+
}
|
|
592
|
+
# endif
|
|
593
|
+
|
|
594
|
+
if (symbolize) {
|
|
595
|
+
result = rb_str_intern(result);
|
|
596
|
+
}
|
|
597
|
+
|
|
514
598
|
return result;
|
|
515
599
|
}
|
|
516
600
|
|
|
@@ -521,12 +605,11 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
|
|
|
521
605
|
write data;
|
|
522
606
|
|
|
523
607
|
action parse_string {
|
|
524
|
-
*result = json_string_unescape(
|
|
608
|
+
*result = json_string_unescape(json->memo + 1, p, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names);
|
|
525
609
|
if (NIL_P(*result)) {
|
|
526
610
|
fhold;
|
|
527
611
|
fbreak;
|
|
528
612
|
} else {
|
|
529
|
-
FORCE_UTF8(*result);
|
|
530
613
|
fexec p + 1;
|
|
531
614
|
}
|
|
532
615
|
}
|
|
@@ -553,7 +636,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
|
553
636
|
int cs = EVIL;
|
|
554
637
|
VALUE match_string;
|
|
555
638
|
|
|
556
|
-
*result = rb_str_buf_new(0);
|
|
557
639
|
%% write init;
|
|
558
640
|
json->memo = p;
|
|
559
641
|
%% write exec;
|
|
@@ -569,11 +651,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
|
569
651
|
}
|
|
570
652
|
}
|
|
571
653
|
|
|
572
|
-
if (json->symbolize_names && json->parsing_name) {
|
|
573
|
-
*result = rb_str_intern(*result);
|
|
574
|
-
} else if (RB_TYPE_P(*result, T_STRING)) {
|
|
575
|
-
rb_str_resize(*result, RSTRING_LEN(*result));
|
|
576
|
-
}
|
|
577
654
|
if (cs >= JSON_string_first_final) {
|
|
578
655
|
return p + 1;
|
|
579
656
|
} else {
|
|
@@ -680,6 +757,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
680
757
|
} else {
|
|
681
758
|
json->symbolize_names = 0;
|
|
682
759
|
}
|
|
760
|
+
tmp = ID2SYM(i_freeze);
|
|
761
|
+
if (option_given_p(opts, tmp)) {
|
|
762
|
+
json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
|
|
763
|
+
} else {
|
|
764
|
+
json->freeze = 0;
|
|
765
|
+
}
|
|
683
766
|
tmp = ID2SYM(i_create_additions);
|
|
684
767
|
if (option_given_p(opts, tmp)) {
|
|
685
768
|
json->create_additions = RTEST(rb_hash_aref(opts, tmp));
|
|
@@ -764,6 +847,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
764
847
|
*
|
|
765
848
|
* Parses the current JSON text _source_ and returns the complete data
|
|
766
849
|
* structure as a result.
|
|
850
|
+
* It raises JSON::ParseError if fail to parse.
|
|
767
851
|
*/
|
|
768
852
|
static VALUE cParser_parse(VALUE self)
|
|
769
853
|
{
|
|
@@ -842,6 +926,10 @@ static VALUE cParser_source(VALUE self)
|
|
|
842
926
|
|
|
843
927
|
void Init_parser(void)
|
|
844
928
|
{
|
|
929
|
+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
|
930
|
+
rb_ext_ractor_safe(true);
|
|
931
|
+
#endif
|
|
932
|
+
|
|
845
933
|
#undef rb_intern
|
|
846
934
|
rb_require("json/common");
|
|
847
935
|
mJSON = rb_define_module("JSON");
|
|
@@ -884,7 +972,9 @@ void Init_parser(void)
|
|
|
884
972
|
i_aref = rb_intern("[]");
|
|
885
973
|
i_leftshift = rb_intern("<<");
|
|
886
974
|
i_new = rb_intern("new");
|
|
887
|
-
|
|
975
|
+
i_try_convert = rb_intern("try_convert");
|
|
976
|
+
i_freeze = rb_intern("freeze");
|
|
977
|
+
i_uminus = rb_intern("-@");
|
|
888
978
|
}
|
|
889
979
|
|
|
890
980
|
/*
|
data/ext/json/extconf.rb
CHANGED
data/json.gemspec
CHANGED
|
Binary file
|
data/lib/json/add/complex.rb
CHANGED