oj 3.13.23 → 3.16.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +81 -0
  3. data/README.md +2 -2
  4. data/ext/oj/buf.h +7 -6
  5. data/ext/oj/cache.c +29 -26
  6. data/ext/oj/cache.h +3 -2
  7. data/ext/oj/cache8.c +10 -9
  8. data/ext/oj/circarray.c +7 -5
  9. data/ext/oj/circarray.h +2 -2
  10. data/ext/oj/code.c +5 -12
  11. data/ext/oj/code.h +2 -2
  12. data/ext/oj/compat.c +20 -60
  13. data/ext/oj/custom.c +26 -59
  14. data/ext/oj/debug.c +3 -9
  15. data/ext/oj/dump.c +103 -53
  16. data/ext/oj/dump.h +1 -4
  17. data/ext/oj/dump_compat.c +557 -592
  18. data/ext/oj/dump_leaf.c +3 -5
  19. data/ext/oj/dump_object.c +42 -48
  20. data/ext/oj/dump_strict.c +10 -22
  21. data/ext/oj/encoder.c +1 -1
  22. data/ext/oj/err.c +2 -13
  23. data/ext/oj/err.h +9 -12
  24. data/ext/oj/extconf.rb +16 -7
  25. data/ext/oj/fast.c +60 -92
  26. data/ext/oj/intern.c +62 -47
  27. data/ext/oj/intern.h +3 -7
  28. data/ext/oj/mem.c +318 -0
  29. data/ext/oj/mem.h +53 -0
  30. data/ext/oj/mimic_json.c +51 -32
  31. data/ext/oj/object.c +33 -43
  32. data/ext/oj/odd.c +8 -6
  33. data/ext/oj/odd.h +4 -4
  34. data/ext/oj/oj.c +243 -212
  35. data/ext/oj/oj.h +83 -81
  36. data/ext/oj/parse.c +94 -148
  37. data/ext/oj/parse.h +21 -24
  38. data/ext/oj/parser.c +80 -67
  39. data/ext/oj/parser.h +7 -8
  40. data/ext/oj/rails.c +70 -92
  41. data/ext/oj/reader.c +9 -14
  42. data/ext/oj/reader.h +4 -2
  43. data/ext/oj/resolve.c +3 -4
  44. data/ext/oj/rxclass.c +6 -5
  45. data/ext/oj/rxclass.h +1 -1
  46. data/ext/oj/saj.c +10 -9
  47. data/ext/oj/saj2.c +37 -49
  48. data/ext/oj/saj2.h +1 -1
  49. data/ext/oj/scp.c +3 -14
  50. data/ext/oj/sparse.c +22 -70
  51. data/ext/oj/stream_writer.c +45 -41
  52. data/ext/oj/strict.c +20 -52
  53. data/ext/oj/string_writer.c +64 -38
  54. data/ext/oj/trace.h +31 -4
  55. data/ext/oj/usual.c +125 -114
  56. data/ext/oj/usual.h +7 -6
  57. data/ext/oj/util.h +1 -1
  58. data/ext/oj/val_stack.c +13 -2
  59. data/ext/oj/val_stack.h +8 -7
  60. data/ext/oj/wab.c +25 -57
  61. data/lib/oj/active_support_helper.rb +1 -3
  62. data/lib/oj/bag.rb +7 -1
  63. data/lib/oj/easy_hash.rb +4 -5
  64. data/lib/oj/error.rb +0 -1
  65. data/lib/oj/json.rb +162 -150
  66. data/lib/oj/mimic.rb +7 -7
  67. data/lib/oj/schandler.rb +5 -4
  68. data/lib/oj/state.rb +8 -5
  69. data/lib/oj/version.rb +1 -2
  70. data/lib/oj.rb +2 -0
  71. data/pages/InstallOptions.md +20 -0
  72. data/pages/Options.md +4 -0
  73. data/test/_test_active.rb +8 -9
  74. data/test/_test_active_mimic.rb +7 -8
  75. data/test/_test_mimic_rails.rb +17 -20
  76. data/test/activerecord/result_test.rb +5 -6
  77. data/test/activesupport6/encoding_test.rb +63 -28
  78. data/test/activesupport7/abstract_unit.rb +4 -1
  79. data/test/activesupport7/encoding_test.rb +72 -22
  80. data/test/files.rb +15 -15
  81. data/test/foo.rb +18 -69
  82. data/test/helper.rb +5 -8
  83. data/test/isolated/shared.rb +3 -2
  84. data/test/json_gem/json_addition_test.rb +2 -2
  85. data/test/json_gem/json_common_interface_test.rb +8 -6
  86. data/test/json_gem/json_encoding_test.rb +0 -0
  87. data/test/json_gem/json_ext_parser_test.rb +1 -0
  88. data/test/json_gem/json_fixtures_test.rb +3 -2
  89. data/test/json_gem/json_generator_test.rb +50 -33
  90. data/test/json_gem/json_generic_object_test.rb +11 -11
  91. data/test/json_gem/json_parser_test.rb +46 -46
  92. data/test/json_gem/json_string_matching_test.rb +9 -9
  93. data/test/mem.rb +13 -12
  94. data/test/perf.rb +21 -26
  95. data/test/perf_compat.rb +31 -33
  96. data/test/perf_dump.rb +28 -28
  97. data/test/perf_fast.rb +80 -82
  98. data/test/perf_file.rb +27 -29
  99. data/test/perf_object.rb +65 -69
  100. data/test/perf_once.rb +12 -11
  101. data/test/perf_parser.rb +42 -48
  102. data/test/perf_saj.rb +46 -54
  103. data/test/perf_scp.rb +57 -69
  104. data/test/perf_simple.rb +41 -39
  105. data/test/perf_strict.rb +68 -70
  106. data/test/perf_wab.rb +67 -69
  107. data/test/prec.rb +5 -5
  108. data/test/sample/change.rb +0 -1
  109. data/test/sample/dir.rb +0 -1
  110. data/test/sample/doc.rb +0 -1
  111. data/test/sample/file.rb +0 -1
  112. data/test/sample/group.rb +0 -1
  113. data/test/sample/hasprops.rb +0 -1
  114. data/test/sample/layer.rb +0 -1
  115. data/test/sample/rect.rb +0 -1
  116. data/test/sample/shape.rb +0 -1
  117. data/test/sample/text.rb +0 -1
  118. data/test/sample.rb +16 -16
  119. data/test/sample_json.rb +8 -8
  120. data/test/test_compat.rb +81 -54
  121. data/test/test_custom.rb +63 -52
  122. data/test/test_debian.rb +7 -10
  123. data/test/test_fast.rb +86 -90
  124. data/test/test_file.rb +24 -29
  125. data/test/test_gc.rb +5 -5
  126. data/test/test_generate.rb +5 -5
  127. data/test/test_hash.rb +4 -4
  128. data/test/test_integer_range.rb +9 -9
  129. data/test/test_null.rb +20 -20
  130. data/test/test_object.rb +92 -87
  131. data/test/test_parser.rb +4 -4
  132. data/test/test_parser_debug.rb +5 -5
  133. data/test/test_parser_saj.rb +27 -25
  134. data/test/test_parser_usual.rb +44 -6
  135. data/test/test_rails.rb +2 -2
  136. data/test/test_saj.rb +10 -8
  137. data/test/test_scp.rb +35 -35
  138. data/test/test_strict.rb +38 -32
  139. data/test/test_various.rb +146 -97
  140. data/test/test_wab.rb +46 -44
  141. data/test/test_writer.rb +63 -47
  142. data/test/tests.rb +7 -7
  143. data/test/tests_mimic.rb +6 -6
  144. data/test/tests_mimic_addition.rb +6 -6
  145. metadata +46 -26
  146. data/test/activesupport4/decoding_test.rb +0 -108
  147. data/test/activesupport4/encoding_test.rb +0 -531
  148. data/test/activesupport4/test_helper.rb +0 -41
  149. data/test/activesupport5/abstract_unit.rb +0 -45
  150. data/test/activesupport5/decoding_test.rb +0 -133
  151. data/test/activesupport5/encoding_test.rb +0 -500
  152. data/test/activesupport5/encoding_test_cases.rb +0 -98
  153. data/test/activesupport5/test_helper.rb +0 -72
  154. data/test/activesupport5/time_zone_test_helpers.rb +0 -39
  155. data/test/bar.rb +0 -11
  156. data/test/baz.rb +0 -16
  157. data/test/bug.rb +0 -16
  158. data/test/zoo.rb +0 -13
data/ext/oj/fast.c CHANGED
@@ -11,14 +11,15 @@
11
11
  #include <stdlib.h>
12
12
  #include <string.h>
13
13
 
14
+ #include "dump.h"
14
15
  #include "encode.h"
16
+ #include "mem.h"
15
17
  #include "oj.h"
16
- #include "dump.h"
17
18
 
18
19
  // maximum to allocate on the stack, arbitrary limit
19
20
  #define SMALL_JSON 65536
20
21
  #define MAX_STACK 100
21
- //#define BATCH_SIZE (4096 / sizeof(struct _leaf) - 1)
22
+ // #define BATCH_SIZE (4096 / sizeof(struct _leaf) - 1)
22
23
  #define BATCH_SIZE 100
23
24
 
24
25
  // Support for compaction
@@ -32,25 +33,25 @@ typedef struct _batch {
32
33
  struct _batch *next;
33
34
  int next_avail;
34
35
  struct _leaf leaves[BATCH_SIZE];
35
- } * Batch;
36
+ } *Batch;
36
37
 
37
38
  typedef struct _doc {
38
39
  Leaf data;
39
- Leaf * where; // points to current location
40
+ Leaf *where; // points to current location
40
41
  Leaf where_path[MAX_STACK]; // points to head of path
41
- char * json;
42
+ char *json;
42
43
  unsigned long size; // number of leaves/branches in the doc
43
44
  VALUE self;
44
45
  Batch batches;
45
46
  struct _batch batch0;
46
- } * Doc;
47
+ } *Doc;
47
48
 
48
49
  typedef struct _parseInfo {
49
50
  char *str; // buffer being read from
50
51
  char *s; // current position in buffer
51
52
  Doc doc;
52
53
  void *stack_min;
53
- } * ParseInfo;
54
+ } *ParseInfo;
54
55
 
55
56
  static void leaf_init(Leaf leaf, int type);
56
57
  static Leaf leaf_new(Doc doc, int type);
@@ -74,7 +75,7 @@ static char *read_quoted_value(ParseInfo pi);
74
75
  static void skip_comment(ParseInfo pi);
75
76
 
76
77
  static VALUE protect_open_proc(VALUE x);
77
- static VALUE parse_json(VALUE clas, char *json, bool given, bool allocated);
78
+ static VALUE parse_json(VALUE clas, char *json, bool given);
78
79
  static void each_leaf(Doc doc, VALUE self);
79
80
  static int move_step(Doc doc, const char *path, int loc);
80
81
  static Leaf get_doc_leaf(Doc doc, const char *path);
@@ -113,10 +114,7 @@ inline static char *ulong_fill(char *s, size_t num) {
113
114
  char *b = buf + sizeof(buf) - 1;
114
115
 
115
116
  *b-- = '\0';
116
- for (; 0 < num; num /= 10, b--) {
117
- *b = (num % 10) + '0';
118
- }
119
- b++;
117
+ b = oj_longlong_to_string((long long)num, false, b);
120
118
  if ('\0' == *b) {
121
119
  b--;
122
120
  *b = '0';
@@ -160,7 +158,7 @@ inline static Leaf leaf_new(Doc doc, int type) {
160
158
  Leaf leaf;
161
159
 
162
160
  if (0 == doc->batches || BATCH_SIZE == doc->batches->next_avail) {
163
- Batch b = ALLOC(struct _batch);
161
+ Batch b = OJ_R_ALLOC(struct _batch);
164
162
 
165
163
  // Initializes all leaves with a NO_VAL value_type
166
164
  memset(b, 0, sizeof(struct _batch));
@@ -250,7 +248,7 @@ static void skip_comment(ParseInfo pi) {
250
248
  #endif
251
249
 
252
250
  static void leaf_fixnum_value(Leaf leaf) {
253
- char * s = leaf->str;
251
+ char *s = leaf->str;
254
252
  int64_t n = 0;
255
253
  int neg = 0;
256
254
  int big = 0;
@@ -356,7 +354,7 @@ static Leaf read_next(ParseInfo pi) {
356
354
 
357
355
  static Leaf read_obj(ParseInfo pi) {
358
356
  Leaf h = leaf_new(pi->doc, T_HASH);
359
- char * end;
357
+ char *end;
360
358
  const char *key = 0;
361
359
  Leaf val = 0;
362
360
 
@@ -648,10 +646,11 @@ static void doc_free(Doc doc) {
648
646
  while (0 != (b = doc->batches)) {
649
647
  doc->batches = doc->batches->next;
650
648
  if (&doc->batch0 != b) {
651
- xfree(b);
649
+ OJ_R_FREE(b);
652
650
  }
653
651
  }
654
- // xfree(f);
652
+ OJ_R_FREE(doc->json);
653
+ OJ_R_FREE(doc);
655
654
  }
656
655
  }
657
656
 
@@ -671,7 +670,6 @@ static void free_doc_cb(void *x) {
671
670
  Doc doc = (Doc)x;
672
671
 
673
672
  if (0 != doc) {
674
- xfree(doc->json);
675
673
  doc_free(doc);
676
674
  }
677
675
  }
@@ -749,20 +747,15 @@ static const rb_data_type_t oj_doc_type = {
749
747
  0,
750
748
  };
751
749
 
752
- static VALUE parse_json(VALUE clas, char *json, bool given, bool allocated) {
750
+ static VALUE parse_json(VALUE clas, char *json, bool given) {
753
751
  struct _parseInfo pi;
754
752
  volatile VALUE result = Qnil;
755
753
  Doc doc;
756
754
  int ex = 0;
757
755
  volatile VALUE self;
758
756
 
759
- // TBD are both needed? is stack allocation ever needed?
757
+ doc = OJ_R_ALLOC_N(struct _doc, 1);
760
758
 
761
- if (given) {
762
- doc = ALLOCA_N(struct _doc, 1);
763
- } else {
764
- doc = ALLOC(struct _doc);
765
- }
766
759
  // skip UTF-8 BOM if present
767
760
  if (0xEF == (uint8_t)*json && 0xBB == (uint8_t)json[1] && 0xBF == (uint8_t)json[2]) {
768
761
  pi.str = json + 3;
@@ -772,7 +765,7 @@ static VALUE parse_json(VALUE clas, char *json, bool given, bool allocated) {
772
765
  pi.s = pi.str;
773
766
  doc_init(doc);
774
767
  pi.doc = doc;
775
- #if IS_WINDOWS
768
+ #if IS_WINDOWS || !defined(HAVE_GETRLIMIT)
776
769
  // assume a 1M stack and give half to ruby
777
770
  pi.stack_min = (void *)((char *)&pi - (512L * 1024L));
778
771
  #else
@@ -787,18 +780,19 @@ static VALUE parse_json(VALUE clas, char *json, bool given, bool allocated) {
787
780
  }
788
781
  }
789
782
  #endif
790
- self = TypedData_Wrap_Struct(clas, &oj_doc_type, doc);
791
- doc->self = self;
792
- doc->json = json;
793
- DATA_PTR(doc->self) = doc;
794
- result = rb_protect(protect_open_proc, (VALUE)&pi, &ex);
783
+ doc->json = json;
784
+ self = TypedData_Wrap_Struct(clas, &oj_doc_type, doc);
785
+ doc->self = self;
786
+ result = rb_protect(protect_open_proc, (VALUE)&pi, &ex);
795
787
  if (given || 0 != ex) {
796
788
  DATA_PTR(doc->self) = NULL;
789
+ // TBD is this needed?
790
+ /*
797
791
  doc_free(pi.doc);
798
- if (allocated && 0 != ex) { // will jump so caller will not free
799
- xfree(json);
792
+ if (0 != ex) { // will jump so caller will not free
793
+ OJ_R_FREE(json);
800
794
  }
801
- rb_gc_enable();
795
+ */
802
796
  } else {
803
797
  result = doc->self;
804
798
  }
@@ -1088,31 +1082,23 @@ static void each_value(Doc doc, Leaf leaf) {
1088
1082
  * doc.close()
1089
1083
  */
1090
1084
  static VALUE doc_open(VALUE clas, VALUE str) {
1091
- char * json;
1085
+ char *json;
1092
1086
  size_t len;
1093
1087
  volatile VALUE obj;
1094
1088
  int given = rb_block_given_p();
1095
- int allocate;
1096
1089
 
1097
1090
  Check_Type(str, T_STRING);
1098
- len = (int)RSTRING_LEN(str) + 1;
1099
- allocate = (SMALL_JSON < len || !given);
1100
- if (allocate) {
1101
- json = ALLOC_N(char, len);
1102
- } else {
1103
- json = ALLOCA_N(char, len);
1104
- }
1105
- // It should not be necessaary to stop GC but if it is not stopped and a
1106
- // large string is parsed that string is corrupted or freed during
1107
- // parsing. I'm not sure what is going on exactly but disabling GC avoids
1108
- // the issue.
1109
- rb_gc_disable();
1091
+ len = (int)RSTRING_LEN(str) + 1;
1092
+ json = OJ_R_ALLOC_N(char, len);
1093
+
1110
1094
  memcpy(json, StringValuePtr(str), len);
1111
- obj = parse_json(clas, json, given, allocate);
1112
- rb_gc_enable();
1113
- if (given && allocate) {
1114
- xfree(json);
1095
+ obj = parse_json(clas, json, given);
1096
+ // TBD is this needed
1097
+ /*
1098
+ if (given) {
1099
+ OJ_R_FREE(json);
1115
1100
  }
1101
+ */
1116
1102
  return obj;
1117
1103
  }
1118
1104
 
@@ -1136,27 +1122,21 @@ static VALUE doc_open(VALUE clas, VALUE str) {
1136
1122
  * doc.close()
1137
1123
  */
1138
1124
  static VALUE doc_open_file(VALUE clas, VALUE filename) {
1139
- char * path;
1140
- char * json;
1141
- FILE * f;
1125
+ char *path;
1126
+ char *json;
1127
+ FILE *f;
1142
1128
  size_t len;
1143
1129
  volatile VALUE obj;
1144
1130
  int given = rb_block_given_p();
1145
- int allocate;
1146
1131
 
1147
- Check_Type(filename, T_STRING);
1148
1132
  path = StringValuePtr(filename);
1149
1133
  if (0 == (f = fopen(path, "r"))) {
1150
1134
  rb_raise(rb_eIOError, "%s", strerror(errno));
1151
1135
  }
1152
1136
  fseek(f, 0, SEEK_END);
1153
- len = ftell(f);
1154
- allocate = (SMALL_JSON < len || !given);
1155
- if (allocate) {
1156
- json = ALLOC_N(char, len + 1);
1157
- } else {
1158
- json = ALLOCA_N(char, len + 1);
1159
- }
1137
+ len = ftell(f);
1138
+ json = OJ_R_ALLOC_N(char, len + 1);
1139
+
1160
1140
  fseek(f, 0, SEEK_SET);
1161
1141
  if (len != fread(json, 1, len, f)) {
1162
1142
  fclose(f);
@@ -1167,12 +1147,13 @@ static VALUE doc_open_file(VALUE clas, VALUE filename) {
1167
1147
  }
1168
1148
  fclose(f);
1169
1149
  json[len] = '\0';
1170
- rb_gc_disable();
1171
- obj = parse_json(clas, json, given, allocate);
1172
- rb_gc_enable();
1173
- if (given && allocate) {
1174
- xfree(json);
1150
+ obj = parse_json(clas, json, given);
1151
+ // TBD is this needed
1152
+ /*
1153
+ if (given) {
1154
+ OJ_R_FREE(json);
1175
1155
  }
1156
+ */
1176
1157
  return obj;
1177
1158
  }
1178
1159
 
@@ -1212,11 +1193,11 @@ static VALUE doc_where(VALUE self) {
1212
1193
  if (0 == *doc->where_path || doc->where == doc->where_path) {
1213
1194
  return oj_slash_string;
1214
1195
  } else {
1215
- Leaf * lp;
1196
+ Leaf *lp;
1216
1197
  Leaf leaf;
1217
1198
  size_t size = 3; // leading / and terminating \0
1218
- char * path;
1219
- char * p;
1199
+ char *path;
1200
+ char *p;
1220
1201
 
1221
1202
  for (lp = doc->where_path; lp <= doc->where; lp++) {
1222
1203
  leaf = *lp;
@@ -1319,7 +1300,6 @@ static VALUE doc_type(int argc, VALUE *argv, VALUE self) {
1319
1300
  VALUE type = Qnil;
1320
1301
 
1321
1302
  if (1 <= argc) {
1322
- Check_Type(*argv, T_STRING);
1323
1303
  path = StringValuePtr(*argv);
1324
1304
  }
1325
1305
  if (0 != (leaf = get_doc_leaf(doc, path))) {
@@ -1328,11 +1308,7 @@ static VALUE doc_type(int argc, VALUE *argv, VALUE self) {
1328
1308
  case T_TRUE: type = rb_cTrueClass; break;
1329
1309
  case T_FALSE: type = rb_cFalseClass; break;
1330
1310
  case T_STRING: type = rb_cString; break;
1331
- #ifdef RUBY_INTEGER_UNIFICATION
1332
1311
  case T_FIXNUM: type = rb_cInteger; break;
1333
- #else
1334
- case T_FIXNUM: type = rb_cFixnum; break;
1335
- #endif
1336
1312
  case T_FLOAT: type = rb_cFloat; break;
1337
1313
  case T_ARRAY: type = rb_cArray; break;
1338
1314
  case T_HASH: type = rb_cHash; break;
@@ -1359,11 +1335,10 @@ static VALUE doc_fetch(int argc, VALUE *argv, VALUE self) {
1359
1335
  Doc doc;
1360
1336
  Leaf leaf;
1361
1337
  volatile VALUE val = Qnil;
1362
- const char * path = 0;
1338
+ const char *path = 0;
1363
1339
 
1364
1340
  doc = self_doc(self);
1365
1341
  if (1 <= argc) {
1366
- Check_Type(*argv, T_STRING);
1367
1342
  path = StringValuePtr(*argv);
1368
1343
  if (2 == argc) {
1369
1344
  val = argv[1];
@@ -1388,7 +1363,6 @@ static VALUE doc_exists(VALUE self, VALUE str) {
1388
1363
  Leaf leaf;
1389
1364
 
1390
1365
  doc = self_doc(self);
1391
- Check_Type(str, T_STRING);
1392
1366
  if (0 != (leaf = get_doc_leaf(doc, StringValuePtr(str)))) {
1393
1367
  if (NULL != leaf) {
1394
1368
  return Qtrue;
@@ -1425,7 +1399,6 @@ static VALUE doc_each_leaf(int argc, VALUE *argv, VALUE self) {
1425
1399
  memcpy(save_path, doc->where_path, sizeof(Leaf) * (wlen + 1));
1426
1400
  }
1427
1401
  if (1 <= argc) {
1428
- Check_Type(*argv, T_STRING);
1429
1402
  path = StringValuePtr(*argv);
1430
1403
  if ('/' == *path) {
1431
1404
  doc->where = doc->where_path;
@@ -1460,7 +1433,6 @@ static VALUE doc_move(VALUE self, VALUE str) {
1460
1433
  const char *path;
1461
1434
  int loc;
1462
1435
 
1463
- Check_Type(str, T_STRING);
1464
1436
  path = StringValuePtr(str);
1465
1437
  if ('/' == *path) {
1466
1438
  doc->where = doc->where_path;
@@ -1495,14 +1467,13 @@ static VALUE doc_each_child(int argc, VALUE *argv, VALUE self) {
1495
1467
  Doc doc = self_doc(self);
1496
1468
  const char *path = 0;
1497
1469
  size_t wlen;
1498
- Leaf * where_orig = doc->where;
1470
+ Leaf *where_orig = doc->where;
1499
1471
 
1500
1472
  wlen = doc->where - doc->where_path;
1501
1473
  if (0 < wlen) {
1502
1474
  memcpy(save_path, doc->where_path, sizeof(Leaf) * (wlen + 1));
1503
1475
  }
1504
1476
  if (1 <= argc) {
1505
- Check_Type(*argv, T_STRING);
1506
1477
  path = StringValuePtr(*argv);
1507
1478
  if ('/' == *path) {
1508
1479
  doc->where = doc->where_path;
@@ -1569,7 +1540,6 @@ static VALUE doc_each_value(int argc, VALUE *argv, VALUE self) {
1569
1540
  Leaf leaf;
1570
1541
 
1571
1542
  if (1 <= argc) {
1572
- Check_Type(*argv, T_STRING);
1573
1543
  path = StringValuePtr(*argv);
1574
1544
  }
1575
1545
  if (0 != (leaf = get_doc_leaf(doc, path))) {
@@ -1601,11 +1571,9 @@ static VALUE doc_dump(int argc, VALUE *argv, VALUE self) {
1601
1571
 
1602
1572
  if (1 <= argc) {
1603
1573
  if (Qnil != *argv) {
1604
- Check_Type(*argv, T_STRING);
1605
1574
  path = StringValuePtr(*argv);
1606
1575
  }
1607
1576
  if (2 <= argc) {
1608
- Check_Type(argv[1], T_STRING);
1609
1577
  filename = StringValuePtr(argv[1]);
1610
1578
  }
1611
1579
  }
@@ -1617,7 +1585,7 @@ static VALUE doc_dump(int argc, VALUE *argv, VALUE self) {
1617
1585
 
1618
1586
  oj_out_init(&out);
1619
1587
 
1620
- out.omit_nil = oj_default_options.dump_opts.omit_nil;
1588
+ out.omit_nil = oj_default_options.dump_opts.omit_nil;
1621
1589
  oj_dump_leaf_to_json(leaf, &oj_default_options, &out);
1622
1590
  rjson = rb_str_new2(out.buf);
1623
1591
 
@@ -1640,7 +1608,9 @@ static VALUE doc_dump(int argc, VALUE *argv, VALUE self) {
1640
1608
  * Oj::Doc.open('[1,2,3]') { |doc| doc.size() } #=> 4
1641
1609
  */
1642
1610
  static VALUE doc_size(VALUE self) {
1643
- return ULONG2NUM(((Doc)DATA_PTR(self))->size);
1611
+ Doc d;
1612
+ TypedData_Get_Struct(self, struct _doc, &oj_doc_type, d);
1613
+ return ULONG2NUM(d->size);
1644
1614
  }
1645
1615
 
1646
1616
  /* @overload close() => nil
@@ -1656,11 +1626,9 @@ static VALUE doc_close(VALUE self) {
1656
1626
  Doc doc = self_doc(self);
1657
1627
 
1658
1628
  rb_gc_unregister_address(&doc->self);
1659
- DATA_PTR(doc->self) = 0;
1629
+ DATA_PTR(doc->self) = NULL;
1660
1630
  if (0 != doc) {
1661
- xfree(doc->json);
1662
1631
  doc_free(doc);
1663
- xfree(doc);
1664
1632
  }
1665
1633
  return Qnil;
1666
1634
  }
data/ext/oj/intern.c CHANGED
@@ -8,7 +8,9 @@
8
8
  #if HAVE_PTHREAD_MUTEX_INIT
9
9
  #include <pthread.h>
10
10
  #endif
11
+
11
12
  #include "cache.h"
13
+ #include "mem.h"
12
14
  #include "parse.h"
13
15
 
14
16
  // Only used for the class cache so 256 should be sufficient.
@@ -20,10 +22,10 @@
20
22
 
21
23
  typedef struct _keyVal {
22
24
  struct _keyVal *next;
23
- const char * key;
25
+ const char *key;
24
26
  size_t len;
25
27
  VALUE val;
26
- } * KeyVal;
28
+ } *KeyVal;
27
29
 
28
30
  typedef struct _hash {
29
31
  struct _keyVal slots[HASH_SLOT_CNT];
@@ -32,16 +34,16 @@ typedef struct _hash {
32
34
  #else
33
35
  VALUE mutex;
34
36
  #endif
35
- } * Hash;
37
+ } *Hash;
36
38
 
37
39
  struct _hash class_hash;
38
40
  struct _hash attr_hash;
39
41
 
40
- static VALUE str_cache_obj;
42
+ static VALUE str_cache_obj;
41
43
 
42
- static VALUE sym_cache_obj;
44
+ static VALUE sym_cache_obj;
43
45
 
44
- static VALUE attr_cache_obj;
46
+ static VALUE attr_cache_obj;
45
47
 
46
48
  static VALUE form_str(const char *str, size_t len) {
47
49
  return rb_str_freeze(rb_utf8_str_new(str, len));
@@ -55,51 +57,59 @@ static VALUE form_attr(const char *str, size_t len) {
55
57
  char buf[256];
56
58
 
57
59
  if (sizeof(buf) - 2 <= len) {
58
- char *b = ALLOC_N(char, len + 2);
60
+ char *b = OJ_R_ALLOC_N(char, len + 2);
59
61
  ID id;
60
62
 
61
63
  if ('~' == *str) {
62
- memcpy(b, str + 1, len - 1);
63
- b[len - 1] = '\0';
64
- len -= 2;
65
- } else {
66
- *b = '@';
67
- memcpy(b + 1, str, len);
68
- b[len + 1] = '\0';
69
- }
64
+ memcpy(b, str + 1, len - 1);
65
+ b[len - 1] = '\0';
66
+ len -= 2;
67
+ } else {
68
+ *b = '@';
69
+ memcpy(b + 1, str, len);
70
+ b[len + 1] = '\0';
71
+ }
70
72
  id = rb_intern3(buf, len + 1, oj_utf8_encoding);
71
- xfree(b);
73
+ OJ_R_FREE(b);
72
74
  return id;
73
75
  }
74
76
  if ('~' == *str) {
75
- memcpy(buf, str + 1, len - 1);
76
- buf[len - 1] = '\0';
77
- len -= 2;
77
+ memcpy(buf, str + 1, len - 1);
78
+ buf[len - 1] = '\0';
79
+ len -= 2;
78
80
  } else {
79
- *buf = '@';
80
- memcpy(buf + 1, str, len);
81
- buf[len + 1] = '\0';
81
+ *buf = '@';
82
+ memcpy(buf + 1, str, len);
83
+ buf[len + 1] = '\0';
82
84
  }
83
85
  return (VALUE)rb_intern3(buf, len + 1, oj_utf8_encoding);
84
86
  }
85
87
 
88
+ static const rb_data_type_t oj_cache_type = {
89
+ "Oj/cache",
90
+ {
91
+ cache_mark,
92
+ cache_free,
93
+ NULL,
94
+ },
95
+ 0,
96
+ 0,
97
+ };
98
+
86
99
  void oj_hash_init(void) {
87
100
  VALUE cache_class = rb_define_class_under(Oj, "Cache", rb_cObject);
88
101
  rb_undef_alloc_func(cache_class);
89
102
 
90
- rb_gc_register_address(&cache_class);
91
- rb_undef_alloc_func(cache_class);
92
-
93
- struct _cache *str_cache = cache_create(0, form_str, true, true);
94
- str_cache_obj = Data_Wrap_Struct(cache_class, cache_mark, cache_free, str_cache);
103
+ struct _cache *str_cache = cache_create(0, form_str, true, true);
104
+ str_cache_obj = TypedData_Wrap_Struct(cache_class, &oj_cache_type, str_cache);
95
105
  rb_gc_register_address(&str_cache_obj);
96
106
 
97
- struct _cache *sym_cache = cache_create(0, form_sym, true, true);
98
- sym_cache_obj = Data_Wrap_Struct(cache_class, cache_mark, cache_free, sym_cache);
107
+ struct _cache *sym_cache = cache_create(0, form_sym, true, true);
108
+ sym_cache_obj = TypedData_Wrap_Struct(cache_class, &oj_cache_type, sym_cache);
99
109
  rb_gc_register_address(&sym_cache_obj);
100
110
 
101
111
  struct _cache *attr_cache = cache_create(0, form_attr, false, true);
102
- attr_cache_obj = Data_Wrap_Struct(cache_class, cache_mark, cache_free, attr_cache);
112
+ attr_cache_obj = TypedData_Wrap_Struct(cache_class, &oj_cache_type, attr_cache);
103
113
  rb_gc_register_address(&attr_cache_obj);
104
114
 
105
115
  memset(class_hash.slots, 0, sizeof(class_hash.slots));
@@ -119,18 +129,23 @@ oj_str_intern(const char *key, size_t len) {
119
129
  #if HAVE_RB_ENC_INTERNED_STR && 0
120
130
  return rb_enc_interned_str(key, len, rb_utf8_encoding());
121
131
  #else
122
- return cache_intern(DATA_PTR(str_cache_obj), key, len);
132
+ Cache c;
133
+ TypedData_Get_Struct(str_cache_obj, struct _cache, &oj_cache_type, c);
134
+ return cache_intern(c, key, len);
123
135
  #endif
124
136
  }
125
137
 
126
138
  VALUE
127
139
  oj_sym_intern(const char *key, size_t len) {
128
- return cache_intern(DATA_PTR(sym_cache_obj), key, len);
140
+ Cache c;
141
+ TypedData_Get_Struct(sym_cache_obj, struct _cache, &oj_cache_type, c);
142
+ return cache_intern(c, key, len);
129
143
  }
130
144
 
131
- ID
132
- oj_attr_intern(const char *key, size_t len) {
133
- return cache_intern(DATA_PTR(attr_cache_obj), key, len);
145
+ ID oj_attr_intern(const char *key, size_t len) {
146
+ Cache c;
147
+ TypedData_Get_Struct(attr_cache_obj, struct _cache, &oj_cache_type, c);
148
+ return cache_intern(c, key, len);
134
149
  }
135
150
 
136
151
  static uint64_t hash_calc(const uint8_t *key, size_t len) {
@@ -184,10 +199,10 @@ static VALUE resolve_classname(VALUE mod, const char *classname, int auto_define
184
199
  static VALUE resolve_classpath(ParseInfo pi, const char *name, size_t len, int auto_define, VALUE error_class) {
185
200
  char class_name[1024];
186
201
  VALUE clas;
187
- char * end = class_name + sizeof(class_name) - 1;
188
- char * s;
189
- const char *n = name;
190
- size_t nlen = len;
202
+ char *end = class_name + sizeof(class_name) - 1;
203
+ char *s;
204
+ const char *n = name;
205
+ size_t nlen = len;
191
206
 
192
207
  clas = rb_cObject;
193
208
  for (s = class_name; 0 < len; n++, len--) {
@@ -210,11 +225,11 @@ static VALUE resolve_classpath(ParseInfo pi, const char *name, size_t len, int a
210
225
  }
211
226
  *s = '\0';
212
227
  if (Qundef == (clas = resolve_classname(clas, class_name, auto_define))) {
213
- if (sizeof(class_name) <= nlen) {
214
- nlen = sizeof(class_name) - 1;
215
- }
216
- strncpy(class_name, name, nlen);
217
- class_name[nlen] = '\0';
228
+ if (sizeof(class_name) <= nlen) {
229
+ nlen = sizeof(class_name) - 1;
230
+ }
231
+ strncpy(class_name, name, nlen);
232
+ class_name[nlen] = '\0';
218
233
  oj_set_error_at(pi, error_class, __FILE__, __LINE__, "class '%s' is not defined", class_name);
219
234
  if (Qnil != error_class) {
220
235
  pi->err_class = error_class;
@@ -246,7 +261,7 @@ VALUE oj_class_intern(const char *key, size_t len, bool safe, ParseInfo pi, int
246
261
  }
247
262
  bucket = b;
248
263
  }
249
- b = ALLOC(struct _keyVal);
264
+ b = OJ_R_ALLOC(struct _keyVal);
250
265
  b->next = NULL;
251
266
  bucket->next = b;
252
267
  bucket = b;
@@ -267,7 +282,7 @@ VALUE oj_class_intern(const char *key, size_t len, bool safe, ParseInfo pi, int
267
282
  }
268
283
  bucket = b;
269
284
  }
270
- b = ALLOC(struct _keyVal);
285
+ b = OJ_R_ALLOC(struct _keyVal);
271
286
  b->next = NULL;
272
287
  bucket->next = b;
273
288
  bucket = b;
@@ -281,7 +296,7 @@ VALUE oj_class_intern(const char *key, size_t len, bool safe, ParseInfo pi, int
281
296
  }
282
297
 
283
298
  char *oj_strndup(const char *s, size_t len) {
284
- char *d = ALLOC_N(char, len + 1);
299
+ char *d = OJ_R_ALLOC_N(char, len + 1);
285
300
 
286
301
  memcpy(d, s, len);
287
302
  d[len] = '\0';
data/ext/oj/intern.h CHANGED
@@ -4,8 +4,8 @@
4
4
  #ifndef OJ_INTERN_H
5
5
  #define OJ_INTERN_H
6
6
 
7
- #include <stdbool.h>
8
7
  #include <ruby.h>
8
+ #include <stdbool.h>
9
9
 
10
10
  struct _parseInfo;
11
11
 
@@ -14,12 +14,8 @@ extern void oj_hash_init(void);
14
14
  extern VALUE oj_str_intern(const char *key, size_t len);
15
15
  extern VALUE oj_sym_intern(const char *key, size_t len);
16
16
  extern ID oj_attr_intern(const char *key, size_t len);
17
- extern VALUE oj_class_intern(const char * key,
18
- size_t len,
19
- bool safe,
20
- struct _parseInfo *pi,
21
- int auto_define,
22
- VALUE error_class);
17
+ extern VALUE
18
+ oj_class_intern(const char *key, size_t len, bool safe, struct _parseInfo *pi, int auto_define, VALUE error_class);
23
19
 
24
20
  extern char *oj_strndup(const char *s, size_t len);
25
21