json 1.8.2 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.gitignore +2 -0
- data/.travis.yml +11 -9
- data/{CHANGES → CHANGES.md} +220 -89
- data/Gemfile +10 -6
- data/{README-json-jruby.markdown → README-json-jruby.md} +0 -0
- data/{README.rdoc → README.md} +204 -137
- data/Rakefile +35 -113
- data/VERSION +1 -1
- data/ext/json/ext/fbuffer/fbuffer.h +0 -3
- data/ext/json/ext/generator/generator.c +215 -110
- data/ext/json/ext/generator/generator.h +18 -5
- data/ext/json/ext/parser/extconf.rb +3 -0
- data/ext/json/ext/parser/parser.c +422 -508
- data/ext/json/ext/parser/parser.h +15 -8
- data/ext/json/ext/parser/parser.rl +151 -200
- data/ext/json/extconf.rb +0 -1
- data/java/src/json/ext/ByteListTranscoder.java +1 -2
- data/java/src/json/ext/Generator.java +44 -22
- data/java/src/json/ext/GeneratorMethods.java +1 -2
- data/java/src/json/ext/GeneratorService.java +1 -2
- data/java/src/json/ext/GeneratorState.java +3 -56
- data/java/src/json/ext/OptionsReader.java +2 -3
- data/java/src/json/ext/Parser.java +132 -415
- data/java/src/json/ext/Parser.rl +48 -124
- data/java/src/json/ext/ParserService.java +1 -2
- data/java/src/json/ext/RuntimeInfo.java +1 -6
- data/java/src/json/ext/StringDecoder.java +1 -2
- data/java/src/json/ext/StringEncoder.java +5 -0
- data/java/src/json/ext/Utils.java +1 -2
- data/json-java.gemspec +16 -2
- data/json.gemspec +0 -0
- data/json_pure.gemspec +22 -29
- data/lib/json.rb +379 -29
- data/lib/json/add/bigdecimal.rb +3 -2
- data/lib/json/add/complex.rb +4 -3
- data/lib/json/add/core.rb +1 -0
- data/lib/json/add/date.rb +1 -1
- data/lib/json/add/date_time.rb +1 -1
- data/lib/json/add/exception.rb +1 -1
- data/lib/json/add/ostruct.rb +3 -3
- data/lib/json/add/range.rb +1 -1
- data/lib/json/add/rational.rb +3 -2
- data/lib/json/add/regexp.rb +3 -3
- data/lib/json/add/set.rb +29 -0
- data/lib/json/add/struct.rb +1 -1
- data/lib/json/add/symbol.rb +1 -1
- data/lib/json/add/time.rb +1 -1
- data/lib/json/common.rb +335 -128
- data/lib/json/ext.rb +0 -6
- data/lib/json/generic_object.rb +5 -4
- data/lib/json/pure.rb +2 -8
- data/lib/json/pure/generator.rb +64 -127
- data/lib/json/pure/parser.rb +42 -82
- data/lib/json/version.rb +2 -1
- data/references/rfc7159.txt +899 -0
- data/tests/fixtures/obsolete_fail1.json +1 -0
- data/tests/{test_json_addition.rb → json_addition_test.rb} +32 -25
- data/tests/json_common_interface_test.rb +126 -0
- data/tests/json_encoding_test.rb +107 -0
- data/tests/json_ext_parser_test.rb +15 -0
- data/tests/{test_json_fixtures.rb → json_fixtures_test.rb} +10 -8
- data/tests/{test_json_generate.rb → json_generator_test.rb} +123 -39
- data/tests/{test_json_generic_object.rb → json_generic_object_test.rb} +15 -8
- data/tests/json_parser_test.rb +472 -0
- data/tests/json_string_matching_test.rb +38 -0
- data/tests/{setup_variant.rb → test_helper.rb} +6 -0
- data/tools/diff.sh +18 -0
- data/tools/fuzz.rb +1 -9
- metadata +46 -53
- data/COPYING +0 -58
- data/COPYING-json-jruby +0 -57
- data/GPL +0 -340
- data/TODO +0 -1
- data/data/example.json +0 -1
- data/data/index.html +0 -38
- data/data/prototype.js +0 -4184
- data/tests/fixtures/fail1.json +0 -1
- data/tests/test_json.rb +0 -553
- data/tests/test_json_encoding.rb +0 -65
- data/tests/test_json_string_matching.rb +0 -39
- data/tests/test_json_unicode.rb +0 -72
@@ -34,13 +34,12 @@ typedef struct JSON_ParserStruct {
|
|
34
34
|
char *memo;
|
35
35
|
VALUE create_id;
|
36
36
|
int max_nesting;
|
37
|
-
int current_nesting;
|
38
37
|
int allow_nan;
|
39
38
|
int parsing_name;
|
40
39
|
int symbolize_names;
|
41
|
-
int quirks_mode;
|
42
40
|
VALUE object_class;
|
43
41
|
VALUE array_class;
|
42
|
+
VALUE decimal_class;
|
44
43
|
int create_additions;
|
45
44
|
VALUE match_string;
|
46
45
|
FBuffer *fbuffer;
|
@@ -58,26 +57,34 @@ 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);
|
69
68
|
static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self);
|
70
69
|
static VALUE cParser_parse(VALUE self);
|
71
|
-
static JSON_Parser *JSON_allocate(void);
|
72
70
|
static void JSON_mark(void *json);
|
73
71
|
static void JSON_free(void *json);
|
74
72
|
static VALUE cJSON_parser_s_allocate(VALUE klass);
|
75
73
|
static VALUE cParser_source(VALUE self);
|
76
|
-
#
|
74
|
+
#ifndef ZALLOC
|
75
|
+
#define ZALLOC(type) ((type *)ruby_zalloc(sizeof(type)))
|
76
|
+
static inline void *ruby_zalloc(size_t n)
|
77
|
+
{
|
78
|
+
void *p = ruby_xmalloc(n);
|
79
|
+
memset(p, 0, n);
|
80
|
+
return p;
|
81
|
+
}
|
82
|
+
#endif
|
83
|
+
#ifdef TypedData_Make_Struct
|
77
84
|
static const rb_data_type_t JSON_Parser_type;
|
78
85
|
#define NEW_TYPEDDATA_WRAPPER 1
|
79
86
|
#else
|
80
|
-
#define
|
87
|
+
#define TypedData_Make_Struct(klass, type, ignore, json) Data_Make_Struct(klass, type, NULL, JSON_free, json)
|
81
88
|
#define TypedData_Get_Struct(self, JSON_Parser, ignore, json) Data_Get_Struct(self, JSON_Parser, json)
|
82
89
|
#endif
|
83
90
|
|
@@ -1,9 +1,31 @@
|
|
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
|
-
static const char digit_values[256] = {
|
28
|
+
static const signed char digit_values[256] = {
|
7
29
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
8
30
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
9
31
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1,
|
@@ -22,20 +44,20 @@ static const char digit_values[256] = {
|
|
22
44
|
|
23
45
|
static UTF32 unescape_unicode(const unsigned char *p)
|
24
46
|
{
|
25
|
-
char b;
|
47
|
+
signed char b;
|
26
48
|
UTF32 result = 0;
|
27
49
|
b = digit_values[p[0]];
|
28
50
|
if (b < 0) return UNI_REPLACEMENT_CHAR;
|
29
|
-
result = (result << 4) | b;
|
51
|
+
result = (result << 4) | (unsigned char)b;
|
30
52
|
b = digit_values[p[1]];
|
31
|
-
result = (result << 4) | b;
|
32
53
|
if (b < 0) return UNI_REPLACEMENT_CHAR;
|
54
|
+
result = (result << 4) | (unsigned char)b;
|
33
55
|
b = digit_values[p[2]];
|
34
|
-
result = (result << 4) | b;
|
35
56
|
if (b < 0) return UNI_REPLACEMENT_CHAR;
|
57
|
+
result = (result << 4) | (unsigned char)b;
|
36
58
|
b = digit_values[p[3]];
|
37
|
-
result = (result << 4) | b;
|
38
59
|
if (b < 0) return UNI_REPLACEMENT_CHAR;
|
60
|
+
result = (result << 4) | (unsigned char)b;
|
39
61
|
return result;
|
40
62
|
}
|
41
63
|
|
@@ -65,21 +87,15 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
|
|
65
87
|
return len;
|
66
88
|
}
|
67
89
|
|
68
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
69
|
-
static VALUE CEncoding_ASCII_8BIT, CEncoding_UTF_8, CEncoding_UTF_16BE,
|
70
|
-
CEncoding_UTF_16LE, CEncoding_UTF_32BE, CEncoding_UTF_32LE;
|
71
|
-
static ID i_encoding, i_encode;
|
72
|
-
#else
|
73
|
-
static ID i_iconv;
|
74
|
-
#endif
|
75
|
-
|
76
90
|
static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
|
77
91
|
static VALUE CNaN, CInfinity, CMinusInfinity;
|
92
|
+
static VALUE cBigDecimal = Qundef;
|
78
93
|
|
79
94
|
static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
80
|
-
i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
|
81
|
-
i_object_class, i_array_class,
|
82
|
-
i_match_string, i_aset, i_aref,
|
95
|
+
i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
|
96
|
+
i_object_class, i_array_class, i_decimal_class, i_key_p,
|
97
|
+
i_deep_const_get, i_match, i_match_string, i_aset, i_aref,
|
98
|
+
i_leftshift, i_new, i_BigDecimal;
|
83
99
|
|
84
100
|
%%{
|
85
101
|
machine JSON_common;
|
@@ -117,11 +133,12 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
|
117
133
|
|
118
134
|
action parse_value {
|
119
135
|
VALUE v = Qnil;
|
120
|
-
char *np = JSON_parse_value(json, fpc, pe, &v);
|
136
|
+
char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
|
121
137
|
if (np == NULL) {
|
122
138
|
fhold; fbreak;
|
123
139
|
} else {
|
124
140
|
if (NIL_P(json->object_class)) {
|
141
|
+
OBJ_FREEZE(last_name);
|
125
142
|
rb_hash_aset(*result, last_name, v);
|
126
143
|
} else {
|
127
144
|
rb_funcall(*result, i_aset, 2, last_name, v);
|
@@ -150,14 +167,14 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
|
150
167
|
) @exit;
|
151
168
|
}%%
|
152
169
|
|
153
|
-
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
170
|
+
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
|
154
171
|
{
|
155
172
|
int cs = EVIL;
|
156
173
|
VALUE last_name = Qnil;
|
157
174
|
VALUE object_class = json->object_class;
|
158
175
|
|
159
|
-
if (json->max_nesting &&
|
160
|
-
rb_raise(eNestingError, "nesting of %d is too deep",
|
176
|
+
if (json->max_nesting && current_nesting > json->max_nesting) {
|
177
|
+
rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
|
161
178
|
}
|
162
179
|
|
163
180
|
*result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class);
|
@@ -206,14 +223,14 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
206
223
|
if (json->allow_nan) {
|
207
224
|
*result = CNaN;
|
208
225
|
} else {
|
209
|
-
|
226
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2);
|
210
227
|
}
|
211
228
|
}
|
212
229
|
action parse_infinity {
|
213
230
|
if (json->allow_nan) {
|
214
231
|
*result = CInfinity;
|
215
232
|
} else {
|
216
|
-
|
233
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8);
|
217
234
|
}
|
218
235
|
}
|
219
236
|
action parse_string {
|
@@ -223,13 +240,13 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
223
240
|
|
224
241
|
action parse_number {
|
225
242
|
char *np;
|
226
|
-
if(pe > fpc +
|
243
|
+
if(pe > fpc + 8 && !strncmp(MinusInfinity, fpc, 9)) {
|
227
244
|
if (json->allow_nan) {
|
228
245
|
*result = CMinusInfinity;
|
229
246
|
fexec p + 10;
|
230
247
|
fhold; fbreak;
|
231
248
|
} else {
|
232
|
-
|
249
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
233
250
|
}
|
234
251
|
}
|
235
252
|
np = JSON_parse_float(json, fpc, pe, result);
|
@@ -241,23 +258,19 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
241
258
|
|
242
259
|
action parse_array {
|
243
260
|
char *np;
|
244
|
-
json
|
245
|
-
np = JSON_parse_array(json, fpc, pe, result);
|
246
|
-
json->current_nesting--;
|
261
|
+
np = JSON_parse_array(json, fpc, pe, result, current_nesting + 1);
|
247
262
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
248
263
|
}
|
249
264
|
|
250
265
|
action parse_object {
|
251
266
|
char *np;
|
252
|
-
json
|
253
|
-
np = JSON_parse_object(json, fpc, pe, result);
|
254
|
-
json->current_nesting--;
|
267
|
+
np = JSON_parse_object(json, fpc, pe, result, current_nesting + 1);
|
255
268
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
256
269
|
}
|
257
270
|
|
258
271
|
action exit { fhold; fbreak; }
|
259
272
|
|
260
|
-
main := (
|
273
|
+
main := ignore* (
|
261
274
|
Vnull @parse_null |
|
262
275
|
Vfalse @parse_false |
|
263
276
|
Vtrue @parse_true |
|
@@ -267,10 +280,10 @@ main := (
|
|
267
280
|
begin_string >parse_string |
|
268
281
|
begin_array >parse_array |
|
269
282
|
begin_object >parse_object
|
270
|
-
) %*exit;
|
283
|
+
) ignore* %*exit;
|
271
284
|
}%%
|
272
285
|
|
273
|
-
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
286
|
+
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
|
274
287
|
{
|
275
288
|
int cs = EVIL;
|
276
289
|
|
@@ -328,6 +341,19 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
|
|
328
341
|
) (^[0-9Ee.\-]? @exit );
|
329
342
|
}%%
|
330
343
|
|
344
|
+
static int is_bigdecimal_class(VALUE obj)
|
345
|
+
{
|
346
|
+
if (cBigDecimal == Qundef) {
|
347
|
+
if (rb_const_defined(rb_cObject, i_BigDecimal)) {
|
348
|
+
cBigDecimal = rb_const_get_at(rb_cObject, i_BigDecimal);
|
349
|
+
}
|
350
|
+
else {
|
351
|
+
return 0;
|
352
|
+
}
|
353
|
+
}
|
354
|
+
return obj == cBigDecimal;
|
355
|
+
}
|
356
|
+
|
331
357
|
static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
332
358
|
{
|
333
359
|
int cs = EVIL;
|
@@ -341,7 +367,17 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
341
367
|
fbuffer_clear(json->fbuffer);
|
342
368
|
fbuffer_append(json->fbuffer, json->memo, len);
|
343
369
|
fbuffer_append_char(json->fbuffer, '\0');
|
344
|
-
|
370
|
+
if (NIL_P(json->decimal_class)) {
|
371
|
+
*result = rb_float_new(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
|
372
|
+
} else {
|
373
|
+
VALUE text;
|
374
|
+
text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
|
375
|
+
if (is_bigdecimal_class(json->decimal_class)) {
|
376
|
+
*result = rb_funcall(Qnil, i_BigDecimal, 1, text);
|
377
|
+
} else {
|
378
|
+
*result = rb_funcall(json->decimal_class, i_new, 1, text);
|
379
|
+
}
|
380
|
+
}
|
345
381
|
return p + 1;
|
346
382
|
} else {
|
347
383
|
return NULL;
|
@@ -357,7 +393,7 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
357
393
|
|
358
394
|
action parse_value {
|
359
395
|
VALUE v = Qnil;
|
360
|
-
char *np = JSON_parse_value(json, fpc, pe, &v);
|
396
|
+
char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
|
361
397
|
if (np == NULL) {
|
362
398
|
fhold; fbreak;
|
363
399
|
} else {
|
@@ -380,13 +416,13 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
380
416
|
end_array @exit;
|
381
417
|
}%%
|
382
418
|
|
383
|
-
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result)
|
419
|
+
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
|
384
420
|
{
|
385
421
|
int cs = EVIL;
|
386
422
|
VALUE array_class = json->array_class;
|
387
423
|
|
388
|
-
if (json->max_nesting &&
|
389
|
-
rb_raise(eNestingError, "nesting of %d is too deep",
|
424
|
+
if (json->max_nesting && current_nesting > json->max_nesting) {
|
425
|
+
rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
|
390
426
|
}
|
391
427
|
*result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
|
392
428
|
|
@@ -396,7 +432,7 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
396
432
|
if(cs >= JSON_array_first_final) {
|
397
433
|
return p + 1;
|
398
434
|
} else {
|
399
|
-
|
435
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
400
436
|
return NULL;
|
401
437
|
}
|
402
438
|
}
|
@@ -436,13 +472,21 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
|
|
436
472
|
break;
|
437
473
|
case 'u':
|
438
474
|
if (pe > stringEnd - 4) {
|
439
|
-
|
475
|
+
rb_enc_raise(
|
476
|
+
EXC_ENCODING eParserError,
|
477
|
+
"%u: incomplete unicode character escape sequence at '%s'", __LINE__, p
|
478
|
+
);
|
440
479
|
} else {
|
441
480
|
UTF32 ch = unescape_unicode((unsigned char *) ++pe);
|
442
481
|
pe += 3;
|
443
482
|
if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
|
444
483
|
pe++;
|
445
|
-
if (pe > stringEnd - 6)
|
484
|
+
if (pe > stringEnd - 6) {
|
485
|
+
rb_enc_raise(
|
486
|
+
EXC_ENCODING eParserError,
|
487
|
+
"%u: incomplete surrogate pair at '%s'", __LINE__, p
|
488
|
+
);
|
489
|
+
}
|
446
490
|
if (pe[0] == '\\' && pe[1] == 'u') {
|
447
491
|
UTF32 sur = unescape_unicode((unsigned char *) pe + 2);
|
448
492
|
ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16)
|
@@ -528,6 +572,8 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
528
572
|
|
529
573
|
if (json->symbolize_names && json->parsing_name) {
|
530
574
|
*result = rb_str_intern(*result);
|
575
|
+
} else if (RB_TYPE_P(*result, T_STRING)) {
|
576
|
+
rb_str_resize(*result, RSTRING_LEN(*result));
|
531
577
|
}
|
532
578
|
if (cs >= JSON_string_first_final) {
|
533
579
|
return p + 1;
|
@@ -550,41 +596,16 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
550
596
|
|
551
597
|
static VALUE convert_encoding(VALUE source)
|
552
598
|
{
|
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
599
|
#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);
|
600
|
+
rb_encoding *enc = rb_enc_get(source);
|
601
|
+
if (enc == rb_ascii8bit_encoding()) {
|
602
|
+
if (OBJ_FROZEN(source)) {
|
603
|
+
source = rb_str_dup(source);
|
587
604
|
}
|
605
|
+
FORCE_UTF8(source);
|
606
|
+
} else {
|
607
|
+
source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding());
|
608
|
+
}
|
588
609
|
#endif
|
589
610
|
return source;
|
590
611
|
}
|
@@ -607,8 +628,9 @@ static VALUE convert_encoding(VALUE source)
|
|
607
628
|
* defiance of RFC 4627 to be parsed by the Parser. This option defaults to
|
608
629
|
* false.
|
609
630
|
* * *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.
|
631
|
+
* (keys) in a JSON object. Otherwise strings are returned, which is
|
632
|
+
* also the default. It's not possible to use this option in
|
633
|
+
* conjunction with the *create_additions* option.
|
612
634
|
* * *create_additions*: If set to false, the Parser doesn't create
|
613
635
|
* additions even if a matching class and create_id was found. This option
|
614
636
|
* defaults to false.
|
@@ -623,12 +645,18 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
623
645
|
if (json->Vsource) {
|
624
646
|
rb_raise(rb_eTypeError, "already initialized instance");
|
625
647
|
}
|
648
|
+
#ifdef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
|
649
|
+
rb_scan_args(argc, argv, "1:", &source, &opts);
|
650
|
+
#else
|
626
651
|
rb_scan_args(argc, argv, "11", &source, &opts);
|
652
|
+
#endif
|
627
653
|
if (!NIL_P(opts)) {
|
654
|
+
#ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
|
628
655
|
opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
|
629
656
|
if (NIL_P(opts)) {
|
630
657
|
rb_raise(rb_eArgError, "opts needs to be like a hash");
|
631
658
|
} else {
|
659
|
+
#endif
|
632
660
|
VALUE tmp = ID2SYM(i_max_nesting);
|
633
661
|
if (option_given_p(opts, tmp)) {
|
634
662
|
VALUE max_nesting = rb_hash_aref(opts, tmp);
|
@@ -653,19 +681,17 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
653
681
|
} else {
|
654
682
|
json->symbolize_names = 0;
|
655
683
|
}
|
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
684
|
tmp = ID2SYM(i_create_additions);
|
664
685
|
if (option_given_p(opts, tmp)) {
|
665
686
|
json->create_additions = RTEST(rb_hash_aref(opts, tmp));
|
666
687
|
} else {
|
667
688
|
json->create_additions = 0;
|
668
689
|
}
|
690
|
+
if (json->symbolize_names && json->create_additions) {
|
691
|
+
rb_raise(rb_eArgError,
|
692
|
+
"options :symbolize_names and :create_additions cannot be "
|
693
|
+
" used in conjunction");
|
694
|
+
}
|
669
695
|
tmp = ID2SYM(i_create_id);
|
670
696
|
if (option_given_p(opts, tmp)) {
|
671
697
|
json->create_id = rb_hash_aref(opts, tmp);
|
@@ -684,6 +710,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
684
710
|
} else {
|
685
711
|
json->array_class = Qnil;
|
686
712
|
}
|
713
|
+
tmp = ID2SYM(i_decimal_class);
|
714
|
+
if (option_given_p(opts, tmp)) {
|
715
|
+
json->decimal_class = rb_hash_aref(opts, tmp);
|
716
|
+
} else {
|
717
|
+
json->decimal_class = Qnil;
|
718
|
+
}
|
687
719
|
tmp = ID2SYM(i_match_string);
|
688
720
|
if (option_given_p(opts, tmp)) {
|
689
721
|
VALUE match_string = rb_hash_aref(opts, tmp);
|
@@ -691,20 +723,19 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
691
723
|
} else {
|
692
724
|
json->match_string = Qnil;
|
693
725
|
}
|
726
|
+
#ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
|
694
727
|
}
|
728
|
+
#endif
|
695
729
|
} else {
|
696
730
|
json->max_nesting = 100;
|
697
731
|
json->allow_nan = 0;
|
698
|
-
json->create_additions =
|
732
|
+
json->create_additions = 0;
|
699
733
|
json->create_id = rb_funcall(mJSON, i_create_id, 0);
|
700
734
|
json->object_class = Qnil;
|
701
735
|
json->array_class = Qnil;
|
736
|
+
json->decimal_class = Qnil;
|
702
737
|
}
|
703
|
-
source =
|
704
|
-
if (!json->quirks_mode) {
|
705
|
-
source = convert_encoding(StringValue(source));
|
706
|
-
}
|
707
|
-
json->current_nesting = 0;
|
738
|
+
source = convert_encoding(StringValue(source));
|
708
739
|
StringValue(source);
|
709
740
|
json->len = RSTRING_LEN(source);
|
710
741
|
json->source = RSTRING_PTR(source);;
|
@@ -719,56 +750,8 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
719
750
|
|
720
751
|
include JSON_common;
|
721
752
|
|
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
753
|
action parse_value {
|
771
|
-
char *np = JSON_parse_value(json, fpc, pe, &result);
|
754
|
+
char *np = JSON_parse_value(json, fpc, pe, &result, 0);
|
772
755
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
773
756
|
}
|
774
757
|
|
@@ -777,26 +760,6 @@ static VALUE cParser_parse_strict(VALUE self)
|
|
777
760
|
) ignore*;
|
778
761
|
}%%
|
779
762
|
|
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
763
|
/*
|
801
764
|
* call-seq: parse()
|
802
765
|
*
|
@@ -805,24 +768,24 @@ static VALUE cParser_parse_quirks_mode(VALUE self)
|
|
805
768
|
*/
|
806
769
|
static VALUE cParser_parse(VALUE self)
|
807
770
|
{
|
771
|
+
char *p, *pe;
|
772
|
+
int cs = EVIL;
|
773
|
+
VALUE result = Qnil;
|
808
774
|
GET_PARSER;
|
809
775
|
|
810
|
-
|
811
|
-
|
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;
|
812
783
|
} else {
|
813
|
-
|
784
|
+
rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
|
785
|
+
return Qnil;
|
814
786
|
}
|
815
787
|
}
|
816
788
|
|
817
|
-
|
818
|
-
static JSON_Parser *JSON_allocate(void)
|
819
|
-
{
|
820
|
-
JSON_Parser *json = ALLOC(JSON_Parser);
|
821
|
-
MEMZERO(json, JSON_Parser, 1);
|
822
|
-
json->fbuffer = fbuffer_alloc(0);
|
823
|
-
return json;
|
824
|
-
}
|
825
|
-
|
826
789
|
static void JSON_mark(void *ptr)
|
827
790
|
{
|
828
791
|
JSON_Parser *json = ptr;
|
@@ -830,6 +793,7 @@ static void JSON_mark(void *ptr)
|
|
830
793
|
rb_gc_mark_maybe(json->create_id);
|
831
794
|
rb_gc_mark_maybe(json->object_class);
|
832
795
|
rb_gc_mark_maybe(json->array_class);
|
796
|
+
rb_gc_mark_maybe(json->decimal_class);
|
833
797
|
rb_gc_mark_maybe(json->match_string);
|
834
798
|
}
|
835
799
|
|
@@ -859,8 +823,10 @@ static const rb_data_type_t JSON_Parser_type = {
|
|
859
823
|
|
860
824
|
static VALUE cJSON_parser_s_allocate(VALUE klass)
|
861
825
|
{
|
862
|
-
JSON_Parser *json
|
863
|
-
|
826
|
+
JSON_Parser *json;
|
827
|
+
VALUE obj = TypedData_Make_Struct(klass, JSON_Parser, &JSON_Parser_type, json);
|
828
|
+
json->fbuffer = fbuffer_alloc(0);
|
829
|
+
return obj;
|
864
830
|
}
|
865
831
|
|
866
832
|
/*
|
@@ -875,35 +841,30 @@ static VALUE cParser_source(VALUE self)
|
|
875
841
|
return rb_str_dup(json->Vsource);
|
876
842
|
}
|
877
843
|
|
878
|
-
|
879
|
-
* call-seq: quirks_mode?()
|
880
|
-
*
|
881
|
-
* Returns a true, if this parser is in quirks_mode, false otherwise.
|
882
|
-
*/
|
883
|
-
static VALUE cParser_quirks_mode_p(VALUE self)
|
884
|
-
{
|
885
|
-
GET_PARSER;
|
886
|
-
return json->quirks_mode ? Qtrue : Qfalse;
|
887
|
-
}
|
888
|
-
|
889
|
-
|
890
|
-
void Init_parser()
|
844
|
+
void Init_parser(void)
|
891
845
|
{
|
846
|
+
#undef rb_intern
|
892
847
|
rb_require("json/common");
|
893
848
|
mJSON = rb_define_module("JSON");
|
894
849
|
mExt = rb_define_module_under(mJSON, "Ext");
|
895
850
|
cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
|
896
851
|
eParserError = rb_path2class("JSON::ParserError");
|
897
852
|
eNestingError = rb_path2class("JSON::NestingError");
|
853
|
+
rb_gc_register_mark_object(eParserError);
|
854
|
+
rb_gc_register_mark_object(eNestingError);
|
898
855
|
rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
|
899
856
|
rb_define_method(cParser, "initialize", cParser_initialize, -1);
|
900
857
|
rb_define_method(cParser, "parse", cParser_parse, 0);
|
901
858
|
rb_define_method(cParser, "source", cParser_source, 0);
|
902
|
-
rb_define_method(cParser, "quirks_mode?", cParser_quirks_mode_p, 0);
|
903
859
|
|
904
860
|
CNaN = rb_const_get(mJSON, rb_intern("NaN"));
|
861
|
+
rb_gc_register_mark_object(CNaN);
|
862
|
+
|
905
863
|
CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
|
864
|
+
rb_gc_register_mark_object(CInfinity);
|
865
|
+
|
906
866
|
CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
|
867
|
+
rb_gc_register_mark_object(CMinusInfinity);
|
907
868
|
|
908
869
|
i_json_creatable_p = rb_intern("json_creatable?");
|
909
870
|
i_json_create = rb_intern("json_create");
|
@@ -913,9 +874,9 @@ void Init_parser()
|
|
913
874
|
i_max_nesting = rb_intern("max_nesting");
|
914
875
|
i_allow_nan = rb_intern("allow_nan");
|
915
876
|
i_symbolize_names = rb_intern("symbolize_names");
|
916
|
-
i_quirks_mode = rb_intern("quirks_mode");
|
917
877
|
i_object_class = rb_intern("object_class");
|
918
878
|
i_array_class = rb_intern("array_class");
|
879
|
+
i_decimal_class = rb_intern("decimal_class");
|
919
880
|
i_match = rb_intern("match");
|
920
881
|
i_match_string = rb_intern("match_string");
|
921
882
|
i_key_p = rb_intern("key?");
|
@@ -923,18 +884,8 @@ void Init_parser()
|
|
923
884
|
i_aset = rb_intern("[]=");
|
924
885
|
i_aref = rb_intern("[]");
|
925
886
|
i_leftshift = rb_intern("<<");
|
926
|
-
|
927
|
-
|
928
|
-
CEncoding_UTF_16BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16be"));
|
929
|
-
CEncoding_UTF_16LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16le"));
|
930
|
-
CEncoding_UTF_32BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32be"));
|
931
|
-
CEncoding_UTF_32LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32le"));
|
932
|
-
CEncoding_ASCII_8BIT = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("ascii-8bit"));
|
933
|
-
i_encoding = rb_intern("encoding");
|
934
|
-
i_encode = rb_intern("encode");
|
935
|
-
#else
|
936
|
-
i_iconv = rb_intern("iconv");
|
937
|
-
#endif
|
887
|
+
i_new = rb_intern("new");
|
888
|
+
i_BigDecimal = rb_intern("BigDecimal");
|
938
889
|
}
|
939
890
|
|
940
891
|
/*
|