json 1.8.3 → 2.3.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 -11
- data/{CHANGES → CHANGES.md} +186 -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} +185 -134
- data/Rakefile +41 -40
- data/VERSION +1 -1
- data/ext/json/ext/fbuffer/fbuffer.h +0 -3
- data/ext/json/ext/generator/generator.c +142 -101
- data/ext/json/ext/generator/generator.h +7 -2
- data/ext/json/ext/parser/extconf.rb +3 -0
- data/ext/json/ext/parser/parser.c +383 -463
- data/ext/json/ext/parser/parser.h +4 -5
- data/ext/json/ext/parser/parser.rl +141 -184
- data/ext/json/extconf.rb +0 -1
- data/java/src/json/ext/ByteListTranscoder.java +1 -2
- data/java/src/json/ext/Generator.java +44 -22
- 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 +3 -56
- data/java/src/json/ext/OptionsReader.java +2 -3
- data/java/src/json/ext/Parser.java +132 -415
- data/java/src/json/ext/Parser.rl +48 -124
- 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 +5 -0
- data/java/src/json/ext/Utils.java +1 -2
- data/json-java.gemspec +16 -2
- data/json.gemspec +0 -0
- data/json_pure.gemspec +24 -26
- data/lib/json/add/bigdecimal.rb +3 -2
- data/lib/json/add/complex.rb +4 -3
- 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 -2
- 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 +26 -54
- data/lib/json/ext.rb +0 -6
- data/lib/json/generic_object.rb +5 -4
- data/lib/json/pure/generator.rb +63 -126
- data/lib/json/pure/parser.rb +41 -81
- data/lib/json/pure.rb +2 -8
- data/lib/json/version.rb +2 -1
- data/lib/json.rb +1 -0
- data/references/rfc7159.txt +899 -0
- data/tests/fixtures/obsolete_fail1.json +1 -0
- data/tests/{test_json_addition.rb → json_addition_test.rb} +32 -25
- data/tests/json_common_interface_test.rb +126 -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} +5 -8
- data/tests/{test_json_generate.rb → json_generator_test.rb} +123 -39
- data/tests/{test_json_generic_object.rb → json_generic_object_test.rb} +15 -8
- data/tests/json_parser_test.rb +472 -0
- data/tests/json_string_matching_test.rb +38 -0
- data/tests/{setup_variant.rb → test_helper.rb} +6 -0
- data/tools/diff.sh +18 -0
- data/tools/fuzz.rb +1 -9
- metadata +30 -47
- 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/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,12 @@ 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 quirks_mode;
|
42
40
|
VALUE object_class;
|
43
41
|
VALUE array_class;
|
42
|
+
VALUE decimal_class;
|
44
43
|
int create_additions;
|
45
44
|
VALUE match_string;
|
46
45
|
FBuffer *fbuffer;
|
@@ -58,11 +57,11 @@ typedef struct JSON_ParserStruct {
|
|
58
57
|
|
59
58
|
static UTF32 unescape_unicode(const unsigned char *p);
|
60
59
|
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);
|
60
|
+
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
|
61
|
+
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
|
63
62
|
static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result);
|
64
63
|
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);
|
64
|
+
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
|
66
65
|
static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd);
|
67
66
|
static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result);
|
68
67
|
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;
|
83
99
|
|
84
100
|
%%{
|
85
101
|
machine JSON_common;
|
@@ -117,7 +133,7 @@ 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 {
|
@@ -150,14 +166,14 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
|
150
166
|
) @exit;
|
151
167
|
}%%
|
152
168
|
|
153
|
-
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
169
|
+
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
|
154
170
|
{
|
155
171
|
int cs = EVIL;
|
156
172
|
VALUE last_name = Qnil;
|
157
173
|
VALUE object_class = json->object_class;
|
158
174
|
|
159
|
-
if (json->max_nesting &&
|
160
|
-
rb_raise(eNestingError, "nesting of %d is too deep",
|
175
|
+
if (json->max_nesting && current_nesting > json->max_nesting) {
|
176
|
+
rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
|
161
177
|
}
|
162
178
|
|
163
179
|
*result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class);
|
@@ -206,14 +222,14 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
206
222
|
if (json->allow_nan) {
|
207
223
|
*result = CNaN;
|
208
224
|
} else {
|
209
|
-
|
225
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2);
|
210
226
|
}
|
211
227
|
}
|
212
228
|
action parse_infinity {
|
213
229
|
if (json->allow_nan) {
|
214
230
|
*result = CInfinity;
|
215
231
|
} else {
|
216
|
-
|
232
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8);
|
217
233
|
}
|
218
234
|
}
|
219
235
|
action parse_string {
|
@@ -223,13 +239,13 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
223
239
|
|
224
240
|
action parse_number {
|
225
241
|
char *np;
|
226
|
-
if(pe > fpc +
|
242
|
+
if(pe > fpc + 8 && !strncmp(MinusInfinity, fpc, 9)) {
|
227
243
|
if (json->allow_nan) {
|
228
244
|
*result = CMinusInfinity;
|
229
245
|
fexec p + 10;
|
230
246
|
fhold; fbreak;
|
231
247
|
} else {
|
232
|
-
|
248
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
233
249
|
}
|
234
250
|
}
|
235
251
|
np = JSON_parse_float(json, fpc, pe, result);
|
@@ -241,23 +257,19 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
241
257
|
|
242
258
|
action parse_array {
|
243
259
|
char *np;
|
244
|
-
json
|
245
|
-
np = JSON_parse_array(json, fpc, pe, result);
|
246
|
-
json->current_nesting--;
|
260
|
+
np = JSON_parse_array(json, fpc, pe, result, current_nesting + 1);
|
247
261
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
248
262
|
}
|
249
263
|
|
250
264
|
action parse_object {
|
251
265
|
char *np;
|
252
|
-
json
|
253
|
-
np = JSON_parse_object(json, fpc, pe, result);
|
254
|
-
json->current_nesting--;
|
266
|
+
np = JSON_parse_object(json, fpc, pe, result, current_nesting + 1);
|
255
267
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
256
268
|
}
|
257
269
|
|
258
270
|
action exit { fhold; fbreak; }
|
259
271
|
|
260
|
-
main := (
|
272
|
+
main := ignore* (
|
261
273
|
Vnull @parse_null |
|
262
274
|
Vfalse @parse_false |
|
263
275
|
Vtrue @parse_true |
|
@@ -267,10 +279,10 @@ main := (
|
|
267
279
|
begin_string >parse_string |
|
268
280
|
begin_array >parse_array |
|
269
281
|
begin_object >parse_object
|
270
|
-
) %*exit;
|
282
|
+
) ignore* %*exit;
|
271
283
|
}%%
|
272
284
|
|
273
|
-
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
285
|
+
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
|
274
286
|
{
|
275
287
|
int cs = EVIL;
|
276
288
|
|
@@ -328,6 +340,19 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
|
|
328
340
|
) (^[0-9Ee.\-]? @exit );
|
329
341
|
}%%
|
330
342
|
|
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
|
+
|
331
356
|
static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
332
357
|
{
|
333
358
|
int cs = EVIL;
|
@@ -341,7 +366,17 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
341
366
|
fbuffer_clear(json->fbuffer);
|
342
367
|
fbuffer_append(json->fbuffer, json->memo, len);
|
343
368
|
fbuffer_append_char(json->fbuffer, '\0');
|
344
|
-
|
369
|
+
if (NIL_P(json->decimal_class)) {
|
370
|
+
*result = rb_float_new(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
|
371
|
+
} else {
|
372
|
+
VALUE text;
|
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
|
+
}
|
379
|
+
}
|
345
380
|
return p + 1;
|
346
381
|
} else {
|
347
382
|
return NULL;
|
@@ -357,7 +392,7 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
357
392
|
|
358
393
|
action parse_value {
|
359
394
|
VALUE v = Qnil;
|
360
|
-
char *np = JSON_parse_value(json, fpc, pe, &v);
|
395
|
+
char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
|
361
396
|
if (np == NULL) {
|
362
397
|
fhold; fbreak;
|
363
398
|
} else {
|
@@ -380,13 +415,13 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
380
415
|
end_array @exit;
|
381
416
|
}%%
|
382
417
|
|
383
|
-
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
418
|
+
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
|
384
419
|
{
|
385
420
|
int cs = EVIL;
|
386
421
|
VALUE array_class = json->array_class;
|
387
422
|
|
388
|
-
if (json->max_nesting &&
|
389
|
-
rb_raise(eNestingError, "nesting of %d is too deep",
|
423
|
+
if (json->max_nesting && current_nesting > json->max_nesting) {
|
424
|
+
rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
|
390
425
|
}
|
391
426
|
*result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
|
392
427
|
|
@@ -396,7 +431,7 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
396
431
|
if(cs >= JSON_array_first_final) {
|
397
432
|
return p + 1;
|
398
433
|
} else {
|
399
|
-
|
434
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
400
435
|
return NULL;
|
401
436
|
}
|
402
437
|
}
|
@@ -436,13 +471,21 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
|
|
436
471
|
break;
|
437
472
|
case 'u':
|
438
473
|
if (pe > stringEnd - 4) {
|
439
|
-
|
474
|
+
rb_enc_raise(
|
475
|
+
EXC_ENCODING eParserError,
|
476
|
+
"%u: incomplete unicode character escape sequence at '%s'", __LINE__, p
|
477
|
+
);
|
440
478
|
} else {
|
441
479
|
UTF32 ch = unescape_unicode((unsigned char *) ++pe);
|
442
480
|
pe += 3;
|
443
481
|
if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
|
444
482
|
pe++;
|
445
|
-
if (pe > stringEnd - 6)
|
483
|
+
if (pe > stringEnd - 6) {
|
484
|
+
rb_enc_raise(
|
485
|
+
EXC_ENCODING eParserError,
|
486
|
+
"%u: incomplete surrogate pair at '%s'", __LINE__, p
|
487
|
+
);
|
488
|
+
}
|
446
489
|
if (pe[0] == '\\' && pe[1] == 'u') {
|
447
490
|
UTF32 sur = unescape_unicode((unsigned char *) pe + 2);
|
448
491
|
ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16)
|
@@ -528,6 +571,8 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
528
571
|
|
529
572
|
if (json->symbolize_names && json->parsing_name) {
|
530
573
|
*result = rb_str_intern(*result);
|
574
|
+
} else if (RB_TYPE_P(*result, T_STRING)) {
|
575
|
+
rb_str_resize(*result, RSTRING_LEN(*result));
|
531
576
|
}
|
532
577
|
if (cs >= JSON_string_first_final) {
|
533
578
|
return p + 1;
|
@@ -550,41 +595,16 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
550
595
|
|
551
596
|
static VALUE convert_encoding(VALUE source)
|
552
597
|
{
|
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
598
|
#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);
|
599
|
+
rb_encoding *enc = rb_enc_get(source);
|
600
|
+
if (enc == rb_ascii8bit_encoding()) {
|
601
|
+
if (OBJ_FROZEN(source)) {
|
602
|
+
source = rb_str_dup(source);
|
587
603
|
}
|
604
|
+
FORCE_UTF8(source);
|
605
|
+
} else {
|
606
|
+
source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding());
|
607
|
+
}
|
588
608
|
#endif
|
589
609
|
return source;
|
590
610
|
}
|
@@ -607,8 +627,9 @@ static VALUE convert_encoding(VALUE source)
|
|
607
627
|
* defiance of RFC 4627 to be parsed by the Parser. This option defaults to
|
608
628
|
* false.
|
609
629
|
* * *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.
|
630
|
+
* (keys) in a JSON object. Otherwise strings are returned, which is
|
631
|
+
* also the default. It's not possible to use this option in
|
632
|
+
* conjunction with the *create_additions* option.
|
612
633
|
* * *create_additions*: If set to false, the Parser doesn't create
|
613
634
|
* additions even if a matching class and create_id was found. This option
|
614
635
|
* defaults to false.
|
@@ -623,12 +644,18 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
623
644
|
if (json->Vsource) {
|
624
645
|
rb_raise(rb_eTypeError, "already initialized instance");
|
625
646
|
}
|
647
|
+
#ifdef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
|
648
|
+
rb_scan_args(argc, argv, "1:", &source, &opts);
|
649
|
+
#else
|
626
650
|
rb_scan_args(argc, argv, "11", &source, &opts);
|
651
|
+
#endif
|
627
652
|
if (!NIL_P(opts)) {
|
653
|
+
#ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
|
628
654
|
opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
|
629
655
|
if (NIL_P(opts)) {
|
630
656
|
rb_raise(rb_eArgError, "opts needs to be like a hash");
|
631
657
|
} else {
|
658
|
+
#endif
|
632
659
|
VALUE tmp = ID2SYM(i_max_nesting);
|
633
660
|
if (option_given_p(opts, tmp)) {
|
634
661
|
VALUE max_nesting = rb_hash_aref(opts, tmp);
|
@@ -653,19 +680,17 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
653
680
|
} else {
|
654
681
|
json->symbolize_names = 0;
|
655
682
|
}
|
656
|
-
tmp = ID2SYM(i_quirks_mode);
|
657
|
-
if (option_given_p(opts, tmp)) {
|
658
|
-
VALUE quirks_mode = rb_hash_aref(opts, tmp);
|
659
|
-
json->quirks_mode = RTEST(quirks_mode) ? 1 : 0;
|
660
|
-
} else {
|
661
|
-
json->quirks_mode = 0;
|
662
|
-
}
|
663
683
|
tmp = ID2SYM(i_create_additions);
|
664
684
|
if (option_given_p(opts, tmp)) {
|
665
685
|
json->create_additions = RTEST(rb_hash_aref(opts, tmp));
|
666
686
|
} else {
|
667
687
|
json->create_additions = 0;
|
668
688
|
}
|
689
|
+
if (json->symbolize_names && json->create_additions) {
|
690
|
+
rb_raise(rb_eArgError,
|
691
|
+
"options :symbolize_names and :create_additions cannot be "
|
692
|
+
" used in conjunction");
|
693
|
+
}
|
669
694
|
tmp = ID2SYM(i_create_id);
|
670
695
|
if (option_given_p(opts, tmp)) {
|
671
696
|
json->create_id = rb_hash_aref(opts, tmp);
|
@@ -684,6 +709,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
684
709
|
} else {
|
685
710
|
json->array_class = Qnil;
|
686
711
|
}
|
712
|
+
tmp = ID2SYM(i_decimal_class);
|
713
|
+
if (option_given_p(opts, tmp)) {
|
714
|
+
json->decimal_class = rb_hash_aref(opts, tmp);
|
715
|
+
} else {
|
716
|
+
json->decimal_class = Qnil;
|
717
|
+
}
|
687
718
|
tmp = ID2SYM(i_match_string);
|
688
719
|
if (option_given_p(opts, tmp)) {
|
689
720
|
VALUE match_string = rb_hash_aref(opts, tmp);
|
@@ -691,20 +722,19 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
691
722
|
} else {
|
692
723
|
json->match_string = Qnil;
|
693
724
|
}
|
725
|
+
#ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
|
694
726
|
}
|
727
|
+
#endif
|
695
728
|
} else {
|
696
729
|
json->max_nesting = 100;
|
697
730
|
json->allow_nan = 0;
|
698
|
-
json->create_additions =
|
731
|
+
json->create_additions = 0;
|
699
732
|
json->create_id = rb_funcall(mJSON, i_create_id, 0);
|
700
733
|
json->object_class = Qnil;
|
701
734
|
json->array_class = Qnil;
|
735
|
+
json->decimal_class = Qnil;
|
702
736
|
}
|
703
|
-
source =
|
704
|
-
if (!json->quirks_mode) {
|
705
|
-
source = convert_encoding(StringValue(source));
|
706
|
-
}
|
707
|
-
json->current_nesting = 0;
|
737
|
+
source = convert_encoding(StringValue(source));
|
708
738
|
StringValue(source);
|
709
739
|
json->len = RSTRING_LEN(source);
|
710
740
|
json->source = RSTRING_PTR(source);;
|
@@ -719,56 +749,8 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
719
749
|
|
720
750
|
include JSON_common;
|
721
751
|
|
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
752
|
action parse_value {
|
771
|
-
char *np = JSON_parse_value(json, fpc, pe, &result);
|
753
|
+
char *np = JSON_parse_value(json, fpc, pe, &result, 0);
|
772
754
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
773
755
|
}
|
774
756
|
|
@@ -777,26 +759,6 @@ static VALUE cParser_parse_strict(VALUE self)
|
|
777
759
|
) ignore*;
|
778
760
|
}%%
|
779
761
|
|
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
762
|
/*
|
801
763
|
* call-seq: parse()
|
802
764
|
*
|
@@ -805,12 +767,21 @@ static VALUE cParser_parse_quirks_mode(VALUE self)
|
|
805
767
|
*/
|
806
768
|
static VALUE cParser_parse(VALUE self)
|
807
769
|
{
|
770
|
+
char *p, *pe;
|
771
|
+
int cs = EVIL;
|
772
|
+
VALUE result = Qnil;
|
808
773
|
GET_PARSER;
|
809
774
|
|
810
|
-
|
811
|
-
|
775
|
+
%% write init;
|
776
|
+
p = json->source;
|
777
|
+
pe = p + json->len;
|
778
|
+
%% write exec;
|
779
|
+
|
780
|
+
if (cs >= JSON_first_final && p == pe) {
|
781
|
+
return result;
|
812
782
|
} else {
|
813
|
-
|
783
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
784
|
+
return Qnil;
|
814
785
|
}
|
815
786
|
}
|
816
787
|
|
@@ -821,6 +792,7 @@ static void JSON_mark(void *ptr)
|
|
821
792
|
rb_gc_mark_maybe(json->create_id);
|
822
793
|
rb_gc_mark_maybe(json->object_class);
|
823
794
|
rb_gc_mark_maybe(json->array_class);
|
795
|
+
rb_gc_mark_maybe(json->decimal_class);
|
824
796
|
rb_gc_mark_maybe(json->match_string);
|
825
797
|
}
|
826
798
|
|
@@ -868,35 +840,30 @@ static VALUE cParser_source(VALUE self)
|
|
868
840
|
return rb_str_dup(json->Vsource);
|
869
841
|
}
|
870
842
|
|
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
843
|
void Init_parser(void)
|
884
844
|
{
|
845
|
+
#undef rb_intern
|
885
846
|
rb_require("json/common");
|
886
847
|
mJSON = rb_define_module("JSON");
|
887
848
|
mExt = rb_define_module_under(mJSON, "Ext");
|
888
849
|
cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
|
889
850
|
eParserError = rb_path2class("JSON::ParserError");
|
890
851
|
eNestingError = rb_path2class("JSON::NestingError");
|
852
|
+
rb_gc_register_mark_object(eParserError);
|
853
|
+
rb_gc_register_mark_object(eNestingError);
|
891
854
|
rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
|
892
855
|
rb_define_method(cParser, "initialize", cParser_initialize, -1);
|
893
856
|
rb_define_method(cParser, "parse", cParser_parse, 0);
|
894
857
|
rb_define_method(cParser, "source", cParser_source, 0);
|
895
|
-
rb_define_method(cParser, "quirks_mode?", cParser_quirks_mode_p, 0);
|
896
858
|
|
897
859
|
CNaN = rb_const_get(mJSON, rb_intern("NaN"));
|
860
|
+
rb_gc_register_mark_object(CNaN);
|
861
|
+
|
898
862
|
CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
|
863
|
+
rb_gc_register_mark_object(CInfinity);
|
864
|
+
|
899
865
|
CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
|
866
|
+
rb_gc_register_mark_object(CMinusInfinity);
|
900
867
|
|
901
868
|
i_json_creatable_p = rb_intern("json_creatable?");
|
902
869
|
i_json_create = rb_intern("json_create");
|
@@ -906,9 +873,9 @@ void Init_parser(void)
|
|
906
873
|
i_max_nesting = rb_intern("max_nesting");
|
907
874
|
i_allow_nan = rb_intern("allow_nan");
|
908
875
|
i_symbolize_names = rb_intern("symbolize_names");
|
909
|
-
i_quirks_mode = rb_intern("quirks_mode");
|
910
876
|
i_object_class = rb_intern("object_class");
|
911
877
|
i_array_class = rb_intern("array_class");
|
878
|
+
i_decimal_class = rb_intern("decimal_class");
|
912
879
|
i_match = rb_intern("match");
|
913
880
|
i_match_string = rb_intern("match_string");
|
914
881
|
i_key_p = rb_intern("key?");
|
@@ -916,18 +883,8 @@ void Init_parser(void)
|
|
916
883
|
i_aset = rb_intern("[]=");
|
917
884
|
i_aref = rb_intern("[]");
|
918
885
|
i_leftshift = rb_intern("<<");
|
919
|
-
|
920
|
-
|
921
|
-
CEncoding_UTF_16BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16be"));
|
922
|
-
CEncoding_UTF_16LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16le"));
|
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
|
886
|
+
i_new = rb_intern("new");
|
887
|
+
i_BigDecimal = rb_intern("BigDecimal");
|
931
888
|
}
|
932
889
|
|
933
890
|
/*
|
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
|
|