json 1.8.6 → 2.6.2
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/{CHANGES → CHANGES.md} +248 -98
- data/LICENSE +56 -0
- data/README.md +188 -108
- data/VERSION +1 -1
- data/ext/json/ext/fbuffer/fbuffer.h +0 -3
- data/ext/json/ext/generator/generator.c +227 -111
- data/ext/json/ext/generator/generator.h +5 -8
- data/ext/json/ext/parser/extconf.rb +29 -0
- data/ext/json/ext/parser/parser.c +3022 -1915
- data/ext/json/ext/parser/parser.h +10 -6
- data/ext/json/ext/parser/parser.rl +206 -183
- data/ext/json/extconf.rb +1 -1
- data/json.gemspec +0 -0
- data/lib/json/add/bigdecimal.rb +3 -2
- data/lib/json/add/complex.rb +4 -4
- data/lib/json/add/core.rb +1 -0
- data/lib/json/add/date.rb +1 -1
- data/lib/json/add/date_time.rb +1 -1
- data/lib/json/add/exception.rb +1 -1
- data/lib/json/add/ostruct.rb +3 -3
- data/lib/json/add/range.rb +1 -1
- data/lib/json/add/rational.rb +3 -3
- data/lib/json/add/regexp.rb +3 -3
- data/lib/json/add/set.rb +29 -0
- data/lib/json/add/struct.rb +1 -1
- data/lib/json/add/symbol.rb +1 -1
- data/lib/json/add/time.rb +1 -1
- data/lib/json/common.rb +381 -162
- data/lib/json/ext.rb +0 -6
- data/lib/json/generic_object.rb +5 -4
- data/lib/json/pure/generator.rb +73 -124
- data/lib/json/pure/parser.rb +63 -85
- data/lib/json/pure.rb +2 -8
- data/lib/json/version.rb +2 -1
- data/lib/json.rb +550 -29
- metadata +20 -127
- data/.gitignore +0 -17
- data/.travis.yml +0 -18
- data/Gemfile +0 -7
- data/README-json-jruby.markdown +0 -33
- data/Rakefile +0 -402
- data/TODO +0 -1
- data/data/example.json +0 -1
- data/data/index.html +0 -38
- data/data/prototype.js +0 -4184
- data/diagrams/.keep +0 -0
- data/install.rb +0 -23
- data/java/src/json/ext/ByteListTranscoder.java +0 -166
- data/java/src/json/ext/Generator.java +0 -446
- data/java/src/json/ext/GeneratorMethods.java +0 -231
- data/java/src/json/ext/GeneratorService.java +0 -42
- data/java/src/json/ext/GeneratorState.java +0 -542
- data/java/src/json/ext/OptionsReader.java +0 -113
- data/java/src/json/ext/Parser.java +0 -2644
- data/java/src/json/ext/Parser.rl +0 -968
- data/java/src/json/ext/ParserService.java +0 -34
- data/java/src/json/ext/RuntimeInfo.java +0 -120
- data/java/src/json/ext/StringDecoder.java +0 -166
- data/java/src/json/ext/StringEncoder.java +0 -111
- data/java/src/json/ext/Utils.java +0 -88
- data/json-java.gemspec +0 -38
- data/json_pure.gemspec +0 -37
- data/lib/json/ext/.keep +0 -0
- data/tests/fixtures/fail1.json +0 -1
- data/tests/fixtures/fail10.json +0 -1
- data/tests/fixtures/fail11.json +0 -1
- data/tests/fixtures/fail12.json +0 -1
- data/tests/fixtures/fail13.json +0 -1
- data/tests/fixtures/fail14.json +0 -1
- data/tests/fixtures/fail18.json +0 -1
- data/tests/fixtures/fail19.json +0 -1
- data/tests/fixtures/fail2.json +0 -1
- data/tests/fixtures/fail20.json +0 -1
- data/tests/fixtures/fail21.json +0 -1
- data/tests/fixtures/fail22.json +0 -1
- data/tests/fixtures/fail23.json +0 -1
- data/tests/fixtures/fail24.json +0 -1
- data/tests/fixtures/fail25.json +0 -1
- data/tests/fixtures/fail27.json +0 -2
- data/tests/fixtures/fail28.json +0 -2
- data/tests/fixtures/fail3.json +0 -1
- data/tests/fixtures/fail4.json +0 -1
- data/tests/fixtures/fail5.json +0 -1
- data/tests/fixtures/fail6.json +0 -1
- data/tests/fixtures/fail7.json +0 -1
- data/tests/fixtures/fail8.json +0 -1
- data/tests/fixtures/fail9.json +0 -1
- data/tests/fixtures/pass1.json +0 -56
- data/tests/fixtures/pass15.json +0 -1
- data/tests/fixtures/pass16.json +0 -1
- data/tests/fixtures/pass17.json +0 -1
- data/tests/fixtures/pass2.json +0 -1
- data/tests/fixtures/pass26.json +0 -1
- data/tests/fixtures/pass3.json +0 -6
- data/tests/setup_variant.rb +0 -11
- data/tests/test_json.rb +0 -519
- data/tests/test_json_addition.rb +0 -196
- data/tests/test_json_encoding.rb +0 -65
- data/tests/test_json_fixtures.rb +0 -35
- data/tests/test_json_generate.rb +0 -348
- data/tests/test_json_generic_object.rb +0 -75
- data/tests/test_json_string_matching.rb +0 -39
- data/tests/test_json_unicode.rb +0 -72
- data/tools/diff.sh +0 -18
- data/tools/fuzz.rb +0 -139
- data/tools/server.rb +0 -62
|
@@ -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,14 @@ 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;
|
|
98
92
|
|
|
99
93
|
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,
|
|
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, i_try_convert, i_freeze, i_uminus;
|
|
103
98
|
|
|
104
99
|
%%{
|
|
105
100
|
machine JSON_common;
|
|
@@ -137,11 +132,12 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
|
|
137
132
|
|
|
138
133
|
action parse_value {
|
|
139
134
|
VALUE v = Qnil;
|
|
140
|
-
char *np = JSON_parse_value(json, fpc, pe, &v);
|
|
135
|
+
char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
|
|
141
136
|
if (np == NULL) {
|
|
142
137
|
fhold; fbreak;
|
|
143
138
|
} else {
|
|
144
139
|
if (NIL_P(json->object_class)) {
|
|
140
|
+
OBJ_FREEZE(last_name);
|
|
145
141
|
rb_hash_aset(*result, last_name, v);
|
|
146
142
|
} else {
|
|
147
143
|
rb_funcall(*result, i_aset, 2, last_name, v);
|
|
@@ -170,14 +166,14 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
|
|
170
166
|
) @exit;
|
|
171
167
|
}%%
|
|
172
168
|
|
|
173
|
-
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)
|
|
174
170
|
{
|
|
175
171
|
int cs = EVIL;
|
|
176
172
|
VALUE last_name = Qnil;
|
|
177
173
|
VALUE object_class = json->object_class;
|
|
178
174
|
|
|
179
|
-
if (json->max_nesting &&
|
|
180
|
-
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);
|
|
181
177
|
}
|
|
182
178
|
|
|
183
179
|
*result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class);
|
|
@@ -243,7 +239,7 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
|
243
239
|
|
|
244
240
|
action parse_number {
|
|
245
241
|
char *np;
|
|
246
|
-
if(pe > fpc +
|
|
242
|
+
if(pe > fpc + 8 && !strncmp(MinusInfinity, fpc, 9)) {
|
|
247
243
|
if (json->allow_nan) {
|
|
248
244
|
*result = CMinusInfinity;
|
|
249
245
|
fexec p + 10;
|
|
@@ -261,23 +257,19 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
|
261
257
|
|
|
262
258
|
action parse_array {
|
|
263
259
|
char *np;
|
|
264
|
-
json
|
|
265
|
-
np = JSON_parse_array(json, fpc, pe, result);
|
|
266
|
-
json->current_nesting--;
|
|
260
|
+
np = JSON_parse_array(json, fpc, pe, result, current_nesting + 1);
|
|
267
261
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
|
268
262
|
}
|
|
269
263
|
|
|
270
264
|
action parse_object {
|
|
271
265
|
char *np;
|
|
272
|
-
json
|
|
273
|
-
np = JSON_parse_object(json, fpc, pe, result);
|
|
274
|
-
json->current_nesting--;
|
|
266
|
+
np = JSON_parse_object(json, fpc, pe, result, current_nesting + 1);
|
|
275
267
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
|
276
268
|
}
|
|
277
269
|
|
|
278
270
|
action exit { fhold; fbreak; }
|
|
279
271
|
|
|
280
|
-
main := (
|
|
272
|
+
main := ignore* (
|
|
281
273
|
Vnull @parse_null |
|
|
282
274
|
Vfalse @parse_false |
|
|
283
275
|
Vtrue @parse_true |
|
|
@@ -287,16 +279,20 @@ main := (
|
|
|
287
279
|
begin_string >parse_string |
|
|
288
280
|
begin_array >parse_array |
|
|
289
281
|
begin_object >parse_object
|
|
290
|
-
) %*exit;
|
|
282
|
+
) ignore* %*exit;
|
|
291
283
|
}%%
|
|
292
284
|
|
|
293
|
-
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)
|
|
294
286
|
{
|
|
295
287
|
int cs = EVIL;
|
|
296
288
|
|
|
297
289
|
%% write init;
|
|
298
290
|
%% write exec;
|
|
299
291
|
|
|
292
|
+
if (json->freeze) {
|
|
293
|
+
OBJ_FREEZE(*result);
|
|
294
|
+
}
|
|
295
|
+
|
|
300
296
|
if (cs >= JSON_value_first_final) {
|
|
301
297
|
return p;
|
|
302
298
|
} else {
|
|
@@ -357,11 +353,46 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
|
357
353
|
%% write exec;
|
|
358
354
|
|
|
359
355
|
if (cs >= JSON_float_first_final) {
|
|
356
|
+
VALUE mod = Qnil;
|
|
357
|
+
ID method_id = 0;
|
|
358
|
+
if (rb_respond_to(json->decimal_class, i_try_convert)) {
|
|
359
|
+
mod = json->decimal_class;
|
|
360
|
+
method_id = i_try_convert;
|
|
361
|
+
} else if (rb_respond_to(json->decimal_class, i_new)) {
|
|
362
|
+
mod = json->decimal_class;
|
|
363
|
+
method_id = i_new;
|
|
364
|
+
} else if (RB_TYPE_P(json->decimal_class, T_CLASS)) {
|
|
365
|
+
VALUE name = rb_class_name(json->decimal_class);
|
|
366
|
+
const char *name_cstr = RSTRING_PTR(name);
|
|
367
|
+
const char *last_colon = strrchr(name_cstr, ':');
|
|
368
|
+
if (last_colon) {
|
|
369
|
+
const char *mod_path_end = last_colon - 1;
|
|
370
|
+
VALUE mod_path = rb_str_substr(name, 0, mod_path_end - name_cstr);
|
|
371
|
+
mod = rb_path_to_class(mod_path);
|
|
372
|
+
|
|
373
|
+
const char *method_name_beg = last_colon + 1;
|
|
374
|
+
long before_len = method_name_beg - name_cstr;
|
|
375
|
+
long len = RSTRING_LEN(name) - before_len;
|
|
376
|
+
VALUE method_name = rb_str_substr(name, before_len, len);
|
|
377
|
+
method_id = SYM2ID(rb_str_intern(method_name));
|
|
378
|
+
} else {
|
|
379
|
+
mod = rb_mKernel;
|
|
380
|
+
method_id = SYM2ID(rb_str_intern(name));
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
360
384
|
long len = p - json->memo;
|
|
361
385
|
fbuffer_clear(json->fbuffer);
|
|
362
386
|
fbuffer_append(json->fbuffer, json->memo, len);
|
|
363
387
|
fbuffer_append_char(json->fbuffer, '\0');
|
|
364
|
-
|
|
388
|
+
|
|
389
|
+
if (method_id) {
|
|
390
|
+
VALUE text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
|
|
391
|
+
*result = rb_funcallv(mod, method_id, 1, &text);
|
|
392
|
+
} else {
|
|
393
|
+
*result = DBL2NUM(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
|
|
394
|
+
}
|
|
395
|
+
|
|
365
396
|
return p + 1;
|
|
366
397
|
} else {
|
|
367
398
|
return NULL;
|
|
@@ -377,7 +408,7 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
|
377
408
|
|
|
378
409
|
action parse_value {
|
|
379
410
|
VALUE v = Qnil;
|
|
380
|
-
char *np = JSON_parse_value(json, fpc, pe, &v);
|
|
411
|
+
char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
|
|
381
412
|
if (np == NULL) {
|
|
382
413
|
fhold; fbreak;
|
|
383
414
|
} else {
|
|
@@ -400,13 +431,13 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
|
400
431
|
end_array @exit;
|
|
401
432
|
}%%
|
|
402
433
|
|
|
403
|
-
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
|
434
|
+
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
|
|
404
435
|
{
|
|
405
436
|
int cs = EVIL;
|
|
406
437
|
VALUE array_class = json->array_class;
|
|
407
438
|
|
|
408
|
-
if (json->max_nesting &&
|
|
409
|
-
rb_raise(eNestingError, "nesting of %d is too deep",
|
|
439
|
+
if (json->max_nesting && current_nesting > json->max_nesting) {
|
|
440
|
+
rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
|
|
410
441
|
}
|
|
411
442
|
*result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
|
|
412
443
|
|
|
@@ -421,17 +452,37 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
|
421
452
|
}
|
|
422
453
|
}
|
|
423
454
|
|
|
424
|
-
static
|
|
455
|
+
static const size_t MAX_STACK_BUFFER_SIZE = 128;
|
|
456
|
+
static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int symbolize)
|
|
425
457
|
{
|
|
426
|
-
|
|
458
|
+
VALUE result = Qnil;
|
|
459
|
+
size_t bufferSize = stringEnd - string;
|
|
460
|
+
char *p = string, *pe = string, *unescape, *bufferStart, *buffer;
|
|
427
461
|
int unescape_len;
|
|
428
462
|
char buf[4];
|
|
429
463
|
|
|
464
|
+
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
|
|
465
|
+
# ifdef HAVE_RB_ENC_INTERNED_STR
|
|
466
|
+
bufferStart = buffer = ALLOC_N(char, bufferSize ? bufferSize : 1);
|
|
467
|
+
# else
|
|
468
|
+
bufferStart = buffer = ALLOC_N(char, bufferSize);
|
|
469
|
+
# endif
|
|
470
|
+
} else {
|
|
471
|
+
# ifdef HAVE_RB_ENC_INTERNED_STR
|
|
472
|
+
bufferStart = buffer = ALLOCA_N(char, bufferSize ? bufferSize : 1);
|
|
473
|
+
# else
|
|
474
|
+
bufferStart = buffer = ALLOCA_N(char, bufferSize);
|
|
475
|
+
# endif
|
|
476
|
+
}
|
|
477
|
+
|
|
430
478
|
while (pe < stringEnd) {
|
|
431
479
|
if (*pe == '\\') {
|
|
432
480
|
unescape = (char *) "?";
|
|
433
481
|
unescape_len = 1;
|
|
434
|
-
if (pe > p)
|
|
482
|
+
if (pe > p) {
|
|
483
|
+
MEMCPY(buffer, p, char, pe - p);
|
|
484
|
+
buffer += pe - p;
|
|
485
|
+
}
|
|
435
486
|
switch (*++pe) {
|
|
436
487
|
case 'n':
|
|
437
488
|
unescape = (char *) "\n";
|
|
@@ -456,13 +507,27 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
|
|
|
456
507
|
break;
|
|
457
508
|
case 'u':
|
|
458
509
|
if (pe > stringEnd - 4) {
|
|
459
|
-
|
|
510
|
+
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
|
|
511
|
+
free(bufferStart);
|
|
512
|
+
}
|
|
513
|
+
rb_enc_raise(
|
|
514
|
+
EXC_ENCODING eParserError,
|
|
515
|
+
"%u: incomplete unicode character escape sequence at '%s'", __LINE__, p
|
|
516
|
+
);
|
|
460
517
|
} else {
|
|
461
518
|
UTF32 ch = unescape_unicode((unsigned char *) ++pe);
|
|
462
519
|
pe += 3;
|
|
463
520
|
if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
|
|
464
521
|
pe++;
|
|
465
|
-
if (pe > stringEnd - 6)
|
|
522
|
+
if (pe > stringEnd - 6) {
|
|
523
|
+
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
|
|
524
|
+
free(bufferStart);
|
|
525
|
+
}
|
|
526
|
+
rb_enc_raise(
|
|
527
|
+
EXC_ENCODING eParserError,
|
|
528
|
+
"%u: incomplete surrogate pair at '%s'", __LINE__, p
|
|
529
|
+
);
|
|
530
|
+
}
|
|
466
531
|
if (pe[0] == '\\' && pe[1] == 'u') {
|
|
467
532
|
UTF32 sur = unescape_unicode((unsigned char *) pe + 2);
|
|
468
533
|
ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16)
|
|
@@ -481,13 +546,55 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
|
|
|
481
546
|
p = pe;
|
|
482
547
|
continue;
|
|
483
548
|
}
|
|
484
|
-
|
|
549
|
+
MEMCPY(buffer, unescape, char, unescape_len);
|
|
550
|
+
buffer += unescape_len;
|
|
485
551
|
p = ++pe;
|
|
486
552
|
} else {
|
|
487
553
|
pe++;
|
|
488
554
|
}
|
|
489
555
|
}
|
|
490
|
-
|
|
556
|
+
|
|
557
|
+
if (pe > p) {
|
|
558
|
+
MEMCPY(buffer, p, char, pe - p);
|
|
559
|
+
buffer += pe - p;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
# ifdef HAVE_RB_ENC_INTERNED_STR
|
|
563
|
+
if (intern) {
|
|
564
|
+
result = rb_enc_interned_str(bufferStart, (long)(buffer - bufferStart), rb_utf8_encoding());
|
|
565
|
+
} else {
|
|
566
|
+
result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
|
|
567
|
+
}
|
|
568
|
+
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
|
|
569
|
+
free(bufferStart);
|
|
570
|
+
}
|
|
571
|
+
# else
|
|
572
|
+
result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
|
|
573
|
+
|
|
574
|
+
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
|
|
575
|
+
free(bufferStart);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
if (intern) {
|
|
579
|
+
# if STR_UMINUS_DEDUPE_FROZEN
|
|
580
|
+
// Starting from MRI 2.8 it is preferable to freeze the string
|
|
581
|
+
// before deduplication so that it can be interned directly
|
|
582
|
+
// otherwise it would be duplicated first which is wasteful.
|
|
583
|
+
result = rb_funcall(rb_str_freeze(result), i_uminus, 0);
|
|
584
|
+
# elif STR_UMINUS_DEDUPE
|
|
585
|
+
// MRI 2.5 and older do not deduplicate strings that are already
|
|
586
|
+
// frozen.
|
|
587
|
+
result = rb_funcall(result, i_uminus, 0);
|
|
588
|
+
# else
|
|
589
|
+
result = rb_str_freeze(result);
|
|
590
|
+
# endif
|
|
591
|
+
}
|
|
592
|
+
# endif
|
|
593
|
+
|
|
594
|
+
if (symbolize) {
|
|
595
|
+
result = rb_str_intern(result);
|
|
596
|
+
}
|
|
597
|
+
|
|
491
598
|
return result;
|
|
492
599
|
}
|
|
493
600
|
|
|
@@ -498,12 +605,11 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
|
|
|
498
605
|
write data;
|
|
499
606
|
|
|
500
607
|
action parse_string {
|
|
501
|
-
*result = json_string_unescape(
|
|
608
|
+
*result = json_string_unescape(json->memo + 1, p, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names);
|
|
502
609
|
if (NIL_P(*result)) {
|
|
503
610
|
fhold;
|
|
504
611
|
fbreak;
|
|
505
612
|
} else {
|
|
506
|
-
FORCE_UTF8(*result);
|
|
507
613
|
fexec p + 1;
|
|
508
614
|
}
|
|
509
615
|
}
|
|
@@ -530,7 +636,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
|
530
636
|
int cs = EVIL;
|
|
531
637
|
VALUE match_string;
|
|
532
638
|
|
|
533
|
-
*result = rb_str_buf_new(0);
|
|
534
639
|
%% write init;
|
|
535
640
|
json->memo = p;
|
|
536
641
|
%% write exec;
|
|
@@ -546,9 +651,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
|
546
651
|
}
|
|
547
652
|
}
|
|
548
653
|
|
|
549
|
-
if (json->symbolize_names && json->parsing_name) {
|
|
550
|
-
*result = rb_str_intern(*result);
|
|
551
|
-
}
|
|
552
654
|
if (cs >= JSON_string_first_final) {
|
|
553
655
|
return p + 1;
|
|
554
656
|
} else {
|
|
@@ -570,41 +672,16 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
|
570
672
|
|
|
571
673
|
static VALUE convert_encoding(VALUE source)
|
|
572
674
|
{
|
|
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
675
|
#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);
|
|
676
|
+
rb_encoding *enc = rb_enc_get(source);
|
|
677
|
+
if (enc == rb_ascii8bit_encoding()) {
|
|
678
|
+
if (OBJ_FROZEN(source)) {
|
|
679
|
+
source = rb_str_dup(source);
|
|
607
680
|
}
|
|
681
|
+
FORCE_UTF8(source);
|
|
682
|
+
} else {
|
|
683
|
+
source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding());
|
|
684
|
+
}
|
|
608
685
|
#endif
|
|
609
686
|
return source;
|
|
610
687
|
}
|
|
@@ -627,8 +704,9 @@ static VALUE convert_encoding(VALUE source)
|
|
|
627
704
|
* defiance of RFC 4627 to be parsed by the Parser. This option defaults to
|
|
628
705
|
* false.
|
|
629
706
|
* * *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.
|
|
707
|
+
* (keys) in a JSON object. Otherwise strings are returned, which is
|
|
708
|
+
* also the default. It's not possible to use this option in
|
|
709
|
+
* conjunction with the *create_additions* option.
|
|
632
710
|
* * *create_additions*: If set to false, the Parser doesn't create
|
|
633
711
|
* additions even if a matching class and create_id was found. This option
|
|
634
712
|
* defaults to false.
|
|
@@ -679,12 +757,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
679
757
|
} else {
|
|
680
758
|
json->symbolize_names = 0;
|
|
681
759
|
}
|
|
682
|
-
tmp = ID2SYM(
|
|
760
|
+
tmp = ID2SYM(i_freeze);
|
|
683
761
|
if (option_given_p(opts, tmp)) {
|
|
684
|
-
|
|
685
|
-
json->quirks_mode = RTEST(quirks_mode) ? 1 : 0;
|
|
762
|
+
json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
|
|
686
763
|
} else {
|
|
687
|
-
json->
|
|
764
|
+
json->freeze = 0;
|
|
688
765
|
}
|
|
689
766
|
tmp = ID2SYM(i_create_additions);
|
|
690
767
|
if (option_given_p(opts, tmp)) {
|
|
@@ -692,6 +769,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
692
769
|
} else {
|
|
693
770
|
json->create_additions = 0;
|
|
694
771
|
}
|
|
772
|
+
if (json->symbolize_names && json->create_additions) {
|
|
773
|
+
rb_raise(rb_eArgError,
|
|
774
|
+
"options :symbolize_names and :create_additions cannot be "
|
|
775
|
+
" used in conjunction");
|
|
776
|
+
}
|
|
695
777
|
tmp = ID2SYM(i_create_id);
|
|
696
778
|
if (option_given_p(opts, tmp)) {
|
|
697
779
|
json->create_id = rb_hash_aref(opts, tmp);
|
|
@@ -710,6 +792,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
710
792
|
} else {
|
|
711
793
|
json->array_class = Qnil;
|
|
712
794
|
}
|
|
795
|
+
tmp = ID2SYM(i_decimal_class);
|
|
796
|
+
if (option_given_p(opts, tmp)) {
|
|
797
|
+
json->decimal_class = rb_hash_aref(opts, tmp);
|
|
798
|
+
} else {
|
|
799
|
+
json->decimal_class = Qnil;
|
|
800
|
+
}
|
|
713
801
|
tmp = ID2SYM(i_match_string);
|
|
714
802
|
if (option_given_p(opts, tmp)) {
|
|
715
803
|
VALUE match_string = rb_hash_aref(opts, tmp);
|
|
@@ -723,16 +811,14 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
723
811
|
} else {
|
|
724
812
|
json->max_nesting = 100;
|
|
725
813
|
json->allow_nan = 0;
|
|
726
|
-
json->create_additions =
|
|
814
|
+
json->create_additions = 0;
|
|
727
815
|
json->create_id = rb_funcall(mJSON, i_create_id, 0);
|
|
728
816
|
json->object_class = Qnil;
|
|
729
817
|
json->array_class = Qnil;
|
|
818
|
+
json->decimal_class = Qnil;
|
|
730
819
|
}
|
|
820
|
+
source = convert_encoding(StringValue(source));
|
|
731
821
|
StringValue(source);
|
|
732
|
-
if (!json->quirks_mode) {
|
|
733
|
-
source = convert_encoding(source);
|
|
734
|
-
}
|
|
735
|
-
json->current_nesting = 0;
|
|
736
822
|
json->len = RSTRING_LEN(source);
|
|
737
823
|
json->source = RSTRING_PTR(source);;
|
|
738
824
|
json->Vsource = source;
|
|
@@ -746,56 +832,8 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
746
832
|
|
|
747
833
|
include JSON_common;
|
|
748
834
|
|
|
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
835
|
action parse_value {
|
|
798
|
-
char *np = JSON_parse_value(json, fpc, pe, &result);
|
|
836
|
+
char *np = JSON_parse_value(json, fpc, pe, &result, 0);
|
|
799
837
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
|
800
838
|
}
|
|
801
839
|
|
|
@@ -804,40 +842,30 @@ static VALUE cParser_parse_strict(VALUE self)
|
|
|
804
842
|
) ignore*;
|
|
805
843
|
}%%
|
|
806
844
|
|
|
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
845
|
/*
|
|
828
846
|
* call-seq: parse()
|
|
829
847
|
*
|
|
830
848
|
* Parses the current JSON text _source_ and returns the complete data
|
|
831
849
|
* structure as a result.
|
|
850
|
+
* It raises JSON::ParseError if fail to parse.
|
|
832
851
|
*/
|
|
833
852
|
static VALUE cParser_parse(VALUE self)
|
|
834
853
|
{
|
|
854
|
+
char *p, *pe;
|
|
855
|
+
int cs = EVIL;
|
|
856
|
+
VALUE result = Qnil;
|
|
835
857
|
GET_PARSER;
|
|
836
858
|
|
|
837
|
-
|
|
838
|
-
|
|
859
|
+
%% write init;
|
|
860
|
+
p = json->source;
|
|
861
|
+
pe = p + json->len;
|
|
862
|
+
%% write exec;
|
|
863
|
+
|
|
864
|
+
if (cs >= JSON_first_final && p == pe) {
|
|
865
|
+
return result;
|
|
839
866
|
} else {
|
|
840
|
-
|
|
867
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
|
868
|
+
return Qnil;
|
|
841
869
|
}
|
|
842
870
|
}
|
|
843
871
|
|
|
@@ -848,6 +876,7 @@ static void JSON_mark(void *ptr)
|
|
|
848
876
|
rb_gc_mark_maybe(json->create_id);
|
|
849
877
|
rb_gc_mark_maybe(json->object_class);
|
|
850
878
|
rb_gc_mark_maybe(json->array_class);
|
|
879
|
+
rb_gc_mark_maybe(json->decimal_class);
|
|
851
880
|
rb_gc_mark_maybe(json->match_string);
|
|
852
881
|
}
|
|
853
882
|
|
|
@@ -895,35 +924,34 @@ static VALUE cParser_source(VALUE self)
|
|
|
895
924
|
return rb_str_dup(json->Vsource);
|
|
896
925
|
}
|
|
897
926
|
|
|
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
927
|
void Init_parser(void)
|
|
911
928
|
{
|
|
929
|
+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
|
930
|
+
rb_ext_ractor_safe(true);
|
|
931
|
+
#endif
|
|
932
|
+
|
|
933
|
+
#undef rb_intern
|
|
912
934
|
rb_require("json/common");
|
|
913
935
|
mJSON = rb_define_module("JSON");
|
|
914
936
|
mExt = rb_define_module_under(mJSON, "Ext");
|
|
915
937
|
cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
|
|
916
938
|
eParserError = rb_path2class("JSON::ParserError");
|
|
917
939
|
eNestingError = rb_path2class("JSON::NestingError");
|
|
940
|
+
rb_gc_register_mark_object(eParserError);
|
|
941
|
+
rb_gc_register_mark_object(eNestingError);
|
|
918
942
|
rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
|
|
919
943
|
rb_define_method(cParser, "initialize", cParser_initialize, -1);
|
|
920
944
|
rb_define_method(cParser, "parse", cParser_parse, 0);
|
|
921
945
|
rb_define_method(cParser, "source", cParser_source, 0);
|
|
922
|
-
rb_define_method(cParser, "quirks_mode?", cParser_quirks_mode_p, 0);
|
|
923
946
|
|
|
924
947
|
CNaN = rb_const_get(mJSON, rb_intern("NaN"));
|
|
948
|
+
rb_gc_register_mark_object(CNaN);
|
|
949
|
+
|
|
925
950
|
CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
|
|
951
|
+
rb_gc_register_mark_object(CInfinity);
|
|
952
|
+
|
|
926
953
|
CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
|
|
954
|
+
rb_gc_register_mark_object(CMinusInfinity);
|
|
927
955
|
|
|
928
956
|
i_json_creatable_p = rb_intern("json_creatable?");
|
|
929
957
|
i_json_create = rb_intern("json_create");
|
|
@@ -933,9 +961,9 @@ void Init_parser(void)
|
|
|
933
961
|
i_max_nesting = rb_intern("max_nesting");
|
|
934
962
|
i_allow_nan = rb_intern("allow_nan");
|
|
935
963
|
i_symbolize_names = rb_intern("symbolize_names");
|
|
936
|
-
i_quirks_mode = rb_intern("quirks_mode");
|
|
937
964
|
i_object_class = rb_intern("object_class");
|
|
938
965
|
i_array_class = rb_intern("array_class");
|
|
966
|
+
i_decimal_class = rb_intern("decimal_class");
|
|
939
967
|
i_match = rb_intern("match");
|
|
940
968
|
i_match_string = rb_intern("match_string");
|
|
941
969
|
i_key_p = rb_intern("key?");
|
|
@@ -943,15 +971,10 @@ void Init_parser(void)
|
|
|
943
971
|
i_aset = rb_intern("[]=");
|
|
944
972
|
i_aref = rb_intern("[]");
|
|
945
973
|
i_leftshift = rb_intern("<<");
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
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
|
|
974
|
+
i_new = rb_intern("new");
|
|
975
|
+
i_try_convert = rb_intern("try_convert");
|
|
976
|
+
i_freeze = rb_intern("freeze");
|
|
977
|
+
i_uminus = rb_intern("-@");
|
|
955
978
|
}
|
|
956
979
|
|
|
957
980
|
/*
|
data/ext/json/extconf.rb
CHANGED
data/json.gemspec
CHANGED
|
Binary file
|