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
@@ -5,6 +5,7 @@
5
5
  #include <ruby.h>
6
6
 
7
7
  #include "encode.h"
8
+ #include "mem.h"
8
9
 
9
10
  extern VALUE Oj;
10
11
 
@@ -15,11 +16,22 @@ static void stream_writer_free(void *ptr) {
15
16
  return;
16
17
  }
17
18
  sw = (StreamWriter)ptr;
18
- xfree(sw->sw.out.buf);
19
- xfree(sw->sw.types);
20
- xfree(ptr);
19
+ OJ_R_FREE(sw->sw.out.buf);
20
+ OJ_R_FREE(sw->sw.types);
21
+ OJ_R_FREE(ptr);
21
22
  }
22
23
 
24
+ static const rb_data_type_t oj_stream_writer_type = {
25
+ "Oj/stream_writer",
26
+ {
27
+ NULL,
28
+ stream_writer_free,
29
+ NULL,
30
+ },
31
+ 0,
32
+ 0,
33
+ };
34
+
23
35
  static void stream_writer_reset_buf(StreamWriter sw) {
24
36
  sw->sw.out.cur = sw->sw.out.buf;
25
37
  *sw->sw.out.cur = '\0';
@@ -30,7 +42,8 @@ static void stream_writer_write(StreamWriter sw) {
30
42
 
31
43
  switch (sw->type) {
32
44
  case STRING_IO:
33
- case STREAM_IO: {
45
+ case STREAM_IO:
46
+ case FILE_IO: {
34
47
  volatile VALUE rs = rb_str_new(sw->sw.out.buf, size);
35
48
 
36
49
  // Oddly enough, when pushing ASCII characters with UTF-8 encoding or
@@ -41,11 +54,6 @@ static void stream_writer_write(StreamWriter sw) {
41
54
  rb_funcall(sw->stream, oj_write_id, 1, rs);
42
55
  break;
43
56
  }
44
- case FILE_IO:
45
- if (size != write(sw->fd, sw->sw.out.buf, size)) {
46
- rb_raise(rb_eIOError, "Write failed. [_%d_:%s]\n", errno, strerror(errno));
47
- }
48
- break;
49
57
  default: rb_raise(rb_eArgError, "expected an IO Object.");
50
58
  }
51
59
  stream_writer_reset_buf(sw);
@@ -82,8 +90,8 @@ static VALUE stream_writer_new(int argc, VALUE *argv, VALUE self) {
82
90
  if (oj_stringio_class == clas) {
83
91
  type = STRING_IO;
84
92
  #if !IS_WINDOWS
85
- } else if (rb_respond_to(stream, oj_fileno_id) &&
86
- Qnil != (s = rb_funcall(stream, oj_fileno_id, 0)) && 0 != (fd = FIX2INT(s))) {
93
+ } else if (rb_respond_to(stream, oj_fileno_id) && Qnil != (s = rb_funcall(stream, oj_fileno_id, 0)) &&
94
+ 0 != (fd = FIX2INT(s))) {
87
95
  type = FILE_IO;
88
96
  #endif
89
97
  } else if (rb_respond_to(stream, oj_write_id)) {
@@ -91,7 +99,7 @@ static VALUE stream_writer_new(int argc, VALUE *argv, VALUE self) {
91
99
  } else {
92
100
  rb_raise(rb_eArgError, "expected an IO Object.");
93
101
  }
94
- sw = ALLOC(struct _streamWriter);
102
+ sw = OJ_R_ALLOC(struct _streamWriter);
95
103
  if (2 == argc && T_HASH == rb_type(argv[1])) {
96
104
  volatile VALUE v;
97
105
  int buf_size = 0;
@@ -101,15 +109,10 @@ static VALUE stream_writer_new(int argc, VALUE *argv, VALUE self) {
101
109
  rb_gc_register_address(&buffer_size_sym);
102
110
  }
103
111
  if (Qnil != (v = rb_hash_lookup(argv[1], buffer_size_sym))) {
104
- #ifdef RUBY_INTEGER_UNIFICATION
105
112
  if (rb_cInteger != rb_obj_class(v)) {
113
+ OJ_R_FREE(sw);
106
114
  rb_raise(rb_eArgError, ":buffer size must be a Integer.");
107
115
  }
108
- #else
109
- if (T_FIXNUM != rb_type(v)) {
110
- rb_raise(rb_eArgError, ":buffer size must be a Integer.");
111
- }
112
- #endif
113
116
  buf_size = FIX2INT(v);
114
117
  }
115
118
  oj_str_writer_init(&sw->sw, buf_size);
@@ -124,7 +127,7 @@ static VALUE stream_writer_new(int argc, VALUE *argv, VALUE self) {
124
127
  sw->type = type;
125
128
  sw->fd = fd;
126
129
 
127
- return Data_Wrap_Struct(oj_stream_writer_class, 0, stream_writer_free, sw);
130
+ return TypedData_Wrap_Struct(oj_stream_writer_class, &oj_stream_writer_type, sw);
128
131
  }
129
132
 
130
133
  /* Document-method: push_key
@@ -137,9 +140,9 @@ static VALUE stream_writer_new(int argc, VALUE *argv, VALUE self) {
137
140
  * - *key* [_String_] the key pending for the next push
138
141
  */
139
142
  static VALUE stream_writer_push_key(VALUE self, VALUE key) {
140
- StreamWriter sw = (StreamWriter)DATA_PTR(self);
143
+ StreamWriter sw;
144
+ TypedData_Get_Struct(self, struct _streamWriter, &oj_stream_writer_type, sw);
141
145
 
142
- rb_check_type(key, T_STRING);
143
146
  oj_str_writer_push_key(&sw->sw, StringValuePtr(key));
144
147
  if (sw->flush_limit < sw->sw.out.cur - sw->sw.out.buf) {
145
148
  stream_writer_write(sw);
@@ -156,7 +159,8 @@ static VALUE stream_writer_push_key(VALUE self, VALUE key) {
156
159
  * - *key* [_String_] the key if adding to an object in the JSON document
157
160
  */
158
161
  static VALUE stream_writer_push_object(int argc, VALUE *argv, VALUE self) {
159
- StreamWriter sw = (StreamWriter)DATA_PTR(self);
162
+ StreamWriter sw;
163
+ TypedData_Get_Struct(self, struct _streamWriter, &oj_stream_writer_type, sw);
160
164
 
161
165
  switch (argc) {
162
166
  case 0: oj_str_writer_push_object(&sw->sw, 0); break;
@@ -164,7 +168,6 @@ static VALUE stream_writer_push_object(int argc, VALUE *argv, VALUE self) {
164
168
  if (Qnil == argv[0]) {
165
169
  oj_str_writer_push_object(&sw->sw, 0);
166
170
  } else {
167
- rb_check_type(argv[0], T_STRING);
168
171
  oj_str_writer_push_object(&sw->sw, StringValuePtr(argv[0]));
169
172
  }
170
173
  break;
@@ -185,7 +188,8 @@ static VALUE stream_writer_push_object(int argc, VALUE *argv, VALUE self) {
185
188
  * - *key* [_String_] the key if adding to an object in the JSON document
186
189
  */
187
190
  static VALUE stream_writer_push_array(int argc, VALUE *argv, VALUE self) {
188
- StreamWriter sw = (StreamWriter)DATA_PTR(self);
191
+ StreamWriter sw;
192
+ TypedData_Get_Struct(self, struct _streamWriter, &oj_stream_writer_type, sw);
189
193
 
190
194
  switch (argc) {
191
195
  case 0: oj_str_writer_push_array(&sw->sw, 0); break;
@@ -193,7 +197,6 @@ static VALUE stream_writer_push_array(int argc, VALUE *argv, VALUE self) {
193
197
  if (Qnil == argv[0]) {
194
198
  oj_str_writer_push_array(&sw->sw, 0);
195
199
  } else {
196
- rb_check_type(argv[0], T_STRING);
197
200
  oj_str_writer_push_array(&sw->sw, StringValuePtr(argv[0]));
198
201
  }
199
202
  break;
@@ -213,16 +216,16 @@ static VALUE stream_writer_push_array(int argc, VALUE *argv, VALUE self) {
213
216
  * - *key* [_String_] the key if adding to an object in the JSON document
214
217
  */
215
218
  static VALUE stream_writer_push_value(int argc, VALUE *argv, VALUE self) {
216
- StreamWriter sw = (StreamWriter)DATA_PTR(self);
219
+ StreamWriter sw;
220
+ TypedData_Get_Struct(self, struct _streamWriter, &oj_stream_writer_type, sw);
217
221
 
218
222
  switch (argc) {
219
- case 1: oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, 0); break;
223
+ case 1: oj_str_writer_push_value((StrWriter)sw, *argv, 0); break;
220
224
  case 2:
221
225
  if (Qnil == argv[1]) {
222
- oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, 0);
226
+ oj_str_writer_push_value((StrWriter)sw, *argv, 0);
223
227
  } else {
224
- rb_check_type(argv[1], T_STRING);
225
- oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, StringValuePtr(argv[1]));
228
+ oj_str_writer_push_value((StrWriter)sw, *argv, StringValuePtr(argv[1]));
226
229
  }
227
230
  break;
228
231
  default: rb_raise(rb_eArgError, "Wrong number of argument to 'push_value'."); break;
@@ -243,19 +246,16 @@ static VALUE stream_writer_push_value(int argc, VALUE *argv, VALUE self) {
243
246
  * - *key* [_String_] the key if adding to an object in the JSON document
244
247
  */
245
248
  static VALUE stream_writer_push_json(int argc, VALUE *argv, VALUE self) {
246
- StreamWriter sw = (StreamWriter)DATA_PTR(self);
249
+ StreamWriter sw;
250
+ TypedData_Get_Struct(self, struct _streamWriter, &oj_stream_writer_type, sw);
247
251
 
248
- rb_check_type(argv[0], T_STRING);
249
252
  switch (argc) {
250
- case 1: oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0); break;
253
+ case 1: oj_str_writer_push_json((StrWriter)sw, StringValuePtr(*argv), 0); break;
251
254
  case 2:
252
255
  if (Qnil == argv[1]) {
253
- oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0);
256
+ oj_str_writer_push_json((StrWriter)sw, StringValuePtr(*argv), 0);
254
257
  } else {
255
- rb_check_type(argv[1], T_STRING);
256
- oj_str_writer_push_json((StrWriter)DATA_PTR(self),
257
- StringValuePtr(*argv),
258
- StringValuePtr(argv[1]));
258
+ oj_str_writer_push_json((StrWriter)sw, StringValuePtr(*argv), StringValuePtr(argv[1]));
259
259
  }
260
260
  break;
261
261
  default: rb_raise(rb_eArgError, "Wrong number of argument to 'push_json'."); break;
@@ -273,7 +273,8 @@ static VALUE stream_writer_push_json(int argc, VALUE *argv, VALUE self) {
273
273
  * currently open.
274
274
  */
275
275
  static VALUE stream_writer_pop(VALUE self) {
276
- StreamWriter sw = (StreamWriter)DATA_PTR(self);
276
+ StreamWriter sw;
277
+ TypedData_Get_Struct(self, struct _streamWriter, &oj_stream_writer_type, sw);
277
278
 
278
279
  oj_str_writer_pop(&sw->sw);
279
280
  if (sw->flush_limit < sw->sw.out.cur - sw->sw.out.buf) {
@@ -289,7 +290,8 @@ static VALUE stream_writer_pop(VALUE self) {
289
290
  * currently open.
290
291
  */
291
292
  static VALUE stream_writer_pop_all(VALUE self) {
292
- StreamWriter sw = (StreamWriter)DATA_PTR(self);
293
+ StreamWriter sw;
294
+ TypedData_Get_Struct(self, struct _streamWriter, &oj_stream_writer_type, sw);
293
295
 
294
296
  oj_str_writer_pop_all(&sw->sw);
295
297
  stream_writer_write(sw);
@@ -303,7 +305,9 @@ static VALUE stream_writer_pop_all(VALUE self) {
303
305
  * Flush any remaining characters in the buffer.
304
306
  */
305
307
  static VALUE stream_writer_flush(VALUE self) {
306
- stream_writer_write((StreamWriter)DATA_PTR(self));
308
+ StreamWriter sw;
309
+ TypedData_Get_Struct(self, struct _streamWriter, &oj_stream_writer_type, sw);
310
+ stream_writer_write(sw);
307
311
 
308
312
  return Qnil;
309
313
  }
data/ext/oj/strict.c CHANGED
@@ -17,7 +17,7 @@ VALUE oj_cstr_to_value(const char *str, size_t len, size_t cache_str) {
17
17
  volatile VALUE rstr = Qnil;
18
18
 
19
19
  if (len < cache_str) {
20
- rstr = oj_str_intern(str, len);
20
+ rstr = oj_str_intern(str, len);
21
21
  } else {
22
22
  rstr = rb_str_new(str, len);
23
23
  rstr = oj_encode(rstr);
@@ -37,28 +37,24 @@ VALUE oj_calc_hash_key(ParseInfo pi, Val parent) {
37
37
  } else {
38
38
  rkey = rb_str_new(parent->key, parent->klen);
39
39
  rkey = oj_encode(rkey);
40
- OBJ_FREEZE(rkey); // frozen when used as a Hash key anyway
40
+ OBJ_FREEZE(rkey); // frozen when used as a Hash key anyway
41
41
  }
42
42
  return rkey;
43
43
  }
44
44
  if (Yes == pi->options.sym_key) {
45
- rkey = oj_sym_intern(parent->key, parent->klen);
45
+ rkey = oj_sym_intern(parent->key, parent->klen);
46
46
  } else {
47
- rkey = oj_str_intern(parent->key, parent->klen);
47
+ rkey = oj_str_intern(parent->key, parent->klen);
48
48
  }
49
49
  return rkey;
50
50
  }
51
51
 
52
52
  static void hash_end(ParseInfo pi) {
53
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
54
- oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
55
- }
53
+ TRACE_PARSE_HASH_END(pi->options.trace, pi);
56
54
  }
57
55
 
58
56
  static void array_end(ParseInfo pi) {
59
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
60
- oj_trace_parse_array_end(pi, __FILE__, __LINE__);
61
- }
57
+ TRACE_PARSE_ARRAY_END(pi->options.trace, pi);
62
58
  }
63
59
 
64
60
  static VALUE noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
@@ -66,9 +62,7 @@ static VALUE noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
66
62
  }
67
63
 
68
64
  static void add_value(ParseInfo pi, VALUE val) {
69
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
70
- oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, val);
71
- }
65
+ TRACE_PARSE_CALL(pi->options.trace, "add_value", pi, val);
72
66
  pi->stack.head->val = val;
73
67
  }
74
68
 
@@ -76,9 +70,7 @@ static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig
76
70
  volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
77
71
 
78
72
  pi->stack.head->val = rstr;
79
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
80
- oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, rstr);
81
- }
73
+ TRACE_PARSE_CALL(pi->options.trace, "add_string", pi, rstr);
82
74
  }
83
75
 
84
76
  static void add_num(ParseInfo pi, NumInfo ni) {
@@ -86,30 +78,22 @@ static void add_num(ParseInfo pi, NumInfo ni) {
86
78
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
87
79
  }
88
80
  pi->stack.head->val = oj_num_as_value(ni);
89
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
90
- oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, pi->stack.head->val);
91
- }
81
+ TRACE_PARSE_CALL(pi->options.trace, "add_number", pi, pi->stack.head->val);
92
82
  }
93
83
 
94
84
  static VALUE start_hash(ParseInfo pi) {
95
85
  if (Qnil != pi->options.hash_class) {
96
86
  return rb_class_new_instance(0, NULL, pi->options.hash_class);
97
87
  }
98
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
99
- oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
100
- }
88
+ TRACE_PARSE_IN(pi->options.trace, "start_hash", pi);
101
89
  return rb_hash_new();
102
90
  }
103
91
 
104
92
  static void hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len, const char *orig) {
105
93
  volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
106
94
 
107
- rb_hash_aset(stack_peek(&pi->stack)->val,
108
- oj_calc_hash_key(pi, parent),
109
- rstr);
110
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
111
- oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
112
- }
95
+ rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), rstr);
96
+ TRACE_PARSE_CALL(pi->options.trace, "set_string", pi, rstr);
113
97
  }
114
98
 
115
99
  static void hash_set_num(ParseInfo pi, Val parent, NumInfo ni) {
@@ -119,27 +103,17 @@ static void hash_set_num(ParseInfo pi, Val parent, NumInfo ni) {
119
103
  oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
120
104
  }
121
105
  v = oj_num_as_value(ni);
122
- rb_hash_aset(stack_peek(&pi->stack)->val,
123
- oj_calc_hash_key(pi, parent),
124
- v);
125
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
126
- oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, v);
127
- }
106
+ rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), v);
107
+ TRACE_PARSE_CALL(pi->options.trace, "set_number", pi, v);
128
108
  }
129
109
 
130
110
  static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
131
- rb_hash_aset(stack_peek(&pi->stack)->val,
132
- oj_calc_hash_key(pi, parent),
133
- value);
134
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
135
- oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
136
- }
111
+ rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), value);
112
+ TRACE_PARSE_CALL(pi->options.trace, "set_value", pi, value);
137
113
  }
138
114
 
139
115
  static VALUE start_array(ParseInfo pi) {
140
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
141
- oj_trace_parse_in("start_array", pi, __FILE__, __LINE__);
142
- }
116
+ TRACE_PARSE_IN(pi->options.trace, "start_array", pi);
143
117
  return rb_ary_new();
144
118
  }
145
119
 
@@ -147,9 +121,7 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
147
121
  volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
148
122
 
149
123
  rb_ary_push(stack_peek(&pi->stack)->val, rstr);
150
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
151
- oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
152
- }
124
+ TRACE_PARSE_CALL(pi->options.trace, "append_string", pi, rstr);
153
125
  }
154
126
 
155
127
  static void array_append_num(ParseInfo pi, NumInfo ni) {
@@ -160,16 +132,12 @@ static void array_append_num(ParseInfo pi, NumInfo ni) {
160
132
  }
161
133
  v = oj_num_as_value(ni);
162
134
  rb_ary_push(stack_peek(&pi->stack)->val, v);
163
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
164
- oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, v);
165
- }
135
+ TRACE_PARSE_CALL(pi->options.trace, "append_number", pi, v);
166
136
  }
167
137
 
168
138
  static void array_append_value(ParseInfo pi, VALUE value) {
169
139
  rb_ary_push(stack_peek(&pi->stack)->val, value);
170
- if (RB_UNLIKELY(Yes == pi->options.trace)) {
171
- oj_trace_parse_call("append_value", pi, __FILE__, __LINE__, value);
172
- }
140
+ TRACE_PARSE_CALL(pi->options.trace, "append_value", pi, value);
173
141
  }
174
142
 
175
143
  void oj_set_strict_callbacks(ParseInfo pi) {
@@ -3,6 +3,7 @@
3
3
 
4
4
  #include "dump.h"
5
5
  #include "encode.h"
6
+ #include "mem.h"
6
7
 
7
8
  extern VALUE Oj;
8
9
 
@@ -20,7 +21,7 @@ static void push_type(StrWriter sw, DumpType type) {
20
21
  if (sw->types_end <= sw->types + sw->depth + 1) {
21
22
  size_t size = (sw->types_end - sw->types) * 2;
22
23
 
23
- REALLOC_N(sw->types, char, size);
24
+ OJ_R_REALLOC_N(sw->types, char, size);
24
25
  sw->types_end = sw->types + size;
25
26
  }
26
27
  sw->depth++;
@@ -43,7 +44,7 @@ static void maybe_comma(StrWriter sw) {
43
44
  void oj_str_writer_init(StrWriter sw, int buf_size) {
44
45
  sw->opts = oj_default_options;
45
46
  sw->depth = 0;
46
- sw->types = ALLOC_N(char, 256);
47
+ sw->types = OJ_R_ALLOC_N(char, 256);
47
48
  sw->types_end = sw->types + 256;
48
49
  *sw->types = '\0';
49
50
  sw->keyWritten = 0;
@@ -55,10 +56,10 @@ void oj_str_writer_init(StrWriter sw, int buf_size) {
55
56
  }
56
57
  // Must be allocated. Using the out.stack_buffer results in double frees
57
58
  // and I haven't figured out why yet.
58
- sw->out.buf = ALLOC_N(char, buf_size);
59
- sw->out.cur = sw->out.buf;
60
- sw->out.end = sw->out.buf + buf_size - BUFFER_EXTRA;
61
- sw->out.allocated = true;
59
+ sw->out.buf = OJ_R_ALLOC_N(char, buf_size);
60
+ sw->out.cur = sw->out.buf;
61
+ sw->out.end = sw->out.buf + buf_size - BUFFER_EXTRA;
62
+ sw->out.allocated = true;
62
63
 
63
64
  *sw->out.cur = '\0';
64
65
  sw->out.circ_cache = NULL;
@@ -69,7 +70,6 @@ void oj_str_writer_init(StrWriter sw, int buf_size) {
69
70
  sw->out.depth = 0;
70
71
  sw->out.argc = 0;
71
72
  sw->out.argv = NULL;
72
- sw->out.caller = 0;
73
73
  sw->out.ropts = NULL;
74
74
  sw->out.omit_nil = oj_default_options.dump_opts.omit_nil;
75
75
  }
@@ -225,7 +225,7 @@ void oj_str_writer_pop_all(StrWriter sw) {
225
225
  }
226
226
  }
227
227
 
228
- static void str_writer_free(void *ptr) {
228
+ static void string_writer_free(void *ptr) {
229
229
  StrWriter sw;
230
230
 
231
231
  if (0 == ptr) {
@@ -235,8 +235,25 @@ static void str_writer_free(void *ptr) {
235
235
 
236
236
  oj_out_free(&sw->out);
237
237
 
238
- xfree(sw->types);
239
- xfree(ptr);
238
+ OJ_R_FREE(sw->types);
239
+ OJ_R_FREE(ptr);
240
+ }
241
+
242
+ static const rb_data_type_t oj_string_writer_type = {
243
+ "Oj/string_writer",
244
+ {
245
+ NULL,
246
+ string_writer_free,
247
+ NULL,
248
+ },
249
+ 0,
250
+ 0,
251
+ };
252
+
253
+ StrWriter oj_str_writer_unwrap(VALUE writer) {
254
+ StrWriter sw;
255
+ TypedData_Get_Struct(writer, struct _strWriter, &oj_string_writer_type, sw);
256
+ return sw;
240
257
  }
241
258
 
242
259
  /* Document-method: new
@@ -256,7 +273,7 @@ static void str_writer_free(void *ptr) {
256
273
  * - *options* [_Hash_] formatting options
257
274
  */
258
275
  static VALUE str_writer_new(int argc, VALUE *argv, VALUE self) {
259
- StrWriter sw = ALLOC(struct _strWriter);
276
+ StrWriter sw = OJ_R_ALLOC(struct _strWriter);
260
277
 
261
278
  oj_str_writer_init(sw, 0);
262
279
  if (1 == argc) {
@@ -266,7 +283,7 @@ static VALUE str_writer_new(int argc, VALUE *argv, VALUE self) {
266
283
  sw->out.argv = argv + 1;
267
284
  sw->out.indent = sw->opts.indent;
268
285
 
269
- return Data_Wrap_Struct(oj_string_writer_class, 0, str_writer_free, sw);
286
+ return TypedData_Wrap_Struct(oj_string_writer_class, &oj_string_writer_type, sw);
270
287
  }
271
288
 
272
289
  /* Document-method: push_key
@@ -278,9 +295,9 @@ static VALUE str_writer_new(int argc, VALUE *argv, VALUE self) {
278
295
  * - *key* [_String_] the key pending for the next push
279
296
  */
280
297
  static VALUE str_writer_push_key(VALUE self, VALUE key) {
281
- StrWriter sw = (StrWriter)DATA_PTR(self);
298
+ StrWriter sw;
299
+ TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
282
300
 
283
- rb_check_type(key, T_STRING);
284
301
  oj_str_writer_push_key(sw, StringValuePtr(key));
285
302
 
286
303
  return Qnil;
@@ -294,7 +311,8 @@ static VALUE str_writer_push_key(VALUE self, VALUE key) {
294
311
  * - *key* [_String_] the key if adding to an object in the JSON document
295
312
  */
296
313
  static VALUE str_writer_push_object(int argc, VALUE *argv, VALUE self) {
297
- StrWriter sw = (StrWriter)DATA_PTR(self);
314
+ StrWriter sw;
315
+ TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
298
316
 
299
317
  switch (argc) {
300
318
  case 0: oj_str_writer_push_object(sw, 0); break;
@@ -302,7 +320,6 @@ static VALUE str_writer_push_object(int argc, VALUE *argv, VALUE self) {
302
320
  if (Qnil == argv[0]) {
303
321
  oj_str_writer_push_object(sw, 0);
304
322
  } else {
305
- rb_check_type(argv[0], T_STRING);
306
323
  oj_str_writer_push_object(sw, StringValuePtr(argv[0]));
307
324
  }
308
325
  break;
@@ -323,7 +340,8 @@ static VALUE str_writer_push_object(int argc, VALUE *argv, VALUE self) {
323
340
  * - *key* [_String_] the key if adding to an object in the JSON document
324
341
  */
325
342
  static VALUE str_writer_push_array(int argc, VALUE *argv, VALUE self) {
326
- StrWriter sw = (StrWriter)DATA_PTR(self);
343
+ StrWriter sw;
344
+ TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
327
345
 
328
346
  switch (argc) {
329
347
  case 0: oj_str_writer_push_array(sw, 0); break;
@@ -331,7 +349,6 @@ static VALUE str_writer_push_array(int argc, VALUE *argv, VALUE self) {
331
349
  if (Qnil == argv[0]) {
332
350
  oj_str_writer_push_array(sw, 0);
333
351
  } else {
334
- rb_check_type(argv[0], T_STRING);
335
352
  oj_str_writer_push_array(sw, StringValuePtr(argv[0]));
336
353
  }
337
354
  break;
@@ -352,14 +369,16 @@ static VALUE str_writer_push_array(int argc, VALUE *argv, VALUE self) {
352
369
  * - *key* [_String_] the key if adding to an object in the JSON document
353
370
  */
354
371
  static VALUE str_writer_push_value(int argc, VALUE *argv, VALUE self) {
372
+ StrWriter sw;
373
+ TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
374
+
355
375
  switch (argc) {
356
- case 1: oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, 0); break;
376
+ case 1: oj_str_writer_push_value(sw, *argv, 0); break;
357
377
  case 2:
358
378
  if (Qnil == argv[1]) {
359
- oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, 0);
379
+ oj_str_writer_push_value(sw, *argv, 0);
360
380
  } else {
361
- rb_check_type(argv[1], T_STRING);
362
- oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, StringValuePtr(argv[1]));
381
+ oj_str_writer_push_value(sw, *argv, StringValuePtr(argv[1]));
363
382
  }
364
383
  break;
365
384
  default: rb_raise(rb_eArgError, "Wrong number of argument to 'push_value'."); break;
@@ -377,17 +396,16 @@ static VALUE str_writer_push_value(int argc, VALUE *argv, VALUE self) {
377
396
  * - *key* [_String_] the key if adding to an object in the JSON document
378
397
  */
379
398
  static VALUE str_writer_push_json(int argc, VALUE *argv, VALUE self) {
380
- rb_check_type(argv[0], T_STRING);
399
+ StrWriter sw;
400
+ TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
401
+
381
402
  switch (argc) {
382
- case 1: oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0); break;
403
+ case 1: oj_str_writer_push_json(sw, StringValuePtr(*argv), 0); break;
383
404
  case 2:
384
405
  if (Qnil == argv[1]) {
385
- oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0);
406
+ oj_str_writer_push_json(sw, StringValuePtr(*argv), 0);
386
407
  } else {
387
- rb_check_type(argv[1], T_STRING);
388
- oj_str_writer_push_json((StrWriter)DATA_PTR(self),
389
- StringValuePtr(*argv),
390
- StringValuePtr(argv[1]));
408
+ oj_str_writer_push_json(sw, StringValuePtr(*argv), StringValuePtr(argv[1]));
391
409
  }
392
410
  break;
393
411
  default: rb_raise(rb_eArgError, "Wrong number of argument to 'push_json'."); break;
@@ -401,7 +419,10 @@ static VALUE str_writer_push_json(int argc, VALUE *argv, VALUE self) {
401
419
  * currently open.
402
420
  */
403
421
  static VALUE str_writer_pop(VALUE self) {
404
- oj_str_writer_pop((StrWriter)DATA_PTR(self));
422
+ StrWriter sw;
423
+ TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
424
+
425
+ oj_str_writer_pop(sw);
405
426
  return Qnil;
406
427
  }
407
428
 
@@ -412,7 +433,10 @@ static VALUE str_writer_pop(VALUE self) {
412
433
  * currently open.
413
434
  */
414
435
  static VALUE str_writer_pop_all(VALUE self) {
415
- oj_str_writer_pop_all((StrWriter)DATA_PTR(self));
436
+ StrWriter sw;
437
+ TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
438
+
439
+ oj_str_writer_pop_all(sw);
416
440
 
417
441
  return Qnil;
418
442
  }
@@ -423,7 +447,8 @@ static VALUE str_writer_pop_all(VALUE self) {
423
447
  * Reset the writer back to the empty state.
424
448
  */
425
449
  static VALUE str_writer_reset(VALUE self) {
426
- StrWriter sw = (StrWriter)DATA_PTR(self);
450
+ StrWriter sw;
451
+ TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
427
452
 
428
453
  sw->depth = 0;
429
454
  *sw->types = '\0';
@@ -442,23 +467,24 @@ static VALUE str_writer_reset(VALUE self) {
442
467
  * *return* [_String_]
443
468
  */
444
469
  static VALUE str_writer_to_s(VALUE self) {
445
- StrWriter sw = (StrWriter)DATA_PTR(self);
446
- VALUE rstr = rb_str_new(sw->out.buf, sw->out.cur - sw->out.buf);
470
+ StrWriter sw;
471
+ TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
472
+ VALUE rstr = rb_str_new(sw->out.buf, sw->out.cur - sw->out.buf);
447
473
 
448
474
  return oj_encode(rstr);
449
475
  }
450
476
 
451
477
  /* Document-method: as_json
452
- * call-seq: as_json()
478
+ * call-seq: as_json(*)
453
479
  *
454
480
  * Returns the contents of the writer as a JSON element. If called from inside
455
481
  * an array or hash by Oj the raw buffer will be used othersize a more
456
482
  * inefficient parse of the contents and a return of the result is
457
- * completed. The parse uses the strict mode.
483
+ * completed. The parse uses the strict mode. Optional arguments are ignored.
458
484
  *
459
485
  * *return* [_Hash_|_Array_|_String_|_Integer_|_Float_|_True_|_False_|_nil|)
460
486
  */
461
- static VALUE str_writer_as_json(VALUE self) {
487
+ static VALUE str_writer_as_json(int argc, VALUE *argv, VALUE self) {
462
488
  if (string_writer_optimized) {
463
489
  return self;
464
490
  }
@@ -489,5 +515,5 @@ void oj_string_writer_init(void) {
489
515
  rb_define_method(oj_string_writer_class, "reset", str_writer_reset, 0);
490
516
  rb_define_method(oj_string_writer_class, "to_s", str_writer_to_s, 0);
491
517
  rb_define_method(oj_string_writer_class, "raw_json", str_writer_to_s, 0);
492
- rb_define_method(oj_string_writer_class, "as_json", str_writer_as_json, 0);
518
+ rb_define_method(oj_string_writer_class, "as_json", str_writer_as_json, -1);
493
519
  }