json 1.8.3 → 2.6.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. checksums.yaml +5 -5
  2. data/{CHANGES → CHANGES.md} +255 -93
  3. data/{COPYING-json-jruby → LICENSE} +5 -6
  4. data/{README.rdoc → README.md} +202 -135
  5. data/VERSION +1 -1
  6. data/ext/json/ext/fbuffer/fbuffer.h +0 -3
  7. data/ext/json/ext/generator/generator.c +266 -116
  8. data/ext/json/ext/generator/generator.h +12 -4
  9. data/ext/json/ext/parser/extconf.rb +29 -0
  10. data/ext/json/ext/parser/parser.c +3011 -1880
  11. data/ext/json/ext/parser/parser.h +10 -6
  12. data/ext/json/ext/parser/parser.rl +239 -192
  13. data/ext/json/extconf.rb +1 -1
  14. data/json.gemspec +0 -0
  15. data/lib/json/add/bigdecimal.rb +3 -2
  16. data/lib/json/add/complex.rb +4 -4
  17. data/lib/json/add/core.rb +1 -0
  18. data/lib/json/add/date.rb +1 -1
  19. data/lib/json/add/date_time.rb +1 -1
  20. data/lib/json/add/exception.rb +1 -1
  21. data/lib/json/add/ostruct.rb +3 -3
  22. data/lib/json/add/range.rb +1 -1
  23. data/lib/json/add/rational.rb +3 -3
  24. data/lib/json/add/regexp.rb +3 -3
  25. data/lib/json/add/set.rb +29 -0
  26. data/lib/json/add/struct.rb +1 -1
  27. data/lib/json/add/symbol.rb +1 -1
  28. data/lib/json/add/time.rb +1 -1
  29. data/lib/json/common.rb +381 -162
  30. data/lib/json/ext.rb +0 -6
  31. data/lib/json/generic_object.rb +5 -4
  32. data/lib/json/pure/generator.rb +83 -126
  33. data/lib/json/pure/parser.rb +64 -86
  34. data/lib/json/pure.rb +2 -8
  35. data/lib/json/version.rb +2 -1
  36. data/lib/json.rb +550 -29
  37. metadata +23 -132
  38. data/.gitignore +0 -16
  39. data/.travis.yml +0 -26
  40. data/COPYING +0 -58
  41. data/GPL +0 -340
  42. data/Gemfile +0 -10
  43. data/README-json-jruby.markdown +0 -33
  44. data/Rakefile +0 -412
  45. data/TODO +0 -1
  46. data/data/example.json +0 -1
  47. data/data/index.html +0 -38
  48. data/data/prototype.js +0 -4184
  49. data/diagrams/.keep +0 -0
  50. data/install.rb +0 -23
  51. data/java/src/json/ext/ByteListTranscoder.java +0 -167
  52. data/java/src/json/ext/Generator.java +0 -444
  53. data/java/src/json/ext/GeneratorMethods.java +0 -232
  54. data/java/src/json/ext/GeneratorService.java +0 -43
  55. data/java/src/json/ext/GeneratorState.java +0 -543
  56. data/java/src/json/ext/OptionsReader.java +0 -114
  57. data/java/src/json/ext/Parser.java +0 -2645
  58. data/java/src/json/ext/Parser.rl +0 -969
  59. data/java/src/json/ext/ParserService.java +0 -35
  60. data/java/src/json/ext/RuntimeInfo.java +0 -121
  61. data/java/src/json/ext/StringDecoder.java +0 -167
  62. data/java/src/json/ext/StringEncoder.java +0 -106
  63. data/java/src/json/ext/Utils.java +0 -89
  64. data/json-java.gemspec +0 -23
  65. data/json_pure.gemspec +0 -40
  66. data/lib/json/ext/.keep +0 -0
  67. data/tests/fixtures/fail1.json +0 -1
  68. data/tests/fixtures/fail10.json +0 -1
  69. data/tests/fixtures/fail11.json +0 -1
  70. data/tests/fixtures/fail12.json +0 -1
  71. data/tests/fixtures/fail13.json +0 -1
  72. data/tests/fixtures/fail14.json +0 -1
  73. data/tests/fixtures/fail18.json +0 -1
  74. data/tests/fixtures/fail19.json +0 -1
  75. data/tests/fixtures/fail2.json +0 -1
  76. data/tests/fixtures/fail20.json +0 -1
  77. data/tests/fixtures/fail21.json +0 -1
  78. data/tests/fixtures/fail22.json +0 -1
  79. data/tests/fixtures/fail23.json +0 -1
  80. data/tests/fixtures/fail24.json +0 -1
  81. data/tests/fixtures/fail25.json +0 -1
  82. data/tests/fixtures/fail27.json +0 -2
  83. data/tests/fixtures/fail28.json +0 -2
  84. data/tests/fixtures/fail3.json +0 -1
  85. data/tests/fixtures/fail4.json +0 -1
  86. data/tests/fixtures/fail5.json +0 -1
  87. data/tests/fixtures/fail6.json +0 -1
  88. data/tests/fixtures/fail7.json +0 -1
  89. data/tests/fixtures/fail8.json +0 -1
  90. data/tests/fixtures/fail9.json +0 -1
  91. data/tests/fixtures/pass1.json +0 -56
  92. data/tests/fixtures/pass15.json +0 -1
  93. data/tests/fixtures/pass16.json +0 -1
  94. data/tests/fixtures/pass17.json +0 -1
  95. data/tests/fixtures/pass2.json +0 -1
  96. data/tests/fixtures/pass26.json +0 -1
  97. data/tests/fixtures/pass3.json +0 -6
  98. data/tests/setup_variant.rb +0 -11
  99. data/tests/test_json.rb +0 -553
  100. data/tests/test_json_addition.rb +0 -196
  101. data/tests/test_json_encoding.rb +0 -65
  102. data/tests/test_json_fixtures.rb +0 -35
  103. data/tests/test_json_generate.rb +0 -337
  104. data/tests/test_json_generic_object.rb +0 -75
  105. data/tests/test_json_string_matching.rb +0 -39
  106. data/tests/test_json_unicode.rb +0 -72
  107. data/tools/fuzz.rb +0 -139
  108. 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,7 +44,7 @@ static const char digit_values[256] = {
22
44
 
23
45
  static UTF32 unescape_unicode(const unsigned char *p)
24
46
  {
25
- char b;
47
+ signed char b;
26
48
  UTF32 result = 0;
27
49
  b = digit_values[p[0]];
28
50
  if (b < 0) return UNI_REPLACEMENT_CHAR;
@@ -65,21 +87,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, "unexpected token at '%s'", 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, "unexpected token at '%s'", 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, "unexpected token at '%s'", 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, "unexpected token at '%s'", 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
+ "incomplete unicode character escape sequence at '%s'", 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
+ "incomplete surrogate pair at '%s'", 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,8 +704,9 @@ 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
711
  * additions even if a matching class and create_id was found. This option
614
712
  * defaults to false.
@@ -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,40 +842,30 @@ 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, "unexpected token at '%s'", p);
868
+ return Qnil;
814
869
  }
815
870
  }
816
871
 
@@ -821,6 +876,7 @@ static void JSON_mark(void *ptr)
821
876
  rb_gc_mark_maybe(json->create_id);
822
877
  rb_gc_mark_maybe(json->object_class);
823
878
  rb_gc_mark_maybe(json->array_class);
879
+ rb_gc_mark_maybe(json->decimal_class);
824
880
  rb_gc_mark_maybe(json->match_string);
825
881
  }
826
882
 
@@ -868,35 +924,34 @@ static VALUE cParser_source(VALUE self)
868
924
  return rb_str_dup(json->Vsource);
869
925
  }
870
926
 
871
- /*
872
- * call-seq: quirks_mode?()
873
- *
874
- * Returns a true, if this parser is in quirks_mode, false otherwise.
875
- */
876
- static VALUE cParser_quirks_mode_p(VALUE self)
877
- {
878
- GET_PARSER;
879
- return json->quirks_mode ? Qtrue : Qfalse;
880
- }
881
-
882
-
883
927
  void Init_parser(void)
884
928
  {
929
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
930
+ rb_ext_ractor_safe(true);
931
+ #endif
932
+
933
+ #undef rb_intern
885
934
  rb_require("json/common");
886
935
  mJSON = rb_define_module("JSON");
887
936
  mExt = rb_define_module_under(mJSON, "Ext");
888
937
  cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
889
938
  eParserError = rb_path2class("JSON::ParserError");
890
939
  eNestingError = rb_path2class("JSON::NestingError");
940
+ rb_gc_register_mark_object(eParserError);
941
+ rb_gc_register_mark_object(eNestingError);
891
942
  rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
892
943
  rb_define_method(cParser, "initialize", cParser_initialize, -1);
893
944
  rb_define_method(cParser, "parse", cParser_parse, 0);
894
945
  rb_define_method(cParser, "source", cParser_source, 0);
895
- rb_define_method(cParser, "quirks_mode?", cParser_quirks_mode_p, 0);
896
946
 
897
947
  CNaN = rb_const_get(mJSON, rb_intern("NaN"));
948
+ rb_gc_register_mark_object(CNaN);
949
+
898
950
  CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
951
+ rb_gc_register_mark_object(CInfinity);
952
+
899
953
  CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
954
+ rb_gc_register_mark_object(CMinusInfinity);
900
955
 
901
956
  i_json_creatable_p = rb_intern("json_creatable?");
902
957
  i_json_create = rb_intern("json_create");
@@ -906,9 +961,9 @@ void Init_parser(void)
906
961
  i_max_nesting = rb_intern("max_nesting");
907
962
  i_allow_nan = rb_intern("allow_nan");
908
963
  i_symbolize_names = rb_intern("symbolize_names");
909
- i_quirks_mode = rb_intern("quirks_mode");
910
964
  i_object_class = rb_intern("object_class");
911
965
  i_array_class = rb_intern("array_class");
966
+ i_decimal_class = rb_intern("decimal_class");
912
967
  i_match = rb_intern("match");
913
968
  i_match_string = rb_intern("match_string");
914
969
  i_key_p = rb_intern("key?");
@@ -916,18 +971,10 @@ void Init_parser(void)
916
971
  i_aset = rb_intern("[]=");
917
972
  i_aref = rb_intern("[]");
918
973
  i_leftshift = rb_intern("<<");
919
- #ifdef HAVE_RUBY_ENCODING_H
920
- CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
921
- CEncoding_UTF_16BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16be"));
922
- CEncoding_UTF_16LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16le"));
923
- CEncoding_UTF_32BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32be"));
924
- CEncoding_UTF_32LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32le"));
925
- CEncoding_ASCII_8BIT = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("ascii-8bit"));
926
- i_encoding = rb_intern("encoding");
927
- i_encode = rb_intern("encode");
928
- #else
929
- i_iconv = rb_intern("iconv");
930
- #endif
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("-@");
931
978
  }
932
979
 
933
980
  /*