json 1.8.6 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/.travis.yml +13 -5
- data/{CHANGES → CHANGES.md} +212 -95
- data/Gemfile +10 -3
- data/{README-json-jruby.markdown → README-json-jruby.md} +0 -0
- data/README.md +187 -107
- data/Rakefile +36 -104
- data/VERSION +1 -1
- data/ext/json/ext/fbuffer/fbuffer.h +0 -3
- data/ext/json/ext/generator/generator.c +175 -98
- data/ext/json/ext/generator/generator.h +0 -6
- data/ext/json/ext/parser/extconf.rb +3 -0
- data/ext/json/ext/parser/parser.c +380 -483
- data/ext/json/ext/parser/parser.h +4 -5
- data/ext/json/ext/parser/parser.rl +109 -175
- data/ext/json/extconf.rb +0 -1
- data/java/src/json/ext/Generator.java +35 -15
- data/java/src/json/ext/GeneratorState.java +2 -54
- data/java/src/json/ext/OptionsReader.java +1 -1
- data/java/src/json/ext/Parser.java +131 -413
- data/java/src/json/ext/Parser.rl +47 -122
- data/java/src/json/ext/RuntimeInfo.java +0 -4
- data/json-java.gemspec +4 -5
- data/json.gemspec +0 -0
- data/json_pure.gemspec +11 -15
- data/lib/json.rb +379 -29
- 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 +335 -128
- data/lib/json/ext.rb +0 -6
- data/lib/json/generic_object.rb +5 -4
- data/lib/json/pure.rb +2 -8
- data/lib/json/pure/generator.rb +54 -125
- data/lib/json/pure/parser.rb +42 -82
- data/lib/json/version.rb +2 -1
- 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} +10 -8
- data/tests/{test_json_generate.rb → json_generator_test.rb} +112 -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/fuzz.rb +1 -9
- metadata +38 -43
- 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 -519
- 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);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
#include "parser.h"
|
|
3
3
|
|
|
4
4
|
#if defined HAVE_RUBY_ENCODING_H
|
|
5
|
-
# define EXC_ENCODING
|
|
5
|
+
# define EXC_ENCODING rb_utf8_encoding(),
|
|
6
6
|
# ifndef HAVE_RB_ENC_RAISE
|
|
7
7
|
static void
|
|
8
8
|
enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
|
|
@@ -25,7 +25,7 @@ enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
|
|
|
25
25
|
|
|
26
26
|
/* unicode */
|
|
27
27
|
|
|
28
|
-
static const char digit_values[256] = {
|
|
28
|
+
static const signed char digit_values[256] = {
|
|
29
29
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
30
30
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
31
31
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1,
|
|
@@ -44,7 +44,7 @@ static const char digit_values[256] = {
|
|
|
44
44
|
|
|
45
45
|
static UTF32 unescape_unicode(const unsigned char *p)
|
|
46
46
|
{
|
|
47
|
-
char b;
|
|
47
|
+
signed char b;
|
|
48
48
|
UTF32 result = 0;
|
|
49
49
|
b = digit_values[p[0]];
|
|
50
50
|
if (b < 0) return UNI_REPLACEMENT_CHAR;
|
|
@@ -87,19 +87,15 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
|
|
|
87
87
|
return len;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
|
91
|
-
static rb_encoding *UTF_8, *UTF_16BE, *UTF_16LE, *UTF_32BE, *UTF_32LE;
|
|
92
|
-
#else
|
|
93
|
-
static ID i_iconv;
|
|
94
|
-
#endif
|
|
95
|
-
|
|
96
90
|
static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
|
|
97
91
|
static VALUE CNaN, CInfinity, CMinusInfinity;
|
|
92
|
+
static VALUE cBigDecimal = Qundef;
|
|
98
93
|
|
|
99
94
|
static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
|
100
|
-
i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
|
|
101
|
-
i_object_class, i_array_class,
|
|
102
|
-
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;
|
|
103
99
|
|
|
104
100
|
%%{
|
|
105
101
|
machine JSON_common;
|
|
@@ -137,11 +133,12 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
|
|
137
133
|
|
|
138
134
|
action parse_value {
|
|
139
135
|
VALUE v = Qnil;
|
|
140
|
-
char *np = JSON_parse_value(json, fpc, pe, &v);
|
|
136
|
+
char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
|
|
141
137
|
if (np == NULL) {
|
|
142
138
|
fhold; fbreak;
|
|
143
139
|
} else {
|
|
144
140
|
if (NIL_P(json->object_class)) {
|
|
141
|
+
OBJ_FREEZE(last_name);
|
|
145
142
|
rb_hash_aset(*result, last_name, v);
|
|
146
143
|
} else {
|
|
147
144
|
rb_funcall(*result, i_aset, 2, last_name, v);
|
|
@@ -170,14 +167,14 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
|
|
170
167
|
) @exit;
|
|
171
168
|
}%%
|
|
172
169
|
|
|
173
|
-
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)
|
|
174
171
|
{
|
|
175
172
|
int cs = EVIL;
|
|
176
173
|
VALUE last_name = Qnil;
|
|
177
174
|
VALUE object_class = json->object_class;
|
|
178
175
|
|
|
179
|
-
if (json->max_nesting &&
|
|
180
|
-
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);
|
|
181
178
|
}
|
|
182
179
|
|
|
183
180
|
*result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class);
|
|
@@ -243,7 +240,7 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
|
243
240
|
|
|
244
241
|
action parse_number {
|
|
245
242
|
char *np;
|
|
246
|
-
if(pe > fpc +
|
|
243
|
+
if(pe > fpc + 8 && !strncmp(MinusInfinity, fpc, 9)) {
|
|
247
244
|
if (json->allow_nan) {
|
|
248
245
|
*result = CMinusInfinity;
|
|
249
246
|
fexec p + 10;
|
|
@@ -261,23 +258,19 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
|
261
258
|
|
|
262
259
|
action parse_array {
|
|
263
260
|
char *np;
|
|
264
|
-
json
|
|
265
|
-
np = JSON_parse_array(json, fpc, pe, result);
|
|
266
|
-
json->current_nesting--;
|
|
261
|
+
np = JSON_parse_array(json, fpc, pe, result, current_nesting + 1);
|
|
267
262
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
|
268
263
|
}
|
|
269
264
|
|
|
270
265
|
action parse_object {
|
|
271
266
|
char *np;
|
|
272
|
-
json
|
|
273
|
-
np = JSON_parse_object(json, fpc, pe, result);
|
|
274
|
-
json->current_nesting--;
|
|
267
|
+
np = JSON_parse_object(json, fpc, pe, result, current_nesting + 1);
|
|
275
268
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
|
276
269
|
}
|
|
277
270
|
|
|
278
271
|
action exit { fhold; fbreak; }
|
|
279
272
|
|
|
280
|
-
main := (
|
|
273
|
+
main := ignore* (
|
|
281
274
|
Vnull @parse_null |
|
|
282
275
|
Vfalse @parse_false |
|
|
283
276
|
Vtrue @parse_true |
|
|
@@ -287,10 +280,10 @@ main := (
|
|
|
287
280
|
begin_string >parse_string |
|
|
288
281
|
begin_array >parse_array |
|
|
289
282
|
begin_object >parse_object
|
|
290
|
-
) %*exit;
|
|
283
|
+
) ignore* %*exit;
|
|
291
284
|
}%%
|
|
292
285
|
|
|
293
|
-
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)
|
|
294
287
|
{
|
|
295
288
|
int cs = EVIL;
|
|
296
289
|
|
|
@@ -348,6 +341,19 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
|
|
|
348
341
|
) (^[0-9Ee.\-]? @exit );
|
|
349
342
|
}%%
|
|
350
343
|
|
|
344
|
+
static int is_bigdecimal_class(VALUE obj)
|
|
345
|
+
{
|
|
346
|
+
if (cBigDecimal == Qundef) {
|
|
347
|
+
if (rb_const_defined(rb_cObject, i_BigDecimal)) {
|
|
348
|
+
cBigDecimal = rb_const_get_at(rb_cObject, i_BigDecimal);
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
return 0;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
return obj == cBigDecimal;
|
|
355
|
+
}
|
|
356
|
+
|
|
351
357
|
static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
|
352
358
|
{
|
|
353
359
|
int cs = EVIL;
|
|
@@ -361,7 +367,17 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
|
361
367
|
fbuffer_clear(json->fbuffer);
|
|
362
368
|
fbuffer_append(json->fbuffer, json->memo, len);
|
|
363
369
|
fbuffer_append_char(json->fbuffer, '\0');
|
|
364
|
-
|
|
370
|
+
if (NIL_P(json->decimal_class)) {
|
|
371
|
+
*result = rb_float_new(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
|
|
372
|
+
} else {
|
|
373
|
+
VALUE text;
|
|
374
|
+
text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
|
|
375
|
+
if (is_bigdecimal_class(json->decimal_class)) {
|
|
376
|
+
*result = rb_funcall(Qnil, i_BigDecimal, 1, text);
|
|
377
|
+
} else {
|
|
378
|
+
*result = rb_funcall(json->decimal_class, i_new, 1, text);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
365
381
|
return p + 1;
|
|
366
382
|
} else {
|
|
367
383
|
return NULL;
|
|
@@ -377,7 +393,7 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
|
377
393
|
|
|
378
394
|
action parse_value {
|
|
379
395
|
VALUE v = Qnil;
|
|
380
|
-
char *np = JSON_parse_value(json, fpc, pe, &v);
|
|
396
|
+
char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
|
|
381
397
|
if (np == NULL) {
|
|
382
398
|
fhold; fbreak;
|
|
383
399
|
} else {
|
|
@@ -400,13 +416,13 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
|
400
416
|
end_array @exit;
|
|
401
417
|
}%%
|
|
402
418
|
|
|
403
|
-
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
|
419
|
+
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
|
|
404
420
|
{
|
|
405
421
|
int cs = EVIL;
|
|
406
422
|
VALUE array_class = json->array_class;
|
|
407
423
|
|
|
408
|
-
if (json->max_nesting &&
|
|
409
|
-
rb_raise(eNestingError, "nesting of %d is too deep",
|
|
424
|
+
if (json->max_nesting && current_nesting > json->max_nesting) {
|
|
425
|
+
rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
|
|
410
426
|
}
|
|
411
427
|
*result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
|
|
412
428
|
|
|
@@ -456,13 +472,21 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
|
|
|
456
472
|
break;
|
|
457
473
|
case 'u':
|
|
458
474
|
if (pe > stringEnd - 4) {
|
|
459
|
-
|
|
475
|
+
rb_enc_raise(
|
|
476
|
+
EXC_ENCODING eParserError,
|
|
477
|
+
"%u: incomplete unicode character escape sequence at '%s'", __LINE__, p
|
|
478
|
+
);
|
|
460
479
|
} else {
|
|
461
480
|
UTF32 ch = unescape_unicode((unsigned char *) ++pe);
|
|
462
481
|
pe += 3;
|
|
463
482
|
if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
|
|
464
483
|
pe++;
|
|
465
|
-
if (pe > stringEnd - 6)
|
|
484
|
+
if (pe > stringEnd - 6) {
|
|
485
|
+
rb_enc_raise(
|
|
486
|
+
EXC_ENCODING eParserError,
|
|
487
|
+
"%u: incomplete surrogate pair at '%s'", __LINE__, p
|
|
488
|
+
);
|
|
489
|
+
}
|
|
466
490
|
if (pe[0] == '\\' && pe[1] == 'u') {
|
|
467
491
|
UTF32 sur = unescape_unicode((unsigned char *) pe + 2);
|
|
468
492
|
ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16)
|
|
@@ -548,6 +572,8 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
|
548
572
|
|
|
549
573
|
if (json->symbolize_names && json->parsing_name) {
|
|
550
574
|
*result = rb_str_intern(*result);
|
|
575
|
+
} else if (RB_TYPE_P(*result, T_STRING)) {
|
|
576
|
+
rb_str_resize(*result, RSTRING_LEN(*result));
|
|
551
577
|
}
|
|
552
578
|
if (cs >= JSON_string_first_final) {
|
|
553
579
|
return p + 1;
|
|
@@ -570,41 +596,16 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
|
570
596
|
|
|
571
597
|
static VALUE convert_encoding(VALUE source)
|
|
572
598
|
{
|
|
573
|
-
const char *ptr = RSTRING_PTR(source);
|
|
574
|
-
long len = RSTRING_LEN(source);
|
|
575
|
-
if (len < 2) {
|
|
576
|
-
rb_raise(eParserError, "A JSON text must at least contain two octets!");
|
|
577
|
-
}
|
|
578
599
|
#ifdef HAVE_RUBY_ENCODING_H
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
source = rb_str_conv_enc(source, UTF_32BE, rb_utf8_encoding());
|
|
584
|
-
} else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
|
|
585
|
-
source = rb_str_conv_enc(source, UTF_16BE, rb_utf8_encoding());
|
|
586
|
-
} else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
|
|
587
|
-
source = rb_str_conv_enc(source, UTF_32LE, rb_utf8_encoding());
|
|
588
|
-
} else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
|
|
589
|
-
source = rb_str_conv_enc(source, UTF_16LE, rb_utf8_encoding());
|
|
590
|
-
} else {
|
|
591
|
-
source = rb_str_dup(source);
|
|
592
|
-
FORCE_UTF8(source);
|
|
593
|
-
}
|
|
594
|
-
} else {
|
|
595
|
-
source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding());
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
#else
|
|
599
|
-
if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
|
|
600
|
-
source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-32be"), source);
|
|
601
|
-
} else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
|
|
602
|
-
source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-16be"), source);
|
|
603
|
-
} else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
|
|
604
|
-
source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-32le"), source);
|
|
605
|
-
} else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
|
|
606
|
-
source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-16le"), source);
|
|
600
|
+
rb_encoding *enc = rb_enc_get(source);
|
|
601
|
+
if (enc == rb_ascii8bit_encoding()) {
|
|
602
|
+
if (OBJ_FROZEN(source)) {
|
|
603
|
+
source = rb_str_dup(source);
|
|
607
604
|
}
|
|
605
|
+
FORCE_UTF8(source);
|
|
606
|
+
} else {
|
|
607
|
+
source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding());
|
|
608
|
+
}
|
|
608
609
|
#endif
|
|
609
610
|
return source;
|
|
610
611
|
}
|
|
@@ -627,8 +628,9 @@ static VALUE convert_encoding(VALUE source)
|
|
|
627
628
|
* defiance of RFC 4627 to be parsed by the Parser. This option defaults to
|
|
628
629
|
* false.
|
|
629
630
|
* * *symbolize_names*: If set to true, returns symbols for the names
|
|
630
|
-
* (keys) in a JSON object. Otherwise strings are returned, which is
|
|
631
|
-
* the default.
|
|
631
|
+
* (keys) in a JSON object. Otherwise strings are returned, which is
|
|
632
|
+
* also the default. It's not possible to use this option in
|
|
633
|
+
* conjunction with the *create_additions* option.
|
|
632
634
|
* * *create_additions*: If set to false, the Parser doesn't create
|
|
633
635
|
* additions even if a matching class and create_id was found. This option
|
|
634
636
|
* defaults to false.
|
|
@@ -679,19 +681,17 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
679
681
|
} else {
|
|
680
682
|
json->symbolize_names = 0;
|
|
681
683
|
}
|
|
682
|
-
tmp = ID2SYM(i_quirks_mode);
|
|
683
|
-
if (option_given_p(opts, tmp)) {
|
|
684
|
-
VALUE quirks_mode = rb_hash_aref(opts, tmp);
|
|
685
|
-
json->quirks_mode = RTEST(quirks_mode) ? 1 : 0;
|
|
686
|
-
} else {
|
|
687
|
-
json->quirks_mode = 0;
|
|
688
|
-
}
|
|
689
684
|
tmp = ID2SYM(i_create_additions);
|
|
690
685
|
if (option_given_p(opts, tmp)) {
|
|
691
686
|
json->create_additions = RTEST(rb_hash_aref(opts, tmp));
|
|
692
687
|
} else {
|
|
693
688
|
json->create_additions = 0;
|
|
694
689
|
}
|
|
690
|
+
if (json->symbolize_names && json->create_additions) {
|
|
691
|
+
rb_raise(rb_eArgError,
|
|
692
|
+
"options :symbolize_names and :create_additions cannot be "
|
|
693
|
+
" used in conjunction");
|
|
694
|
+
}
|
|
695
695
|
tmp = ID2SYM(i_create_id);
|
|
696
696
|
if (option_given_p(opts, tmp)) {
|
|
697
697
|
json->create_id = rb_hash_aref(opts, tmp);
|
|
@@ -710,6 +710,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
710
710
|
} else {
|
|
711
711
|
json->array_class = Qnil;
|
|
712
712
|
}
|
|
713
|
+
tmp = ID2SYM(i_decimal_class);
|
|
714
|
+
if (option_given_p(opts, tmp)) {
|
|
715
|
+
json->decimal_class = rb_hash_aref(opts, tmp);
|
|
716
|
+
} else {
|
|
717
|
+
json->decimal_class = Qnil;
|
|
718
|
+
}
|
|
713
719
|
tmp = ID2SYM(i_match_string);
|
|
714
720
|
if (option_given_p(opts, tmp)) {
|
|
715
721
|
VALUE match_string = rb_hash_aref(opts, tmp);
|
|
@@ -723,16 +729,14 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
723
729
|
} else {
|
|
724
730
|
json->max_nesting = 100;
|
|
725
731
|
json->allow_nan = 0;
|
|
726
|
-
json->create_additions =
|
|
732
|
+
json->create_additions = 0;
|
|
727
733
|
json->create_id = rb_funcall(mJSON, i_create_id, 0);
|
|
728
734
|
json->object_class = Qnil;
|
|
729
735
|
json->array_class = Qnil;
|
|
736
|
+
json->decimal_class = Qnil;
|
|
730
737
|
}
|
|
738
|
+
source = convert_encoding(StringValue(source));
|
|
731
739
|
StringValue(source);
|
|
732
|
-
if (!json->quirks_mode) {
|
|
733
|
-
source = convert_encoding(source);
|
|
734
|
-
}
|
|
735
|
-
json->current_nesting = 0;
|
|
736
740
|
json->len = RSTRING_LEN(source);
|
|
737
741
|
json->source = RSTRING_PTR(source);;
|
|
738
742
|
json->Vsource = source;
|
|
@@ -746,56 +750,8 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
746
750
|
|
|
747
751
|
include JSON_common;
|
|
748
752
|
|
|
749
|
-
action parse_object {
|
|
750
|
-
char *np;
|
|
751
|
-
json->current_nesting = 1;
|
|
752
|
-
np = JSON_parse_object(json, fpc, pe, &result);
|
|
753
|
-
if (np == NULL) { fhold; fbreak; } else fexec np;
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
action parse_array {
|
|
757
|
-
char *np;
|
|
758
|
-
json->current_nesting = 1;
|
|
759
|
-
np = JSON_parse_array(json, fpc, pe, &result);
|
|
760
|
-
if (np == NULL) { fhold; fbreak; } else fexec np;
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
main := ignore* (
|
|
764
|
-
begin_object >parse_object |
|
|
765
|
-
begin_array >parse_array
|
|
766
|
-
) ignore*;
|
|
767
|
-
}%%
|
|
768
|
-
|
|
769
|
-
static VALUE cParser_parse_strict(VALUE self)
|
|
770
|
-
{
|
|
771
|
-
char *p, *pe;
|
|
772
|
-
int cs = EVIL;
|
|
773
|
-
VALUE result = Qnil;
|
|
774
|
-
GET_PARSER;
|
|
775
|
-
|
|
776
|
-
%% write init;
|
|
777
|
-
p = json->source;
|
|
778
|
-
pe = p + json->len;
|
|
779
|
-
%% write exec;
|
|
780
|
-
|
|
781
|
-
if (cs >= JSON_first_final && p == pe) {
|
|
782
|
-
return result;
|
|
783
|
-
} else {
|
|
784
|
-
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
|
785
|
-
return Qnil;
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
%%{
|
|
791
|
-
machine JSON_quirks_mode;
|
|
792
|
-
|
|
793
|
-
write data;
|
|
794
|
-
|
|
795
|
-
include JSON_common;
|
|
796
|
-
|
|
797
753
|
action parse_value {
|
|
798
|
-
char *np = JSON_parse_value(json, fpc, pe, &result);
|
|
754
|
+
char *np = JSON_parse_value(json, fpc, pe, &result, 0);
|
|
799
755
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
|
800
756
|
}
|
|
801
757
|
|
|
@@ -804,26 +760,6 @@ static VALUE cParser_parse_strict(VALUE self)
|
|
|
804
760
|
) ignore*;
|
|
805
761
|
}%%
|
|
806
762
|
|
|
807
|
-
static VALUE cParser_parse_quirks_mode(VALUE self)
|
|
808
|
-
{
|
|
809
|
-
char *p, *pe;
|
|
810
|
-
int cs = EVIL;
|
|
811
|
-
VALUE result = Qnil;
|
|
812
|
-
GET_PARSER;
|
|
813
|
-
|
|
814
|
-
%% write init;
|
|
815
|
-
p = json->source;
|
|
816
|
-
pe = p + json->len;
|
|
817
|
-
%% write exec;
|
|
818
|
-
|
|
819
|
-
if (cs >= JSON_quirks_mode_first_final && p == pe) {
|
|
820
|
-
return result;
|
|
821
|
-
} else {
|
|
822
|
-
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
|
823
|
-
return Qnil;
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
|
|
827
763
|
/*
|
|
828
764
|
* call-seq: parse()
|
|
829
765
|
*
|
|
@@ -832,12 +768,21 @@ static VALUE cParser_parse_quirks_mode(VALUE self)
|
|
|
832
768
|
*/
|
|
833
769
|
static VALUE cParser_parse(VALUE self)
|
|
834
770
|
{
|
|
771
|
+
char *p, *pe;
|
|
772
|
+
int cs = EVIL;
|
|
773
|
+
VALUE result = Qnil;
|
|
835
774
|
GET_PARSER;
|
|
836
775
|
|
|
837
|
-
|
|
838
|
-
|
|
776
|
+
%% write init;
|
|
777
|
+
p = json->source;
|
|
778
|
+
pe = p + json->len;
|
|
779
|
+
%% write exec;
|
|
780
|
+
|
|
781
|
+
if (cs >= JSON_first_final && p == pe) {
|
|
782
|
+
return result;
|
|
839
783
|
} else {
|
|
840
|
-
|
|
784
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
|
785
|
+
return Qnil;
|
|
841
786
|
}
|
|
842
787
|
}
|
|
843
788
|
|
|
@@ -848,6 +793,7 @@ static void JSON_mark(void *ptr)
|
|
|
848
793
|
rb_gc_mark_maybe(json->create_id);
|
|
849
794
|
rb_gc_mark_maybe(json->object_class);
|
|
850
795
|
rb_gc_mark_maybe(json->array_class);
|
|
796
|
+
rb_gc_mark_maybe(json->decimal_class);
|
|
851
797
|
rb_gc_mark_maybe(json->match_string);
|
|
852
798
|
}
|
|
853
799
|
|
|
@@ -895,35 +841,30 @@ static VALUE cParser_source(VALUE self)
|
|
|
895
841
|
return rb_str_dup(json->Vsource);
|
|
896
842
|
}
|
|
897
843
|
|
|
898
|
-
/*
|
|
899
|
-
* call-seq: quirks_mode?()
|
|
900
|
-
*
|
|
901
|
-
* Returns a true, if this parser is in quirks_mode, false otherwise.
|
|
902
|
-
*/
|
|
903
|
-
static VALUE cParser_quirks_mode_p(VALUE self)
|
|
904
|
-
{
|
|
905
|
-
GET_PARSER;
|
|
906
|
-
return json->quirks_mode ? Qtrue : Qfalse;
|
|
907
|
-
}
|
|
908
|
-
|
|
909
|
-
|
|
910
844
|
void Init_parser(void)
|
|
911
845
|
{
|
|
846
|
+
#undef rb_intern
|
|
912
847
|
rb_require("json/common");
|
|
913
848
|
mJSON = rb_define_module("JSON");
|
|
914
849
|
mExt = rb_define_module_under(mJSON, "Ext");
|
|
915
850
|
cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
|
|
916
851
|
eParserError = rb_path2class("JSON::ParserError");
|
|
917
852
|
eNestingError = rb_path2class("JSON::NestingError");
|
|
853
|
+
rb_gc_register_mark_object(eParserError);
|
|
854
|
+
rb_gc_register_mark_object(eNestingError);
|
|
918
855
|
rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
|
|
919
856
|
rb_define_method(cParser, "initialize", cParser_initialize, -1);
|
|
920
857
|
rb_define_method(cParser, "parse", cParser_parse, 0);
|
|
921
858
|
rb_define_method(cParser, "source", cParser_source, 0);
|
|
922
|
-
rb_define_method(cParser, "quirks_mode?", cParser_quirks_mode_p, 0);
|
|
923
859
|
|
|
924
860
|
CNaN = rb_const_get(mJSON, rb_intern("NaN"));
|
|
861
|
+
rb_gc_register_mark_object(CNaN);
|
|
862
|
+
|
|
925
863
|
CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
|
|
864
|
+
rb_gc_register_mark_object(CInfinity);
|
|
865
|
+
|
|
926
866
|
CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
|
|
867
|
+
rb_gc_register_mark_object(CMinusInfinity);
|
|
927
868
|
|
|
928
869
|
i_json_creatable_p = rb_intern("json_creatable?");
|
|
929
870
|
i_json_create = rb_intern("json_create");
|
|
@@ -933,9 +874,9 @@ void Init_parser(void)
|
|
|
933
874
|
i_max_nesting = rb_intern("max_nesting");
|
|
934
875
|
i_allow_nan = rb_intern("allow_nan");
|
|
935
876
|
i_symbolize_names = rb_intern("symbolize_names");
|
|
936
|
-
i_quirks_mode = rb_intern("quirks_mode");
|
|
937
877
|
i_object_class = rb_intern("object_class");
|
|
938
878
|
i_array_class = rb_intern("array_class");
|
|
879
|
+
i_decimal_class = rb_intern("decimal_class");
|
|
939
880
|
i_match = rb_intern("match");
|
|
940
881
|
i_match_string = rb_intern("match_string");
|
|
941
882
|
i_key_p = rb_intern("key?");
|
|
@@ -943,15 +884,8 @@ void Init_parser(void)
|
|
|
943
884
|
i_aset = rb_intern("[]=");
|
|
944
885
|
i_aref = rb_intern("[]");
|
|
945
886
|
i_leftshift = rb_intern("<<");
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
UTF_16BE = rb_enc_find("utf-16be");
|
|
949
|
-
UTF_16LE = rb_enc_find("utf-16le");
|
|
950
|
-
UTF_32BE = rb_enc_find("utf-32be");
|
|
951
|
-
UTF_32LE = rb_enc_find("utf-32le");
|
|
952
|
-
#else
|
|
953
|
-
i_iconv = rb_intern("iconv");
|
|
954
|
-
#endif
|
|
887
|
+
i_new = rb_intern("new");
|
|
888
|
+
i_BigDecimal = rb_intern("BigDecimal");
|
|
955
889
|
}
|
|
956
890
|
|
|
957
891
|
/*
|