json 2.3.0 → 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.
@@ -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"
@@ -97,7 +97,7 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
97
97
  i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
98
98
  i_object_class, i_array_class, i_decimal_class, i_key_p,
99
99
  i_deep_const_get, i_match, i_match_string, i_aset, i_aref,
100
- i_leftshift, i_new, i_BigDecimal;
100
+ i_leftshift, i_new, i_BigDecimal, i_freeze, i_uminus;
101
101
 
102
102
 
103
103
  #line 126 "parser.rl"
@@ -112,7 +112,7 @@ enum {JSON_object_error = 0};
112
112
  enum {JSON_object_en_main = 1};
113
113
 
114
114
 
115
- #line 167 "parser.rl"
115
+ #line 168 "parser.rl"
116
116
 
117
117
 
118
118
  static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
@@ -133,7 +133,7 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
133
133
  cs = JSON_object_start;
134
134
  }
135
135
 
136
- #line 182 "parser.rl"
136
+ #line 183 "parser.rl"
137
137
 
138
138
  #line 139 "parser.c"
139
139
  {
@@ -163,7 +163,7 @@ case 2:
163
163
  goto st2;
164
164
  goto st0;
165
165
  tr2:
166
- #line 149 "parser.rl"
166
+ #line 150 "parser.rl"
167
167
  {
168
168
  char *np;
169
169
  json->parsing_name = 1;
@@ -251,6 +251,7 @@ tr11:
251
251
  p--; {p++; cs = 9; goto _out;}
252
252
  } else {
253
253
  if (NIL_P(json->object_class)) {
254
+ OBJ_FREEZE(last_name);
254
255
  rb_hash_aset(*result, last_name, v);
255
256
  } else {
256
257
  rb_funcall(*result, i_aset, 2, last_name, v);
@@ -263,7 +264,7 @@ st9:
263
264
  if ( ++p == pe )
264
265
  goto _test_eof9;
265
266
  case 9:
266
- #line 267 "parser.c"
267
+ #line 268 "parser.c"
267
268
  switch( (*p) ) {
268
269
  case 13: goto st9;
269
270
  case 32: goto st9;
@@ -352,14 +353,14 @@ case 18:
352
353
  goto st9;
353
354
  goto st18;
354
355
  tr4:
355
- #line 157 "parser.rl"
356
+ #line 158 "parser.rl"
356
357
  { p--; {p++; cs = 27; goto _out;} }
357
358
  goto st27;
358
359
  st27:
359
360
  if ( ++p == pe )
360
361
  goto _test_eof27;
361
362
  case 27:
362
- #line 363 "parser.c"
363
+ #line 364 "parser.c"
363
364
  goto st0;
364
365
  st19:
365
366
  if ( ++p == pe )
@@ -457,7 +458,7 @@ case 26:
457
458
  _out: {}
458
459
  }
459
460
 
460
- #line 183 "parser.rl"
461
+ #line 184 "parser.rl"
461
462
 
462
463
  if (cs >= JSON_object_first_final) {
463
464
  if (json->create_additions) {
@@ -482,7 +483,7 @@ case 26:
482
483
 
483
484
 
484
485
 
485
- #line 486 "parser.c"
486
+ #line 487 "parser.c"
486
487
  enum {JSON_value_start = 1};
487
488
  enum {JSON_value_first_final = 29};
488
489
  enum {JSON_value_error = 0};
@@ -490,7 +491,7 @@ enum {JSON_value_error = 0};
490
491
  enum {JSON_value_en_main = 1};
491
492
 
492
493
 
493
- #line 283 "parser.rl"
494
+ #line 284 "parser.rl"
494
495
 
495
496
 
496
497
  static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
@@ -498,14 +499,14 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
498
499
  int cs = EVIL;
499
500
 
500
501
 
501
- #line 502 "parser.c"
502
+ #line 503 "parser.c"
502
503
  {
503
504
  cs = JSON_value_start;
504
505
  }
505
506
 
506
- #line 290 "parser.rl"
507
+ #line 291 "parser.rl"
507
508
 
508
- #line 509 "parser.c"
509
+ #line 510 "parser.c"
509
510
  {
510
511
  if ( p == pe )
511
512
  goto _test_eof;
@@ -539,14 +540,14 @@ st0:
539
540
  cs = 0;
540
541
  goto _out;
541
542
  tr2:
542
- #line 235 "parser.rl"
543
+ #line 236 "parser.rl"
543
544
  {
544
545
  char *np = JSON_parse_string(json, p, pe, result);
545
546
  if (np == NULL) { p--; {p++; cs = 29; goto _out;} } else {p = (( np))-1;}
546
547
  }
547
548
  goto st29;
548
549
  tr3:
549
- #line 240 "parser.rl"
550
+ #line 241 "parser.rl"
550
551
  {
551
552
  char *np;
552
553
  if(pe > p + 8 && !strncmp(MinusInfinity, p, 9)) {
@@ -566,7 +567,7 @@ tr3:
566
567
  }
567
568
  goto st29;
568
569
  tr7:
569
- #line 258 "parser.rl"
570
+ #line 259 "parser.rl"
570
571
  {
571
572
  char *np;
572
573
  np = JSON_parse_array(json, p, pe, result, current_nesting + 1);
@@ -574,7 +575,7 @@ tr7:
574
575
  }
575
576
  goto st29;
576
577
  tr11:
577
- #line 264 "parser.rl"
578
+ #line 265 "parser.rl"
578
579
  {
579
580
  char *np;
580
581
  np = JSON_parse_object(json, p, pe, result, current_nesting + 1);
@@ -582,7 +583,7 @@ tr11:
582
583
  }
583
584
  goto st29;
584
585
  tr25:
585
- #line 228 "parser.rl"
586
+ #line 229 "parser.rl"
586
587
  {
587
588
  if (json->allow_nan) {
588
589
  *result = CInfinity;
@@ -592,7 +593,7 @@ tr25:
592
593
  }
593
594
  goto st29;
594
595
  tr27:
595
- #line 221 "parser.rl"
596
+ #line 222 "parser.rl"
596
597
  {
597
598
  if (json->allow_nan) {
598
599
  *result = CNaN;
@@ -602,19 +603,19 @@ tr27:
602
603
  }
603
604
  goto st29;
604
605
  tr31:
605
- #line 215 "parser.rl"
606
+ #line 216 "parser.rl"
606
607
  {
607
608
  *result = Qfalse;
608
609
  }
609
610
  goto st29;
610
611
  tr34:
611
- #line 212 "parser.rl"
612
+ #line 213 "parser.rl"
612
613
  {
613
614
  *result = Qnil;
614
615
  }
615
616
  goto st29;
616
617
  tr37:
617
- #line 218 "parser.rl"
618
+ #line 219 "parser.rl"
618
619
  {
619
620
  *result = Qtrue;
620
621
  }
@@ -623,9 +624,9 @@ st29:
623
624
  if ( ++p == pe )
624
625
  goto _test_eof29;
625
626
  case 29:
626
- #line 270 "parser.rl"
627
+ #line 271 "parser.rl"
627
628
  { p--; {p++; cs = 29; goto _out;} }
628
- #line 629 "parser.c"
629
+ #line 630 "parser.c"
629
630
  switch( (*p) ) {
630
631
  case 13: goto st29;
631
632
  case 32: goto st29;
@@ -866,7 +867,11 @@ case 28:
866
867
  _out: {}
867
868
  }
868
869
 
869
- #line 291 "parser.rl"
870
+ #line 292 "parser.rl"
871
+
872
+ if (json->freeze) {
873
+ OBJ_FREEZE(*result);
874
+ }
870
875
 
871
876
  if (cs >= JSON_value_first_final) {
872
877
  return p;
@@ -876,7 +881,7 @@ case 28:
876
881
  }
877
882
 
878
883
 
879
- #line 880 "parser.c"
884
+ #line 885 "parser.c"
880
885
  enum {JSON_integer_start = 1};
881
886
  enum {JSON_integer_first_final = 3};
882
887
  enum {JSON_integer_error = 0};
@@ -884,7 +889,7 @@ enum {JSON_integer_error = 0};
884
889
  enum {JSON_integer_en_main = 1};
885
890
 
886
891
 
887
- #line 307 "parser.rl"
892
+ #line 312 "parser.rl"
888
893
 
889
894
 
890
895
  static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -892,15 +897,15 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
892
897
  int cs = EVIL;
893
898
 
894
899
 
895
- #line 896 "parser.c"
900
+ #line 901 "parser.c"
896
901
  {
897
902
  cs = JSON_integer_start;
898
903
  }
899
904
 
900
- #line 314 "parser.rl"
905
+ #line 319 "parser.rl"
901
906
  json->memo = p;
902
907
 
903
- #line 904 "parser.c"
908
+ #line 909 "parser.c"
904
909
  {
905
910
  if ( p == pe )
906
911
  goto _test_eof;
@@ -934,14 +939,14 @@ case 3:
934
939
  goto st0;
935
940
  goto tr4;
936
941
  tr4:
937
- #line 304 "parser.rl"
942
+ #line 309 "parser.rl"
938
943
  { p--; {p++; cs = 4; goto _out;} }
939
944
  goto st4;
940
945
  st4:
941
946
  if ( ++p == pe )
942
947
  goto _test_eof4;
943
948
  case 4:
944
- #line 945 "parser.c"
949
+ #line 950 "parser.c"
945
950
  goto st0;
946
951
  st5:
947
952
  if ( ++p == pe )
@@ -960,7 +965,7 @@ case 5:
960
965
  _out: {}
961
966
  }
962
967
 
963
- #line 316 "parser.rl"
968
+ #line 321 "parser.rl"
964
969
 
965
970
  if (cs >= JSON_integer_first_final) {
966
971
  long len = p - json->memo;
@@ -975,7 +980,7 @@ case 5:
975
980
  }
976
981
 
977
982
 
978
- #line 979 "parser.c"
983
+ #line 984 "parser.c"
979
984
  enum {JSON_float_start = 1};
980
985
  enum {JSON_float_first_final = 8};
981
986
  enum {JSON_float_error = 0};
@@ -983,7 +988,7 @@ enum {JSON_float_error = 0};
983
988
  enum {JSON_float_en_main = 1};
984
989
 
985
990
 
986
- #line 341 "parser.rl"
991
+ #line 346 "parser.rl"
987
992
 
988
993
 
989
994
  static int is_bigdecimal_class(VALUE obj)
@@ -1004,15 +1009,15 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
1004
1009
  int cs = EVIL;
1005
1010
 
1006
1011
 
1007
- #line 1008 "parser.c"
1012
+ #line 1013 "parser.c"
1008
1013
  {
1009
1014
  cs = JSON_float_start;
1010
1015
  }
1011
1016
 
1012
- #line 361 "parser.rl"
1017
+ #line 366 "parser.rl"
1013
1018
  json->memo = p;
1014
1019
 
1015
- #line 1016 "parser.c"
1020
+ #line 1021 "parser.c"
1016
1021
  {
1017
1022
  if ( p == pe )
1018
1023
  goto _test_eof;
@@ -1070,14 +1075,14 @@ case 8:
1070
1075
  goto st0;
1071
1076
  goto tr9;
1072
1077
  tr9:
1073
- #line 335 "parser.rl"
1078
+ #line 340 "parser.rl"
1074
1079
  { p--; {p++; cs = 9; goto _out;} }
1075
1080
  goto st9;
1076
1081
  st9:
1077
1082
  if ( ++p == pe )
1078
1083
  goto _test_eof9;
1079
1084
  case 9:
1080
- #line 1081 "parser.c"
1085
+ #line 1086 "parser.c"
1081
1086
  goto st0;
1082
1087
  st5:
1083
1088
  if ( ++p == pe )
@@ -1138,7 +1143,7 @@ case 7:
1138
1143
  _out: {}
1139
1144
  }
1140
1145
 
1141
- #line 363 "parser.rl"
1146
+ #line 368 "parser.rl"
1142
1147
 
1143
1148
  if (cs >= JSON_float_first_final) {
1144
1149
  long len = p - json->memo;
@@ -1164,7 +1169,7 @@ case 7:
1164
1169
 
1165
1170
 
1166
1171
 
1167
- #line 1168 "parser.c"
1172
+ #line 1173 "parser.c"
1168
1173
  enum {JSON_array_start = 1};
1169
1174
  enum {JSON_array_first_final = 17};
1170
1175
  enum {JSON_array_error = 0};
@@ -1172,7 +1177,7 @@ enum {JSON_array_error = 0};
1172
1177
  enum {JSON_array_en_main = 1};
1173
1178
 
1174
1179
 
1175
- #line 416 "parser.rl"
1180
+ #line 421 "parser.rl"
1176
1181
 
1177
1182
 
1178
1183
  static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
@@ -1186,14 +1191,14 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
1186
1191
  *result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
1187
1192
 
1188
1193
 
1189
- #line 1190 "parser.c"
1194
+ #line 1195 "parser.c"
1190
1195
  {
1191
1196
  cs = JSON_array_start;
1192
1197
  }
1193
1198
 
1194
- #line 429 "parser.rl"
1199
+ #line 434 "parser.rl"
1195
1200
 
1196
- #line 1197 "parser.c"
1201
+ #line 1202 "parser.c"
1197
1202
  {
1198
1203
  if ( p == pe )
1199
1204
  goto _test_eof;
@@ -1232,7 +1237,7 @@ case 2:
1232
1237
  goto st2;
1233
1238
  goto st0;
1234
1239
  tr2:
1235
- #line 393 "parser.rl"
1240
+ #line 398 "parser.rl"
1236
1241
  {
1237
1242
  VALUE v = Qnil;
1238
1243
  char *np = JSON_parse_value(json, p, pe, &v, current_nesting);
@@ -1252,7 +1257,7 @@ st3:
1252
1257
  if ( ++p == pe )
1253
1258
  goto _test_eof3;
1254
1259
  case 3:
1255
- #line 1256 "parser.c"
1260
+ #line 1261 "parser.c"
1256
1261
  switch( (*p) ) {
1257
1262
  case 13: goto st3;
1258
1263
  case 32: goto st3;
@@ -1352,14 +1357,14 @@ case 12:
1352
1357
  goto st3;
1353
1358
  goto st12;
1354
1359
  tr4:
1355
- #line 408 "parser.rl"
1360
+ #line 413 "parser.rl"
1356
1361
  { p--; {p++; cs = 17; goto _out;} }
1357
1362
  goto st17;
1358
1363
  st17:
1359
1364
  if ( ++p == pe )
1360
1365
  goto _test_eof17;
1361
1366
  case 17:
1362
- #line 1363 "parser.c"
1367
+ #line 1368 "parser.c"
1363
1368
  goto st0;
1364
1369
  st13:
1365
1370
  if ( ++p == pe )
@@ -1415,7 +1420,7 @@ case 16:
1415
1420
  _out: {}
1416
1421
  }
1417
1422
 
1418
- #line 430 "parser.rl"
1423
+ #line 435 "parser.rl"
1419
1424
 
1420
1425
  if(cs >= JSON_array_first_final) {
1421
1426
  return p + 1;
@@ -1504,7 +1509,7 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
1504
1509
  }
1505
1510
 
1506
1511
 
1507
- #line 1508 "parser.c"
1512
+ #line 1513 "parser.c"
1508
1513
  enum {JSON_string_start = 1};
1509
1514
  enum {JSON_string_first_final = 8};
1510
1515
  enum {JSON_string_error = 0};
@@ -1512,7 +1517,7 @@ enum {JSON_string_error = 0};
1512
1517
  enum {JSON_string_en_main = 1};
1513
1518
 
1514
1519
 
1515
- #line 537 "parser.rl"
1520
+ #line 542 "parser.rl"
1516
1521
 
1517
1522
 
1518
1523
  static int
@@ -1534,15 +1539,15 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
1534
1539
 
1535
1540
  *result = rb_str_buf_new(0);
1536
1541
 
1537
- #line 1538 "parser.c"
1542
+ #line 1543 "parser.c"
1538
1543
  {
1539
1544
  cs = JSON_string_start;
1540
1545
  }
1541
1546
 
1542
- #line 558 "parser.rl"
1547
+ #line 563 "parser.rl"
1543
1548
  json->memo = p;
1544
1549
 
1545
- #line 1546 "parser.c"
1550
+ #line 1551 "parser.c"
1546
1551
  {
1547
1552
  if ( p == pe )
1548
1553
  goto _test_eof;
@@ -1563,11 +1568,11 @@ case 2:
1563
1568
  case 34: goto tr2;
1564
1569
  case 92: goto st3;
1565
1570
  }
1566
- if ( 0 <= (*p) && (*p) <= 31 )
1571
+ if ( 0 <= (signed char)(*p) && (*p) <= 31 )
1567
1572
  goto st0;
1568
1573
  goto st2;
1569
1574
  tr2:
1570
- #line 523 "parser.rl"
1575
+ #line 528 "parser.rl"
1571
1576
  {
1572
1577
  *result = json_string_unescape(*result, json->memo + 1, p);
1573
1578
  if (NIL_P(*result)) {
@@ -1578,14 +1583,14 @@ tr2:
1578
1583
  {p = (( p + 1))-1;}
1579
1584
  }
1580
1585
  }
1581
- #line 534 "parser.rl"
1586
+ #line 539 "parser.rl"
1582
1587
  { p--; {p++; cs = 8; goto _out;} }
1583
1588
  goto st8;
1584
1589
  st8:
1585
1590
  if ( ++p == pe )
1586
1591
  goto _test_eof8;
1587
1592
  case 8:
1588
- #line 1589 "parser.c"
1593
+ #line 1594 "parser.c"
1589
1594
  goto st0;
1590
1595
  st3:
1591
1596
  if ( ++p == pe )
@@ -1593,7 +1598,7 @@ st3:
1593
1598
  case 3:
1594
1599
  if ( (*p) == 117 )
1595
1600
  goto st4;
1596
- if ( 0 <= (*p) && (*p) <= 31 )
1601
+ if ( 0 <= (signed char)(*p) && (*p) <= 31 )
1597
1602
  goto st0;
1598
1603
  goto st2;
1599
1604
  st4:
@@ -1661,7 +1666,7 @@ case 7:
1661
1666
  _out: {}
1662
1667
  }
1663
1668
 
1664
- #line 560 "parser.rl"
1669
+ #line 565 "parser.rl"
1665
1670
 
1666
1671
  if (json->create_additions && RTEST(match_string = json->match_string)) {
1667
1672
  VALUE klass;
@@ -1677,7 +1682,22 @@ case 7:
1677
1682
  if (json->symbolize_names && json->parsing_name) {
1678
1683
  *result = rb_str_intern(*result);
1679
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
1680
1699
  rb_str_resize(*result, RSTRING_LEN(*result));
1700
+ # endif
1681
1701
  }
1682
1702
  if (cs >= JSON_string_first_final) {
1683
1703
  return p + 1;
@@ -1785,6 +1805,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
1785
1805
  } else {
1786
1806
  json->symbolize_names = 0;
1787
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
+ }
1788
1814
  tmp = ID2SYM(i_create_additions);
1789
1815
  if (option_given_p(opts, tmp)) {
1790
1816
  json->create_additions = RTEST(rb_hash_aref(opts, tmp));
@@ -1848,7 +1874,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
1848
1874
  }
1849
1875
 
1850
1876
 
1851
- #line 1852 "parser.c"
1877
+ #line 1878 "parser.c"
1852
1878
  enum {JSON_start = 1};
1853
1879
  enum {JSON_first_final = 10};
1854
1880
  enum {JSON_error = 0};
@@ -1856,7 +1882,7 @@ enum {JSON_error = 0};
1856
1882
  enum {JSON_en_main = 1};
1857
1883
 
1858
1884
 
1859
- #line 760 "parser.rl"
1885
+ #line 786 "parser.rl"
1860
1886
 
1861
1887
 
1862
1888
  /*
@@ -1873,16 +1899,16 @@ static VALUE cParser_parse(VALUE self)
1873
1899
  GET_PARSER;
1874
1900
 
1875
1901
 
1876
- #line 1877 "parser.c"
1902
+ #line 1903 "parser.c"
1877
1903
  {
1878
1904
  cs = JSON_start;
1879
1905
  }
1880
1906
 
1881
- #line 776 "parser.rl"
1907
+ #line 802 "parser.rl"
1882
1908
  p = json->source;
1883
1909
  pe = p + json->len;
1884
1910
 
1885
- #line 1886 "parser.c"
1911
+ #line 1912 "parser.c"
1886
1912
  {
1887
1913
  if ( p == pe )
1888
1914
  goto _test_eof;
@@ -1916,7 +1942,7 @@ st0:
1916
1942
  cs = 0;
1917
1943
  goto _out;
1918
1944
  tr2:
1919
- #line 752 "parser.rl"
1945
+ #line 778 "parser.rl"
1920
1946
  {
1921
1947
  char *np = JSON_parse_value(json, p, pe, &result, 0);
1922
1948
  if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
@@ -1926,7 +1952,7 @@ st10:
1926
1952
  if ( ++p == pe )
1927
1953
  goto _test_eof10;
1928
1954
  case 10:
1929
- #line 1930 "parser.c"
1955
+ #line 1956 "parser.c"
1930
1956
  switch( (*p) ) {
1931
1957
  case 13: goto st10;
1932
1958
  case 32: goto st10;
@@ -2015,7 +2041,7 @@ case 9:
2015
2041
  _out: {}
2016
2042
  }
2017
2043
 
2018
- #line 779 "parser.rl"
2044
+ #line 805 "parser.rl"
2019
2045
 
2020
2046
  if (cs >= JSON_first_final && p == pe) {
2021
2047
  return result;
@@ -2125,6 +2151,8 @@ void Init_parser(void)
2125
2151
  i_leftshift = rb_intern("<<");
2126
2152
  i_new = rb_intern("new");
2127
2153
  i_BigDecimal = rb_intern("BigDecimal");
2154
+ i_freeze = rb_intern("freeze");
2155
+ i_uminus = rb_intern("-@");
2128
2156
  }
2129
2157
 
2130
2158
  /*
@@ -37,6 +37,7 @@ typedef struct JSON_ParserStruct {
37
37
  int allow_nan;
38
38
  int parsing_name;
39
39
  int symbolize_names;
40
+ int freeze;
40
41
  VALUE object_class;
41
42
  VALUE array_class;
42
43
  VALUE decimal_class;
@@ -95,7 +95,7 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
95
95
  i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
96
96
  i_object_class, i_array_class, i_decimal_class, i_key_p,
97
97
  i_deep_const_get, i_match, i_match_string, i_aset, i_aref,
98
- i_leftshift, i_new, i_BigDecimal;
98
+ i_leftshift, i_new, i_BigDecimal, i_freeze, i_uminus;
99
99
 
100
100
  %%{
101
101
  machine JSON_common;
@@ -138,6 +138,7 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
138
138
  fhold; fbreak;
139
139
  } else {
140
140
  if (NIL_P(json->object_class)) {
141
+ OBJ_FREEZE(last_name);
141
142
  rb_hash_aset(*result, last_name, v);
142
143
  } else {
143
144
  rb_funcall(*result, i_aset, 2, last_name, v);
@@ -289,6 +290,10 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
289
290
  %% write init;
290
291
  %% write exec;
291
292
 
293
+ if (json->freeze) {
294
+ OBJ_FREEZE(*result);
295
+ }
296
+
292
297
  if (cs >= JSON_value_first_final) {
293
298
  return p;
294
299
  } else {
@@ -572,7 +577,22 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
572
577
  if (json->symbolize_names && json->parsing_name) {
573
578
  *result = rb_str_intern(*result);
574
579
  } else if (RB_TYPE_P(*result, T_STRING)) {
580
+ # if STR_UMINUS_DEDUPE_FROZEN
581
+ if (json->freeze) {
582
+ // Starting from MRI 2.8 it is preferable to freeze the string
583
+ // before deduplication so that it can be interned directly
584
+ // otherwise it would be duplicated first which is wasteful.
585
+ *result = rb_funcall(rb_str_freeze(*result), i_uminus, 0);
586
+ }
587
+ # elif STR_UMINUS_DEDUPE
588
+ if (json->freeze) {
589
+ // MRI 2.5 and older do not deduplicate strings that are already
590
+ // frozen.
591
+ *result = rb_funcall(*result, i_uminus, 0);
592
+ }
593
+ # else
575
594
  rb_str_resize(*result, RSTRING_LEN(*result));
595
+ # endif
576
596
  }
577
597
  if (cs >= JSON_string_first_final) {
578
598
  return p + 1;
@@ -680,6 +700,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
680
700
  } else {
681
701
  json->symbolize_names = 0;
682
702
  }
703
+ tmp = ID2SYM(i_freeze);
704
+ if (option_given_p(opts, tmp)) {
705
+ json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
706
+ } else {
707
+ json->freeze = 0;
708
+ }
683
709
  tmp = ID2SYM(i_create_additions);
684
710
  if (option_given_p(opts, tmp)) {
685
711
  json->create_additions = RTEST(rb_hash_aref(opts, tmp));
@@ -885,6 +911,8 @@ void Init_parser(void)
885
911
  i_leftshift = rb_intern("<<");
886
912
  i_new = rb_intern("new");
887
913
  i_BigDecimal = rb_intern("BigDecimal");
914
+ i_freeze = rb_intern("freeze");
915
+ i_uminus = rb_intern("-@");
888
916
  }
889
917
 
890
918
  /*
data/ext/json/extconf.rb CHANGED
@@ -1,2 +1,3 @@
1
1
  require 'mkmf'
2
+
2
3
  create_makefile('json')