json 1.8.3 → 2.2.0

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 (82) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.travis.yml +7 -10
  4. data/{CHANGES → CHANGES.md} +186 -90
  5. data/Gemfile +10 -6
  6. data/{README-json-jruby.markdown → README-json-jruby.md} +0 -0
  7. data/{README.rdoc → README.md} +184 -133
  8. data/Rakefile +33 -37
  9. data/VERSION +1 -1
  10. data/ext/json/ext/fbuffer/fbuffer.h +0 -3
  11. data/ext/json/ext/generator/generator.c +47 -61
  12. data/ext/json/ext/generator/generator.h +7 -2
  13. data/ext/json/ext/parser/extconf.rb +3 -0
  14. data/ext/json/ext/parser/parser.c +374 -459
  15. data/ext/json/ext/parser/parser.h +4 -5
  16. data/ext/json/ext/parser/parser.rl +133 -181
  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 +11 -12
  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 +15 -0
  32. data/json.gemspec +0 -0
  33. data/json_pure.gemspec +24 -26
  34. data/lib/json/add/bigdecimal.rb +1 -0
  35. data/lib/json/add/complex.rb +2 -1
  36. data/lib/json/add/core.rb +1 -0
  37. data/lib/json/add/date.rb +1 -1
  38. data/lib/json/add/date_time.rb +1 -1
  39. data/lib/json/add/exception.rb +1 -1
  40. data/lib/json/add/ostruct.rb +3 -3
  41. data/lib/json/add/range.rb +1 -1
  42. data/lib/json/add/rational.rb +1 -0
  43. data/lib/json/add/regexp.rb +1 -1
  44. data/lib/json/add/set.rb +29 -0
  45. data/lib/json/add/struct.rb +1 -1
  46. data/lib/json/add/symbol.rb +1 -1
  47. data/lib/json/add/time.rb +1 -1
  48. data/lib/json/common.rb +24 -52
  49. data/lib/json/ext.rb +0 -6
  50. data/lib/json/generic_object.rb +5 -4
  51. data/lib/json/pure/generator.rb +61 -125
  52. data/lib/json/pure/parser.rb +33 -81
  53. data/lib/json/pure.rb +2 -8
  54. data/lib/json/version.rb +2 -1
  55. data/lib/json.rb +1 -0
  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} +5 -8
  63. data/tests/{test_json_generate.rb → json_generator_test.rb} +79 -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 +29 -47
  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,11 +57,11 @@ 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);
@@ -1,6 +1,28 @@
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
28
  static const char digit_values[256] = {
@@ -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,10 @@ 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 {
575
+ if (RB_TYPE_P(*result, T_STRING)) {
576
+ rb_str_resize(*result, RSTRING_LEN(*result));
577
+ }
531
578
  }
532
579
  if (cs >= JSON_string_first_final) {
533
580
  return p + 1;
@@ -550,41 +597,16 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
550
597
 
551
598
  static VALUE convert_encoding(VALUE source)
552
599
  {
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
600
  #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);
601
+ rb_encoding *enc = rb_enc_get(source);
602
+ if (enc == rb_ascii8bit_encoding()) {
603
+ if (OBJ_FROZEN(source)) {
604
+ source = rb_str_dup(source);
587
605
  }
606
+ FORCE_UTF8(source);
607
+ } else {
608
+ source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding());
609
+ }
588
610
  #endif
589
611
  return source;
590
612
  }
@@ -607,8 +629,9 @@ static VALUE convert_encoding(VALUE source)
607
629
  * defiance of RFC 4627 to be parsed by the Parser. This option defaults to
608
630
  * false.
609
631
  * * *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.
632
+ * (keys) in a JSON object. Otherwise strings are returned, which is
633
+ * also the default. It's not possible to use this option in
634
+ * conjunction with the *create_additions* option.
612
635
  * * *create_additions*: If set to false, the Parser doesn't create
613
636
  * additions even if a matching class and create_id was found. This option
614
637
  * defaults to false.
@@ -623,12 +646,18 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
623
646
  if (json->Vsource) {
624
647
  rb_raise(rb_eTypeError, "already initialized instance");
625
648
  }
649
+ #ifdef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
650
+ rb_scan_args(argc, argv, "1:", &source, &opts);
651
+ #else
626
652
  rb_scan_args(argc, argv, "11", &source, &opts);
653
+ #endif
627
654
  if (!NIL_P(opts)) {
655
+ #ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
628
656
  opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
629
657
  if (NIL_P(opts)) {
630
658
  rb_raise(rb_eArgError, "opts needs to be like a hash");
631
659
  } else {
660
+ #endif
632
661
  VALUE tmp = ID2SYM(i_max_nesting);
633
662
  if (option_given_p(opts, tmp)) {
634
663
  VALUE max_nesting = rb_hash_aref(opts, tmp);
@@ -653,19 +682,17 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
653
682
  } else {
654
683
  json->symbolize_names = 0;
655
684
  }
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
685
  tmp = ID2SYM(i_create_additions);
664
686
  if (option_given_p(opts, tmp)) {
665
687
  json->create_additions = RTEST(rb_hash_aref(opts, tmp));
666
688
  } else {
667
689
  json->create_additions = 0;
668
690
  }
691
+ if (json->symbolize_names && json->create_additions) {
692
+ rb_raise(rb_eArgError,
693
+ "options :symbolize_names and :create_additions cannot be "
694
+ " used in conjunction");
695
+ }
669
696
  tmp = ID2SYM(i_create_id);
670
697
  if (option_given_p(opts, tmp)) {
671
698
  json->create_id = rb_hash_aref(opts, tmp);
@@ -684,6 +711,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
684
711
  } else {
685
712
  json->array_class = Qnil;
686
713
  }
714
+ tmp = ID2SYM(i_decimal_class);
715
+ if (option_given_p(opts, tmp)) {
716
+ json->decimal_class = rb_hash_aref(opts, tmp);
717
+ } else {
718
+ json->decimal_class = Qnil;
719
+ }
687
720
  tmp = ID2SYM(i_match_string);
688
721
  if (option_given_p(opts, tmp)) {
689
722
  VALUE match_string = rb_hash_aref(opts, tmp);
@@ -691,7 +724,9 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
691
724
  } else {
692
725
  json->match_string = Qnil;
693
726
  }
727
+ #ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
694
728
  }
729
+ #endif
695
730
  } else {
696
731
  json->max_nesting = 100;
697
732
  json->allow_nan = 0;
@@ -699,12 +734,9 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
699
734
  json->create_id = rb_funcall(mJSON, i_create_id, 0);
700
735
  json->object_class = Qnil;
701
736
  json->array_class = Qnil;
737
+ json->decimal_class = Qnil;
702
738
  }
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;
739
+ source = convert_encoding(StringValue(source));
708
740
  StringValue(source);
709
741
  json->len = RSTRING_LEN(source);
710
742
  json->source = RSTRING_PTR(source);;
@@ -719,56 +751,8 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
719
751
 
720
752
  include JSON_common;
721
753
 
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
754
  action parse_value {
771
- char *np = JSON_parse_value(json, fpc, pe, &result);
755
+ char *np = JSON_parse_value(json, fpc, pe, &result, 0);
772
756
  if (np == NULL) { fhold; fbreak; } else fexec np;
773
757
  }
774
758
 
@@ -777,26 +761,6 @@ static VALUE cParser_parse_strict(VALUE self)
777
761
  ) ignore*;
778
762
  }%%
779
763
 
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
764
  /*
801
765
  * call-seq: parse()
802
766
  *
@@ -805,12 +769,21 @@ static VALUE cParser_parse_quirks_mode(VALUE self)
805
769
  */
806
770
  static VALUE cParser_parse(VALUE self)
807
771
  {
772
+ char *p, *pe;
773
+ int cs = EVIL;
774
+ VALUE result = Qnil;
808
775
  GET_PARSER;
809
776
 
810
- if (json->quirks_mode) {
811
- return cParser_parse_quirks_mode(self);
777
+ %% write init;
778
+ p = json->source;
779
+ pe = p + json->len;
780
+ %% write exec;
781
+
782
+ if (cs >= JSON_first_final && p == pe) {
783
+ return result;
812
784
  } else {
813
- return cParser_parse_strict(self);
785
+ rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
786
+ return Qnil;
814
787
  }
815
788
  }
816
789
 
@@ -821,6 +794,7 @@ static void JSON_mark(void *ptr)
821
794
  rb_gc_mark_maybe(json->create_id);
822
795
  rb_gc_mark_maybe(json->object_class);
823
796
  rb_gc_mark_maybe(json->array_class);
797
+ rb_gc_mark_maybe(json->decimal_class);
824
798
  rb_gc_mark_maybe(json->match_string);
825
799
  }
826
800
 
@@ -868,20 +842,9 @@ static VALUE cParser_source(VALUE self)
868
842
  return rb_str_dup(json->Vsource);
869
843
  }
870
844
 
871
- /*
872
- * call-seq: quirks_mode?()
873
- *
874
- * Returns a true, if this parser is in quirks_mode, false otherwise.
875
- */
876
- static VALUE cParser_quirks_mode_p(VALUE self)
877
- {
878
- GET_PARSER;
879
- return json->quirks_mode ? Qtrue : Qfalse;
880
- }
881
-
882
-
883
845
  void Init_parser(void)
884
846
  {
847
+ #undef rb_intern
885
848
  rb_require("json/common");
886
849
  mJSON = rb_define_module("JSON");
887
850
  mExt = rb_define_module_under(mJSON, "Ext");
@@ -892,7 +855,6 @@ void Init_parser(void)
892
855
  rb_define_method(cParser, "initialize", cParser_initialize, -1);
893
856
  rb_define_method(cParser, "parse", cParser_parse, 0);
894
857
  rb_define_method(cParser, "source", cParser_source, 0);
895
- rb_define_method(cParser, "quirks_mode?", cParser_quirks_mode_p, 0);
896
858
 
897
859
  CNaN = rb_const_get(mJSON, rb_intern("NaN"));
898
860
  CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
@@ -906,9 +868,9 @@ void Init_parser(void)
906
868
  i_max_nesting = rb_intern("max_nesting");
907
869
  i_allow_nan = rb_intern("allow_nan");
908
870
  i_symbolize_names = rb_intern("symbolize_names");
909
- i_quirks_mode = rb_intern("quirks_mode");
910
871
  i_object_class = rb_intern("object_class");
911
872
  i_array_class = rb_intern("array_class");
873
+ i_decimal_class = rb_intern("decimal_class");
912
874
  i_match = rb_intern("match");
913
875
  i_match_string = rb_intern("match_string");
914
876
  i_key_p = rb_intern("key?");
@@ -916,18 +878,8 @@ void Init_parser(void)
916
878
  i_aset = rb_intern("[]=");
917
879
  i_aref = rb_intern("[]");
918
880
  i_leftshift = rb_intern("<<");
919
- #ifdef HAVE_RUBY_ENCODING_H
920
- CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
921
- CEncoding_UTF_16BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16be"));
922
- CEncoding_UTF_16LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16le"));
923
- CEncoding_UTF_32BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32be"));
924
- CEncoding_UTF_32LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32le"));
925
- CEncoding_ASCII_8BIT = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("ascii-8bit"));
926
- i_encoding = rb_intern("encoding");
927
- i_encode = rb_intern("encode");
928
- #else
929
- i_iconv = rb_intern("iconv");
930
- #endif
881
+ i_new = rb_intern("new");
882
+ i_BigDecimal = rb_intern("BigDecimal");
931
883
  }
932
884
 
933
885
  /*
data/ext/json/extconf.rb CHANGED
@@ -1,3 +1,2 @@
1
1
  require 'mkmf'
2
2
  create_makefile('json')
3
-
@@ -1,8 +1,7 @@
1
1
  /*
2
2
  * This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
3
3
  *
4
- * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
5
- * for details.
4
+ * Distributed under the Ruby license: https://www.ruby-lang.org/en/about/license.txt
6
5
  */
7
6
  package json.ext;
8
7
 
@@ -1,8 +1,7 @@
1
1
  /*
2
2
  * This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
3
3
  *
4
- * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
5
- * for details.
4
+ * Distributed under the Ruby license: https://www.ruby-lang.org/en/about/license.txt
6
5
  */
7
6
  package json.ext;
8
7
 
@@ -173,9 +172,7 @@ public final class Generator {
173
172
  result = RubyString.newString(session.getRuntime(), buffer);
174
173
  ThreadContext context = session.getContext();
175
174
  RuntimeInfo info = session.getInfo();
176
- if (info.encodingsSupported()) {
177
- result.force_encoding(context, info.utf8.get());
178
- }
175
+ result.force_encoding(context, info.utf8.get());
179
176
  return result;
180
177
  }
181
178
 
@@ -382,8 +379,7 @@ public final class Generator {
382
379
  RuntimeInfo info = session.getInfo();
383
380
  RubyString src;
384
381
 
385
- if (info.encodingsSupported() &&
386
- object.encoding(session.getContext()) != info.utf8.get()) {
382
+ if (object.encoding(session.getContext()) != info.utf8.get()) {
387
383
  src = (RubyString)object.encode(session.getContext(),
388
384
  info.utf8.get());
389
385
  } else {
@@ -428,11 +424,14 @@ public final class Generator {
428
424
  new Handler<IRubyObject>() {
429
425
  @Override
430
426
  RubyString generateNew(Session session, IRubyObject object) {
431
- IRubyObject result =
432
- object.callMethod(session.getContext(), "to_json",
433
- new IRubyObject[] {session.getState()});
434
- if (result instanceof RubyString) return (RubyString)result;
435
- throw session.getRuntime().newTypeError("to_json must return a String");
427
+ if (object.respondsTo("to_json")) {
428
+ IRubyObject result = object.callMethod(session.getContext(), "to_json",
429
+ new IRubyObject[] {session.getState()});
430
+ if (result instanceof RubyString) return (RubyString)result;
431
+ throw session.getRuntime().newTypeError("to_json must return a String");
432
+ } else {
433
+ return OBJECT_HANDLER.generateNew(session, object);
434
+ }
436
435
  }
437
436
 
438
437
  @Override
@@ -1,8 +1,7 @@
1
1
  /*
2
2
  * This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
3
3
  *
4
- * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
5
- * for details.
4
+ * Distributed under the Ruby license: https://www.ruby-lang.org/en/about/license.txt
6
5
  */
7
6
  package json.ext;
8
7