oj 3.13.23 → 3.16.10

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 (178) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +86 -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 +63 -98
  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 +54 -38
  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 +245 -216
  35. data/ext/oj/oj.h +83 -81
  36. data/ext/oj/parse.c +109 -153
  37. data/ext/oj/parse.h +21 -24
  38. data/ext/oj/parser.c +80 -67
  39. data/ext/oj/parser.h +9 -8
  40. data/ext/oj/rails.c +71 -94
  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 +13 -15
  47. data/ext/oj/saj2.c +37 -49
  48. data/ext/oj/saj2.h +1 -1
  49. data/ext/oj/scp.c +6 -20
  50. data/ext/oj/sparse.c +22 -70
  51. data/ext/oj/stream_writer.c +46 -48
  52. data/ext/oj/strict.c +22 -56
  53. data/ext/oj/string_writer.c +64 -40
  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. metadata +46 -121
  74. data/test/_test_active.rb +0 -76
  75. data/test/_test_active_mimic.rb +0 -96
  76. data/test/_test_mimic_rails.rb +0 -126
  77. data/test/activerecord/result_test.rb +0 -32
  78. data/test/activesupport4/decoding_test.rb +0 -108
  79. data/test/activesupport4/encoding_test.rb +0 -531
  80. data/test/activesupport4/test_helper.rb +0 -41
  81. data/test/activesupport5/abstract_unit.rb +0 -45
  82. data/test/activesupport5/decoding_test.rb +0 -133
  83. data/test/activesupport5/encoding_test.rb +0 -500
  84. data/test/activesupport5/encoding_test_cases.rb +0 -98
  85. data/test/activesupport5/test_helper.rb +0 -72
  86. data/test/activesupport5/time_zone_test_helpers.rb +0 -39
  87. data/test/activesupport6/abstract_unit.rb +0 -44
  88. data/test/activesupport6/decoding_test.rb +0 -133
  89. data/test/activesupport6/encoding_test.rb +0 -507
  90. data/test/activesupport6/encoding_test_cases.rb +0 -98
  91. data/test/activesupport6/test_common.rb +0 -17
  92. data/test/activesupport6/test_helper.rb +0 -163
  93. data/test/activesupport6/time_zone_test_helpers.rb +0 -39
  94. data/test/activesupport7/abstract_unit.rb +0 -49
  95. data/test/activesupport7/decoding_test.rb +0 -125
  96. data/test/activesupport7/encoding_test.rb +0 -486
  97. data/test/activesupport7/encoding_test_cases.rb +0 -104
  98. data/test/activesupport7/time_zone_test_helpers.rb +0 -47
  99. data/test/bar.rb +0 -11
  100. data/test/baz.rb +0 -16
  101. data/test/bug.rb +0 -16
  102. data/test/files.rb +0 -29
  103. data/test/foo.rb +0 -77
  104. data/test/helper.rb +0 -42
  105. data/test/isolated/shared.rb +0 -308
  106. data/test/isolated/test_mimic_after.rb +0 -13
  107. data/test/isolated/test_mimic_alone.rb +0 -12
  108. data/test/isolated/test_mimic_as_json.rb +0 -45
  109. data/test/isolated/test_mimic_before.rb +0 -13
  110. data/test/isolated/test_mimic_define.rb +0 -28
  111. data/test/isolated/test_mimic_rails_after.rb +0 -22
  112. data/test/isolated/test_mimic_rails_before.rb +0 -21
  113. data/test/isolated/test_mimic_redefine.rb +0 -15
  114. data/test/json_gem/json_addition_test.rb +0 -216
  115. data/test/json_gem/json_common_interface_test.rb +0 -153
  116. data/test/json_gem/json_encoding_test.rb +0 -107
  117. data/test/json_gem/json_ext_parser_test.rb +0 -20
  118. data/test/json_gem/json_fixtures_test.rb +0 -35
  119. data/test/json_gem/json_generator_test.rb +0 -396
  120. data/test/json_gem/json_generic_object_test.rb +0 -90
  121. data/test/json_gem/json_parser_test.rb +0 -477
  122. data/test/json_gem/json_string_matching_test.rb +0 -42
  123. data/test/json_gem/test_helper.rb +0 -30
  124. data/test/mem.rb +0 -33
  125. data/test/perf.rb +0 -107
  126. data/test/perf_compat.rb +0 -130
  127. data/test/perf_dump.rb +0 -50
  128. data/test/perf_fast.rb +0 -164
  129. data/test/perf_file.rb +0 -64
  130. data/test/perf_object.rb +0 -138
  131. data/test/perf_once.rb +0 -58
  132. data/test/perf_parser.rb +0 -189
  133. data/test/perf_saj.rb +0 -109
  134. data/test/perf_scp.rb +0 -152
  135. data/test/perf_simple.rb +0 -287
  136. data/test/perf_strict.rb +0 -139
  137. data/test/perf_wab.rb +0 -131
  138. data/test/prec.rb +0 -23
  139. data/test/sample/change.rb +0 -14
  140. data/test/sample/dir.rb +0 -19
  141. data/test/sample/doc.rb +0 -36
  142. data/test/sample/file.rb +0 -48
  143. data/test/sample/group.rb +0 -16
  144. data/test/sample/hasprops.rb +0 -16
  145. data/test/sample/layer.rb +0 -12
  146. data/test/sample/line.rb +0 -20
  147. data/test/sample/oval.rb +0 -10
  148. data/test/sample/rect.rb +0 -10
  149. data/test/sample/shape.rb +0 -35
  150. data/test/sample/text.rb +0 -20
  151. data/test/sample.rb +0 -54
  152. data/test/sample_json.rb +0 -37
  153. data/test/test_compat.rb +0 -540
  154. data/test/test_custom.rb +0 -544
  155. data/test/test_debian.rb +0 -53
  156. data/test/test_fast.rb +0 -530
  157. data/test/test_file.rb +0 -255
  158. data/test/test_gc.rb +0 -60
  159. data/test/test_generate.rb +0 -21
  160. data/test/test_hash.rb +0 -39
  161. data/test/test_integer_range.rb +0 -72
  162. data/test/test_null.rb +0 -376
  163. data/test/test_object.rb +0 -1025
  164. data/test/test_parser.rb +0 -11
  165. data/test/test_parser_debug.rb +0 -27
  166. data/test/test_parser_saj.rb +0 -335
  167. data/test/test_parser_usual.rb +0 -217
  168. data/test/test_rails.rb +0 -35
  169. data/test/test_saj.rb +0 -186
  170. data/test/test_scp.rb +0 -431
  171. data/test/test_strict.rb +0 -435
  172. data/test/test_various.rb +0 -752
  173. data/test/test_wab.rb +0 -309
  174. data/test/test_writer.rb +0 -380
  175. data/test/tests.rb +0 -33
  176. data/test/tests_mimic.rb +0 -23
  177. data/test/tests_mimic_addition.rb +0 -16
  178. 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));
@@ -195,8 +193,7 @@ static VALUE leaf_value(Doc doc, Leaf leaf) {
195
193
  case T_FIXNUM: leaf_fixnum_value(leaf); break;
196
194
  case T_FLOAT: leaf_float_value(leaf); break;
197
195
  case T_STRING:
198
- leaf->value = rb_str_new2(leaf->str);
199
- leaf->value = oj_encode(leaf->value);
196
+ leaf->value = rb_utf8_str_new_cstr(leaf->str);
200
197
  leaf->value_type = RUBY_VAL;
201
198
  break;
202
199
  case T_ARRAY: return leaf_array_value(doc, leaf); break;
@@ -250,7 +247,7 @@ static void skip_comment(ParseInfo pi) {
250
247
  #endif
251
248
 
252
249
  static void leaf_fixnum_value(Leaf leaf) {
253
- char * s = leaf->str;
250
+ char *s = leaf->str;
254
251
  int64_t n = 0;
255
252
  int neg = 0;
256
253
  int big = 0;
@@ -311,8 +308,7 @@ static VALUE leaf_hash_value(Doc doc, Leaf leaf) {
311
308
  volatile VALUE key;
312
309
 
313
310
  do {
314
- key = rb_str_new2(e->key);
315
- key = oj_encode(key);
311
+ key = rb_utf8_str_new_cstr(e->key);
316
312
  rb_hash_aset(h, key, leaf_value(doc, e));
317
313
  e = e->next;
318
314
  } while (e != first);
@@ -356,7 +352,7 @@ static Leaf read_next(ParseInfo pi) {
356
352
 
357
353
  static Leaf read_obj(ParseInfo pi) {
358
354
  Leaf h = leaf_new(pi->doc, T_HASH);
359
- char * end;
355
+ char *end;
360
356
  const char *key = 0;
361
357
  Leaf val = 0;
362
358
 
@@ -648,10 +644,11 @@ static void doc_free(Doc doc) {
648
644
  while (0 != (b = doc->batches)) {
649
645
  doc->batches = doc->batches->next;
650
646
  if (&doc->batch0 != b) {
651
- xfree(b);
647
+ OJ_R_FREE(b);
652
648
  }
653
649
  }
654
- // xfree(f);
650
+ OJ_R_FREE(doc->json);
651
+ OJ_R_FREE(doc);
655
652
  }
656
653
  }
657
654
 
@@ -671,7 +668,6 @@ static void free_doc_cb(void *x) {
671
668
  Doc doc = (Doc)x;
672
669
 
673
670
  if (0 != doc) {
674
- xfree(doc->json);
675
671
  doc_free(doc);
676
672
  }
677
673
  }
@@ -749,20 +745,15 @@ static const rb_data_type_t oj_doc_type = {
749
745
  0,
750
746
  };
751
747
 
752
- static VALUE parse_json(VALUE clas, char *json, bool given, bool allocated) {
748
+ static VALUE parse_json(VALUE clas, char *json, bool given) {
753
749
  struct _parseInfo pi;
754
750
  volatile VALUE result = Qnil;
755
751
  Doc doc;
756
752
  int ex = 0;
757
753
  volatile VALUE self;
758
754
 
759
- // TBD are both needed? is stack allocation ever needed?
755
+ doc = OJ_R_ALLOC_N(struct _doc, 1);
760
756
 
761
- if (given) {
762
- doc = ALLOCA_N(struct _doc, 1);
763
- } else {
764
- doc = ALLOC(struct _doc);
765
- }
766
757
  // skip UTF-8 BOM if present
767
758
  if (0xEF == (uint8_t)*json && 0xBB == (uint8_t)json[1] && 0xBF == (uint8_t)json[2]) {
768
759
  pi.str = json + 3;
@@ -772,7 +763,7 @@ static VALUE parse_json(VALUE clas, char *json, bool given, bool allocated) {
772
763
  pi.s = pi.str;
773
764
  doc_init(doc);
774
765
  pi.doc = doc;
775
- #if IS_WINDOWS
766
+ #if IS_WINDOWS || !defined(HAVE_GETRLIMIT)
776
767
  // assume a 1M stack and give half to ruby
777
768
  pi.stack_min = (void *)((char *)&pi - (512L * 1024L));
778
769
  #else
@@ -787,18 +778,19 @@ static VALUE parse_json(VALUE clas, char *json, bool given, bool allocated) {
787
778
  }
788
779
  }
789
780
  #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);
781
+ doc->json = json;
782
+ self = TypedData_Wrap_Struct(clas, &oj_doc_type, doc);
783
+ doc->self = self;
784
+ result = rb_protect(protect_open_proc, (VALUE)&pi, &ex);
795
785
  if (given || 0 != ex) {
796
786
  DATA_PTR(doc->self) = NULL;
787
+ // TBD is this needed?
788
+ /*
797
789
  doc_free(pi.doc);
798
- if (allocated && 0 != ex) { // will jump so caller will not free
799
- xfree(json);
790
+ if (0 != ex) { // will jump so caller will not free
791
+ OJ_R_FREE(json);
800
792
  }
801
- rb_gc_enable();
793
+ */
802
794
  } else {
803
795
  result = doc->self;
804
796
  }
@@ -1088,31 +1080,23 @@ static void each_value(Doc doc, Leaf leaf) {
1088
1080
  * doc.close()
1089
1081
  */
1090
1082
  static VALUE doc_open(VALUE clas, VALUE str) {
1091
- char * json;
1083
+ char *json;
1092
1084
  size_t len;
1093
1085
  volatile VALUE obj;
1094
1086
  int given = rb_block_given_p();
1095
- int allocate;
1096
1087
 
1097
1088
  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();
1089
+ len = (int)RSTRING_LEN(str) + 1;
1090
+ json = OJ_R_ALLOC_N(char, len);
1091
+
1110
1092
  memcpy(json, StringValuePtr(str), len);
1111
- obj = parse_json(clas, json, given, allocate);
1112
- rb_gc_enable();
1113
- if (given && allocate) {
1114
- xfree(json);
1093
+ obj = parse_json(clas, json, given);
1094
+ // TBD is this needed
1095
+ /*
1096
+ if (given) {
1097
+ OJ_R_FREE(json);
1115
1098
  }
1099
+ */
1116
1100
  return obj;
1117
1101
  }
1118
1102
 
@@ -1136,27 +1120,21 @@ static VALUE doc_open(VALUE clas, VALUE str) {
1136
1120
  * doc.close()
1137
1121
  */
1138
1122
  static VALUE doc_open_file(VALUE clas, VALUE filename) {
1139
- char * path;
1140
- char * json;
1141
- FILE * f;
1123
+ char *path;
1124
+ char *json;
1125
+ FILE *f;
1142
1126
  size_t len;
1143
1127
  volatile VALUE obj;
1144
1128
  int given = rb_block_given_p();
1145
- int allocate;
1146
1129
 
1147
- Check_Type(filename, T_STRING);
1148
1130
  path = StringValuePtr(filename);
1149
1131
  if (0 == (f = fopen(path, "r"))) {
1150
1132
  rb_raise(rb_eIOError, "%s", strerror(errno));
1151
1133
  }
1152
1134
  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
- }
1135
+ len = ftell(f);
1136
+ json = OJ_R_ALLOC_N(char, len + 1);
1137
+
1160
1138
  fseek(f, 0, SEEK_SET);
1161
1139
  if (len != fread(json, 1, len, f)) {
1162
1140
  fclose(f);
@@ -1167,12 +1145,13 @@ static VALUE doc_open_file(VALUE clas, VALUE filename) {
1167
1145
  }
1168
1146
  fclose(f);
1169
1147
  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);
1148
+ obj = parse_json(clas, json, given);
1149
+ // TBD is this needed
1150
+ /*
1151
+ if (given) {
1152
+ OJ_R_FREE(json);
1175
1153
  }
1154
+ */
1176
1155
  return obj;
1177
1156
  }
1178
1157
 
@@ -1212,11 +1191,11 @@ static VALUE doc_where(VALUE self) {
1212
1191
  if (0 == *doc->where_path || doc->where == doc->where_path) {
1213
1192
  return oj_slash_string;
1214
1193
  } else {
1215
- Leaf * lp;
1194
+ Leaf *lp;
1216
1195
  Leaf leaf;
1217
1196
  size_t size = 3; // leading / and terminating \0
1218
- char * path;
1219
- char * p;
1197
+ char *path;
1198
+ char *p;
1220
1199
 
1221
1200
  for (lp = doc->where_path; lp <= doc->where; lp++) {
1222
1201
  leaf = *lp;
@@ -1276,8 +1255,7 @@ static VALUE doc_local_key(VALUE self) {
1276
1255
  volatile VALUE key = Qnil;
1277
1256
 
1278
1257
  if (T_HASH == leaf->parent_type) {
1279
- key = rb_str_new2(leaf->key);
1280
- key = oj_encode(key);
1258
+ key = rb_utf8_str_new_cstr(leaf->key);
1281
1259
  } else if (T_ARRAY == leaf->parent_type) {
1282
1260
  key = LONG2NUM(leaf->index);
1283
1261
  }
@@ -1319,7 +1297,6 @@ static VALUE doc_type(int argc, VALUE *argv, VALUE self) {
1319
1297
  VALUE type = Qnil;
1320
1298
 
1321
1299
  if (1 <= argc) {
1322
- Check_Type(*argv, T_STRING);
1323
1300
  path = StringValuePtr(*argv);
1324
1301
  }
1325
1302
  if (0 != (leaf = get_doc_leaf(doc, path))) {
@@ -1328,11 +1305,7 @@ static VALUE doc_type(int argc, VALUE *argv, VALUE self) {
1328
1305
  case T_TRUE: type = rb_cTrueClass; break;
1329
1306
  case T_FALSE: type = rb_cFalseClass; break;
1330
1307
  case T_STRING: type = rb_cString; break;
1331
- #ifdef RUBY_INTEGER_UNIFICATION
1332
1308
  case T_FIXNUM: type = rb_cInteger; break;
1333
- #else
1334
- case T_FIXNUM: type = rb_cFixnum; break;
1335
- #endif
1336
1309
  case T_FLOAT: type = rb_cFloat; break;
1337
1310
  case T_ARRAY: type = rb_cArray; break;
1338
1311
  case T_HASH: type = rb_cHash; break;
@@ -1359,11 +1332,10 @@ static VALUE doc_fetch(int argc, VALUE *argv, VALUE self) {
1359
1332
  Doc doc;
1360
1333
  Leaf leaf;
1361
1334
  volatile VALUE val = Qnil;
1362
- const char * path = 0;
1335
+ const char *path = 0;
1363
1336
 
1364
1337
  doc = self_doc(self);
1365
1338
  if (1 <= argc) {
1366
- Check_Type(*argv, T_STRING);
1367
1339
  path = StringValuePtr(*argv);
1368
1340
  if (2 == argc) {
1369
1341
  val = argv[1];
@@ -1388,7 +1360,6 @@ static VALUE doc_exists(VALUE self, VALUE str) {
1388
1360
  Leaf leaf;
1389
1361
 
1390
1362
  doc = self_doc(self);
1391
- Check_Type(str, T_STRING);
1392
1363
  if (0 != (leaf = get_doc_leaf(doc, StringValuePtr(str)))) {
1393
1364
  if (NULL != leaf) {
1394
1365
  return Qtrue;
@@ -1425,7 +1396,6 @@ static VALUE doc_each_leaf(int argc, VALUE *argv, VALUE self) {
1425
1396
  memcpy(save_path, doc->where_path, sizeof(Leaf) * (wlen + 1));
1426
1397
  }
1427
1398
  if (1 <= argc) {
1428
- Check_Type(*argv, T_STRING);
1429
1399
  path = StringValuePtr(*argv);
1430
1400
  if ('/' == *path) {
1431
1401
  doc->where = doc->where_path;
@@ -1460,7 +1430,6 @@ static VALUE doc_move(VALUE self, VALUE str) {
1460
1430
  const char *path;
1461
1431
  int loc;
1462
1432
 
1463
- Check_Type(str, T_STRING);
1464
1433
  path = StringValuePtr(str);
1465
1434
  if ('/' == *path) {
1466
1435
  doc->where = doc->where_path;
@@ -1495,14 +1464,13 @@ static VALUE doc_each_child(int argc, VALUE *argv, VALUE self) {
1495
1464
  Doc doc = self_doc(self);
1496
1465
  const char *path = 0;
1497
1466
  size_t wlen;
1498
- Leaf * where_orig = doc->where;
1467
+ Leaf *where_orig = doc->where;
1499
1468
 
1500
1469
  wlen = doc->where - doc->where_path;
1501
1470
  if (0 < wlen) {
1502
1471
  memcpy(save_path, doc->where_path, sizeof(Leaf) * (wlen + 1));
1503
1472
  }
1504
1473
  if (1 <= argc) {
1505
- Check_Type(*argv, T_STRING);
1506
1474
  path = StringValuePtr(*argv);
1507
1475
  if ('/' == *path) {
1508
1476
  doc->where = doc->where_path;
@@ -1569,7 +1537,6 @@ static VALUE doc_each_value(int argc, VALUE *argv, VALUE self) {
1569
1537
  Leaf leaf;
1570
1538
 
1571
1539
  if (1 <= argc) {
1572
- Check_Type(*argv, T_STRING);
1573
1540
  path = StringValuePtr(*argv);
1574
1541
  }
1575
1542
  if (0 != (leaf = get_doc_leaf(doc, path))) {
@@ -1601,11 +1568,9 @@ static VALUE doc_dump(int argc, VALUE *argv, VALUE self) {
1601
1568
 
1602
1569
  if (1 <= argc) {
1603
1570
  if (Qnil != *argv) {
1604
- Check_Type(*argv, T_STRING);
1605
1571
  path = StringValuePtr(*argv);
1606
1572
  }
1607
1573
  if (2 <= argc) {
1608
- Check_Type(argv[1], T_STRING);
1609
1574
  filename = StringValuePtr(argv[1]);
1610
1575
  }
1611
1576
  }
@@ -1617,7 +1582,7 @@ static VALUE doc_dump(int argc, VALUE *argv, VALUE self) {
1617
1582
 
1618
1583
  oj_out_init(&out);
1619
1584
 
1620
- out.omit_nil = oj_default_options.dump_opts.omit_nil;
1585
+ out.omit_nil = oj_default_options.dump_opts.omit_nil;
1621
1586
  oj_dump_leaf_to_json(leaf, &oj_default_options, &out);
1622
1587
  rjson = rb_str_new2(out.buf);
1623
1588
 
@@ -1640,7 +1605,9 @@ static VALUE doc_dump(int argc, VALUE *argv, VALUE self) {
1640
1605
  * Oj::Doc.open('[1,2,3]') { |doc| doc.size() } #=> 4
1641
1606
  */
1642
1607
  static VALUE doc_size(VALUE self) {
1643
- return ULONG2NUM(((Doc)DATA_PTR(self))->size);
1608
+ Doc d;
1609
+ TypedData_Get_Struct(self, struct _doc, &oj_doc_type, d);
1610
+ return ULONG2NUM(d->size);
1644
1611
  }
1645
1612
 
1646
1613
  /* @overload close() => nil
@@ -1656,11 +1623,9 @@ static VALUE doc_close(VALUE self) {
1656
1623
  Doc doc = self_doc(self);
1657
1624
 
1658
1625
  rb_gc_unregister_address(&doc->self);
1659
- DATA_PTR(doc->self) = 0;
1626
+ DATA_PTR(doc->self) = NULL;
1660
1627
  if (0 != doc) {
1661
- xfree(doc->json);
1662
1628
  doc_free(doc);
1663
- xfree(doc);
1664
1629
  }
1665
1630
  return Qnil;
1666
1631
  }
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