json 1.8.2 → 2.3.1

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