json 1.8.3 → 2.4.0
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/.gitignore +2 -0
- data/.travis.yml +9 -12
- data/{CHANGES → CHANGES.md} +219 -90
- data/Gemfile +10 -6
- data/{COPYING-json-jruby → LICENSE} +5 -6
- data/{README-json-jruby.markdown → README-json-jruby.md} +0 -0
- data/{README.rdoc → README.md} +201 -134
- data/Rakefile +35 -113
- data/VERSION +1 -1
- data/ext/json/ext/fbuffer/fbuffer.h +0 -3
- data/ext/json/ext/generator/generator.c +255 -101
- data/ext/json/ext/generator/generator.h +12 -4
- data/ext/json/ext/parser/extconf.rb +28 -0
- data/ext/json/ext/parser/parser.c +410 -462
- data/ext/json/ext/parser/parser.h +5 -5
- data/ext/json/ext/parser/parser.rl +166 -181
- data/ext/json/extconf.rb +1 -1
- data/java/src/json/ext/ByteListTranscoder.java +1 -2
- data/java/src/json/ext/Generator.java +39 -36
- data/java/src/json/ext/GeneratorMethods.java +1 -2
- data/java/src/json/ext/GeneratorService.java +1 -2
- data/java/src/json/ext/GeneratorState.java +33 -56
- data/java/src/json/ext/OptionsReader.java +2 -3
- data/java/src/json/ext/Parser.java +146 -417
- data/java/src/json/ext/Parser.rl +62 -126
- data/java/src/json/ext/ParserService.java +1 -2
- data/java/src/json/ext/RuntimeInfo.java +1 -6
- data/java/src/json/ext/StringDecoder.java +1 -2
- data/java/src/json/ext/StringEncoder.java +13 -2
- data/java/src/json/ext/Utils.java +1 -2
- data/json-java.gemspec +22 -7
- data/json.gemspec +0 -0
- data/json_pure.gemspec +22 -29
- data/lib/json/add/bigdecimal.rb +3 -2
- data/lib/json/add/complex.rb +4 -4
- data/lib/json/add/core.rb +1 -0
- data/lib/json/add/date.rb +1 -1
- data/lib/json/add/date_time.rb +1 -1
- data/lib/json/add/exception.rb +1 -1
- data/lib/json/add/ostruct.rb +3 -3
- data/lib/json/add/range.rb +1 -1
- data/lib/json/add/rational.rb +3 -3
- data/lib/json/add/regexp.rb +3 -3
- data/lib/json/add/set.rb +29 -0
- data/lib/json/add/struct.rb +1 -1
- data/lib/json/add/symbol.rb +1 -1
- data/lib/json/add/time.rb +1 -1
- data/lib/json/common.rb +350 -152
- data/lib/json/ext.rb +0 -6
- data/lib/json/generic_object.rb +5 -4
- data/lib/json/pure/generator.rb +83 -126
- data/lib/json/pure/parser.rb +62 -84
- data/lib/json/pure.rb +2 -8
- data/lib/json/version.rb +2 -1
- data/lib/json.rb +550 -29
- data/references/rfc7159.txt +899 -0
- data/tests/fixtures/obsolete_fail1.json +1 -0
- data/tests/{test_json_addition.rb → json_addition_test.rb} +28 -25
- data/tests/json_common_interface_test.rb +169 -0
- data/tests/json_encoding_test.rb +107 -0
- data/tests/json_ext_parser_test.rb +15 -0
- data/tests/{test_json_fixtures.rb → json_fixtures_test.rb} +13 -8
- data/tests/{test_json_generate.rb → json_generator_test.rb} +134 -39
- data/tests/{test_json_generic_object.rb → json_generic_object_test.rb} +15 -8
- data/tests/json_parser_test.rb +497 -0
- data/tests/json_string_matching_test.rb +38 -0
- data/tests/test_helper.rb +17 -0
- data/tools/diff.sh +18 -0
- data/tools/fuzz.rb +1 -9
- metadata +47 -53
- data/COPYING +0 -58
- data/GPL +0 -340
- data/TODO +0 -1
- data/data/example.json +0 -1
- data/data/index.html +0 -38
- data/data/prototype.js +0 -4184
- data/tests/fixtures/fail1.json +0 -1
- data/tests/setup_variant.rb +0 -11
- data/tests/test_json.rb +0 -553
- data/tests/test_json_encoding.rb +0 -65
- data/tests/test_json_string_matching.rb +0 -39
- data/tests/test_json_unicode.rb +0 -72
@@ -34,13 +34,13 @@ typedef struct JSON_ParserStruct {
|
|
34
34
|
char *memo;
|
35
35
|
VALUE create_id;
|
36
36
|
int max_nesting;
|
37
|
-
int current_nesting;
|
38
37
|
int allow_nan;
|
39
38
|
int parsing_name;
|
40
39
|
int symbolize_names;
|
41
|
-
int
|
40
|
+
int freeze;
|
42
41
|
VALUE object_class;
|
43
42
|
VALUE array_class;
|
43
|
+
VALUE decimal_class;
|
44
44
|
int create_additions;
|
45
45
|
VALUE match_string;
|
46
46
|
FBuffer *fbuffer;
|
@@ -58,11 +58,11 @@ typedef struct JSON_ParserStruct {
|
|
58
58
|
|
59
59
|
static UTF32 unescape_unicode(const unsigned char *p);
|
60
60
|
static int convert_UTF32_to_UTF8(char *buf, UTF32 ch);
|
61
|
-
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result);
|
62
|
-
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result);
|
61
|
+
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
|
62
|
+
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
|
63
63
|
static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result);
|
64
64
|
static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result);
|
65
|
-
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result);
|
65
|
+
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
|
66
66
|
static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd);
|
67
67
|
static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result);
|
68
68
|
static VALUE convert_encoding(VALUE source);
|
@@ -1,9 +1,31 @@
|
|
1
1
|
#include "../fbuffer/fbuffer.h"
|
2
2
|
#include "parser.h"
|
3
3
|
|
4
|
+
#if defined HAVE_RUBY_ENCODING_H
|
5
|
+
# define EXC_ENCODING rb_utf8_encoding(),
|
6
|
+
# ifndef HAVE_RB_ENC_RAISE
|
7
|
+
static void
|
8
|
+
enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
|
9
|
+
{
|
10
|
+
va_list args;
|
11
|
+
VALUE mesg;
|
12
|
+
|
13
|
+
va_start(args, fmt);
|
14
|
+
mesg = rb_enc_vsprintf(enc, fmt, args);
|
15
|
+
va_end(args);
|
16
|
+
|
17
|
+
rb_exc_raise(rb_exc_new3(exc, mesg));
|
18
|
+
}
|
19
|
+
# define rb_enc_raise enc_raise
|
20
|
+
# endif
|
21
|
+
#else
|
22
|
+
# define EXC_ENCODING /* nothing */
|
23
|
+
# define rb_enc_raise rb_raise
|
24
|
+
#endif
|
25
|
+
|
4
26
|
/* unicode */
|
5
27
|
|
6
|
-
static const char digit_values[256] = {
|
28
|
+
static const signed char digit_values[256] = {
|
7
29
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
8
30
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
9
31
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1,
|
@@ -22,7 +44,7 @@ static const char digit_values[256] = {
|
|
22
44
|
|
23
45
|
static UTF32 unescape_unicode(const unsigned char *p)
|
24
46
|
{
|
25
|
-
char b;
|
47
|
+
signed char b;
|
26
48
|
UTF32 result = 0;
|
27
49
|
b = digit_values[p[0]];
|
28
50
|
if (b < 0) return UNI_REPLACEMENT_CHAR;
|
@@ -65,21 +87,15 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
|
|
65
87
|
return len;
|
66
88
|
}
|
67
89
|
|
68
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
69
|
-
static VALUE CEncoding_ASCII_8BIT, CEncoding_UTF_8, CEncoding_UTF_16BE,
|
70
|
-
CEncoding_UTF_16LE, CEncoding_UTF_32BE, CEncoding_UTF_32LE;
|
71
|
-
static ID i_encoding, i_encode;
|
72
|
-
#else
|
73
|
-
static ID i_iconv;
|
74
|
-
#endif
|
75
|
-
|
76
90
|
static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
|
77
91
|
static VALUE CNaN, CInfinity, CMinusInfinity;
|
92
|
+
static VALUE cBigDecimal = Qundef;
|
78
93
|
|
79
94
|
static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
80
|
-
i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
|
81
|
-
i_object_class, i_array_class,
|
82
|
-
i_match_string, i_aset, i_aref,
|
95
|
+
i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
|
96
|
+
i_object_class, i_array_class, i_decimal_class, i_key_p,
|
97
|
+
i_deep_const_get, i_match, i_match_string, i_aset, i_aref,
|
98
|
+
i_leftshift, i_new, i_BigDecimal, i_freeze, i_uminus;
|
83
99
|
|
84
100
|
%%{
|
85
101
|
machine JSON_common;
|
@@ -117,11 +133,12 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
|
117
133
|
|
118
134
|
action parse_value {
|
119
135
|
VALUE v = Qnil;
|
120
|
-
char *np = JSON_parse_value(json, fpc, pe, &v);
|
136
|
+
char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
|
121
137
|
if (np == NULL) {
|
122
138
|
fhold; fbreak;
|
123
139
|
} else {
|
124
140
|
if (NIL_P(json->object_class)) {
|
141
|
+
OBJ_FREEZE(last_name);
|
125
142
|
rb_hash_aset(*result, last_name, v);
|
126
143
|
} else {
|
127
144
|
rb_funcall(*result, i_aset, 2, last_name, v);
|
@@ -150,14 +167,14 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
|
150
167
|
) @exit;
|
151
168
|
}%%
|
152
169
|
|
153
|
-
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
170
|
+
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
|
154
171
|
{
|
155
172
|
int cs = EVIL;
|
156
173
|
VALUE last_name = Qnil;
|
157
174
|
VALUE object_class = json->object_class;
|
158
175
|
|
159
|
-
if (json->max_nesting &&
|
160
|
-
rb_raise(eNestingError, "nesting of %d is too deep",
|
176
|
+
if (json->max_nesting && current_nesting > json->max_nesting) {
|
177
|
+
rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
|
161
178
|
}
|
162
179
|
|
163
180
|
*result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class);
|
@@ -206,14 +223,14 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
206
223
|
if (json->allow_nan) {
|
207
224
|
*result = CNaN;
|
208
225
|
} else {
|
209
|
-
|
226
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2);
|
210
227
|
}
|
211
228
|
}
|
212
229
|
action parse_infinity {
|
213
230
|
if (json->allow_nan) {
|
214
231
|
*result = CInfinity;
|
215
232
|
} else {
|
216
|
-
|
233
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8);
|
217
234
|
}
|
218
235
|
}
|
219
236
|
action parse_string {
|
@@ -223,13 +240,13 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
223
240
|
|
224
241
|
action parse_number {
|
225
242
|
char *np;
|
226
|
-
if(pe > fpc +
|
243
|
+
if(pe > fpc + 8 && !strncmp(MinusInfinity, fpc, 9)) {
|
227
244
|
if (json->allow_nan) {
|
228
245
|
*result = CMinusInfinity;
|
229
246
|
fexec p + 10;
|
230
247
|
fhold; fbreak;
|
231
248
|
} else {
|
232
|
-
|
249
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
233
250
|
}
|
234
251
|
}
|
235
252
|
np = JSON_parse_float(json, fpc, pe, result);
|
@@ -241,23 +258,19 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
241
258
|
|
242
259
|
action parse_array {
|
243
260
|
char *np;
|
244
|
-
json
|
245
|
-
np = JSON_parse_array(json, fpc, pe, result);
|
246
|
-
json->current_nesting--;
|
261
|
+
np = JSON_parse_array(json, fpc, pe, result, current_nesting + 1);
|
247
262
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
248
263
|
}
|
249
264
|
|
250
265
|
action parse_object {
|
251
266
|
char *np;
|
252
|
-
json
|
253
|
-
np = JSON_parse_object(json, fpc, pe, result);
|
254
|
-
json->current_nesting--;
|
267
|
+
np = JSON_parse_object(json, fpc, pe, result, current_nesting + 1);
|
255
268
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
256
269
|
}
|
257
270
|
|
258
271
|
action exit { fhold; fbreak; }
|
259
272
|
|
260
|
-
main := (
|
273
|
+
main := ignore* (
|
261
274
|
Vnull @parse_null |
|
262
275
|
Vfalse @parse_false |
|
263
276
|
Vtrue @parse_true |
|
@@ -267,16 +280,20 @@ main := (
|
|
267
280
|
begin_string >parse_string |
|
268
281
|
begin_array >parse_array |
|
269
282
|
begin_object >parse_object
|
270
|
-
) %*exit;
|
283
|
+
) ignore* %*exit;
|
271
284
|
}%%
|
272
285
|
|
273
|
-
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
286
|
+
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
|
274
287
|
{
|
275
288
|
int cs = EVIL;
|
276
289
|
|
277
290
|
%% write init;
|
278
291
|
%% write exec;
|
279
292
|
|
293
|
+
if (json->freeze) {
|
294
|
+
OBJ_FREEZE(*result);
|
295
|
+
}
|
296
|
+
|
280
297
|
if (cs >= JSON_value_first_final) {
|
281
298
|
return p;
|
282
299
|
} else {
|
@@ -328,6 +345,19 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
|
|
328
345
|
) (^[0-9Ee.\-]? @exit );
|
329
346
|
}%%
|
330
347
|
|
348
|
+
static int is_bigdecimal_class(VALUE obj)
|
349
|
+
{
|
350
|
+
if (cBigDecimal == Qundef) {
|
351
|
+
if (rb_const_defined(rb_cObject, i_BigDecimal)) {
|
352
|
+
cBigDecimal = rb_const_get_at(rb_cObject, i_BigDecimal);
|
353
|
+
}
|
354
|
+
else {
|
355
|
+
return 0;
|
356
|
+
}
|
357
|
+
}
|
358
|
+
return obj == cBigDecimal;
|
359
|
+
}
|
360
|
+
|
331
361
|
static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
332
362
|
{
|
333
363
|
int cs = EVIL;
|
@@ -341,7 +371,17 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
341
371
|
fbuffer_clear(json->fbuffer);
|
342
372
|
fbuffer_append(json->fbuffer, json->memo, len);
|
343
373
|
fbuffer_append_char(json->fbuffer, '\0');
|
344
|
-
|
374
|
+
if (NIL_P(json->decimal_class)) {
|
375
|
+
*result = rb_float_new(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
|
376
|
+
} else {
|
377
|
+
VALUE text;
|
378
|
+
text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
|
379
|
+
if (is_bigdecimal_class(json->decimal_class)) {
|
380
|
+
*result = rb_funcall(Qnil, i_BigDecimal, 1, text);
|
381
|
+
} else {
|
382
|
+
*result = rb_funcall(json->decimal_class, i_new, 1, text);
|
383
|
+
}
|
384
|
+
}
|
345
385
|
return p + 1;
|
346
386
|
} else {
|
347
387
|
return NULL;
|
@@ -357,7 +397,7 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
357
397
|
|
358
398
|
action parse_value {
|
359
399
|
VALUE v = Qnil;
|
360
|
-
char *np = JSON_parse_value(json, fpc, pe, &v);
|
400
|
+
char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
|
361
401
|
if (np == NULL) {
|
362
402
|
fhold; fbreak;
|
363
403
|
} else {
|
@@ -380,13 +420,13 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
380
420
|
end_array @exit;
|
381
421
|
}%%
|
382
422
|
|
383
|
-
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
423
|
+
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
|
384
424
|
{
|
385
425
|
int cs = EVIL;
|
386
426
|
VALUE array_class = json->array_class;
|
387
427
|
|
388
|
-
if (json->max_nesting &&
|
389
|
-
rb_raise(eNestingError, "nesting of %d is too deep",
|
428
|
+
if (json->max_nesting && current_nesting > json->max_nesting) {
|
429
|
+
rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
|
390
430
|
}
|
391
431
|
*result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
|
392
432
|
|
@@ -396,7 +436,7 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
396
436
|
if(cs >= JSON_array_first_final) {
|
397
437
|
return p + 1;
|
398
438
|
} else {
|
399
|
-
|
439
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
400
440
|
return NULL;
|
401
441
|
}
|
402
442
|
}
|
@@ -436,13 +476,21 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
|
|
436
476
|
break;
|
437
477
|
case 'u':
|
438
478
|
if (pe > stringEnd - 4) {
|
439
|
-
|
479
|
+
rb_enc_raise(
|
480
|
+
EXC_ENCODING eParserError,
|
481
|
+
"%u: incomplete unicode character escape sequence at '%s'", __LINE__, p
|
482
|
+
);
|
440
483
|
} else {
|
441
484
|
UTF32 ch = unescape_unicode((unsigned char *) ++pe);
|
442
485
|
pe += 3;
|
443
486
|
if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
|
444
487
|
pe++;
|
445
|
-
if (pe > stringEnd - 6)
|
488
|
+
if (pe > stringEnd - 6) {
|
489
|
+
rb_enc_raise(
|
490
|
+
EXC_ENCODING eParserError,
|
491
|
+
"%u: incomplete surrogate pair at '%s'", __LINE__, p
|
492
|
+
);
|
493
|
+
}
|
446
494
|
if (pe[0] == '\\' && pe[1] == 'u') {
|
447
495
|
UTF32 sur = unescape_unicode((unsigned char *) pe + 2);
|
448
496
|
ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16)
|
@@ -528,6 +576,23 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
528
576
|
|
529
577
|
if (json->symbolize_names && json->parsing_name) {
|
530
578
|
*result = rb_str_intern(*result);
|
579
|
+
} else if (RB_TYPE_P(*result, T_STRING)) {
|
580
|
+
# if STR_UMINUS_DEDUPE_FROZEN
|
581
|
+
if (json->freeze) {
|
582
|
+
// Starting from MRI 2.8 it is preferable to freeze the string
|
583
|
+
// before deduplication so that it can be interned directly
|
584
|
+
// otherwise it would be duplicated first which is wasteful.
|
585
|
+
*result = rb_funcall(rb_str_freeze(*result), i_uminus, 0);
|
586
|
+
}
|
587
|
+
# elif STR_UMINUS_DEDUPE
|
588
|
+
if (json->freeze) {
|
589
|
+
// MRI 2.5 and older do not deduplicate strings that are already
|
590
|
+
// frozen.
|
591
|
+
*result = rb_funcall(*result, i_uminus, 0);
|
592
|
+
}
|
593
|
+
# else
|
594
|
+
rb_str_resize(*result, RSTRING_LEN(*result));
|
595
|
+
# endif
|
531
596
|
}
|
532
597
|
if (cs >= JSON_string_first_final) {
|
533
598
|
return p + 1;
|
@@ -550,41 +615,16 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
550
615
|
|
551
616
|
static VALUE convert_encoding(VALUE source)
|
552
617
|
{
|
553
|
-
char *ptr = RSTRING_PTR(source);
|
554
|
-
long len = RSTRING_LEN(source);
|
555
|
-
if (len < 2) {
|
556
|
-
rb_raise(eParserError, "A JSON text must at least contain two octets!");
|
557
|
-
}
|
558
618
|
#ifdef HAVE_RUBY_ENCODING_H
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_32BE);
|
564
|
-
} else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
|
565
|
-
source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_16BE);
|
566
|
-
} else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
|
567
|
-
source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_32LE);
|
568
|
-
} else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
|
569
|
-
source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_16LE);
|
570
|
-
} else {
|
571
|
-
source = rb_str_dup(source);
|
572
|
-
FORCE_UTF8(source);
|
573
|
-
}
|
574
|
-
} else {
|
575
|
-
source = rb_funcall(source, i_encode, 1, CEncoding_UTF_8);
|
576
|
-
}
|
577
|
-
}
|
578
|
-
#else
|
579
|
-
if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
|
580
|
-
source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-32be"), source);
|
581
|
-
} else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
|
582
|
-
source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-16be"), source);
|
583
|
-
} else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
|
584
|
-
source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-32le"), source);
|
585
|
-
} else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
|
586
|
-
source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-16le"), source);
|
619
|
+
rb_encoding *enc = rb_enc_get(source);
|
620
|
+
if (enc == rb_ascii8bit_encoding()) {
|
621
|
+
if (OBJ_FROZEN(source)) {
|
622
|
+
source = rb_str_dup(source);
|
587
623
|
}
|
624
|
+
FORCE_UTF8(source);
|
625
|
+
} else {
|
626
|
+
source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding());
|
627
|
+
}
|
588
628
|
#endif
|
589
629
|
return source;
|
590
630
|
}
|
@@ -607,8 +647,9 @@ static VALUE convert_encoding(VALUE source)
|
|
607
647
|
* defiance of RFC 4627 to be parsed by the Parser. This option defaults to
|
608
648
|
* false.
|
609
649
|
* * *symbolize_names*: If set to true, returns symbols for the names
|
610
|
-
* (keys) in a JSON object. Otherwise strings are returned, which is
|
611
|
-
* the default.
|
650
|
+
* (keys) in a JSON object. Otherwise strings are returned, which is
|
651
|
+
* also the default. It's not possible to use this option in
|
652
|
+
* conjunction with the *create_additions* option.
|
612
653
|
* * *create_additions*: If set to false, the Parser doesn't create
|
613
654
|
* additions even if a matching class and create_id was found. This option
|
614
655
|
* defaults to false.
|
@@ -623,12 +664,18 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
623
664
|
if (json->Vsource) {
|
624
665
|
rb_raise(rb_eTypeError, "already initialized instance");
|
625
666
|
}
|
667
|
+
#ifdef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
|
668
|
+
rb_scan_args(argc, argv, "1:", &source, &opts);
|
669
|
+
#else
|
626
670
|
rb_scan_args(argc, argv, "11", &source, &opts);
|
671
|
+
#endif
|
627
672
|
if (!NIL_P(opts)) {
|
673
|
+
#ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
|
628
674
|
opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
|
629
675
|
if (NIL_P(opts)) {
|
630
676
|
rb_raise(rb_eArgError, "opts needs to be like a hash");
|
631
677
|
} else {
|
678
|
+
#endif
|
632
679
|
VALUE tmp = ID2SYM(i_max_nesting);
|
633
680
|
if (option_given_p(opts, tmp)) {
|
634
681
|
VALUE max_nesting = rb_hash_aref(opts, tmp);
|
@@ -653,12 +700,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
653
700
|
} else {
|
654
701
|
json->symbolize_names = 0;
|
655
702
|
}
|
656
|
-
tmp = ID2SYM(
|
703
|
+
tmp = ID2SYM(i_freeze);
|
657
704
|
if (option_given_p(opts, tmp)) {
|
658
|
-
|
659
|
-
json->quirks_mode = RTEST(quirks_mode) ? 1 : 0;
|
705
|
+
json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
|
660
706
|
} else {
|
661
|
-
json->
|
707
|
+
json->freeze = 0;
|
662
708
|
}
|
663
709
|
tmp = ID2SYM(i_create_additions);
|
664
710
|
if (option_given_p(opts, tmp)) {
|
@@ -666,6 +712,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
666
712
|
} else {
|
667
713
|
json->create_additions = 0;
|
668
714
|
}
|
715
|
+
if (json->symbolize_names && json->create_additions) {
|
716
|
+
rb_raise(rb_eArgError,
|
717
|
+
"options :symbolize_names and :create_additions cannot be "
|
718
|
+
" used in conjunction");
|
719
|
+
}
|
669
720
|
tmp = ID2SYM(i_create_id);
|
670
721
|
if (option_given_p(opts, tmp)) {
|
671
722
|
json->create_id = rb_hash_aref(opts, tmp);
|
@@ -684,6 +735,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
684
735
|
} else {
|
685
736
|
json->array_class = Qnil;
|
686
737
|
}
|
738
|
+
tmp = ID2SYM(i_decimal_class);
|
739
|
+
if (option_given_p(opts, tmp)) {
|
740
|
+
json->decimal_class = rb_hash_aref(opts, tmp);
|
741
|
+
} else {
|
742
|
+
json->decimal_class = Qnil;
|
743
|
+
}
|
687
744
|
tmp = ID2SYM(i_match_string);
|
688
745
|
if (option_given_p(opts, tmp)) {
|
689
746
|
VALUE match_string = rb_hash_aref(opts, tmp);
|
@@ -691,20 +748,19 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
691
748
|
} else {
|
692
749
|
json->match_string = Qnil;
|
693
750
|
}
|
751
|
+
#ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
|
694
752
|
}
|
753
|
+
#endif
|
695
754
|
} else {
|
696
755
|
json->max_nesting = 100;
|
697
756
|
json->allow_nan = 0;
|
698
|
-
json->create_additions =
|
757
|
+
json->create_additions = 0;
|
699
758
|
json->create_id = rb_funcall(mJSON, i_create_id, 0);
|
700
759
|
json->object_class = Qnil;
|
701
760
|
json->array_class = Qnil;
|
761
|
+
json->decimal_class = Qnil;
|
702
762
|
}
|
703
|
-
source =
|
704
|
-
if (!json->quirks_mode) {
|
705
|
-
source = convert_encoding(StringValue(source));
|
706
|
-
}
|
707
|
-
json->current_nesting = 0;
|
763
|
+
source = convert_encoding(StringValue(source));
|
708
764
|
StringValue(source);
|
709
765
|
json->len = RSTRING_LEN(source);
|
710
766
|
json->source = RSTRING_PTR(source);;
|
@@ -719,56 +775,8 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
719
775
|
|
720
776
|
include JSON_common;
|
721
777
|
|
722
|
-
action parse_object {
|
723
|
-
char *np;
|
724
|
-
json->current_nesting = 1;
|
725
|
-
np = JSON_parse_object(json, fpc, pe, &result);
|
726
|
-
if (np == NULL) { fhold; fbreak; } else fexec np;
|
727
|
-
}
|
728
|
-
|
729
|
-
action parse_array {
|
730
|
-
char *np;
|
731
|
-
json->current_nesting = 1;
|
732
|
-
np = JSON_parse_array(json, fpc, pe, &result);
|
733
|
-
if (np == NULL) { fhold; fbreak; } else fexec np;
|
734
|
-
}
|
735
|
-
|
736
|
-
main := ignore* (
|
737
|
-
begin_object >parse_object |
|
738
|
-
begin_array >parse_array
|
739
|
-
) ignore*;
|
740
|
-
}%%
|
741
|
-
|
742
|
-
static VALUE cParser_parse_strict(VALUE self)
|
743
|
-
{
|
744
|
-
char *p, *pe;
|
745
|
-
int cs = EVIL;
|
746
|
-
VALUE result = Qnil;
|
747
|
-
GET_PARSER;
|
748
|
-
|
749
|
-
%% write init;
|
750
|
-
p = json->source;
|
751
|
-
pe = p + json->len;
|
752
|
-
%% write exec;
|
753
|
-
|
754
|
-
if (cs >= JSON_first_final && p == pe) {
|
755
|
-
return result;
|
756
|
-
} else {
|
757
|
-
rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
758
|
-
return Qnil;
|
759
|
-
}
|
760
|
-
}
|
761
|
-
|
762
|
-
|
763
|
-
%%{
|
764
|
-
machine JSON_quirks_mode;
|
765
|
-
|
766
|
-
write data;
|
767
|
-
|
768
|
-
include JSON_common;
|
769
|
-
|
770
778
|
action parse_value {
|
771
|
-
char *np = JSON_parse_value(json, fpc, pe, &result);
|
779
|
+
char *np = JSON_parse_value(json, fpc, pe, &result, 0);
|
772
780
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
773
781
|
}
|
774
782
|
|
@@ -777,26 +785,6 @@ static VALUE cParser_parse_strict(VALUE self)
|
|
777
785
|
) ignore*;
|
778
786
|
}%%
|
779
787
|
|
780
|
-
static VALUE cParser_parse_quirks_mode(VALUE self)
|
781
|
-
{
|
782
|
-
char *p, *pe;
|
783
|
-
int cs = EVIL;
|
784
|
-
VALUE result = Qnil;
|
785
|
-
GET_PARSER;
|
786
|
-
|
787
|
-
%% write init;
|
788
|
-
p = json->source;
|
789
|
-
pe = p + json->len;
|
790
|
-
%% write exec;
|
791
|
-
|
792
|
-
if (cs >= JSON_quirks_mode_first_final && p == pe) {
|
793
|
-
return result;
|
794
|
-
} else {
|
795
|
-
rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
796
|
-
return Qnil;
|
797
|
-
}
|
798
|
-
}
|
799
|
-
|
800
788
|
/*
|
801
789
|
* call-seq: parse()
|
802
790
|
*
|
@@ -805,12 +793,21 @@ static VALUE cParser_parse_quirks_mode(VALUE self)
|
|
805
793
|
*/
|
806
794
|
static VALUE cParser_parse(VALUE self)
|
807
795
|
{
|
796
|
+
char *p, *pe;
|
797
|
+
int cs = EVIL;
|
798
|
+
VALUE result = Qnil;
|
808
799
|
GET_PARSER;
|
809
800
|
|
810
|
-
|
811
|
-
|
801
|
+
%% write init;
|
802
|
+
p = json->source;
|
803
|
+
pe = p + json->len;
|
804
|
+
%% write exec;
|
805
|
+
|
806
|
+
if (cs >= JSON_first_final && p == pe) {
|
807
|
+
return result;
|
812
808
|
} else {
|
813
|
-
|
809
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
810
|
+
return Qnil;
|
814
811
|
}
|
815
812
|
}
|
816
813
|
|
@@ -821,6 +818,7 @@ static void JSON_mark(void *ptr)
|
|
821
818
|
rb_gc_mark_maybe(json->create_id);
|
822
819
|
rb_gc_mark_maybe(json->object_class);
|
823
820
|
rb_gc_mark_maybe(json->array_class);
|
821
|
+
rb_gc_mark_maybe(json->decimal_class);
|
824
822
|
rb_gc_mark_maybe(json->match_string);
|
825
823
|
}
|
826
824
|
|
@@ -868,35 +866,30 @@ static VALUE cParser_source(VALUE self)
|
|
868
866
|
return rb_str_dup(json->Vsource);
|
869
867
|
}
|
870
868
|
|
871
|
-
/*
|
872
|
-
* call-seq: quirks_mode?()
|
873
|
-
*
|
874
|
-
* Returns a true, if this parser is in quirks_mode, false otherwise.
|
875
|
-
*/
|
876
|
-
static VALUE cParser_quirks_mode_p(VALUE self)
|
877
|
-
{
|
878
|
-
GET_PARSER;
|
879
|
-
return json->quirks_mode ? Qtrue : Qfalse;
|
880
|
-
}
|
881
|
-
|
882
|
-
|
883
869
|
void Init_parser(void)
|
884
870
|
{
|
871
|
+
#undef rb_intern
|
885
872
|
rb_require("json/common");
|
886
873
|
mJSON = rb_define_module("JSON");
|
887
874
|
mExt = rb_define_module_under(mJSON, "Ext");
|
888
875
|
cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
|
889
876
|
eParserError = rb_path2class("JSON::ParserError");
|
890
877
|
eNestingError = rb_path2class("JSON::NestingError");
|
878
|
+
rb_gc_register_mark_object(eParserError);
|
879
|
+
rb_gc_register_mark_object(eNestingError);
|
891
880
|
rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
|
892
881
|
rb_define_method(cParser, "initialize", cParser_initialize, -1);
|
893
882
|
rb_define_method(cParser, "parse", cParser_parse, 0);
|
894
883
|
rb_define_method(cParser, "source", cParser_source, 0);
|
895
|
-
rb_define_method(cParser, "quirks_mode?", cParser_quirks_mode_p, 0);
|
896
884
|
|
897
885
|
CNaN = rb_const_get(mJSON, rb_intern("NaN"));
|
886
|
+
rb_gc_register_mark_object(CNaN);
|
887
|
+
|
898
888
|
CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
|
889
|
+
rb_gc_register_mark_object(CInfinity);
|
890
|
+
|
899
891
|
CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
|
892
|
+
rb_gc_register_mark_object(CMinusInfinity);
|
900
893
|
|
901
894
|
i_json_creatable_p = rb_intern("json_creatable?");
|
902
895
|
i_json_create = rb_intern("json_create");
|
@@ -906,9 +899,9 @@ void Init_parser(void)
|
|
906
899
|
i_max_nesting = rb_intern("max_nesting");
|
907
900
|
i_allow_nan = rb_intern("allow_nan");
|
908
901
|
i_symbolize_names = rb_intern("symbolize_names");
|
909
|
-
i_quirks_mode = rb_intern("quirks_mode");
|
910
902
|
i_object_class = rb_intern("object_class");
|
911
903
|
i_array_class = rb_intern("array_class");
|
904
|
+
i_decimal_class = rb_intern("decimal_class");
|
912
905
|
i_match = rb_intern("match");
|
913
906
|
i_match_string = rb_intern("match_string");
|
914
907
|
i_key_p = rb_intern("key?");
|
@@ -916,18 +909,10 @@ void Init_parser(void)
|
|
916
909
|
i_aset = rb_intern("[]=");
|
917
910
|
i_aref = rb_intern("[]");
|
918
911
|
i_leftshift = rb_intern("<<");
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
CEncoding_UTF_32BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32be"));
|
924
|
-
CEncoding_UTF_32LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32le"));
|
925
|
-
CEncoding_ASCII_8BIT = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("ascii-8bit"));
|
926
|
-
i_encoding = rb_intern("encoding");
|
927
|
-
i_encode = rb_intern("encode");
|
928
|
-
#else
|
929
|
-
i_iconv = rb_intern("iconv");
|
930
|
-
#endif
|
912
|
+
i_new = rb_intern("new");
|
913
|
+
i_BigDecimal = rb_intern("BigDecimal");
|
914
|
+
i_freeze = rb_intern("freeze");
|
915
|
+
i_uminus = rb_intern("-@");
|
931
916
|
}
|
932
917
|
|
933
918
|
/*
|
data/ext/json/extconf.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
/*
|
2
2
|
* This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
|
3
3
|
*
|
4
|
-
* Distributed under the Ruby
|
5
|
-
* for details.
|
4
|
+
* Distributed under the Ruby license: https://www.ruby-lang.org/en/about/license.txt
|
6
5
|
*/
|
7
6
|
package json.ext;
|
8
7
|
|