json_pure 2.0.4 → 2.4.0

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