json 1.1.5-x86-linux

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of json might be problematic. Click here for more details.

Files changed (117) hide show
  1. data/CHANGES +106 -0
  2. data/GPL +340 -0
  3. data/README +78 -0
  4. data/RUBY +58 -0
  5. data/Rakefile +268 -0
  6. data/TODO +1 -0
  7. data/VERSION +1 -0
  8. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkComparison.log +52 -0
  9. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast-autocorrelation.dat +1000 -0
  10. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast.dat +1001 -0
  11. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty-autocorrelation.dat +900 -0
  12. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty.dat +901 -0
  13. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe-autocorrelation.dat +1000 -0
  14. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe.dat +1001 -0
  15. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt.log +261 -0
  16. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast-autocorrelation.dat +1000 -0
  17. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast.dat +1001 -0
  18. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty-autocorrelation.dat +1000 -0
  19. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty.dat +1001 -0
  20. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe-autocorrelation.dat +1000 -0
  21. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe.dat +1001 -0
  22. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure.log +262 -0
  23. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator-autocorrelation.dat +1000 -0
  24. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator.dat +1001 -0
  25. data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails.log +82 -0
  26. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkComparison.log +34 -0
  27. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser-autocorrelation.dat +900 -0
  28. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser.dat +901 -0
  29. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt.log +81 -0
  30. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser-autocorrelation.dat +1000 -0
  31. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser.dat +1001 -0
  32. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure.log +82 -0
  33. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser-autocorrelation.dat +1000 -0
  34. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser.dat +1001 -0
  35. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails.log +82 -0
  36. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser-autocorrelation.dat +1000 -0
  37. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser.dat +1001 -0
  38. data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML.log +82 -0
  39. data/benchmarks/generator_benchmark.rb +165 -0
  40. data/benchmarks/parser_benchmark.rb +197 -0
  41. data/bin/edit_json.rb +9 -0
  42. data/bin/prettify_json.rb +75 -0
  43. data/data/example.json +1 -0
  44. data/data/index.html +38 -0
  45. data/data/prototype.js +4184 -0
  46. data/doc-templates/main.txt +283 -0
  47. data/ext/json/ext/generator/extconf.rb +11 -0
  48. data/ext/json/ext/generator/generator.c +919 -0
  49. data/ext/json/ext/generator/unicode.c +182 -0
  50. data/ext/json/ext/generator/unicode.h +53 -0
  51. data/ext/json/ext/parser/extconf.rb +11 -0
  52. data/ext/json/ext/parser/parser.c +1829 -0
  53. data/ext/json/ext/parser/parser.rl +686 -0
  54. data/ext/json/ext/parser/unicode.c +154 -0
  55. data/ext/json/ext/parser/unicode.h +58 -0
  56. data/install.rb +26 -0
  57. data/lib/json.rb +10 -0
  58. data/lib/json/Array.xpm +21 -0
  59. data/lib/json/FalseClass.xpm +21 -0
  60. data/lib/json/Hash.xpm +21 -0
  61. data/lib/json/Key.xpm +73 -0
  62. data/lib/json/NilClass.xpm +21 -0
  63. data/lib/json/Numeric.xpm +28 -0
  64. data/lib/json/String.xpm +96 -0
  65. data/lib/json/TrueClass.xpm +21 -0
  66. data/lib/json/add/core.rb +135 -0
  67. data/lib/json/add/rails.rb +58 -0
  68. data/lib/json/common.rb +354 -0
  69. data/lib/json/editor.rb +1371 -0
  70. data/lib/json/ext.rb +15 -0
  71. data/lib/json/ext/generator.so +0 -0
  72. data/lib/json/ext/parser.so +0 -0
  73. data/lib/json/json.xpm +1499 -0
  74. data/lib/json/pure.rb +77 -0
  75. data/lib/json/pure/generator.rb +430 -0
  76. data/lib/json/pure/parser.rb +267 -0
  77. data/lib/json/version.rb +8 -0
  78. data/tests/fixtures/fail1.json +1 -0
  79. data/tests/fixtures/fail10.json +1 -0
  80. data/tests/fixtures/fail11.json +1 -0
  81. data/tests/fixtures/fail12.json +1 -0
  82. data/tests/fixtures/fail13.json +1 -0
  83. data/tests/fixtures/fail14.json +1 -0
  84. data/tests/fixtures/fail18.json +1 -0
  85. data/tests/fixtures/fail19.json +1 -0
  86. data/tests/fixtures/fail2.json +1 -0
  87. data/tests/fixtures/fail20.json +1 -0
  88. data/tests/fixtures/fail21.json +1 -0
  89. data/tests/fixtures/fail22.json +1 -0
  90. data/tests/fixtures/fail23.json +1 -0
  91. data/tests/fixtures/fail24.json +1 -0
  92. data/tests/fixtures/fail25.json +1 -0
  93. data/tests/fixtures/fail27.json +2 -0
  94. data/tests/fixtures/fail28.json +2 -0
  95. data/tests/fixtures/fail3.json +1 -0
  96. data/tests/fixtures/fail4.json +1 -0
  97. data/tests/fixtures/fail5.json +1 -0
  98. data/tests/fixtures/fail6.json +1 -0
  99. data/tests/fixtures/fail7.json +1 -0
  100. data/tests/fixtures/fail8.json +1 -0
  101. data/tests/fixtures/fail9.json +1 -0
  102. data/tests/fixtures/pass1.json +56 -0
  103. data/tests/fixtures/pass15.json +1 -0
  104. data/tests/fixtures/pass16.json +1 -0
  105. data/tests/fixtures/pass17.json +1 -0
  106. data/tests/fixtures/pass2.json +1 -0
  107. data/tests/fixtures/pass26.json +1 -0
  108. data/tests/fixtures/pass3.json +6 -0
  109. data/tests/test_json.rb +312 -0
  110. data/tests/test_json_addition.rb +164 -0
  111. data/tests/test_json_fixtures.rb +34 -0
  112. data/tests/test_json_generate.rb +106 -0
  113. data/tests/test_json_rails.rb +146 -0
  114. data/tests/test_json_unicode.rb +62 -0
  115. data/tools/fuzz.rb +139 -0
  116. data/tools/server.rb +61 -0
  117. metadata +200 -0
@@ -0,0 +1,686 @@
1
+ #include "ruby.h"
2
+ #include "unicode.h"
3
+ #if HAVE_RE_H
4
+ #include "re.h"
5
+ #endif
6
+ #if HAVE_RUBY_ST_H
7
+ #include "ruby/st.h"
8
+ #endif
9
+ #if HAVE_ST_H
10
+ #include "st.h"
11
+ #endif
12
+
13
+ #define EVIL 0x666
14
+
15
+ #ifndef RHASH_TBL
16
+ #define RHASH_TBL(hsh) (RHASH(hsh)->tbl)
17
+ #endif
18
+
19
+ #ifdef HAVE_RUBY_ENCODING_H
20
+ #include "ruby/encoding.h"
21
+ #define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding())
22
+ #else
23
+ #define FORCE_UTF8(obj)
24
+ #endif
25
+
26
+ static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
27
+ static VALUE CNaN, CInfinity, CMinusInfinity;
28
+
29
+ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
30
+ i_chr, i_max_nesting, i_allow_nan, i_object_class, i_array_class;
31
+
32
+ #define MinusInfinity "-Infinity"
33
+
34
+ typedef struct JSON_ParserStruct {
35
+ VALUE Vsource;
36
+ char *source;
37
+ long len;
38
+ char *memo;
39
+ VALUE create_id;
40
+ int max_nesting;
41
+ int current_nesting;
42
+ int allow_nan;
43
+ VALUE object_class;
44
+ VALUE array_class;
45
+ } JSON_Parser;
46
+
47
+ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result);
48
+ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result);
49
+ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result);
50
+ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result);
51
+ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result);
52
+ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result);
53
+
54
+ #define GET_STRUCT \
55
+ JSON_Parser *json; \
56
+ Data_Get_Struct(self, JSON_Parser, json);
57
+
58
+ %%{
59
+ machine JSON_common;
60
+
61
+ cr = '\n';
62
+ cr_neg = [^\n];
63
+ ws = [ \t\r\n];
64
+ c_comment = '/*' ( any* - (any* '*/' any* ) ) '*/';
65
+ cpp_comment = '//' cr_neg* cr;
66
+ comment = c_comment | cpp_comment;
67
+ ignore = ws | comment;
68
+ name_separator = ':';
69
+ value_separator = ',';
70
+ Vnull = 'null';
71
+ Vfalse = 'false';
72
+ Vtrue = 'true';
73
+ VNaN = 'NaN';
74
+ VInfinity = 'Infinity';
75
+ VMinusInfinity = '-Infinity';
76
+ begin_value = [nft"\-[{NI] | digit;
77
+ begin_object = '{';
78
+ end_object = '}';
79
+ begin_array = '[';
80
+ end_array = ']';
81
+ begin_string = '"';
82
+ begin_name = begin_string;
83
+ begin_number = digit | '-';
84
+ }%%
85
+
86
+ %%{
87
+ machine JSON_object;
88
+ include JSON_common;
89
+
90
+ write data;
91
+
92
+ action parse_value {
93
+ VALUE v = Qnil;
94
+ char *np = JSON_parse_value(json, fpc, pe, &v);
95
+ if (np == NULL) {
96
+ fhold; fbreak;
97
+ } else {
98
+ rb_hash_aset(*result, last_name, v);
99
+ fexec np;
100
+ }
101
+ }
102
+
103
+ action parse_name {
104
+ char *np = JSON_parse_string(json, fpc, pe, &last_name);
105
+ if (np == NULL) { fhold; fbreak; } else fexec np;
106
+ }
107
+
108
+ action exit { fhold; fbreak; }
109
+
110
+ a_pair = ignore* begin_name >parse_name
111
+ ignore* name_separator ignore*
112
+ begin_value >parse_value;
113
+
114
+ main := begin_object
115
+ (a_pair (ignore* value_separator a_pair)*)?
116
+ ignore* end_object @exit;
117
+ }%%
118
+
119
+ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result)
120
+ {
121
+ int cs = EVIL;
122
+ VALUE last_name = Qnil;
123
+ VALUE object_class = json->object_class;
124
+
125
+ if (json->max_nesting && json->current_nesting > json->max_nesting) {
126
+ rb_raise(eNestingError, "nesting of %d is to deep", json->current_nesting);
127
+ }
128
+
129
+ *result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class);
130
+
131
+ %% write init;
132
+ %% write exec;
133
+
134
+ if (cs >= JSON_object_first_final) {
135
+ if (RTEST(json->create_id)) {
136
+ VALUE klassname = rb_hash_aref(*result, json->create_id);
137
+ if (!NIL_P(klassname)) {
138
+ VALUE klass = rb_path2class(StringValueCStr(klassname));
139
+ if RTEST(rb_funcall(klass, i_json_creatable_p, 0)) {
140
+ *result = rb_funcall(klass, i_json_create, 1, *result);
141
+ }
142
+ }
143
+ }
144
+ return p + 1;
145
+ } else {
146
+ return NULL;
147
+ }
148
+ }
149
+
150
+ %%{
151
+ machine JSON_value;
152
+ include JSON_common;
153
+
154
+ write data;
155
+
156
+ action parse_null {
157
+ *result = Qnil;
158
+ }
159
+ action parse_false {
160
+ *result = Qfalse;
161
+ }
162
+ action parse_true {
163
+ *result = Qtrue;
164
+ }
165
+ action parse_nan {
166
+ if (json->allow_nan) {
167
+ *result = CNaN;
168
+ } else {
169
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2);
170
+ }
171
+ }
172
+ action parse_infinity {
173
+ if (json->allow_nan) {
174
+ *result = CInfinity;
175
+ } else {
176
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8);
177
+ }
178
+ }
179
+ action parse_string {
180
+ char *np = JSON_parse_string(json, fpc, pe, result);
181
+ if (np == NULL) { fhold; fbreak; } else fexec np;
182
+ }
183
+
184
+ action parse_number {
185
+ char *np;
186
+ if(pe > fpc + 9 && !strncmp(MinusInfinity, fpc, 9)) {
187
+ if (json->allow_nan) {
188
+ *result = CMinusInfinity;
189
+ fexec p + 10;
190
+ fhold; fbreak;
191
+ } else {
192
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
193
+ }
194
+ }
195
+ np = JSON_parse_float(json, fpc, pe, result);
196
+ if (np != NULL) fexec np;
197
+ np = JSON_parse_integer(json, fpc, pe, result);
198
+ if (np != NULL) fexec np;
199
+ fhold; fbreak;
200
+ }
201
+
202
+ action parse_array {
203
+ char *np;
204
+ json->current_nesting++;
205
+ np = JSON_parse_array(json, fpc, pe, result);
206
+ json->current_nesting--;
207
+ if (np == NULL) { fhold; fbreak; } else fexec np;
208
+ }
209
+
210
+ action parse_object {
211
+ char *np;
212
+ json->current_nesting++;
213
+ np = JSON_parse_object(json, fpc, pe, result);
214
+ json->current_nesting--;
215
+ if (np == NULL) { fhold; fbreak; } else fexec np;
216
+ }
217
+
218
+ action exit { fhold; fbreak; }
219
+
220
+ main := (
221
+ Vnull @parse_null |
222
+ Vfalse @parse_false |
223
+ Vtrue @parse_true |
224
+ VNaN @parse_nan |
225
+ VInfinity @parse_infinity |
226
+ begin_number >parse_number |
227
+ begin_string >parse_string |
228
+ begin_array >parse_array |
229
+ begin_object >parse_object
230
+ ) %*exit;
231
+ }%%
232
+
233
+ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result)
234
+ {
235
+ int cs = EVIL;
236
+
237
+ %% write init;
238
+ %% write exec;
239
+
240
+ if (cs >= JSON_value_first_final) {
241
+ return p;
242
+ } else {
243
+ return NULL;
244
+ }
245
+ }
246
+
247
+ %%{
248
+ machine JSON_integer;
249
+
250
+ write data;
251
+
252
+ action exit { fhold; fbreak; }
253
+
254
+ main := '-'? ('0' | [1-9][0-9]*) (^[0-9] @exit);
255
+ }%%
256
+
257
+ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
258
+ {
259
+ int cs = EVIL;
260
+
261
+ %% write init;
262
+ json->memo = p;
263
+ %% write exec;
264
+
265
+ if (cs >= JSON_integer_first_final) {
266
+ long len = p - json->memo;
267
+ *result = rb_Integer(rb_str_new(json->memo, len));
268
+ return p + 1;
269
+ } else {
270
+ return NULL;
271
+ }
272
+ }
273
+
274
+ %%{
275
+ machine JSON_float;
276
+ include JSON_common;
277
+
278
+ write data;
279
+
280
+ action exit { fhold; fbreak; }
281
+
282
+ main := '-'? (
283
+ (('0' | [1-9][0-9]*) '.' [0-9]+ ([Ee] [+\-]?[0-9]+)?)
284
+ | (('0' | [1-9][0-9]*) ([Ee] [+\-]?[0-9]+))
285
+ ) (^[0-9Ee.\-] @exit );
286
+ }%%
287
+
288
+ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
289
+ {
290
+ int cs = EVIL;
291
+
292
+ %% write init;
293
+ json->memo = p;
294
+ %% write exec;
295
+
296
+ if (cs >= JSON_float_first_final) {
297
+ long len = p - json->memo;
298
+ *result = rb_Float(rb_str_new(json->memo, len));
299
+ return p + 1;
300
+ } else {
301
+ return NULL;
302
+ }
303
+ }
304
+
305
+
306
+ %%{
307
+ machine JSON_array;
308
+ include JSON_common;
309
+
310
+ write data;
311
+
312
+ action parse_value {
313
+ VALUE v = Qnil;
314
+ char *np = JSON_parse_value(json, fpc, pe, &v);
315
+ if (np == NULL) {
316
+ fhold; fbreak;
317
+ } else {
318
+ rb_ary_push(*result, v);
319
+ fexec np;
320
+ }
321
+ }
322
+
323
+ action exit { fhold; fbreak; }
324
+
325
+ next_element = value_separator ignore* begin_value >parse_value;
326
+
327
+ main := begin_array ignore*
328
+ ((begin_value >parse_value ignore*)
329
+ (ignore* next_element ignore*)*)?
330
+ end_array @exit;
331
+ }%%
332
+
333
+ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result)
334
+ {
335
+ int cs = EVIL;
336
+ VALUE array_class = json->array_class;
337
+
338
+ if (json->max_nesting && json->current_nesting > json->max_nesting) {
339
+ rb_raise(eNestingError, "nesting of %d is to deep", json->current_nesting);
340
+ }
341
+ *result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
342
+
343
+ %% write init;
344
+ %% write exec;
345
+
346
+ if(cs >= JSON_array_first_final) {
347
+ return p + 1;
348
+ } else {
349
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
350
+ }
351
+ }
352
+
353
+ static VALUE json_string_unescape(char *p, char *pe)
354
+ {
355
+ VALUE result = rb_str_buf_new(pe - p + 1);
356
+
357
+ while (p < pe) {
358
+ if (*p == '\\') {
359
+ p++;
360
+ if (p >= pe) return Qnil; /* raise an exception later, \ at end */
361
+ switch (*p) {
362
+ case '"':
363
+ case '\\':
364
+ rb_str_buf_cat(result, p, 1);
365
+ p++;
366
+ break;
367
+ case 'b':
368
+ rb_str_buf_cat2(result, "\b");
369
+ p++;
370
+ break;
371
+ case 'f':
372
+ rb_str_buf_cat2(result, "\f");
373
+ p++;
374
+ break;
375
+ case 'n':
376
+ rb_str_buf_cat2(result, "\n");
377
+ p++;
378
+ break;
379
+ case 'r':
380
+ rb_str_buf_cat2(result, "\r");
381
+ p++;
382
+ break;
383
+ case 't':
384
+ rb_str_buf_cat2(result, "\t");
385
+ p++;
386
+ break;
387
+ case 'u':
388
+ if (p > pe - 4) {
389
+ return Qnil;
390
+ } else {
391
+ p = JSON_convert_UTF16_to_UTF8(result, p, pe, strictConversion);
392
+ }
393
+ break;
394
+ default:
395
+ rb_str_buf_cat(result, p, 1);
396
+ p++;
397
+ break;
398
+ }
399
+ } else {
400
+ char *q = p;
401
+ while (*q != '\\' && q < pe) q++;
402
+ rb_str_buf_cat(result, p, q - p);
403
+ p = q;
404
+ }
405
+ }
406
+ return result;
407
+ }
408
+
409
+ %%{
410
+ machine JSON_string;
411
+ include JSON_common;
412
+
413
+ write data;
414
+
415
+ action parse_string {
416
+ *result = json_string_unescape(json->memo + 1, p);
417
+ if (NIL_P(*result)) {
418
+ fhold;
419
+ fbreak;
420
+ } else {
421
+ FORCE_UTF8(*result);
422
+ fexec p + 1;
423
+ }
424
+ }
425
+
426
+ action exit { fhold; fbreak; }
427
+
428
+ main := '"' ((^(["\\] | 0..0x1f) | '\\'["\\/bfnrt] | '\\u'[0-9a-fA-F]{4} | '\\'^(["\\/bfnrtu]|0..0x1f))* %parse_string) '"' @exit;
429
+ }%%
430
+
431
+ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result)
432
+ {
433
+ int cs = EVIL;
434
+
435
+ *result = rb_str_new("", 0);
436
+ %% write init;
437
+ json->memo = p;
438
+ %% write exec;
439
+
440
+ if (cs >= JSON_string_first_final) {
441
+ return p + 1;
442
+ } else {
443
+ return NULL;
444
+ }
445
+ }
446
+
447
+
448
+ %%{
449
+ machine JSON;
450
+
451
+ write data;
452
+
453
+ include JSON_common;
454
+
455
+ action parse_object {
456
+ char *np;
457
+ json->current_nesting = 1;
458
+ np = JSON_parse_object(json, fpc, pe, &result);
459
+ if (np == NULL) { fhold; fbreak; } else fexec np;
460
+ }
461
+
462
+ action parse_array {
463
+ char *np;
464
+ json->current_nesting = 1;
465
+ np = JSON_parse_array(json, fpc, pe, &result);
466
+ if (np == NULL) { fhold; fbreak; } else fexec np;
467
+ }
468
+
469
+ main := ignore* (
470
+ begin_object >parse_object |
471
+ begin_array >parse_array
472
+ ) ignore*;
473
+ }%%
474
+
475
+ /*
476
+ * Document-class: JSON::Ext::Parser
477
+ *
478
+ * This is the JSON parser implemented as a C extension. It can be configured
479
+ * to be used by setting
480
+ *
481
+ * JSON.parser = JSON::Ext::Parser
482
+ *
483
+ * with the method parser= in JSON.
484
+ *
485
+ */
486
+
487
+ /*
488
+ * call-seq: new(source, opts => {})
489
+ *
490
+ * Creates a new JSON::Ext::Parser instance for the string _source_.
491
+ *
492
+ * Creates a new JSON::Ext::Parser instance for the string _source_.
493
+ *
494
+ * It will be configured by the _opts_ hash. _opts_ can have the following
495
+ * keys:
496
+ *
497
+ * _opts_ can have the following keys:
498
+ * * *max_nesting*: The maximum depth of nesting allowed in the parsed data
499
+ * structures. Disable depth checking with :max_nesting => false|nil|0, it
500
+ * defaults to 19.
501
+ * * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
502
+ * defiance of RFC 4627 to be parsed by the Parser. This option defaults to
503
+ * false.
504
+ * * *create_additions*: If set to false, the Parser doesn't create
505
+ * additions even if a matchin class and create_id was found. This option
506
+ * defaults to true.
507
+ * * *object_class*: Defaults to Hash
508
+ * * *array_class*: Defaults to Array
509
+ */
510
+ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
511
+ {
512
+ char *ptr;
513
+ long len;
514
+ VALUE source, opts;
515
+ GET_STRUCT;
516
+ rb_scan_args(argc, argv, "11", &source, &opts);
517
+ source = StringValue(source);
518
+ ptr = RSTRING_PTR(source);
519
+ len = RSTRING_LEN(source);
520
+ if (len < 2) {
521
+ rb_raise(eParserError, "A JSON text must at least contain two octets!");
522
+ }
523
+ if (!NIL_P(opts)) {
524
+ opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
525
+ if (NIL_P(opts)) {
526
+ rb_raise(rb_eArgError, "opts needs to be like a hash");
527
+ } else {
528
+ VALUE tmp = ID2SYM(i_max_nesting);
529
+ if (st_lookup(RHASH_TBL(opts), tmp, 0)) {
530
+ VALUE max_nesting = rb_hash_aref(opts, tmp);
531
+ if (RTEST(max_nesting)) {
532
+ Check_Type(max_nesting, T_FIXNUM);
533
+ json->max_nesting = FIX2INT(max_nesting);
534
+ } else {
535
+ json->max_nesting = 0;
536
+ }
537
+ } else {
538
+ json->max_nesting = 19;
539
+ }
540
+ tmp = ID2SYM(i_allow_nan);
541
+ if (st_lookup(RHASH_TBL(opts), tmp, 0)) {
542
+ VALUE allow_nan = rb_hash_aref(opts, tmp);
543
+ json->allow_nan = RTEST(allow_nan) ? 1 : 0;
544
+ } else {
545
+ json->allow_nan = 0;
546
+ }
547
+ tmp = ID2SYM(i_create_additions);
548
+ if (st_lookup(RHASH_TBL(opts), tmp, 0)) {
549
+ VALUE create_additions = rb_hash_aref(opts, tmp);
550
+ if (RTEST(create_additions)) {
551
+ json->create_id = rb_funcall(mJSON, i_create_id, 0);
552
+ } else {
553
+ json->create_id = Qnil;
554
+ }
555
+ } else {
556
+ json->create_id = rb_funcall(mJSON, i_create_id, 0);
557
+ }
558
+ tmp = ID2SYM(i_object_class);
559
+ if (st_lookup(RHASH_TBL(opts), tmp, 0)) {
560
+ json->object_class = rb_hash_aref(opts, tmp);
561
+ } else {
562
+ json->object_class = Qnil;
563
+ }
564
+ tmp = ID2SYM(i_array_class);
565
+ if (st_lookup(RHASH_TBL(opts), tmp, 0)) {
566
+ json->array_class = rb_hash_aref(opts, tmp);
567
+ } else {
568
+ json->array_class = Qnil;
569
+ }
570
+ }
571
+ } else {
572
+ json->max_nesting = 19;
573
+ json->allow_nan = 0;
574
+ json->create_id = rb_funcall(mJSON, i_create_id, 0);
575
+ json->object_class = Qnil;
576
+ json->array_class = Qnil;
577
+ }
578
+ json->current_nesting = 0;
579
+ /*
580
+ Convert these?
581
+ if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
582
+ rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
583
+ } else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
584
+ rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
585
+ } else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
586
+ rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
587
+ } else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
588
+ rb_raise(eParserError, "Only UTF8 octet streams are supported atm!");
589
+ }
590
+ */
591
+ json->len = len;
592
+ json->source = ptr;
593
+ json->Vsource = source;
594
+ return self;
595
+ }
596
+
597
+ /*
598
+ * call-seq: parse()
599
+ *
600
+ * Parses the current JSON text _source_ and returns the complete data
601
+ * structure as a result.
602
+ */
603
+ static VALUE cParser_parse(VALUE self)
604
+ {
605
+ char *p, *pe;
606
+ int cs = EVIL;
607
+ VALUE result = Qnil;
608
+ GET_STRUCT;
609
+
610
+ %% write init;
611
+ p = json->source;
612
+ pe = p + json->len;
613
+ %% write exec;
614
+
615
+ if (cs >= JSON_first_final && p == pe) {
616
+ return result;
617
+ } else {
618
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
619
+ }
620
+ }
621
+
622
+ inline static JSON_Parser *JSON_allocate()
623
+ {
624
+ JSON_Parser *json = ALLOC(JSON_Parser);
625
+ MEMZERO(json, JSON_Parser, 1);
626
+ return json;
627
+ }
628
+
629
+ static void JSON_mark(JSON_Parser *json)
630
+ {
631
+ rb_gc_mark_maybe(json->Vsource);
632
+ rb_gc_mark_maybe(json->create_id);
633
+ rb_gc_mark_maybe(json->object_class);
634
+ rb_gc_mark_maybe(json->array_class);
635
+ }
636
+
637
+ static void JSON_free(JSON_Parser *json)
638
+ {
639
+ ruby_xfree(json);
640
+ }
641
+
642
+ static VALUE cJSON_parser_s_allocate(VALUE klass)
643
+ {
644
+ JSON_Parser *json = JSON_allocate();
645
+ return Data_Wrap_Struct(klass, JSON_mark, JSON_free, json);
646
+ }
647
+
648
+ /*
649
+ * call-seq: source()
650
+ *
651
+ * Returns a copy of the current _source_ string, that was used to construct
652
+ * this Parser.
653
+ */
654
+ static VALUE cParser_source(VALUE self)
655
+ {
656
+ GET_STRUCT;
657
+ return rb_str_dup(json->Vsource);
658
+ }
659
+
660
+ void Init_parser()
661
+ {
662
+ rb_require("json/common");
663
+ mJSON = rb_define_module("JSON");
664
+ mExt = rb_define_module_under(mJSON, "Ext");
665
+ cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
666
+ eParserError = rb_path2class("JSON::ParserError");
667
+ eNestingError = rb_path2class("JSON::NestingError");
668
+ rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
669
+ rb_define_method(cParser, "initialize", cParser_initialize, -1);
670
+ rb_define_method(cParser, "parse", cParser_parse, 0);
671
+ rb_define_method(cParser, "source", cParser_source, 0);
672
+
673
+ CNaN = rb_const_get(mJSON, rb_intern("NaN"));
674
+ CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
675
+ CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
676
+
677
+ i_json_creatable_p = rb_intern("json_creatable?");
678
+ i_json_create = rb_intern("json_create");
679
+ i_create_id = rb_intern("create_id");
680
+ i_create_additions = rb_intern("create_additions");
681
+ i_chr = rb_intern("chr");
682
+ i_max_nesting = rb_intern("max_nesting");
683
+ i_allow_nan = rb_intern("allow_nan");
684
+ i_object_class = rb_intern("object_class");
685
+ i_array_class = rb_intern("array_class");
686
+ }