json 2.0.3 → 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.md +66 -0
- data/Gemfile +1 -3
- data/LICENSE +56 -0
- data/README.md +54 -21
- data/VERSION +1 -1
- data/ext/json/ext/fbuffer/fbuffer.h +0 -3
- data/ext/json/ext/generator/generator.c +229 -54
- data/ext/json/ext/generator/generator.h +5 -3
- data/ext/json/ext/parser/extconf.rb +25 -0
- data/ext/json/ext/parser/parser.c +180 -85
- data/ext/json/ext/parser/parser.h +2 -0
- data/ext/json/ext/parser/parser.rl +104 -9
- data/ext/json/extconf.rb +1 -0
- data/json.gemspec +0 -0
- data/lib/json/add/bigdecimal.rb +2 -2
- data/lib/json/add/complex.rb +2 -3
- data/lib/json/add/ostruct.rb +1 -1
- data/lib/json/add/rational.rb +2 -3
- data/lib/json/add/regexp.rb +2 -2
- data/lib/json/add/set.rb +29 -0
- data/lib/json/common.rb +372 -125
- data/lib/json/pure/generator.rb +31 -10
- data/lib/json/pure/parser.rb +35 -5
- data/lib/json/version.rb +1 -1
- data/lib/json.rb +549 -29
- 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/json_addition_test.rb +6 -0
- data/tests/json_common_interface_test.rb +47 -4
- data/tests/json_encoding_test.rb +2 -0
- data/tests/json_fixtures_test.rb +9 -1
- data/tests/json_generator_test.rb +30 -8
- data/tests/json_parser_test.rb +43 -12
- 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 +3 -7
- metadata +31 -44
- data/.gitignore +0 -17
- data/.travis.yml +0 -19
- data/README-json-jruby.md +0 -33
- data/Rakefile +0 -408
- 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 -443
- 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 -2347
- data/java/src/json/ext/Parser.rl +0 -878
- 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 -38
- data/json_pure.gemspec +0 -38
- data/references/rfc7159.txt +0 -899
- data/tools/diff.sh +0 -18
- data/tools/fuzz.rb +0 -131
- data/tools/server.rb +0 -62
@@ -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;
|
@@ -92,8 +92,9 @@ static VALUE CNaN, CInfinity, CMinusInfinity;
|
|
92
92
|
|
93
93
|
static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
94
94
|
i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
|
95
|
-
i_object_class, i_array_class,
|
96
|
-
i_match_string, i_aset, i_aref,
|
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;
|
97
98
|
|
98
99
|
%%{
|
99
100
|
machine JSON_common;
|
@@ -136,6 +137,7 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
|
136
137
|
fhold; fbreak;
|
137
138
|
} else {
|
138
139
|
if (NIL_P(json->object_class)) {
|
140
|
+
OBJ_FREEZE(last_name);
|
139
141
|
rb_hash_aset(*result, last_name, v);
|
140
142
|
} else {
|
141
143
|
rb_funcall(*result, i_aset, 2, last_name, v);
|
@@ -287,6 +289,10 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
287
289
|
%% write init;
|
288
290
|
%% write exec;
|
289
291
|
|
292
|
+
if (json->freeze) {
|
293
|
+
OBJ_FREEZE(*result);
|
294
|
+
}
|
295
|
+
|
290
296
|
if (cs >= JSON_value_first_final) {
|
291
297
|
return p;
|
292
298
|
} else {
|
@@ -347,11 +353,46 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
347
353
|
%% write exec;
|
348
354
|
|
349
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
|
+
|
350
384
|
long len = p - json->memo;
|
351
385
|
fbuffer_clear(json->fbuffer);
|
352
386
|
fbuffer_append(json->fbuffer, json->memo, len);
|
353
387
|
fbuffer_append_char(json->fbuffer, '\0');
|
354
|
-
|
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
|
+
|
355
396
|
return p + 1;
|
356
397
|
} else {
|
357
398
|
return NULL;
|
@@ -446,13 +487,21 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
|
|
446
487
|
break;
|
447
488
|
case 'u':
|
448
489
|
if (pe > stringEnd - 4) {
|
449
|
-
|
490
|
+
rb_enc_raise(
|
491
|
+
EXC_ENCODING eParserError,
|
492
|
+
"%u: incomplete unicode character escape sequence at '%s'", __LINE__, p
|
493
|
+
);
|
450
494
|
} else {
|
451
495
|
UTF32 ch = unescape_unicode((unsigned char *) ++pe);
|
452
496
|
pe += 3;
|
453
497
|
if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
|
454
498
|
pe++;
|
455
|
-
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
|
+
}
|
456
505
|
if (pe[0] == '\\' && pe[1] == 'u') {
|
457
506
|
UTF32 sur = unescape_unicode((unsigned char *) pe + 2);
|
458
507
|
ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16)
|
@@ -538,8 +587,23 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
538
587
|
|
539
588
|
if (json->symbolize_names && json->parsing_name) {
|
540
589
|
*result = rb_str_intern(*result);
|
541
|
-
} else {
|
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
|
542
605
|
rb_str_resize(*result, RSTRING_LEN(*result));
|
606
|
+
# endif
|
543
607
|
}
|
544
608
|
if (cs >= JSON_string_first_final) {
|
545
609
|
return p + 1;
|
@@ -647,6 +711,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
647
711
|
} else {
|
648
712
|
json->symbolize_names = 0;
|
649
713
|
}
|
714
|
+
tmp = ID2SYM(i_freeze);
|
715
|
+
if (option_given_p(opts, tmp)) {
|
716
|
+
json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
|
717
|
+
} else {
|
718
|
+
json->freeze = 0;
|
719
|
+
}
|
650
720
|
tmp = ID2SYM(i_create_additions);
|
651
721
|
if (option_given_p(opts, tmp)) {
|
652
722
|
json->create_additions = RTEST(rb_hash_aref(opts, tmp));
|
@@ -676,6 +746,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
676
746
|
} else {
|
677
747
|
json->array_class = Qnil;
|
678
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
|
+
}
|
679
755
|
tmp = ID2SYM(i_match_string);
|
680
756
|
if (option_given_p(opts, tmp)) {
|
681
757
|
VALUE match_string = rb_hash_aref(opts, tmp);
|
@@ -689,10 +765,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
689
765
|
} else {
|
690
766
|
json->max_nesting = 100;
|
691
767
|
json->allow_nan = 0;
|
692
|
-
json->create_additions =
|
768
|
+
json->create_additions = 0;
|
693
769
|
json->create_id = rb_funcall(mJSON, i_create_id, 0);
|
694
770
|
json->object_class = Qnil;
|
695
771
|
json->array_class = Qnil;
|
772
|
+
json->decimal_class = Qnil;
|
696
773
|
}
|
697
774
|
source = convert_encoding(StringValue(source));
|
698
775
|
StringValue(source);
|
@@ -752,6 +829,7 @@ static void JSON_mark(void *ptr)
|
|
752
829
|
rb_gc_mark_maybe(json->create_id);
|
753
830
|
rb_gc_mark_maybe(json->object_class);
|
754
831
|
rb_gc_mark_maybe(json->array_class);
|
832
|
+
rb_gc_mark_maybe(json->decimal_class);
|
755
833
|
rb_gc_mark_maybe(json->match_string);
|
756
834
|
}
|
757
835
|
|
@@ -801,20 +879,32 @@ static VALUE cParser_source(VALUE self)
|
|
801
879
|
|
802
880
|
void Init_parser(void)
|
803
881
|
{
|
882
|
+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
883
|
+
rb_ext_ractor_safe(true);
|
884
|
+
#endif
|
885
|
+
|
886
|
+
#undef rb_intern
|
804
887
|
rb_require("json/common");
|
805
888
|
mJSON = rb_define_module("JSON");
|
806
889
|
mExt = rb_define_module_under(mJSON, "Ext");
|
807
890
|
cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
|
808
891
|
eParserError = rb_path2class("JSON::ParserError");
|
809
892
|
eNestingError = rb_path2class("JSON::NestingError");
|
893
|
+
rb_gc_register_mark_object(eParserError);
|
894
|
+
rb_gc_register_mark_object(eNestingError);
|
810
895
|
rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
|
811
896
|
rb_define_method(cParser, "initialize", cParser_initialize, -1);
|
812
897
|
rb_define_method(cParser, "parse", cParser_parse, 0);
|
813
898
|
rb_define_method(cParser, "source", cParser_source, 0);
|
814
899
|
|
815
900
|
CNaN = rb_const_get(mJSON, rb_intern("NaN"));
|
901
|
+
rb_gc_register_mark_object(CNaN);
|
902
|
+
|
816
903
|
CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
|
904
|
+
rb_gc_register_mark_object(CInfinity);
|
905
|
+
|
817
906
|
CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
|
907
|
+
rb_gc_register_mark_object(CMinusInfinity);
|
818
908
|
|
819
909
|
i_json_creatable_p = rb_intern("json_creatable?");
|
820
910
|
i_json_create = rb_intern("json_create");
|
@@ -826,6 +916,7 @@ void Init_parser(void)
|
|
826
916
|
i_symbolize_names = rb_intern("symbolize_names");
|
827
917
|
i_object_class = rb_intern("object_class");
|
828
918
|
i_array_class = rb_intern("array_class");
|
919
|
+
i_decimal_class = rb_intern("decimal_class");
|
829
920
|
i_match = rb_intern("match");
|
830
921
|
i_match_string = rb_intern("match_string");
|
831
922
|
i_key_p = rb_intern("key?");
|
@@ -833,6 +924,10 @@ void Init_parser(void)
|
|
833
924
|
i_aset = rb_intern("[]=");
|
834
925
|
i_aref = rb_intern("[]");
|
835
926
|
i_leftshift = rb_intern("<<");
|
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("-@");
|
836
931
|
}
|
837
932
|
|
838
933
|
/*
|
data/ext/json/extconf.rb
CHANGED
data/json.gemspec
CHANGED
Binary file
|
data/lib/json/add/bigdecimal.rb
CHANGED
data/lib/json/add/complex.rb
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
|
3
3
|
require 'json'
|
4
4
|
end
|
5
|
-
defined?(::Complex) or require 'complex'
|
6
5
|
|
7
6
|
class Complex
|
8
7
|
|
@@ -23,7 +22,7 @@ class Complex
|
|
23
22
|
end
|
24
23
|
|
25
24
|
# Stores class name (Complex) along with real value <tt>r</tt> and imaginary value <tt>i</tt> as JSON string
|
26
|
-
def to_json(*)
|
27
|
-
as_json.to_json
|
25
|
+
def to_json(*args)
|
26
|
+
as_json.to_json(*args)
|
28
27
|
end
|
29
28
|
end
|
data/lib/json/add/ostruct.rb
CHANGED
data/lib/json/add/rational.rb
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
|
3
3
|
require 'json'
|
4
4
|
end
|
5
|
-
defined?(::Rational) or require 'rational'
|
6
5
|
|
7
6
|
class Rational
|
8
7
|
# Deserializes JSON string by converting numerator value <tt>n</tt>,
|
@@ -22,7 +21,7 @@ class Rational
|
|
22
21
|
end
|
23
22
|
|
24
23
|
# Stores class name (Rational) along with numerator value <tt>n</tt> and denominator value <tt>d</tt> as JSON string
|
25
|
-
def to_json(*)
|
26
|
-
as_json.to_json
|
24
|
+
def to_json(*args)
|
25
|
+
as_json.to_json(*args)
|
27
26
|
end
|
28
27
|
end
|
data/lib/json/add/regexp.rb
CHANGED
data/lib/json/add/set.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
|
2
|
+
require 'json'
|
3
|
+
end
|
4
|
+
defined?(::Set) or require 'set'
|
5
|
+
|
6
|
+
class Set
|
7
|
+
# Import a JSON Marshalled object.
|
8
|
+
#
|
9
|
+
# method used for JSON marshalling support.
|
10
|
+
def self.json_create(object)
|
11
|
+
new object['a']
|
12
|
+
end
|
13
|
+
|
14
|
+
# Marshal the object to JSON.
|
15
|
+
#
|
16
|
+
# method used for JSON marshalling support.
|
17
|
+
def as_json(*)
|
18
|
+
{
|
19
|
+
JSON.create_id => self.class.name,
|
20
|
+
'a' => to_a,
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
# return the JSON value
|
25
|
+
def to_json(*args)
|
26
|
+
as_json.to_json(*args)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|