json 1.0.0 → 2.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES.md +503 -0
  3. data/LICENSE +56 -0
  4. data/README.md +416 -0
  5. data/ext/json/ext/fbuffer/fbuffer.h +187 -0
  6. data/ext/json/ext/generator/depend +1 -0
  7. data/ext/json/ext/generator/extconf.rb +2 -7
  8. data/ext/json/ext/generator/generator.c +1312 -338
  9. data/ext/json/ext/generator/generator.h +177 -0
  10. data/ext/json/ext/parser/depend +1 -0
  11. data/ext/json/ext/parser/extconf.rb +28 -5
  12. data/ext/json/ext/parser/parser.c +1349 -689
  13. data/ext/json/ext/parser/parser.h +96 -0
  14. data/ext/json/ext/parser/parser.rl +644 -188
  15. data/ext/json/extconf.rb +3 -0
  16. data/json.gemspec +68 -0
  17. data/lib/json/add/bigdecimal.rb +58 -0
  18. data/lib/json/add/complex.rb +51 -0
  19. data/lib/json/add/core.rb +12 -0
  20. data/lib/json/add/date.rb +54 -0
  21. data/lib/json/add/date_time.rb +67 -0
  22. data/lib/json/add/exception.rb +49 -0
  23. data/lib/json/add/ostruct.rb +54 -0
  24. data/lib/json/add/range.rb +54 -0
  25. data/lib/json/add/rational.rb +49 -0
  26. data/lib/json/add/regexp.rb +48 -0
  27. data/lib/json/add/set.rb +48 -0
  28. data/lib/json/add/struct.rb +52 -0
  29. data/lib/json/add/symbol.rb +48 -0
  30. data/lib/json/add/time.rb +59 -0
  31. data/lib/json/common.rb +588 -74
  32. data/lib/json/ext.rb +3 -1
  33. data/lib/json/generic_object.rb +75 -0
  34. data/lib/json/pure/generator.rb +311 -119
  35. data/lib/json/pure/parser.rb +182 -55
  36. data/lib/json/pure.rb +5 -65
  37. data/lib/json/version.rb +2 -1
  38. data/lib/json.rb +583 -196
  39. metadata +78 -137
  40. data/CHANGES +0 -25
  41. data/GPL +0 -340
  42. data/README +0 -77
  43. data/Rakefile +0 -250
  44. data/TODO +0 -1
  45. data/VERSION +0 -1
  46. data/benchmarks/benchmark.txt +0 -133
  47. data/benchmarks/benchmark_generator.rb +0 -44
  48. data/benchmarks/benchmark_parser.rb +0 -22
  49. data/benchmarks/benchmark_rails.rb +0 -26
  50. data/bin/edit_json.rb +0 -11
  51. data/data/example.json +0 -1
  52. data/data/index.html +0 -37
  53. data/data/prototype.js +0 -2515
  54. data/ext/json/ext/generator/Makefile +0 -149
  55. data/ext/json/ext/generator/unicode.c +0 -184
  56. data/ext/json/ext/generator/unicode.h +0 -40
  57. data/ext/json/ext/parser/Makefile +0 -149
  58. data/ext/json/ext/parser/unicode.c +0 -156
  59. data/ext/json/ext/parser/unicode.h +0 -44
  60. data/install.rb +0 -26
  61. data/lib/json/Array.xpm +0 -21
  62. data/lib/json/FalseClass.xpm +0 -21
  63. data/lib/json/Hash.xpm +0 -21
  64. data/lib/json/Key.xpm +0 -73
  65. data/lib/json/NilClass.xpm +0 -21
  66. data/lib/json/Numeric.xpm +0 -28
  67. data/lib/json/String.xpm +0 -96
  68. data/lib/json/TrueClass.xpm +0 -21
  69. data/lib/json/editor.rb +0 -1207
  70. data/lib/json/json.xpm +0 -1499
  71. data/tests/fixtures/fail1.json +0 -1
  72. data/tests/fixtures/fail10.json +0 -1
  73. data/tests/fixtures/fail11.json +0 -1
  74. data/tests/fixtures/fail12.json +0 -1
  75. data/tests/fixtures/fail13.json +0 -1
  76. data/tests/fixtures/fail14.json +0 -1
  77. data/tests/fixtures/fail15.json +0 -1
  78. data/tests/fixtures/fail16.json +0 -1
  79. data/tests/fixtures/fail17.json +0 -1
  80. data/tests/fixtures/fail19.json +0 -1
  81. data/tests/fixtures/fail2.json +0 -1
  82. data/tests/fixtures/fail20.json +0 -1
  83. data/tests/fixtures/fail21.json +0 -1
  84. data/tests/fixtures/fail22.json +0 -1
  85. data/tests/fixtures/fail23.json +0 -1
  86. data/tests/fixtures/fail24.json +0 -1
  87. data/tests/fixtures/fail25.json +0 -1
  88. data/tests/fixtures/fail26.json +0 -1
  89. data/tests/fixtures/fail27.json +0 -2
  90. data/tests/fixtures/fail28.json +0 -2
  91. data/tests/fixtures/fail3.json +0 -1
  92. data/tests/fixtures/fail4.json +0 -1
  93. data/tests/fixtures/fail5.json +0 -1
  94. data/tests/fixtures/fail6.json +0 -1
  95. data/tests/fixtures/fail7.json +0 -1
  96. data/tests/fixtures/fail8.json +0 -1
  97. data/tests/fixtures/fail9.json +0 -1
  98. data/tests/fixtures/pass1.json +0 -56
  99. data/tests/fixtures/pass18.json +0 -1
  100. data/tests/fixtures/pass2.json +0 -1
  101. data/tests/fixtures/pass3.json +0 -6
  102. data/tests/runner.rb +0 -24
  103. data/tests/test_json.rb +0 -235
  104. data/tests/test_json_addition.rb +0 -94
  105. data/tests/test_json_fixtures.rb +0 -30
  106. data/tests/test_json_generate.rb +0 -81
  107. data/tests/test_json_unicode.rb +0 -55
  108. data/tools/fuzz.rb +0 -133
  109. data/tools/server.rb +0 -62
@@ -1,37 +1,100 @@
1
- /* vim: set cin et sw=4 ts=4: */
1
+ #include "../fbuffer/fbuffer.h"
2
+ #include "parser.h"
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;
2
12
 
3
- #include "ruby.h"
4
- #include "re.h"
5
- #include "unicode.h"
13
+ va_start(args, fmt);
14
+ mesg = rb_enc_vsprintf(enc, fmt, args);
15
+ va_end(args);
6
16
 
7
- #ifndef swap16
8
- #define swap16(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
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
9
24
  #endif
10
25
 
11
- #define EVIL 0x666
12
-
13
- static VALUE mJSON, mExt, cParser, eParserError;
14
-
15
- static ID i_json_creatable_p, i_json_create, i_create_id, i_chr;
26
+ /* unicode */
27
+
28
+ static const signed char digit_values[256] = {
29
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
30
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
31
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1,
32
+ -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1,
33
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
34
+ 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
35
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
36
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
37
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
38
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
39
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
40
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
41
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
42
+ -1, -1, -1, -1, -1, -1, -1
43
+ };
44
+
45
+ static UTF32 unescape_unicode(const unsigned char *p)
46
+ {
47
+ signed char b;
48
+ UTF32 result = 0;
49
+ b = digit_values[p[0]];
50
+ if (b < 0) return UNI_REPLACEMENT_CHAR;
51
+ result = (result << 4) | (unsigned char)b;
52
+ b = digit_values[p[1]];
53
+ if (b < 0) return UNI_REPLACEMENT_CHAR;
54
+ result = (result << 4) | (unsigned char)b;
55
+ b = digit_values[p[2]];
56
+ if (b < 0) return UNI_REPLACEMENT_CHAR;
57
+ result = (result << 4) | (unsigned char)b;
58
+ b = digit_values[p[3]];
59
+ if (b < 0) return UNI_REPLACEMENT_CHAR;
60
+ result = (result << 4) | (unsigned char)b;
61
+ return result;
62
+ }
16
63
 
17
- typedef struct JSON_ParserStruct {
18
- VALUE Vsource;
19
- char *source;
20
- long len;
21
- char *memo;
22
- VALUE create_id;
23
- } JSON_Parser;
64
+ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
65
+ {
66
+ int len = 1;
67
+ if (ch <= 0x7F) {
68
+ buf[0] = (char) ch;
69
+ } else if (ch <= 0x07FF) {
70
+ buf[0] = (char) ((ch >> 6) | 0xC0);
71
+ buf[1] = (char) ((ch & 0x3F) | 0x80);
72
+ len++;
73
+ } else if (ch <= 0xFFFF) {
74
+ buf[0] = (char) ((ch >> 12) | 0xE0);
75
+ buf[1] = (char) (((ch >> 6) & 0x3F) | 0x80);
76
+ buf[2] = (char) ((ch & 0x3F) | 0x80);
77
+ len += 2;
78
+ } else if (ch <= 0x1fffff) {
79
+ buf[0] =(char) ((ch >> 18) | 0xF0);
80
+ buf[1] =(char) (((ch >> 12) & 0x3F) | 0x80);
81
+ buf[2] =(char) (((ch >> 6) & 0x3F) | 0x80);
82
+ buf[3] =(char) ((ch & 0x3F) | 0x80);
83
+ len += 3;
84
+ } else {
85
+ buf[0] = '?';
86
+ }
87
+ return len;
88
+ }
24
89
 
25
- static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result);
26
- static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result);
27
- static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result);
28
- static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result);
29
- static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result);
30
- static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result);
90
+ static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
91
+ static VALUE CNaN, CInfinity, CMinusInfinity;
31
92
 
32
- #define GET_STRUCT \
33
- JSON_Parser *json; \
34
- Data_Get_Struct(self, JSON_Parser, json);
93
+ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
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;
35
98
 
36
99
  %%{
37
100
  machine JSON_common;
@@ -48,7 +111,10 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
48
111
  Vnull = 'null';
49
112
  Vfalse = 'false';
50
113
  Vtrue = 'true';
51
- begin_value = [nft"\-[{] | digit;
114
+ VNaN = 'NaN';
115
+ VInfinity = 'Infinity';
116
+ VMinusInfinity = '-Infinity';
117
+ begin_value = [nft\"\-\[\{NI] | digit;
52
118
  begin_object = '{';
53
119
  end_object = '}';
54
120
  begin_array = '[';
@@ -66,46 +132,68 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
66
132
 
67
133
  action parse_value {
68
134
  VALUE v = Qnil;
69
- char *np = JSON_parse_value(json, fpc, pe, &v);
135
+ char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
70
136
  if (np == NULL) {
71
- fbreak;
137
+ fhold; fbreak;
72
138
  } else {
73
- rb_hash_aset(*result, last_name, v);
139
+ if (NIL_P(json->object_class)) {
140
+ OBJ_FREEZE(last_name);
141
+ rb_hash_aset(*result, last_name, v);
142
+ } else {
143
+ rb_funcall(*result, i_aset, 2, last_name, v);
144
+ }
74
145
  fexec np;
75
146
  }
76
147
  }
77
148
 
78
149
  action parse_name {
79
- char *np = JSON_parse_string(json, fpc, pe, &last_name);
80
- if (np == NULL) fbreak; else fexec np;
150
+ char *np;
151
+ json->parsing_name = 1;
152
+ np = JSON_parse_string(json, fpc, pe, &last_name);
153
+ json->parsing_name = 0;
154
+ if (np == NULL) { fhold; fbreak; } else fexec np;
81
155
  }
82
156
 
83
- action exit { fbreak; }
157
+ action exit { fhold; fbreak; }
84
158
 
85
- a_pair = ignore* begin_name >parse_name
86
- ignore* name_separator ignore*
87
- begin_value >parse_value;
159
+ pair = ignore* begin_name >parse_name ignore* name_separator ignore* begin_value >parse_value;
160
+ next_pair = ignore* value_separator pair;
88
161
 
89
- main := begin_object
90
- (a_pair (ignore* value_separator a_pair)*)?
91
- ignore* end_object @exit;
162
+ main := (
163
+ begin_object
164
+ (pair (next_pair)*)? ignore*
165
+ end_object
166
+ ) @exit;
92
167
  }%%
93
168
 
94
- 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)
95
170
  {
96
171
  int cs = EVIL;
97
172
  VALUE last_name = Qnil;
98
- *result = rb_hash_new();
173
+ VALUE object_class = json->object_class;
174
+
175
+ if (json->max_nesting && current_nesting > json->max_nesting) {
176
+ rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
177
+ }
178
+
179
+ *result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class);
99
180
 
100
181
  %% write init;
101
182
  %% write exec;
102
183
 
103
184
  if (cs >= JSON_object_first_final) {
104
- VALUE klassname = rb_hash_aref(*result, json->create_id);
105
- if (!NIL_P(klassname)) {
106
- VALUE klass = rb_path2class(StringValueCStr(klassname));
107
- if RTEST(rb_funcall(klass, i_json_creatable_p, 0)) {
108
- *result = rb_funcall(klass, i_json_create, 1, *result);
185
+ if (json->create_additions) {
186
+ VALUE klassname;
187
+ if (NIL_P(json->object_class)) {
188
+ klassname = rb_hash_aref(*result, json->create_id);
189
+ } else {
190
+ klassname = rb_funcall(*result, i_aref, 1, json->create_id);
191
+ }
192
+ if (!NIL_P(klassname)) {
193
+ VALUE klass = rb_funcall(mJSON, i_deep_const_get, 1, klassname);
194
+ if (RTEST(rb_funcall(klass, i_json_creatable_p, 0))) {
195
+ *result = rb_funcall(klass, i_json_create, 1, *result);
196
+ }
109
197
  }
110
198
  }
111
199
  return p + 1;
@@ -114,6 +202,7 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
114
202
  }
115
203
  }
116
204
 
205
+
117
206
  %%{
118
207
  machine JSON_value;
119
208
  include JSON_common;
@@ -129,50 +218,81 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
129
218
  action parse_true {
130
219
  *result = Qtrue;
131
220
  }
221
+ action parse_nan {
222
+ if (json->allow_nan) {
223
+ *result = CNaN;
224
+ } else {
225
+ rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 2);
226
+ }
227
+ }
228
+ action parse_infinity {
229
+ if (json->allow_nan) {
230
+ *result = CInfinity;
231
+ } else {
232
+ rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 7);
233
+ }
234
+ }
132
235
  action parse_string {
133
236
  char *np = JSON_parse_string(json, fpc, pe, result);
134
- if (np == NULL) fbreak; else fexec np;
237
+ if (np == NULL) { fhold; fbreak; } else fexec np;
135
238
  }
136
239
 
137
240
  action parse_number {
138
241
  char *np;
242
+ if(pe > fpc + 8 && !strncmp(MinusInfinity, fpc, 9)) {
243
+ if (json->allow_nan) {
244
+ *result = CMinusInfinity;
245
+ fexec p + 10;
246
+ fhold; fbreak;
247
+ } else {
248
+ rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p);
249
+ }
250
+ }
139
251
  np = JSON_parse_float(json, fpc, pe, result);
140
252
  if (np != NULL) fexec np;
141
253
  np = JSON_parse_integer(json, fpc, pe, result);
142
254
  if (np != NULL) fexec np;
143
- fbreak;
255
+ fhold; fbreak;
144
256
  }
145
257
 
146
- action parse_array {
147
- char *np = JSON_parse_array(json, fpc, pe, result);
148
- if (np == NULL) fbreak; else fexec np;
258
+ action parse_array {
259
+ char *np;
260
+ np = JSON_parse_array(json, fpc, pe, result, current_nesting + 1);
261
+ if (np == NULL) { fhold; fbreak; } else fexec np;
149
262
  }
150
263
 
151
- action parse_object {
152
- char *np = JSON_parse_object(json, fpc, pe, result);
153
- if (np == NULL) fbreak; else fexec np;
264
+ action parse_object {
265
+ char *np;
266
+ np = JSON_parse_object(json, fpc, pe, result, current_nesting + 1);
267
+ if (np == NULL) { fhold; fbreak; } else fexec np;
154
268
  }
155
269
 
156
- action exit { fbreak; }
270
+ action exit { fhold; fbreak; }
157
271
 
158
- main := (
272
+ main := ignore* (
159
273
  Vnull @parse_null |
160
274
  Vfalse @parse_false |
161
275
  Vtrue @parse_true |
276
+ VNaN @parse_nan |
277
+ VInfinity @parse_infinity |
162
278
  begin_number >parse_number |
163
279
  begin_string >parse_string |
164
280
  begin_array >parse_array |
165
281
  begin_object >parse_object
166
- ) %*exit;
282
+ ) ignore* %*exit;
167
283
  }%%
168
284
 
169
- 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)
170
286
  {
171
287
  int cs = EVIL;
172
288
 
173
289
  %% write init;
174
290
  %% write exec;
175
291
 
292
+ if (json->freeze) {
293
+ OBJ_FREEZE(*result);
294
+ }
295
+
176
296
  if (cs >= JSON_value_first_final) {
177
297
  return p;
178
298
  } else {
@@ -185,9 +305,9 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
185
305
 
186
306
  write data;
187
307
 
188
- action exit { fbreak; }
308
+ action exit { fhold; fbreak; }
189
309
 
190
- main := '-'? ('0' | [1-9][0-9]*) (^[0-9] @exit);
310
+ main := '-'? ('0' | [1-9][0-9]*) (^[0-9]? @exit);
191
311
  }%%
192
312
 
193
313
  static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -200,7 +320,10 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
200
320
 
201
321
  if (cs >= JSON_integer_first_final) {
202
322
  long len = p - json->memo;
203
- *result = rb_Integer(rb_str_new(json->memo, len));
323
+ fbuffer_clear(json->fbuffer);
324
+ fbuffer_append(json->fbuffer, json->memo, len);
325
+ fbuffer_append_char(json->fbuffer, '\0');
326
+ *result = rb_cstr2inum(FBUFFER_PTR(json->fbuffer), 10);
204
327
  return p + 1;
205
328
  } else {
206
329
  return NULL;
@@ -213,12 +336,12 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
213
336
 
214
337
  write data;
215
338
 
216
- action exit { fbreak; }
339
+ action exit { fhold; fbreak; }
217
340
 
218
341
  main := '-'? (
219
342
  (('0' | [1-9][0-9]*) '.' [0-9]+ ([Ee] [+\-]?[0-9]+)?)
220
- | ([1-9][0-9]* ([Ee] [+\-]?[0-9]+))
221
- ) (^[0-9Ee.\-] @exit );
343
+ | (('0' | [1-9][0-9]*) ([Ee] [+\-]?[0-9]+))
344
+ ) (^[0-9Ee.\-]? @exit );
222
345
  }%%
223
346
 
224
347
  static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -230,8 +353,46 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
230
353
  %% write exec;
231
354
 
232
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
+
233
384
  long len = p - json->memo;
234
- *result = rb_Float(rb_str_new(json->memo, len));
385
+ fbuffer_clear(json->fbuffer);
386
+ fbuffer_append(json->fbuffer, json->memo, len);
387
+ fbuffer_append_char(json->fbuffer, '\0');
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
+
235
396
  return p + 1;
236
397
  } else {
237
398
  return NULL;
@@ -247,16 +408,20 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
247
408
 
248
409
  action parse_value {
249
410
  VALUE v = Qnil;
250
- char *np = JSON_parse_value(json, fpc, pe, &v);
411
+ char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
251
412
  if (np == NULL) {
252
- fbreak;
413
+ fhold; fbreak;
253
414
  } else {
254
- rb_ary_push(*result, v);
415
+ if (NIL_P(json->array_class)) {
416
+ rb_ary_push(*result, v);
417
+ } else {
418
+ rb_funcall(*result, i_leftshift, 1, v);
419
+ }
255
420
  fexec np;
256
421
  }
257
422
  }
258
423
 
259
- action exit { fbreak; }
424
+ action exit { fhold; fbreak; }
260
425
 
261
426
  next_element = value_separator ignore* begin_value >parse_value;
262
427
 
@@ -266,10 +431,15 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
266
431
  end_array @exit;
267
432
  }%%
268
433
 
269
- 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)
270
435
  {
271
436
  int cs = EVIL;
272
- *result = rb_ary_new();
437
+ VALUE array_class = json->array_class;
438
+
439
+ if (json->max_nesting && current_nesting > json->max_nesting) {
440
+ rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
441
+ }
442
+ *result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
273
443
 
274
444
  %% write init;
275
445
  %% write exec;
@@ -277,59 +447,154 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
277
447
  if(cs >= JSON_array_first_final) {
278
448
  return p + 1;
279
449
  } else {
280
- rb_raise(eParserError, "unexpected token at '%s'", p);
450
+ rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p);
451
+ return NULL;
281
452
  }
282
453
  }
283
454
 
284
- static VALUE json_string_escape(char *p, char *pe)
455
+ static const size_t MAX_STACK_BUFFER_SIZE = 128;
456
+ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int symbolize)
285
457
  {
286
- VALUE result = rb_str_buf_new(pe - p + 1);
458
+ VALUE result = Qnil;
459
+ size_t bufferSize = stringEnd - string;
460
+ char *p = string, *pe = string, *unescape, *bufferStart, *buffer;
461
+ int unescape_len;
462
+ char buf[4];
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
+ }
287
477
 
288
- while (p < pe) {
289
- if (*p == '\\') {
290
- p++;
291
- if (p >= pe) return Qnil; /* raise an exception later, \ at end */
292
- switch (*p) {
478
+ while (pe < stringEnd) {
479
+ if (*pe == '\\') {
480
+ unescape = (char *) "?";
481
+ unescape_len = 1;
482
+ if (pe > p) {
483
+ MEMCPY(buffer, p, char, pe - p);
484
+ buffer += pe - p;
485
+ }
486
+ switch (*++pe) {
487
+ case 'n':
488
+ unescape = (char *) "\n";
489
+ break;
490
+ case 'r':
491
+ unescape = (char *) "\r";
492
+ break;
493
+ case 't':
494
+ unescape = (char *) "\t";
495
+ break;
293
496
  case '"':
497
+ unescape = (char *) "\"";
498
+ break;
294
499
  case '\\':
295
- rb_str_buf_cat(result, p, 1);
296
- p++;
500
+ unescape = (char *) "\\";
297
501
  break;
298
502
  case 'b':
299
- rb_str_buf_cat2(result, "\b");
300
- p++;
503
+ unescape = (char *) "\b";
301
504
  break;
302
505
  case 'f':
303
- rb_str_buf_cat2(result, "\f");
304
- p++;
305
- break;
306
- case 'n':
307
- rb_str_buf_cat2(result, "\n");
308
- p++;
309
- break;
310
- case 'r':
311
- rb_str_buf_cat2(result, "\r");
312
- p++;
313
- break;
314
- case 't':
315
- rb_str_buf_cat2(result, "\t");
316
- p++;
506
+ unescape = (char *) "\f";
317
507
  break;
318
508
  case 'u':
319
- if (p > pe - 4) {
320
- return Qnil;
509
+ if (pe > stringEnd - 4) {
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
+ );
321
517
  } else {
322
- p = JSON_convert_UTF16_to_UTF8(result, p, pe, strictConversion);
518
+ UTF32 ch = unescape_unicode((unsigned char *) ++pe);
519
+ pe += 3;
520
+ if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
521
+ pe++;
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
+ }
531
+ if (pe[0] == '\\' && pe[1] == 'u') {
532
+ UTF32 sur = unescape_unicode((unsigned char *) pe + 2);
533
+ ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16)
534
+ | (sur & 0x3FF));
535
+ pe += 5;
536
+ } else {
537
+ unescape = (char *) "?";
538
+ break;
539
+ }
540
+ }
541
+ unescape_len = convert_UTF32_to_UTF8(buf, ch);
542
+ unescape = buf;
323
543
  }
324
544
  break;
545
+ default:
546
+ p = pe;
547
+ continue;
325
548
  }
549
+ MEMCPY(buffer, unescape, char, unescape_len);
550
+ buffer += unescape_len;
551
+ p = ++pe;
326
552
  } else {
327
- char *q = p;
328
- while (*q != '\\' && q < pe) q++;
329
- rb_str_buf_cat(result, p, q - p);
330
- p = q;
553
+ pe++;
331
554
  }
332
555
  }
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
+
333
598
  return result;
334
599
  }
335
600
 
@@ -340,24 +605,52 @@ static VALUE json_string_escape(char *p, char *pe)
340
605
  write data;
341
606
 
342
607
  action parse_string {
343
- *result = json_string_escape(json->memo + 1, p);
344
- if (NIL_P(*result)) fbreak; else fexec p + 1;
608
+ *result = json_string_unescape(json->memo + 1, p, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names);
609
+ if (NIL_P(*result)) {
610
+ fhold;
611
+ fbreak;
612
+ } else {
613
+ fexec p + 1;
614
+ }
345
615
  }
346
616
 
347
- action exit { fbreak; }
617
+ action exit { fhold; fbreak; }
348
618
 
349
- main := '"' ((^(["\\] | 0..0x1f) | '\\'["\\/bfnrt] | '\\u'[0-9a-fA-F]{4})* %parse_string) '"' @exit;
619
+ main := '"' ((^([\"\\] | 0..0x1f) | '\\'[\"\\/bfnrt] | '\\u'[0-9a-fA-F]{4} | '\\'^([\"\\/bfnrtu]|0..0x1f))* %parse_string) '"' @exit;
350
620
  }%%
351
621
 
622
+ static int
623
+ match_i(VALUE regexp, VALUE klass, VALUE memo)
624
+ {
625
+ if (regexp == Qundef) return ST_STOP;
626
+ if (RTEST(rb_funcall(klass, i_json_creatable_p, 0)) &&
627
+ RTEST(rb_funcall(regexp, i_match, 1, rb_ary_entry(memo, 0)))) {
628
+ rb_ary_push(memo, klass);
629
+ return ST_STOP;
630
+ }
631
+ return ST_CONTINUE;
632
+ }
633
+
352
634
  static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result)
353
635
  {
354
636
  int cs = EVIL;
637
+ VALUE match_string;
355
638
 
356
- *result = rb_str_new("", 0);
357
639
  %% write init;
358
640
  json->memo = p;
359
641
  %% write exec;
360
642
 
643
+ if (json->create_additions && RTEST(match_string = json->match_string)) {
644
+ VALUE klass;
645
+ VALUE memo = rb_ary_new2(2);
646
+ rb_ary_push(memo, *result);
647
+ rb_hash_foreach(match_string, match_i, memo);
648
+ klass = rb_ary_entry(memo, 1);
649
+ if (RTEST(klass)) {
650
+ *result = rb_funcall(klass, i_json_create, 1, *result);
651
+ }
652
+ }
653
+
361
654
  if (cs >= JSON_string_first_final) {
362
655
  return p + 1;
363
656
  } else {
@@ -365,31 +658,7 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
365
658
  }
366
659
  }
367
660
 
368
-
369
- %%{
370
- machine JSON;
371
-
372
- write data;
373
-
374
- include JSON_common;
375
-
376
- action parse_object {
377
- char *np = JSON_parse_object(json, fpc, pe, &result);
378
- if (np == NULL) fbreak; else fexec np;
379
- }
380
-
381
- action parse_array {
382
- char *np = JSON_parse_array(json, fpc, pe, &result);
383
- if (np == NULL) fbreak; else fexec np;
384
- }
385
-
386
- main := ignore* (
387
- begin_object >parse_object |
388
- begin_array >parse_array
389
- ) ignore*;
390
- }%%
391
-
392
- /*
661
+ /*
393
662
  * Document-class: JSON::Ext::Parser
394
663
  *
395
664
  * This is the JSON parser implemented as a C extension. It can be configured
@@ -401,88 +670,231 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
401
670
  *
402
671
  */
403
672
 
673
+ static VALUE convert_encoding(VALUE source)
674
+ {
675
+ #ifdef HAVE_RUBY_ENCODING_H
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);
680
+ }
681
+ FORCE_UTF8(source);
682
+ } else {
683
+ source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding());
684
+ }
685
+ #endif
686
+ return source;
687
+ }
688
+
404
689
  /*
405
- * call-seq: new(source)
690
+ * call-seq: new(source, opts => {})
406
691
  *
407
692
  * Creates a new JSON::Ext::Parser instance for the string _source_.
693
+ *
694
+ * It will be configured by the _opts_ hash. _opts_ can have the following
695
+ * keys:
696
+ *
697
+ * _opts_ can have the following keys:
698
+ * * *max_nesting*: The maximum depth of nesting allowed in the parsed data
699
+ * structures. Disable depth checking with :max_nesting => false|nil|0, it
700
+ * defaults to 100.
701
+ * * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
702
+ * defiance of RFC 4627 to be parsed by the Parser. This option defaults to
703
+ * false.
704
+ * * *symbolize_names*: If set to true, returns symbols for the names
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.
708
+ * * *create_additions*: If set to false, the Parser doesn't create
709
+ * additions even if a matching class and create_id was found. This option
710
+ * defaults to false.
711
+ * * *object_class*: Defaults to Hash
712
+ * * *array_class*: Defaults to Array
408
713
  */
409
- static VALUE cParser_initialize(VALUE self, VALUE source)
714
+ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
410
715
  {
411
- char *ptr;
412
- long len;
413
- GET_STRUCT;
414
- source = StringValue(source);
415
- ptr = RSTRING(source)->ptr;
416
- len = RSTRING(source)->len;
417
- if (len < 2) {
418
- rb_raise(eParserError, "A JSON text must at least contain two octets!");
419
- }
420
- /*
421
- Convert these?
422
- if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
423
- rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
424
- } else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
425
- rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
426
- } else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
427
- rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
428
- } else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
429
- rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
430
- }
431
- */
432
- json->len = len;
433
- json->source = ptr;
716
+ VALUE source, opts;
717
+ GET_PARSER_INIT;
718
+
719
+ if (json->Vsource) {
720
+ rb_raise(rb_eTypeError, "already initialized instance");
721
+ }
722
+ rb_scan_args(argc, argv, "1:", &source, &opts);
723
+ if (!NIL_P(opts)) {
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
+ }
796
+ } else {
797
+ json->max_nesting = 100;
798
+ json->allow_nan = 0;
799
+ json->create_additions = 0;
800
+ json->create_id = Qnil;
801
+ json->object_class = Qnil;
802
+ json->array_class = Qnil;
803
+ json->decimal_class = Qnil;
804
+ }
805
+ source = convert_encoding(StringValue(source));
806
+ StringValue(source);
807
+ json->len = RSTRING_LEN(source);
808
+ json->source = RSTRING_PTR(source);;
434
809
  json->Vsource = source;
435
- json->create_id = rb_funcall(mJSON, i_create_id, 0);
436
810
  return self;
437
811
  }
438
812
 
813
+ %%{
814
+ machine JSON;
815
+
816
+ write data;
817
+
818
+ include JSON_common;
819
+
820
+ action parse_value {
821
+ char *np = JSON_parse_value(json, fpc, pe, &result, 0);
822
+ if (np == NULL) { fhold; fbreak; } else fexec np;
823
+ }
824
+
825
+ main := ignore* (
826
+ begin_value >parse_value
827
+ ) ignore*;
828
+ }%%
829
+
439
830
  /*
440
831
  * call-seq: parse()
441
832
  *
442
833
  * Parses the current JSON text _source_ and returns the complete data
443
834
  * structure as a result.
835
+ * It raises JSON::ParserError if fail to parse.
444
836
  */
445
837
  static VALUE cParser_parse(VALUE self)
446
838
  {
447
- GET_STRUCT;
448
- char *p, *pe;
449
- int cs = EVIL;
450
- VALUE result = Qnil;
839
+ char *p, *pe;
840
+ int cs = EVIL;
841
+ VALUE result = Qnil;
842
+ GET_PARSER;
451
843
 
452
- %% write init;
453
- p = json->source;
454
- pe = p + json->len;
455
- %% write exec;
844
+ %% write init;
845
+ p = json->source;
846
+ pe = p + json->len;
847
+ %% write exec;
456
848
 
457
- if (cs >= JSON_first_final && p == pe) {
458
- return result;
459
- } else {
460
- rb_raise(eParserError, "unexpected token at '%s'", p);
461
- }
849
+ if (cs >= JSON_first_final && p == pe) {
850
+ return result;
851
+ } else {
852
+ rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p);
853
+ return Qnil;
854
+ }
462
855
  }
463
856
 
464
- static JSON_Parser *JSON_allocate()
857
+ static void JSON_mark(void *ptr)
465
858
  {
466
- JSON_Parser *json = ALLOC(JSON_Parser);
467
- MEMZERO(json, JSON_Parser, 1);
468
- return json;
859
+ JSON_Parser *json = ptr;
860
+ rb_gc_mark_maybe(json->Vsource);
861
+ rb_gc_mark_maybe(json->create_id);
862
+ rb_gc_mark_maybe(json->object_class);
863
+ rb_gc_mark_maybe(json->array_class);
864
+ rb_gc_mark_maybe(json->decimal_class);
865
+ rb_gc_mark_maybe(json->match_string);
469
866
  }
470
867
 
471
- static void JSON_mark(JSON_Parser *json)
868
+ static void JSON_free(void *ptr)
472
869
  {
473
- rb_gc_mark_maybe(json->Vsource);
474
- rb_gc_mark_maybe(json->create_id);
870
+ JSON_Parser *json = ptr;
871
+ fbuffer_free(json->fbuffer);
872
+ ruby_xfree(json);
475
873
  }
476
874
 
477
- static void JSON_free(JSON_Parser *json)
875
+ static size_t JSON_memsize(const void *ptr)
478
876
  {
479
- free(json);
877
+ const JSON_Parser *json = ptr;
878
+ return sizeof(*json) + FBUFFER_CAPA(json->fbuffer);
480
879
  }
481
880
 
881
+ #ifdef NEW_TYPEDDATA_WRAPPER
882
+ static const rb_data_type_t JSON_Parser_type = {
883
+ "JSON/Parser",
884
+ {JSON_mark, JSON_free, JSON_memsize,},
885
+ #ifdef RUBY_TYPED_FREE_IMMEDIATELY
886
+ 0, 0,
887
+ RUBY_TYPED_FREE_IMMEDIATELY,
888
+ #endif
889
+ };
890
+ #endif
891
+
482
892
  static VALUE cJSON_parser_s_allocate(VALUE klass)
483
893
  {
484
- JSON_Parser *json = JSON_allocate();
485
- return Data_Wrap_Struct(klass, JSON_mark, JSON_free, json);
894
+ JSON_Parser *json;
895
+ VALUE obj = TypedData_Make_Struct(klass, JSON_Parser, &JSON_Parser_type, json);
896
+ json->fbuffer = fbuffer_alloc(0);
897
+ return obj;
486
898
  }
487
899
 
488
900
  /*
@@ -493,23 +905,67 @@ static VALUE cJSON_parser_s_allocate(VALUE klass)
493
905
  */
494
906
  static VALUE cParser_source(VALUE self)
495
907
  {
496
- GET_STRUCT;
908
+ GET_PARSER;
497
909
  return rb_str_dup(json->Vsource);
498
910
  }
499
911
 
500
- void Init_parser()
912
+ void Init_parser(void)
501
913
  {
914
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
915
+ rb_ext_ractor_safe(true);
916
+ #endif
917
+
918
+ #undef rb_intern
919
+ rb_require("json/common");
502
920
  mJSON = rb_define_module("JSON");
503
921
  mExt = rb_define_module_under(mJSON, "Ext");
504
922
  cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
505
923
  eParserError = rb_path2class("JSON::ParserError");
924
+ eNestingError = rb_path2class("JSON::NestingError");
925
+ rb_gc_register_mark_object(eParserError);
926
+ rb_gc_register_mark_object(eNestingError);
506
927
  rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
507
- rb_define_method(cParser, "initialize", cParser_initialize, 1);
928
+ rb_define_method(cParser, "initialize", cParser_initialize, -1);
508
929
  rb_define_method(cParser, "parse", cParser_parse, 0);
509
930
  rb_define_method(cParser, "source", cParser_source, 0);
510
931
 
932
+ CNaN = rb_const_get(mJSON, rb_intern("NaN"));
933
+ rb_gc_register_mark_object(CNaN);
934
+
935
+ CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
936
+ rb_gc_register_mark_object(CInfinity);
937
+
938
+ CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
939
+ rb_gc_register_mark_object(CMinusInfinity);
940
+
511
941
  i_json_creatable_p = rb_intern("json_creatable?");
512
942
  i_json_create = rb_intern("json_create");
513
943
  i_create_id = rb_intern("create_id");
944
+ i_create_additions = rb_intern("create_additions");
514
945
  i_chr = rb_intern("chr");
946
+ i_max_nesting = rb_intern("max_nesting");
947
+ i_allow_nan = rb_intern("allow_nan");
948
+ i_symbolize_names = rb_intern("symbolize_names");
949
+ i_object_class = rb_intern("object_class");
950
+ i_array_class = rb_intern("array_class");
951
+ i_decimal_class = rb_intern("decimal_class");
952
+ i_match = rb_intern("match");
953
+ i_match_string = rb_intern("match_string");
954
+ i_key_p = rb_intern("key?");
955
+ i_deep_const_get = rb_intern("deep_const_get");
956
+ i_aset = rb_intern("[]=");
957
+ i_aref = rb_intern("[]");
958
+ i_leftshift = rb_intern("<<");
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("-@");
515
963
  }
964
+
965
+ /*
966
+ * Local variables:
967
+ * mode: c
968
+ * c-file-style: ruby
969
+ * indent-tabs-mode: nil
970
+ * End:
971
+ */