json 1.8.6 → 2.7.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} +292 -96
- data/LICENSE +56 -0
- data/README.md +185 -114
- data/ext/json/ext/fbuffer/fbuffer.h +0 -3
- data/ext/json/ext/generator/generator.c +328 -117
- data/ext/json/ext/generator/generator.h +8 -8
- data/ext/json/ext/parser/extconf.rb +29 -0
- data/ext/json/ext/parser/parser.c +540 -569
- data/ext/json/ext/parser/parser.h +10 -6
- data/ext/json/ext/parser/parser.rl +269 -261
- data/ext/json/extconf.rb +1 -1
- data/json.gemspec +0 -0
- data/lib/json/add/bigdecimal.rb +40 -10
- data/lib/json/add/complex.rb +32 -9
- data/lib/json/add/core.rb +1 -0
- data/lib/json/add/date.rb +27 -7
- data/lib/json/add/date_time.rb +26 -9
- data/lib/json/add/exception.rb +25 -7
- data/lib/json/add/ostruct.rb +32 -9
- data/lib/json/add/range.rb +33 -8
- data/lib/json/add/rational.rb +30 -8
- data/lib/json/add/regexp.rb +28 -10
- data/lib/json/add/set.rb +48 -0
- data/lib/json/add/struct.rb +29 -7
- data/lib/json/add/symbol.rb +28 -5
- data/lib/json/add/time.rb +27 -6
- data/lib/json/common.rb +402 -188
- data/lib/json/ext.rb +0 -6
- data/lib/json/generic_object.rb +11 -6
- data/lib/json/pure/generator.rb +120 -137
- data/lib/json/pure/parser.rb +64 -86
- data/lib/json/pure.rb +2 -8
- data/lib/json/version.rb +2 -1
- data/lib/json.rb +559 -29
- metadata +18 -129
- 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/VERSION +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);
|
@@ -226,14 +222,14 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
226
222
|
if (json->allow_nan) {
|
227
223
|
*result = CNaN;
|
228
224
|
} else {
|
229
|
-
rb_enc_raise(EXC_ENCODING eParserError, "
|
225
|
+
rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 2);
|
230
226
|
}
|
231
227
|
}
|
232
228
|
action parse_infinity {
|
233
229
|
if (json->allow_nan) {
|
234
230
|
*result = CInfinity;
|
235
231
|
} else {
|
236
|
-
rb_enc_raise(EXC_ENCODING eParserError, "
|
232
|
+
rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 7);
|
237
233
|
}
|
238
234
|
}
|
239
235
|
action parse_string {
|
@@ -243,13 +239,13 @@ 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;
|
250
246
|
fhold; fbreak;
|
251
247
|
} else {
|
252
|
-
rb_enc_raise(EXC_ENCODING eParserError, "
|
248
|
+
rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p);
|
253
249
|
}
|
254
250
|
}
|
255
251
|
np = JSON_parse_float(json, fpc, pe, result);
|
@@ -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
|
|
@@ -416,22 +447,42 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
416
447
|
if(cs >= JSON_array_first_final) {
|
417
448
|
return p + 1;
|
418
449
|
} else {
|
419
|
-
rb_enc_raise(EXC_ENCODING eParserError, "
|
450
|
+
rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p);
|
420
451
|
return NULL;
|
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
|
+
ruby_xfree(bufferStart);
|
512
|
+
}
|
513
|
+
rb_enc_raise(
|
514
|
+
EXC_ENCODING eParserError,
|
515
|
+
"incomplete unicode character escape sequence at '%s'", 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
|
+
ruby_xfree(bufferStart);
|
525
|
+
}
|
526
|
+
rb_enc_raise(
|
527
|
+
EXC_ENCODING eParserError,
|
528
|
+
"incomplete surrogate pair at '%s'", 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
|
+
ruby_xfree(bufferStart);
|
570
|
+
}
|
571
|
+
# else
|
572
|
+
result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
|
573
|
+
|
574
|
+
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
|
575
|
+
ruby_xfree(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
|
}
|
@@ -614,8 +691,6 @@ static VALUE convert_encoding(VALUE source)
|
|
614
691
|
*
|
615
692
|
* Creates a new JSON::Ext::Parser instance for the string _source_.
|
616
693
|
*
|
617
|
-
* Creates a new JSON::Ext::Parser instance for the string _source_.
|
618
|
-
*
|
619
694
|
* It will be configured by the _opts_ hash. _opts_ can have the following
|
620
695
|
* keys:
|
621
696
|
*
|
@@ -627,8 +702,9 @@ static VALUE convert_encoding(VALUE source)
|
|
627
702
|
* defiance of RFC 4627 to be parsed by the Parser. This option defaults to
|
628
703
|
* false.
|
629
704
|
* * *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.
|
705
|
+
* (keys) in a JSON object. Otherwise strings are returned, which is
|
706
|
+
* also the default. It's not possible to use this option in
|
707
|
+
* conjunction with the *create_additions* option.
|
632
708
|
* * *create_additions*: If set to false, the Parser doesn't create
|
633
709
|
* additions even if a matching class and create_id was found. This option
|
634
710
|
* defaults to false.
|
@@ -643,96 +719,91 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
643
719
|
if (json->Vsource) {
|
644
720
|
rb_raise(rb_eTypeError, "already initialized instance");
|
645
721
|
}
|
646
|
-
#ifdef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
|
647
722
|
rb_scan_args(argc, argv, "1:", &source, &opts);
|
648
|
-
#else
|
649
|
-
rb_scan_args(argc, argv, "11", &source, &opts);
|
650
|
-
#endif
|
651
723
|
if (!NIL_P(opts)) {
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
724
|
+
VALUE tmp = ID2SYM(i_max_nesting);
|
725
|
+
if (option_given_p(opts, tmp)) {
|
726
|
+
VALUE max_nesting = rb_hash_aref(opts, tmp);
|
727
|
+
if (RTEST(max_nesting)) {
|
728
|
+
Check_Type(max_nesting, T_FIXNUM);
|
729
|
+
json->max_nesting = FIX2INT(max_nesting);
|
730
|
+
} else {
|
731
|
+
json->max_nesting = 0;
|
732
|
+
}
|
733
|
+
} else {
|
734
|
+
json->max_nesting = 100;
|
735
|
+
}
|
736
|
+
tmp = ID2SYM(i_allow_nan);
|
737
|
+
if (option_given_p(opts, tmp)) {
|
738
|
+
json->allow_nan = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
|
739
|
+
} else {
|
740
|
+
json->allow_nan = 0;
|
741
|
+
}
|
742
|
+
tmp = ID2SYM(i_symbolize_names);
|
743
|
+
if (option_given_p(opts, tmp)) {
|
744
|
+
json->symbolize_names = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
|
745
|
+
} else {
|
746
|
+
json->symbolize_names = 0;
|
747
|
+
}
|
748
|
+
tmp = ID2SYM(i_freeze);
|
749
|
+
if (option_given_p(opts, tmp)) {
|
750
|
+
json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
|
751
|
+
} else {
|
752
|
+
json->freeze = 0;
|
753
|
+
}
|
754
|
+
tmp = ID2SYM(i_create_additions);
|
755
|
+
if (option_given_p(opts, tmp)) {
|
756
|
+
json->create_additions = RTEST(rb_hash_aref(opts, tmp));
|
757
|
+
} else {
|
758
|
+
json->create_additions = 0;
|
759
|
+
}
|
760
|
+
if (json->symbolize_names && json->create_additions) {
|
761
|
+
rb_raise(rb_eArgError,
|
762
|
+
"options :symbolize_names and :create_additions cannot be "
|
763
|
+
" used in conjunction");
|
764
|
+
}
|
765
|
+
tmp = ID2SYM(i_create_id);
|
766
|
+
if (option_given_p(opts, tmp)) {
|
767
|
+
json->create_id = rb_hash_aref(opts, tmp);
|
768
|
+
} else {
|
769
|
+
json->create_id = rb_funcall(mJSON, i_create_id, 0);
|
770
|
+
}
|
771
|
+
tmp = ID2SYM(i_object_class);
|
772
|
+
if (option_given_p(opts, tmp)) {
|
773
|
+
json->object_class = rb_hash_aref(opts, tmp);
|
774
|
+
} else {
|
775
|
+
json->object_class = Qnil;
|
776
|
+
}
|
777
|
+
tmp = ID2SYM(i_array_class);
|
778
|
+
if (option_given_p(opts, tmp)) {
|
779
|
+
json->array_class = rb_hash_aref(opts, tmp);
|
780
|
+
} else {
|
781
|
+
json->array_class = Qnil;
|
782
|
+
}
|
783
|
+
tmp = ID2SYM(i_decimal_class);
|
784
|
+
if (option_given_p(opts, tmp)) {
|
785
|
+
json->decimal_class = rb_hash_aref(opts, tmp);
|
786
|
+
} else {
|
787
|
+
json->decimal_class = Qnil;
|
788
|
+
}
|
789
|
+
tmp = ID2SYM(i_match_string);
|
790
|
+
if (option_given_p(opts, tmp)) {
|
791
|
+
VALUE match_string = rb_hash_aref(opts, tmp);
|
792
|
+
json->match_string = RTEST(match_string) ? match_string : Qnil;
|
793
|
+
} else {
|
794
|
+
json->match_string = Qnil;
|
795
|
+
}
|
723
796
|
} else {
|
724
797
|
json->max_nesting = 100;
|
725
798
|
json->allow_nan = 0;
|
726
|
-
json->create_additions =
|
727
|
-
json->create_id =
|
799
|
+
json->create_additions = 0;
|
800
|
+
json->create_id = Qnil;
|
728
801
|
json->object_class = Qnil;
|
729
802
|
json->array_class = Qnil;
|
803
|
+
json->decimal_class = Qnil;
|
730
804
|
}
|
805
|
+
source = convert_encoding(StringValue(source));
|
731
806
|
StringValue(source);
|
732
|
-
if (!json->quirks_mode) {
|
733
|
-
source = convert_encoding(source);
|
734
|
-
}
|
735
|
-
json->current_nesting = 0;
|
736
807
|
json->len = RSTRING_LEN(source);
|
737
808
|
json->source = RSTRING_PTR(source);;
|
738
809
|
json->Vsource = source;
|
@@ -746,56 +817,8 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
746
817
|
|
747
818
|
include JSON_common;
|
748
819
|
|
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
820
|
action parse_value {
|
798
|
-
char *np = JSON_parse_value(json, fpc, pe, &result);
|
821
|
+
char *np = JSON_parse_value(json, fpc, pe, &result, 0);
|
799
822
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
800
823
|
}
|
801
824
|
|
@@ -804,40 +827,30 @@ static VALUE cParser_parse_strict(VALUE self)
|
|
804
827
|
) ignore*;
|
805
828
|
}%%
|
806
829
|
|
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
830
|
/*
|
828
831
|
* call-seq: parse()
|
829
832
|
*
|
830
833
|
* Parses the current JSON text _source_ and returns the complete data
|
831
834
|
* structure as a result.
|
835
|
+
* It raises JSON::ParserError if fail to parse.
|
832
836
|
*/
|
833
837
|
static VALUE cParser_parse(VALUE self)
|
834
838
|
{
|
839
|
+
char *p, *pe;
|
840
|
+
int cs = EVIL;
|
841
|
+
VALUE result = Qnil;
|
835
842
|
GET_PARSER;
|
836
843
|
|
837
|
-
|
838
|
-
|
844
|
+
%% write init;
|
845
|
+
p = json->source;
|
846
|
+
pe = p + json->len;
|
847
|
+
%% write exec;
|
848
|
+
|
849
|
+
if (cs >= JSON_first_final && p == pe) {
|
850
|
+
return result;
|
839
851
|
} else {
|
840
|
-
|
852
|
+
rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p);
|
853
|
+
return Qnil;
|
841
854
|
}
|
842
855
|
}
|
843
856
|
|
@@ -848,6 +861,7 @@ static void JSON_mark(void *ptr)
|
|
848
861
|
rb_gc_mark_maybe(json->create_id);
|
849
862
|
rb_gc_mark_maybe(json->object_class);
|
850
863
|
rb_gc_mark_maybe(json->array_class);
|
864
|
+
rb_gc_mark_maybe(json->decimal_class);
|
851
865
|
rb_gc_mark_maybe(json->match_string);
|
852
866
|
}
|
853
867
|
|
@@ -895,35 +909,34 @@ static VALUE cParser_source(VALUE self)
|
|
895
909
|
return rb_str_dup(json->Vsource);
|
896
910
|
}
|
897
911
|
|
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
912
|
void Init_parser(void)
|
911
913
|
{
|
914
|
+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
915
|
+
rb_ext_ractor_safe(true);
|
916
|
+
#endif
|
917
|
+
|
918
|
+
#undef rb_intern
|
912
919
|
rb_require("json/common");
|
913
920
|
mJSON = rb_define_module("JSON");
|
914
921
|
mExt = rb_define_module_under(mJSON, "Ext");
|
915
922
|
cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
|
916
923
|
eParserError = rb_path2class("JSON::ParserError");
|
917
924
|
eNestingError = rb_path2class("JSON::NestingError");
|
925
|
+
rb_gc_register_mark_object(eParserError);
|
926
|
+
rb_gc_register_mark_object(eNestingError);
|
918
927
|
rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
|
919
928
|
rb_define_method(cParser, "initialize", cParser_initialize, -1);
|
920
929
|
rb_define_method(cParser, "parse", cParser_parse, 0);
|
921
930
|
rb_define_method(cParser, "source", cParser_source, 0);
|
922
|
-
rb_define_method(cParser, "quirks_mode?", cParser_quirks_mode_p, 0);
|
923
931
|
|
924
932
|
CNaN = rb_const_get(mJSON, rb_intern("NaN"));
|
933
|
+
rb_gc_register_mark_object(CNaN);
|
934
|
+
|
925
935
|
CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
|
936
|
+
rb_gc_register_mark_object(CInfinity);
|
937
|
+
|
926
938
|
CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
|
939
|
+
rb_gc_register_mark_object(CMinusInfinity);
|
927
940
|
|
928
941
|
i_json_creatable_p = rb_intern("json_creatable?");
|
929
942
|
i_json_create = rb_intern("json_create");
|
@@ -933,9 +946,9 @@ void Init_parser(void)
|
|
933
946
|
i_max_nesting = rb_intern("max_nesting");
|
934
947
|
i_allow_nan = rb_intern("allow_nan");
|
935
948
|
i_symbolize_names = rb_intern("symbolize_names");
|
936
|
-
i_quirks_mode = rb_intern("quirks_mode");
|
937
949
|
i_object_class = rb_intern("object_class");
|
938
950
|
i_array_class = rb_intern("array_class");
|
951
|
+
i_decimal_class = rb_intern("decimal_class");
|
939
952
|
i_match = rb_intern("match");
|
940
953
|
i_match_string = rb_intern("match_string");
|
941
954
|
i_key_p = rb_intern("key?");
|
@@ -943,15 +956,10 @@ void Init_parser(void)
|
|
943
956
|
i_aset = rb_intern("[]=");
|
944
957
|
i_aref = rb_intern("[]");
|
945
958
|
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
|
959
|
+
i_new = rb_intern("new");
|
960
|
+
i_try_convert = rb_intern("try_convert");
|
961
|
+
i_freeze = rb_intern("freeze");
|
962
|
+
i_uminus = rb_intern("-@");
|
955
963
|
}
|
956
964
|
|
957
965
|
/*
|