json 2.3.0 → 2.6.2
Sign up to get free protection for your applications and to get access to all the features.
- 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