json 1.8.6 → 2.7.2

Sign up to get free protection for your applications and to get access to all the features.
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
  /*