json_pure 2.0.4 → 2.4.0

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 (46) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.travis.yml +9 -5
  4. data/CHANGES.md +39 -0
  5. data/Gemfile +1 -3
  6. data/LICENSE +56 -0
  7. data/README.md +54 -21
  8. data/Rakefile +19 -93
  9. data/VERSION +1 -1
  10. data/ext/json/ext/generator/generator.c +214 -45
  11. data/ext/json/ext/generator/generator.h +5 -2
  12. data/ext/json/ext/parser/extconf.rb +25 -0
  13. data/ext/json/ext/parser/parser.c +155 -83
  14. data/ext/json/ext/parser/parser.h +2 -0
  15. data/ext/json/ext/parser/parser.rl +79 -7
  16. data/ext/json/extconf.rb +1 -0
  17. data/java/src/json/ext/Generator.java +28 -24
  18. data/java/src/json/ext/GeneratorState.java +30 -0
  19. data/java/src/json/ext/Parser.java +109 -82
  20. data/java/src/json/ext/Parser.rl +39 -12
  21. data/java/src/json/ext/StringEncoder.java +8 -2
  22. data/json-java.gemspec +22 -22
  23. data/json.gemspec +0 -0
  24. data/json_pure.gemspec +9 -14
  25. data/lib/json.rb +549 -29
  26. data/lib/json/add/bigdecimal.rb +2 -2
  27. data/lib/json/add/complex.rb +2 -3
  28. data/lib/json/add/ostruct.rb +1 -1
  29. data/lib/json/add/rational.rb +2 -3
  30. data/lib/json/add/regexp.rb +2 -2
  31. data/lib/json/add/set.rb +29 -0
  32. data/lib/json/common.rb +341 -115
  33. data/lib/json/pure/generator.rb +31 -10
  34. data/lib/json/pure/parser.rb +35 -5
  35. data/lib/json/version.rb +1 -1
  36. data/tests/json_addition_test.rb +6 -0
  37. data/tests/json_common_interface_test.rb +47 -4
  38. data/tests/json_encoding_test.rb +2 -2
  39. data/tests/json_fixtures_test.rb +9 -1
  40. data/tests/json_generator_test.rb +55 -0
  41. data/tests/json_parser_test.rb +43 -12
  42. data/tests/test_helper.rb +3 -7
  43. metadata +17 -13
  44. data/data/example.json +0 -1
  45. data/data/index.html +0 -38
  46. data/data/prototype.js +0 -4184
@@ -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,18 +91,20 @@ 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;
94
95
 
95
96
  static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
96
97
  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;
98
+ i_object_class, i_array_class, i_decimal_class, i_key_p,
99
+ i_deep_const_get, i_match, i_match_string, i_aset, i_aref,
100
+ i_leftshift, i_new, i_BigDecimal, i_freeze, i_uminus;
99
101
 
100
102
 
101
- #line 124 "parser.rl"
103
+ #line 126 "parser.rl"
102
104
 
103
105
 
104
106
 
105
- #line 106 "parser.c"
107
+ #line 108 "parser.c"
106
108
  enum {JSON_object_start = 1};
107
109
  enum {JSON_object_first_final = 27};
108
110
  enum {JSON_object_error = 0};
@@ -110,7 +112,7 @@ enum {JSON_object_error = 0};
110
112
  enum {JSON_object_en_main = 1};
111
113
 
112
114
 
113
- #line 165 "parser.rl"
115
+ #line 168 "parser.rl"
114
116
 
115
117
 
116
118
  static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
@@ -126,14 +128,14 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
126
128
  *result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class);
127
129
 
128
130
 
129
- #line 130 "parser.c"
131
+ #line 132 "parser.c"
130
132
  {
131
133
  cs = JSON_object_start;
132
134
  }
133
135
 
134
- #line 180 "parser.rl"
136
+ #line 183 "parser.rl"
135
137
 
136
- #line 137 "parser.c"
138
+ #line 139 "parser.c"
137
139
  {
138
140
  if ( p == pe )
139
141
  goto _test_eof;
@@ -161,7 +163,7 @@ case 2:
161
163
  goto st2;
162
164
  goto st0;
163
165
  tr2:
164
- #line 147 "parser.rl"
166
+ #line 150 "parser.rl"
165
167
  {
166
168
  char *np;
167
169
  json->parsing_name = 1;
@@ -174,7 +176,7 @@ st3:
174
176
  if ( ++p == pe )
175
177
  goto _test_eof3;
176
178
  case 3:
177
- #line 178 "parser.c"
179
+ #line 180 "parser.c"
178
180
  switch( (*p) ) {
179
181
  case 13: goto st3;
180
182
  case 32: goto st3;
@@ -241,7 +243,7 @@ case 8:
241
243
  goto st8;
242
244
  goto st0;
243
245
  tr11:
244
- #line 132 "parser.rl"
246
+ #line 134 "parser.rl"
245
247
  {
246
248
  VALUE v = Qnil;
247
249
  char *np = JSON_parse_value(json, p, pe, &v, current_nesting);
@@ -249,6 +251,7 @@ tr11:
249
251
  p--; {p++; cs = 9; goto _out;}
250
252
  } else {
251
253
  if (NIL_P(json->object_class)) {
254
+ OBJ_FREEZE(last_name);
252
255
  rb_hash_aset(*result, last_name, v);
253
256
  } else {
254
257
  rb_funcall(*result, i_aset, 2, last_name, v);
@@ -261,7 +264,7 @@ st9:
261
264
  if ( ++p == pe )
262
265
  goto _test_eof9;
263
266
  case 9:
264
- #line 265 "parser.c"
267
+ #line 268 "parser.c"
265
268
  switch( (*p) ) {
266
269
  case 13: goto st9;
267
270
  case 32: goto st9;
@@ -350,14 +353,14 @@ case 18:
350
353
  goto st9;
351
354
  goto st18;
352
355
  tr4:
353
- #line 155 "parser.rl"
356
+ #line 158 "parser.rl"
354
357
  { p--; {p++; cs = 27; goto _out;} }
355
358
  goto st27;
356
359
  st27:
357
360
  if ( ++p == pe )
358
361
  goto _test_eof27;
359
362
  case 27:
360
- #line 361 "parser.c"
363
+ #line 364 "parser.c"
361
364
  goto st0;
362
365
  st19:
363
366
  if ( ++p == pe )
@@ -455,7 +458,7 @@ case 26:
455
458
  _out: {}
456
459
  }
457
460
 
458
- #line 181 "parser.rl"
461
+ #line 184 "parser.rl"
459
462
 
460
463
  if (cs >= JSON_object_first_final) {
461
464
  if (json->create_additions) {
@@ -480,7 +483,7 @@ case 26:
480
483
 
481
484
 
482
485
 
483
- #line 484 "parser.c"
486
+ #line 487 "parser.c"
484
487
  enum {JSON_value_start = 1};
485
488
  enum {JSON_value_first_final = 29};
486
489
  enum {JSON_value_error = 0};
@@ -488,7 +491,7 @@ enum {JSON_value_error = 0};
488
491
  enum {JSON_value_en_main = 1};
489
492
 
490
493
 
491
- #line 281 "parser.rl"
494
+ #line 284 "parser.rl"
492
495
 
493
496
 
494
497
  static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
@@ -496,14 +499,14 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
496
499
  int cs = EVIL;
497
500
 
498
501
 
499
- #line 500 "parser.c"
502
+ #line 503 "parser.c"
500
503
  {
501
504
  cs = JSON_value_start;
502
505
  }
503
506
 
504
- #line 288 "parser.rl"
507
+ #line 291 "parser.rl"
505
508
 
506
- #line 507 "parser.c"
509
+ #line 510 "parser.c"
507
510
  {
508
511
  if ( p == pe )
509
512
  goto _test_eof;
@@ -537,14 +540,14 @@ st0:
537
540
  cs = 0;
538
541
  goto _out;
539
542
  tr2:
540
- #line 233 "parser.rl"
543
+ #line 236 "parser.rl"
541
544
  {
542
545
  char *np = JSON_parse_string(json, p, pe, result);
543
546
  if (np == NULL) { p--; {p++; cs = 29; goto _out;} } else {p = (( np))-1;}
544
547
  }
545
548
  goto st29;
546
549
  tr3:
547
- #line 238 "parser.rl"
550
+ #line 241 "parser.rl"
548
551
  {
549
552
  char *np;
550
553
  if(pe > p + 8 && !strncmp(MinusInfinity, p, 9)) {
@@ -564,7 +567,7 @@ tr3:
564
567
  }
565
568
  goto st29;
566
569
  tr7:
567
- #line 256 "parser.rl"
570
+ #line 259 "parser.rl"
568
571
  {
569
572
  char *np;
570
573
  np = JSON_parse_array(json, p, pe, result, current_nesting + 1);
@@ -572,7 +575,7 @@ tr7:
572
575
  }
573
576
  goto st29;
574
577
  tr11:
575
- #line 262 "parser.rl"
578
+ #line 265 "parser.rl"
576
579
  {
577
580
  char *np;
578
581
  np = JSON_parse_object(json, p, pe, result, current_nesting + 1);
@@ -580,7 +583,7 @@ tr11:
580
583
  }
581
584
  goto st29;
582
585
  tr25:
583
- #line 226 "parser.rl"
586
+ #line 229 "parser.rl"
584
587
  {
585
588
  if (json->allow_nan) {
586
589
  *result = CInfinity;
@@ -590,7 +593,7 @@ tr25:
590
593
  }
591
594
  goto st29;
592
595
  tr27:
593
- #line 219 "parser.rl"
596
+ #line 222 "parser.rl"
594
597
  {
595
598
  if (json->allow_nan) {
596
599
  *result = CNaN;
@@ -600,19 +603,19 @@ tr27:
600
603
  }
601
604
  goto st29;
602
605
  tr31:
603
- #line 213 "parser.rl"
606
+ #line 216 "parser.rl"
604
607
  {
605
608
  *result = Qfalse;
606
609
  }
607
610
  goto st29;
608
611
  tr34:
609
- #line 210 "parser.rl"
612
+ #line 213 "parser.rl"
610
613
  {
611
614
  *result = Qnil;
612
615
  }
613
616
  goto st29;
614
617
  tr37:
615
- #line 216 "parser.rl"
618
+ #line 219 "parser.rl"
616
619
  {
617
620
  *result = Qtrue;
618
621
  }
@@ -621,9 +624,9 @@ st29:
621
624
  if ( ++p == pe )
622
625
  goto _test_eof29;
623
626
  case 29:
624
- #line 268 "parser.rl"
627
+ #line 271 "parser.rl"
625
628
  { p--; {p++; cs = 29; goto _out;} }
626
- #line 627 "parser.c"
629
+ #line 630 "parser.c"
627
630
  switch( (*p) ) {
628
631
  case 13: goto st29;
629
632
  case 32: goto st29;
@@ -864,7 +867,11 @@ case 28:
864
867
  _out: {}
865
868
  }
866
869
 
867
- #line 289 "parser.rl"
870
+ #line 292 "parser.rl"
871
+
872
+ if (json->freeze) {
873
+ OBJ_FREEZE(*result);
874
+ }
868
875
 
869
876
  if (cs >= JSON_value_first_final) {
870
877
  return p;
@@ -874,7 +881,7 @@ case 28:
874
881
  }
875
882
 
876
883
 
877
- #line 878 "parser.c"
884
+ #line 885 "parser.c"
878
885
  enum {JSON_integer_start = 1};
879
886
  enum {JSON_integer_first_final = 3};
880
887
  enum {JSON_integer_error = 0};
@@ -882,7 +889,7 @@ enum {JSON_integer_error = 0};
882
889
  enum {JSON_integer_en_main = 1};
883
890
 
884
891
 
885
- #line 305 "parser.rl"
892
+ #line 312 "parser.rl"
886
893
 
887
894
 
888
895
  static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -890,15 +897,15 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
890
897
  int cs = EVIL;
891
898
 
892
899
 
893
- #line 894 "parser.c"
900
+ #line 901 "parser.c"
894
901
  {
895
902
  cs = JSON_integer_start;
896
903
  }
897
904
 
898
- #line 312 "parser.rl"
905
+ #line 319 "parser.rl"
899
906
  json->memo = p;
900
907
 
901
- #line 902 "parser.c"
908
+ #line 909 "parser.c"
902
909
  {
903
910
  if ( p == pe )
904
911
  goto _test_eof;
@@ -932,14 +939,14 @@ case 3:
932
939
  goto st0;
933
940
  goto tr4;
934
941
  tr4:
935
- #line 302 "parser.rl"
942
+ #line 309 "parser.rl"
936
943
  { p--; {p++; cs = 4; goto _out;} }
937
944
  goto st4;
938
945
  st4:
939
946
  if ( ++p == pe )
940
947
  goto _test_eof4;
941
948
  case 4:
942
- #line 943 "parser.c"
949
+ #line 950 "parser.c"
943
950
  goto st0;
944
951
  st5:
945
952
  if ( ++p == pe )
@@ -958,7 +965,7 @@ case 5:
958
965
  _out: {}
959
966
  }
960
967
 
961
- #line 314 "parser.rl"
968
+ #line 321 "parser.rl"
962
969
 
963
970
  if (cs >= JSON_integer_first_final) {
964
971
  long len = p - json->memo;
@@ -973,7 +980,7 @@ case 5:
973
980
  }
974
981
 
975
982
 
976
- #line 977 "parser.c"
983
+ #line 984 "parser.c"
977
984
  enum {JSON_float_start = 1};
978
985
  enum {JSON_float_first_final = 8};
979
986
  enum {JSON_float_error = 0};
@@ -981,23 +988,36 @@ enum {JSON_float_error = 0};
981
988
  enum {JSON_float_en_main = 1};
982
989
 
983
990
 
984
- #line 339 "parser.rl"
991
+ #line 346 "parser.rl"
985
992
 
986
993
 
994
+ static int is_bigdecimal_class(VALUE obj)
995
+ {
996
+ if (cBigDecimal == Qundef) {
997
+ if (rb_const_defined(rb_cObject, i_BigDecimal)) {
998
+ cBigDecimal = rb_const_get_at(rb_cObject, i_BigDecimal);
999
+ }
1000
+ else {
1001
+ return 0;
1002
+ }
1003
+ }
1004
+ return obj == cBigDecimal;
1005
+ }
1006
+
987
1007
  static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
988
1008
  {
989
1009
  int cs = EVIL;
990
1010
 
991
1011
 
992
- #line 993 "parser.c"
1012
+ #line 1013 "parser.c"
993
1013
  {
994
1014
  cs = JSON_float_start;
995
1015
  }
996
1016
 
997
- #line 346 "parser.rl"
1017
+ #line 366 "parser.rl"
998
1018
  json->memo = p;
999
1019
 
1000
- #line 1001 "parser.c"
1020
+ #line 1021 "parser.c"
1001
1021
  {
1002
1022
  if ( p == pe )
1003
1023
  goto _test_eof;
@@ -1055,14 +1075,14 @@ case 8:
1055
1075
  goto st0;
1056
1076
  goto tr9;
1057
1077
  tr9:
1058
- #line 333 "parser.rl"
1078
+ #line 340 "parser.rl"
1059
1079
  { p--; {p++; cs = 9; goto _out;} }
1060
1080
  goto st9;
1061
1081
  st9:
1062
1082
  if ( ++p == pe )
1063
1083
  goto _test_eof9;
1064
1084
  case 9:
1065
- #line 1066 "parser.c"
1085
+ #line 1086 "parser.c"
1066
1086
  goto st0;
1067
1087
  st5:
1068
1088
  if ( ++p == pe )
@@ -1123,14 +1143,24 @@ case 7:
1123
1143
  _out: {}
1124
1144
  }
1125
1145
 
1126
- #line 348 "parser.rl"
1146
+ #line 368 "parser.rl"
1127
1147
 
1128
1148
  if (cs >= JSON_float_first_final) {
1129
1149
  long len = p - json->memo;
1130
1150
  fbuffer_clear(json->fbuffer);
1131
1151
  fbuffer_append(json->fbuffer, json->memo, len);
1132
1152
  fbuffer_append_char(json->fbuffer, '\0');
1133
- *result = rb_float_new(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
1153
+ if (NIL_P(json->decimal_class)) {
1154
+ *result = rb_float_new(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
1155
+ } else {
1156
+ VALUE text;
1157
+ text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
1158
+ if (is_bigdecimal_class(json->decimal_class)) {
1159
+ *result = rb_funcall(Qnil, i_BigDecimal, 1, text);
1160
+ } else {
1161
+ *result = rb_funcall(json->decimal_class, i_new, 1, text);
1162
+ }
1163
+ }
1134
1164
  return p + 1;
1135
1165
  } else {
1136
1166
  return NULL;
@@ -1139,7 +1169,7 @@ case 7:
1139
1169
 
1140
1170
 
1141
1171
 
1142
- #line 1143 "parser.c"
1172
+ #line 1173 "parser.c"
1143
1173
  enum {JSON_array_start = 1};
1144
1174
  enum {JSON_array_first_final = 17};
1145
1175
  enum {JSON_array_error = 0};
@@ -1147,7 +1177,7 @@ enum {JSON_array_error = 0};
1147
1177
  enum {JSON_array_en_main = 1};
1148
1178
 
1149
1179
 
1150
- #line 391 "parser.rl"
1180
+ #line 421 "parser.rl"
1151
1181
 
1152
1182
 
1153
1183
  static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
@@ -1161,14 +1191,14 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
1161
1191
  *result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
1162
1192
 
1163
1193
 
1164
- #line 1165 "parser.c"
1194
+ #line 1195 "parser.c"
1165
1195
  {
1166
1196
  cs = JSON_array_start;
1167
1197
  }
1168
1198
 
1169
- #line 404 "parser.rl"
1199
+ #line 434 "parser.rl"
1170
1200
 
1171
- #line 1172 "parser.c"
1201
+ #line 1202 "parser.c"
1172
1202
  {
1173
1203
  if ( p == pe )
1174
1204
  goto _test_eof;
@@ -1207,7 +1237,7 @@ case 2:
1207
1237
  goto st2;
1208
1238
  goto st0;
1209
1239
  tr2:
1210
- #line 368 "parser.rl"
1240
+ #line 398 "parser.rl"
1211
1241
  {
1212
1242
  VALUE v = Qnil;
1213
1243
  char *np = JSON_parse_value(json, p, pe, &v, current_nesting);
@@ -1227,7 +1257,7 @@ st3:
1227
1257
  if ( ++p == pe )
1228
1258
  goto _test_eof3;
1229
1259
  case 3:
1230
- #line 1231 "parser.c"
1260
+ #line 1261 "parser.c"
1231
1261
  switch( (*p) ) {
1232
1262
  case 13: goto st3;
1233
1263
  case 32: goto st3;
@@ -1327,14 +1357,14 @@ case 12:
1327
1357
  goto st3;
1328
1358
  goto st12;
1329
1359
  tr4:
1330
- #line 383 "parser.rl"
1360
+ #line 413 "parser.rl"
1331
1361
  { p--; {p++; cs = 17; goto _out;} }
1332
1362
  goto st17;
1333
1363
  st17:
1334
1364
  if ( ++p == pe )
1335
1365
  goto _test_eof17;
1336
1366
  case 17:
1337
- #line 1338 "parser.c"
1367
+ #line 1368 "parser.c"
1338
1368
  goto st0;
1339
1369
  st13:
1340
1370
  if ( ++p == pe )
@@ -1390,7 +1420,7 @@ case 16:
1390
1420
  _out: {}
1391
1421
  }
1392
1422
 
1393
- #line 405 "parser.rl"
1423
+ #line 435 "parser.rl"
1394
1424
 
1395
1425
  if(cs >= JSON_array_first_final) {
1396
1426
  return p + 1;
@@ -1479,7 +1509,7 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
1479
1509
  }
1480
1510
 
1481
1511
 
1482
- #line 1483 "parser.c"
1512
+ #line 1513 "parser.c"
1483
1513
  enum {JSON_string_start = 1};
1484
1514
  enum {JSON_string_first_final = 8};
1485
1515
  enum {JSON_string_error = 0};
@@ -1487,7 +1517,7 @@ enum {JSON_string_error = 0};
1487
1517
  enum {JSON_string_en_main = 1};
1488
1518
 
1489
1519
 
1490
- #line 512 "parser.rl"
1520
+ #line 542 "parser.rl"
1491
1521
 
1492
1522
 
1493
1523
  static int
@@ -1509,15 +1539,15 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
1509
1539
 
1510
1540
  *result = rb_str_buf_new(0);
1511
1541
 
1512
- #line 1513 "parser.c"
1542
+ #line 1543 "parser.c"
1513
1543
  {
1514
1544
  cs = JSON_string_start;
1515
1545
  }
1516
1546
 
1517
- #line 533 "parser.rl"
1547
+ #line 563 "parser.rl"
1518
1548
  json->memo = p;
1519
1549
 
1520
- #line 1521 "parser.c"
1550
+ #line 1551 "parser.c"
1521
1551
  {
1522
1552
  if ( p == pe )
1523
1553
  goto _test_eof;
@@ -1538,11 +1568,11 @@ case 2:
1538
1568
  case 34: goto tr2;
1539
1569
  case 92: goto st3;
1540
1570
  }
1541
- if ( 0 <= (*p) && (*p) <= 31 )
1571
+ if ( 0 <= (signed char)(*p) && (*p) <= 31 )
1542
1572
  goto st0;
1543
1573
  goto st2;
1544
1574
  tr2:
1545
- #line 498 "parser.rl"
1575
+ #line 528 "parser.rl"
1546
1576
  {
1547
1577
  *result = json_string_unescape(*result, json->memo + 1, p);
1548
1578
  if (NIL_P(*result)) {
@@ -1553,14 +1583,14 @@ tr2:
1553
1583
  {p = (( p + 1))-1;}
1554
1584
  }
1555
1585
  }
1556
- #line 509 "parser.rl"
1586
+ #line 539 "parser.rl"
1557
1587
  { p--; {p++; cs = 8; goto _out;} }
1558
1588
  goto st8;
1559
1589
  st8:
1560
1590
  if ( ++p == pe )
1561
1591
  goto _test_eof8;
1562
1592
  case 8:
1563
- #line 1564 "parser.c"
1593
+ #line 1594 "parser.c"
1564
1594
  goto st0;
1565
1595
  st3:
1566
1596
  if ( ++p == pe )
@@ -1568,7 +1598,7 @@ st3:
1568
1598
  case 3:
1569
1599
  if ( (*p) == 117 )
1570
1600
  goto st4;
1571
- if ( 0 <= (*p) && (*p) <= 31 )
1601
+ if ( 0 <= (signed char)(*p) && (*p) <= 31 )
1572
1602
  goto st0;
1573
1603
  goto st2;
1574
1604
  st4:
@@ -1636,7 +1666,7 @@ case 7:
1636
1666
  _out: {}
1637
1667
  }
1638
1668
 
1639
- #line 535 "parser.rl"
1669
+ #line 565 "parser.rl"
1640
1670
 
1641
1671
  if (json->create_additions && RTEST(match_string = json->match_string)) {
1642
1672
  VALUE klass;
@@ -1651,8 +1681,23 @@ case 7:
1651
1681
 
1652
1682
  if (json->symbolize_names && json->parsing_name) {
1653
1683
  *result = rb_str_intern(*result);
1654
- } else {
1684
+ } else if (RB_TYPE_P(*result, T_STRING)) {
1685
+ # if STR_UMINUS_DEDUPE_FROZEN
1686
+ if (json->freeze) {
1687
+ // Starting from MRI 2.8 it is preferable to freeze the string
1688
+ // before deduplication so that it can be interned directly
1689
+ // otherwise it would be duplicated first which is wasteful.
1690
+ *result = rb_funcall(rb_str_freeze(*result), i_uminus, 0);
1691
+ }
1692
+ # elif STR_UMINUS_DEDUPE
1693
+ if (json->freeze) {
1694
+ // MRI 2.5 and older do not deduplicate strings that are already
1695
+ // frozen.
1696
+ *result = rb_funcall(*result, i_uminus, 0);
1697
+ }
1698
+ # else
1655
1699
  rb_str_resize(*result, RSTRING_LEN(*result));
1700
+ # endif
1656
1701
  }
1657
1702
  if (cs >= JSON_string_first_final) {
1658
1703
  return p + 1;
@@ -1760,6 +1805,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
1760
1805
  } else {
1761
1806
  json->symbolize_names = 0;
1762
1807
  }
1808
+ tmp = ID2SYM(i_freeze);
1809
+ if (option_given_p(opts, tmp)) {
1810
+ json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
1811
+ } else {
1812
+ json->freeze = 0;
1813
+ }
1763
1814
  tmp = ID2SYM(i_create_additions);
1764
1815
  if (option_given_p(opts, tmp)) {
1765
1816
  json->create_additions = RTEST(rb_hash_aref(opts, tmp));
@@ -1789,6 +1840,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
1789
1840
  } else {
1790
1841
  json->array_class = Qnil;
1791
1842
  }
1843
+ tmp = ID2SYM(i_decimal_class);
1844
+ if (option_given_p(opts, tmp)) {
1845
+ json->decimal_class = rb_hash_aref(opts, tmp);
1846
+ } else {
1847
+ json->decimal_class = Qnil;
1848
+ }
1792
1849
  tmp = ID2SYM(i_match_string);
1793
1850
  if (option_given_p(opts, tmp)) {
1794
1851
  VALUE match_string = rb_hash_aref(opts, tmp);
@@ -1802,10 +1859,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
1802
1859
  } else {
1803
1860
  json->max_nesting = 100;
1804
1861
  json->allow_nan = 0;
1805
- json->create_additions = 1;
1862
+ json->create_additions = 0;
1806
1863
  json->create_id = rb_funcall(mJSON, i_create_id, 0);
1807
1864
  json->object_class = Qnil;
1808
1865
  json->array_class = Qnil;
1866
+ json->decimal_class = Qnil;
1809
1867
  }
1810
1868
  source = convert_encoding(StringValue(source));
1811
1869
  StringValue(source);
@@ -1816,7 +1874,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
1816
1874
  }
1817
1875
 
1818
1876
 
1819
- #line 1820 "parser.c"
1877
+ #line 1878 "parser.c"
1820
1878
  enum {JSON_start = 1};
1821
1879
  enum {JSON_first_final = 10};
1822
1880
  enum {JSON_error = 0};
@@ -1824,7 +1882,7 @@ enum {JSON_error = 0};
1824
1882
  enum {JSON_en_main = 1};
1825
1883
 
1826
1884
 
1827
- #line 728 "parser.rl"
1885
+ #line 786 "parser.rl"
1828
1886
 
1829
1887
 
1830
1888
  /*
@@ -1841,16 +1899,16 @@ static VALUE cParser_parse(VALUE self)
1841
1899
  GET_PARSER;
1842
1900
 
1843
1901
 
1844
- #line 1845 "parser.c"
1902
+ #line 1903 "parser.c"
1845
1903
  {
1846
1904
  cs = JSON_start;
1847
1905
  }
1848
1906
 
1849
- #line 744 "parser.rl"
1907
+ #line 802 "parser.rl"
1850
1908
  p = json->source;
1851
1909
  pe = p + json->len;
1852
1910
 
1853
- #line 1854 "parser.c"
1911
+ #line 1912 "parser.c"
1854
1912
  {
1855
1913
  if ( p == pe )
1856
1914
  goto _test_eof;
@@ -1884,7 +1942,7 @@ st0:
1884
1942
  cs = 0;
1885
1943
  goto _out;
1886
1944
  tr2:
1887
- #line 720 "parser.rl"
1945
+ #line 778 "parser.rl"
1888
1946
  {
1889
1947
  char *np = JSON_parse_value(json, p, pe, &result, 0);
1890
1948
  if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
@@ -1894,7 +1952,7 @@ st10:
1894
1952
  if ( ++p == pe )
1895
1953
  goto _test_eof10;
1896
1954
  case 10:
1897
- #line 1898 "parser.c"
1955
+ #line 1956 "parser.c"
1898
1956
  switch( (*p) ) {
1899
1957
  case 13: goto st10;
1900
1958
  case 32: goto st10;
@@ -1983,7 +2041,7 @@ case 9:
1983
2041
  _out: {}
1984
2042
  }
1985
2043
 
1986
- #line 747 "parser.rl"
2044
+ #line 805 "parser.rl"
1987
2045
 
1988
2046
  if (cs >= JSON_first_final && p == pe) {
1989
2047
  return result;
@@ -2000,6 +2058,7 @@ static void JSON_mark(void *ptr)
2000
2058
  rb_gc_mark_maybe(json->create_id);
2001
2059
  rb_gc_mark_maybe(json->object_class);
2002
2060
  rb_gc_mark_maybe(json->array_class);
2061
+ rb_gc_mark_maybe(json->decimal_class);
2003
2062
  rb_gc_mark_maybe(json->match_string);
2004
2063
  }
2005
2064
 
@@ -2049,20 +2108,28 @@ static VALUE cParser_source(VALUE self)
2049
2108
 
2050
2109
  void Init_parser(void)
2051
2110
  {
2111
+ #undef rb_intern
2052
2112
  rb_require("json/common");
2053
2113
  mJSON = rb_define_module("JSON");
2054
2114
  mExt = rb_define_module_under(mJSON, "Ext");
2055
2115
  cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
2056
2116
  eParserError = rb_path2class("JSON::ParserError");
2057
2117
  eNestingError = rb_path2class("JSON::NestingError");
2118
+ rb_gc_register_mark_object(eParserError);
2119
+ rb_gc_register_mark_object(eNestingError);
2058
2120
  rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
2059
2121
  rb_define_method(cParser, "initialize", cParser_initialize, -1);
2060
2122
  rb_define_method(cParser, "parse", cParser_parse, 0);
2061
2123
  rb_define_method(cParser, "source", cParser_source, 0);
2062
2124
 
2063
2125
  CNaN = rb_const_get(mJSON, rb_intern("NaN"));
2126
+ rb_gc_register_mark_object(CNaN);
2127
+
2064
2128
  CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
2129
+ rb_gc_register_mark_object(CInfinity);
2130
+
2065
2131
  CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
2132
+ rb_gc_register_mark_object(CMinusInfinity);
2066
2133
 
2067
2134
  i_json_creatable_p = rb_intern("json_creatable?");
2068
2135
  i_json_create = rb_intern("json_create");
@@ -2074,6 +2141,7 @@ void Init_parser(void)
2074
2141
  i_symbolize_names = rb_intern("symbolize_names");
2075
2142
  i_object_class = rb_intern("object_class");
2076
2143
  i_array_class = rb_intern("array_class");
2144
+ i_decimal_class = rb_intern("decimal_class");
2077
2145
  i_match = rb_intern("match");
2078
2146
  i_match_string = rb_intern("match_string");
2079
2147
  i_key_p = rb_intern("key?");
@@ -2081,6 +2149,10 @@ void Init_parser(void)
2081
2149
  i_aset = rb_intern("[]=");
2082
2150
  i_aref = rb_intern("[]");
2083
2151
  i_leftshift = rb_intern("<<");
2152
+ i_new = rb_intern("new");
2153
+ i_BigDecimal = rb_intern("BigDecimal");
2154
+ i_freeze = rb_intern("freeze");
2155
+ i_uminus = rb_intern("-@");
2084
2156
  }
2085
2157
 
2086
2158
  /*