json 1.8.6 → 2.5.1

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 (92) hide show
  1. checksums.yaml +5 -5
  2. data/{CHANGES → CHANGES.md} +234 -95
  3. data/Gemfile +10 -3
  4. data/LICENSE +56 -0
  5. data/README.md +187 -107
  6. data/VERSION +1 -1
  7. data/ext/json/ext/fbuffer/fbuffer.h +0 -3
  8. data/ext/json/ext/generator/generator.c +227 -101
  9. data/ext/json/ext/generator/generator.h +5 -8
  10. data/ext/json/ext/parser/extconf.rb +28 -0
  11. data/ext/json/ext/parser/parser.c +420 -481
  12. data/ext/json/ext/parser/parser.h +5 -5
  13. data/ext/json/ext/parser/parser.rl +148 -172
  14. data/ext/json/extconf.rb +1 -1
  15. data/json.gemspec +0 -0
  16. data/lib/json.rb +550 -29
  17. data/lib/json/add/bigdecimal.rb +3 -2
  18. data/lib/json/add/complex.rb +4 -4
  19. data/lib/json/add/core.rb +1 -0
  20. data/lib/json/add/date.rb +1 -1
  21. data/lib/json/add/date_time.rb +1 -1
  22. data/lib/json/add/exception.rb +1 -1
  23. data/lib/json/add/ostruct.rb +3 -3
  24. data/lib/json/add/range.rb +1 -1
  25. data/lib/json/add/rational.rb +3 -3
  26. data/lib/json/add/regexp.rb +3 -3
  27. data/lib/json/add/set.rb +29 -0
  28. data/lib/json/add/struct.rb +1 -1
  29. data/lib/json/add/symbol.rb +1 -1
  30. data/lib/json/add/time.rb +1 -1
  31. data/lib/json/common.rb +381 -162
  32. data/lib/json/ext.rb +0 -6
  33. data/lib/json/generic_object.rb +5 -4
  34. data/lib/json/pure.rb +2 -8
  35. data/lib/json/pure/generator.rb +73 -124
  36. data/lib/json/pure/parser.rb +62 -84
  37. data/lib/json/version.rb +2 -1
  38. data/tests/fixtures/fail29.json +1 -0
  39. data/tests/fixtures/fail30.json +1 -0
  40. data/tests/fixtures/fail31.json +1 -0
  41. data/tests/fixtures/fail32.json +1 -0
  42. data/tests/fixtures/obsolete_fail1.json +1 -0
  43. data/tests/{test_json_addition.rb → json_addition_test.rb} +28 -25
  44. data/tests/json_common_interface_test.rb +169 -0
  45. data/tests/json_encoding_test.rb +107 -0
  46. data/tests/json_ext_parser_test.rb +15 -0
  47. data/tests/{test_json_fixtures.rb → json_fixtures_test.rb} +13 -8
  48. data/tests/{test_json_generate.rb → json_generator_test.rb} +98 -47
  49. data/tests/{test_json_generic_object.rb → json_generic_object_test.rb} +15 -8
  50. data/tests/json_parser_test.rb +497 -0
  51. data/tests/json_string_matching_test.rb +38 -0
  52. data/tests/lib/core_assertions.rb +763 -0
  53. data/tests/lib/envutil.rb +365 -0
  54. data/tests/lib/find_executable.rb +22 -0
  55. data/tests/lib/helper.rb +4 -0
  56. data/tests/ractor_test.rb +30 -0
  57. data/tests/test_helper.rb +17 -0
  58. metadata +43 -69
  59. data/.gitignore +0 -17
  60. data/.travis.yml +0 -18
  61. data/README-json-jruby.markdown +0 -33
  62. data/Rakefile +0 -402
  63. data/TODO +0 -1
  64. data/data/example.json +0 -1
  65. data/data/index.html +0 -38
  66. data/data/prototype.js +0 -4184
  67. data/diagrams/.keep +0 -0
  68. data/install.rb +0 -23
  69. data/java/src/json/ext/ByteListTranscoder.java +0 -166
  70. data/java/src/json/ext/Generator.java +0 -446
  71. data/java/src/json/ext/GeneratorMethods.java +0 -231
  72. data/java/src/json/ext/GeneratorService.java +0 -42
  73. data/java/src/json/ext/GeneratorState.java +0 -542
  74. data/java/src/json/ext/OptionsReader.java +0 -113
  75. data/java/src/json/ext/Parser.java +0 -2644
  76. data/java/src/json/ext/Parser.rl +0 -968
  77. data/java/src/json/ext/ParserService.java +0 -34
  78. data/java/src/json/ext/RuntimeInfo.java +0 -120
  79. data/java/src/json/ext/StringDecoder.java +0 -166
  80. data/java/src/json/ext/StringEncoder.java +0 -111
  81. data/java/src/json/ext/Utils.java +0 -88
  82. data/json-java.gemspec +0 -38
  83. data/json_pure.gemspec +0 -37
  84. data/tests/fixtures/fail1.json +0 -1
  85. data/tests/setup_variant.rb +0 -11
  86. data/tests/test_json.rb +0 -519
  87. data/tests/test_json_encoding.rb +0 -65
  88. data/tests/test_json_string_matching.rb +0 -39
  89. data/tests/test_json_unicode.rb +0 -72
  90. data/tools/diff.sh +0 -18
  91. data/tools/fuzz.rb +0 -139
  92. data/tools/server.rb +0 -62
@@ -1,7 +1,6 @@
1
1
  #ifndef _GENERATOR_H_
2
2
  #define _GENERATOR_H_
3
3
 
4
- #include <string.h>
5
4
  #include <math.h>
6
5
  #include <ctype.h>
7
6
 
@@ -21,10 +20,6 @@
21
20
  #define rb_obj_instance_variables(object) rb_funcall(object, rb_intern("instance_variables"), 0)
22
21
  #endif
23
22
 
24
- #ifndef RB_TYPE_P
25
- #define RB_TYPE_P(obj, type) (rb_type(obj) == type)
26
- #endif
27
-
28
23
  #define option_given_p(opts, key) RTEST(rb_funcall(opts, i_key_p, 1, key))
29
24
 
30
25
  /* unicode definitions */
@@ -54,8 +49,8 @@ static const UTF32 halfMask = 0x3FFUL;
54
49
  static unsigned char isLegalUTF8(const UTF8 *source, unsigned long length);
55
50
  static void unicode_escape(char *buf, UTF16 character);
56
51
  static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16 character);
57
- static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string);
58
- static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string);
52
+ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escape_slash);
53
+ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slash);
59
54
  static char *fstrndup(const char *ptr, unsigned long len);
60
55
 
61
56
  /* ruby api and some helpers */
@@ -77,7 +72,7 @@ typedef struct JSON_Generator_StateStruct {
77
72
  long max_nesting;
78
73
  char allow_nan;
79
74
  char ascii_only;
80
- char quirks_mode;
75
+ char escape_slash;
81
76
  long depth;
82
77
  long buffer_initial_length;
83
78
  } JSON_Generator_State;
@@ -156,6 +151,8 @@ static VALUE cState_allow_nan_p(VALUE self);
156
151
  static VALUE cState_ascii_only_p(VALUE self);
157
152
  static VALUE cState_depth(VALUE self);
158
153
  static VALUE cState_depth_set(VALUE self, VALUE depth);
154
+ static VALUE cState_escape_slash(VALUE self);
155
+ static VALUE cState_escape_slash_set(VALUE self, VALUE depth);
159
156
  static FBuffer *cState_prepare_buffer(VALUE self);
160
157
  #ifndef ZALLOC
161
158
  #define ZALLOC(type) ((type *)ruby_zalloc(sizeof(type)))
@@ -1,3 +1,31 @@
1
+ # frozen_string_literal: false
1
2
  require 'mkmf'
2
3
 
4
+ have_func("rb_enc_raise", "ruby.h")
5
+
6
+ # checking if String#-@ (str_uminus) dedupes... '
7
+ begin
8
+ a = -(%w(t e s t).join)
9
+ b = -(%w(t e s t).join)
10
+ if a.equal?(b)
11
+ $CFLAGS << ' -DSTR_UMINUS_DEDUPE=1 '
12
+ else
13
+ $CFLAGS << ' -DSTR_UMINUS_DEDUPE=0 '
14
+ end
15
+ rescue NoMethodError
16
+ $CFLAGS << ' -DSTR_UMINUS_DEDUPE=0 '
17
+ end
18
+
19
+ # checking if String#-@ (str_uminus) directly interns frozen strings... '
20
+ begin
21
+ s = rand.to_s.freeze
22
+ if (-s).equal?(s) && (-s.dup).equal?(s)
23
+ $CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=1 '
24
+ else
25
+ $CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=0 '
26
+ end
27
+ rescue NoMethodError
28
+ $CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=0 '
29
+ end
30
+
3
31
  create_makefile 'json/ext/parser'
@@ -1,10 +1,10 @@
1
-
1
+ /* This file is automatically generated from parser.rl by using ragel */
2
2
  #line 1 "parser.rl"
3
3
  #include "../fbuffer/fbuffer.h"
4
4
  #include "parser.h"
5
5
 
6
6
  #if defined HAVE_RUBY_ENCODING_H
7
- # define EXC_ENCODING UTF_8,
7
+ # define EXC_ENCODING rb_utf8_encoding(),
8
8
  # ifndef HAVE_RB_ENC_RAISE
9
9
  static void
10
10
  enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
@@ -27,7 +27,7 @@ enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
27
27
 
28
28
  /* unicode */
29
29
 
30
- static const char digit_values[256] = {
30
+ static const signed char digit_values[256] = {
31
31
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
32
32
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
33
33
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1,
@@ -46,7 +46,7 @@ static const char digit_values[256] = {
46
46
 
47
47
  static UTF32 unescape_unicode(const unsigned char *p)
48
48
  {
49
- char b;
49
+ signed char b;
50
50
  UTF32 result = 0;
51
51
  b = digit_values[p[0]];
52
52
  if (b < 0) return UNI_REPLACEMENT_CHAR;
@@ -89,57 +89,52 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
89
89
  return len;
90
90
  }
91
91
 
92
- #ifdef HAVE_RUBY_ENCODING_H
93
- static rb_encoding *UTF_8, *UTF_16BE, *UTF_16LE, *UTF_32BE, *UTF_32LE;
94
- #else
95
- static ID i_iconv;
96
- #endif
97
-
98
92
  static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
99
93
  static VALUE CNaN, CInfinity, CMinusInfinity;
100
94
 
101
95
  static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
102
- i_chr, i_max_nesting, i_allow_nan, i_symbolize_names, i_quirks_mode,
103
- i_object_class, i_array_class, i_key_p, i_deep_const_get, i_match,
104
- i_match_string, i_aset, i_aref, i_leftshift;
96
+ i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
97
+ i_object_class, i_array_class, i_decimal_class, i_key_p,
98
+ i_deep_const_get, i_match, i_match_string, i_aset, i_aref,
99
+ i_leftshift, i_new, i_try_convert, i_freeze, i_uminus;
105
100
 
106
101
 
107
- #line 130 "parser.rl"
102
+ #line 126 "parser.rl"
108
103
 
109
104
 
110
105
 
111
- #line 112 "parser.c"
112
- static const int JSON_object_start = 1;
113
- static const int JSON_object_first_final = 27;
114
- static const int JSON_object_error = 0;
106
+ #line 108 "parser.c"
107
+ enum {JSON_object_start = 1};
108
+ enum {JSON_object_first_final = 27};
109
+ enum {JSON_object_error = 0};
115
110
 
116
- static const int JSON_object_en_main = 1;
111
+ enum {JSON_object_en_main = 1};
117
112
 
118
113
 
119
- #line 171 "parser.rl"
114
+ #line 168 "parser.rl"
120
115
 
121
116
 
122
- static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result)
117
+ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
123
118
  {
124
119
  int cs = EVIL;
125
120
  VALUE last_name = Qnil;
126
121
  VALUE object_class = json->object_class;
127
122
 
128
- if (json->max_nesting && json->current_nesting > json->max_nesting) {
129
- rb_raise(eNestingError, "nesting of %d is too deep", json->current_nesting);
123
+ if (json->max_nesting && current_nesting > json->max_nesting) {
124
+ rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
130
125
  }
131
126
 
132
127
  *result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class);
133
128
 
134
129
 
135
- #line 136 "parser.c"
130
+ #line 132 "parser.c"
136
131
  {
137
132
  cs = JSON_object_start;
138
133
  }
139
134
 
140
- #line 186 "parser.rl"
135
+ #line 183 "parser.rl"
141
136
 
142
- #line 143 "parser.c"
137
+ #line 139 "parser.c"
143
138
  {
144
139
  if ( p == pe )
145
140
  goto _test_eof;
@@ -167,7 +162,7 @@ case 2:
167
162
  goto st2;
168
163
  goto st0;
169
164
  tr2:
170
- #line 153 "parser.rl"
165
+ #line 150 "parser.rl"
171
166
  {
172
167
  char *np;
173
168
  json->parsing_name = 1;
@@ -180,7 +175,7 @@ st3:
180
175
  if ( ++p == pe )
181
176
  goto _test_eof3;
182
177
  case 3:
183
- #line 184 "parser.c"
178
+ #line 180 "parser.c"
184
179
  switch( (*p) ) {
185
180
  case 13: goto st3;
186
181
  case 32: goto st3;
@@ -247,14 +242,15 @@ case 8:
247
242
  goto st8;
248
243
  goto st0;
249
244
  tr11:
250
- #line 138 "parser.rl"
245
+ #line 134 "parser.rl"
251
246
  {
252
247
  VALUE v = Qnil;
253
- char *np = JSON_parse_value(json, p, pe, &v);
248
+ char *np = JSON_parse_value(json, p, pe, &v, current_nesting);
254
249
  if (np == NULL) {
255
250
  p--; {p++; cs = 9; goto _out;}
256
251
  } else {
257
252
  if (NIL_P(json->object_class)) {
253
+ OBJ_FREEZE(last_name);
258
254
  rb_hash_aset(*result, last_name, v);
259
255
  } else {
260
256
  rb_funcall(*result, i_aset, 2, last_name, v);
@@ -267,7 +263,7 @@ st9:
267
263
  if ( ++p == pe )
268
264
  goto _test_eof9;
269
265
  case 9:
270
- #line 271 "parser.c"
266
+ #line 268 "parser.c"
271
267
  switch( (*p) ) {
272
268
  case 13: goto st9;
273
269
  case 32: goto st9;
@@ -356,14 +352,14 @@ case 18:
356
352
  goto st9;
357
353
  goto st18;
358
354
  tr4:
359
- #line 161 "parser.rl"
355
+ #line 158 "parser.rl"
360
356
  { p--; {p++; cs = 27; goto _out;} }
361
357
  goto st27;
362
358
  st27:
363
359
  if ( ++p == pe )
364
360
  goto _test_eof27;
365
361
  case 27:
366
- #line 367 "parser.c"
362
+ #line 364 "parser.c"
367
363
  goto st0;
368
364
  st19:
369
365
  if ( ++p == pe )
@@ -461,7 +457,7 @@ case 26:
461
457
  _out: {}
462
458
  }
463
459
 
464
- #line 187 "parser.rl"
460
+ #line 184 "parser.rl"
465
461
 
466
462
  if (cs >= JSON_object_first_final) {
467
463
  if (json->create_additions) {
@@ -486,69 +482,78 @@ case 26:
486
482
 
487
483
 
488
484
 
489
- #line 490 "parser.c"
490
- static const int JSON_value_start = 1;
491
- static const int JSON_value_first_final = 21;
492
- static const int JSON_value_error = 0;
485
+ #line 487 "parser.c"
486
+ enum {JSON_value_start = 1};
487
+ enum {JSON_value_first_final = 29};
488
+ enum {JSON_value_error = 0};
493
489
 
494
- static const int JSON_value_en_main = 1;
490
+ enum {JSON_value_en_main = 1};
495
491
 
496
492
 
497
- #line 291 "parser.rl"
493
+ #line 284 "parser.rl"
498
494
 
499
495
 
500
- static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result)
496
+ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
501
497
  {
502
498
  int cs = EVIL;
503
499
 
504
500
 
505
- #line 506 "parser.c"
501
+ #line 503 "parser.c"
506
502
  {
507
503
  cs = JSON_value_start;
508
504
  }
509
505
 
510
- #line 298 "parser.rl"
506
+ #line 291 "parser.rl"
511
507
 
512
- #line 513 "parser.c"
508
+ #line 510 "parser.c"
513
509
  {
514
510
  if ( p == pe )
515
511
  goto _test_eof;
516
512
  switch ( cs )
517
513
  {
514
+ st1:
515
+ if ( ++p == pe )
516
+ goto _test_eof1;
518
517
  case 1:
519
518
  switch( (*p) ) {
520
- case 34: goto tr0;
521
- case 45: goto tr2;
522
- case 73: goto st2;
523
- case 78: goto st9;
524
- case 91: goto tr5;
525
- case 102: goto st11;
526
- case 110: goto st15;
527
- case 116: goto st18;
528
- case 123: goto tr9;
519
+ case 13: goto st1;
520
+ case 32: goto st1;
521
+ case 34: goto tr2;
522
+ case 45: goto tr3;
523
+ case 47: goto st6;
524
+ case 73: goto st10;
525
+ case 78: goto st17;
526
+ case 91: goto tr7;
527
+ case 102: goto st19;
528
+ case 110: goto st23;
529
+ case 116: goto st26;
530
+ case 123: goto tr11;
529
531
  }
530
- if ( 48 <= (*p) && (*p) <= 57 )
531
- goto tr2;
532
+ if ( (*p) > 10 ) {
533
+ if ( 48 <= (*p) && (*p) <= 57 )
534
+ goto tr3;
535
+ } else if ( (*p) >= 9 )
536
+ goto st1;
532
537
  goto st0;
533
538
  st0:
534
539
  cs = 0;
535
540
  goto _out;
536
- tr0:
537
- #line 239 "parser.rl"
541
+ tr2:
542
+ #line 236 "parser.rl"
538
543
  {
539
544
  char *np = JSON_parse_string(json, p, pe, result);
540
- if (np == NULL) { p--; {p++; cs = 21; goto _out;} } else {p = (( np))-1;}
545
+ if (np == NULL) { p--; {p++; cs = 29; goto _out;} } else {p = (( np))-1;}
541
546
  }
542
- goto st21;
543
- tr2:
544
- #line 244 "parser.rl"
547
+ goto st29;
548
+ tr3:
549
+ #line 241 "parser.rl"
545
550
  {
546
551
  char *np;
547
- if(pe > p + 9 - json->quirks_mode && !strncmp(MinusInfinity, p, 9)) {
552
+ if(pe > p + 8 && !strncmp(MinusInfinity, p, 9)) {
548
553
  if (json->allow_nan) {
549
554
  *result = CMinusInfinity;
550
555
  {p = (( p + 10))-1;}
551
- p--; {p++; cs = 21; goto _out;}
556
+ p--; {p++; cs = 29; goto _out;}
552
557
  } else {
553
558
  rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
554
559
  }
@@ -557,31 +562,27 @@ tr2:
557
562
  if (np != NULL) {p = (( np))-1;}
558
563
  np = JSON_parse_integer(json, p, pe, result);
559
564
  if (np != NULL) {p = (( np))-1;}
560
- p--; {p++; cs = 21; goto _out;}
565
+ p--; {p++; cs = 29; goto _out;}
561
566
  }
562
- goto st21;
563
- tr5:
564
- #line 262 "parser.rl"
567
+ goto st29;
568
+ tr7:
569
+ #line 259 "parser.rl"
565
570
  {
566
571
  char *np;
567
- json->current_nesting++;
568
- np = JSON_parse_array(json, p, pe, result);
569
- json->current_nesting--;
570
- if (np == NULL) { p--; {p++; cs = 21; goto _out;} } else {p = (( np))-1;}
572
+ np = JSON_parse_array(json, p, pe, result, current_nesting + 1);
573
+ if (np == NULL) { p--; {p++; cs = 29; goto _out;} } else {p = (( np))-1;}
571
574
  }
572
- goto st21;
573
- tr9:
574
- #line 270 "parser.rl"
575
+ goto st29;
576
+ tr11:
577
+ #line 265 "parser.rl"
575
578
  {
576
579
  char *np;
577
- json->current_nesting++;
578
- np = JSON_parse_object(json, p, pe, result);
579
- json->current_nesting--;
580
- if (np == NULL) { p--; {p++; cs = 21; goto _out;} } else {p = (( np))-1;}
580
+ np = JSON_parse_object(json, p, pe, result, current_nesting + 1);
581
+ if (np == NULL) { p--; {p++; cs = 29; goto _out;} } else {p = (( np))-1;}
581
582
  }
582
- goto st21;
583
- tr16:
584
- #line 232 "parser.rl"
583
+ goto st29;
584
+ tr25:
585
+ #line 229 "parser.rl"
585
586
  {
586
587
  if (json->allow_nan) {
587
588
  *result = CInfinity;
@@ -589,9 +590,9 @@ tr16:
589
590
  rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8);
590
591
  }
591
592
  }
592
- goto st21;
593
- tr18:
594
- #line 225 "parser.rl"
593
+ goto st29;
594
+ tr27:
595
+ #line 222 "parser.rl"
595
596
  {
596
597
  if (json->allow_nan) {
597
598
  *result = CNaN;
@@ -599,168 +600,240 @@ tr18:
599
600
  rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2);
600
601
  }
601
602
  }
602
- goto st21;
603
- tr22:
604
- #line 219 "parser.rl"
603
+ goto st29;
604
+ tr31:
605
+ #line 216 "parser.rl"
605
606
  {
606
607
  *result = Qfalse;
607
608
  }
608
- goto st21;
609
- tr25:
610
- #line 216 "parser.rl"
609
+ goto st29;
610
+ tr34:
611
+ #line 213 "parser.rl"
611
612
  {
612
613
  *result = Qnil;
613
614
  }
614
- goto st21;
615
- tr28:
616
- #line 222 "parser.rl"
615
+ goto st29;
616
+ tr37:
617
+ #line 219 "parser.rl"
617
618
  {
618
619
  *result = Qtrue;
619
620
  }
620
- goto st21;
621
- st21:
622
- if ( ++p == pe )
623
- goto _test_eof21;
624
- case 21:
625
- #line 278 "parser.rl"
626
- { p--; {p++; cs = 21; goto _out;} }
627
- #line 628 "parser.c"
621
+ goto st29;
622
+ st29:
623
+ if ( ++p == pe )
624
+ goto _test_eof29;
625
+ case 29:
626
+ #line 271 "parser.rl"
627
+ { p--; {p++; cs = 29; goto _out;} }
628
+ #line 630 "parser.c"
629
+ switch( (*p) ) {
630
+ case 13: goto st29;
631
+ case 32: goto st29;
632
+ case 47: goto st2;
633
+ }
634
+ if ( 9 <= (*p) && (*p) <= 10 )
635
+ goto st29;
628
636
  goto st0;
629
637
  st2:
630
638
  if ( ++p == pe )
631
639
  goto _test_eof2;
632
640
  case 2:
633
- if ( (*p) == 110 )
634
- goto st3;
641
+ switch( (*p) ) {
642
+ case 42: goto st3;
643
+ case 47: goto st5;
644
+ }
635
645
  goto st0;
636
646
  st3:
637
647
  if ( ++p == pe )
638
648
  goto _test_eof3;
639
649
  case 3:
640
- if ( (*p) == 102 )
650
+ if ( (*p) == 42 )
641
651
  goto st4;
642
- goto st0;
652
+ goto st3;
643
653
  st4:
644
654
  if ( ++p == pe )
645
655
  goto _test_eof4;
646
656
  case 4:
647
- if ( (*p) == 105 )
648
- goto st5;
649
- goto st0;
657
+ switch( (*p) ) {
658
+ case 42: goto st4;
659
+ case 47: goto st29;
660
+ }
661
+ goto st3;
650
662
  st5:
651
663
  if ( ++p == pe )
652
664
  goto _test_eof5;
653
665
  case 5:
654
- if ( (*p) == 110 )
655
- goto st6;
656
- goto st0;
666
+ if ( (*p) == 10 )
667
+ goto st29;
668
+ goto st5;
657
669
  st6:
658
670
  if ( ++p == pe )
659
671
  goto _test_eof6;
660
672
  case 6:
661
- if ( (*p) == 105 )
662
- goto st7;
673
+ switch( (*p) ) {
674
+ case 42: goto st7;
675
+ case 47: goto st9;
676
+ }
663
677
  goto st0;
664
678
  st7:
665
679
  if ( ++p == pe )
666
680
  goto _test_eof7;
667
681
  case 7:
668
- if ( (*p) == 116 )
682
+ if ( (*p) == 42 )
669
683
  goto st8;
670
- goto st0;
684
+ goto st7;
671
685
  st8:
672
686
  if ( ++p == pe )
673
687
  goto _test_eof8;
674
688
  case 8:
675
- if ( (*p) == 121 )
676
- goto tr16;
677
- goto st0;
689
+ switch( (*p) ) {
690
+ case 42: goto st8;
691
+ case 47: goto st1;
692
+ }
693
+ goto st7;
678
694
  st9:
679
695
  if ( ++p == pe )
680
696
  goto _test_eof9;
681
697
  case 9:
682
- if ( (*p) == 97 )
683
- goto st10;
684
- goto st0;
698
+ if ( (*p) == 10 )
699
+ goto st1;
700
+ goto st9;
685
701
  st10:
686
702
  if ( ++p == pe )
687
703
  goto _test_eof10;
688
704
  case 10:
689
- if ( (*p) == 78 )
690
- goto tr18;
705
+ if ( (*p) == 110 )
706
+ goto st11;
691
707
  goto st0;
692
708
  st11:
693
709
  if ( ++p == pe )
694
710
  goto _test_eof11;
695
711
  case 11:
696
- if ( (*p) == 97 )
712
+ if ( (*p) == 102 )
697
713
  goto st12;
698
714
  goto st0;
699
715
  st12:
700
716
  if ( ++p == pe )
701
717
  goto _test_eof12;
702
718
  case 12:
703
- if ( (*p) == 108 )
719
+ if ( (*p) == 105 )
704
720
  goto st13;
705
721
  goto st0;
706
722
  st13:
707
723
  if ( ++p == pe )
708
724
  goto _test_eof13;
709
725
  case 13:
710
- if ( (*p) == 115 )
726
+ if ( (*p) == 110 )
711
727
  goto st14;
712
728
  goto st0;
713
729
  st14:
714
730
  if ( ++p == pe )
715
731
  goto _test_eof14;
716
732
  case 14:
717
- if ( (*p) == 101 )
718
- goto tr22;
733
+ if ( (*p) == 105 )
734
+ goto st15;
719
735
  goto st0;
720
736
  st15:
721
737
  if ( ++p == pe )
722
738
  goto _test_eof15;
723
739
  case 15:
724
- if ( (*p) == 117 )
740
+ if ( (*p) == 116 )
725
741
  goto st16;
726
742
  goto st0;
727
743
  st16:
728
744
  if ( ++p == pe )
729
745
  goto _test_eof16;
730
746
  case 16:
731
- if ( (*p) == 108 )
732
- goto st17;
747
+ if ( (*p) == 121 )
748
+ goto tr25;
733
749
  goto st0;
734
750
  st17:
735
751
  if ( ++p == pe )
736
752
  goto _test_eof17;
737
753
  case 17:
738
- if ( (*p) == 108 )
739
- goto tr25;
754
+ if ( (*p) == 97 )
755
+ goto st18;
740
756
  goto st0;
741
757
  st18:
742
758
  if ( ++p == pe )
743
759
  goto _test_eof18;
744
760
  case 18:
745
- if ( (*p) == 114 )
746
- goto st19;
761
+ if ( (*p) == 78 )
762
+ goto tr27;
747
763
  goto st0;
748
764
  st19:
749
765
  if ( ++p == pe )
750
766
  goto _test_eof19;
751
767
  case 19:
752
- if ( (*p) == 117 )
768
+ if ( (*p) == 97 )
753
769
  goto st20;
754
770
  goto st0;
755
771
  st20:
756
772
  if ( ++p == pe )
757
773
  goto _test_eof20;
758
774
  case 20:
775
+ if ( (*p) == 108 )
776
+ goto st21;
777
+ goto st0;
778
+ st21:
779
+ if ( ++p == pe )
780
+ goto _test_eof21;
781
+ case 21:
782
+ if ( (*p) == 115 )
783
+ goto st22;
784
+ goto st0;
785
+ st22:
786
+ if ( ++p == pe )
787
+ goto _test_eof22;
788
+ case 22:
759
789
  if ( (*p) == 101 )
760
- goto tr28;
790
+ goto tr31;
791
+ goto st0;
792
+ st23:
793
+ if ( ++p == pe )
794
+ goto _test_eof23;
795
+ case 23:
796
+ if ( (*p) == 117 )
797
+ goto st24;
798
+ goto st0;
799
+ st24:
800
+ if ( ++p == pe )
801
+ goto _test_eof24;
802
+ case 24:
803
+ if ( (*p) == 108 )
804
+ goto st25;
805
+ goto st0;
806
+ st25:
807
+ if ( ++p == pe )
808
+ goto _test_eof25;
809
+ case 25:
810
+ if ( (*p) == 108 )
811
+ goto tr34;
812
+ goto st0;
813
+ st26:
814
+ if ( ++p == pe )
815
+ goto _test_eof26;
816
+ case 26:
817
+ if ( (*p) == 114 )
818
+ goto st27;
819
+ goto st0;
820
+ st27:
821
+ if ( ++p == pe )
822
+ goto _test_eof27;
823
+ case 27:
824
+ if ( (*p) == 117 )
825
+ goto st28;
826
+ goto st0;
827
+ st28:
828
+ if ( ++p == pe )
829
+ goto _test_eof28;
830
+ case 28:
831
+ if ( (*p) == 101 )
832
+ goto tr37;
761
833
  goto st0;
762
834
  }
763
- _test_eof21: cs = 21; goto _test_eof;
835
+ _test_eof1: cs = 1; goto _test_eof;
836
+ _test_eof29: cs = 29; goto _test_eof;
764
837
  _test_eof2: cs = 2; goto _test_eof;
765
838
  _test_eof3: cs = 3; goto _test_eof;
766
839
  _test_eof4: cs = 4; goto _test_eof;
@@ -780,12 +853,24 @@ case 20:
780
853
  _test_eof18: cs = 18; goto _test_eof;
781
854
  _test_eof19: cs = 19; goto _test_eof;
782
855
  _test_eof20: cs = 20; goto _test_eof;
856
+ _test_eof21: cs = 21; goto _test_eof;
857
+ _test_eof22: cs = 22; goto _test_eof;
858
+ _test_eof23: cs = 23; goto _test_eof;
859
+ _test_eof24: cs = 24; goto _test_eof;
860
+ _test_eof25: cs = 25; goto _test_eof;
861
+ _test_eof26: cs = 26; goto _test_eof;
862
+ _test_eof27: cs = 27; goto _test_eof;
863
+ _test_eof28: cs = 28; goto _test_eof;
783
864
 
784
865
  _test_eof: {}
785
866
  _out: {}
786
867
  }
787
868
 
788
- #line 299 "parser.rl"
869
+ #line 292 "parser.rl"
870
+
871
+ if (json->freeze) {
872
+ OBJ_FREEZE(*result);
873
+ }
789
874
 
790
875
  if (cs >= JSON_value_first_final) {
791
876
  return p;
@@ -795,15 +880,15 @@ case 20:
795
880
  }
796
881
 
797
882
 
798
- #line 799 "parser.c"
799
- static const int JSON_integer_start = 1;
800
- static const int JSON_integer_first_final = 3;
801
- static const int JSON_integer_error = 0;
883
+ #line 885 "parser.c"
884
+ enum {JSON_integer_start = 1};
885
+ enum {JSON_integer_first_final = 3};
886
+ enum {JSON_integer_error = 0};
802
887
 
803
- static const int JSON_integer_en_main = 1;
888
+ enum {JSON_integer_en_main = 1};
804
889
 
805
890
 
806
- #line 315 "parser.rl"
891
+ #line 312 "parser.rl"
807
892
 
808
893
 
809
894
  static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -811,15 +896,15 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
811
896
  int cs = EVIL;
812
897
 
813
898
 
814
- #line 815 "parser.c"
899
+ #line 901 "parser.c"
815
900
  {
816
901
  cs = JSON_integer_start;
817
902
  }
818
903
 
819
- #line 322 "parser.rl"
904
+ #line 319 "parser.rl"
820
905
  json->memo = p;
821
906
 
822
- #line 823 "parser.c"
907
+ #line 909 "parser.c"
823
908
  {
824
909
  if ( p == pe )
825
910
  goto _test_eof;
@@ -853,14 +938,14 @@ case 3:
853
938
  goto st0;
854
939
  goto tr4;
855
940
  tr4:
856
- #line 312 "parser.rl"
941
+ #line 309 "parser.rl"
857
942
  { p--; {p++; cs = 4; goto _out;} }
858
943
  goto st4;
859
944
  st4:
860
945
  if ( ++p == pe )
861
946
  goto _test_eof4;
862
947
  case 4:
863
- #line 864 "parser.c"
948
+ #line 950 "parser.c"
864
949
  goto st0;
865
950
  st5:
866
951
  if ( ++p == pe )
@@ -879,7 +964,7 @@ case 5:
879
964
  _out: {}
880
965
  }
881
966
 
882
- #line 324 "parser.rl"
967
+ #line 321 "parser.rl"
883
968
 
884
969
  if (cs >= JSON_integer_first_final) {
885
970
  long len = p - json->memo;
@@ -894,15 +979,15 @@ case 5:
894
979
  }
895
980
 
896
981
 
897
- #line 898 "parser.c"
898
- static const int JSON_float_start = 1;
899
- static const int JSON_float_first_final = 8;
900
- static const int JSON_float_error = 0;
982
+ #line 984 "parser.c"
983
+ enum {JSON_float_start = 1};
984
+ enum {JSON_float_first_final = 8};
985
+ enum {JSON_float_error = 0};
901
986
 
902
- static const int JSON_float_en_main = 1;
987
+ enum {JSON_float_en_main = 1};
903
988
 
904
989
 
905
- #line 349 "parser.rl"
990
+ #line 346 "parser.rl"
906
991
 
907
992
 
908
993
  static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -910,15 +995,15 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
910
995
  int cs = EVIL;
911
996
 
912
997
 
913
- #line 914 "parser.c"
998
+ #line 1013 "parser.c"
914
999
  {
915
1000
  cs = JSON_float_start;
916
1001
  }
917
1002
 
918
- #line 356 "parser.rl"
1003
+ #line 366 "parser.rl"
919
1004
  json->memo = p;
920
1005
 
921
- #line 922 "parser.c"
1006
+ #line 1021 "parser.c"
922
1007
  {
923
1008
  if ( p == pe )
924
1009
  goto _test_eof;
@@ -976,14 +1061,14 @@ case 8:
976
1061
  goto st0;
977
1062
  goto tr9;
978
1063
  tr9:
979
- #line 343 "parser.rl"
1064
+ #line 340 "parser.rl"
980
1065
  { p--; {p++; cs = 9; goto _out;} }
981
1066
  goto st9;
982
1067
  st9:
983
1068
  if ( ++p == pe )
984
1069
  goto _test_eof9;
985
1070
  case 9:
986
- #line 987 "parser.c"
1071
+ #line 1086 "parser.c"
987
1072
  goto st0;
988
1073
  st5:
989
1074
  if ( ++p == pe )
@@ -1044,14 +1129,49 @@ case 7:
1044
1129
  _out: {}
1045
1130
  }
1046
1131
 
1047
- #line 358 "parser.rl"
1132
+ #line 368 "parser.rl"
1048
1133
 
1049
1134
  if (cs >= JSON_float_first_final) {
1135
+ VALUE mod = Qnil;
1136
+ ID method_id = 0;
1137
+ if (rb_respond_to(json->decimal_class, i_try_convert)) {
1138
+ mod = json->decimal_class;
1139
+ method_id = i_try_convert;
1140
+ } else if (rb_respond_to(json->decimal_class, i_new)) {
1141
+ mod = json->decimal_class;
1142
+ method_id = i_new;
1143
+ } else if (RB_TYPE_P(json->decimal_class, T_CLASS)) {
1144
+ VALUE name = rb_class_name(json->decimal_class);
1145
+ const char *name_cstr = RSTRING_PTR(name);
1146
+ const char *last_colon = strrchr(name_cstr, ':');
1147
+ if (last_colon) {
1148
+ const char *mod_path_end = last_colon - 1;
1149
+ VALUE mod_path = rb_str_substr(name, 0, mod_path_end - name_cstr);
1150
+ mod = rb_path_to_class(mod_path);
1151
+
1152
+ const char *method_name_beg = last_colon + 1;
1153
+ long before_len = method_name_beg - name_cstr;
1154
+ long len = RSTRING_LEN(name) - before_len;
1155
+ VALUE method_name = rb_str_substr(name, before_len, len);
1156
+ method_id = SYM2ID(rb_str_intern(method_name));
1157
+ } else {
1158
+ mod = rb_mKernel;
1159
+ method_id = SYM2ID(rb_str_intern(name));
1160
+ }
1161
+ }
1162
+
1050
1163
  long len = p - json->memo;
1051
1164
  fbuffer_clear(json->fbuffer);
1052
1165
  fbuffer_append(json->fbuffer, json->memo, len);
1053
1166
  fbuffer_append_char(json->fbuffer, '\0');
1054
- *result = rb_float_new(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
1167
+
1168
+ if (method_id) {
1169
+ VALUE text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
1170
+ *result = rb_funcallv(mod, method_id, 1, &text);
1171
+ } else {
1172
+ *result = DBL2NUM(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
1173
+ }
1174
+
1055
1175
  return p + 1;
1056
1176
  } else {
1057
1177
  return NULL;
@@ -1060,36 +1180,36 @@ case 7:
1060
1180
 
1061
1181
 
1062
1182
 
1063
- #line 1064 "parser.c"
1064
- static const int JSON_array_start = 1;
1065
- static const int JSON_array_first_final = 17;
1066
- static const int JSON_array_error = 0;
1183
+ #line 1173 "parser.c"
1184
+ enum {JSON_array_start = 1};
1185
+ enum {JSON_array_first_final = 17};
1186
+ enum {JSON_array_error = 0};
1067
1187
 
1068
- static const int JSON_array_en_main = 1;
1188
+ enum {JSON_array_en_main = 1};
1069
1189
 
1070
1190
 
1071
- #line 401 "parser.rl"
1191
+ #line 421 "parser.rl"
1072
1192
 
1073
1193
 
1074
- static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result)
1194
+ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
1075
1195
  {
1076
1196
  int cs = EVIL;
1077
1197
  VALUE array_class = json->array_class;
1078
1198
 
1079
- if (json->max_nesting && json->current_nesting > json->max_nesting) {
1080
- rb_raise(eNestingError, "nesting of %d is too deep", json->current_nesting);
1199
+ if (json->max_nesting && current_nesting > json->max_nesting) {
1200
+ rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
1081
1201
  }
1082
1202
  *result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
1083
1203
 
1084
1204
 
1085
- #line 1086 "parser.c"
1205
+ #line 1195 "parser.c"
1086
1206
  {
1087
1207
  cs = JSON_array_start;
1088
1208
  }
1089
1209
 
1090
- #line 414 "parser.rl"
1210
+ #line 434 "parser.rl"
1091
1211
 
1092
- #line 1093 "parser.c"
1212
+ #line 1202 "parser.c"
1093
1213
  {
1094
1214
  if ( p == pe )
1095
1215
  goto _test_eof;
@@ -1128,10 +1248,10 @@ case 2:
1128
1248
  goto st2;
1129
1249
  goto st0;
1130
1250
  tr2:
1131
- #line 378 "parser.rl"
1251
+ #line 398 "parser.rl"
1132
1252
  {
1133
1253
  VALUE v = Qnil;
1134
- char *np = JSON_parse_value(json, p, pe, &v);
1254
+ char *np = JSON_parse_value(json, p, pe, &v, current_nesting);
1135
1255
  if (np == NULL) {
1136
1256
  p--; {p++; cs = 3; goto _out;}
1137
1257
  } else {
@@ -1148,7 +1268,7 @@ st3:
1148
1268
  if ( ++p == pe )
1149
1269
  goto _test_eof3;
1150
1270
  case 3:
1151
- #line 1152 "parser.c"
1271
+ #line 1261 "parser.c"
1152
1272
  switch( (*p) ) {
1153
1273
  case 13: goto st3;
1154
1274
  case 32: goto st3;
@@ -1248,14 +1368,14 @@ case 12:
1248
1368
  goto st3;
1249
1369
  goto st12;
1250
1370
  tr4:
1251
- #line 393 "parser.rl"
1371
+ #line 413 "parser.rl"
1252
1372
  { p--; {p++; cs = 17; goto _out;} }
1253
1373
  goto st17;
1254
1374
  st17:
1255
1375
  if ( ++p == pe )
1256
1376
  goto _test_eof17;
1257
1377
  case 17:
1258
- #line 1259 "parser.c"
1378
+ #line 1368 "parser.c"
1259
1379
  goto st0;
1260
1380
  st13:
1261
1381
  if ( ++p == pe )
@@ -1311,7 +1431,7 @@ case 16:
1311
1431
  _out: {}
1312
1432
  }
1313
1433
 
1314
- #line 415 "parser.rl"
1434
+ #line 435 "parser.rl"
1315
1435
 
1316
1436
  if(cs >= JSON_array_first_final) {
1317
1437
  return p + 1;
@@ -1356,13 +1476,21 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
1356
1476
  break;
1357
1477
  case 'u':
1358
1478
  if (pe > stringEnd - 4) {
1359
- return Qnil;
1479
+ rb_enc_raise(
1480
+ EXC_ENCODING eParserError,
1481
+ "%u: incomplete unicode character escape sequence at '%s'", __LINE__, p
1482
+ );
1360
1483
  } else {
1361
1484
  UTF32 ch = unescape_unicode((unsigned char *) ++pe);
1362
1485
  pe += 3;
1363
1486
  if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
1364
1487
  pe++;
1365
- if (pe > stringEnd - 6) return Qnil;
1488
+ if (pe > stringEnd - 6) {
1489
+ rb_enc_raise(
1490
+ EXC_ENCODING eParserError,
1491
+ "%u: incomplete surrogate pair at '%s'", __LINE__, p
1492
+ );
1493
+ }
1366
1494
  if (pe[0] == '\\' && pe[1] == 'u') {
1367
1495
  UTF32 sur = unescape_unicode((unsigned char *) pe + 2);
1368
1496
  ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16)
@@ -1392,15 +1520,15 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
1392
1520
  }
1393
1521
 
1394
1522
 
1395
- #line 1396 "parser.c"
1396
- static const int JSON_string_start = 1;
1397
- static const int JSON_string_first_final = 8;
1398
- static const int JSON_string_error = 0;
1523
+ #line 1513 "parser.c"
1524
+ enum {JSON_string_start = 1};
1525
+ enum {JSON_string_first_final = 8};
1526
+ enum {JSON_string_error = 0};
1399
1527
 
1400
- static const int JSON_string_en_main = 1;
1528
+ enum {JSON_string_en_main = 1};
1401
1529
 
1402
1530
 
1403
- #line 514 "parser.rl"
1531
+ #line 542 "parser.rl"
1404
1532
 
1405
1533
 
1406
1534
  static int
@@ -1422,15 +1550,15 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
1422
1550
 
1423
1551
  *result = rb_str_buf_new(0);
1424
1552
 
1425
- #line 1426 "parser.c"
1553
+ #line 1543 "parser.c"
1426
1554
  {
1427
1555
  cs = JSON_string_start;
1428
1556
  }
1429
1557
 
1430
- #line 535 "parser.rl"
1558
+ #line 563 "parser.rl"
1431
1559
  json->memo = p;
1432
1560
 
1433
- #line 1434 "parser.c"
1561
+ #line 1551 "parser.c"
1434
1562
  {
1435
1563
  if ( p == pe )
1436
1564
  goto _test_eof;
@@ -1451,11 +1579,11 @@ case 2:
1451
1579
  case 34: goto tr2;
1452
1580
  case 92: goto st3;
1453
1581
  }
1454
- if ( 0 <= (*p) && (*p) <= 31 )
1582
+ if ( 0 <= (signed char)(*p) && (*p) <= 31 )
1455
1583
  goto st0;
1456
1584
  goto st2;
1457
1585
  tr2:
1458
- #line 500 "parser.rl"
1586
+ #line 528 "parser.rl"
1459
1587
  {
1460
1588
  *result = json_string_unescape(*result, json->memo + 1, p);
1461
1589
  if (NIL_P(*result)) {
@@ -1466,14 +1594,14 @@ tr2:
1466
1594
  {p = (( p + 1))-1;}
1467
1595
  }
1468
1596
  }
1469
- #line 511 "parser.rl"
1597
+ #line 539 "parser.rl"
1470
1598
  { p--; {p++; cs = 8; goto _out;} }
1471
1599
  goto st8;
1472
1600
  st8:
1473
1601
  if ( ++p == pe )
1474
1602
  goto _test_eof8;
1475
1603
  case 8:
1476
- #line 1477 "parser.c"
1604
+ #line 1594 "parser.c"
1477
1605
  goto st0;
1478
1606
  st3:
1479
1607
  if ( ++p == pe )
@@ -1481,7 +1609,7 @@ st3:
1481
1609
  case 3:
1482
1610
  if ( (*p) == 117 )
1483
1611
  goto st4;
1484
- if ( 0 <= (*p) && (*p) <= 31 )
1612
+ if ( 0 <= (signed char)(*p) && (*p) <= 31 )
1485
1613
  goto st0;
1486
1614
  goto st2;
1487
1615
  st4:
@@ -1549,7 +1677,7 @@ case 7:
1549
1677
  _out: {}
1550
1678
  }
1551
1679
 
1552
- #line 537 "parser.rl"
1680
+ #line 565 "parser.rl"
1553
1681
 
1554
1682
  if (json->create_additions && RTEST(match_string = json->match_string)) {
1555
1683
  VALUE klass;
@@ -1564,6 +1692,23 @@ case 7:
1564
1692
 
1565
1693
  if (json->symbolize_names && json->parsing_name) {
1566
1694
  *result = rb_str_intern(*result);
1695
+ } else if (RB_TYPE_P(*result, T_STRING)) {
1696
+ # if STR_UMINUS_DEDUPE_FROZEN
1697
+ if (json->freeze) {
1698
+ // Starting from MRI 2.8 it is preferable to freeze the string
1699
+ // before deduplication so that it can be interned directly
1700
+ // otherwise it would be duplicated first which is wasteful.
1701
+ *result = rb_funcall(rb_str_freeze(*result), i_uminus, 0);
1702
+ }
1703
+ # elif STR_UMINUS_DEDUPE
1704
+ if (json->freeze) {
1705
+ // MRI 2.5 and older do not deduplicate strings that are already
1706
+ // frozen.
1707
+ *result = rb_funcall(*result, i_uminus, 0);
1708
+ }
1709
+ # else
1710
+ rb_str_resize(*result, RSTRING_LEN(*result));
1711
+ # endif
1567
1712
  }
1568
1713
  if (cs >= JSON_string_first_final) {
1569
1714
  return p + 1;
@@ -1586,41 +1731,16 @@ case 7:
1586
1731
 
1587
1732
  static VALUE convert_encoding(VALUE source)
1588
1733
  {
1589
- const char *ptr = RSTRING_PTR(source);
1590
- long len = RSTRING_LEN(source);
1591
- if (len < 2) {
1592
- rb_raise(eParserError, "A JSON text must at least contain two octets!");
1593
- }
1594
1734
  #ifdef HAVE_RUBY_ENCODING_H
1595
- {
1596
- rb_encoding *enc = rb_enc_get(source);
1597
- if (enc == rb_ascii8bit_encoding()) {
1598
- if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
1599
- source = rb_str_conv_enc(source, UTF_32BE, rb_utf8_encoding());
1600
- } else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
1601
- source = rb_str_conv_enc(source, UTF_16BE, rb_utf8_encoding());
1602
- } else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
1603
- source = rb_str_conv_enc(source, UTF_32LE, rb_utf8_encoding());
1604
- } else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
1605
- source = rb_str_conv_enc(source, UTF_16LE, rb_utf8_encoding());
1606
- } else {
1607
- source = rb_str_dup(source);
1608
- FORCE_UTF8(source);
1609
- }
1610
- } else {
1611
- source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding());
1612
- }
1613
- }
1614
- #else
1615
- if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
1616
- source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-32be"), source);
1617
- } else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
1618
- source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-16be"), source);
1619
- } else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
1620
- source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-32le"), source);
1621
- } else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
1622
- source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-16le"), source);
1735
+ rb_encoding *enc = rb_enc_get(source);
1736
+ if (enc == rb_ascii8bit_encoding()) {
1737
+ if (OBJ_FROZEN(source)) {
1738
+ source = rb_str_dup(source);
1623
1739
  }
1740
+ FORCE_UTF8(source);
1741
+ } else {
1742
+ source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding());
1743
+ }
1624
1744
  #endif
1625
1745
  return source;
1626
1746
  }
@@ -1643,8 +1763,9 @@ static VALUE convert_encoding(VALUE source)
1643
1763
  * defiance of RFC 4627 to be parsed by the Parser. This option defaults to
1644
1764
  * false.
1645
1765
  * * *symbolize_names*: If set to true, returns symbols for the names
1646
- * (keys) in a JSON object. Otherwise strings are returned, which is also
1647
- * the default.
1766
+ * (keys) in a JSON object. Otherwise strings are returned, which is
1767
+ * also the default. It's not possible to use this option in
1768
+ * conjunction with the *create_additions* option.
1648
1769
  * * *create_additions*: If set to false, the Parser doesn't create
1649
1770
  * additions even if a matching class and create_id was found. This option
1650
1771
  * defaults to false.
@@ -1695,12 +1816,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
1695
1816
  } else {
1696
1817
  json->symbolize_names = 0;
1697
1818
  }
1698
- tmp = ID2SYM(i_quirks_mode);
1819
+ tmp = ID2SYM(i_freeze);
1699
1820
  if (option_given_p(opts, tmp)) {
1700
- VALUE quirks_mode = rb_hash_aref(opts, tmp);
1701
- json->quirks_mode = RTEST(quirks_mode) ? 1 : 0;
1821
+ json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
1702
1822
  } else {
1703
- json->quirks_mode = 0;
1823
+ json->freeze = 0;
1704
1824
  }
1705
1825
  tmp = ID2SYM(i_create_additions);
1706
1826
  if (option_given_p(opts, tmp)) {
@@ -1708,6 +1828,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
1708
1828
  } else {
1709
1829
  json->create_additions = 0;
1710
1830
  }
1831
+ if (json->symbolize_names && json->create_additions) {
1832
+ rb_raise(rb_eArgError,
1833
+ "options :symbolize_names and :create_additions cannot be "
1834
+ " used in conjunction");
1835
+ }
1711
1836
  tmp = ID2SYM(i_create_id);
1712
1837
  if (option_given_p(opts, tmp)) {
1713
1838
  json->create_id = rb_hash_aref(opts, tmp);
@@ -1726,6 +1851,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
1726
1851
  } else {
1727
1852
  json->array_class = Qnil;
1728
1853
  }
1854
+ tmp = ID2SYM(i_decimal_class);
1855
+ if (option_given_p(opts, tmp)) {
1856
+ json->decimal_class = rb_hash_aref(opts, tmp);
1857
+ } else {
1858
+ json->decimal_class = Qnil;
1859
+ }
1729
1860
  tmp = ID2SYM(i_match_string);
1730
1861
  if (option_given_p(opts, tmp)) {
1731
1862
  VALUE match_string = rb_hash_aref(opts, tmp);
@@ -1739,16 +1870,14 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
1739
1870
  } else {
1740
1871
  json->max_nesting = 100;
1741
1872
  json->allow_nan = 0;
1742
- json->create_additions = 1;
1873
+ json->create_additions = 0;
1743
1874
  json->create_id = rb_funcall(mJSON, i_create_id, 0);
1744
1875
  json->object_class = Qnil;
1745
1876
  json->array_class = Qnil;
1877
+ json->decimal_class = Qnil;
1746
1878
  }
1879
+ source = convert_encoding(StringValue(source));
1747
1880
  StringValue(source);
1748
- if (!json->quirks_mode) {
1749
- source = convert_encoding(source);
1750
- }
1751
- json->current_nesting = 0;
1752
1881
  json->len = RSTRING_LEN(source);
1753
1882
  json->source = RSTRING_PTR(source);;
1754
1883
  json->Vsource = source;
@@ -1756,209 +1885,41 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
1756
1885
  }
1757
1886
 
1758
1887
 
1759
- #line 1760 "parser.c"
1760
- static const int JSON_start = 1;
1761
- static const int JSON_first_final = 10;
1762
- static const int JSON_error = 0;
1888
+ #line 1878 "parser.c"
1889
+ enum {JSON_start = 1};
1890
+ enum {JSON_first_final = 10};
1891
+ enum {JSON_error = 0};
1763
1892
 
1764
- static const int JSON_en_main = 1;
1893
+ enum {JSON_en_main = 1};
1765
1894
 
1766
1895
 
1767
- #line 767 "parser.rl"
1896
+ #line 786 "parser.rl"
1768
1897
 
1769
1898
 
1770
- static VALUE cParser_parse_strict(VALUE self)
1899
+ /*
1900
+ * call-seq: parse()
1901
+ *
1902
+ * Parses the current JSON text _source_ and returns the complete data
1903
+ * structure as a result.
1904
+ */
1905
+ static VALUE cParser_parse(VALUE self)
1771
1906
  {
1772
- char *p, *pe;
1773
- int cs = EVIL;
1774
- VALUE result = Qnil;
1775
- GET_PARSER;
1907
+ char *p, *pe;
1908
+ int cs = EVIL;
1909
+ VALUE result = Qnil;
1910
+ GET_PARSER;
1776
1911
 
1777
1912
 
1778
- #line 1779 "parser.c"
1913
+ #line 1903 "parser.c"
1779
1914
  {
1780
1915
  cs = JSON_start;
1781
1916
  }
1782
1917
 
1783
- #line 777 "parser.rl"
1784
- p = json->source;
1785
- pe = p + json->len;
1918
+ #line 802 "parser.rl"
1919
+ p = json->source;
1920
+ pe = p + json->len;
1786
1921
 
1787
- #line 1788 "parser.c"
1788
- {
1789
- if ( p == pe )
1790
- goto _test_eof;
1791
- switch ( cs )
1792
- {
1793
- st1:
1794
- if ( ++p == pe )
1795
- goto _test_eof1;
1796
- case 1:
1797
- switch( (*p) ) {
1798
- case 13: goto st1;
1799
- case 32: goto st1;
1800
- case 47: goto st2;
1801
- case 91: goto tr3;
1802
- case 123: goto tr4;
1803
- }
1804
- if ( 9 <= (*p) && (*p) <= 10 )
1805
- goto st1;
1806
- goto st0;
1807
- st0:
1808
- cs = 0;
1809
- goto _out;
1810
- st2:
1811
- if ( ++p == pe )
1812
- goto _test_eof2;
1813
- case 2:
1814
- switch( (*p) ) {
1815
- case 42: goto st3;
1816
- case 47: goto st5;
1817
- }
1818
- goto st0;
1819
- st3:
1820
- if ( ++p == pe )
1821
- goto _test_eof3;
1822
- case 3:
1823
- if ( (*p) == 42 )
1824
- goto st4;
1825
- goto st3;
1826
- st4:
1827
- if ( ++p == pe )
1828
- goto _test_eof4;
1829
- case 4:
1830
- switch( (*p) ) {
1831
- case 42: goto st4;
1832
- case 47: goto st1;
1833
- }
1834
- goto st3;
1835
- st5:
1836
- if ( ++p == pe )
1837
- goto _test_eof5;
1838
- case 5:
1839
- if ( (*p) == 10 )
1840
- goto st1;
1841
- goto st5;
1842
- tr3:
1843
- #line 756 "parser.rl"
1844
- {
1845
- char *np;
1846
- json->current_nesting = 1;
1847
- np = JSON_parse_array(json, p, pe, &result);
1848
- if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
1849
- }
1850
- goto st10;
1851
- tr4:
1852
- #line 749 "parser.rl"
1853
- {
1854
- char *np;
1855
- json->current_nesting = 1;
1856
- np = JSON_parse_object(json, p, pe, &result);
1857
- if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
1858
- }
1859
- goto st10;
1860
- st10:
1861
- if ( ++p == pe )
1862
- goto _test_eof10;
1863
- case 10:
1864
- #line 1865 "parser.c"
1865
- switch( (*p) ) {
1866
- case 13: goto st10;
1867
- case 32: goto st10;
1868
- case 47: goto st6;
1869
- }
1870
- if ( 9 <= (*p) && (*p) <= 10 )
1871
- goto st10;
1872
- goto st0;
1873
- st6:
1874
- if ( ++p == pe )
1875
- goto _test_eof6;
1876
- case 6:
1877
- switch( (*p) ) {
1878
- case 42: goto st7;
1879
- case 47: goto st9;
1880
- }
1881
- goto st0;
1882
- st7:
1883
- if ( ++p == pe )
1884
- goto _test_eof7;
1885
- case 7:
1886
- if ( (*p) == 42 )
1887
- goto st8;
1888
- goto st7;
1889
- st8:
1890
- if ( ++p == pe )
1891
- goto _test_eof8;
1892
- case 8:
1893
- switch( (*p) ) {
1894
- case 42: goto st8;
1895
- case 47: goto st10;
1896
- }
1897
- goto st7;
1898
- st9:
1899
- if ( ++p == pe )
1900
- goto _test_eof9;
1901
- case 9:
1902
- if ( (*p) == 10 )
1903
- goto st10;
1904
- goto st9;
1905
- }
1906
- _test_eof1: cs = 1; goto _test_eof;
1907
- _test_eof2: cs = 2; goto _test_eof;
1908
- _test_eof3: cs = 3; goto _test_eof;
1909
- _test_eof4: cs = 4; goto _test_eof;
1910
- _test_eof5: cs = 5; goto _test_eof;
1911
- _test_eof10: cs = 10; goto _test_eof;
1912
- _test_eof6: cs = 6; goto _test_eof;
1913
- _test_eof7: cs = 7; goto _test_eof;
1914
- _test_eof8: cs = 8; goto _test_eof;
1915
- _test_eof9: cs = 9; goto _test_eof;
1916
-
1917
- _test_eof: {}
1918
- _out: {}
1919
- }
1920
-
1921
- #line 780 "parser.rl"
1922
-
1923
- if (cs >= JSON_first_final && p == pe) {
1924
- return result;
1925
- } else {
1926
- rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
1927
- return Qnil;
1928
- }
1929
- }
1930
-
1931
-
1932
-
1933
- #line 1934 "parser.c"
1934
- static const int JSON_quirks_mode_start = 1;
1935
- static const int JSON_quirks_mode_first_final = 10;
1936
- static const int JSON_quirks_mode_error = 0;
1937
-
1938
- static const int JSON_quirks_mode_en_main = 1;
1939
-
1940
-
1941
- #line 805 "parser.rl"
1942
-
1943
-
1944
- static VALUE cParser_parse_quirks_mode(VALUE self)
1945
- {
1946
- char *p, *pe;
1947
- int cs = EVIL;
1948
- VALUE result = Qnil;
1949
- GET_PARSER;
1950
-
1951
-
1952
- #line 1953 "parser.c"
1953
- {
1954
- cs = JSON_quirks_mode_start;
1955
- }
1956
-
1957
- #line 815 "parser.rl"
1958
- p = json->source;
1959
- pe = p + json->len;
1960
-
1961
- #line 1962 "parser.c"
1922
+ #line 1912 "parser.c"
1962
1923
  {
1963
1924
  if ( p == pe )
1964
1925
  goto _test_eof;
@@ -1992,9 +1953,9 @@ st0:
1992
1953
  cs = 0;
1993
1954
  goto _out;
1994
1955
  tr2:
1995
- #line 797 "parser.rl"
1956
+ #line 778 "parser.rl"
1996
1957
  {
1997
- char *np = JSON_parse_value(json, p, pe, &result);
1958
+ char *np = JSON_parse_value(json, p, pe, &result, 0);
1998
1959
  if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
1999
1960
  }
2000
1961
  goto st10;
@@ -2002,7 +1963,7 @@ st10:
2002
1963
  if ( ++p == pe )
2003
1964
  goto _test_eof10;
2004
1965
  case 10:
2005
- #line 2006 "parser.c"
1966
+ #line 1956 "parser.c"
2006
1967
  switch( (*p) ) {
2007
1968
  case 13: goto st10;
2008
1969
  case 32: goto st10;
@@ -2091,30 +2052,13 @@ case 9:
2091
2052
  _out: {}
2092
2053
  }
2093
2054
 
2094
- #line 818 "parser.rl"
2095
-
2096
- if (cs >= JSON_quirks_mode_first_final && p == pe) {
2097
- return result;
2098
- } else {
2099
- rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
2100
- return Qnil;
2101
- }
2102
- }
2103
-
2104
- /*
2105
- * call-seq: parse()
2106
- *
2107
- * Parses the current JSON text _source_ and returns the complete data
2108
- * structure as a result.
2109
- */
2110
- static VALUE cParser_parse(VALUE self)
2111
- {
2112
- GET_PARSER;
2055
+ #line 805 "parser.rl"
2113
2056
 
2114
- if (json->quirks_mode) {
2115
- return cParser_parse_quirks_mode(self);
2057
+ if (cs >= JSON_first_final && p == pe) {
2058
+ return result;
2116
2059
  } else {
2117
- return cParser_parse_strict(self);
2060
+ rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
2061
+ return Qnil;
2118
2062
  }
2119
2063
  }
2120
2064
 
@@ -2125,6 +2069,7 @@ static void JSON_mark(void *ptr)
2125
2069
  rb_gc_mark_maybe(json->create_id);
2126
2070
  rb_gc_mark_maybe(json->object_class);
2127
2071
  rb_gc_mark_maybe(json->array_class);
2072
+ rb_gc_mark_maybe(json->decimal_class);
2128
2073
  rb_gc_mark_maybe(json->match_string);
2129
2074
  }
2130
2075
 
@@ -2172,35 +2117,34 @@ static VALUE cParser_source(VALUE self)
2172
2117
  return rb_str_dup(json->Vsource);
2173
2118
  }
2174
2119
 
2175
- /*
2176
- * call-seq: quirks_mode?()
2177
- *
2178
- * Returns a true, if this parser is in quirks_mode, false otherwise.
2179
- */
2180
- static VALUE cParser_quirks_mode_p(VALUE self)
2181
- {
2182
- GET_PARSER;
2183
- return json->quirks_mode ? Qtrue : Qfalse;
2184
- }
2185
-
2186
-
2187
2120
  void Init_parser(void)
2188
2121
  {
2122
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
2123
+ rb_ext_ractor_safe(true);
2124
+ #endif
2125
+
2126
+ #undef rb_intern
2189
2127
  rb_require("json/common");
2190
2128
  mJSON = rb_define_module("JSON");
2191
2129
  mExt = rb_define_module_under(mJSON, "Ext");
2192
2130
  cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
2193
2131
  eParserError = rb_path2class("JSON::ParserError");
2194
2132
  eNestingError = rb_path2class("JSON::NestingError");
2133
+ rb_gc_register_mark_object(eParserError);
2134
+ rb_gc_register_mark_object(eNestingError);
2195
2135
  rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
2196
2136
  rb_define_method(cParser, "initialize", cParser_initialize, -1);
2197
2137
  rb_define_method(cParser, "parse", cParser_parse, 0);
2198
2138
  rb_define_method(cParser, "source", cParser_source, 0);
2199
- rb_define_method(cParser, "quirks_mode?", cParser_quirks_mode_p, 0);
2200
2139
 
2201
2140
  CNaN = rb_const_get(mJSON, rb_intern("NaN"));
2141
+ rb_gc_register_mark_object(CNaN);
2142
+
2202
2143
  CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
2144
+ rb_gc_register_mark_object(CInfinity);
2145
+
2203
2146
  CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
2147
+ rb_gc_register_mark_object(CMinusInfinity);
2204
2148
 
2205
2149
  i_json_creatable_p = rb_intern("json_creatable?");
2206
2150
  i_json_create = rb_intern("json_create");
@@ -2210,9 +2154,9 @@ void Init_parser(void)
2210
2154
  i_max_nesting = rb_intern("max_nesting");
2211
2155
  i_allow_nan = rb_intern("allow_nan");
2212
2156
  i_symbolize_names = rb_intern("symbolize_names");
2213
- i_quirks_mode = rb_intern("quirks_mode");
2214
2157
  i_object_class = rb_intern("object_class");
2215
2158
  i_array_class = rb_intern("array_class");
2159
+ i_decimal_class = rb_intern("decimal_class");
2216
2160
  i_match = rb_intern("match");
2217
2161
  i_match_string = rb_intern("match_string");
2218
2162
  i_key_p = rb_intern("key?");
@@ -2220,15 +2164,10 @@ void Init_parser(void)
2220
2164
  i_aset = rb_intern("[]=");
2221
2165
  i_aref = rb_intern("[]");
2222
2166
  i_leftshift = rb_intern("<<");
2223
- #ifdef HAVE_RUBY_ENCODING_H
2224
- UTF_8 = rb_utf8_encoding();
2225
- UTF_16BE = rb_enc_find("utf-16be");
2226
- UTF_16LE = rb_enc_find("utf-16le");
2227
- UTF_32BE = rb_enc_find("utf-32be");
2228
- UTF_32LE = rb_enc_find("utf-32le");
2229
- #else
2230
- i_iconv = rb_intern("iconv");
2231
- #endif
2167
+ i_new = rb_intern("new");
2168
+ i_try_convert = rb_intern("try_convert");
2169
+ i_freeze = rb_intern("freeze");
2170
+ i_uminus = rb_intern("-@");
2232
2171
  }
2233
2172
 
2234
2173
  /*