json 1.8.3 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of json might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/.travis.yml +7 -10
- data/{CHANGES → CHANGES.md} +186 -90
- data/Gemfile +10 -6
- data/{README-json-jruby.markdown → README-json-jruby.md} +0 -0
- data/{README.rdoc → README.md} +184 -133
- data/Rakefile +33 -37
- data/VERSION +1 -1
- data/ext/json/ext/fbuffer/fbuffer.h +0 -3
- data/ext/json/ext/generator/generator.c +47 -61
- 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 +374 -459
- data/ext/json/ext/parser/parser.h +4 -5
- data/ext/json/ext/parser/parser.rl +133 -181
- data/ext/json/extconf.rb +0 -1
- data/java/src/json/ext/ByteListTranscoder.java +1 -2
- data/java/src/json/ext/Generator.java +11 -12
- 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 +15 -0
- data/json.gemspec +0 -0
- data/json_pure.gemspec +24 -26
- data/lib/json/add/bigdecimal.rb +1 -0
- data/lib/json/add/complex.rb +2 -1
- 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 +1 -0
- data/lib/json/add/regexp.rb +1 -1
- 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 +24 -52
- data/lib/json/ext.rb +0 -6
- data/lib/json/generic_object.rb +5 -4
- data/lib/json/pure/generator.rb +61 -125
- data/lib/json/pure/parser.rb +33 -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} +79 -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 +29 -47
- data/COPYING +0 -58
- data/COPYING-json-jruby +0 -57
- 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,6 +1,28 @@
|
|
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
28
|
static const char digit_values[256] = {
|
@@ -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,10 @@ 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 {
|
575
|
+
if (RB_TYPE_P(*result, T_STRING)) {
|
576
|
+
rb_str_resize(*result, RSTRING_LEN(*result));
|
577
|
+
}
|
531
578
|
}
|
532
579
|
if (cs >= JSON_string_first_final) {
|
533
580
|
return p + 1;
|
@@ -550,41 +597,16 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
550
597
|
|
551
598
|
static VALUE convert_encoding(VALUE source)
|
552
599
|
{
|
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
600
|
#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);
|
601
|
+
rb_encoding *enc = rb_enc_get(source);
|
602
|
+
if (enc == rb_ascii8bit_encoding()) {
|
603
|
+
if (OBJ_FROZEN(source)) {
|
604
|
+
source = rb_str_dup(source);
|
587
605
|
}
|
606
|
+
FORCE_UTF8(source);
|
607
|
+
} else {
|
608
|
+
source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding());
|
609
|
+
}
|
588
610
|
#endif
|
589
611
|
return source;
|
590
612
|
}
|
@@ -607,8 +629,9 @@ static VALUE convert_encoding(VALUE source)
|
|
607
629
|
* defiance of RFC 4627 to be parsed by the Parser. This option defaults to
|
608
630
|
* false.
|
609
631
|
* * *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.
|
632
|
+
* (keys) in a JSON object. Otherwise strings are returned, which is
|
633
|
+
* also the default. It's not possible to use this option in
|
634
|
+
* conjunction with the *create_additions* option.
|
612
635
|
* * *create_additions*: If set to false, the Parser doesn't create
|
613
636
|
* additions even if a matching class and create_id was found. This option
|
614
637
|
* defaults to false.
|
@@ -623,12 +646,18 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
623
646
|
if (json->Vsource) {
|
624
647
|
rb_raise(rb_eTypeError, "already initialized instance");
|
625
648
|
}
|
649
|
+
#ifdef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
|
650
|
+
rb_scan_args(argc, argv, "1:", &source, &opts);
|
651
|
+
#else
|
626
652
|
rb_scan_args(argc, argv, "11", &source, &opts);
|
653
|
+
#endif
|
627
654
|
if (!NIL_P(opts)) {
|
655
|
+
#ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
|
628
656
|
opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
|
629
657
|
if (NIL_P(opts)) {
|
630
658
|
rb_raise(rb_eArgError, "opts needs to be like a hash");
|
631
659
|
} else {
|
660
|
+
#endif
|
632
661
|
VALUE tmp = ID2SYM(i_max_nesting);
|
633
662
|
if (option_given_p(opts, tmp)) {
|
634
663
|
VALUE max_nesting = rb_hash_aref(opts, tmp);
|
@@ -653,19 +682,17 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
653
682
|
} else {
|
654
683
|
json->symbolize_names = 0;
|
655
684
|
}
|
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
685
|
tmp = ID2SYM(i_create_additions);
|
664
686
|
if (option_given_p(opts, tmp)) {
|
665
687
|
json->create_additions = RTEST(rb_hash_aref(opts, tmp));
|
666
688
|
} else {
|
667
689
|
json->create_additions = 0;
|
668
690
|
}
|
691
|
+
if (json->symbolize_names && json->create_additions) {
|
692
|
+
rb_raise(rb_eArgError,
|
693
|
+
"options :symbolize_names and :create_additions cannot be "
|
694
|
+
" used in conjunction");
|
695
|
+
}
|
669
696
|
tmp = ID2SYM(i_create_id);
|
670
697
|
if (option_given_p(opts, tmp)) {
|
671
698
|
json->create_id = rb_hash_aref(opts, tmp);
|
@@ -684,6 +711,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
684
711
|
} else {
|
685
712
|
json->array_class = Qnil;
|
686
713
|
}
|
714
|
+
tmp = ID2SYM(i_decimal_class);
|
715
|
+
if (option_given_p(opts, tmp)) {
|
716
|
+
json->decimal_class = rb_hash_aref(opts, tmp);
|
717
|
+
} else {
|
718
|
+
json->decimal_class = Qnil;
|
719
|
+
}
|
687
720
|
tmp = ID2SYM(i_match_string);
|
688
721
|
if (option_given_p(opts, tmp)) {
|
689
722
|
VALUE match_string = rb_hash_aref(opts, tmp);
|
@@ -691,7 +724,9 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
691
724
|
} else {
|
692
725
|
json->match_string = Qnil;
|
693
726
|
}
|
727
|
+
#ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
|
694
728
|
}
|
729
|
+
#endif
|
695
730
|
} else {
|
696
731
|
json->max_nesting = 100;
|
697
732
|
json->allow_nan = 0;
|
@@ -699,12 +734,9 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
699
734
|
json->create_id = rb_funcall(mJSON, i_create_id, 0);
|
700
735
|
json->object_class = Qnil;
|
701
736
|
json->array_class = Qnil;
|
737
|
+
json->decimal_class = Qnil;
|
702
738
|
}
|
703
|
-
source =
|
704
|
-
if (!json->quirks_mode) {
|
705
|
-
source = convert_encoding(StringValue(source));
|
706
|
-
}
|
707
|
-
json->current_nesting = 0;
|
739
|
+
source = convert_encoding(StringValue(source));
|
708
740
|
StringValue(source);
|
709
741
|
json->len = RSTRING_LEN(source);
|
710
742
|
json->source = RSTRING_PTR(source);;
|
@@ -719,56 +751,8 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
719
751
|
|
720
752
|
include JSON_common;
|
721
753
|
|
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
754
|
action parse_value {
|
771
|
-
char *np = JSON_parse_value(json, fpc, pe, &result);
|
755
|
+
char *np = JSON_parse_value(json, fpc, pe, &result, 0);
|
772
756
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
773
757
|
}
|
774
758
|
|
@@ -777,26 +761,6 @@ static VALUE cParser_parse_strict(VALUE self)
|
|
777
761
|
) ignore*;
|
778
762
|
}%%
|
779
763
|
|
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
764
|
/*
|
801
765
|
* call-seq: parse()
|
802
766
|
*
|
@@ -805,12 +769,21 @@ static VALUE cParser_parse_quirks_mode(VALUE self)
|
|
805
769
|
*/
|
806
770
|
static VALUE cParser_parse(VALUE self)
|
807
771
|
{
|
772
|
+
char *p, *pe;
|
773
|
+
int cs = EVIL;
|
774
|
+
VALUE result = Qnil;
|
808
775
|
GET_PARSER;
|
809
776
|
|
810
|
-
|
811
|
-
|
777
|
+
%% write init;
|
778
|
+
p = json->source;
|
779
|
+
pe = p + json->len;
|
780
|
+
%% write exec;
|
781
|
+
|
782
|
+
if (cs >= JSON_first_final && p == pe) {
|
783
|
+
return result;
|
812
784
|
} else {
|
813
|
-
|
785
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
786
|
+
return Qnil;
|
814
787
|
}
|
815
788
|
}
|
816
789
|
|
@@ -821,6 +794,7 @@ static void JSON_mark(void *ptr)
|
|
821
794
|
rb_gc_mark_maybe(json->create_id);
|
822
795
|
rb_gc_mark_maybe(json->object_class);
|
823
796
|
rb_gc_mark_maybe(json->array_class);
|
797
|
+
rb_gc_mark_maybe(json->decimal_class);
|
824
798
|
rb_gc_mark_maybe(json->match_string);
|
825
799
|
}
|
826
800
|
|
@@ -868,20 +842,9 @@ static VALUE cParser_source(VALUE self)
|
|
868
842
|
return rb_str_dup(json->Vsource);
|
869
843
|
}
|
870
844
|
|
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
845
|
void Init_parser(void)
|
884
846
|
{
|
847
|
+
#undef rb_intern
|
885
848
|
rb_require("json/common");
|
886
849
|
mJSON = rb_define_module("JSON");
|
887
850
|
mExt = rb_define_module_under(mJSON, "Ext");
|
@@ -892,7 +855,6 @@ void Init_parser(void)
|
|
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"));
|
898
860
|
CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
|
@@ -906,9 +868,9 @@ void Init_parser(void)
|
|
906
868
|
i_max_nesting = rb_intern("max_nesting");
|
907
869
|
i_allow_nan = rb_intern("allow_nan");
|
908
870
|
i_symbolize_names = rb_intern("symbolize_names");
|
909
|
-
i_quirks_mode = rb_intern("quirks_mode");
|
910
871
|
i_object_class = rb_intern("object_class");
|
911
872
|
i_array_class = rb_intern("array_class");
|
873
|
+
i_decimal_class = rb_intern("decimal_class");
|
912
874
|
i_match = rb_intern("match");
|
913
875
|
i_match_string = rb_intern("match_string");
|
914
876
|
i_key_p = rb_intern("key?");
|
@@ -916,18 +878,8 @@ void Init_parser(void)
|
|
916
878
|
i_aset = rb_intern("[]=");
|
917
879
|
i_aref = rb_intern("[]");
|
918
880
|
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
|
881
|
+
i_new = rb_intern("new");
|
882
|
+
i_BigDecimal = rb_intern("BigDecimal");
|
931
883
|
}
|
932
884
|
|
933
885
|
/*
|
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
|
|
@@ -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
|
|
@@ -173,9 +172,7 @@ public final class Generator {
|
|
173
172
|
result = RubyString.newString(session.getRuntime(), buffer);
|
174
173
|
ThreadContext context = session.getContext();
|
175
174
|
RuntimeInfo info = session.getInfo();
|
176
|
-
|
177
|
-
result.force_encoding(context, info.utf8.get());
|
178
|
-
}
|
175
|
+
result.force_encoding(context, info.utf8.get());
|
179
176
|
return result;
|
180
177
|
}
|
181
178
|
|
@@ -382,8 +379,7 @@ public final class Generator {
|
|
382
379
|
RuntimeInfo info = session.getInfo();
|
383
380
|
RubyString src;
|
384
381
|
|
385
|
-
if (info.
|
386
|
-
object.encoding(session.getContext()) != info.utf8.get()) {
|
382
|
+
if (object.encoding(session.getContext()) != info.utf8.get()) {
|
387
383
|
src = (RubyString)object.encode(session.getContext(),
|
388
384
|
info.utf8.get());
|
389
385
|
} else {
|
@@ -428,11 +424,14 @@ public final class Generator {
|
|
428
424
|
new Handler<IRubyObject>() {
|
429
425
|
@Override
|
430
426
|
RubyString generateNew(Session session, IRubyObject object) {
|
431
|
-
|
432
|
-
object.callMethod(session.getContext(), "to_json",
|
433
|
-
|
434
|
-
|
435
|
-
|
427
|
+
if (object.respondsTo("to_json")) {
|
428
|
+
IRubyObject result = object.callMethod(session.getContext(), "to_json",
|
429
|
+
new IRubyObject[] {session.getState()});
|
430
|
+
if (result instanceof RubyString) return (RubyString)result;
|
431
|
+
throw session.getRuntime().newTypeError("to_json must return a String");
|
432
|
+
} else {
|
433
|
+
return OBJECT_HANDLER.generateNew(session, object);
|
434
|
+
}
|
436
435
|
}
|
437
436
|
|
438
437
|
@Override
|
@@ -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
|
|