oj 3.13.23 → 3.16.9

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 (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