json 1.8.0 → 2.6.2

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 (110) hide show
  1. checksums.yaml +5 -5
  2. data/{CHANGES → CHANGES.md} +262 -87
  3. data/{COPYING-json-jruby → LICENSE} +5 -6
  4. data/README.md +425 -0
  5. data/VERSION +1 -1
  6. data/ext/json/ext/fbuffer/fbuffer.h +10 -4
  7. data/ext/json/ext/generator/extconf.rb +0 -10
  8. data/ext/json/ext/generator/generator.c +308 -135
  9. data/ext/json/ext/generator/generator.h +35 -9
  10. data/ext/json/ext/parser/extconf.rb +25 -6
  11. data/ext/json/ext/parser/parser.c +3044 -1901
  12. data/ext/json/ext/parser/parser.h +29 -10
  13. data/ext/json/ext/parser/parser.rl +270 -211
  14. data/ext/json/extconf.rb +3 -0
  15. data/json.gemspec +57 -27
  16. data/lib/json/add/bigdecimal.rb +3 -2
  17. data/lib/json/add/complex.rb +9 -3
  18. data/lib/json/add/core.rb +1 -0
  19. data/lib/json/add/date.rb +1 -1
  20. data/lib/json/add/date_time.rb +1 -1
  21. data/lib/json/add/exception.rb +1 -1
  22. data/lib/json/add/ostruct.rb +3 -3
  23. data/lib/json/add/range.rb +1 -1
  24. data/lib/json/add/rational.rb +8 -3
  25. data/lib/json/add/regexp.rb +3 -3
  26. data/lib/json/add/set.rb +29 -0
  27. data/lib/json/add/struct.rb +1 -1
  28. data/lib/json/add/symbol.rb +1 -1
  29. data/lib/json/add/time.rb +2 -2
  30. data/lib/json/common.rb +383 -167
  31. data/lib/json/ext.rb +0 -6
  32. data/lib/json/generic_object.rb +5 -4
  33. data/lib/json/pure/generator.rb +83 -126
  34. data/lib/json/pure/parser.rb +63 -85
  35. data/lib/json/pure.rb +2 -8
  36. data/lib/json/version.rb +2 -1
  37. data/lib/json.rb +550 -29
  38. metadata +29 -136
  39. data/.gitignore +0 -12
  40. data/.travis.yml +0 -20
  41. data/COPYING +0 -58
  42. data/GPL +0 -340
  43. data/Gemfile +0 -11
  44. data/README-json-jruby.markdown +0 -33
  45. data/README.rdoc +0 -358
  46. data/Rakefile +0 -412
  47. data/TODO +0 -1
  48. data/data/example.json +0 -1
  49. data/data/index.html +0 -38
  50. data/data/prototype.js +0 -4184
  51. data/diagrams/.keep +0 -0
  52. data/install.rb +0 -23
  53. data/java/src/json/ext/ByteListTranscoder.java +0 -167
  54. data/java/src/json/ext/Generator.java +0 -444
  55. data/java/src/json/ext/GeneratorMethods.java +0 -232
  56. data/java/src/json/ext/GeneratorService.java +0 -43
  57. data/java/src/json/ext/GeneratorState.java +0 -543
  58. data/java/src/json/ext/OptionsReader.java +0 -114
  59. data/java/src/json/ext/Parser.java +0 -2644
  60. data/java/src/json/ext/Parser.rl +0 -968
  61. data/java/src/json/ext/ParserService.java +0 -35
  62. data/java/src/json/ext/RuntimeInfo.java +0 -121
  63. data/java/src/json/ext/StringDecoder.java +0 -167
  64. data/java/src/json/ext/StringEncoder.java +0 -106
  65. data/java/src/json/ext/Utils.java +0 -89
  66. data/json-java.gemspec +0 -23
  67. data/json_pure.gemspec +0 -39
  68. data/lib/json/ext/.keep +0 -0
  69. data/tests/fixtures/fail1.json +0 -1
  70. data/tests/fixtures/fail10.json +0 -1
  71. data/tests/fixtures/fail11.json +0 -1
  72. data/tests/fixtures/fail12.json +0 -1
  73. data/tests/fixtures/fail13.json +0 -1
  74. data/tests/fixtures/fail14.json +0 -1
  75. data/tests/fixtures/fail18.json +0 -1
  76. data/tests/fixtures/fail19.json +0 -1
  77. data/tests/fixtures/fail2.json +0 -1
  78. data/tests/fixtures/fail20.json +0 -1
  79. data/tests/fixtures/fail21.json +0 -1
  80. data/tests/fixtures/fail22.json +0 -1
  81. data/tests/fixtures/fail23.json +0 -1
  82. data/tests/fixtures/fail24.json +0 -1
  83. data/tests/fixtures/fail25.json +0 -1
  84. data/tests/fixtures/fail27.json +0 -2
  85. data/tests/fixtures/fail28.json +0 -2
  86. data/tests/fixtures/fail3.json +0 -1
  87. data/tests/fixtures/fail4.json +0 -1
  88. data/tests/fixtures/fail5.json +0 -1
  89. data/tests/fixtures/fail6.json +0 -1
  90. data/tests/fixtures/fail7.json +0 -1
  91. data/tests/fixtures/fail8.json +0 -1
  92. data/tests/fixtures/fail9.json +0 -1
  93. data/tests/fixtures/pass1.json +0 -56
  94. data/tests/fixtures/pass15.json +0 -1
  95. data/tests/fixtures/pass16.json +0 -1
  96. data/tests/fixtures/pass17.json +0 -1
  97. data/tests/fixtures/pass2.json +0 -1
  98. data/tests/fixtures/pass26.json +0 -1
  99. data/tests/fixtures/pass3.json +0 -6
  100. data/tests/setup_variant.rb +0 -11
  101. data/tests/test_json.rb +0 -545
  102. data/tests/test_json_addition.rb +0 -196
  103. data/tests/test_json_encoding.rb +0 -65
  104. data/tests/test_json_fixtures.rb +0 -35
  105. data/tests/test_json_generate.rb +0 -322
  106. data/tests/test_json_generic_object.rb +0 -75
  107. data/tests/test_json_string_matching.rb +0 -39
  108. data/tests/test_json_unicode.rb +0 -72
  109. data/tools/fuzz.rb +0 -139
  110. data/tools/server.rb +0 -62
@@ -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,14 @@ 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;
78
92
 
79
93
  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;
94
+ i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
95
+ i_object_class, i_array_class, i_decimal_class, i_key_p,
96
+ i_deep_const_get, i_match, i_match_string, i_aset, i_aref,
97
+ i_leftshift, i_new, i_try_convert, i_freeze, i_uminus;
83
98
 
84
99
  %%{
85
100
  machine JSON_common;
@@ -117,11 +132,12 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
117
132
 
118
133
  action parse_value {
119
134
  VALUE v = Qnil;
120
- char *np = JSON_parse_value(json, fpc, pe, &v);
135
+ char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
121
136
  if (np == NULL) {
122
137
  fhold; fbreak;
123
138
  } else {
124
139
  if (NIL_P(json->object_class)) {
140
+ OBJ_FREEZE(last_name);
125
141
  rb_hash_aset(*result, last_name, v);
126
142
  } else {
127
143
  rb_funcall(*result, i_aset, 2, last_name, v);
@@ -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,16 +279,20 @@ 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
 
277
289
  %% write init;
278
290
  %% write exec;
279
291
 
292
+ if (json->freeze) {
293
+ OBJ_FREEZE(*result);
294
+ }
295
+
280
296
  if (cs >= JSON_value_first_final) {
281
297
  return p;
282
298
  } else {
@@ -337,11 +353,46 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
337
353
  %% write exec;
338
354
 
339
355
  if (cs >= JSON_float_first_final) {
356
+ VALUE mod = Qnil;
357
+ ID method_id = 0;
358
+ if (rb_respond_to(json->decimal_class, i_try_convert)) {
359
+ mod = json->decimal_class;
360
+ method_id = i_try_convert;
361
+ } else if (rb_respond_to(json->decimal_class, i_new)) {
362
+ mod = json->decimal_class;
363
+ method_id = i_new;
364
+ } else if (RB_TYPE_P(json->decimal_class, T_CLASS)) {
365
+ VALUE name = rb_class_name(json->decimal_class);
366
+ const char *name_cstr = RSTRING_PTR(name);
367
+ const char *last_colon = strrchr(name_cstr, ':');
368
+ if (last_colon) {
369
+ const char *mod_path_end = last_colon - 1;
370
+ VALUE mod_path = rb_str_substr(name, 0, mod_path_end - name_cstr);
371
+ mod = rb_path_to_class(mod_path);
372
+
373
+ const char *method_name_beg = last_colon + 1;
374
+ long before_len = method_name_beg - name_cstr;
375
+ long len = RSTRING_LEN(name) - before_len;
376
+ VALUE method_name = rb_str_substr(name, before_len, len);
377
+ method_id = SYM2ID(rb_str_intern(method_name));
378
+ } else {
379
+ mod = rb_mKernel;
380
+ method_id = SYM2ID(rb_str_intern(name));
381
+ }
382
+ }
383
+
340
384
  long len = p - json->memo;
341
385
  fbuffer_clear(json->fbuffer);
342
386
  fbuffer_append(json->fbuffer, json->memo, len);
343
387
  fbuffer_append_char(json->fbuffer, '\0');
344
- *result = rb_float_new(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
388
+
389
+ if (method_id) {
390
+ VALUE text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
391
+ *result = rb_funcallv(mod, method_id, 1, &text);
392
+ } else {
393
+ *result = DBL2NUM(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
394
+ }
395
+
345
396
  return p + 1;
346
397
  } else {
347
398
  return NULL;
@@ -357,7 +408,7 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
357
408
 
358
409
  action parse_value {
359
410
  VALUE v = Qnil;
360
- char *np = JSON_parse_value(json, fpc, pe, &v);
411
+ char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
361
412
  if (np == NULL) {
362
413
  fhold; fbreak;
363
414
  } else {
@@ -380,13 +431,13 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
380
431
  end_array @exit;
381
432
  }%%
382
433
 
383
- static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result)
434
+ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
384
435
  {
385
436
  int cs = EVIL;
386
437
  VALUE array_class = json->array_class;
387
438
 
388
- if (json->max_nesting && json->current_nesting > json->max_nesting) {
389
- rb_raise(eNestingError, "nesting of %d is too deep", json->current_nesting);
439
+ if (json->max_nesting && current_nesting > json->max_nesting) {
440
+ rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
390
441
  }
391
442
  *result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
392
443
 
@@ -396,22 +447,42 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
396
447
  if(cs >= JSON_array_first_final) {
397
448
  return p + 1;
398
449
  } else {
399
- rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
450
+ rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
400
451
  return NULL;
401
452
  }
402
453
  }
403
454
 
404
- static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
455
+ static const size_t MAX_STACK_BUFFER_SIZE = 128;
456
+ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int symbolize)
405
457
  {
406
- char *p = string, *pe = string, *unescape;
458
+ VALUE result = Qnil;
459
+ size_t bufferSize = stringEnd - string;
460
+ char *p = string, *pe = string, *unescape, *bufferStart, *buffer;
407
461
  int unescape_len;
408
462
  char buf[4];
409
463
 
464
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
465
+ # ifdef HAVE_RB_ENC_INTERNED_STR
466
+ bufferStart = buffer = ALLOC_N(char, bufferSize ? bufferSize : 1);
467
+ # else
468
+ bufferStart = buffer = ALLOC_N(char, bufferSize);
469
+ # endif
470
+ } else {
471
+ # ifdef HAVE_RB_ENC_INTERNED_STR
472
+ bufferStart = buffer = ALLOCA_N(char, bufferSize ? bufferSize : 1);
473
+ # else
474
+ bufferStart = buffer = ALLOCA_N(char, bufferSize);
475
+ # endif
476
+ }
477
+
410
478
  while (pe < stringEnd) {
411
479
  if (*pe == '\\') {
412
480
  unescape = (char *) "?";
413
481
  unescape_len = 1;
414
- if (pe > p) rb_str_buf_cat(result, p, pe - p);
482
+ if (pe > p) {
483
+ MEMCPY(buffer, p, char, pe - p);
484
+ buffer += pe - p;
485
+ }
415
486
  switch (*++pe) {
416
487
  case 'n':
417
488
  unescape = (char *) "\n";
@@ -436,13 +507,27 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
436
507
  break;
437
508
  case 'u':
438
509
  if (pe > stringEnd - 4) {
439
- return Qnil;
510
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
511
+ free(bufferStart);
512
+ }
513
+ rb_enc_raise(
514
+ EXC_ENCODING eParserError,
515
+ "%u: incomplete unicode character escape sequence at '%s'", __LINE__, p
516
+ );
440
517
  } else {
441
518
  UTF32 ch = unescape_unicode((unsigned char *) ++pe);
442
519
  pe += 3;
443
520
  if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
444
521
  pe++;
445
- if (pe > stringEnd - 6) return Qnil;
522
+ if (pe > stringEnd - 6) {
523
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
524
+ free(bufferStart);
525
+ }
526
+ rb_enc_raise(
527
+ EXC_ENCODING eParserError,
528
+ "%u: incomplete surrogate pair at '%s'", __LINE__, p
529
+ );
530
+ }
446
531
  if (pe[0] == '\\' && pe[1] == 'u') {
447
532
  UTF32 sur = unescape_unicode((unsigned char *) pe + 2);
448
533
  ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16)
@@ -461,13 +546,55 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
461
546
  p = pe;
462
547
  continue;
463
548
  }
464
- rb_str_buf_cat(result, unescape, unescape_len);
549
+ MEMCPY(buffer, unescape, char, unescape_len);
550
+ buffer += unescape_len;
465
551
  p = ++pe;
466
552
  } else {
467
553
  pe++;
468
554
  }
469
555
  }
470
- rb_str_buf_cat(result, p, pe - p);
556
+
557
+ if (pe > p) {
558
+ MEMCPY(buffer, p, char, pe - p);
559
+ buffer += pe - p;
560
+ }
561
+
562
+ # ifdef HAVE_RB_ENC_INTERNED_STR
563
+ if (intern) {
564
+ result = rb_enc_interned_str(bufferStart, (long)(buffer - bufferStart), rb_utf8_encoding());
565
+ } else {
566
+ result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
567
+ }
568
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
569
+ free(bufferStart);
570
+ }
571
+ # else
572
+ result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
573
+
574
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
575
+ free(bufferStart);
576
+ }
577
+
578
+ if (intern) {
579
+ # if STR_UMINUS_DEDUPE_FROZEN
580
+ // Starting from MRI 2.8 it is preferable to freeze the string
581
+ // before deduplication so that it can be interned directly
582
+ // otherwise it would be duplicated first which is wasteful.
583
+ result = rb_funcall(rb_str_freeze(result), i_uminus, 0);
584
+ # elif STR_UMINUS_DEDUPE
585
+ // MRI 2.5 and older do not deduplicate strings that are already
586
+ // frozen.
587
+ result = rb_funcall(result, i_uminus, 0);
588
+ # else
589
+ result = rb_str_freeze(result);
590
+ # endif
591
+ }
592
+ # endif
593
+
594
+ if (symbolize) {
595
+ result = rb_str_intern(result);
596
+ }
597
+
471
598
  return result;
472
599
  }
473
600
 
@@ -478,12 +605,11 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
478
605
  write data;
479
606
 
480
607
  action parse_string {
481
- *result = json_string_unescape(*result, json->memo + 1, p);
608
+ *result = json_string_unescape(json->memo + 1, p, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names);
482
609
  if (NIL_P(*result)) {
483
610
  fhold;
484
611
  fbreak;
485
612
  } else {
486
- FORCE_UTF8(*result);
487
613
  fexec p + 1;
488
614
  }
489
615
  }
@@ -510,7 +636,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
510
636
  int cs = EVIL;
511
637
  VALUE match_string;
512
638
 
513
- *result = rb_str_buf_new(0);
514
639
  %% write init;
515
640
  json->memo = p;
516
641
  %% write exec;
@@ -526,9 +651,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
526
651
  }
527
652
  }
528
653
 
529
- if (json->symbolize_names && json->parsing_name) {
530
- *result = rb_str_intern(*result);
531
- }
532
654
  if (cs >= JSON_string_first_final) {
533
655
  return p + 1;
534
656
  } else {
@@ -550,41 +672,16 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
550
672
 
551
673
  static VALUE convert_encoding(VALUE source)
552
674
  {
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
675
  #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);
676
+ rb_encoding *enc = rb_enc_get(source);
677
+ if (enc == rb_ascii8bit_encoding()) {
678
+ if (OBJ_FROZEN(source)) {
679
+ source = rb_str_dup(source);
587
680
  }
681
+ FORCE_UTF8(source);
682
+ } else {
683
+ source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding());
684
+ }
588
685
  #endif
589
686
  return source;
590
687
  }
@@ -607,11 +704,12 @@ static VALUE convert_encoding(VALUE source)
607
704
  * defiance of RFC 4627 to be parsed by the Parser. This option defaults to
608
705
  * false.
609
706
  * * *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.
707
+ * (keys) in a JSON object. Otherwise strings are returned, which is
708
+ * also the default. It's not possible to use this option in
709
+ * conjunction with the *create_additions* option.
612
710
  * * *create_additions*: If set to false, the Parser doesn't create
613
- * additions even if a matchin class and create_id was found. This option
614
- * defaults to true.
711
+ * additions even if a matching class and create_id was found. This option
712
+ * defaults to false.
615
713
  * * *object_class*: Defaults to Hash
616
714
  * * *array_class*: Defaults to Array
617
715
  */
@@ -623,12 +721,18 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
623
721
  if (json->Vsource) {
624
722
  rb_raise(rb_eTypeError, "already initialized instance");
625
723
  }
724
+ #ifdef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
725
+ rb_scan_args(argc, argv, "1:", &source, &opts);
726
+ #else
626
727
  rb_scan_args(argc, argv, "11", &source, &opts);
728
+ #endif
627
729
  if (!NIL_P(opts)) {
730
+ #ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
628
731
  opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
629
732
  if (NIL_P(opts)) {
630
733
  rb_raise(rb_eArgError, "opts needs to be like a hash");
631
734
  } else {
735
+ #endif
632
736
  VALUE tmp = ID2SYM(i_max_nesting);
633
737
  if (option_given_p(opts, tmp)) {
634
738
  VALUE max_nesting = rb_hash_aref(opts, tmp);
@@ -653,12 +757,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
653
757
  } else {
654
758
  json->symbolize_names = 0;
655
759
  }
656
- tmp = ID2SYM(i_quirks_mode);
760
+ tmp = ID2SYM(i_freeze);
657
761
  if (option_given_p(opts, tmp)) {
658
- VALUE quirks_mode = rb_hash_aref(opts, tmp);
659
- json->quirks_mode = RTEST(quirks_mode) ? 1 : 0;
762
+ json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
660
763
  } else {
661
- json->quirks_mode = 0;
764
+ json->freeze = 0;
662
765
  }
663
766
  tmp = ID2SYM(i_create_additions);
664
767
  if (option_given_p(opts, tmp)) {
@@ -666,6 +769,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
666
769
  } else {
667
770
  json->create_additions = 0;
668
771
  }
772
+ if (json->symbolize_names && json->create_additions) {
773
+ rb_raise(rb_eArgError,
774
+ "options :symbolize_names and :create_additions cannot be "
775
+ " used in conjunction");
776
+ }
669
777
  tmp = ID2SYM(i_create_id);
670
778
  if (option_given_p(opts, tmp)) {
671
779
  json->create_id = rb_hash_aref(opts, tmp);
@@ -684,6 +792,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
684
792
  } else {
685
793
  json->array_class = Qnil;
686
794
  }
795
+ tmp = ID2SYM(i_decimal_class);
796
+ if (option_given_p(opts, tmp)) {
797
+ json->decimal_class = rb_hash_aref(opts, tmp);
798
+ } else {
799
+ json->decimal_class = Qnil;
800
+ }
687
801
  tmp = ID2SYM(i_match_string);
688
802
  if (option_given_p(opts, tmp)) {
689
803
  VALUE match_string = rb_hash_aref(opts, tmp);
@@ -691,20 +805,19 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
691
805
  } else {
692
806
  json->match_string = Qnil;
693
807
  }
808
+ #ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
694
809
  }
810
+ #endif
695
811
  } else {
696
812
  json->max_nesting = 100;
697
813
  json->allow_nan = 0;
698
- json->create_additions = 1;
814
+ json->create_additions = 0;
699
815
  json->create_id = rb_funcall(mJSON, i_create_id, 0);
700
816
  json->object_class = Qnil;
701
817
  json->array_class = Qnil;
818
+ json->decimal_class = Qnil;
702
819
  }
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;
820
+ source = convert_encoding(StringValue(source));
708
821
  StringValue(source);
709
822
  json->len = RSTRING_LEN(source);
710
823
  json->source = RSTRING_PTR(source);;
@@ -719,56 +832,8 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
719
832
 
720
833
  include JSON_common;
721
834
 
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
835
  action parse_value {
771
- char *np = JSON_parse_value(json, fpc, pe, &result);
836
+ char *np = JSON_parse_value(json, fpc, pe, &result, 0);
772
837
  if (np == NULL) { fhold; fbreak; } else fexec np;
773
838
  }
774
839
 
@@ -777,71 +842,74 @@ static VALUE cParser_parse_strict(VALUE self)
777
842
  ) ignore*;
778
843
  }%%
779
844
 
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
845
  /*
801
846
  * call-seq: parse()
802
847
  *
803
848
  * Parses the current JSON text _source_ and returns the complete data
804
849
  * structure as a result.
850
+ * It raises JSON::ParseError if fail to parse.
805
851
  */
806
852
  static VALUE cParser_parse(VALUE self)
807
853
  {
854
+ char *p, *pe;
855
+ int cs = EVIL;
856
+ VALUE result = Qnil;
808
857
  GET_PARSER;
809
858
 
810
- if (json->quirks_mode) {
811
- return cParser_parse_quirks_mode(self);
859
+ %% write init;
860
+ p = json->source;
861
+ pe = p + json->len;
862
+ %% write exec;
863
+
864
+ if (cs >= JSON_first_final && p == pe) {
865
+ return result;
812
866
  } else {
813
- return cParser_parse_strict(self);
867
+ rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
868
+ return Qnil;
814
869
  }
815
870
  }
816
871
 
817
-
818
- static JSON_Parser *JSON_allocate()
819
- {
820
- JSON_Parser *json = ALLOC(JSON_Parser);
821
- MEMZERO(json, JSON_Parser, 1);
822
- json->fbuffer = fbuffer_alloc(0);
823
- return json;
824
- }
825
-
826
- static void JSON_mark(JSON_Parser *json)
872
+ static void JSON_mark(void *ptr)
827
873
  {
874
+ JSON_Parser *json = ptr;
828
875
  rb_gc_mark_maybe(json->Vsource);
829
876
  rb_gc_mark_maybe(json->create_id);
830
877
  rb_gc_mark_maybe(json->object_class);
831
878
  rb_gc_mark_maybe(json->array_class);
879
+ rb_gc_mark_maybe(json->decimal_class);
832
880
  rb_gc_mark_maybe(json->match_string);
833
881
  }
834
882
 
835
- static void JSON_free(JSON_Parser *json)
883
+ static void JSON_free(void *ptr)
836
884
  {
885
+ JSON_Parser *json = ptr;
837
886
  fbuffer_free(json->fbuffer);
838
887
  ruby_xfree(json);
839
888
  }
840
889
 
890
+ static size_t JSON_memsize(const void *ptr)
891
+ {
892
+ const JSON_Parser *json = ptr;
893
+ return sizeof(*json) + FBUFFER_CAPA(json->fbuffer);
894
+ }
895
+
896
+ #ifdef NEW_TYPEDDATA_WRAPPER
897
+ static const rb_data_type_t JSON_Parser_type = {
898
+ "JSON/Parser",
899
+ {JSON_mark, JSON_free, JSON_memsize,},
900
+ #ifdef RUBY_TYPED_FREE_IMMEDIATELY
901
+ 0, 0,
902
+ RUBY_TYPED_FREE_IMMEDIATELY,
903
+ #endif
904
+ };
905
+ #endif
906
+
841
907
  static VALUE cJSON_parser_s_allocate(VALUE klass)
842
908
  {
843
- JSON_Parser *json = JSON_allocate();
844
- return Data_Wrap_Struct(klass, JSON_mark, JSON_free, json);
909
+ JSON_Parser *json;
910
+ VALUE obj = TypedData_Make_Struct(klass, JSON_Parser, &JSON_Parser_type, json);
911
+ json->fbuffer = fbuffer_alloc(0);
912
+ return obj;
845
913
  }
846
914
 
847
915
  /*
@@ -856,35 +924,34 @@ static VALUE cParser_source(VALUE self)
856
924
  return rb_str_dup(json->Vsource);
857
925
  }
858
926
 
859
- /*
860
- * call-seq: quirks_mode?()
861
- *
862
- * Returns a true, if this parser is in quirks_mode, false otherwise.
863
- */
864
- static VALUE cParser_quirks_mode_p(VALUE self)
927
+ void Init_parser(void)
865
928
  {
866
- GET_PARSER;
867
- return json->quirks_mode ? Qtrue : Qfalse;
868
- }
869
-
929
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
930
+ rb_ext_ractor_safe(true);
931
+ #endif
870
932
 
871
- void Init_parser()
872
- {
933
+ #undef rb_intern
873
934
  rb_require("json/common");
874
935
  mJSON = rb_define_module("JSON");
875
936
  mExt = rb_define_module_under(mJSON, "Ext");
876
937
  cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
877
938
  eParserError = rb_path2class("JSON::ParserError");
878
939
  eNestingError = rb_path2class("JSON::NestingError");
940
+ rb_gc_register_mark_object(eParserError);
941
+ rb_gc_register_mark_object(eNestingError);
879
942
  rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
880
943
  rb_define_method(cParser, "initialize", cParser_initialize, -1);
881
944
  rb_define_method(cParser, "parse", cParser_parse, 0);
882
945
  rb_define_method(cParser, "source", cParser_source, 0);
883
- rb_define_method(cParser, "quirks_mode?", cParser_quirks_mode_p, 0);
884
946
 
885
947
  CNaN = rb_const_get(mJSON, rb_intern("NaN"));
948
+ rb_gc_register_mark_object(CNaN);
949
+
886
950
  CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
951
+ rb_gc_register_mark_object(CInfinity);
952
+
887
953
  CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
954
+ rb_gc_register_mark_object(CMinusInfinity);
888
955
 
889
956
  i_json_creatable_p = rb_intern("json_creatable?");
890
957
  i_json_create = rb_intern("json_create");
@@ -894,9 +961,9 @@ void Init_parser()
894
961
  i_max_nesting = rb_intern("max_nesting");
895
962
  i_allow_nan = rb_intern("allow_nan");
896
963
  i_symbolize_names = rb_intern("symbolize_names");
897
- i_quirks_mode = rb_intern("quirks_mode");
898
964
  i_object_class = rb_intern("object_class");
899
965
  i_array_class = rb_intern("array_class");
966
+ i_decimal_class = rb_intern("decimal_class");
900
967
  i_match = rb_intern("match");
901
968
  i_match_string = rb_intern("match_string");
902
969
  i_key_p = rb_intern("key?");
@@ -904,18 +971,10 @@ void Init_parser()
904
971
  i_aset = rb_intern("[]=");
905
972
  i_aref = rb_intern("[]");
906
973
  i_leftshift = rb_intern("<<");
907
- #ifdef HAVE_RUBY_ENCODING_H
908
- CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
909
- CEncoding_UTF_16BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16be"));
910
- CEncoding_UTF_16LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16le"));
911
- CEncoding_UTF_32BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32be"));
912
- CEncoding_UTF_32LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32le"));
913
- CEncoding_ASCII_8BIT = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("ascii-8bit"));
914
- i_encoding = rb_intern("encoding");
915
- i_encode = rb_intern("encode");
916
- #else
917
- i_iconv = rb_intern("iconv");
918
- #endif
974
+ i_new = rb_intern("new");
975
+ i_try_convert = rb_intern("try_convert");
976
+ i_freeze = rb_intern("freeze");
977
+ i_uminus = rb_intern("-@");
919
978
  }
920
979
 
921
980
  /*