json 2.3.0 → 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 +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 +2970 -1768
- data/ext/json/ext/parser/parser.h +6 -1
- data/ext/json/ext/parser/parser.rl +119 -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,29 @@ 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
|
+
bufferStart = buffer = ALLOC_N(char, bufferSize);
|
|
466
|
+
} else {
|
|
467
|
+
bufferStart = buffer = ALLOCA_N(char, bufferSize);
|
|
468
|
+
}
|
|
469
|
+
|
|
445
470
|
while (pe < stringEnd) {
|
|
446
471
|
if (*pe == '\\') {
|
|
447
472
|
unescape = (char *) "?";
|
|
448
473
|
unescape_len = 1;
|
|
449
|
-
if (pe > p)
|
|
474
|
+
if (pe > p) {
|
|
475
|
+
MEMCPY(buffer, p, char, pe - p);
|
|
476
|
+
buffer += pe - p;
|
|
477
|
+
}
|
|
450
478
|
switch (*++pe) {
|
|
451
479
|
case 'n':
|
|
452
480
|
unescape = (char *) "\n";
|
|
@@ -471,6 +499,9 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
|
|
|
471
499
|
break;
|
|
472
500
|
case 'u':
|
|
473
501
|
if (pe > stringEnd - 4) {
|
|
502
|
+
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
|
|
503
|
+
free(bufferStart);
|
|
504
|
+
}
|
|
474
505
|
rb_enc_raise(
|
|
475
506
|
EXC_ENCODING eParserError,
|
|
476
507
|
"%u: incomplete unicode character escape sequence at '%s'", __LINE__, p
|
|
@@ -481,6 +512,9 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
|
|
|
481
512
|
if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
|
|
482
513
|
pe++;
|
|
483
514
|
if (pe > stringEnd - 6) {
|
|
515
|
+
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
|
|
516
|
+
free(bufferStart);
|
|
517
|
+
}
|
|
484
518
|
rb_enc_raise(
|
|
485
519
|
EXC_ENCODING eParserError,
|
|
486
520
|
"%u: incomplete surrogate pair at '%s'", __LINE__, p
|
|
@@ -504,13 +538,55 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
|
|
|
504
538
|
p = pe;
|
|
505
539
|
continue;
|
|
506
540
|
}
|
|
507
|
-
|
|
541
|
+
MEMCPY(buffer, unescape, char, unescape_len);
|
|
542
|
+
buffer += unescape_len;
|
|
508
543
|
p = ++pe;
|
|
509
544
|
} else {
|
|
510
545
|
pe++;
|
|
511
546
|
}
|
|
512
547
|
}
|
|
513
|
-
|
|
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
|
+
|
|
514
590
|
return result;
|
|
515
591
|
}
|
|
516
592
|
|
|
@@ -521,12 +597,11 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
|
|
|
521
597
|
write data;
|
|
522
598
|
|
|
523
599
|
action parse_string {
|
|
524
|
-
*result = json_string_unescape(
|
|
600
|
+
*result = json_string_unescape(json->memo + 1, p, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names);
|
|
525
601
|
if (NIL_P(*result)) {
|
|
526
602
|
fhold;
|
|
527
603
|
fbreak;
|
|
528
604
|
} else {
|
|
529
|
-
FORCE_UTF8(*result);
|
|
530
605
|
fexec p + 1;
|
|
531
606
|
}
|
|
532
607
|
}
|
|
@@ -553,7 +628,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
|
553
628
|
int cs = EVIL;
|
|
554
629
|
VALUE match_string;
|
|
555
630
|
|
|
556
|
-
*result = rb_str_buf_new(0);
|
|
557
631
|
%% write init;
|
|
558
632
|
json->memo = p;
|
|
559
633
|
%% write exec;
|
|
@@ -569,11 +643,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
|
569
643
|
}
|
|
570
644
|
}
|
|
571
645
|
|
|
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
646
|
if (cs >= JSON_string_first_final) {
|
|
578
647
|
return p + 1;
|
|
579
648
|
} else {
|
|
@@ -680,6 +749,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
680
749
|
} else {
|
|
681
750
|
json->symbolize_names = 0;
|
|
682
751
|
}
|
|
752
|
+
tmp = ID2SYM(i_freeze);
|
|
753
|
+
if (option_given_p(opts, tmp)) {
|
|
754
|
+
json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
|
|
755
|
+
} else {
|
|
756
|
+
json->freeze = 0;
|
|
757
|
+
}
|
|
683
758
|
tmp = ID2SYM(i_create_additions);
|
|
684
759
|
if (option_given_p(opts, tmp)) {
|
|
685
760
|
json->create_additions = RTEST(rb_hash_aref(opts, tmp));
|
|
@@ -842,6 +917,10 @@ static VALUE cParser_source(VALUE self)
|
|
|
842
917
|
|
|
843
918
|
void Init_parser(void)
|
|
844
919
|
{
|
|
920
|
+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
|
921
|
+
rb_ext_ractor_safe(true);
|
|
922
|
+
#endif
|
|
923
|
+
|
|
845
924
|
#undef rb_intern
|
|
846
925
|
rb_require("json/common");
|
|
847
926
|
mJSON = rb_define_module("JSON");
|
|
@@ -884,7 +963,9 @@ void Init_parser(void)
|
|
|
884
963
|
i_aref = rb_intern("[]");
|
|
885
964
|
i_leftshift = rb_intern("<<");
|
|
886
965
|
i_new = rb_intern("new");
|
|
887
|
-
|
|
966
|
+
i_try_convert = rb_intern("try_convert");
|
|
967
|
+
i_freeze = rb_intern("freeze");
|
|
968
|
+
i_uminus = rb_intern("-@");
|
|
888
969
|
}
|
|
889
970
|
|
|
890
971
|
/*
|
data/ext/json/extconf.rb
CHANGED
data/json.gemspec
CHANGED
|
Binary file
|
data/lib/json/add/complex.rb
CHANGED