json 2.2.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +51 -0
  3. data/LICENSE +56 -0
  4. data/README.md +17 -1
  5. data/VERSION +1 -1
  6. data/ext/json/ext/generator/generator.c +222 -48
  7. data/ext/json/ext/generator/generator.h +5 -2
  8. data/ext/json/ext/parser/extconf.rb +25 -0
  9. data/ext/json/ext/parser/parser.c +150 -102
  10. data/ext/json/ext/parser/parser.h +1 -0
  11. data/ext/json/ext/parser/parser.rl +80 -32
  12. data/ext/json/extconf.rb +1 -0
  13. data/json.gemspec +0 -0
  14. data/lib/json.rb +549 -29
  15. data/lib/json/add/bigdecimal.rb +2 -2
  16. data/lib/json/add/complex.rb +2 -3
  17. data/lib/json/add/rational.rb +2 -3
  18. data/lib/json/add/regexp.rb +2 -2
  19. data/lib/json/common.rb +370 -125
  20. data/lib/json/pure/generator.rb +31 -10
  21. data/lib/json/pure/parser.rb +31 -5
  22. data/lib/json/version.rb +1 -1
  23. data/tests/fixtures/fail29.json +1 -0
  24. data/tests/fixtures/fail30.json +1 -0
  25. data/tests/fixtures/fail31.json +1 -0
  26. data/tests/fixtures/fail32.json +1 -0
  27. data/tests/json_addition_test.rb +0 -4
  28. data/tests/json_common_interface_test.rb +47 -4
  29. data/tests/json_fixtures_test.rb +9 -1
  30. data/tests/json_generator_test.rb +30 -8
  31. data/tests/json_parser_test.rb +39 -14
  32. data/tests/lib/core_assertions.rb +763 -0
  33. data/tests/lib/envutil.rb +365 -0
  34. data/tests/lib/find_executable.rb +22 -0
  35. data/tests/lib/helper.rb +4 -0
  36. data/tests/ractor_test.rb +30 -0
  37. data/tests/test_helper.rb +3 -3
  38. metadata +30 -40
  39. data/.gitignore +0 -17
  40. data/.travis.yml +0 -23
  41. data/README-json-jruby.md +0 -33
  42. data/Rakefile +0 -408
  43. data/diagrams/.keep +0 -0
  44. data/install.rb +0 -23
  45. data/java/src/json/ext/ByteListTranscoder.java +0 -166
  46. data/java/src/json/ext/Generator.java +0 -443
  47. data/java/src/json/ext/GeneratorMethods.java +0 -231
  48. data/java/src/json/ext/GeneratorService.java +0 -42
  49. data/java/src/json/ext/GeneratorState.java +0 -490
  50. data/java/src/json/ext/OptionsReader.java +0 -113
  51. data/java/src/json/ext/Parser.java +0 -2362
  52. data/java/src/json/ext/Parser.rl +0 -893
  53. data/java/src/json/ext/ParserService.java +0 -34
  54. data/java/src/json/ext/RuntimeInfo.java +0 -116
  55. data/java/src/json/ext/StringDecoder.java +0 -166
  56. data/java/src/json/ext/StringEncoder.java +0 -111
  57. data/java/src/json/ext/Utils.java +0 -88
  58. data/json-java.gemspec +0 -38
  59. data/json_pure.gemspec +0 -38
  60. data/references/rfc7159.txt +0 -899
  61. data/tools/diff.sh +0 -18
  62. data/tools/fuzz.rb +0 -131
  63. data/tools/server.rb +0 -62
@@ -49,8 +49,8 @@ static const UTF32 halfMask = 0x3FFUL;
49
49
  static unsigned char isLegalUTF8(const UTF8 *source, unsigned long length);
50
50
  static void unicode_escape(char *buf, UTF16 character);
51
51
  static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16 character);
52
- static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string);
53
- 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);
54
54
  static char *fstrndup(const char *ptr, unsigned long len);
55
55
 
56
56
  /* ruby api and some helpers */
@@ -72,6 +72,7 @@ typedef struct JSON_Generator_StateStruct {
72
72
  long max_nesting;
73
73
  char allow_nan;
74
74
  char ascii_only;
75
+ char escape_slash;
75
76
  long depth;
76
77
  long buffer_initial_length;
77
78
  } JSON_Generator_State;
@@ -150,6 +151,8 @@ static VALUE cState_allow_nan_p(VALUE self);
150
151
  static VALUE cState_ascii_only_p(VALUE self);
151
152
  static VALUE cState_depth(VALUE self);
152
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);
153
156
  static FBuffer *cState_prepare_buffer(VALUE self);
154
157
  #ifndef ZALLOC
155
158
  #define ZALLOC(type) ((type *)ruby_zalloc(sizeof(type)))
@@ -3,4 +3,29 @@ require 'mkmf'
3
3
 
4
4
  have_func("rb_enc_raise", "ruby.h")
5
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
+
6
31
  create_makefile 'json/ext/parser'
@@ -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;
@@ -91,13 +91,12 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
91
91
 
92
92
  static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
93
93
  static VALUE CNaN, CInfinity, CMinusInfinity;
94
- static VALUE cBigDecimal = Qundef;
95
94
 
96
95
  static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
97
96
  i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
98
97
  i_object_class, i_array_class, i_decimal_class, i_key_p,
99
98
  i_deep_const_get, i_match, i_match_string, i_aset, i_aref,
100
- i_leftshift, i_new, i_BigDecimal;
99
+ i_leftshift, i_new, i_try_convert, i_freeze, i_uminus;
101
100
 
102
101
 
103
102
  #line 126 "parser.rl"
@@ -112,7 +111,7 @@ enum {JSON_object_error = 0};
112
111
  enum {JSON_object_en_main = 1};
113
112
 
114
113
 
115
- #line 167 "parser.rl"
114
+ #line 168 "parser.rl"
116
115
 
117
116
 
118
117
  static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
@@ -133,7 +132,7 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
133
132
  cs = JSON_object_start;
134
133
  }
135
134
 
136
- #line 182 "parser.rl"
135
+ #line 183 "parser.rl"
137
136
 
138
137
  #line 139 "parser.c"
139
138
  {
@@ -163,7 +162,7 @@ case 2:
163
162
  goto st2;
164
163
  goto st0;
165
164
  tr2:
166
- #line 149 "parser.rl"
165
+ #line 150 "parser.rl"
167
166
  {
168
167
  char *np;
169
168
  json->parsing_name = 1;
@@ -251,6 +250,7 @@ tr11:
251
250
  p--; {p++; cs = 9; goto _out;}
252
251
  } else {
253
252
  if (NIL_P(json->object_class)) {
253
+ OBJ_FREEZE(last_name);
254
254
  rb_hash_aset(*result, last_name, v);
255
255
  } else {
256
256
  rb_funcall(*result, i_aset, 2, last_name, v);
@@ -263,7 +263,7 @@ st9:
263
263
  if ( ++p == pe )
264
264
  goto _test_eof9;
265
265
  case 9:
266
- #line 267 "parser.c"
266
+ #line 268 "parser.c"
267
267
  switch( (*p) ) {
268
268
  case 13: goto st9;
269
269
  case 32: goto st9;
@@ -352,14 +352,14 @@ case 18:
352
352
  goto st9;
353
353
  goto st18;
354
354
  tr4:
355
- #line 157 "parser.rl"
355
+ #line 158 "parser.rl"
356
356
  { p--; {p++; cs = 27; goto _out;} }
357
357
  goto st27;
358
358
  st27:
359
359
  if ( ++p == pe )
360
360
  goto _test_eof27;
361
361
  case 27:
362
- #line 363 "parser.c"
362
+ #line 364 "parser.c"
363
363
  goto st0;
364
364
  st19:
365
365
  if ( ++p == pe )
@@ -457,7 +457,7 @@ case 26:
457
457
  _out: {}
458
458
  }
459
459
 
460
- #line 183 "parser.rl"
460
+ #line 184 "parser.rl"
461
461
 
462
462
  if (cs >= JSON_object_first_final) {
463
463
  if (json->create_additions) {
@@ -482,7 +482,7 @@ case 26:
482
482
 
483
483
 
484
484
 
485
- #line 486 "parser.c"
485
+ #line 487 "parser.c"
486
486
  enum {JSON_value_start = 1};
487
487
  enum {JSON_value_first_final = 29};
488
488
  enum {JSON_value_error = 0};
@@ -490,7 +490,7 @@ enum {JSON_value_error = 0};
490
490
  enum {JSON_value_en_main = 1};
491
491
 
492
492
 
493
- #line 283 "parser.rl"
493
+ #line 284 "parser.rl"
494
494
 
495
495
 
496
496
  static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
@@ -498,14 +498,14 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
498
498
  int cs = EVIL;
499
499
 
500
500
 
501
- #line 502 "parser.c"
501
+ #line 503 "parser.c"
502
502
  {
503
503
  cs = JSON_value_start;
504
504
  }
505
505
 
506
- #line 290 "parser.rl"
506
+ #line 291 "parser.rl"
507
507
 
508
- #line 509 "parser.c"
508
+ #line 510 "parser.c"
509
509
  {
510
510
  if ( p == pe )
511
511
  goto _test_eof;
@@ -539,14 +539,14 @@ st0:
539
539
  cs = 0;
540
540
  goto _out;
541
541
  tr2:
542
- #line 235 "parser.rl"
542
+ #line 236 "parser.rl"
543
543
  {
544
544
  char *np = JSON_parse_string(json, p, pe, result);
545
545
  if (np == NULL) { p--; {p++; cs = 29; goto _out;} } else {p = (( np))-1;}
546
546
  }
547
547
  goto st29;
548
548
  tr3:
549
- #line 240 "parser.rl"
549
+ #line 241 "parser.rl"
550
550
  {
551
551
  char *np;
552
552
  if(pe > p + 8 && !strncmp(MinusInfinity, p, 9)) {
@@ -566,7 +566,7 @@ tr3:
566
566
  }
567
567
  goto st29;
568
568
  tr7:
569
- #line 258 "parser.rl"
569
+ #line 259 "parser.rl"
570
570
  {
571
571
  char *np;
572
572
  np = JSON_parse_array(json, p, pe, result, current_nesting + 1);
@@ -574,7 +574,7 @@ tr7:
574
574
  }
575
575
  goto st29;
576
576
  tr11:
577
- #line 264 "parser.rl"
577
+ #line 265 "parser.rl"
578
578
  {
579
579
  char *np;
580
580
  np = JSON_parse_object(json, p, pe, result, current_nesting + 1);
@@ -582,7 +582,7 @@ tr11:
582
582
  }
583
583
  goto st29;
584
584
  tr25:
585
- #line 228 "parser.rl"
585
+ #line 229 "parser.rl"
586
586
  {
587
587
  if (json->allow_nan) {
588
588
  *result = CInfinity;
@@ -592,7 +592,7 @@ tr25:
592
592
  }
593
593
  goto st29;
594
594
  tr27:
595
- #line 221 "parser.rl"
595
+ #line 222 "parser.rl"
596
596
  {
597
597
  if (json->allow_nan) {
598
598
  *result = CNaN;
@@ -602,19 +602,19 @@ tr27:
602
602
  }
603
603
  goto st29;
604
604
  tr31:
605
- #line 215 "parser.rl"
605
+ #line 216 "parser.rl"
606
606
  {
607
607
  *result = Qfalse;
608
608
  }
609
609
  goto st29;
610
610
  tr34:
611
- #line 212 "parser.rl"
611
+ #line 213 "parser.rl"
612
612
  {
613
613
  *result = Qnil;
614
614
  }
615
615
  goto st29;
616
616
  tr37:
617
- #line 218 "parser.rl"
617
+ #line 219 "parser.rl"
618
618
  {
619
619
  *result = Qtrue;
620
620
  }
@@ -623,9 +623,9 @@ st29:
623
623
  if ( ++p == pe )
624
624
  goto _test_eof29;
625
625
  case 29:
626
- #line 270 "parser.rl"
626
+ #line 271 "parser.rl"
627
627
  { p--; {p++; cs = 29; goto _out;} }
628
- #line 629 "parser.c"
628
+ #line 630 "parser.c"
629
629
  switch( (*p) ) {
630
630
  case 13: goto st29;
631
631
  case 32: goto st29;
@@ -866,7 +866,11 @@ case 28:
866
866
  _out: {}
867
867
  }
868
868
 
869
- #line 291 "parser.rl"
869
+ #line 292 "parser.rl"
870
+
871
+ if (json->freeze) {
872
+ OBJ_FREEZE(*result);
873
+ }
870
874
 
871
875
  if (cs >= JSON_value_first_final) {
872
876
  return p;
@@ -876,7 +880,7 @@ case 28:
876
880
  }
877
881
 
878
882
 
879
- #line 880 "parser.c"
883
+ #line 885 "parser.c"
880
884
  enum {JSON_integer_start = 1};
881
885
  enum {JSON_integer_first_final = 3};
882
886
  enum {JSON_integer_error = 0};
@@ -884,7 +888,7 @@ enum {JSON_integer_error = 0};
884
888
  enum {JSON_integer_en_main = 1};
885
889
 
886
890
 
887
- #line 307 "parser.rl"
891
+ #line 312 "parser.rl"
888
892
 
889
893
 
890
894
  static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -892,15 +896,15 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
892
896
  int cs = EVIL;
893
897
 
894
898
 
895
- #line 896 "parser.c"
899
+ #line 901 "parser.c"
896
900
  {
897
901
  cs = JSON_integer_start;
898
902
  }
899
903
 
900
- #line 314 "parser.rl"
904
+ #line 319 "parser.rl"
901
905
  json->memo = p;
902
906
 
903
- #line 904 "parser.c"
907
+ #line 909 "parser.c"
904
908
  {
905
909
  if ( p == pe )
906
910
  goto _test_eof;
@@ -934,14 +938,14 @@ case 3:
934
938
  goto st0;
935
939
  goto tr4;
936
940
  tr4:
937
- #line 304 "parser.rl"
941
+ #line 309 "parser.rl"
938
942
  { p--; {p++; cs = 4; goto _out;} }
939
943
  goto st4;
940
944
  st4:
941
945
  if ( ++p == pe )
942
946
  goto _test_eof4;
943
947
  case 4:
944
- #line 945 "parser.c"
948
+ #line 950 "parser.c"
945
949
  goto st0;
946
950
  st5:
947
951
  if ( ++p == pe )
@@ -960,7 +964,7 @@ case 5:
960
964
  _out: {}
961
965
  }
962
966
 
963
- #line 316 "parser.rl"
967
+ #line 321 "parser.rl"
964
968
 
965
969
  if (cs >= JSON_integer_first_final) {
966
970
  long len = p - json->memo;
@@ -975,7 +979,7 @@ case 5:
975
979
  }
976
980
 
977
981
 
978
- #line 979 "parser.c"
982
+ #line 984 "parser.c"
979
983
  enum {JSON_float_start = 1};
980
984
  enum {JSON_float_first_final = 8};
981
985
  enum {JSON_float_error = 0};
@@ -983,36 +987,23 @@ enum {JSON_float_error = 0};
983
987
  enum {JSON_float_en_main = 1};
984
988
 
985
989
 
986
- #line 341 "parser.rl"
987
-
990
+ #line 346 "parser.rl"
988
991
 
989
- static int is_bigdecimal_class(VALUE obj)
990
- {
991
- if (cBigDecimal == Qundef) {
992
- if (rb_const_defined(rb_cObject, i_BigDecimal)) {
993
- cBigDecimal = rb_const_get_at(rb_cObject, i_BigDecimal);
994
- }
995
- else {
996
- return 0;
997
- }
998
- }
999
- return obj == cBigDecimal;
1000
- }
1001
992
 
1002
993
  static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
1003
994
  {
1004
995
  int cs = EVIL;
1005
996
 
1006
997
 
1007
- #line 1008 "parser.c"
998
+ #line 1013 "parser.c"
1008
999
  {
1009
1000
  cs = JSON_float_start;
1010
1001
  }
1011
1002
 
1012
- #line 361 "parser.rl"
1003
+ #line 366 "parser.rl"
1013
1004
  json->memo = p;
1014
1005
 
1015
- #line 1016 "parser.c"
1006
+ #line 1021 "parser.c"
1016
1007
  {
1017
1008
  if ( p == pe )
1018
1009
  goto _test_eof;
@@ -1070,14 +1061,14 @@ case 8:
1070
1061
  goto st0;
1071
1062
  goto tr9;
1072
1063
  tr9:
1073
- #line 335 "parser.rl"
1064
+ #line 340 "parser.rl"
1074
1065
  { p--; {p++; cs = 9; goto _out;} }
1075
1066
  goto st9;
1076
1067
  st9:
1077
1068
  if ( ++p == pe )
1078
1069
  goto _test_eof9;
1079
1070
  case 9:
1080
- #line 1081 "parser.c"
1071
+ #line 1086 "parser.c"
1081
1072
  goto st0;
1082
1073
  st5:
1083
1074
  if ( ++p == pe )
@@ -1138,24 +1129,49 @@ case 7:
1138
1129
  _out: {}
1139
1130
  }
1140
1131
 
1141
- #line 363 "parser.rl"
1132
+ #line 368 "parser.rl"
1142
1133
 
1143
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
+
1144
1163
  long len = p - json->memo;
1145
1164
  fbuffer_clear(json->fbuffer);
1146
1165
  fbuffer_append(json->fbuffer, json->memo, len);
1147
1166
  fbuffer_append_char(json->fbuffer, '\0');
1148
- if (NIL_P(json->decimal_class)) {
1149
- *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);
1150
1171
  } else {
1151
- VALUE text;
1152
- text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
1153
- if (is_bigdecimal_class(json->decimal_class)) {
1154
- *result = rb_funcall(Qnil, i_BigDecimal, 1, text);
1155
- } else {
1156
- *result = rb_funcall(json->decimal_class, i_new, 1, text);
1157
- }
1172
+ *result = DBL2NUM(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
1158
1173
  }
1174
+
1159
1175
  return p + 1;
1160
1176
  } else {
1161
1177
  return NULL;
@@ -1164,7 +1180,7 @@ case 7:
1164
1180
 
1165
1181
 
1166
1182
 
1167
- #line 1168 "parser.c"
1183
+ #line 1173 "parser.c"
1168
1184
  enum {JSON_array_start = 1};
1169
1185
  enum {JSON_array_first_final = 17};
1170
1186
  enum {JSON_array_error = 0};
@@ -1172,7 +1188,7 @@ enum {JSON_array_error = 0};
1172
1188
  enum {JSON_array_en_main = 1};
1173
1189
 
1174
1190
 
1175
- #line 416 "parser.rl"
1191
+ #line 421 "parser.rl"
1176
1192
 
1177
1193
 
1178
1194
  static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
@@ -1186,14 +1202,14 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
1186
1202
  *result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
1187
1203
 
1188
1204
 
1189
- #line 1190 "parser.c"
1205
+ #line 1195 "parser.c"
1190
1206
  {
1191
1207
  cs = JSON_array_start;
1192
1208
  }
1193
1209
 
1194
- #line 429 "parser.rl"
1210
+ #line 434 "parser.rl"
1195
1211
 
1196
- #line 1197 "parser.c"
1212
+ #line 1202 "parser.c"
1197
1213
  {
1198
1214
  if ( p == pe )
1199
1215
  goto _test_eof;
@@ -1232,7 +1248,7 @@ case 2:
1232
1248
  goto st2;
1233
1249
  goto st0;
1234
1250
  tr2:
1235
- #line 393 "parser.rl"
1251
+ #line 398 "parser.rl"
1236
1252
  {
1237
1253
  VALUE v = Qnil;
1238
1254
  char *np = JSON_parse_value(json, p, pe, &v, current_nesting);
@@ -1252,7 +1268,7 @@ st3:
1252
1268
  if ( ++p == pe )
1253
1269
  goto _test_eof3;
1254
1270
  case 3:
1255
- #line 1256 "parser.c"
1271
+ #line 1261 "parser.c"
1256
1272
  switch( (*p) ) {
1257
1273
  case 13: goto st3;
1258
1274
  case 32: goto st3;
@@ -1352,14 +1368,14 @@ case 12:
1352
1368
  goto st3;
1353
1369
  goto st12;
1354
1370
  tr4:
1355
- #line 408 "parser.rl"
1371
+ #line 413 "parser.rl"
1356
1372
  { p--; {p++; cs = 17; goto _out;} }
1357
1373
  goto st17;
1358
1374
  st17:
1359
1375
  if ( ++p == pe )
1360
1376
  goto _test_eof17;
1361
1377
  case 17:
1362
- #line 1363 "parser.c"
1378
+ #line 1368 "parser.c"
1363
1379
  goto st0;
1364
1380
  st13:
1365
1381
  if ( ++p == pe )
@@ -1415,7 +1431,7 @@ case 16:
1415
1431
  _out: {}
1416
1432
  }
1417
1433
 
1418
- #line 430 "parser.rl"
1434
+ #line 435 "parser.rl"
1419
1435
 
1420
1436
  if(cs >= JSON_array_first_final) {
1421
1437
  return p + 1;
@@ -1504,7 +1520,7 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
1504
1520
  }
1505
1521
 
1506
1522
 
1507
- #line 1508 "parser.c"
1523
+ #line 1513 "parser.c"
1508
1524
  enum {JSON_string_start = 1};
1509
1525
  enum {JSON_string_first_final = 8};
1510
1526
  enum {JSON_string_error = 0};
@@ -1512,7 +1528,7 @@ enum {JSON_string_error = 0};
1512
1528
  enum {JSON_string_en_main = 1};
1513
1529
 
1514
1530
 
1515
- #line 537 "parser.rl"
1531
+ #line 542 "parser.rl"
1516
1532
 
1517
1533
 
1518
1534
  static int
@@ -1534,15 +1550,15 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
1534
1550
 
1535
1551
  *result = rb_str_buf_new(0);
1536
1552
 
1537
- #line 1538 "parser.c"
1553
+ #line 1543 "parser.c"
1538
1554
  {
1539
1555
  cs = JSON_string_start;
1540
1556
  }
1541
1557
 
1542
- #line 558 "parser.rl"
1558
+ #line 563 "parser.rl"
1543
1559
  json->memo = p;
1544
1560
 
1545
- #line 1546 "parser.c"
1561
+ #line 1551 "parser.c"
1546
1562
  {
1547
1563
  if ( p == pe )
1548
1564
  goto _test_eof;
@@ -1563,11 +1579,11 @@ case 2:
1563
1579
  case 34: goto tr2;
1564
1580
  case 92: goto st3;
1565
1581
  }
1566
- if ( 0 <= (*p) && (*p) <= 31 )
1582
+ if ( 0 <= (signed char)(*p) && (*p) <= 31 )
1567
1583
  goto st0;
1568
1584
  goto st2;
1569
1585
  tr2:
1570
- #line 523 "parser.rl"
1586
+ #line 528 "parser.rl"
1571
1587
  {
1572
1588
  *result = json_string_unescape(*result, json->memo + 1, p);
1573
1589
  if (NIL_P(*result)) {
@@ -1578,14 +1594,14 @@ tr2:
1578
1594
  {p = (( p + 1))-1;}
1579
1595
  }
1580
1596
  }
1581
- #line 534 "parser.rl"
1597
+ #line 539 "parser.rl"
1582
1598
  { p--; {p++; cs = 8; goto _out;} }
1583
1599
  goto st8;
1584
1600
  st8:
1585
1601
  if ( ++p == pe )
1586
1602
  goto _test_eof8;
1587
1603
  case 8:
1588
- #line 1589 "parser.c"
1604
+ #line 1594 "parser.c"
1589
1605
  goto st0;
1590
1606
  st3:
1591
1607
  if ( ++p == pe )
@@ -1593,7 +1609,7 @@ st3:
1593
1609
  case 3:
1594
1610
  if ( (*p) == 117 )
1595
1611
  goto st4;
1596
- if ( 0 <= (*p) && (*p) <= 31 )
1612
+ if ( 0 <= (signed char)(*p) && (*p) <= 31 )
1597
1613
  goto st0;
1598
1614
  goto st2;
1599
1615
  st4:
@@ -1661,7 +1677,7 @@ case 7:
1661
1677
  _out: {}
1662
1678
  }
1663
1679
 
1664
- #line 560 "parser.rl"
1680
+ #line 565 "parser.rl"
1665
1681
 
1666
1682
  if (json->create_additions && RTEST(match_string = json->match_string)) {
1667
1683
  VALUE klass;
@@ -1676,10 +1692,23 @@ case 7:
1676
1692
 
1677
1693
  if (json->symbolize_names && json->parsing_name) {
1678
1694
  *result = rb_str_intern(*result);
1679
- } else {
1680
- if (RB_TYPE_P(*result, T_STRING)) {
1681
- rb_str_resize(*result, RSTRING_LEN(*result));
1682
- }
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
1683
1712
  }
1684
1713
  if (cs >= JSON_string_first_final) {
1685
1714
  return p + 1;
@@ -1787,6 +1816,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
1787
1816
  } else {
1788
1817
  json->symbolize_names = 0;
1789
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
+ }
1790
1825
  tmp = ID2SYM(i_create_additions);
1791
1826
  if (option_given_p(opts, tmp)) {
1792
1827
  json->create_additions = RTEST(rb_hash_aref(opts, tmp));
@@ -1835,7 +1870,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
1835
1870
  } else {
1836
1871
  json->max_nesting = 100;
1837
1872
  json->allow_nan = 0;
1838
- json->create_additions = 1;
1873
+ json->create_additions = 0;
1839
1874
  json->create_id = rb_funcall(mJSON, i_create_id, 0);
1840
1875
  json->object_class = Qnil;
1841
1876
  json->array_class = Qnil;
@@ -1850,7 +1885,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
1850
1885
  }
1851
1886
 
1852
1887
 
1853
- #line 1854 "parser.c"
1888
+ #line 1878 "parser.c"
1854
1889
  enum {JSON_start = 1};
1855
1890
  enum {JSON_first_final = 10};
1856
1891
  enum {JSON_error = 0};
@@ -1858,7 +1893,7 @@ enum {JSON_error = 0};
1858
1893
  enum {JSON_en_main = 1};
1859
1894
 
1860
1895
 
1861
- #line 762 "parser.rl"
1896
+ #line 786 "parser.rl"
1862
1897
 
1863
1898
 
1864
1899
  /*
@@ -1875,16 +1910,16 @@ static VALUE cParser_parse(VALUE self)
1875
1910
  GET_PARSER;
1876
1911
 
1877
1912
 
1878
- #line 1879 "parser.c"
1913
+ #line 1903 "parser.c"
1879
1914
  {
1880
1915
  cs = JSON_start;
1881
1916
  }
1882
1917
 
1883
- #line 778 "parser.rl"
1918
+ #line 802 "parser.rl"
1884
1919
  p = json->source;
1885
1920
  pe = p + json->len;
1886
1921
 
1887
- #line 1888 "parser.c"
1922
+ #line 1912 "parser.c"
1888
1923
  {
1889
1924
  if ( p == pe )
1890
1925
  goto _test_eof;
@@ -1918,7 +1953,7 @@ st0:
1918
1953
  cs = 0;
1919
1954
  goto _out;
1920
1955
  tr2:
1921
- #line 754 "parser.rl"
1956
+ #line 778 "parser.rl"
1922
1957
  {
1923
1958
  char *np = JSON_parse_value(json, p, pe, &result, 0);
1924
1959
  if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
@@ -1928,7 +1963,7 @@ st10:
1928
1963
  if ( ++p == pe )
1929
1964
  goto _test_eof10;
1930
1965
  case 10:
1931
- #line 1932 "parser.c"
1966
+ #line 1956 "parser.c"
1932
1967
  switch( (*p) ) {
1933
1968
  case 13: goto st10;
1934
1969
  case 32: goto st10;
@@ -2017,7 +2052,7 @@ case 9:
2017
2052
  _out: {}
2018
2053
  }
2019
2054
 
2020
- #line 781 "parser.rl"
2055
+ #line 805 "parser.rl"
2021
2056
 
2022
2057
  if (cs >= JSON_first_final && p == pe) {
2023
2058
  return result;
@@ -2084,6 +2119,10 @@ static VALUE cParser_source(VALUE self)
2084
2119
 
2085
2120
  void Init_parser(void)
2086
2121
  {
2122
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
2123
+ rb_ext_ractor_safe(true);
2124
+ #endif
2125
+
2087
2126
  #undef rb_intern
2088
2127
  rb_require("json/common");
2089
2128
  mJSON = rb_define_module("JSON");
@@ -2091,14 +2130,21 @@ void Init_parser(void)
2091
2130
  cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
2092
2131
  eParserError = rb_path2class("JSON::ParserError");
2093
2132
  eNestingError = rb_path2class("JSON::NestingError");
2133
+ rb_gc_register_mark_object(eParserError);
2134
+ rb_gc_register_mark_object(eNestingError);
2094
2135
  rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
2095
2136
  rb_define_method(cParser, "initialize", cParser_initialize, -1);
2096
2137
  rb_define_method(cParser, "parse", cParser_parse, 0);
2097
2138
  rb_define_method(cParser, "source", cParser_source, 0);
2098
2139
 
2099
2140
  CNaN = rb_const_get(mJSON, rb_intern("NaN"));
2141
+ rb_gc_register_mark_object(CNaN);
2142
+
2100
2143
  CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
2144
+ rb_gc_register_mark_object(CInfinity);
2145
+
2101
2146
  CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
2147
+ rb_gc_register_mark_object(CMinusInfinity);
2102
2148
 
2103
2149
  i_json_creatable_p = rb_intern("json_creatable?");
2104
2150
  i_json_create = rb_intern("json_create");
@@ -2119,7 +2165,9 @@ void Init_parser(void)
2119
2165
  i_aref = rb_intern("[]");
2120
2166
  i_leftshift = rb_intern("<<");
2121
2167
  i_new = rb_intern("new");
2122
- i_BigDecimal = rb_intern("BigDecimal");
2168
+ i_try_convert = rb_intern("try_convert");
2169
+ i_freeze = rb_intern("freeze");
2170
+ i_uminus = rb_intern("-@");
2123
2171
  }
2124
2172
 
2125
2173
  /*