json 1.8.3 → 2.4.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 (83) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +2 -0
  3. data/.travis.yml +9 -12
  4. data/{CHANGES → CHANGES.md} +219 -90
  5. data/Gemfile +10 -6
  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} +201 -134
  9. data/Rakefile +35 -113
  10. data/VERSION +1 -1
  11. data/ext/json/ext/fbuffer/fbuffer.h +0 -3
  12. data/ext/json/ext/generator/generator.c +255 -101
  13. data/ext/json/ext/generator/generator.h +12 -4
  14. data/ext/json/ext/parser/extconf.rb +28 -0
  15. data/ext/json/ext/parser/parser.c +410 -462
  16. data/ext/json/ext/parser/parser.h +5 -5
  17. data/ext/json/ext/parser/parser.rl +166 -181
  18. data/ext/json/extconf.rb +1 -1
  19. data/java/src/json/ext/ByteListTranscoder.java +1 -2
  20. data/java/src/json/ext/Generator.java +39 -36
  21. data/java/src/json/ext/GeneratorMethods.java +1 -2
  22. data/java/src/json/ext/GeneratorService.java +1 -2
  23. data/java/src/json/ext/GeneratorState.java +33 -56
  24. data/java/src/json/ext/OptionsReader.java +2 -3
  25. data/java/src/json/ext/Parser.java +146 -417
  26. data/java/src/json/ext/Parser.rl +62 -126
  27. data/java/src/json/ext/ParserService.java +1 -2
  28. data/java/src/json/ext/RuntimeInfo.java +1 -6
  29. data/java/src/json/ext/StringDecoder.java +1 -2
  30. data/java/src/json/ext/StringEncoder.java +13 -2
  31. data/java/src/json/ext/Utils.java +1 -2
  32. data/json-java.gemspec +22 -7
  33. data/json.gemspec +0 -0
  34. data/json_pure.gemspec +22 -29
  35. data/lib/json/add/bigdecimal.rb +3 -2
  36. data/lib/json/add/complex.rb +4 -4
  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 -3
  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 +350 -152
  50. data/lib/json/ext.rb +0 -6
  51. data/lib/json/generic_object.rb +5 -4
  52. data/lib/json/pure/generator.rb +83 -126
  53. data/lib/json/pure/parser.rb +62 -84
  54. data/lib/json/pure.rb +2 -8
  55. data/lib/json/version.rb +2 -1
  56. data/lib/json.rb +550 -29
  57. data/references/rfc7159.txt +899 -0
  58. data/tests/fixtures/obsolete_fail1.json +1 -0
  59. data/tests/{test_json_addition.rb → json_addition_test.rb} +28 -25
  60. data/tests/json_common_interface_test.rb +169 -0
  61. data/tests/json_encoding_test.rb +107 -0
  62. data/tests/json_ext_parser_test.rb +15 -0
  63. data/tests/{test_json_fixtures.rb → json_fixtures_test.rb} +13 -8
  64. data/tests/{test_json_generate.rb → json_generator_test.rb} +134 -39
  65. data/tests/{test_json_generic_object.rb → json_generic_object_test.rb} +15 -8
  66. data/tests/json_parser_test.rb +497 -0
  67. data/tests/json_string_matching_test.rb +38 -0
  68. data/tests/test_helper.rb +17 -0
  69. data/tools/diff.sh +18 -0
  70. data/tools/fuzz.rb +1 -9
  71. metadata +47 -53
  72. data/COPYING +0 -58
  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/setup_variant.rb +0 -11
  80. data/tests/test_json.rb +0 -553
  81. data/tests/test_json_encoding.rb +0 -65
  82. data/tests/test_json_string_matching.rb +0 -39
  83. data/tests/test_json_unicode.rb +0 -72
@@ -34,13 +34,13 @@ 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;
40
+ int freeze;
42
41
  VALUE object_class;
43
42
  VALUE array_class;
43
+ VALUE decimal_class;
44
44
  int create_additions;
45
45
  VALUE match_string;
46
46
  FBuffer *fbuffer;
@@ -58,11 +58,11 @@ typedef struct JSON_ParserStruct {
58
58
 
59
59
  static UTF32 unescape_unicode(const unsigned char *p);
60
60
  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);
61
+ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
62
+ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
63
63
  static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result);
64
64
  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);
65
+ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
66
66
  static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd);
67
67
  static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result);
68
68
  static VALUE convert_encoding(VALUE source);
@@ -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,7 +44,7 @@ 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;
@@ -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, i_freeze, i_uminus;
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,16 +280,20 @@ 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
 
277
290
  %% write init;
278
291
  %% write exec;
279
292
 
293
+ if (json->freeze) {
294
+ OBJ_FREEZE(*result);
295
+ }
296
+
280
297
  if (cs >= JSON_value_first_final) {
281
298
  return p;
282
299
  } else {
@@ -328,6 +345,19 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
328
345
  ) (^[0-9Ee.\-]? @exit );
329
346
  }%%
330
347
 
348
+ static int is_bigdecimal_class(VALUE obj)
349
+ {
350
+ if (cBigDecimal == Qundef) {
351
+ if (rb_const_defined(rb_cObject, i_BigDecimal)) {
352
+ cBigDecimal = rb_const_get_at(rb_cObject, i_BigDecimal);
353
+ }
354
+ else {
355
+ return 0;
356
+ }
357
+ }
358
+ return obj == cBigDecimal;
359
+ }
360
+
331
361
  static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
332
362
  {
333
363
  int cs = EVIL;
@@ -341,7 +371,17 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
341
371
  fbuffer_clear(json->fbuffer);
342
372
  fbuffer_append(json->fbuffer, json->memo, len);
343
373
  fbuffer_append_char(json->fbuffer, '\0');
344
- *result = rb_float_new(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
374
+ if (NIL_P(json->decimal_class)) {
375
+ *result = rb_float_new(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
376
+ } else {
377
+ VALUE text;
378
+ text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
379
+ if (is_bigdecimal_class(json->decimal_class)) {
380
+ *result = rb_funcall(Qnil, i_BigDecimal, 1, text);
381
+ } else {
382
+ *result = rb_funcall(json->decimal_class, i_new, 1, text);
383
+ }
384
+ }
345
385
  return p + 1;
346
386
  } else {
347
387
  return NULL;
@@ -357,7 +397,7 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
357
397
 
358
398
  action parse_value {
359
399
  VALUE v = Qnil;
360
- char *np = JSON_parse_value(json, fpc, pe, &v);
400
+ char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
361
401
  if (np == NULL) {
362
402
  fhold; fbreak;
363
403
  } else {
@@ -380,13 +420,13 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
380
420
  end_array @exit;
381
421
  }%%
382
422
 
383
- static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result)
423
+ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
384
424
  {
385
425
  int cs = EVIL;
386
426
  VALUE array_class = json->array_class;
387
427
 
388
- if (json->max_nesting && json->current_nesting > json->max_nesting) {
389
- rb_raise(eNestingError, "nesting of %d is too deep", json->current_nesting);
428
+ if (json->max_nesting && current_nesting > json->max_nesting) {
429
+ rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
390
430
  }
391
431
  *result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
392
432
 
@@ -396,7 +436,7 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
396
436
  if(cs >= JSON_array_first_final) {
397
437
  return p + 1;
398
438
  } else {
399
- rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
439
+ rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
400
440
  return NULL;
401
441
  }
402
442
  }
@@ -436,13 +476,21 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
436
476
  break;
437
477
  case 'u':
438
478
  if (pe > stringEnd - 4) {
439
- return Qnil;
479
+ rb_enc_raise(
480
+ EXC_ENCODING eParserError,
481
+ "%u: incomplete unicode character escape sequence at '%s'", __LINE__, p
482
+ );
440
483
  } else {
441
484
  UTF32 ch = unescape_unicode((unsigned char *) ++pe);
442
485
  pe += 3;
443
486
  if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
444
487
  pe++;
445
- if (pe > stringEnd - 6) return Qnil;
488
+ if (pe > stringEnd - 6) {
489
+ rb_enc_raise(
490
+ EXC_ENCODING eParserError,
491
+ "%u: incomplete surrogate pair at '%s'", __LINE__, p
492
+ );
493
+ }
446
494
  if (pe[0] == '\\' && pe[1] == 'u') {
447
495
  UTF32 sur = unescape_unicode((unsigned char *) pe + 2);
448
496
  ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16)
@@ -528,6 +576,23 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
528
576
 
529
577
  if (json->symbolize_names && json->parsing_name) {
530
578
  *result = rb_str_intern(*result);
579
+ } else if (RB_TYPE_P(*result, T_STRING)) {
580
+ # if STR_UMINUS_DEDUPE_FROZEN
581
+ if (json->freeze) {
582
+ // Starting from MRI 2.8 it is preferable to freeze the string
583
+ // before deduplication so that it can be interned directly
584
+ // otherwise it would be duplicated first which is wasteful.
585
+ *result = rb_funcall(rb_str_freeze(*result), i_uminus, 0);
586
+ }
587
+ # elif STR_UMINUS_DEDUPE
588
+ if (json->freeze) {
589
+ // MRI 2.5 and older do not deduplicate strings that are already
590
+ // frozen.
591
+ *result = rb_funcall(*result, i_uminus, 0);
592
+ }
593
+ # else
594
+ rb_str_resize(*result, RSTRING_LEN(*result));
595
+ # endif
531
596
  }
532
597
  if (cs >= JSON_string_first_final) {
533
598
  return p + 1;
@@ -550,41 +615,16 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
550
615
 
551
616
  static VALUE convert_encoding(VALUE source)
552
617
  {
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
618
  #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);
619
+ rb_encoding *enc = rb_enc_get(source);
620
+ if (enc == rb_ascii8bit_encoding()) {
621
+ if (OBJ_FROZEN(source)) {
622
+ source = rb_str_dup(source);
587
623
  }
624
+ FORCE_UTF8(source);
625
+ } else {
626
+ source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding());
627
+ }
588
628
  #endif
589
629
  return source;
590
630
  }
@@ -607,8 +647,9 @@ static VALUE convert_encoding(VALUE source)
607
647
  * defiance of RFC 4627 to be parsed by the Parser. This option defaults to
608
648
  * false.
609
649
  * * *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.
650
+ * (keys) in a JSON object. Otherwise strings are returned, which is
651
+ * also the default. It's not possible to use this option in
652
+ * conjunction with the *create_additions* option.
612
653
  * * *create_additions*: If set to false, the Parser doesn't create
613
654
  * additions even if a matching class and create_id was found. This option
614
655
  * defaults to false.
@@ -623,12 +664,18 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
623
664
  if (json->Vsource) {
624
665
  rb_raise(rb_eTypeError, "already initialized instance");
625
666
  }
667
+ #ifdef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
668
+ rb_scan_args(argc, argv, "1:", &source, &opts);
669
+ #else
626
670
  rb_scan_args(argc, argv, "11", &source, &opts);
671
+ #endif
627
672
  if (!NIL_P(opts)) {
673
+ #ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
628
674
  opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
629
675
  if (NIL_P(opts)) {
630
676
  rb_raise(rb_eArgError, "opts needs to be like a hash");
631
677
  } else {
678
+ #endif
632
679
  VALUE tmp = ID2SYM(i_max_nesting);
633
680
  if (option_given_p(opts, tmp)) {
634
681
  VALUE max_nesting = rb_hash_aref(opts, tmp);
@@ -653,12 +700,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
653
700
  } else {
654
701
  json->symbolize_names = 0;
655
702
  }
656
- tmp = ID2SYM(i_quirks_mode);
703
+ tmp = ID2SYM(i_freeze);
657
704
  if (option_given_p(opts, tmp)) {
658
- VALUE quirks_mode = rb_hash_aref(opts, tmp);
659
- json->quirks_mode = RTEST(quirks_mode) ? 1 : 0;
705
+ json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
660
706
  } else {
661
- json->quirks_mode = 0;
707
+ json->freeze = 0;
662
708
  }
663
709
  tmp = ID2SYM(i_create_additions);
664
710
  if (option_given_p(opts, tmp)) {
@@ -666,6 +712,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
666
712
  } else {
667
713
  json->create_additions = 0;
668
714
  }
715
+ if (json->symbolize_names && json->create_additions) {
716
+ rb_raise(rb_eArgError,
717
+ "options :symbolize_names and :create_additions cannot be "
718
+ " used in conjunction");
719
+ }
669
720
  tmp = ID2SYM(i_create_id);
670
721
  if (option_given_p(opts, tmp)) {
671
722
  json->create_id = rb_hash_aref(opts, tmp);
@@ -684,6 +735,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
684
735
  } else {
685
736
  json->array_class = Qnil;
686
737
  }
738
+ tmp = ID2SYM(i_decimal_class);
739
+ if (option_given_p(opts, tmp)) {
740
+ json->decimal_class = rb_hash_aref(opts, tmp);
741
+ } else {
742
+ json->decimal_class = Qnil;
743
+ }
687
744
  tmp = ID2SYM(i_match_string);
688
745
  if (option_given_p(opts, tmp)) {
689
746
  VALUE match_string = rb_hash_aref(opts, tmp);
@@ -691,20 +748,19 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
691
748
  } else {
692
749
  json->match_string = Qnil;
693
750
  }
751
+ #ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
694
752
  }
753
+ #endif
695
754
  } else {
696
755
  json->max_nesting = 100;
697
756
  json->allow_nan = 0;
698
- json->create_additions = 1;
757
+ json->create_additions = 0;
699
758
  json->create_id = rb_funcall(mJSON, i_create_id, 0);
700
759
  json->object_class = Qnil;
701
760
  json->array_class = Qnil;
761
+ json->decimal_class = Qnil;
702
762
  }
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;
763
+ source = convert_encoding(StringValue(source));
708
764
  StringValue(source);
709
765
  json->len = RSTRING_LEN(source);
710
766
  json->source = RSTRING_PTR(source);;
@@ -719,56 +775,8 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
719
775
 
720
776
  include JSON_common;
721
777
 
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
778
  action parse_value {
771
- char *np = JSON_parse_value(json, fpc, pe, &result);
779
+ char *np = JSON_parse_value(json, fpc, pe, &result, 0);
772
780
  if (np == NULL) { fhold; fbreak; } else fexec np;
773
781
  }
774
782
 
@@ -777,26 +785,6 @@ static VALUE cParser_parse_strict(VALUE self)
777
785
  ) ignore*;
778
786
  }%%
779
787
 
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
788
  /*
801
789
  * call-seq: parse()
802
790
  *
@@ -805,12 +793,21 @@ static VALUE cParser_parse_quirks_mode(VALUE self)
805
793
  */
806
794
  static VALUE cParser_parse(VALUE self)
807
795
  {
796
+ char *p, *pe;
797
+ int cs = EVIL;
798
+ VALUE result = Qnil;
808
799
  GET_PARSER;
809
800
 
810
- if (json->quirks_mode) {
811
- return cParser_parse_quirks_mode(self);
801
+ %% write init;
802
+ p = json->source;
803
+ pe = p + json->len;
804
+ %% write exec;
805
+
806
+ if (cs >= JSON_first_final && p == pe) {
807
+ return result;
812
808
  } else {
813
- return cParser_parse_strict(self);
809
+ rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
810
+ return Qnil;
814
811
  }
815
812
  }
816
813
 
@@ -821,6 +818,7 @@ static void JSON_mark(void *ptr)
821
818
  rb_gc_mark_maybe(json->create_id);
822
819
  rb_gc_mark_maybe(json->object_class);
823
820
  rb_gc_mark_maybe(json->array_class);
821
+ rb_gc_mark_maybe(json->decimal_class);
824
822
  rb_gc_mark_maybe(json->match_string);
825
823
  }
826
824
 
@@ -868,35 +866,30 @@ static VALUE cParser_source(VALUE self)
868
866
  return rb_str_dup(json->Vsource);
869
867
  }
870
868
 
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
869
  void Init_parser(void)
884
870
  {
871
+ #undef rb_intern
885
872
  rb_require("json/common");
886
873
  mJSON = rb_define_module("JSON");
887
874
  mExt = rb_define_module_under(mJSON, "Ext");
888
875
  cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
889
876
  eParserError = rb_path2class("JSON::ParserError");
890
877
  eNestingError = rb_path2class("JSON::NestingError");
878
+ rb_gc_register_mark_object(eParserError);
879
+ rb_gc_register_mark_object(eNestingError);
891
880
  rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
892
881
  rb_define_method(cParser, "initialize", cParser_initialize, -1);
893
882
  rb_define_method(cParser, "parse", cParser_parse, 0);
894
883
  rb_define_method(cParser, "source", cParser_source, 0);
895
- rb_define_method(cParser, "quirks_mode?", cParser_quirks_mode_p, 0);
896
884
 
897
885
  CNaN = rb_const_get(mJSON, rb_intern("NaN"));
886
+ rb_gc_register_mark_object(CNaN);
887
+
898
888
  CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
889
+ rb_gc_register_mark_object(CInfinity);
890
+
899
891
  CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
892
+ rb_gc_register_mark_object(CMinusInfinity);
900
893
 
901
894
  i_json_creatable_p = rb_intern("json_creatable?");
902
895
  i_json_create = rb_intern("json_create");
@@ -906,9 +899,9 @@ void Init_parser(void)
906
899
  i_max_nesting = rb_intern("max_nesting");
907
900
  i_allow_nan = rb_intern("allow_nan");
908
901
  i_symbolize_names = rb_intern("symbolize_names");
909
- i_quirks_mode = rb_intern("quirks_mode");
910
902
  i_object_class = rb_intern("object_class");
911
903
  i_array_class = rb_intern("array_class");
904
+ i_decimal_class = rb_intern("decimal_class");
912
905
  i_match = rb_intern("match");
913
906
  i_match_string = rb_intern("match_string");
914
907
  i_key_p = rb_intern("key?");
@@ -916,18 +909,10 @@ void Init_parser(void)
916
909
  i_aset = rb_intern("[]=");
917
910
  i_aref = rb_intern("[]");
918
911
  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
912
+ i_new = rb_intern("new");
913
+ i_BigDecimal = rb_intern("BigDecimal");
914
+ i_freeze = rb_intern("freeze");
915
+ i_uminus = rb_intern("-@");
931
916
  }
932
917
 
933
918
  /*
data/ext/json/extconf.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  require 'mkmf'
2
- create_makefile('json')
3
2
 
3
+ create_makefile('json')
@@ -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