json 2.0.3 → 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 (71) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGES.md +66 -0
  3. data/Gemfile +1 -3
  4. data/LICENSE +56 -0
  5. data/README.md +54 -21
  6. data/VERSION +1 -1
  7. data/ext/json/ext/fbuffer/fbuffer.h +0 -3
  8. data/ext/json/ext/generator/generator.c +229 -54
  9. data/ext/json/ext/generator/generator.h +5 -3
  10. data/ext/json/ext/parser/extconf.rb +25 -0
  11. data/ext/json/ext/parser/parser.c +180 -85
  12. data/ext/json/ext/parser/parser.h +2 -0
  13. data/ext/json/ext/parser/parser.rl +104 -9
  14. data/ext/json/extconf.rb +1 -0
  15. data/json.gemspec +0 -0
  16. data/lib/json/add/bigdecimal.rb +2 -2
  17. data/lib/json/add/complex.rb +2 -3
  18. data/lib/json/add/ostruct.rb +1 -1
  19. data/lib/json/add/rational.rb +2 -3
  20. data/lib/json/add/regexp.rb +2 -2
  21. data/lib/json/add/set.rb +29 -0
  22. data/lib/json/common.rb +372 -125
  23. data/lib/json/pure/generator.rb +31 -10
  24. data/lib/json/pure/parser.rb +35 -5
  25. data/lib/json/version.rb +1 -1
  26. data/lib/json.rb +549 -29
  27. data/tests/fixtures/fail29.json +1 -0
  28. data/tests/fixtures/fail30.json +1 -0
  29. data/tests/fixtures/fail31.json +1 -0
  30. data/tests/fixtures/fail32.json +1 -0
  31. data/tests/json_addition_test.rb +6 -0
  32. data/tests/json_common_interface_test.rb +47 -4
  33. data/tests/json_encoding_test.rb +2 -0
  34. data/tests/json_fixtures_test.rb +9 -1
  35. data/tests/json_generator_test.rb +30 -8
  36. data/tests/json_parser_test.rb +43 -12
  37. data/tests/lib/core_assertions.rb +763 -0
  38. data/tests/lib/envutil.rb +365 -0
  39. data/tests/lib/find_executable.rb +22 -0
  40. data/tests/lib/helper.rb +4 -0
  41. data/tests/ractor_test.rb +30 -0
  42. data/tests/test_helper.rb +3 -7
  43. metadata +31 -44
  44. data/.gitignore +0 -17
  45. data/.travis.yml +0 -19
  46. data/README-json-jruby.md +0 -33
  47. data/Rakefile +0 -408
  48. data/data/example.json +0 -1
  49. data/data/index.html +0 -38
  50. data/data/prototype.js +0 -4184
  51. data/diagrams/.keep +0 -0
  52. data/install.rb +0 -23
  53. data/java/src/json/ext/ByteListTranscoder.java +0 -166
  54. data/java/src/json/ext/Generator.java +0 -443
  55. data/java/src/json/ext/GeneratorMethods.java +0 -231
  56. data/java/src/json/ext/GeneratorService.java +0 -42
  57. data/java/src/json/ext/GeneratorState.java +0 -490
  58. data/java/src/json/ext/OptionsReader.java +0 -113
  59. data/java/src/json/ext/Parser.java +0 -2347
  60. data/java/src/json/ext/Parser.rl +0 -878
  61. data/java/src/json/ext/ParserService.java +0 -34
  62. data/java/src/json/ext/RuntimeInfo.java +0 -116
  63. data/java/src/json/ext/StringDecoder.java +0 -166
  64. data/java/src/json/ext/StringEncoder.java +0 -111
  65. data/java/src/json/ext/Utils.java +0 -88
  66. data/json-java.gemspec +0 -38
  67. data/json_pure.gemspec +0 -38
  68. data/references/rfc7159.txt +0 -899
  69. data/tools/diff.sh +0 -18
  70. data/tools/fuzz.rb +0 -131
  71. data/tools/server.rb +0 -62
@@ -1,4 +1,4 @@
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"
@@ -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;
@@ -94,15 +94,16 @@ static VALUE CNaN, CInfinity, CMinusInfinity;
94
94
 
95
95
  static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
96
96
  i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
97
- i_object_class, i_array_class, i_key_p, i_deep_const_get, i_match,
98
- i_match_string, i_aset, i_aref, i_leftshift;
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;
99
100
 
100
101
 
101
- #line 124 "parser.rl"
102
+ #line 126 "parser.rl"
102
103
 
103
104
 
104
105
 
105
- #line 106 "parser.c"
106
+ #line 108 "parser.c"
106
107
  enum {JSON_object_start = 1};
107
108
  enum {JSON_object_first_final = 27};
108
109
  enum {JSON_object_error = 0};
@@ -110,7 +111,7 @@ enum {JSON_object_error = 0};
110
111
  enum {JSON_object_en_main = 1};
111
112
 
112
113
 
113
- #line 165 "parser.rl"
114
+ #line 168 "parser.rl"
114
115
 
115
116
 
116
117
  static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
@@ -126,14 +127,14 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
126
127
  *result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class);
127
128
 
128
129
 
129
- #line 130 "parser.c"
130
+ #line 132 "parser.c"
130
131
  {
131
132
  cs = JSON_object_start;
132
133
  }
133
134
 
134
- #line 180 "parser.rl"
135
+ #line 183 "parser.rl"
135
136
 
136
- #line 137 "parser.c"
137
+ #line 139 "parser.c"
137
138
  {
138
139
  if ( p == pe )
139
140
  goto _test_eof;
@@ -161,7 +162,7 @@ case 2:
161
162
  goto st2;
162
163
  goto st0;
163
164
  tr2:
164
- #line 147 "parser.rl"
165
+ #line 150 "parser.rl"
165
166
  {
166
167
  char *np;
167
168
  json->parsing_name = 1;
@@ -174,7 +175,7 @@ st3:
174
175
  if ( ++p == pe )
175
176
  goto _test_eof3;
176
177
  case 3:
177
- #line 178 "parser.c"
178
+ #line 180 "parser.c"
178
179
  switch( (*p) ) {
179
180
  case 13: goto st3;
180
181
  case 32: goto st3;
@@ -241,7 +242,7 @@ case 8:
241
242
  goto st8;
242
243
  goto st0;
243
244
  tr11:
244
- #line 132 "parser.rl"
245
+ #line 134 "parser.rl"
245
246
  {
246
247
  VALUE v = Qnil;
247
248
  char *np = JSON_parse_value(json, p, pe, &v, current_nesting);
@@ -249,6 +250,7 @@ tr11:
249
250
  p--; {p++; cs = 9; goto _out;}
250
251
  } else {
251
252
  if (NIL_P(json->object_class)) {
253
+ OBJ_FREEZE(last_name);
252
254
  rb_hash_aset(*result, last_name, v);
253
255
  } else {
254
256
  rb_funcall(*result, i_aset, 2, last_name, v);
@@ -261,7 +263,7 @@ st9:
261
263
  if ( ++p == pe )
262
264
  goto _test_eof9;
263
265
  case 9:
264
- #line 265 "parser.c"
266
+ #line 268 "parser.c"
265
267
  switch( (*p) ) {
266
268
  case 13: goto st9;
267
269
  case 32: goto st9;
@@ -350,14 +352,14 @@ case 18:
350
352
  goto st9;
351
353
  goto st18;
352
354
  tr4:
353
- #line 155 "parser.rl"
355
+ #line 158 "parser.rl"
354
356
  { p--; {p++; cs = 27; goto _out;} }
355
357
  goto st27;
356
358
  st27:
357
359
  if ( ++p == pe )
358
360
  goto _test_eof27;
359
361
  case 27:
360
- #line 361 "parser.c"
362
+ #line 364 "parser.c"
361
363
  goto st0;
362
364
  st19:
363
365
  if ( ++p == pe )
@@ -455,7 +457,7 @@ case 26:
455
457
  _out: {}
456
458
  }
457
459
 
458
- #line 181 "parser.rl"
460
+ #line 184 "parser.rl"
459
461
 
460
462
  if (cs >= JSON_object_first_final) {
461
463
  if (json->create_additions) {
@@ -480,7 +482,7 @@ case 26:
480
482
 
481
483
 
482
484
 
483
- #line 484 "parser.c"
485
+ #line 487 "parser.c"
484
486
  enum {JSON_value_start = 1};
485
487
  enum {JSON_value_first_final = 29};
486
488
  enum {JSON_value_error = 0};
@@ -488,7 +490,7 @@ enum {JSON_value_error = 0};
488
490
  enum {JSON_value_en_main = 1};
489
491
 
490
492
 
491
- #line 281 "parser.rl"
493
+ #line 284 "parser.rl"
492
494
 
493
495
 
494
496
  static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
@@ -496,14 +498,14 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
496
498
  int cs = EVIL;
497
499
 
498
500
 
499
- #line 500 "parser.c"
501
+ #line 503 "parser.c"
500
502
  {
501
503
  cs = JSON_value_start;
502
504
  }
503
505
 
504
- #line 288 "parser.rl"
506
+ #line 291 "parser.rl"
505
507
 
506
- #line 507 "parser.c"
508
+ #line 510 "parser.c"
507
509
  {
508
510
  if ( p == pe )
509
511
  goto _test_eof;
@@ -537,14 +539,14 @@ st0:
537
539
  cs = 0;
538
540
  goto _out;
539
541
  tr2:
540
- #line 233 "parser.rl"
542
+ #line 236 "parser.rl"
541
543
  {
542
544
  char *np = JSON_parse_string(json, p, pe, result);
543
545
  if (np == NULL) { p--; {p++; cs = 29; goto _out;} } else {p = (( np))-1;}
544
546
  }
545
547
  goto st29;
546
548
  tr3:
547
- #line 238 "parser.rl"
549
+ #line 241 "parser.rl"
548
550
  {
549
551
  char *np;
550
552
  if(pe > p + 8 && !strncmp(MinusInfinity, p, 9)) {
@@ -564,7 +566,7 @@ tr3:
564
566
  }
565
567
  goto st29;
566
568
  tr7:
567
- #line 256 "parser.rl"
569
+ #line 259 "parser.rl"
568
570
  {
569
571
  char *np;
570
572
  np = JSON_parse_array(json, p, pe, result, current_nesting + 1);
@@ -572,7 +574,7 @@ tr7:
572
574
  }
573
575
  goto st29;
574
576
  tr11:
575
- #line 262 "parser.rl"
577
+ #line 265 "parser.rl"
576
578
  {
577
579
  char *np;
578
580
  np = JSON_parse_object(json, p, pe, result, current_nesting + 1);
@@ -580,7 +582,7 @@ tr11:
580
582
  }
581
583
  goto st29;
582
584
  tr25:
583
- #line 226 "parser.rl"
585
+ #line 229 "parser.rl"
584
586
  {
585
587
  if (json->allow_nan) {
586
588
  *result = CInfinity;
@@ -590,7 +592,7 @@ tr25:
590
592
  }
591
593
  goto st29;
592
594
  tr27:
593
- #line 219 "parser.rl"
595
+ #line 222 "parser.rl"
594
596
  {
595
597
  if (json->allow_nan) {
596
598
  *result = CNaN;
@@ -600,19 +602,19 @@ tr27:
600
602
  }
601
603
  goto st29;
602
604
  tr31:
603
- #line 213 "parser.rl"
605
+ #line 216 "parser.rl"
604
606
  {
605
607
  *result = Qfalse;
606
608
  }
607
609
  goto st29;
608
610
  tr34:
609
- #line 210 "parser.rl"
611
+ #line 213 "parser.rl"
610
612
  {
611
613
  *result = Qnil;
612
614
  }
613
615
  goto st29;
614
616
  tr37:
615
- #line 216 "parser.rl"
617
+ #line 219 "parser.rl"
616
618
  {
617
619
  *result = Qtrue;
618
620
  }
@@ -621,9 +623,9 @@ st29:
621
623
  if ( ++p == pe )
622
624
  goto _test_eof29;
623
625
  case 29:
624
- #line 268 "parser.rl"
626
+ #line 271 "parser.rl"
625
627
  { p--; {p++; cs = 29; goto _out;} }
626
- #line 627 "parser.c"
628
+ #line 630 "parser.c"
627
629
  switch( (*p) ) {
628
630
  case 13: goto st29;
629
631
  case 32: goto st29;
@@ -864,7 +866,11 @@ case 28:
864
866
  _out: {}
865
867
  }
866
868
 
867
- #line 289 "parser.rl"
869
+ #line 292 "parser.rl"
870
+
871
+ if (json->freeze) {
872
+ OBJ_FREEZE(*result);
873
+ }
868
874
 
869
875
  if (cs >= JSON_value_first_final) {
870
876
  return p;
@@ -874,7 +880,7 @@ case 28:
874
880
  }
875
881
 
876
882
 
877
- #line 878 "parser.c"
883
+ #line 885 "parser.c"
878
884
  enum {JSON_integer_start = 1};
879
885
  enum {JSON_integer_first_final = 3};
880
886
  enum {JSON_integer_error = 0};
@@ -882,7 +888,7 @@ enum {JSON_integer_error = 0};
882
888
  enum {JSON_integer_en_main = 1};
883
889
 
884
890
 
885
- #line 305 "parser.rl"
891
+ #line 312 "parser.rl"
886
892
 
887
893
 
888
894
  static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -890,15 +896,15 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
890
896
  int cs = EVIL;
891
897
 
892
898
 
893
- #line 894 "parser.c"
899
+ #line 901 "parser.c"
894
900
  {
895
901
  cs = JSON_integer_start;
896
902
  }
897
903
 
898
- #line 312 "parser.rl"
904
+ #line 319 "parser.rl"
899
905
  json->memo = p;
900
906
 
901
- #line 902 "parser.c"
907
+ #line 909 "parser.c"
902
908
  {
903
909
  if ( p == pe )
904
910
  goto _test_eof;
@@ -932,14 +938,14 @@ case 3:
932
938
  goto st0;
933
939
  goto tr4;
934
940
  tr4:
935
- #line 302 "parser.rl"
941
+ #line 309 "parser.rl"
936
942
  { p--; {p++; cs = 4; goto _out;} }
937
943
  goto st4;
938
944
  st4:
939
945
  if ( ++p == pe )
940
946
  goto _test_eof4;
941
947
  case 4:
942
- #line 943 "parser.c"
948
+ #line 950 "parser.c"
943
949
  goto st0;
944
950
  st5:
945
951
  if ( ++p == pe )
@@ -958,7 +964,7 @@ case 5:
958
964
  _out: {}
959
965
  }
960
966
 
961
- #line 314 "parser.rl"
967
+ #line 321 "parser.rl"
962
968
 
963
969
  if (cs >= JSON_integer_first_final) {
964
970
  long len = p - json->memo;
@@ -973,7 +979,7 @@ case 5:
973
979
  }
974
980
 
975
981
 
976
- #line 977 "parser.c"
982
+ #line 984 "parser.c"
977
983
  enum {JSON_float_start = 1};
978
984
  enum {JSON_float_first_final = 8};
979
985
  enum {JSON_float_error = 0};
@@ -981,7 +987,7 @@ enum {JSON_float_error = 0};
981
987
  enum {JSON_float_en_main = 1};
982
988
 
983
989
 
984
- #line 339 "parser.rl"
990
+ #line 346 "parser.rl"
985
991
 
986
992
 
987
993
  static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -989,15 +995,15 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
989
995
  int cs = EVIL;
990
996
 
991
997
 
992
- #line 993 "parser.c"
998
+ #line 1013 "parser.c"
993
999
  {
994
1000
  cs = JSON_float_start;
995
1001
  }
996
1002
 
997
- #line 346 "parser.rl"
1003
+ #line 366 "parser.rl"
998
1004
  json->memo = p;
999
1005
 
1000
- #line 1001 "parser.c"
1006
+ #line 1021 "parser.c"
1001
1007
  {
1002
1008
  if ( p == pe )
1003
1009
  goto _test_eof;
@@ -1055,14 +1061,14 @@ case 8:
1055
1061
  goto st0;
1056
1062
  goto tr9;
1057
1063
  tr9:
1058
- #line 333 "parser.rl"
1064
+ #line 340 "parser.rl"
1059
1065
  { p--; {p++; cs = 9; goto _out;} }
1060
1066
  goto st9;
1061
1067
  st9:
1062
1068
  if ( ++p == pe )
1063
1069
  goto _test_eof9;
1064
1070
  case 9:
1065
- #line 1066 "parser.c"
1071
+ #line 1086 "parser.c"
1066
1072
  goto st0;
1067
1073
  st5:
1068
1074
  if ( ++p == pe )
@@ -1123,14 +1129,49 @@ case 7:
1123
1129
  _out: {}
1124
1130
  }
1125
1131
 
1126
- #line 348 "parser.rl"
1132
+ #line 368 "parser.rl"
1127
1133
 
1128
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
+
1129
1163
  long len = p - json->memo;
1130
1164
  fbuffer_clear(json->fbuffer);
1131
1165
  fbuffer_append(json->fbuffer, json->memo, len);
1132
1166
  fbuffer_append_char(json->fbuffer, '\0');
1133
- *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
+
1134
1175
  return p + 1;
1135
1176
  } else {
1136
1177
  return NULL;
@@ -1139,7 +1180,7 @@ case 7:
1139
1180
 
1140
1181
 
1141
1182
 
1142
- #line 1143 "parser.c"
1183
+ #line 1173 "parser.c"
1143
1184
  enum {JSON_array_start = 1};
1144
1185
  enum {JSON_array_first_final = 17};
1145
1186
  enum {JSON_array_error = 0};
@@ -1147,7 +1188,7 @@ enum {JSON_array_error = 0};
1147
1188
  enum {JSON_array_en_main = 1};
1148
1189
 
1149
1190
 
1150
- #line 391 "parser.rl"
1191
+ #line 421 "parser.rl"
1151
1192
 
1152
1193
 
1153
1194
  static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
@@ -1161,14 +1202,14 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
1161
1202
  *result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
1162
1203
 
1163
1204
 
1164
- #line 1165 "parser.c"
1205
+ #line 1195 "parser.c"
1165
1206
  {
1166
1207
  cs = JSON_array_start;
1167
1208
  }
1168
1209
 
1169
- #line 404 "parser.rl"
1210
+ #line 434 "parser.rl"
1170
1211
 
1171
- #line 1172 "parser.c"
1212
+ #line 1202 "parser.c"
1172
1213
  {
1173
1214
  if ( p == pe )
1174
1215
  goto _test_eof;
@@ -1207,7 +1248,7 @@ case 2:
1207
1248
  goto st2;
1208
1249
  goto st0;
1209
1250
  tr2:
1210
- #line 368 "parser.rl"
1251
+ #line 398 "parser.rl"
1211
1252
  {
1212
1253
  VALUE v = Qnil;
1213
1254
  char *np = JSON_parse_value(json, p, pe, &v, current_nesting);
@@ -1227,7 +1268,7 @@ st3:
1227
1268
  if ( ++p == pe )
1228
1269
  goto _test_eof3;
1229
1270
  case 3:
1230
- #line 1231 "parser.c"
1271
+ #line 1261 "parser.c"
1231
1272
  switch( (*p) ) {
1232
1273
  case 13: goto st3;
1233
1274
  case 32: goto st3;
@@ -1327,14 +1368,14 @@ case 12:
1327
1368
  goto st3;
1328
1369
  goto st12;
1329
1370
  tr4:
1330
- #line 383 "parser.rl"
1371
+ #line 413 "parser.rl"
1331
1372
  { p--; {p++; cs = 17; goto _out;} }
1332
1373
  goto st17;
1333
1374
  st17:
1334
1375
  if ( ++p == pe )
1335
1376
  goto _test_eof17;
1336
1377
  case 17:
1337
- #line 1338 "parser.c"
1378
+ #line 1368 "parser.c"
1338
1379
  goto st0;
1339
1380
  st13:
1340
1381
  if ( ++p == pe )
@@ -1390,7 +1431,7 @@ case 16:
1390
1431
  _out: {}
1391
1432
  }
1392
1433
 
1393
- #line 405 "parser.rl"
1434
+ #line 435 "parser.rl"
1394
1435
 
1395
1436
  if(cs >= JSON_array_first_final) {
1396
1437
  return p + 1;
@@ -1435,13 +1476,21 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
1435
1476
  break;
1436
1477
  case 'u':
1437
1478
  if (pe > stringEnd - 4) {
1438
- return Qnil;
1479
+ rb_enc_raise(
1480
+ EXC_ENCODING eParserError,
1481
+ "%u: incomplete unicode character escape sequence at '%s'", __LINE__, p
1482
+ );
1439
1483
  } else {
1440
1484
  UTF32 ch = unescape_unicode((unsigned char *) ++pe);
1441
1485
  pe += 3;
1442
1486
  if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
1443
1487
  pe++;
1444
- 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
+ }
1445
1494
  if (pe[0] == '\\' && pe[1] == 'u') {
1446
1495
  UTF32 sur = unescape_unicode((unsigned char *) pe + 2);
1447
1496
  ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16)
@@ -1471,7 +1520,7 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
1471
1520
  }
1472
1521
 
1473
1522
 
1474
- #line 1475 "parser.c"
1523
+ #line 1513 "parser.c"
1475
1524
  enum {JSON_string_start = 1};
1476
1525
  enum {JSON_string_first_final = 8};
1477
1526
  enum {JSON_string_error = 0};
@@ -1479,7 +1528,7 @@ enum {JSON_string_error = 0};
1479
1528
  enum {JSON_string_en_main = 1};
1480
1529
 
1481
1530
 
1482
- #line 504 "parser.rl"
1531
+ #line 542 "parser.rl"
1483
1532
 
1484
1533
 
1485
1534
  static int
@@ -1501,15 +1550,15 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
1501
1550
 
1502
1551
  *result = rb_str_buf_new(0);
1503
1552
 
1504
- #line 1505 "parser.c"
1553
+ #line 1543 "parser.c"
1505
1554
  {
1506
1555
  cs = JSON_string_start;
1507
1556
  }
1508
1557
 
1509
- #line 525 "parser.rl"
1558
+ #line 563 "parser.rl"
1510
1559
  json->memo = p;
1511
1560
 
1512
- #line 1513 "parser.c"
1561
+ #line 1551 "parser.c"
1513
1562
  {
1514
1563
  if ( p == pe )
1515
1564
  goto _test_eof;
@@ -1530,11 +1579,11 @@ case 2:
1530
1579
  case 34: goto tr2;
1531
1580
  case 92: goto st3;
1532
1581
  }
1533
- if ( 0 <= (*p) && (*p) <= 31 )
1582
+ if ( 0 <= (signed char)(*p) && (*p) <= 31 )
1534
1583
  goto st0;
1535
1584
  goto st2;
1536
1585
  tr2:
1537
- #line 490 "parser.rl"
1586
+ #line 528 "parser.rl"
1538
1587
  {
1539
1588
  *result = json_string_unescape(*result, json->memo + 1, p);
1540
1589
  if (NIL_P(*result)) {
@@ -1545,14 +1594,14 @@ tr2:
1545
1594
  {p = (( p + 1))-1;}
1546
1595
  }
1547
1596
  }
1548
- #line 501 "parser.rl"
1597
+ #line 539 "parser.rl"
1549
1598
  { p--; {p++; cs = 8; goto _out;} }
1550
1599
  goto st8;
1551
1600
  st8:
1552
1601
  if ( ++p == pe )
1553
1602
  goto _test_eof8;
1554
1603
  case 8:
1555
- #line 1556 "parser.c"
1604
+ #line 1594 "parser.c"
1556
1605
  goto st0;
1557
1606
  st3:
1558
1607
  if ( ++p == pe )
@@ -1560,7 +1609,7 @@ st3:
1560
1609
  case 3:
1561
1610
  if ( (*p) == 117 )
1562
1611
  goto st4;
1563
- if ( 0 <= (*p) && (*p) <= 31 )
1612
+ if ( 0 <= (signed char)(*p) && (*p) <= 31 )
1564
1613
  goto st0;
1565
1614
  goto st2;
1566
1615
  st4:
@@ -1628,7 +1677,7 @@ case 7:
1628
1677
  _out: {}
1629
1678
  }
1630
1679
 
1631
- #line 527 "parser.rl"
1680
+ #line 565 "parser.rl"
1632
1681
 
1633
1682
  if (json->create_additions && RTEST(match_string = json->match_string)) {
1634
1683
  VALUE klass;
@@ -1643,8 +1692,23 @@ case 7:
1643
1692
 
1644
1693
  if (json->symbolize_names && json->parsing_name) {
1645
1694
  *result = rb_str_intern(*result);
1646
- } else {
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
1647
1710
  rb_str_resize(*result, RSTRING_LEN(*result));
1711
+ # endif
1648
1712
  }
1649
1713
  if (cs >= JSON_string_first_final) {
1650
1714
  return p + 1;
@@ -1752,6 +1816,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
1752
1816
  } else {
1753
1817
  json->symbolize_names = 0;
1754
1818
  }
1819
+ tmp = ID2SYM(i_freeze);
1820
+ if (option_given_p(opts, tmp)) {
1821
+ json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
1822
+ } else {
1823
+ json->freeze = 0;
1824
+ }
1755
1825
  tmp = ID2SYM(i_create_additions);
1756
1826
  if (option_given_p(opts, tmp)) {
1757
1827
  json->create_additions = RTEST(rb_hash_aref(opts, tmp));
@@ -1781,6 +1851,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
1781
1851
  } else {
1782
1852
  json->array_class = Qnil;
1783
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
+ }
1784
1860
  tmp = ID2SYM(i_match_string);
1785
1861
  if (option_given_p(opts, tmp)) {
1786
1862
  VALUE match_string = rb_hash_aref(opts, tmp);
@@ -1794,10 +1870,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
1794
1870
  } else {
1795
1871
  json->max_nesting = 100;
1796
1872
  json->allow_nan = 0;
1797
- json->create_additions = 1;
1873
+ json->create_additions = 0;
1798
1874
  json->create_id = rb_funcall(mJSON, i_create_id, 0);
1799
1875
  json->object_class = Qnil;
1800
1876
  json->array_class = Qnil;
1877
+ json->decimal_class = Qnil;
1801
1878
  }
1802
1879
  source = convert_encoding(StringValue(source));
1803
1880
  StringValue(source);
@@ -1808,7 +1885,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
1808
1885
  }
1809
1886
 
1810
1887
 
1811
- #line 1812 "parser.c"
1888
+ #line 1878 "parser.c"
1812
1889
  enum {JSON_start = 1};
1813
1890
  enum {JSON_first_final = 10};
1814
1891
  enum {JSON_error = 0};
@@ -1816,7 +1893,7 @@ enum {JSON_error = 0};
1816
1893
  enum {JSON_en_main = 1};
1817
1894
 
1818
1895
 
1819
- #line 720 "parser.rl"
1896
+ #line 786 "parser.rl"
1820
1897
 
1821
1898
 
1822
1899
  /*
@@ -1833,16 +1910,16 @@ static VALUE cParser_parse(VALUE self)
1833
1910
  GET_PARSER;
1834
1911
 
1835
1912
 
1836
- #line 1837 "parser.c"
1913
+ #line 1903 "parser.c"
1837
1914
  {
1838
1915
  cs = JSON_start;
1839
1916
  }
1840
1917
 
1841
- #line 736 "parser.rl"
1918
+ #line 802 "parser.rl"
1842
1919
  p = json->source;
1843
1920
  pe = p + json->len;
1844
1921
 
1845
- #line 1846 "parser.c"
1922
+ #line 1912 "parser.c"
1846
1923
  {
1847
1924
  if ( p == pe )
1848
1925
  goto _test_eof;
@@ -1876,7 +1953,7 @@ st0:
1876
1953
  cs = 0;
1877
1954
  goto _out;
1878
1955
  tr2:
1879
- #line 712 "parser.rl"
1956
+ #line 778 "parser.rl"
1880
1957
  {
1881
1958
  char *np = JSON_parse_value(json, p, pe, &result, 0);
1882
1959
  if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
@@ -1886,7 +1963,7 @@ st10:
1886
1963
  if ( ++p == pe )
1887
1964
  goto _test_eof10;
1888
1965
  case 10:
1889
- #line 1890 "parser.c"
1966
+ #line 1956 "parser.c"
1890
1967
  switch( (*p) ) {
1891
1968
  case 13: goto st10;
1892
1969
  case 32: goto st10;
@@ -1975,7 +2052,7 @@ case 9:
1975
2052
  _out: {}
1976
2053
  }
1977
2054
 
1978
- #line 739 "parser.rl"
2055
+ #line 805 "parser.rl"
1979
2056
 
1980
2057
  if (cs >= JSON_first_final && p == pe) {
1981
2058
  return result;
@@ -1992,6 +2069,7 @@ static void JSON_mark(void *ptr)
1992
2069
  rb_gc_mark_maybe(json->create_id);
1993
2070
  rb_gc_mark_maybe(json->object_class);
1994
2071
  rb_gc_mark_maybe(json->array_class);
2072
+ rb_gc_mark_maybe(json->decimal_class);
1995
2073
  rb_gc_mark_maybe(json->match_string);
1996
2074
  }
1997
2075
 
@@ -2041,20 +2119,32 @@ static VALUE cParser_source(VALUE self)
2041
2119
 
2042
2120
  void Init_parser(void)
2043
2121
  {
2122
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
2123
+ rb_ext_ractor_safe(true);
2124
+ #endif
2125
+
2126
+ #undef rb_intern
2044
2127
  rb_require("json/common");
2045
2128
  mJSON = rb_define_module("JSON");
2046
2129
  mExt = rb_define_module_under(mJSON, "Ext");
2047
2130
  cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
2048
2131
  eParserError = rb_path2class("JSON::ParserError");
2049
2132
  eNestingError = rb_path2class("JSON::NestingError");
2133
+ rb_gc_register_mark_object(eParserError);
2134
+ rb_gc_register_mark_object(eNestingError);
2050
2135
  rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
2051
2136
  rb_define_method(cParser, "initialize", cParser_initialize, -1);
2052
2137
  rb_define_method(cParser, "parse", cParser_parse, 0);
2053
2138
  rb_define_method(cParser, "source", cParser_source, 0);
2054
2139
 
2055
2140
  CNaN = rb_const_get(mJSON, rb_intern("NaN"));
2141
+ rb_gc_register_mark_object(CNaN);
2142
+
2056
2143
  CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
2144
+ rb_gc_register_mark_object(CInfinity);
2145
+
2057
2146
  CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
2147
+ rb_gc_register_mark_object(CMinusInfinity);
2058
2148
 
2059
2149
  i_json_creatable_p = rb_intern("json_creatable?");
2060
2150
  i_json_create = rb_intern("json_create");
@@ -2066,6 +2156,7 @@ void Init_parser(void)
2066
2156
  i_symbolize_names = rb_intern("symbolize_names");
2067
2157
  i_object_class = rb_intern("object_class");
2068
2158
  i_array_class = rb_intern("array_class");
2159
+ i_decimal_class = rb_intern("decimal_class");
2069
2160
  i_match = rb_intern("match");
2070
2161
  i_match_string = rb_intern("match_string");
2071
2162
  i_key_p = rb_intern("key?");
@@ -2073,6 +2164,10 @@ void Init_parser(void)
2073
2164
  i_aset = rb_intern("[]=");
2074
2165
  i_aref = rb_intern("[]");
2075
2166
  i_leftshift = rb_intern("<<");
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("-@");
2076
2171
  }
2077
2172
 
2078
2173
  /*