json 1.0.0 → 2.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ */