json 2.0.3 → 2.5.1

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