json 1.7.0 → 2.3.0

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