json 2.7.2 → 2.7.5
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 +4 -4
- data/BSDL +22 -0
- data/CHANGES.md +50 -17
- data/LEGAL +60 -0
- data/README.md +13 -165
- data/ext/json/ext/fbuffer/fbuffer.h +21 -62
- data/ext/json/ext/generator/extconf.rb +8 -2
- data/ext/json/ext/generator/generator.c +497 -668
- data/ext/json/ext/generator/generator.h +16 -75
- data/ext/json/ext/parser/extconf.rb +3 -1
- data/ext/json/ext/parser/parser.c +279 -253
- data/ext/json/ext/parser/parser.h +4 -40
- data/ext/json/ext/parser/parser.rl +208 -182
- data/json.gemspec +42 -49
- data/lib/json/add/bigdecimal.rb +1 -1
- data/lib/json/add/complex.rb +1 -1
- data/lib/json/add/core.rb +1 -1
- 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 +1 -1
- data/lib/json/add/range.rb +1 -1
- data/lib/json/add/rational.rb +1 -1
- data/lib/json/add/regexp.rb +1 -1
- data/lib/json/add/struct.rb +1 -1
- data/lib/json/add/symbol.rb +1 -2
- data/lib/json/add/time.rb +3 -10
- data/lib/json/common.rb +79 -43
- data/lib/json/ext/generator/state.rb +135 -0
- data/lib/json/ext.rb +15 -5
- data/lib/json/generic_object.rb +1 -1
- data/lib/json/pure/generator.rb +96 -29
- data/lib/json/pure/parser.rb +27 -33
- data/lib/json/pure.rb +1 -0
- data/lib/json/version.rb +3 -7
- data/lib/json.rb +1 -1
- metadata +17 -15
- data/ext/json/ext/generator/depend +0 -1
- data/ext/json/ext/parser/depend +0 -1
- data/ext/json/extconf.rb +0 -3
- /data/{LICENSE → COPYING} +0 -0
@@ -3,33 +3,11 @@
|
|
3
3
|
|
4
4
|
#include "ruby.h"
|
5
5
|
|
6
|
-
#ifndef HAVE_RUBY_RE_H
|
7
|
-
#include "re.h"
|
8
|
-
#endif
|
9
|
-
|
10
|
-
#ifdef HAVE_RUBY_ST_H
|
11
|
-
#include "ruby/st.h"
|
12
|
-
#else
|
13
|
-
#include "st.h"
|
14
|
-
#endif
|
15
|
-
|
16
6
|
#ifndef MAYBE_UNUSED
|
17
7
|
# define MAYBE_UNUSED(x) x
|
18
8
|
#endif
|
19
9
|
|
20
|
-
#define option_given_p(opts, key)
|
21
|
-
|
22
|
-
/* unicode */
|
23
|
-
|
24
|
-
typedef unsigned long UTF32; /* at least 32 bits */
|
25
|
-
typedef unsigned short UTF16; /* at least 16 bits */
|
26
|
-
typedef unsigned char UTF8; /* typically 8 bits */
|
27
|
-
|
28
|
-
#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
|
29
|
-
#define UNI_SUR_HIGH_START (UTF32)0xD800
|
30
|
-
#define UNI_SUR_HIGH_END (UTF32)0xDBFF
|
31
|
-
#define UNI_SUR_LOW_START (UTF32)0xDC00
|
32
|
-
#define UNI_SUR_LOW_END (UTF32)0xDFFF
|
10
|
+
#define option_given_p(opts, key) (rb_hash_lookup2(opts, key, Qundef) != Qundef)
|
33
11
|
|
34
12
|
typedef struct JSON_ParserStruct {
|
35
13
|
VALUE Vsource;
|
@@ -60,8 +38,8 @@ typedef struct JSON_ParserStruct {
|
|
60
38
|
#define MinusInfinity "-Infinity"
|
61
39
|
#define EVIL 0x666
|
62
40
|
|
63
|
-
static
|
64
|
-
static int convert_UTF32_to_UTF8(char *buf,
|
41
|
+
static uint32_t unescape_unicode(const unsigned char *p);
|
42
|
+
static int convert_UTF32_to_UTF8(char *buf, uint32_t ch);
|
65
43
|
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
|
66
44
|
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
|
67
45
|
static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result);
|
@@ -76,21 +54,7 @@ static void JSON_mark(void *json);
|
|
76
54
|
static void JSON_free(void *json);
|
77
55
|
static VALUE cJSON_parser_s_allocate(VALUE klass);
|
78
56
|
static VALUE cParser_source(VALUE self);
|
79
|
-
|
80
|
-
#define ZALLOC(type) ((type *)ruby_zalloc(sizeof(type)))
|
81
|
-
static inline void *ruby_zalloc(size_t n)
|
82
|
-
{
|
83
|
-
void *p = ruby_xmalloc(n);
|
84
|
-
memset(p, 0, n);
|
85
|
-
return p;
|
86
|
-
}
|
87
|
-
#endif
|
88
|
-
#ifdef TypedData_Make_Struct
|
57
|
+
|
89
58
|
static const rb_data_type_t JSON_Parser_type;
|
90
|
-
#define NEW_TYPEDDATA_WRAPPER 1
|
91
|
-
#else
|
92
|
-
#define TypedData_Make_Struct(klass, type, ignore, json) Data_Make_Struct(klass, type, NULL, JSON_free, json)
|
93
|
-
#define TypedData_Get_Struct(self, JSON_Parser, ignore, json) Data_Get_Struct(self, JSON_Parser, json)
|
94
|
-
#endif
|
95
59
|
|
96
60
|
#endif
|
@@ -1,28 +1,6 @@
|
|
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
|
-
|
26
4
|
/* unicode */
|
27
5
|
|
28
6
|
static const signed char digit_values[256] = {
|
@@ -42,26 +20,28 @@ static const signed char digit_values[256] = {
|
|
42
20
|
-1, -1, -1, -1, -1, -1, -1
|
43
21
|
};
|
44
22
|
|
45
|
-
static
|
23
|
+
static uint32_t unescape_unicode(const unsigned char *p)
|
46
24
|
{
|
25
|
+
const uint32_t replacement_char = 0xFFFD;
|
26
|
+
|
47
27
|
signed char b;
|
48
|
-
|
28
|
+
uint32_t result = 0;
|
49
29
|
b = digit_values[p[0]];
|
50
|
-
if (b < 0) return
|
30
|
+
if (b < 0) return replacement_char;
|
51
31
|
result = (result << 4) | (unsigned char)b;
|
52
32
|
b = digit_values[p[1]];
|
53
|
-
if (b < 0) return
|
33
|
+
if (b < 0) return replacement_char;
|
54
34
|
result = (result << 4) | (unsigned char)b;
|
55
35
|
b = digit_values[p[2]];
|
56
|
-
if (b < 0) return
|
36
|
+
if (b < 0) return replacement_char;
|
57
37
|
result = (result << 4) | (unsigned char)b;
|
58
38
|
b = digit_values[p[3]];
|
59
|
-
if (b < 0) return
|
39
|
+
if (b < 0) return replacement_char;
|
60
40
|
result = (result << 4) | (unsigned char)b;
|
61
41
|
return result;
|
62
42
|
}
|
63
43
|
|
64
|
-
static int convert_UTF32_to_UTF8(char *buf,
|
44
|
+
static int convert_UTF32_to_UTF8(char *buf, uint32_t ch)
|
65
45
|
{
|
66
46
|
int len = 1;
|
67
47
|
if (ch <= 0x7F) {
|
@@ -87,15 +67,39 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
|
|
87
67
|
return len;
|
88
68
|
}
|
89
69
|
|
90
|
-
|
70
|
+
#define PARSE_ERROR_FRAGMENT_LEN 32
|
71
|
+
#ifdef RBIMPL_ATTR_NORETURN
|
72
|
+
RBIMPL_ATTR_NORETURN()
|
73
|
+
#endif
|
74
|
+
static void raise_parse_error(const char *format, const char *start)
|
75
|
+
{
|
76
|
+
char buffer[PARSE_ERROR_FRAGMENT_LEN + 1];
|
77
|
+
|
78
|
+
size_t len = strnlen(start, PARSE_ERROR_FRAGMENT_LEN);
|
79
|
+
const char *ptr = start;
|
80
|
+
|
81
|
+
if (len == PARSE_ERROR_FRAGMENT_LEN) {
|
82
|
+
MEMCPY(buffer, start, char, PARSE_ERROR_FRAGMENT_LEN);
|
83
|
+
buffer[PARSE_ERROR_FRAGMENT_LEN] = '\0';
|
84
|
+
ptr = buffer;
|
85
|
+
}
|
86
|
+
|
87
|
+
rb_enc_raise(rb_utf8_encoding(), rb_path2class("JSON::ParserError"), format, ptr);
|
88
|
+
}
|
89
|
+
|
90
|
+
static VALUE mJSON, mExt, cParser, eNestingError;
|
91
91
|
static VALUE CNaN, CInfinity, CMinusInfinity;
|
92
92
|
|
93
93
|
static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
94
94
|
i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
|
95
|
-
i_object_class, i_array_class, i_decimal_class,
|
95
|
+
i_object_class, i_array_class, i_decimal_class,
|
96
96
|
i_deep_const_get, i_match, i_match_string, i_aset, i_aref,
|
97
97
|
i_leftshift, i_new, i_try_convert, i_freeze, i_uminus;
|
98
98
|
|
99
|
+
static int binary_encindex;
|
100
|
+
static int utf8_encindex;
|
101
|
+
|
102
|
+
|
99
103
|
%%{
|
100
104
|
machine JSON_common;
|
101
105
|
|
@@ -222,14 +226,14 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
222
226
|
if (json->allow_nan) {
|
223
227
|
*result = CNaN;
|
224
228
|
} else {
|
225
|
-
|
229
|
+
raise_parse_error("unexpected token at '%s'", p - 2);
|
226
230
|
}
|
227
231
|
}
|
228
232
|
action parse_infinity {
|
229
233
|
if (json->allow_nan) {
|
230
234
|
*result = CInfinity;
|
231
235
|
} else {
|
232
|
-
|
236
|
+
raise_parse_error("unexpected token at '%s'", p - 7);
|
233
237
|
}
|
234
238
|
}
|
235
239
|
action parse_string {
|
@@ -245,7 +249,7 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
245
249
|
fexec p + 10;
|
246
250
|
fhold; fbreak;
|
247
251
|
} else {
|
248
|
-
|
252
|
+
raise_parse_error("unexpected token at '%s'", p);
|
249
253
|
}
|
250
254
|
}
|
251
255
|
np = JSON_parse_float(json, fpc, pe, result);
|
@@ -355,29 +359,31 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
355
359
|
if (cs >= JSON_float_first_final) {
|
356
360
|
VALUE mod = Qnil;
|
357
361
|
ID method_id = 0;
|
358
|
-
if (
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
362
|
+
if (!NIL_P(json->decimal_class)) {
|
363
|
+
if (rb_respond_to(json->decimal_class, i_try_convert)) {
|
364
|
+
mod = json->decimal_class;
|
365
|
+
method_id = i_try_convert;
|
366
|
+
} else if (rb_respond_to(json->decimal_class, i_new)) {
|
367
|
+
mod = json->decimal_class;
|
368
|
+
method_id = i_new;
|
369
|
+
} else if (RB_TYPE_P(json->decimal_class, T_CLASS)) {
|
370
|
+
VALUE name = rb_class_name(json->decimal_class);
|
371
|
+
const char *name_cstr = RSTRING_PTR(name);
|
372
|
+
const char *last_colon = strrchr(name_cstr, ':');
|
373
|
+
if (last_colon) {
|
374
|
+
const char *mod_path_end = last_colon - 1;
|
375
|
+
VALUE mod_path = rb_str_substr(name, 0, mod_path_end - name_cstr);
|
376
|
+
mod = rb_path_to_class(mod_path);
|
377
|
+
|
378
|
+
const char *method_name_beg = last_colon + 1;
|
379
|
+
long before_len = method_name_beg - name_cstr;
|
380
|
+
long len = RSTRING_LEN(name) - before_len;
|
381
|
+
VALUE method_name = rb_str_substr(name, before_len, len);
|
382
|
+
method_id = SYM2ID(rb_str_intern(method_name));
|
383
|
+
} else {
|
384
|
+
mod = rb_mKernel;
|
385
|
+
method_id = SYM2ID(rb_str_intern(name));
|
386
|
+
}
|
381
387
|
}
|
382
388
|
}
|
383
389
|
|
@@ -447,7 +453,7 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
|
|
447
453
|
if(cs >= JSON_array_first_final) {
|
448
454
|
return p + 1;
|
449
455
|
} else {
|
450
|
-
|
456
|
+
raise_parse_error("unexpected token at '%s'", p);
|
451
457
|
return NULL;
|
452
458
|
}
|
453
459
|
}
|
@@ -510,26 +516,30 @@ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int
|
|
510
516
|
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
|
511
517
|
ruby_xfree(bufferStart);
|
512
518
|
}
|
513
|
-
|
514
|
-
EXC_ENCODING eParserError,
|
515
|
-
"incomplete unicode character escape sequence at '%s'", p
|
516
|
-
);
|
519
|
+
raise_parse_error("incomplete unicode character escape sequence at '%s'", p);
|
517
520
|
} else {
|
518
|
-
|
521
|
+
uint32_t ch = unescape_unicode((unsigned char *) ++pe);
|
519
522
|
pe += 3;
|
520
|
-
|
523
|
+
/* To handle values above U+FFFF, we take a sequence of
|
524
|
+
* \uXXXX escapes in the U+D800..U+DBFF then
|
525
|
+
* U+DC00..U+DFFF ranges, take the low 10 bits from each
|
526
|
+
* to make a 20-bit number, then add 0x10000 to get the
|
527
|
+
* final codepoint.
|
528
|
+
*
|
529
|
+
* See Unicode 15: 3.8 "Surrogates", 5.3 "Handling
|
530
|
+
* Surrogate Pairs in UTF-16", and 23.6 "Surrogates
|
531
|
+
* Area".
|
532
|
+
*/
|
533
|
+
if ((ch & 0xFC00) == 0xD800) {
|
521
534
|
pe++;
|
522
535
|
if (pe > stringEnd - 6) {
|
523
536
|
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
|
524
537
|
ruby_xfree(bufferStart);
|
525
538
|
}
|
526
|
-
|
527
|
-
EXC_ENCODING eParserError,
|
528
|
-
"incomplete surrogate pair at '%s'", p
|
529
|
-
);
|
539
|
+
raise_parse_error("incomplete surrogate pair at '%s'", p);
|
530
540
|
}
|
531
541
|
if (pe[0] == '\\' && pe[1] == 'u') {
|
532
|
-
|
542
|
+
uint32_t sur = unescape_unicode((unsigned char *) pe + 2);
|
533
543
|
ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16)
|
534
544
|
| (sur & 0x3FF));
|
535
545
|
pe += 5;
|
@@ -672,18 +682,20 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
|
|
672
682
|
|
673
683
|
static VALUE convert_encoding(VALUE source)
|
674
684
|
{
|
675
|
-
|
676
|
-
|
677
|
-
if (
|
678
|
-
if (OBJ_FROZEN(source)) {
|
679
|
-
source = rb_str_dup(source);
|
680
|
-
}
|
681
|
-
FORCE_UTF8(source);
|
682
|
-
} else {
|
683
|
-
source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding());
|
684
|
-
}
|
685
|
-
#endif
|
685
|
+
int encindex = RB_ENCODING_GET(source);
|
686
|
+
|
687
|
+
if (encindex == utf8_encindex) {
|
686
688
|
return source;
|
689
|
+
}
|
690
|
+
|
691
|
+
if (encindex == binary_encindex) {
|
692
|
+
// For historical reason, we silently reinterpret binary strings as UTF-8 if it would work.
|
693
|
+
// TODO: Deprecate in 2.8.0
|
694
|
+
// TODO: Remove in 3.0.0
|
695
|
+
return rb_enc_associate_index(rb_str_dup(source), utf8_encindex);
|
696
|
+
}
|
697
|
+
|
698
|
+
return rb_str_conv_enc(source, rb_enc_from_index(encindex), rb_utf8_encoding());
|
687
699
|
}
|
688
700
|
|
689
701
|
/*
|
@@ -708,8 +720,15 @@ static VALUE convert_encoding(VALUE source)
|
|
708
720
|
* * *create_additions*: If set to false, the Parser doesn't create
|
709
721
|
* additions even if a matching class and create_id was found. This option
|
710
722
|
* defaults to false.
|
711
|
-
* * *object_class*: Defaults to Hash
|
712
|
-
*
|
723
|
+
* * *object_class*: Defaults to Hash. If another type is provided, it will be used
|
724
|
+
* instead of Hash to represent JSON objects. The type must respond to
|
725
|
+
* +new+ without arguments, and return an object that respond to +[]=+.
|
726
|
+
* * *array_class*: Defaults to Array If another type is provided, it will be used
|
727
|
+
* instead of Hash to represent JSON arrays. The type must respond to
|
728
|
+
* +new+ without arguments, and return an object that respond to +<<+.
|
729
|
+
* * *decimal_class*: Specifies which class to use instead of the default
|
730
|
+
* (Float) when parsing decimal numbers. This class must accept a single
|
731
|
+
* string argument in its constructor.
|
713
732
|
*/
|
714
733
|
static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
715
734
|
{
|
@@ -719,80 +738,91 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
719
738
|
if (json->Vsource) {
|
720
739
|
rb_raise(rb_eTypeError, "already initialized instance");
|
721
740
|
}
|
722
|
-
|
741
|
+
|
742
|
+
rb_check_arity(argc, 1, 2);
|
743
|
+
source = argv[0];
|
744
|
+
opts = Qnil;
|
745
|
+
if (argc == 2) {
|
746
|
+
opts = argv[1];
|
747
|
+
Check_Type(argv[1], T_HASH);
|
748
|
+
if (RHASH_SIZE(argv[1]) > 0) {
|
749
|
+
opts = argv[1];
|
750
|
+
}
|
751
|
+
}
|
752
|
+
|
723
753
|
if (!NIL_P(opts)) {
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
754
|
+
VALUE tmp = ID2SYM(i_max_nesting);
|
755
|
+
if (option_given_p(opts, tmp)) {
|
756
|
+
VALUE max_nesting = rb_hash_aref(opts, tmp);
|
757
|
+
if (RTEST(max_nesting)) {
|
758
|
+
Check_Type(max_nesting, T_FIXNUM);
|
759
|
+
json->max_nesting = FIX2INT(max_nesting);
|
760
|
+
} else {
|
761
|
+
json->max_nesting = 0;
|
762
|
+
}
|
763
|
+
} else {
|
764
|
+
json->max_nesting = 100;
|
765
|
+
}
|
766
|
+
tmp = ID2SYM(i_allow_nan);
|
767
|
+
if (option_given_p(opts, tmp)) {
|
768
|
+
json->allow_nan = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
|
769
|
+
} else {
|
770
|
+
json->allow_nan = 0;
|
771
|
+
}
|
772
|
+
tmp = ID2SYM(i_symbolize_names);
|
773
|
+
if (option_given_p(opts, tmp)) {
|
774
|
+
json->symbolize_names = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
|
775
|
+
} else {
|
776
|
+
json->symbolize_names = 0;
|
777
|
+
}
|
778
|
+
tmp = ID2SYM(i_freeze);
|
779
|
+
if (option_given_p(opts, tmp)) {
|
780
|
+
json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
|
781
|
+
} else {
|
782
|
+
json->freeze = 0;
|
783
|
+
}
|
784
|
+
tmp = ID2SYM(i_create_additions);
|
785
|
+
if (option_given_p(opts, tmp)) {
|
786
|
+
json->create_additions = RTEST(rb_hash_aref(opts, tmp));
|
787
|
+
} else {
|
788
|
+
json->create_additions = 0;
|
789
|
+
}
|
790
|
+
if (json->symbolize_names && json->create_additions) {
|
791
|
+
rb_raise(rb_eArgError,
|
792
|
+
"options :symbolize_names and :create_additions cannot be "
|
793
|
+
" used in conjunction");
|
794
|
+
}
|
795
|
+
tmp = ID2SYM(i_create_id);
|
796
|
+
if (option_given_p(opts, tmp)) {
|
797
|
+
json->create_id = rb_hash_aref(opts, tmp);
|
798
|
+
} else {
|
799
|
+
json->create_id = rb_funcall(mJSON, i_create_id, 0);
|
800
|
+
}
|
801
|
+
tmp = ID2SYM(i_object_class);
|
802
|
+
if (option_given_p(opts, tmp)) {
|
803
|
+
json->object_class = rb_hash_aref(opts, tmp);
|
804
|
+
} else {
|
805
|
+
json->object_class = Qnil;
|
806
|
+
}
|
807
|
+
tmp = ID2SYM(i_array_class);
|
808
|
+
if (option_given_p(opts, tmp)) {
|
809
|
+
json->array_class = rb_hash_aref(opts, tmp);
|
810
|
+
} else {
|
811
|
+
json->array_class = Qnil;
|
812
|
+
}
|
813
|
+
tmp = ID2SYM(i_decimal_class);
|
814
|
+
if (option_given_p(opts, tmp)) {
|
815
|
+
json->decimal_class = rb_hash_aref(opts, tmp);
|
816
|
+
} else {
|
817
|
+
json->decimal_class = Qnil;
|
818
|
+
}
|
819
|
+
tmp = ID2SYM(i_match_string);
|
820
|
+
if (option_given_p(opts, tmp)) {
|
821
|
+
VALUE match_string = rb_hash_aref(opts, tmp);
|
822
|
+
json->match_string = RTEST(match_string) ? match_string : Qnil;
|
823
|
+
} else {
|
824
|
+
json->match_string = Qnil;
|
825
|
+
}
|
796
826
|
} else {
|
797
827
|
json->max_nesting = 100;
|
798
828
|
json->allow_nan = 0;
|
@@ -836,33 +866,33 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
|
|
836
866
|
*/
|
837
867
|
static VALUE cParser_parse(VALUE self)
|
838
868
|
{
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
869
|
+
char *p, *pe;
|
870
|
+
int cs = EVIL;
|
871
|
+
VALUE result = Qnil;
|
872
|
+
GET_PARSER;
|
843
873
|
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
874
|
+
%% write init;
|
875
|
+
p = json->source;
|
876
|
+
pe = p + json->len;
|
877
|
+
%% write exec;
|
848
878
|
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
879
|
+
if (cs >= JSON_first_final && p == pe) {
|
880
|
+
return result;
|
881
|
+
} else {
|
882
|
+
raise_parse_error("unexpected token at '%s'", p);
|
883
|
+
return Qnil;
|
884
|
+
}
|
855
885
|
}
|
856
886
|
|
857
887
|
static void JSON_mark(void *ptr)
|
858
888
|
{
|
859
889
|
JSON_Parser *json = ptr;
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
890
|
+
rb_gc_mark(json->Vsource);
|
891
|
+
rb_gc_mark(json->create_id);
|
892
|
+
rb_gc_mark(json->object_class);
|
893
|
+
rb_gc_mark(json->array_class);
|
894
|
+
rb_gc_mark(json->decimal_class);
|
895
|
+
rb_gc_mark(json->match_string);
|
866
896
|
}
|
867
897
|
|
868
898
|
static void JSON_free(void *ptr)
|
@@ -878,16 +908,12 @@ static size_t JSON_memsize(const void *ptr)
|
|
878
908
|
return sizeof(*json) + FBUFFER_CAPA(json->fbuffer);
|
879
909
|
}
|
880
910
|
|
881
|
-
#ifdef NEW_TYPEDDATA_WRAPPER
|
882
911
|
static const rb_data_type_t JSON_Parser_type = {
|
883
912
|
"JSON/Parser",
|
884
913
|
{JSON_mark, JSON_free, JSON_memsize,},
|
885
|
-
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
|
886
914
|
0, 0,
|
887
915
|
RUBY_TYPED_FREE_IMMEDIATELY,
|
888
|
-
#endif
|
889
916
|
};
|
890
|
-
#endif
|
891
917
|
|
892
918
|
static VALUE cJSON_parser_s_allocate(VALUE klass)
|
893
919
|
{
|
@@ -920,9 +946,7 @@ void Init_parser(void)
|
|
920
946
|
mJSON = rb_define_module("JSON");
|
921
947
|
mExt = rb_define_module_under(mJSON, "Ext");
|
922
948
|
cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
|
923
|
-
eParserError = rb_path2class("JSON::ParserError");
|
924
949
|
eNestingError = rb_path2class("JSON::NestingError");
|
925
|
-
rb_gc_register_mark_object(eParserError);
|
926
950
|
rb_gc_register_mark_object(eNestingError);
|
927
951
|
rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
|
928
952
|
rb_define_method(cParser, "initialize", cParser_initialize, -1);
|
@@ -951,7 +975,6 @@ void Init_parser(void)
|
|
951
975
|
i_decimal_class = rb_intern("decimal_class");
|
952
976
|
i_match = rb_intern("match");
|
953
977
|
i_match_string = rb_intern("match_string");
|
954
|
-
i_key_p = rb_intern("key?");
|
955
978
|
i_deep_const_get = rb_intern("deep_const_get");
|
956
979
|
i_aset = rb_intern("[]=");
|
957
980
|
i_aref = rb_intern("[]");
|
@@ -960,6 +983,9 @@ void Init_parser(void)
|
|
960
983
|
i_try_convert = rb_intern("try_convert");
|
961
984
|
i_freeze = rb_intern("freeze");
|
962
985
|
i_uminus = rb_intern("-@");
|
986
|
+
|
987
|
+
binary_encindex = rb_ascii8bit_encindex();
|
988
|
+
utf8_encindex = rb_utf8_encindex();
|
963
989
|
}
|
964
990
|
|
965
991
|
/*
|