json 1.8.3 → 2.1.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.
Potentially problematic release.
This version of json might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +3 -10
- data/{CHANGES → CHANGES.md} +183 -90
- data/Gemfile +11 -5
- data/{README-json-jruby.markdown → README-json-jruby.md} +0 -0
- data/{README.rdoc → README.md} +147 -113
- data/Rakefile +32 -36
- data/VERSION +1 -1
- data/ext/json/ext/fbuffer/fbuffer.h +0 -3
- data/ext/json/ext/generator/generator.c +46 -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 +353 -460
- data/ext/json/ext/parser/parser.h +4 -5
- data/ext/json/ext/parser/parser.rl +111 -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 +135 -418
- 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 +2 -2
- 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/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} +22 -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 +471 -0
- data/tests/json_string_matching_test.rb +38 -0
- data/tests/{setup_variant.rb → test_helper.rb} +10 -0
- data/tools/diff.sh +18 -0
- data/tools/fuzz.rb +1 -9
- metadata +28 -43
- data/COPYING +0 -58
- data/COPYING-json-jruby +0 -57
- data/GPL +0 -340
- data/TODO +0 -1
- 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,14 @@ 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;
|
78
92
|
|
79
93
|
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,
|
94
|
+
i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
|
95
|
+
i_object_class, i_array_class, i_decimal_class, i_key_p,
|
96
|
+
i_deep_const_get, i_match, i_match_string, i_aset, i_aref,
|
97
|
+
i_leftshift, i_new;
|
83
98
|
|
84
99
|
%%{
|
85
100
|
machine JSON_common;
|
@@ -117,7 +132,7 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
|
117
132
|
|
118
133
|
action parse_value {
|
119
134
|
VALUE v = Qnil;
|
120
|
-
char *np = JSON_parse_value(json, fpc, pe, &v);
|
135
|
+
char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
|
121
136
|
if (np == NULL) {
|
122
137
|
fhold; fbreak;
|
123
138
|
} else {
|
@@ -150,14 +165,14 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
|
150
165
|
) @exit;
|
151
166
|
}%%
|
152
167
|
|
153
|
-
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
168
|
+
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
|
154
169
|
{
|
155
170
|
int cs = EVIL;
|
156
171
|
VALUE last_name = Qnil;
|
157
172
|
VALUE object_class = json->object_class;
|
158
173
|
|
159
|
-
if (json->max_nesting &&
|
160
|
-
rb_raise(eNestingError, "nesting of %d is too deep",
|
174
|
+
if (json->max_nesting && current_nesting > json->max_nesting) {
|
175
|
+
rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
|
161
176
|
}
|
162
177
|
|
163
178
|
*result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class);
|
@@ -206,14 +221,14 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
206
221
|
if (json->allow_nan) {
|
207
222
|
*result = CNaN;
|
208
223
|
} else {
|
209
|
-
|
224
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2);
|
210
225
|
}
|
211
226
|
}
|
212
227
|
action parse_infinity {
|
213
228
|
if (json->allow_nan) {
|
214
229
|
*result = CInfinity;
|
215
230
|
} else {
|
216
|
-
|
231
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8);
|
217
232
|
}
|
218
233
|
}
|
219
234
|
action parse_string {
|
@@ -223,13 +238,13 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
223
238
|
|
224
239
|
action parse_number {
|
225
240
|
char *np;
|
226
|
-
if(pe > fpc +
|
241
|
+
if(pe > fpc + 8 && !strncmp(MinusInfinity, fpc, 9)) {
|
227
242
|
if (json->allow_nan) {
|
228
243
|
*result = CMinusInfinity;
|
229
244
|
fexec p + 10;
|
230
245
|
fhold; fbreak;
|
231
246
|
} else {
|
232
|
-
|
247
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
233
248
|
}
|
234
249
|
}
|
235
250
|
np = JSON_parse_float(json, fpc, pe, result);
|
@@ -241,23 +256,19 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
241
256
|
|
242
257
|
action parse_array {
|
243
258
|
char *np;
|
244
|
-
json
|
245
|
-
np = JSON_parse_array(json, fpc, pe, result);
|
246
|
-
json->current_nesting--;
|
259
|
+
np = JSON_parse_array(json, fpc, pe, result, current_nesting + 1);
|
247
260
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
248
261
|
}
|
249
262
|
|
250
263
|
action parse_object {
|
251
264
|
char *np;
|
252
|
-
json
|
253
|
-
np = JSON_parse_object(json, fpc, pe, result);
|
254
|
-
json->current_nesting--;
|
265
|
+
np = JSON_parse_object(json, fpc, pe, result, current_nesting + 1);
|
255
266
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
256
267
|
}
|
257
268
|
|
258
269
|
action exit { fhold; fbreak; }
|
259
270
|
|
260
|
-
main := (
|
271
|
+
main := ignore* (
|
261
272
|
Vnull @parse_null |
|
262
273
|
Vfalse @parse_false |
|
263
274
|
Vtrue @parse_true |
|
@@ -267,10 +278,10 @@ main := (
|
|
267
278
|
begin_string >parse_string |
|
268
279
|
begin_array >parse_array |
|
269
280
|
begin_object >parse_object
|
270
|
-
) %*exit;
|
281
|
+
) ignore* %*exit;
|
271
282
|
}%%
|
272
283
|
|
273
|
-
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
284
|
+
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
|
274
285
|
{
|
275
286
|
int cs = EVIL;
|
276
287
|
|
@@ -341,7 +352,13 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
341
352
|
fbuffer_clear(json->fbuffer);
|
342
353
|
fbuffer_append(json->fbuffer, json->memo, len);
|
343
354
|
fbuffer_append_char(json->fbuffer, '\0');
|
344
|
-
|
355
|
+
if (NIL_P(json->decimal_class)) {
|
356
|
+
*result = rb_float_new(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
|
357
|
+
} else {
|
358
|
+
VALUE text;
|
359
|
+
text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
|
360
|
+
*result = rb_funcall(json->decimal_class, i_new, 1, text);
|
361
|
+
}
|
345
362
|
return p + 1;
|
346
363
|
} else {
|
347
364
|
return NULL;
|
@@ -357,7 +374,7 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
357
374
|
|
358
375
|
action parse_value {
|
359
376
|
VALUE v = Qnil;
|
360
|
-
char *np = JSON_parse_value(json, fpc, pe, &v);
|
377
|
+
char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
|
361
378
|
if (np == NULL) {
|
362
379
|
fhold; fbreak;
|
363
380
|
} else {
|
@@ -380,13 +397,13 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
380
397
|
end_array @exit;
|
381
398
|
}%%
|
382
399
|
|
383
|
-
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
400
|
+
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
|
384
401
|
{
|
385
402
|
int cs = EVIL;
|
386
403
|
VALUE array_class = json->array_class;
|
387
404
|
|
388
|
-
if (json->max_nesting &&
|
389
|
-
rb_raise(eNestingError, "nesting of %d is too deep",
|
405
|
+
if (json->max_nesting && current_nesting > json->max_nesting) {
|
406
|
+
rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
|
390
407
|
}
|
391
408
|
*result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
|
392
409
|
|
@@ -396,7 +413,7 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
396
413
|
if(cs >= JSON_array_first_final) {
|
397
414
|
return p + 1;
|
398
415
|
} else {
|
399
|
-
|
416
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
400
417
|
return NULL;
|
401
418
|
}
|
402
419
|
}
|
@@ -436,13 +453,21 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
|
|
436
453
|
break;
|
437
454
|
case 'u':
|
438
455
|
if (pe > stringEnd - 4) {
|
439
|
-
|
456
|
+
rb_enc_raise(
|
457
|
+
EXC_ENCODING eParserError,
|
458
|
+
"%u: incomplete unicode character escape sequence at '%s'", __LINE__, p
|
459
|
+
);
|
440
460
|
} else {
|
441
461
|
UTF32 ch = unescape_unicode((unsigned char *) ++pe);
|
442
462
|
pe += 3;
|
443
463
|
if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
|
444
464
|
pe++;
|
445
|
-
if (pe > stringEnd - 6)
|
465
|
+
if (pe > stringEnd - 6) {
|
466
|
+
rb_enc_raise(
|
467
|
+
EXC_ENCODING eParserError,
|
468
|
+
"%u: incomplete surrogate pair at '%s'", __LINE__, p
|
469
|
+
);
|
470
|
+
}
|
446
471
|
if (pe[0] == '\\' && pe[1] == 'u') {
|
447
472
|
UTF32 sur = unescape_unicode((unsigned char *) pe + 2);
|
448
473
|
ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16)
|
@@ -528,6 +553,8 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
528
553
|
|
529
554
|
if (json->symbolize_names && json->parsing_name) {
|
530
555
|
*result = rb_str_intern(*result);
|
556
|
+
} else {
|
557
|
+
rb_str_resize(*result, RSTRING_LEN(*result));
|
531
558
|
}
|
532
559
|
if (cs >= JSON_string_first_final) {
|
533
560
|
return p + 1;
|
@@ -550,41 +577,16 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
550
577
|
|
551
578
|
static VALUE convert_encoding(VALUE source)
|
552
579
|
{
|
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
580
|
#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);
|
581
|
+
rb_encoding *enc = rb_enc_get(source);
|
582
|
+
if (enc == rb_ascii8bit_encoding()) {
|
583
|
+
if (OBJ_FROZEN(source)) {
|
584
|
+
source = rb_str_dup(source);
|
587
585
|
}
|
586
|
+
FORCE_UTF8(source);
|
587
|
+
} else {
|
588
|
+
source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding());
|
589
|
+
}
|
588
590
|
#endif
|
589
591
|
return source;
|
590
592
|
}
|
@@ -607,8 +609,9 @@ static VALUE convert_encoding(VALUE source)
|
|
607
609
|
* defiance of RFC 4627 to be parsed by the Parser. This option defaults to
|
608
610
|
* false.
|
609
611
|
* * *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.
|
612
|
+
* (keys) in a JSON object. Otherwise strings are returned, which is
|
613
|
+
* also the default. It's not possible to use this option in
|
614
|
+
* conjunction with the *create_additions* option.
|
612
615
|
* * *create_additions*: If set to false, the Parser doesn't create
|
613
616
|
* additions even if a matching class and create_id was found. This option
|
614
617
|
* defaults to false.
|
@@ -623,12 +626,18 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
623
626
|
if (json->Vsource) {
|
624
627
|
rb_raise(rb_eTypeError, "already initialized instance");
|
625
628
|
}
|
629
|
+
#ifdef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
|
630
|
+
rb_scan_args(argc, argv, "1:", &source, &opts);
|
631
|
+
#else
|
626
632
|
rb_scan_args(argc, argv, "11", &source, &opts);
|
633
|
+
#endif
|
627
634
|
if (!NIL_P(opts)) {
|
635
|
+
#ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
|
628
636
|
opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
|
629
637
|
if (NIL_P(opts)) {
|
630
638
|
rb_raise(rb_eArgError, "opts needs to be like a hash");
|
631
639
|
} else {
|
640
|
+
#endif
|
632
641
|
VALUE tmp = ID2SYM(i_max_nesting);
|
633
642
|
if (option_given_p(opts, tmp)) {
|
634
643
|
VALUE max_nesting = rb_hash_aref(opts, tmp);
|
@@ -653,19 +662,17 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
653
662
|
} else {
|
654
663
|
json->symbolize_names = 0;
|
655
664
|
}
|
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
665
|
tmp = ID2SYM(i_create_additions);
|
664
666
|
if (option_given_p(opts, tmp)) {
|
665
667
|
json->create_additions = RTEST(rb_hash_aref(opts, tmp));
|
666
668
|
} else {
|
667
669
|
json->create_additions = 0;
|
668
670
|
}
|
671
|
+
if (json->symbolize_names && json->create_additions) {
|
672
|
+
rb_raise(rb_eArgError,
|
673
|
+
"options :symbolize_names and :create_additions cannot be "
|
674
|
+
" used in conjunction");
|
675
|
+
}
|
669
676
|
tmp = ID2SYM(i_create_id);
|
670
677
|
if (option_given_p(opts, tmp)) {
|
671
678
|
json->create_id = rb_hash_aref(opts, tmp);
|
@@ -684,6 +691,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
684
691
|
} else {
|
685
692
|
json->array_class = Qnil;
|
686
693
|
}
|
694
|
+
tmp = ID2SYM(i_decimal_class);
|
695
|
+
if (option_given_p(opts, tmp)) {
|
696
|
+
json->decimal_class = rb_hash_aref(opts, tmp);
|
697
|
+
} else {
|
698
|
+
json->decimal_class = Qnil;
|
699
|
+
}
|
687
700
|
tmp = ID2SYM(i_match_string);
|
688
701
|
if (option_given_p(opts, tmp)) {
|
689
702
|
VALUE match_string = rb_hash_aref(opts, tmp);
|
@@ -691,7 +704,9 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
691
704
|
} else {
|
692
705
|
json->match_string = Qnil;
|
693
706
|
}
|
707
|
+
#ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
|
694
708
|
}
|
709
|
+
#endif
|
695
710
|
} else {
|
696
711
|
json->max_nesting = 100;
|
697
712
|
json->allow_nan = 0;
|
@@ -699,12 +714,9 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
699
714
|
json->create_id = rb_funcall(mJSON, i_create_id, 0);
|
700
715
|
json->object_class = Qnil;
|
701
716
|
json->array_class = Qnil;
|
717
|
+
json->decimal_class = Qnil;
|
702
718
|
}
|
703
|
-
source =
|
704
|
-
if (!json->quirks_mode) {
|
705
|
-
source = convert_encoding(StringValue(source));
|
706
|
-
}
|
707
|
-
json->current_nesting = 0;
|
719
|
+
source = convert_encoding(StringValue(source));
|
708
720
|
StringValue(source);
|
709
721
|
json->len = RSTRING_LEN(source);
|
710
722
|
json->source = RSTRING_PTR(source);;
|
@@ -719,56 +731,8 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
719
731
|
|
720
732
|
include JSON_common;
|
721
733
|
|
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
734
|
action parse_value {
|
771
|
-
char *np = JSON_parse_value(json, fpc, pe, &result);
|
735
|
+
char *np = JSON_parse_value(json, fpc, pe, &result, 0);
|
772
736
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
773
737
|
}
|
774
738
|
|
@@ -777,26 +741,6 @@ static VALUE cParser_parse_strict(VALUE self)
|
|
777
741
|
) ignore*;
|
778
742
|
}%%
|
779
743
|
|
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
744
|
/*
|
801
745
|
* call-seq: parse()
|
802
746
|
*
|
@@ -805,12 +749,21 @@ static VALUE cParser_parse_quirks_mode(VALUE self)
|
|
805
749
|
*/
|
806
750
|
static VALUE cParser_parse(VALUE self)
|
807
751
|
{
|
752
|
+
char *p, *pe;
|
753
|
+
int cs = EVIL;
|
754
|
+
VALUE result = Qnil;
|
808
755
|
GET_PARSER;
|
809
756
|
|
810
|
-
|
811
|
-
|
757
|
+
%% write init;
|
758
|
+
p = json->source;
|
759
|
+
pe = p + json->len;
|
760
|
+
%% write exec;
|
761
|
+
|
762
|
+
if (cs >= JSON_first_final && p == pe) {
|
763
|
+
return result;
|
812
764
|
} else {
|
813
|
-
|
765
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
766
|
+
return Qnil;
|
814
767
|
}
|
815
768
|
}
|
816
769
|
|
@@ -821,6 +774,7 @@ static void JSON_mark(void *ptr)
|
|
821
774
|
rb_gc_mark_maybe(json->create_id);
|
822
775
|
rb_gc_mark_maybe(json->object_class);
|
823
776
|
rb_gc_mark_maybe(json->array_class);
|
777
|
+
rb_gc_mark_maybe(json->decimal_class);
|
824
778
|
rb_gc_mark_maybe(json->match_string);
|
825
779
|
}
|
826
780
|
|
@@ -868,18 +822,6 @@ static VALUE cParser_source(VALUE self)
|
|
868
822
|
return rb_str_dup(json->Vsource);
|
869
823
|
}
|
870
824
|
|
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
825
|
void Init_parser(void)
|
884
826
|
{
|
885
827
|
rb_require("json/common");
|
@@ -892,7 +834,6 @@ void Init_parser(void)
|
|
892
834
|
rb_define_method(cParser, "initialize", cParser_initialize, -1);
|
893
835
|
rb_define_method(cParser, "parse", cParser_parse, 0);
|
894
836
|
rb_define_method(cParser, "source", cParser_source, 0);
|
895
|
-
rb_define_method(cParser, "quirks_mode?", cParser_quirks_mode_p, 0);
|
896
837
|
|
897
838
|
CNaN = rb_const_get(mJSON, rb_intern("NaN"));
|
898
839
|
CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
|
@@ -906,9 +847,9 @@ void Init_parser(void)
|
|
906
847
|
i_max_nesting = rb_intern("max_nesting");
|
907
848
|
i_allow_nan = rb_intern("allow_nan");
|
908
849
|
i_symbolize_names = rb_intern("symbolize_names");
|
909
|
-
i_quirks_mode = rb_intern("quirks_mode");
|
910
850
|
i_object_class = rb_intern("object_class");
|
911
851
|
i_array_class = rb_intern("array_class");
|
852
|
+
i_decimal_class = rb_intern("decimal_class");
|
912
853
|
i_match = rb_intern("match");
|
913
854
|
i_match_string = rb_intern("match_string");
|
914
855
|
i_key_p = rb_intern("key?");
|
@@ -916,18 +857,7 @@ void Init_parser(void)
|
|
916
857
|
i_aset = rb_intern("[]=");
|
917
858
|
i_aref = rb_intern("[]");
|
918
859
|
i_leftshift = rb_intern("<<");
|
919
|
-
|
920
|
-
CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
|
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
|
860
|
+
i_new = rb_intern("new");
|
931
861
|
}
|
932
862
|
|
933
863
|
/*
|
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
|
|
@@ -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
|
|