json 2.3.1 → 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 +4 -4
- data/CHANGES.md +22 -0
- data/LICENSE +56 -0
- data/VERSION +1 -1
- data/ext/json/ext/generator/generator.c +60 -11
- data/ext/json/ext/generator/generator.h +5 -2
- data/ext/json/ext/parser/extconf.rb +25 -0
- data/ext/json/ext/parser/parser.c +110 -68
- data/ext/json/ext/parser/parser.h +1 -0
- data/ext/json/ext/parser/parser.rl +67 -25
- data/ext/json/extconf.rb +1 -0
- data/json.gemspec +11 -77
- data/lib/json.rb +171 -0
- data/lib/json/add/complex.rb +0 -1
- data/lib/json/add/rational.rb +0 -1
- data/lib/json/common.rb +240 -228
- data/lib/json/pure/generator.rb +28 -8
- data/lib/json/pure/parser.rb +20 -2
- data/lib/json/version.rb +1 -1
- 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 +0 -4
- data/tests/json_common_interface_test.rb +43 -0
- data/tests/json_fixtures_test.rb +3 -0
- data/tests/json_generator_test.rb +16 -38
- data/tests/json_parser_test.rb +25 -0
- 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 -3
- metadata +16 -37
- data/.gitignore +0 -18
- data/.travis.yml +0 -26
- data/README-json-jruby.md +0 -33
- data/Rakefile +0 -334
- 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 -33
- data/references/rfc7159.txt +0 -899
- data/tools/diff.sh +0 -18
- data/tools/fuzz.rb +0 -131
- data/tools/server.rb +0 -62
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4ba367cf703870f72ec5de7af43e713095df4b9c88cb0ae12a4c10455052383a
|
4
|
+
data.tar.gz: 622fc0230b9a26ddde47fb3e81c2cf2f0143c22cbfd2429019db1a0f9eef5aaa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1cab7c9113f03333b720a039fd065d5dd376ab3b4dda1630ccf316ee72121ed4a8abfc06a576be524ce7a86b78e9af917b507fbe95411efef11a563da95295c4
|
7
|
+
data.tar.gz: 68b7cec95107a831286fc3ff36971cd9cc0efbc29157bc0df95a16238b5594214ffca0d417f2dd9011f9e26bf4e163e01e179cbf06f8c053df68c4d60f2416cc
|
data/CHANGES.md
CHANGED
@@ -1,5 +1,27 @@
|
|
1
1
|
# Changes
|
2
2
|
|
3
|
+
## 2020-12-22 (2.5.1)
|
4
|
+
|
5
|
+
* Restore the compatibility for constants of JSON class.
|
6
|
+
|
7
|
+
## 2020-12-22 (2.5.0)
|
8
|
+
|
9
|
+
* Ready to Ractor-safe at Ruby 3.0.
|
10
|
+
|
11
|
+
## 2020-12-17 (2.4.1)
|
12
|
+
|
13
|
+
* Restore version.rb with 2.4.1
|
14
|
+
|
15
|
+
## 2020-12-15 (2.4.0)
|
16
|
+
|
17
|
+
* Implement a freeze: parser option #447
|
18
|
+
* Fix an issue with generate_pretty and empty objects in the Ruby and Java implementations #449
|
19
|
+
* Fix JSON.load_file doc #448
|
20
|
+
* Fix pure parser with unclosed arrays / objects #425
|
21
|
+
* bundle the LICENSE file in the gem #444
|
22
|
+
* Add an option to escape forward slash character #405
|
23
|
+
* RDoc for JSON #439 #446 #442 #434 #433 #430
|
24
|
+
|
3
25
|
## 2020-06-30 (2.3.1)
|
4
26
|
|
5
27
|
* Spelling and grammar fixes for comments. Pull request #191 by Josh
|
data/LICENSE
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.jp>.
|
2
|
+
You can redistribute it and/or modify it under either the terms of the
|
3
|
+
2-clause BSDL (see the file BSDL), or the conditions below:
|
4
|
+
|
5
|
+
1. You may make and give away verbatim copies of the source form of the
|
6
|
+
software without restriction, provided that you duplicate all of the
|
7
|
+
original copyright notices and associated disclaimers.
|
8
|
+
|
9
|
+
2. You may modify your copy of the software in any way, provided that
|
10
|
+
you do at least ONE of the following:
|
11
|
+
|
12
|
+
a) place your modifications in the Public Domain or otherwise
|
13
|
+
make them Freely Available, such as by posting said
|
14
|
+
modifications to Usenet or an equivalent medium, or by allowing
|
15
|
+
the author to include your modifications in the software.
|
16
|
+
|
17
|
+
b) use the modified software only within your corporation or
|
18
|
+
organization.
|
19
|
+
|
20
|
+
c) give non-standard binaries non-standard names, with
|
21
|
+
instructions on where to get the original software distribution.
|
22
|
+
|
23
|
+
d) make other distribution arrangements with the author.
|
24
|
+
|
25
|
+
3. You may distribute the software in object code or binary form,
|
26
|
+
provided that you do at least ONE of the following:
|
27
|
+
|
28
|
+
a) distribute the binaries and library files of the software,
|
29
|
+
together with instructions (in the manual page or equivalent)
|
30
|
+
on where to get the original distribution.
|
31
|
+
|
32
|
+
b) accompany the distribution with the machine-readable source of
|
33
|
+
the software.
|
34
|
+
|
35
|
+
c) give non-standard binaries non-standard names, with
|
36
|
+
instructions on where to get the original software distribution.
|
37
|
+
|
38
|
+
d) make other distribution arrangements with the author.
|
39
|
+
|
40
|
+
4. You may modify and include the part of the software into any other
|
41
|
+
software (possibly commercial). But some files in the distribution
|
42
|
+
are not written by the author, so that they are not under these terms.
|
43
|
+
|
44
|
+
For the list of those files and their copying conditions, see the
|
45
|
+
file LEGAL.
|
46
|
+
|
47
|
+
5. The scripts and library files supplied as input to or produced as
|
48
|
+
output from the software do not automatically fall under the
|
49
|
+
copyright of the software, but belong to whomever generated them,
|
50
|
+
and may be sold commercially, and may be aggregated with this
|
51
|
+
software.
|
52
|
+
|
53
|
+
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
54
|
+
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
55
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
56
|
+
PURPOSE.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.5.1
|
@@ -15,14 +15,13 @@ static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
|
|
15
15
|
#endif
|
16
16
|
mFloat, mString, mString_Extend,
|
17
17
|
mTrueClass, mFalseClass, mNilClass, eGeneratorError,
|
18
|
-
eNestingError
|
19
|
-
i_SAFE_STATE_PROTOTYPE;
|
18
|
+
eNestingError;
|
20
19
|
|
21
20
|
static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
|
22
21
|
i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only,
|
23
22
|
i_pack, i_unpack, i_create_id, i_extend, i_key_p,
|
24
23
|
i_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth,
|
25
|
-
i_buffer_initial_length, i_dup;
|
24
|
+
i_buffer_initial_length, i_dup, i_escape_slash;
|
26
25
|
|
27
26
|
/*
|
28
27
|
* Copyright 2001-2004 Unicode, Inc.
|
@@ -130,7 +129,7 @@ static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16
|
|
130
129
|
|
131
130
|
/* Converts string to a JSON string in FBuffer buffer, where all but the ASCII
|
132
131
|
* and control characters are JSON escaped. */
|
133
|
-
static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
|
132
|
+
static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escape_slash)
|
134
133
|
{
|
135
134
|
const UTF8 *source = (UTF8 *) RSTRING_PTR(string);
|
136
135
|
const UTF8 *sourceEnd = source + RSTRING_LEN(string);
|
@@ -180,6 +179,11 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
|
|
180
179
|
case '"':
|
181
180
|
fbuffer_append(buffer, "\\\"", 2);
|
182
181
|
break;
|
182
|
+
case '/':
|
183
|
+
if(escape_slash) {
|
184
|
+
fbuffer_append(buffer, "\\/", 2);
|
185
|
+
break;
|
186
|
+
}
|
183
187
|
default:
|
184
188
|
fbuffer_append_char(buffer, (char)ch);
|
185
189
|
break;
|
@@ -229,7 +233,7 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
|
|
229
233
|
* characters required by the JSON standard are JSON escaped. The remaining
|
230
234
|
* characters (should be UTF8) are just passed through and appended to the
|
231
235
|
* result. */
|
232
|
-
static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
|
236
|
+
static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slash)
|
233
237
|
{
|
234
238
|
const char *ptr = RSTRING_PTR(string), *p;
|
235
239
|
unsigned long len = RSTRING_LEN(string), start = 0, end = 0;
|
@@ -280,6 +284,12 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
|
|
280
284
|
escape = "\\\"";
|
281
285
|
escape_len = 2;
|
282
286
|
break;
|
287
|
+
case '/':
|
288
|
+
if(escape_slash) {
|
289
|
+
escape = "\\/";
|
290
|
+
escape_len = 2;
|
291
|
+
break;
|
292
|
+
}
|
283
293
|
default:
|
284
294
|
{
|
285
295
|
unsigned short clen = 1;
|
@@ -609,13 +619,18 @@ static size_t State_memsize(const void *ptr)
|
|
609
619
|
return size;
|
610
620
|
}
|
611
621
|
|
622
|
+
#ifndef HAVE_RB_EXT_RACTOR_SAFE
|
623
|
+
# undef RUBY_TYPED_FROZEN_SHAREABLE
|
624
|
+
# define RUBY_TYPED_FROZEN_SHAREABLE 0
|
625
|
+
#endif
|
626
|
+
|
612
627
|
#ifdef NEW_TYPEDDATA_WRAPPER
|
613
628
|
static const rb_data_type_t JSON_Generator_State_type = {
|
614
629
|
"JSON/Generator/State",
|
615
630
|
{NULL, State_free, State_memsize,},
|
616
631
|
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
|
617
632
|
0, 0,
|
618
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
633
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE,
|
619
634
|
#endif
|
620
635
|
};
|
621
636
|
#endif
|
@@ -716,6 +731,8 @@ static VALUE cState_configure(VALUE self, VALUE opts)
|
|
716
731
|
state->allow_nan = RTEST(tmp);
|
717
732
|
tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
|
718
733
|
state->ascii_only = RTEST(tmp);
|
734
|
+
tmp = rb_hash_aref(opts, ID2SYM(i_escape_slash));
|
735
|
+
state->escape_slash = RTEST(tmp);
|
719
736
|
return self;
|
720
737
|
}
|
721
738
|
|
@@ -750,6 +767,7 @@ static VALUE cState_to_h(VALUE self)
|
|
750
767
|
rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
|
751
768
|
rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
|
752
769
|
rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
|
770
|
+
rb_hash_aset(result, ID2SYM(i_escape_slash), state->escape_slash ? Qtrue : Qfalse);
|
753
771
|
rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
|
754
772
|
rb_hash_aset(result, ID2SYM(i_buffer_initial_length), LONG2FIX(state->buffer_initial_length));
|
755
773
|
return result;
|
@@ -934,9 +952,9 @@ static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_S
|
|
934
952
|
}
|
935
953
|
#endif
|
936
954
|
if (state->ascii_only) {
|
937
|
-
convert_UTF8_to_JSON_ASCII(buffer, obj);
|
955
|
+
convert_UTF8_to_JSON_ASCII(buffer, obj, state->escape_slash);
|
938
956
|
} else {
|
939
|
-
convert_UTF8_to_JSON(buffer, obj);
|
957
|
+
convert_UTF8_to_JSON(buffer, obj, state->escape_slash);
|
940
958
|
}
|
941
959
|
fbuffer_append_char(buffer, '"');
|
942
960
|
}
|
@@ -1152,8 +1170,7 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
|
|
1152
1170
|
} else if (rb_obj_is_kind_of(opts, rb_cHash)) {
|
1153
1171
|
return rb_funcall(self, i_new, 1, opts);
|
1154
1172
|
} else {
|
1155
|
-
|
1156
|
-
return rb_funcall(prototype, i_dup, 0);
|
1173
|
+
return rb_class_new_instance(0, NULL, cState);
|
1157
1174
|
}
|
1158
1175
|
}
|
1159
1176
|
|
@@ -1377,6 +1394,31 @@ static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
|
|
1377
1394
|
return state->max_nesting = FIX2LONG(depth);
|
1378
1395
|
}
|
1379
1396
|
|
1397
|
+
/*
|
1398
|
+
* call-seq: escape_slash
|
1399
|
+
*
|
1400
|
+
* If this boolean is true, the forward slashes will be escaped in
|
1401
|
+
* the json output.
|
1402
|
+
*/
|
1403
|
+
static VALUE cState_escape_slash(VALUE self)
|
1404
|
+
{
|
1405
|
+
GET_STATE(self);
|
1406
|
+
return state->escape_slash ? Qtrue : Qfalse;
|
1407
|
+
}
|
1408
|
+
|
1409
|
+
/*
|
1410
|
+
* call-seq: escape_slash=(depth)
|
1411
|
+
*
|
1412
|
+
* This sets whether or not the forward slashes will be escaped in
|
1413
|
+
* the json output.
|
1414
|
+
*/
|
1415
|
+
static VALUE cState_escape_slash_set(VALUE self, VALUE enable)
|
1416
|
+
{
|
1417
|
+
GET_STATE(self);
|
1418
|
+
state->escape_slash = RTEST(enable);
|
1419
|
+
return Qnil;
|
1420
|
+
}
|
1421
|
+
|
1380
1422
|
/*
|
1381
1423
|
* call-seq: allow_nan?
|
1382
1424
|
*
|
@@ -1460,6 +1502,10 @@ static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_l
|
|
1460
1502
|
*/
|
1461
1503
|
void Init_generator(void)
|
1462
1504
|
{
|
1505
|
+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
1506
|
+
rb_ext_ractor_safe(true);
|
1507
|
+
#endif
|
1508
|
+
|
1463
1509
|
#undef rb_intern
|
1464
1510
|
rb_require("json/common");
|
1465
1511
|
|
@@ -1489,6 +1535,9 @@ void Init_generator(void)
|
|
1489
1535
|
rb_define_method(cState, "array_nl=", cState_array_nl_set, 1);
|
1490
1536
|
rb_define_method(cState, "max_nesting", cState_max_nesting, 0);
|
1491
1537
|
rb_define_method(cState, "max_nesting=", cState_max_nesting_set, 1);
|
1538
|
+
rb_define_method(cState, "escape_slash", cState_escape_slash, 0);
|
1539
|
+
rb_define_method(cState, "escape_slash?", cState_escape_slash, 0);
|
1540
|
+
rb_define_method(cState, "escape_slash=", cState_escape_slash_set, 1);
|
1492
1541
|
rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
|
1493
1542
|
rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
|
1494
1543
|
rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
|
@@ -1545,6 +1594,7 @@ void Init_generator(void)
|
|
1545
1594
|
i_object_nl = rb_intern("object_nl");
|
1546
1595
|
i_array_nl = rb_intern("array_nl");
|
1547
1596
|
i_max_nesting = rb_intern("max_nesting");
|
1597
|
+
i_escape_slash = rb_intern("escape_slash");
|
1548
1598
|
i_allow_nan = rb_intern("allow_nan");
|
1549
1599
|
i_ascii_only = rb_intern("ascii_only");
|
1550
1600
|
i_depth = rb_intern("depth");
|
@@ -1565,5 +1615,4 @@ void Init_generator(void)
|
|
1565
1615
|
i_encoding = rb_intern("encoding");
|
1566
1616
|
i_encode = rb_intern("encode");
|
1567
1617
|
#endif
|
1568
|
-
i_SAFE_STATE_PROTOTYPE = rb_intern("SAFE_STATE_PROTOTYPE");
|
1569
1618
|
}
|
@@ -49,8 +49,8 @@ static const UTF32 halfMask = 0x3FFUL;
|
|
49
49
|
static unsigned char isLegalUTF8(const UTF8 *source, unsigned long length);
|
50
50
|
static void unicode_escape(char *buf, UTF16 character);
|
51
51
|
static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16 character);
|
52
|
-
static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string);
|
53
|
-
static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string);
|
52
|
+
static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escape_slash);
|
53
|
+
static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slash);
|
54
54
|
static char *fstrndup(const char *ptr, unsigned long len);
|
55
55
|
|
56
56
|
/* ruby api and some helpers */
|
@@ -72,6 +72,7 @@ typedef struct JSON_Generator_StateStruct {
|
|
72
72
|
long max_nesting;
|
73
73
|
char allow_nan;
|
74
74
|
char ascii_only;
|
75
|
+
char escape_slash;
|
75
76
|
long depth;
|
76
77
|
long buffer_initial_length;
|
77
78
|
} JSON_Generator_State;
|
@@ -150,6 +151,8 @@ static VALUE cState_allow_nan_p(VALUE self);
|
|
150
151
|
static VALUE cState_ascii_only_p(VALUE self);
|
151
152
|
static VALUE cState_depth(VALUE self);
|
152
153
|
static VALUE cState_depth_set(VALUE self, VALUE depth);
|
154
|
+
static VALUE cState_escape_slash(VALUE self);
|
155
|
+
static VALUE cState_escape_slash_set(VALUE self, VALUE depth);
|
153
156
|
static FBuffer *cState_prepare_buffer(VALUE self);
|
154
157
|
#ifndef ZALLOC
|
155
158
|
#define ZALLOC(type) ((type *)ruby_zalloc(sizeof(type)))
|
@@ -3,4 +3,29 @@ require 'mkmf'
|
|
3
3
|
|
4
4
|
have_func("rb_enc_raise", "ruby.h")
|
5
5
|
|
6
|
+
# checking if String#-@ (str_uminus) dedupes... '
|
7
|
+
begin
|
8
|
+
a = -(%w(t e s t).join)
|
9
|
+
b = -(%w(t e s t).join)
|
10
|
+
if a.equal?(b)
|
11
|
+
$CFLAGS << ' -DSTR_UMINUS_DEDUPE=1 '
|
12
|
+
else
|
13
|
+
$CFLAGS << ' -DSTR_UMINUS_DEDUPE=0 '
|
14
|
+
end
|
15
|
+
rescue NoMethodError
|
16
|
+
$CFLAGS << ' -DSTR_UMINUS_DEDUPE=0 '
|
17
|
+
end
|
18
|
+
|
19
|
+
# checking if String#-@ (str_uminus) directly interns frozen strings... '
|
20
|
+
begin
|
21
|
+
s = rand.to_s.freeze
|
22
|
+
if (-s).equal?(s) && (-s.dup).equal?(s)
|
23
|
+
$CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=1 '
|
24
|
+
else
|
25
|
+
$CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=0 '
|
26
|
+
end
|
27
|
+
rescue NoMethodError
|
28
|
+
$CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=0 '
|
29
|
+
end
|
30
|
+
|
6
31
|
create_makefile 'json/ext/parser'
|
@@ -91,13 +91,12 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
|
|
91
91
|
|
92
92
|
static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
|
93
93
|
static VALUE CNaN, CInfinity, CMinusInfinity;
|
94
|
-
static VALUE cBigDecimal = Qundef;
|
95
94
|
|
96
95
|
static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
97
96
|
i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
|
98
97
|
i_object_class, i_array_class, i_decimal_class, i_key_p,
|
99
98
|
i_deep_const_get, i_match, i_match_string, i_aset, i_aref,
|
100
|
-
i_leftshift, i_new,
|
99
|
+
i_leftshift, i_new, i_try_convert, i_freeze, i_uminus;
|
101
100
|
|
102
101
|
|
103
102
|
#line 126 "parser.rl"
|
@@ -869,6 +868,10 @@ case 28:
|
|
869
868
|
|
870
869
|
#line 292 "parser.rl"
|
871
870
|
|
871
|
+
if (json->freeze) {
|
872
|
+
OBJ_FREEZE(*result);
|
873
|
+
}
|
874
|
+
|
872
875
|
if (cs >= JSON_value_first_final) {
|
873
876
|
return p;
|
874
877
|
} else {
|
@@ -877,7 +880,7 @@ case 28:
|
|
877
880
|
}
|
878
881
|
|
879
882
|
|
880
|
-
#line
|
883
|
+
#line 885 "parser.c"
|
881
884
|
enum {JSON_integer_start = 1};
|
882
885
|
enum {JSON_integer_first_final = 3};
|
883
886
|
enum {JSON_integer_error = 0};
|
@@ -885,7 +888,7 @@ enum {JSON_integer_error = 0};
|
|
885
888
|
enum {JSON_integer_en_main = 1};
|
886
889
|
|
887
890
|
|
888
|
-
#line
|
891
|
+
#line 312 "parser.rl"
|
889
892
|
|
890
893
|
|
891
894
|
static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
@@ -893,15 +896,15 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
|
|
893
896
|
int cs = EVIL;
|
894
897
|
|
895
898
|
|
896
|
-
#line
|
899
|
+
#line 901 "parser.c"
|
897
900
|
{
|
898
901
|
cs = JSON_integer_start;
|
899
902
|
}
|
900
903
|
|
901
|
-
#line
|
904
|
+
#line 319 "parser.rl"
|
902
905
|
json->memo = p;
|
903
906
|
|
904
|
-
#line
|
907
|
+
#line 909 "parser.c"
|
905
908
|
{
|
906
909
|
if ( p == pe )
|
907
910
|
goto _test_eof;
|
@@ -935,14 +938,14 @@ case 3:
|
|
935
938
|
goto st0;
|
936
939
|
goto tr4;
|
937
940
|
tr4:
|
938
|
-
#line
|
941
|
+
#line 309 "parser.rl"
|
939
942
|
{ p--; {p++; cs = 4; goto _out;} }
|
940
943
|
goto st4;
|
941
944
|
st4:
|
942
945
|
if ( ++p == pe )
|
943
946
|
goto _test_eof4;
|
944
947
|
case 4:
|
945
|
-
#line
|
948
|
+
#line 950 "parser.c"
|
946
949
|
goto st0;
|
947
950
|
st5:
|
948
951
|
if ( ++p == pe )
|
@@ -961,7 +964,7 @@ case 5:
|
|
961
964
|
_out: {}
|
962
965
|
}
|
963
966
|
|
964
|
-
#line
|
967
|
+
#line 321 "parser.rl"
|
965
968
|
|
966
969
|
if (cs >= JSON_integer_first_final) {
|
967
970
|
long len = p - json->memo;
|
@@ -976,7 +979,7 @@ case 5:
|
|
976
979
|
}
|
977
980
|
|
978
981
|
|
979
|
-
#line
|
982
|
+
#line 984 "parser.c"
|
980
983
|
enum {JSON_float_start = 1};
|
981
984
|
enum {JSON_float_first_final = 8};
|
982
985
|
enum {JSON_float_error = 0};
|
@@ -984,36 +987,23 @@ enum {JSON_float_error = 0};
|
|
984
987
|
enum {JSON_float_en_main = 1};
|
985
988
|
|
986
989
|
|
987
|
-
#line
|
988
|
-
|
990
|
+
#line 346 "parser.rl"
|
989
991
|
|
990
|
-
static int is_bigdecimal_class(VALUE obj)
|
991
|
-
{
|
992
|
-
if (cBigDecimal == Qundef) {
|
993
|
-
if (rb_const_defined(rb_cObject, i_BigDecimal)) {
|
994
|
-
cBigDecimal = rb_const_get_at(rb_cObject, i_BigDecimal);
|
995
|
-
}
|
996
|
-
else {
|
997
|
-
return 0;
|
998
|
-
}
|
999
|
-
}
|
1000
|
-
return obj == cBigDecimal;
|
1001
|
-
}
|
1002
992
|
|
1003
993
|
static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
1004
994
|
{
|
1005
995
|
int cs = EVIL;
|
1006
996
|
|
1007
997
|
|
1008
|
-
#line
|
998
|
+
#line 1013 "parser.c"
|
1009
999
|
{
|
1010
1000
|
cs = JSON_float_start;
|
1011
1001
|
}
|
1012
1002
|
|
1013
|
-
#line
|
1003
|
+
#line 366 "parser.rl"
|
1014
1004
|
json->memo = p;
|
1015
1005
|
|
1016
|
-
#line
|
1006
|
+
#line 1021 "parser.c"
|
1017
1007
|
{
|
1018
1008
|
if ( p == pe )
|
1019
1009
|
goto _test_eof;
|
@@ -1071,14 +1061,14 @@ case 8:
|
|
1071
1061
|
goto st0;
|
1072
1062
|
goto tr9;
|
1073
1063
|
tr9:
|
1074
|
-
#line
|
1064
|
+
#line 340 "parser.rl"
|
1075
1065
|
{ p--; {p++; cs = 9; goto _out;} }
|
1076
1066
|
goto st9;
|
1077
1067
|
st9:
|
1078
1068
|
if ( ++p == pe )
|
1079
1069
|
goto _test_eof9;
|
1080
1070
|
case 9:
|
1081
|
-
#line
|
1071
|
+
#line 1086 "parser.c"
|
1082
1072
|
goto st0;
|
1083
1073
|
st5:
|
1084
1074
|
if ( ++p == pe )
|
@@ -1139,24 +1129,49 @@ case 7:
|
|
1139
1129
|
_out: {}
|
1140
1130
|
}
|
1141
1131
|
|
1142
|
-
#line
|
1132
|
+
#line 368 "parser.rl"
|
1143
1133
|
|
1144
1134
|
if (cs >= JSON_float_first_final) {
|
1135
|
+
VALUE mod = Qnil;
|
1136
|
+
ID method_id = 0;
|
1137
|
+
if (rb_respond_to(json->decimal_class, i_try_convert)) {
|
1138
|
+
mod = json->decimal_class;
|
1139
|
+
method_id = i_try_convert;
|
1140
|
+
} else if (rb_respond_to(json->decimal_class, i_new)) {
|
1141
|
+
mod = json->decimal_class;
|
1142
|
+
method_id = i_new;
|
1143
|
+
} else if (RB_TYPE_P(json->decimal_class, T_CLASS)) {
|
1144
|
+
VALUE name = rb_class_name(json->decimal_class);
|
1145
|
+
const char *name_cstr = RSTRING_PTR(name);
|
1146
|
+
const char *last_colon = strrchr(name_cstr, ':');
|
1147
|
+
if (last_colon) {
|
1148
|
+
const char *mod_path_end = last_colon - 1;
|
1149
|
+
VALUE mod_path = rb_str_substr(name, 0, mod_path_end - name_cstr);
|
1150
|
+
mod = rb_path_to_class(mod_path);
|
1151
|
+
|
1152
|
+
const char *method_name_beg = last_colon + 1;
|
1153
|
+
long before_len = method_name_beg - name_cstr;
|
1154
|
+
long len = RSTRING_LEN(name) - before_len;
|
1155
|
+
VALUE method_name = rb_str_substr(name, before_len, len);
|
1156
|
+
method_id = SYM2ID(rb_str_intern(method_name));
|
1157
|
+
} else {
|
1158
|
+
mod = rb_mKernel;
|
1159
|
+
method_id = SYM2ID(rb_str_intern(name));
|
1160
|
+
}
|
1161
|
+
}
|
1162
|
+
|
1145
1163
|
long len = p - json->memo;
|
1146
1164
|
fbuffer_clear(json->fbuffer);
|
1147
1165
|
fbuffer_append(json->fbuffer, json->memo, len);
|
1148
1166
|
fbuffer_append_char(json->fbuffer, '\0');
|
1149
|
-
|
1150
|
-
|
1167
|
+
|
1168
|
+
if (method_id) {
|
1169
|
+
VALUE text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
|
1170
|
+
*result = rb_funcallv(mod, method_id, 1, &text);
|
1151
1171
|
} else {
|
1152
|
-
|
1153
|
-
text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
|
1154
|
-
if (is_bigdecimal_class(json->decimal_class)) {
|
1155
|
-
*result = rb_funcall(Qnil, i_BigDecimal, 1, text);
|
1156
|
-
} else {
|
1157
|
-
*result = rb_funcall(json->decimal_class, i_new, 1, text);
|
1158
|
-
}
|
1172
|
+
*result = DBL2NUM(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
|
1159
1173
|
}
|
1174
|
+
|
1160
1175
|
return p + 1;
|
1161
1176
|
} else {
|
1162
1177
|
return NULL;
|
@@ -1165,7 +1180,7 @@ case 7:
|
|
1165
1180
|
|
1166
1181
|
|
1167
1182
|
|
1168
|
-
#line
|
1183
|
+
#line 1173 "parser.c"
|
1169
1184
|
enum {JSON_array_start = 1};
|
1170
1185
|
enum {JSON_array_first_final = 17};
|
1171
1186
|
enum {JSON_array_error = 0};
|
@@ -1173,7 +1188,7 @@ enum {JSON_array_error = 0};
|
|
1173
1188
|
enum {JSON_array_en_main = 1};
|
1174
1189
|
|
1175
1190
|
|
1176
|
-
#line
|
1191
|
+
#line 421 "parser.rl"
|
1177
1192
|
|
1178
1193
|
|
1179
1194
|
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
|
@@ -1187,14 +1202,14 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
1187
1202
|
*result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
|
1188
1203
|
|
1189
1204
|
|
1190
|
-
#line
|
1205
|
+
#line 1195 "parser.c"
|
1191
1206
|
{
|
1192
1207
|
cs = JSON_array_start;
|
1193
1208
|
}
|
1194
1209
|
|
1195
|
-
#line
|
1210
|
+
#line 434 "parser.rl"
|
1196
1211
|
|
1197
|
-
#line
|
1212
|
+
#line 1202 "parser.c"
|
1198
1213
|
{
|
1199
1214
|
if ( p == pe )
|
1200
1215
|
goto _test_eof;
|
@@ -1233,7 +1248,7 @@ case 2:
|
|
1233
1248
|
goto st2;
|
1234
1249
|
goto st0;
|
1235
1250
|
tr2:
|
1236
|
-
#line
|
1251
|
+
#line 398 "parser.rl"
|
1237
1252
|
{
|
1238
1253
|
VALUE v = Qnil;
|
1239
1254
|
char *np = JSON_parse_value(json, p, pe, &v, current_nesting);
|
@@ -1253,7 +1268,7 @@ st3:
|
|
1253
1268
|
if ( ++p == pe )
|
1254
1269
|
goto _test_eof3;
|
1255
1270
|
case 3:
|
1256
|
-
#line
|
1271
|
+
#line 1261 "parser.c"
|
1257
1272
|
switch( (*p) ) {
|
1258
1273
|
case 13: goto st3;
|
1259
1274
|
case 32: goto st3;
|
@@ -1353,14 +1368,14 @@ case 12:
|
|
1353
1368
|
goto st3;
|
1354
1369
|
goto st12;
|
1355
1370
|
tr4:
|
1356
|
-
#line
|
1371
|
+
#line 413 "parser.rl"
|
1357
1372
|
{ p--; {p++; cs = 17; goto _out;} }
|
1358
1373
|
goto st17;
|
1359
1374
|
st17:
|
1360
1375
|
if ( ++p == pe )
|
1361
1376
|
goto _test_eof17;
|
1362
1377
|
case 17:
|
1363
|
-
#line
|
1378
|
+
#line 1368 "parser.c"
|
1364
1379
|
goto st0;
|
1365
1380
|
st13:
|
1366
1381
|
if ( ++p == pe )
|
@@ -1416,7 +1431,7 @@ case 16:
|
|
1416
1431
|
_out: {}
|
1417
1432
|
}
|
1418
1433
|
|
1419
|
-
#line
|
1434
|
+
#line 435 "parser.rl"
|
1420
1435
|
|
1421
1436
|
if(cs >= JSON_array_first_final) {
|
1422
1437
|
return p + 1;
|
@@ -1505,7 +1520,7 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
|
|
1505
1520
|
}
|
1506
1521
|
|
1507
1522
|
|
1508
|
-
#line
|
1523
|
+
#line 1513 "parser.c"
|
1509
1524
|
enum {JSON_string_start = 1};
|
1510
1525
|
enum {JSON_string_first_final = 8};
|
1511
1526
|
enum {JSON_string_error = 0};
|
@@ -1513,7 +1528,7 @@ enum {JSON_string_error = 0};
|
|
1513
1528
|
enum {JSON_string_en_main = 1};
|
1514
1529
|
|
1515
1530
|
|
1516
|
-
#line
|
1531
|
+
#line 542 "parser.rl"
|
1517
1532
|
|
1518
1533
|
|
1519
1534
|
static int
|
@@ -1535,15 +1550,15 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
1535
1550
|
|
1536
1551
|
*result = rb_str_buf_new(0);
|
1537
1552
|
|
1538
|
-
#line
|
1553
|
+
#line 1543 "parser.c"
|
1539
1554
|
{
|
1540
1555
|
cs = JSON_string_start;
|
1541
1556
|
}
|
1542
1557
|
|
1543
|
-
#line
|
1558
|
+
#line 563 "parser.rl"
|
1544
1559
|
json->memo = p;
|
1545
1560
|
|
1546
|
-
#line
|
1561
|
+
#line 1551 "parser.c"
|
1547
1562
|
{
|
1548
1563
|
if ( p == pe )
|
1549
1564
|
goto _test_eof;
|
@@ -1568,7 +1583,7 @@ case 2:
|
|
1568
1583
|
goto st0;
|
1569
1584
|
goto st2;
|
1570
1585
|
tr2:
|
1571
|
-
#line
|
1586
|
+
#line 528 "parser.rl"
|
1572
1587
|
{
|
1573
1588
|
*result = json_string_unescape(*result, json->memo + 1, p);
|
1574
1589
|
if (NIL_P(*result)) {
|
@@ -1579,14 +1594,14 @@ tr2:
|
|
1579
1594
|
{p = (( p + 1))-1;}
|
1580
1595
|
}
|
1581
1596
|
}
|
1582
|
-
#line
|
1597
|
+
#line 539 "parser.rl"
|
1583
1598
|
{ p--; {p++; cs = 8; goto _out;} }
|
1584
1599
|
goto st8;
|
1585
1600
|
st8:
|
1586
1601
|
if ( ++p == pe )
|
1587
1602
|
goto _test_eof8;
|
1588
1603
|
case 8:
|
1589
|
-
#line
|
1604
|
+
#line 1594 "parser.c"
|
1590
1605
|
goto st0;
|
1591
1606
|
st3:
|
1592
1607
|
if ( ++p == pe )
|
@@ -1662,7 +1677,7 @@ case 7:
|
|
1662
1677
|
_out: {}
|
1663
1678
|
}
|
1664
1679
|
|
1665
|
-
#line
|
1680
|
+
#line 565 "parser.rl"
|
1666
1681
|
|
1667
1682
|
if (json->create_additions && RTEST(match_string = json->match_string)) {
|
1668
1683
|
VALUE klass;
|
@@ -1678,7 +1693,22 @@ case 7:
|
|
1678
1693
|
if (json->symbolize_names && json->parsing_name) {
|
1679
1694
|
*result = rb_str_intern(*result);
|
1680
1695
|
} else if (RB_TYPE_P(*result, T_STRING)) {
|
1696
|
+
# if STR_UMINUS_DEDUPE_FROZEN
|
1697
|
+
if (json->freeze) {
|
1698
|
+
// Starting from MRI 2.8 it is preferable to freeze the string
|
1699
|
+
// before deduplication so that it can be interned directly
|
1700
|
+
// otherwise it would be duplicated first which is wasteful.
|
1701
|
+
*result = rb_funcall(rb_str_freeze(*result), i_uminus, 0);
|
1702
|
+
}
|
1703
|
+
# elif STR_UMINUS_DEDUPE
|
1704
|
+
if (json->freeze) {
|
1705
|
+
// MRI 2.5 and older do not deduplicate strings that are already
|
1706
|
+
// frozen.
|
1707
|
+
*result = rb_funcall(*result, i_uminus, 0);
|
1708
|
+
}
|
1709
|
+
# else
|
1681
1710
|
rb_str_resize(*result, RSTRING_LEN(*result));
|
1711
|
+
# endif
|
1682
1712
|
}
|
1683
1713
|
if (cs >= JSON_string_first_final) {
|
1684
1714
|
return p + 1;
|
@@ -1786,6 +1816,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
1786
1816
|
} else {
|
1787
1817
|
json->symbolize_names = 0;
|
1788
1818
|
}
|
1819
|
+
tmp = ID2SYM(i_freeze);
|
1820
|
+
if (option_given_p(opts, tmp)) {
|
1821
|
+
json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
|
1822
|
+
} else {
|
1823
|
+
json->freeze = 0;
|
1824
|
+
}
|
1789
1825
|
tmp = ID2SYM(i_create_additions);
|
1790
1826
|
if (option_given_p(opts, tmp)) {
|
1791
1827
|
json->create_additions = RTEST(rb_hash_aref(opts, tmp));
|
@@ -1849,7 +1885,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
1849
1885
|
}
|
1850
1886
|
|
1851
1887
|
|
1852
|
-
#line
|
1888
|
+
#line 1878 "parser.c"
|
1853
1889
|
enum {JSON_start = 1};
|
1854
1890
|
enum {JSON_first_final = 10};
|
1855
1891
|
enum {JSON_error = 0};
|
@@ -1857,7 +1893,7 @@ enum {JSON_error = 0};
|
|
1857
1893
|
enum {JSON_en_main = 1};
|
1858
1894
|
|
1859
1895
|
|
1860
|
-
#line
|
1896
|
+
#line 786 "parser.rl"
|
1861
1897
|
|
1862
1898
|
|
1863
1899
|
/*
|
@@ -1874,16 +1910,16 @@ static VALUE cParser_parse(VALUE self)
|
|
1874
1910
|
GET_PARSER;
|
1875
1911
|
|
1876
1912
|
|
1877
|
-
#line
|
1913
|
+
#line 1903 "parser.c"
|
1878
1914
|
{
|
1879
1915
|
cs = JSON_start;
|
1880
1916
|
}
|
1881
1917
|
|
1882
|
-
#line
|
1918
|
+
#line 802 "parser.rl"
|
1883
1919
|
p = json->source;
|
1884
1920
|
pe = p + json->len;
|
1885
1921
|
|
1886
|
-
#line
|
1922
|
+
#line 1912 "parser.c"
|
1887
1923
|
{
|
1888
1924
|
if ( p == pe )
|
1889
1925
|
goto _test_eof;
|
@@ -1917,7 +1953,7 @@ st0:
|
|
1917
1953
|
cs = 0;
|
1918
1954
|
goto _out;
|
1919
1955
|
tr2:
|
1920
|
-
#line
|
1956
|
+
#line 778 "parser.rl"
|
1921
1957
|
{
|
1922
1958
|
char *np = JSON_parse_value(json, p, pe, &result, 0);
|
1923
1959
|
if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
|
@@ -1927,7 +1963,7 @@ st10:
|
|
1927
1963
|
if ( ++p == pe )
|
1928
1964
|
goto _test_eof10;
|
1929
1965
|
case 10:
|
1930
|
-
#line
|
1966
|
+
#line 1956 "parser.c"
|
1931
1967
|
switch( (*p) ) {
|
1932
1968
|
case 13: goto st10;
|
1933
1969
|
case 32: goto st10;
|
@@ -2016,7 +2052,7 @@ case 9:
|
|
2016
2052
|
_out: {}
|
2017
2053
|
}
|
2018
2054
|
|
2019
|
-
#line
|
2055
|
+
#line 805 "parser.rl"
|
2020
2056
|
|
2021
2057
|
if (cs >= JSON_first_final && p == pe) {
|
2022
2058
|
return result;
|
@@ -2083,6 +2119,10 @@ static VALUE cParser_source(VALUE self)
|
|
2083
2119
|
|
2084
2120
|
void Init_parser(void)
|
2085
2121
|
{
|
2122
|
+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
2123
|
+
rb_ext_ractor_safe(true);
|
2124
|
+
#endif
|
2125
|
+
|
2086
2126
|
#undef rb_intern
|
2087
2127
|
rb_require("json/common");
|
2088
2128
|
mJSON = rb_define_module("JSON");
|
@@ -2125,7 +2165,9 @@ void Init_parser(void)
|
|
2125
2165
|
i_aref = rb_intern("[]");
|
2126
2166
|
i_leftshift = rb_intern("<<");
|
2127
2167
|
i_new = rb_intern("new");
|
2128
|
-
|
2168
|
+
i_try_convert = rb_intern("try_convert");
|
2169
|
+
i_freeze = rb_intern("freeze");
|
2170
|
+
i_uminus = rb_intern("-@");
|
2129
2171
|
}
|
2130
2172
|
|
2131
2173
|
/*
|