json 1.8.6 → 2.7.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 (107) hide show
  1. checksums.yaml +5 -5
  2. data/{CHANGES → CHANGES.md} +292 -96
  3. data/LICENSE +56 -0
  4. data/README.md +185 -114
  5. data/ext/json/ext/fbuffer/fbuffer.h +0 -3
  6. data/ext/json/ext/generator/generator.c +328 -117
  7. data/ext/json/ext/generator/generator.h +8 -8
  8. data/ext/json/ext/parser/extconf.rb +29 -0
  9. data/ext/json/ext/parser/parser.c +540 -569
  10. data/ext/json/ext/parser/parser.h +10 -6
  11. data/ext/json/ext/parser/parser.rl +269 -261
  12. data/ext/json/extconf.rb +1 -1
  13. data/json.gemspec +0 -0
  14. data/lib/json/add/bigdecimal.rb +40 -10
  15. data/lib/json/add/complex.rb +32 -9
  16. data/lib/json/add/core.rb +1 -0
  17. data/lib/json/add/date.rb +27 -7
  18. data/lib/json/add/date_time.rb +26 -9
  19. data/lib/json/add/exception.rb +25 -7
  20. data/lib/json/add/ostruct.rb +32 -9
  21. data/lib/json/add/range.rb +33 -8
  22. data/lib/json/add/rational.rb +30 -8
  23. data/lib/json/add/regexp.rb +28 -10
  24. data/lib/json/add/set.rb +48 -0
  25. data/lib/json/add/struct.rb +29 -7
  26. data/lib/json/add/symbol.rb +28 -5
  27. data/lib/json/add/time.rb +27 -6
  28. data/lib/json/common.rb +402 -188
  29. data/lib/json/ext.rb +0 -6
  30. data/lib/json/generic_object.rb +11 -6
  31. data/lib/json/pure/generator.rb +120 -137
  32. data/lib/json/pure/parser.rb +64 -86
  33. data/lib/json/pure.rb +2 -8
  34. data/lib/json/version.rb +2 -1
  35. data/lib/json.rb +559 -29
  36. metadata +18 -129
  37. data/.gitignore +0 -17
  38. data/.travis.yml +0 -18
  39. data/Gemfile +0 -7
  40. data/README-json-jruby.markdown +0 -33
  41. data/Rakefile +0 -402
  42. data/TODO +0 -1
  43. data/VERSION +0 -1
  44. data/data/example.json +0 -1
  45. data/data/index.html +0 -38
  46. data/data/prototype.js +0 -4184
  47. data/diagrams/.keep +0 -0
  48. data/install.rb +0 -23
  49. data/java/src/json/ext/ByteListTranscoder.java +0 -166
  50. data/java/src/json/ext/Generator.java +0 -446
  51. data/java/src/json/ext/GeneratorMethods.java +0 -231
  52. data/java/src/json/ext/GeneratorService.java +0 -42
  53. data/java/src/json/ext/GeneratorState.java +0 -542
  54. data/java/src/json/ext/OptionsReader.java +0 -113
  55. data/java/src/json/ext/Parser.java +0 -2644
  56. data/java/src/json/ext/Parser.rl +0 -968
  57. data/java/src/json/ext/ParserService.java +0 -34
  58. data/java/src/json/ext/RuntimeInfo.java +0 -120
  59. data/java/src/json/ext/StringDecoder.java +0 -166
  60. data/java/src/json/ext/StringEncoder.java +0 -111
  61. data/java/src/json/ext/Utils.java +0 -88
  62. data/json-java.gemspec +0 -38
  63. data/json_pure.gemspec +0 -37
  64. data/lib/json/ext/.keep +0 -0
  65. data/tests/fixtures/fail1.json +0 -1
  66. data/tests/fixtures/fail10.json +0 -1
  67. data/tests/fixtures/fail11.json +0 -1
  68. data/tests/fixtures/fail12.json +0 -1
  69. data/tests/fixtures/fail13.json +0 -1
  70. data/tests/fixtures/fail14.json +0 -1
  71. data/tests/fixtures/fail18.json +0 -1
  72. data/tests/fixtures/fail19.json +0 -1
  73. data/tests/fixtures/fail2.json +0 -1
  74. data/tests/fixtures/fail20.json +0 -1
  75. data/tests/fixtures/fail21.json +0 -1
  76. data/tests/fixtures/fail22.json +0 -1
  77. data/tests/fixtures/fail23.json +0 -1
  78. data/tests/fixtures/fail24.json +0 -1
  79. data/tests/fixtures/fail25.json +0 -1
  80. data/tests/fixtures/fail27.json +0 -2
  81. data/tests/fixtures/fail28.json +0 -2
  82. data/tests/fixtures/fail3.json +0 -1
  83. data/tests/fixtures/fail4.json +0 -1
  84. data/tests/fixtures/fail5.json +0 -1
  85. data/tests/fixtures/fail6.json +0 -1
  86. data/tests/fixtures/fail7.json +0 -1
  87. data/tests/fixtures/fail8.json +0 -1
  88. data/tests/fixtures/fail9.json +0 -1
  89. data/tests/fixtures/pass1.json +0 -56
  90. data/tests/fixtures/pass15.json +0 -1
  91. data/tests/fixtures/pass16.json +0 -1
  92. data/tests/fixtures/pass17.json +0 -1
  93. data/tests/fixtures/pass2.json +0 -1
  94. data/tests/fixtures/pass26.json +0 -1
  95. data/tests/fixtures/pass3.json +0 -6
  96. data/tests/setup_variant.rb +0 -11
  97. data/tests/test_json.rb +0 -519
  98. data/tests/test_json_addition.rb +0 -196
  99. data/tests/test_json_encoding.rb +0 -65
  100. data/tests/test_json_fixtures.rb +0 -35
  101. data/tests/test_json_generate.rb +0 -348
  102. data/tests/test_json_generic_object.rb +0 -75
  103. data/tests/test_json_string_matching.rb +0 -39
  104. data/tests/test_json_unicode.rb +0 -72
  105. data/tools/diff.sh +0 -18
  106. data/tools/fuzz.rb +0 -139
  107. data/tools/server.rb +0 -62
@@ -2,7 +2,7 @@
2
2
  #include "parser.h"
3
3
 
4
4
  #if defined HAVE_RUBY_ENCODING_H
5
- # define EXC_ENCODING UTF_8,
5
+ # define EXC_ENCODING rb_utf8_encoding(),
6
6
  # ifndef HAVE_RB_ENC_RAISE
7
7
  static void
8
8
  enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
@@ -25,7 +25,7 @@ enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
25
25
 
26
26
  /* unicode */
27
27
 
28
- static const char digit_values[256] = {
28
+ static const signed char digit_values[256] = {
29
29
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
30
30
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
31
31
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1,
@@ -44,7 +44,7 @@ static const char digit_values[256] = {
44
44
 
45
45
  static UTF32 unescape_unicode(const unsigned char *p)
46
46
  {
47
- char b;
47
+ signed char b;
48
48
  UTF32 result = 0;
49
49
  b = digit_values[p[0]];
50
50
  if (b < 0) return UNI_REPLACEMENT_CHAR;
@@ -87,19 +87,14 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
87
87
  return len;
88
88
  }
89
89
 
90
- #ifdef HAVE_RUBY_ENCODING_H
91
- static rb_encoding *UTF_8, *UTF_16BE, *UTF_16LE, *UTF_32BE, *UTF_32LE;
92
- #else
93
- static ID i_iconv;
94
- #endif
95
-
96
90
  static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
97
91
  static VALUE CNaN, CInfinity, CMinusInfinity;
98
92
 
99
93
  static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
100
- i_chr, i_max_nesting, i_allow_nan, i_symbolize_names, i_quirks_mode,
101
- i_object_class, i_array_class, i_key_p, i_deep_const_get, i_match,
102
- 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;
103
98
 
104
99
  %%{
105
100
  machine JSON_common;
@@ -137,11 +132,12 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
137
132
 
138
133
  action parse_value {
139
134
  VALUE v = Qnil;
140
- char *np = JSON_parse_value(json, fpc, pe, &v);
135
+ char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
141
136
  if (np == NULL) {
142
137
  fhold; fbreak;
143
138
  } else {
144
139
  if (NIL_P(json->object_class)) {
140
+ OBJ_FREEZE(last_name);
145
141
  rb_hash_aset(*result, last_name, v);
146
142
  } else {
147
143
  rb_funcall(*result, i_aset, 2, last_name, v);
@@ -170,14 +166,14 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
170
166
  ) @exit;
171
167
  }%%
172
168
 
173
- 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)
174
170
  {
175
171
  int cs = EVIL;
176
172
  VALUE last_name = Qnil;
177
173
  VALUE object_class = json->object_class;
178
174
 
179
- if (json->max_nesting && json->current_nesting > json->max_nesting) {
180
- 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);
181
177
  }
182
178
 
183
179
  *result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class);
@@ -226,14 +222,14 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
226
222
  if (json->allow_nan) {
227
223
  *result = CNaN;
228
224
  } else {
229
- rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2);
225
+ rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 2);
230
226
  }
231
227
  }
232
228
  action parse_infinity {
233
229
  if (json->allow_nan) {
234
230
  *result = CInfinity;
235
231
  } else {
236
- rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8);
232
+ rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 7);
237
233
  }
238
234
  }
239
235
  action parse_string {
@@ -243,13 +239,13 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
243
239
 
244
240
  action parse_number {
245
241
  char *np;
246
- if(pe > fpc + 9 - json->quirks_mode && !strncmp(MinusInfinity, fpc, 9)) {
242
+ if(pe > fpc + 8 && !strncmp(MinusInfinity, fpc, 9)) {
247
243
  if (json->allow_nan) {
248
244
  *result = CMinusInfinity;
249
245
  fexec p + 10;
250
246
  fhold; fbreak;
251
247
  } else {
252
- rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
248
+ rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p);
253
249
  }
254
250
  }
255
251
  np = JSON_parse_float(json, fpc, pe, result);
@@ -261,23 +257,19 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
261
257
 
262
258
  action parse_array {
263
259
  char *np;
264
- json->current_nesting++;
265
- np = JSON_parse_array(json, fpc, pe, result);
266
- json->current_nesting--;
260
+ np = JSON_parse_array(json, fpc, pe, result, current_nesting + 1);
267
261
  if (np == NULL) { fhold; fbreak; } else fexec np;
268
262
  }
269
263
 
270
264
  action parse_object {
271
265
  char *np;
272
- json->current_nesting++;
273
- np = JSON_parse_object(json, fpc, pe, result);
274
- json->current_nesting--;
266
+ np = JSON_parse_object(json, fpc, pe, result, current_nesting + 1);
275
267
  if (np == NULL) { fhold; fbreak; } else fexec np;
276
268
  }
277
269
 
278
270
  action exit { fhold; fbreak; }
279
271
 
280
- main := (
272
+ main := ignore* (
281
273
  Vnull @parse_null |
282
274
  Vfalse @parse_false |
283
275
  Vtrue @parse_true |
@@ -287,16 +279,20 @@ main := (
287
279
  begin_string >parse_string |
288
280
  begin_array >parse_array |
289
281
  begin_object >parse_object
290
- ) %*exit;
282
+ ) ignore* %*exit;
291
283
  }%%
292
284
 
293
- 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)
294
286
  {
295
287
  int cs = EVIL;
296
288
 
297
289
  %% write init;
298
290
  %% write exec;
299
291
 
292
+ if (json->freeze) {
293
+ OBJ_FREEZE(*result);
294
+ }
295
+
300
296
  if (cs >= JSON_value_first_final) {
301
297
  return p;
302
298
  } else {
@@ -357,11 +353,46 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
357
353
  %% write exec;
358
354
 
359
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
+
360
384
  long len = p - json->memo;
361
385
  fbuffer_clear(json->fbuffer);
362
386
  fbuffer_append(json->fbuffer, json->memo, len);
363
387
  fbuffer_append_char(json->fbuffer, '\0');
364
- *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
+
365
396
  return p + 1;
366
397
  } else {
367
398
  return NULL;
@@ -377,7 +408,7 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
377
408
 
378
409
  action parse_value {
379
410
  VALUE v = Qnil;
380
- char *np = JSON_parse_value(json, fpc, pe, &v);
411
+ char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
381
412
  if (np == NULL) {
382
413
  fhold; fbreak;
383
414
  } else {
@@ -400,13 +431,13 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
400
431
  end_array @exit;
401
432
  }%%
402
433
 
403
- 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)
404
435
  {
405
436
  int cs = EVIL;
406
437
  VALUE array_class = json->array_class;
407
438
 
408
- if (json->max_nesting && json->current_nesting > json->max_nesting) {
409
- 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);
410
441
  }
411
442
  *result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
412
443
 
@@ -416,22 +447,42 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
416
447
  if(cs >= JSON_array_first_final) {
417
448
  return p + 1;
418
449
  } else {
419
- rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
450
+ rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p);
420
451
  return NULL;
421
452
  }
422
453
  }
423
454
 
424
- 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)
425
457
  {
426
- 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;
427
461
  int unescape_len;
428
462
  char buf[4];
429
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
+
430
478
  while (pe < stringEnd) {
431
479
  if (*pe == '\\') {
432
480
  unescape = (char *) "?";
433
481
  unescape_len = 1;
434
- 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
+ }
435
486
  switch (*++pe) {
436
487
  case 'n':
437
488
  unescape = (char *) "\n";
@@ -456,13 +507,27 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
456
507
  break;
457
508
  case 'u':
458
509
  if (pe > stringEnd - 4) {
459
- return Qnil;
510
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
511
+ ruby_xfree(bufferStart);
512
+ }
513
+ rb_enc_raise(
514
+ EXC_ENCODING eParserError,
515
+ "incomplete unicode character escape sequence at '%s'", p
516
+ );
460
517
  } else {
461
518
  UTF32 ch = unescape_unicode((unsigned char *) ++pe);
462
519
  pe += 3;
463
520
  if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
464
521
  pe++;
465
- if (pe > stringEnd - 6) return Qnil;
522
+ if (pe > stringEnd - 6) {
523
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
524
+ ruby_xfree(bufferStart);
525
+ }
526
+ rb_enc_raise(
527
+ EXC_ENCODING eParserError,
528
+ "incomplete surrogate pair at '%s'", p
529
+ );
530
+ }
466
531
  if (pe[0] == '\\' && pe[1] == 'u') {
467
532
  UTF32 sur = unescape_unicode((unsigned char *) pe + 2);
468
533
  ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16)
@@ -481,13 +546,55 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
481
546
  p = pe;
482
547
  continue;
483
548
  }
484
- rb_str_buf_cat(result, unescape, unescape_len);
549
+ MEMCPY(buffer, unescape, char, unescape_len);
550
+ buffer += unescape_len;
485
551
  p = ++pe;
486
552
  } else {
487
553
  pe++;
488
554
  }
489
555
  }
490
- 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
+ ruby_xfree(bufferStart);
570
+ }
571
+ # else
572
+ result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
573
+
574
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
575
+ ruby_xfree(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
+
491
598
  return result;
492
599
  }
493
600
 
@@ -498,12 +605,11 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
498
605
  write data;
499
606
 
500
607
  action parse_string {
501
- *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);
502
609
  if (NIL_P(*result)) {
503
610
  fhold;
504
611
  fbreak;
505
612
  } else {
506
- FORCE_UTF8(*result);
507
613
  fexec p + 1;
508
614
  }
509
615
  }
@@ -530,7 +636,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
530
636
  int cs = EVIL;
531
637
  VALUE match_string;
532
638
 
533
- *result = rb_str_buf_new(0);
534
639
  %% write init;
535
640
  json->memo = p;
536
641
  %% write exec;
@@ -546,9 +651,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
546
651
  }
547
652
  }
548
653
 
549
- if (json->symbolize_names && json->parsing_name) {
550
- *result = rb_str_intern(*result);
551
- }
552
654
  if (cs >= JSON_string_first_final) {
553
655
  return p + 1;
554
656
  } else {
@@ -570,41 +672,16 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
570
672
 
571
673
  static VALUE convert_encoding(VALUE source)
572
674
  {
573
- const char *ptr = RSTRING_PTR(source);
574
- long len = RSTRING_LEN(source);
575
- if (len < 2) {
576
- rb_raise(eParserError, "A JSON text must at least contain two octets!");
577
- }
578
675
  #ifdef HAVE_RUBY_ENCODING_H
579
- {
580
- rb_encoding *enc = rb_enc_get(source);
581
- if (enc == rb_ascii8bit_encoding()) {
582
- if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
583
- source = rb_str_conv_enc(source, UTF_32BE, rb_utf8_encoding());
584
- } else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
585
- source = rb_str_conv_enc(source, UTF_16BE, rb_utf8_encoding());
586
- } else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
587
- source = rb_str_conv_enc(source, UTF_32LE, rb_utf8_encoding());
588
- } else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
589
- source = rb_str_conv_enc(source, UTF_16LE, rb_utf8_encoding());
590
- } else {
591
- source = rb_str_dup(source);
592
- FORCE_UTF8(source);
593
- }
594
- } else {
595
- source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding());
596
- }
597
- }
598
- #else
599
- if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
600
- source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-32be"), source);
601
- } else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
602
- source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-16be"), source);
603
- } else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
604
- source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-32le"), source);
605
- } else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
606
- 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);
607
680
  }
681
+ FORCE_UTF8(source);
682
+ } else {
683
+ source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding());
684
+ }
608
685
  #endif
609
686
  return source;
610
687
  }
@@ -614,8 +691,6 @@ static VALUE convert_encoding(VALUE source)
614
691
  *
615
692
  * Creates a new JSON::Ext::Parser instance for the string _source_.
616
693
  *
617
- * Creates a new JSON::Ext::Parser instance for the string _source_.
618
- *
619
694
  * It will be configured by the _opts_ hash. _opts_ can have the following
620
695
  * keys:
621
696
  *
@@ -627,8 +702,9 @@ static VALUE convert_encoding(VALUE source)
627
702
  * defiance of RFC 4627 to be parsed by the Parser. This option defaults to
628
703
  * false.
629
704
  * * *symbolize_names*: If set to true, returns symbols for the names
630
- * (keys) in a JSON object. Otherwise strings are returned, which is also
631
- * the default.
705
+ * (keys) in a JSON object. Otherwise strings are returned, which is
706
+ * also the default. It's not possible to use this option in
707
+ * conjunction with the *create_additions* option.
632
708
  * * *create_additions*: If set to false, the Parser doesn't create
633
709
  * additions even if a matching class and create_id was found. This option
634
710
  * defaults to false.
@@ -643,96 +719,91 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
643
719
  if (json->Vsource) {
644
720
  rb_raise(rb_eTypeError, "already initialized instance");
645
721
  }
646
- #ifdef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
647
722
  rb_scan_args(argc, argv, "1:", &source, &opts);
648
- #else
649
- rb_scan_args(argc, argv, "11", &source, &opts);
650
- #endif
651
723
  if (!NIL_P(opts)) {
652
- #ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
653
- opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
654
- if (NIL_P(opts)) {
655
- rb_raise(rb_eArgError, "opts needs to be like a hash");
656
- } else {
657
- #endif
658
- VALUE tmp = ID2SYM(i_max_nesting);
659
- if (option_given_p(opts, tmp)) {
660
- VALUE max_nesting = rb_hash_aref(opts, tmp);
661
- if (RTEST(max_nesting)) {
662
- Check_Type(max_nesting, T_FIXNUM);
663
- json->max_nesting = FIX2INT(max_nesting);
664
- } else {
665
- json->max_nesting = 0;
666
- }
667
- } else {
668
- json->max_nesting = 100;
669
- }
670
- tmp = ID2SYM(i_allow_nan);
671
- if (option_given_p(opts, tmp)) {
672
- json->allow_nan = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
673
- } else {
674
- json->allow_nan = 0;
675
- }
676
- tmp = ID2SYM(i_symbolize_names);
677
- if (option_given_p(opts, tmp)) {
678
- json->symbolize_names = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
679
- } else {
680
- json->symbolize_names = 0;
681
- }
682
- tmp = ID2SYM(i_quirks_mode);
683
- if (option_given_p(opts, tmp)) {
684
- VALUE quirks_mode = rb_hash_aref(opts, tmp);
685
- json->quirks_mode = RTEST(quirks_mode) ? 1 : 0;
686
- } else {
687
- json->quirks_mode = 0;
688
- }
689
- tmp = ID2SYM(i_create_additions);
690
- if (option_given_p(opts, tmp)) {
691
- json->create_additions = RTEST(rb_hash_aref(opts, tmp));
692
- } else {
693
- json->create_additions = 0;
694
- }
695
- tmp = ID2SYM(i_create_id);
696
- if (option_given_p(opts, tmp)) {
697
- json->create_id = rb_hash_aref(opts, tmp);
698
- } else {
699
- json->create_id = rb_funcall(mJSON, i_create_id, 0);
700
- }
701
- tmp = ID2SYM(i_object_class);
702
- if (option_given_p(opts, tmp)) {
703
- json->object_class = rb_hash_aref(opts, tmp);
704
- } else {
705
- json->object_class = Qnil;
706
- }
707
- tmp = ID2SYM(i_array_class);
708
- if (option_given_p(opts, tmp)) {
709
- json->array_class = rb_hash_aref(opts, tmp);
710
- } else {
711
- json->array_class = Qnil;
712
- }
713
- tmp = ID2SYM(i_match_string);
714
- if (option_given_p(opts, tmp)) {
715
- VALUE match_string = rb_hash_aref(opts, tmp);
716
- json->match_string = RTEST(match_string) ? match_string : Qnil;
717
- } else {
718
- json->match_string = Qnil;
719
- }
720
- #ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
721
- }
722
- #endif
724
+ VALUE tmp = ID2SYM(i_max_nesting);
725
+ if (option_given_p(opts, tmp)) {
726
+ VALUE max_nesting = rb_hash_aref(opts, tmp);
727
+ if (RTEST(max_nesting)) {
728
+ Check_Type(max_nesting, T_FIXNUM);
729
+ json->max_nesting = FIX2INT(max_nesting);
730
+ } else {
731
+ json->max_nesting = 0;
732
+ }
733
+ } else {
734
+ json->max_nesting = 100;
735
+ }
736
+ tmp = ID2SYM(i_allow_nan);
737
+ if (option_given_p(opts, tmp)) {
738
+ json->allow_nan = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
739
+ } else {
740
+ json->allow_nan = 0;
741
+ }
742
+ tmp = ID2SYM(i_symbolize_names);
743
+ if (option_given_p(opts, tmp)) {
744
+ json->symbolize_names = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
745
+ } else {
746
+ json->symbolize_names = 0;
747
+ }
748
+ tmp = ID2SYM(i_freeze);
749
+ if (option_given_p(opts, tmp)) {
750
+ json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
751
+ } else {
752
+ json->freeze = 0;
753
+ }
754
+ tmp = ID2SYM(i_create_additions);
755
+ if (option_given_p(opts, tmp)) {
756
+ json->create_additions = RTEST(rb_hash_aref(opts, tmp));
757
+ } else {
758
+ json->create_additions = 0;
759
+ }
760
+ if (json->symbolize_names && json->create_additions) {
761
+ rb_raise(rb_eArgError,
762
+ "options :symbolize_names and :create_additions cannot be "
763
+ " used in conjunction");
764
+ }
765
+ tmp = ID2SYM(i_create_id);
766
+ if (option_given_p(opts, tmp)) {
767
+ json->create_id = rb_hash_aref(opts, tmp);
768
+ } else {
769
+ json->create_id = rb_funcall(mJSON, i_create_id, 0);
770
+ }
771
+ tmp = ID2SYM(i_object_class);
772
+ if (option_given_p(opts, tmp)) {
773
+ json->object_class = rb_hash_aref(opts, tmp);
774
+ } else {
775
+ json->object_class = Qnil;
776
+ }
777
+ tmp = ID2SYM(i_array_class);
778
+ if (option_given_p(opts, tmp)) {
779
+ json->array_class = rb_hash_aref(opts, tmp);
780
+ } else {
781
+ json->array_class = Qnil;
782
+ }
783
+ tmp = ID2SYM(i_decimal_class);
784
+ if (option_given_p(opts, tmp)) {
785
+ json->decimal_class = rb_hash_aref(opts, tmp);
786
+ } else {
787
+ json->decimal_class = Qnil;
788
+ }
789
+ tmp = ID2SYM(i_match_string);
790
+ if (option_given_p(opts, tmp)) {
791
+ VALUE match_string = rb_hash_aref(opts, tmp);
792
+ json->match_string = RTEST(match_string) ? match_string : Qnil;
793
+ } else {
794
+ json->match_string = Qnil;
795
+ }
723
796
  } else {
724
797
  json->max_nesting = 100;
725
798
  json->allow_nan = 0;
726
- json->create_additions = 1;
727
- json->create_id = rb_funcall(mJSON, i_create_id, 0);
799
+ json->create_additions = 0;
800
+ json->create_id = Qnil;
728
801
  json->object_class = Qnil;
729
802
  json->array_class = Qnil;
803
+ json->decimal_class = Qnil;
730
804
  }
805
+ source = convert_encoding(StringValue(source));
731
806
  StringValue(source);
732
- if (!json->quirks_mode) {
733
- source = convert_encoding(source);
734
- }
735
- json->current_nesting = 0;
736
807
  json->len = RSTRING_LEN(source);
737
808
  json->source = RSTRING_PTR(source);;
738
809
  json->Vsource = source;
@@ -746,56 +817,8 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
746
817
 
747
818
  include JSON_common;
748
819
 
749
- action parse_object {
750
- char *np;
751
- json->current_nesting = 1;
752
- np = JSON_parse_object(json, fpc, pe, &result);
753
- if (np == NULL) { fhold; fbreak; } else fexec np;
754
- }
755
-
756
- action parse_array {
757
- char *np;
758
- json->current_nesting = 1;
759
- np = JSON_parse_array(json, fpc, pe, &result);
760
- if (np == NULL) { fhold; fbreak; } else fexec np;
761
- }
762
-
763
- main := ignore* (
764
- begin_object >parse_object |
765
- begin_array >parse_array
766
- ) ignore*;
767
- }%%
768
-
769
- static VALUE cParser_parse_strict(VALUE self)
770
- {
771
- char *p, *pe;
772
- int cs = EVIL;
773
- VALUE result = Qnil;
774
- GET_PARSER;
775
-
776
- %% write init;
777
- p = json->source;
778
- pe = p + json->len;
779
- %% write exec;
780
-
781
- if (cs >= JSON_first_final && p == pe) {
782
- return result;
783
- } else {
784
- rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
785
- return Qnil;
786
- }
787
- }
788
-
789
-
790
- %%{
791
- machine JSON_quirks_mode;
792
-
793
- write data;
794
-
795
- include JSON_common;
796
-
797
820
  action parse_value {
798
- char *np = JSON_parse_value(json, fpc, pe, &result);
821
+ char *np = JSON_parse_value(json, fpc, pe, &result, 0);
799
822
  if (np == NULL) { fhold; fbreak; } else fexec np;
800
823
  }
801
824
 
@@ -804,40 +827,30 @@ static VALUE cParser_parse_strict(VALUE self)
804
827
  ) ignore*;
805
828
  }%%
806
829
 
807
- static VALUE cParser_parse_quirks_mode(VALUE self)
808
- {
809
- char *p, *pe;
810
- int cs = EVIL;
811
- VALUE result = Qnil;
812
- GET_PARSER;
813
-
814
- %% write init;
815
- p = json->source;
816
- pe = p + json->len;
817
- %% write exec;
818
-
819
- if (cs >= JSON_quirks_mode_first_final && p == pe) {
820
- return result;
821
- } else {
822
- rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
823
- return Qnil;
824
- }
825
- }
826
-
827
830
  /*
828
831
  * call-seq: parse()
829
832
  *
830
833
  * Parses the current JSON text _source_ and returns the complete data
831
834
  * structure as a result.
835
+ * It raises JSON::ParserError if fail to parse.
832
836
  */
833
837
  static VALUE cParser_parse(VALUE self)
834
838
  {
839
+ char *p, *pe;
840
+ int cs = EVIL;
841
+ VALUE result = Qnil;
835
842
  GET_PARSER;
836
843
 
837
- if (json->quirks_mode) {
838
- return cParser_parse_quirks_mode(self);
844
+ %% write init;
845
+ p = json->source;
846
+ pe = p + json->len;
847
+ %% write exec;
848
+
849
+ if (cs >= JSON_first_final && p == pe) {
850
+ return result;
839
851
  } else {
840
- return cParser_parse_strict(self);
852
+ rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p);
853
+ return Qnil;
841
854
  }
842
855
  }
843
856
 
@@ -848,6 +861,7 @@ static void JSON_mark(void *ptr)
848
861
  rb_gc_mark_maybe(json->create_id);
849
862
  rb_gc_mark_maybe(json->object_class);
850
863
  rb_gc_mark_maybe(json->array_class);
864
+ rb_gc_mark_maybe(json->decimal_class);
851
865
  rb_gc_mark_maybe(json->match_string);
852
866
  }
853
867
 
@@ -895,35 +909,34 @@ static VALUE cParser_source(VALUE self)
895
909
  return rb_str_dup(json->Vsource);
896
910
  }
897
911
 
898
- /*
899
- * call-seq: quirks_mode?()
900
- *
901
- * Returns a true, if this parser is in quirks_mode, false otherwise.
902
- */
903
- static VALUE cParser_quirks_mode_p(VALUE self)
904
- {
905
- GET_PARSER;
906
- return json->quirks_mode ? Qtrue : Qfalse;
907
- }
908
-
909
-
910
912
  void Init_parser(void)
911
913
  {
914
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
915
+ rb_ext_ractor_safe(true);
916
+ #endif
917
+
918
+ #undef rb_intern
912
919
  rb_require("json/common");
913
920
  mJSON = rb_define_module("JSON");
914
921
  mExt = rb_define_module_under(mJSON, "Ext");
915
922
  cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
916
923
  eParserError = rb_path2class("JSON::ParserError");
917
924
  eNestingError = rb_path2class("JSON::NestingError");
925
+ rb_gc_register_mark_object(eParserError);
926
+ rb_gc_register_mark_object(eNestingError);
918
927
  rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
919
928
  rb_define_method(cParser, "initialize", cParser_initialize, -1);
920
929
  rb_define_method(cParser, "parse", cParser_parse, 0);
921
930
  rb_define_method(cParser, "source", cParser_source, 0);
922
- rb_define_method(cParser, "quirks_mode?", cParser_quirks_mode_p, 0);
923
931
 
924
932
  CNaN = rb_const_get(mJSON, rb_intern("NaN"));
933
+ rb_gc_register_mark_object(CNaN);
934
+
925
935
  CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
936
+ rb_gc_register_mark_object(CInfinity);
937
+
926
938
  CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
939
+ rb_gc_register_mark_object(CMinusInfinity);
927
940
 
928
941
  i_json_creatable_p = rb_intern("json_creatable?");
929
942
  i_json_create = rb_intern("json_create");
@@ -933,9 +946,9 @@ void Init_parser(void)
933
946
  i_max_nesting = rb_intern("max_nesting");
934
947
  i_allow_nan = rb_intern("allow_nan");
935
948
  i_symbolize_names = rb_intern("symbolize_names");
936
- i_quirks_mode = rb_intern("quirks_mode");
937
949
  i_object_class = rb_intern("object_class");
938
950
  i_array_class = rb_intern("array_class");
951
+ i_decimal_class = rb_intern("decimal_class");
939
952
  i_match = rb_intern("match");
940
953
  i_match_string = rb_intern("match_string");
941
954
  i_key_p = rb_intern("key?");
@@ -943,15 +956,10 @@ void Init_parser(void)
943
956
  i_aset = rb_intern("[]=");
944
957
  i_aref = rb_intern("[]");
945
958
  i_leftshift = rb_intern("<<");
946
- #ifdef HAVE_RUBY_ENCODING_H
947
- UTF_8 = rb_utf8_encoding();
948
- UTF_16BE = rb_enc_find("utf-16be");
949
- UTF_16LE = rb_enc_find("utf-16le");
950
- UTF_32BE = rb_enc_find("utf-32be");
951
- UTF_32LE = rb_enc_find("utf-32le");
952
- #else
953
- i_iconv = rb_intern("iconv");
954
- #endif
959
+ i_new = rb_intern("new");
960
+ i_try_convert = rb_intern("try_convert");
961
+ i_freeze = rb_intern("freeze");
962
+ i_uminus = rb_intern("-@");
955
963
  }
956
964
 
957
965
  /*