oj 3.13.11 → 3.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +74 -0
  3. data/README.md +4 -2
  4. data/ext/oj/buf.h +11 -6
  5. data/ext/oj/cache.c +25 -24
  6. data/ext/oj/cache8.c +10 -9
  7. data/ext/oj/circarray.c +8 -6
  8. data/ext/oj/circarray.h +2 -2
  9. data/ext/oj/code.c +17 -24
  10. data/ext/oj/code.h +2 -2
  11. data/ext/oj/compat.c +17 -44
  12. data/ext/oj/custom.c +70 -141
  13. data/ext/oj/debug.c +3 -9
  14. data/ext/oj/dump.c +128 -118
  15. data/ext/oj/dump.h +12 -8
  16. data/ext/oj/dump_compat.c +564 -641
  17. data/ext/oj/dump_leaf.c +17 -63
  18. data/ext/oj/dump_object.c +70 -199
  19. data/ext/oj/dump_strict.c +22 -46
  20. data/ext/oj/encoder.c +1 -1
  21. data/ext/oj/err.c +2 -13
  22. data/ext/oj/err.h +9 -12
  23. data/ext/oj/extconf.rb +14 -5
  24. data/ext/oj/fast.c +75 -103
  25. data/ext/oj/intern.c +52 -50
  26. data/ext/oj/intern.h +4 -8
  27. data/ext/oj/mem.c +318 -0
  28. data/ext/oj/mem.h +53 -0
  29. data/ext/oj/mimic_json.c +75 -47
  30. data/ext/oj/object.c +49 -66
  31. data/ext/oj/odd.c +89 -67
  32. data/ext/oj/odd.h +15 -15
  33. data/ext/oj/oj.c +140 -99
  34. data/ext/oj/oj.h +80 -51
  35. data/ext/oj/parse.c +162 -184
  36. data/ext/oj/parse.h +7 -10
  37. data/ext/oj/parser.c +89 -34
  38. data/ext/oj/parser.h +18 -7
  39. data/ext/oj/rails.c +82 -146
  40. data/ext/oj/rails.h +1 -1
  41. data/ext/oj/reader.c +11 -12
  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 +20 -31
  47. data/ext/oj/saj2.c +329 -93
  48. data/ext/oj/saj2.h +23 -0
  49. data/ext/oj/scp.c +3 -14
  50. data/ext/oj/sparse.c +26 -70
  51. data/ext/oj/stream_writer.c +12 -22
  52. data/ext/oj/strict.c +20 -52
  53. data/ext/oj/string_writer.c +21 -21
  54. data/ext/oj/trace.h +31 -4
  55. data/ext/oj/usual.c +105 -150
  56. data/ext/oj/usual.h +68 -0
  57. data/ext/oj/util.h +1 -1
  58. data/ext/oj/val_stack.c +1 -1
  59. data/ext/oj/val_stack.h +8 -7
  60. data/ext/oj/validate.c +21 -26
  61. data/ext/oj/wab.c +31 -68
  62. data/lib/oj/active_support_helper.rb +0 -1
  63. data/lib/oj/bag.rb +7 -1
  64. data/lib/oj/easy_hash.rb +4 -5
  65. data/lib/oj/error.rb +0 -1
  66. data/lib/oj/json.rb +4 -2
  67. data/lib/oj/mimic.rb +4 -2
  68. data/lib/oj/saj.rb +20 -6
  69. data/lib/oj/state.rb +9 -6
  70. data/lib/oj/version.rb +1 -2
  71. data/lib/oj.rb +2 -0
  72. data/pages/Compatibility.md +1 -1
  73. data/pages/InstallOptions.md +20 -0
  74. data/pages/Options.md +10 -0
  75. data/test/_test_active.rb +8 -9
  76. data/test/_test_active_mimic.rb +7 -8
  77. data/test/_test_mimic_rails.rb +17 -20
  78. data/test/activerecord/result_test.rb +5 -6
  79. data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
  80. data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
  81. data/test/{activesupport5 → activesupport7}/encoding_test.rb +20 -34
  82. data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
  83. data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
  84. data/test/files.rb +15 -15
  85. data/test/foo.rb +9 -71
  86. data/test/helper.rb +11 -8
  87. data/test/isolated/shared.rb +3 -2
  88. data/test/json_gem/json_addition_test.rb +2 -2
  89. data/test/json_gem/json_common_interface_test.rb +4 -4
  90. data/test/json_gem/json_encoding_test.rb +0 -0
  91. data/test/json_gem/json_ext_parser_test.rb +1 -0
  92. data/test/json_gem/json_fixtures_test.rb +3 -2
  93. data/test/json_gem/json_generator_test.rb +48 -36
  94. data/test/json_gem/json_generic_object_test.rb +11 -11
  95. data/test/json_gem/json_parser_test.rb +54 -47
  96. data/test/json_gem/json_string_matching_test.rb +9 -9
  97. data/test/json_gem/test_helper.rb +7 -3
  98. data/test/mem.rb +13 -12
  99. data/test/perf.rb +21 -26
  100. data/test/perf_compat.rb +31 -33
  101. data/test/perf_dump.rb +50 -0
  102. data/test/perf_fast.rb +80 -82
  103. data/test/perf_file.rb +27 -29
  104. data/test/perf_object.rb +65 -69
  105. data/test/perf_once.rb +12 -11
  106. data/test/perf_parser.rb +42 -48
  107. data/test/perf_saj.rb +46 -54
  108. data/test/perf_scp.rb +57 -69
  109. data/test/perf_simple.rb +41 -39
  110. data/test/perf_strict.rb +68 -70
  111. data/test/perf_wab.rb +67 -69
  112. data/test/prec.rb +3 -3
  113. data/test/sample/change.rb +0 -1
  114. data/test/sample/dir.rb +0 -1
  115. data/test/sample/doc.rb +0 -1
  116. data/test/sample/file.rb +0 -1
  117. data/test/sample/group.rb +0 -1
  118. data/test/sample/hasprops.rb +0 -1
  119. data/test/sample/layer.rb +0 -1
  120. data/test/sample/rect.rb +0 -1
  121. data/test/sample/shape.rb +0 -1
  122. data/test/sample/text.rb +0 -1
  123. data/test/sample.rb +16 -16
  124. data/test/sample_json.rb +8 -8
  125. data/test/test_compat.rb +76 -42
  126. data/test/test_custom.rb +72 -51
  127. data/test/test_debian.rb +7 -10
  128. data/test/test_fast.rb +86 -90
  129. data/test/test_file.rb +41 -30
  130. data/test/test_gc.rb +16 -5
  131. data/test/test_generate.rb +5 -5
  132. data/test/test_hash.rb +4 -4
  133. data/test/test_integer_range.rb +9 -9
  134. data/test/test_null.rb +20 -20
  135. data/test/test_object.rb +85 -96
  136. data/test/test_parser.rb +6 -22
  137. data/test/test_parser_debug.rb +27 -0
  138. data/test/test_parser_saj.rb +115 -23
  139. data/test/test_parser_usual.rb +6 -6
  140. data/test/test_rails.rb +2 -2
  141. data/test/test_saj.rb +10 -8
  142. data/test/test_scp.rb +37 -39
  143. data/test/test_strict.rb +30 -32
  144. data/test/test_various.rb +147 -99
  145. data/test/test_wab.rb +48 -44
  146. data/test/test_writer.rb +47 -47
  147. data/test/tests.rb +13 -4
  148. data/test/tests_mimic.rb +12 -3
  149. data/test/tests_mimic_addition.rb +12 -3
  150. metadata +33 -144
  151. data/test/activesupport4/decoding_test.rb +0 -108
  152. data/test/activesupport4/encoding_test.rb +0 -531
  153. data/test/activesupport4/test_helper.rb +0 -41
  154. data/test/activesupport5/test_helper.rb +0 -72
  155. data/test/bar.rb +0 -16
  156. data/test/baz.rb +0 -16
  157. data/test/bug.rb +0 -16
  158. data/test/zoo.rb +0 -13
data/ext/oj/dump_leaf.c CHANGED
@@ -8,45 +8,16 @@
8
8
 
9
9
  static void dump_leaf(Leaf leaf, int depth, Out out);
10
10
 
11
- static void grow(Out out, size_t len) {
12
- size_t size = out->end - out->buf;
13
- long pos = out->cur - out->buf;
14
- char * buf;
15
-
16
- size *= 2;
17
- if (size <= len * 2 + pos) {
18
- size += len;
19
- }
20
- if (out->allocated) {
21
- buf = REALLOC_N(out->buf, char, (size + BUFFER_EXTRA));
22
- } else {
23
- buf = ALLOC_N(char, (size + BUFFER_EXTRA));
24
- out->allocated = true;
25
- memcpy(buf, out->buf, out->end - out->buf + BUFFER_EXTRA);
26
- }
27
- if (0 == buf) {
28
- rb_raise(rb_eNoMemError, "Failed to create string. [%d:%s]\n", ENOSPC, strerror(ENOSPC));
29
- }
30
- out->buf = buf;
31
- out->end = buf + size;
32
- out->cur = out->buf + pos;
33
- }
34
-
35
11
  inline static void dump_chars(const char *s, size_t size, Out out) {
36
- if (out->end - out->cur <= (long)size) {
37
- grow(out, size);
38
- }
39
- memcpy(out->cur, s, size);
40
- out->cur += size;
12
+ assure_size(out, size);
13
+ APPEND_CHARS(out->cur, s, size);
41
14
  *out->cur = '\0';
42
15
  }
43
16
 
44
17
  static void dump_leaf_str(Leaf leaf, Out out) {
45
18
  switch (leaf->value_type) {
46
19
  case STR_VAL: oj_dump_cstr(leaf->str, strlen(leaf->str), 0, 0, out); break;
47
- case RUBY_VAL:
48
- oj_dump_cstr(rb_string_value_cstr(&leaf->value), (int)RSTRING_LEN(leaf->value), 0, 0, out);
49
- break;
20
+ case RUBY_VAL: oj_dump_cstr(StringValueCStr(leaf->value), (int)RSTRING_LEN(leaf->value), 0, 0, out); break;
50
21
  case COL_VAL:
51
22
  default: rb_raise(rb_eTypeError, "Unexpected value type %02x.\n", leaf->value_type); break;
52
23
  }
@@ -81,9 +52,7 @@ static void dump_leaf_array(Leaf leaf, int depth, Out out) {
81
52
  int d2 = depth + 1;
82
53
 
83
54
  size = 2;
84
- if (out->end - out->cur <= (long)size) {
85
- grow(out, size);
86
- }
55
+ assure_size(out, size);
87
56
  *out->cur++ = '[';
88
57
  if (0 == leaf->elements) {
89
58
  *out->cur++ = ']';
@@ -93,9 +62,7 @@ static void dump_leaf_array(Leaf leaf, int depth, Out out) {
93
62
 
94
63
  size = d2 * out->indent + 2;
95
64
  do {
96
- if (out->end - out->cur <= (long)size) {
97
- grow(out, size);
98
- }
65
+ assure_size(out, size);
99
66
  fill_indent(out, d2);
100
67
  dump_leaf(e, d2, out);
101
68
  if (e->next != first) {
@@ -104,9 +71,7 @@ static void dump_leaf_array(Leaf leaf, int depth, Out out) {
104
71
  e = e->next;
105
72
  } while (e != first);
106
73
  size = depth * out->indent + 1;
107
- if (out->end - out->cur <= (long)size) {
108
- grow(out, size);
109
- }
74
+ assure_size(out, size);
110
75
  fill_indent(out, depth);
111
76
  *out->cur++ = ']';
112
77
  }
@@ -118,9 +83,7 @@ static void dump_leaf_hash(Leaf leaf, int depth, Out out) {
118
83
  int d2 = depth + 1;
119
84
 
120
85
  size = 2;
121
- if (out->end - out->cur <= (long)size) {
122
- grow(out, size);
123
- }
86
+ assure_size(out, size);
124
87
  *out->cur++ = '{';
125
88
  if (0 == leaf->elements) {
126
89
  *out->cur++ = '}';
@@ -130,9 +93,7 @@ static void dump_leaf_hash(Leaf leaf, int depth, Out out) {
130
93
 
131
94
  size = d2 * out->indent + 2;
132
95
  do {
133
- if (out->end - out->cur <= (long)size) {
134
- grow(out, size);
135
- }
96
+ assure_size(out, size);
136
97
  fill_indent(out, d2);
137
98
  oj_dump_cstr(e->key, strlen(e->key), 0, 0, out);
138
99
  *out->cur++ = ':';
@@ -143,9 +104,7 @@ static void dump_leaf_hash(Leaf leaf, int depth, Out out) {
143
104
  e = e->next;
144
105
  } while (e != first);
145
106
  size = depth * out->indent + 1;
146
- if (out->end - out->cur <= (long)size) {
147
- grow(out, size);
148
- }
107
+ assure_size(out, size);
149
108
  fill_indent(out, depth);
150
109
  *out->cur++ = '}';
151
110
  }
@@ -168,10 +127,7 @@ static void dump_leaf(Leaf leaf, int depth, Out out) {
168
127
 
169
128
  void oj_dump_leaf_to_json(Leaf leaf, Options copts, Out out) {
170
129
  if (0 == out->buf) {
171
- out->buf = ALLOC_N(char, 4096);
172
- out->end = out->buf + 4095 -
173
- BUFFER_EXTRA; // 1 less than end plus extra for possible errors
174
- out->allocated = true;
130
+ oj_out_init(out);
175
131
  }
176
132
  out->cur = out->buf;
177
133
  out->circ_cnt = 0;
@@ -182,15 +138,13 @@ void oj_dump_leaf_to_json(Leaf leaf, Options copts, Out out) {
182
138
  }
183
139
 
184
140
  void oj_write_leaf_to_file(Leaf leaf, const char *path, Options copts) {
185
- char buf[4096];
186
141
  struct _out out;
187
142
  size_t size;
188
- FILE * f;
143
+ FILE *f;
189
144
 
190
- out.buf = buf;
191
- out.end = buf + sizeof(buf) - BUFFER_EXTRA;
192
- out.allocated = false;
193
- out.omit_nil = copts->dump_opts.omit_nil;
145
+ oj_out_init(&out);
146
+
147
+ out.omit_nil = copts->dump_opts.omit_nil;
194
148
  oj_dump_leaf_to_json(leaf, copts, &out);
195
149
  size = out.cur - out.buf;
196
150
  if (0 == (f = fopen(path, "w"))) {
@@ -201,8 +155,8 @@ void oj_write_leaf_to_file(Leaf leaf, const char *path, Options copts) {
201
155
 
202
156
  rb_raise(rb_eIOError, "Write failed. [%d:%s]\n", err, strerror(err));
203
157
  }
204
- if (out.allocated) {
205
- xfree(out.buf);
206
- }
158
+
159
+ oj_out_free(&out);
160
+
207
161
  fclose(f);
208
162
  }
data/ext/oj/dump_object.c CHANGED
@@ -2,6 +2,7 @@
2
2
  // Licensed under the MIT License. See LICENSE file in the project root for license details.
3
3
 
4
4
  #include "dump.h"
5
+ #include "mem.h"
5
6
  #include "odd.h"
6
7
  #include "trace.h"
7
8
 
@@ -24,19 +25,14 @@ static void dump_data(VALUE obj, int depth, Out out, bool as_ok) {
24
25
 
25
26
  if (rb_cTime == clas) {
26
27
  assure_size(out, 6);
27
- *out->cur++ = '{';
28
- *out->cur++ = '"';
29
- *out->cur++ = '^';
30
- *out->cur++ = 't';
31
- *out->cur++ = '"';
32
- *out->cur++ = ':';
28
+ APPEND_CHARS(out->cur, "{\"^t\":", 6);
33
29
  dump_time(obj, out);
34
30
  *out->cur++ = '}';
35
31
  *out->cur = '\0';
36
32
  } else {
37
33
  if (oj_bigdecimal_class == clas) {
38
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
39
- const char * str = RSTRING_PTR(rstr);
34
+ volatile VALUE rstr = oj_safe_string_convert(obj);
35
+ const char *str = RSTRING_PTR(rstr);
40
36
  int len = (int)RSTRING_LEN(rstr);
41
37
 
42
38
  if (No != out->opts->bigdec_as_num) {
@@ -64,8 +60,8 @@ static void dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
64
60
  VALUE clas = rb_obj_class(obj);
65
61
 
66
62
  if (oj_bigdecimal_class == clas) {
67
- volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
68
- const char * str = RSTRING_PTR(rstr);
63
+ volatile VALUE rstr = oj_safe_string_convert(obj);
64
+ const char *str = RSTRING_PTR(rstr);
69
65
  int len = (int)RSTRING_LEN(rstr);
70
66
 
71
67
  if (0 == strcasecmp("Infinity", str)) {
@@ -91,12 +87,7 @@ static void dump_class(VALUE obj, int depth, Out out, bool as_ok) {
91
87
  size_t len = strlen(s);
92
88
 
93
89
  assure_size(out, 6);
94
- *out->cur++ = '{';
95
- *out->cur++ = '"';
96
- *out->cur++ = '^';
97
- *out->cur++ = 'c';
98
- *out->cur++ = '"';
99
- *out->cur++ = ':';
90
+ APPEND_CHARS(out->cur, "{\"^c\":", 6);
100
91
  oj_dump_cstr(s, len, 0, 0, out);
101
92
  *out->cur++ = '}';
102
93
  *out->cur = '\0';
@@ -120,9 +111,7 @@ static void dump_array_class(VALUE a, VALUE clas, int depth, Out out) {
120
111
  if (0 < id) {
121
112
  assure_size(out, d2 * out->indent + 16);
122
113
  fill_indent(out, d2);
123
- *out->cur++ = '"';
124
- *out->cur++ = '^';
125
- *out->cur++ = 'i';
114
+ APPEND_CHARS(out->cur, "\"^i", 3);
126
115
  dump_ulong(id, out);
127
116
  *out->cur++ = '"';
128
117
  }
@@ -139,19 +128,17 @@ static void dump_array_class(VALUE a, VALUE clas, int depth, Out out) {
139
128
  } else {
140
129
  size = d2 * out->indent + 2;
141
130
  }
131
+ assure_size(out, size * cnt);
142
132
  cnt--;
143
133
  for (i = 0; i <= cnt; i++) {
144
- assure_size(out, size);
145
134
  if (out->opts->dump_opts.use) {
146
135
  if (0 < out->opts->dump_opts.array_size) {
147
- strcpy(out->cur, out->opts->dump_opts.array_nl);
148
- out->cur += out->opts->dump_opts.array_size;
136
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
149
137
  }
150
138
  if (0 < out->opts->dump_opts.indent_size) {
151
139
  int i;
152
140
  for (i = d2; 0 < i; i--) {
153
- strcpy(out->cur, out->opts->dump_opts.indent_str);
154
- out->cur += out->opts->dump_opts.indent_size;
141
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
155
142
  }
156
143
  }
157
144
  } else {
@@ -168,15 +155,13 @@ static void dump_array_class(VALUE a, VALUE clas, int depth, Out out) {
168
155
  // printf("*** d2: %u indent: %u '%s'\n", d2, out->opts->dump_opts->indent_size,
169
156
  // out->opts->dump_opts->indent);
170
157
  if (0 < out->opts->dump_opts.array_size) {
171
- strcpy(out->cur, out->opts->dump_opts.array_nl);
172
- out->cur += out->opts->dump_opts.array_size;
158
+ APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
173
159
  }
174
160
  if (0 < out->opts->dump_opts.indent_size) {
175
161
  int i;
176
162
 
177
163
  for (i = depth; 0 < i; i--) {
178
- strcpy(out->cur, out->opts->dump_opts.indent_str);
179
- out->cur += out->opts->dump_opts.indent_size;
164
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
180
165
  }
181
166
  }
182
167
  } else {
@@ -239,41 +224,36 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
239
224
  oj_dump_obj_val(value, depth, out);
240
225
  break;
241
226
 
242
- default:
243
- {
244
- int d2 = depth + 1;
245
- long s2 = size + out->indent + 1;
246
- int i;
247
- int started = 0;
248
- uint8_t b;
249
-
250
- assure_size(out, s2 + 15);
251
- *out->cur++ = '"';
252
- *out->cur++ = '^';
253
- *out->cur++ = '#';
254
- out->hash_cnt++;
255
- for (i = 28; 0 <= i; i -= 4) {
256
- b = (uint8_t)((out->hash_cnt >> i) & 0x0000000F);
257
- if ('\0' != b) {
258
- started = 1;
259
- }
260
- if (started) {
261
- *out->cur++ = hex_chars[b];
262
- }
227
+ default: {
228
+ int d2 = depth + 1;
229
+ long s2 = size + out->indent + 1;
230
+ int i;
231
+ int started = 0;
232
+ uint8_t b;
233
+
234
+ assure_size(out, s2 + 15);
235
+ APPEND_CHARS(out->cur, "\"^#", 3);
236
+ out->hash_cnt++;
237
+ for (i = 28; 0 <= i; i -= 4) {
238
+ b = (uint8_t)((out->hash_cnt >> i) & 0x0000000F);
239
+ if ('\0' != b) {
240
+ started = 1;
241
+ }
242
+ if (started) {
243
+ *out->cur++ = hex_chars[b];
263
244
  }
264
- *out->cur++ = '"';
265
- *out->cur++ = ':';
266
- *out->cur++ = '[';
267
- fill_indent(out, d2);
268
- oj_dump_obj_val(key, d2, out);
269
- assure_size(out, s2);
270
- *out->cur++ = ',';
271
- fill_indent(out, d2);
272
- oj_dump_obj_val(value, d2, out);
273
- assure_size(out, size);
274
- fill_indent(out, depth);
275
- *out->cur++ = ']';
276
245
  }
246
+ APPEND_CHARS(out->cur, "\":[", 3);
247
+ fill_indent(out, d2);
248
+ oj_dump_obj_val(key, d2, out);
249
+ assure_size(out, s2);
250
+ *out->cur++ = ',';
251
+ fill_indent(out, d2);
252
+ oj_dump_obj_val(value, d2, out);
253
+ assure_size(out, size);
254
+ fill_indent(out, depth);
255
+ *out->cur++ = ']';
256
+ }
277
257
  }
278
258
  out->depth = depth;
279
259
  *out->cur++ = ',';
@@ -293,8 +273,7 @@ static void dump_hash_class(VALUE obj, VALUE clas, int depth, Out out) {
293
273
  size = depth * out->indent + 2;
294
274
  assure_size(out, 2);
295
275
  if (0 == cnt) {
296
- *out->cur++ = '{';
297
- *out->cur++ = '}';
276
+ APPEND_CHARS(out->cur, "{}", 2);
298
277
  } else {
299
278
  long id = oj_check_circular(obj, out);
300
279
 
@@ -305,11 +284,7 @@ static void dump_hash_class(VALUE obj, VALUE clas, int depth, Out out) {
305
284
  if (0 < id) {
306
285
  assure_size(out, size + 16);
307
286
  fill_indent(out, depth + 1);
308
- *out->cur++ = '"';
309
- *out->cur++ = '^';
310
- *out->cur++ = 'i';
311
- *out->cur++ = '"';
312
- *out->cur++ = ':';
287
+ APPEND_CHARS(out->cur, "\"^i\":", 5);
313
288
  dump_ulong(id, out);
314
289
  *out->cur++ = ',';
315
290
  }
@@ -325,15 +300,13 @@ static void dump_hash_class(VALUE obj, VALUE clas, int depth, Out out) {
325
300
  size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
326
301
  assure_size(out, size);
327
302
  if (0 < out->opts->dump_opts.hash_size) {
328
- strcpy(out->cur, out->opts->dump_opts.hash_nl);
329
- out->cur += out->opts->dump_opts.hash_size;
303
+ APPEND_CHARS(out->cur, out->opts->dump_opts.hash_nl, out->opts->dump_opts.hash_size);
330
304
  }
331
305
  if (0 < out->opts->dump_opts.indent_size) {
332
306
  int i;
333
307
 
334
308
  for (i = depth; 0 < i; i--) {
335
- strcpy(out->cur, out->opts->dump_opts.indent_str);
336
- out->cur += out->opts->dump_opts.indent_size;
309
+ APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
337
310
  }
338
311
  }
339
312
  }
@@ -342,7 +315,6 @@ static void dump_hash_class(VALUE obj, VALUE clas, int depth, Out out) {
342
315
  *out->cur = '\0';
343
316
  }
344
317
 
345
- #ifdef HAVE_RB_IVAR_FOREACH
346
318
  static int dump_attr_cb(ID key, VALUE value, VALUE ov) {
347
319
  Out out = (Out)ov;
348
320
  int depth = out->depth;
@@ -385,17 +357,16 @@ static int dump_attr_cb(ID key, VALUE value, VALUE ov) {
385
357
 
386
358
  return ST_CONTINUE;
387
359
  }
388
- #endif
389
360
 
390
361
  static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
391
362
  dump_hash_class(obj, rb_obj_class(obj), depth, out);
392
363
  }
393
364
 
394
365
  static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
395
- ID * idp;
396
- AttrGetFunc * fp;
366
+ ID *idp;
367
+ AttrGetFunc *fp;
397
368
  volatile VALUE v;
398
- const char * name;
369
+ const char *name;
399
370
  size_t size;
400
371
  int d2 = depth + 1;
401
372
 
@@ -408,11 +379,7 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
408
379
  size = d2 * out->indent + clen + 10;
409
380
  assure_size(out, size);
410
381
  fill_indent(out, d2);
411
- *out->cur++ = '"';
412
- *out->cur++ = '^';
413
- *out->cur++ = 'O';
414
- *out->cur++ = '"';
415
- *out->cur++ = ':';
382
+ APPEND_CHARS(out->cur, "\"^O\":", 5);
416
383
  oj_dump_cstr(class_name, clen, 0, 0, out);
417
384
  *out->cur++ = ',';
418
385
  }
@@ -430,12 +397,9 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
430
397
  assure_size(out, size);
431
398
  fill_indent(out, d2);
432
399
  *out->cur++ = '"';
433
- memcpy(out->cur, name, nlen);
434
- out->cur += nlen;
435
- *out->cur++ = '"';
436
- *out->cur++ = ':';
437
- memcpy(out->cur, s, len);
438
- out->cur += len;
400
+ APPEND_CHARS(out->cur, name, nlen);
401
+ APPEND_CHARS(out->cur, "\":", 2);
402
+ APPEND_CHARS(out->cur, s, len);
439
403
  *out->cur = '\0';
440
404
  }
441
405
  } else {
@@ -446,7 +410,7 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
446
410
  assure_size(out, size);
447
411
  name = rb_id2name(*idp);
448
412
  nlen = strlen(name);
449
- if (0 != *fp) {
413
+ if (NULL != *fp) {
450
414
  v = (*fp)(obj);
451
415
  } else if (0 == strchr(name, '.')) {
452
416
  v = rb_funcall(obj, *idp, 0);
@@ -458,7 +422,7 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
458
422
  ID i;
459
423
 
460
424
  if (sizeof(nbuf) <= nlen) {
461
- if (NULL == (n2 = strdup(name))) {
425
+ if (NULL == (n2 = OJ_STRDUP(name))) {
462
426
  rb_raise(rb_eNoMemError, "for attribute name.");
463
427
  }
464
428
  } else {
@@ -475,7 +439,7 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
475
439
  i = rb_intern(n);
476
440
  v = rb_funcall(v, i, 0);
477
441
  if (nbuf != n2) {
478
- free(n2);
442
+ OJ_FREE(n2);
479
443
  }
480
444
  }
481
445
  fill_indent(out, d2);
@@ -509,22 +473,14 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
509
473
 
510
474
  assure_size(out, d2 * out->indent + clen + 10);
511
475
  fill_indent(out, d2);
512
- *out->cur++ = '"';
513
- *out->cur++ = '^';
514
- *out->cur++ = 'o';
515
- *out->cur++ = '"';
516
- *out->cur++ = ':';
476
+ APPEND_CHARS(out->cur, "\"^o\":", 5);
517
477
  oj_dump_cstr(class_name, clen, 0, 0, out);
518
478
  }
519
479
  if (0 < id) {
520
480
  assure_size(out, d2 * out->indent + 16);
521
481
  *out->cur++ = ',';
522
482
  fill_indent(out, d2);
523
- *out->cur++ = '"';
524
- *out->cur++ = '^';
525
- *out->cur++ = 'i';
526
- *out->cur++ = '"';
527
- *out->cur++ = ':';
483
+ APPEND_CHARS(out->cur, "\"^i\":", 5);
528
484
  dump_ulong(id, out);
529
485
  }
530
486
  switch (type) {
@@ -532,57 +488,28 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
532
488
  assure_size(out, d2 * out->indent + 14);
533
489
  *out->cur++ = ',';
534
490
  fill_indent(out, d2);
535
- *out->cur++ = '"';
536
- *out->cur++ = 's';
537
- *out->cur++ = 'e';
538
- *out->cur++ = 'l';
539
- *out->cur++ = 'f';
540
- *out->cur++ = '"';
541
- *out->cur++ = ':';
491
+ APPEND_CHARS(out->cur, "\"self\":", 7);
542
492
  oj_dump_cstr(RSTRING_PTR(obj), (int)RSTRING_LEN(obj), 0, 0, out);
543
493
  break;
544
494
  case T_ARRAY:
545
495
  assure_size(out, d2 * out->indent + 14);
546
496
  *out->cur++ = ',';
547
497
  fill_indent(out, d2);
548
- *out->cur++ = '"';
549
- *out->cur++ = 's';
550
- *out->cur++ = 'e';
551
- *out->cur++ = 'l';
552
- *out->cur++ = 'f';
553
- *out->cur++ = '"';
554
- *out->cur++ = ':';
498
+ APPEND_CHARS(out->cur, "\"self\":", 7);
555
499
  dump_array_class(obj, Qundef, depth + 1, out);
556
500
  break;
557
501
  case T_HASH:
558
502
  assure_size(out, d2 * out->indent + 14);
559
503
  *out->cur++ = ',';
560
504
  fill_indent(out, d2);
561
- *out->cur++ = '"';
562
- *out->cur++ = 's';
563
- *out->cur++ = 'e';
564
- *out->cur++ = 'l';
565
- *out->cur++ = 'f';
566
- *out->cur++ = '"';
567
- *out->cur++ = ':';
505
+ APPEND_CHARS(out->cur, "\"self\":", 7);
568
506
  dump_hash_class(obj, Qundef, depth + 1, out);
569
507
  break;
570
508
  default: break;
571
509
  }
572
510
  {
573
- int cnt;
574
- #ifdef HAVE_RB_IVAR_COUNT
575
- cnt = (int)rb_ivar_count(obj);
576
- #else
577
- volatile VALUE vars = rb_funcall2(obj, oj_instance_variables_id, 0, 0);
578
- VALUE * np = RARRAY_PTR(vars);
579
- ID vid;
580
- const char * attr;
581
- int i;
582
- int first = 1;
583
-
584
- cnt = (int)RARRAY_LEN(vars);
585
- #endif
511
+ int cnt = (int)rb_ivar_count(obj);
512
+
586
513
  if (Qundef != clas && 0 < cnt) {
587
514
  *out->cur++ = ',';
588
515
  }
@@ -595,52 +522,10 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
595
522
  }
596
523
  }
597
524
  out->depth = depth + 1;
598
- #ifdef HAVE_RB_IVAR_FOREACH
599
525
  rb_ivar_foreach(obj, dump_attr_cb, (VALUE)out);
600
526
  if (',' == *(out->cur - 1)) {
601
527
  out->cur--; // backup to overwrite last comma
602
528
  }
603
- #else
604
- size = d2 * out->indent + 1;
605
- for (i = cnt; 0 < i; i--, np++) {
606
- VALUE value;
607
-
608
- vid = rb_to_id(*np);
609
- attr = rb_id2name(vid);
610
- if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
611
- continue;
612
- }
613
- value = rb_ivar_get(obj, vid);
614
-
615
- if (dump_ignore(out->opts, value)) {
616
- continue;
617
- }
618
- if (out->omit_nil && Qnil == value) {
619
- continue;
620
- }
621
- if (first) {
622
- first = 0;
623
- } else {
624
- *out->cur++ = ',';
625
- }
626
- assure_size(out, size);
627
- fill_indent(out, d2);
628
- if ('@' == *attr) {
629
- attr++;
630
- oj_dump_cstr(attr, strlen(attr), 0, 0, out);
631
- } else {
632
- char buf[32];
633
-
634
- *buf = '~';
635
- strncpy(buf + 1, attr, sizeof(buf) - 2);
636
- buf[sizeof(buf) - 1] = '\0';
637
- oj_dump_cstr(buf, strlen(attr) + 1, 0, 0, out);
638
- }
639
- *out->cur++ = ':';
640
- oj_dump_obj_val(value, d2, out);
641
- assure_size(out, 2);
642
- }
643
- #endif
644
529
  if (rb_obj_is_kind_of(obj, rb_eException)) {
645
530
  volatile VALUE rv;
646
531
 
@@ -688,12 +573,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
688
573
  assure_size(out, size);
689
574
  *out->cur++ = '{';
690
575
  fill_indent(out, d2);
691
- *out->cur++ = '"';
692
- *out->cur++ = '^';
693
- *out->cur++ = 'u';
694
- *out->cur++ = '"';
695
- *out->cur++ = ':';
696
- *out->cur++ = '[';
576
+ APPEND_CHARS(out->cur, "\"^u\":[", 6);
697
577
  if ('#' == *class_name) {
698
578
  VALUE ma = rb_struct_s_members(clas);
699
579
  const char *name;
@@ -711,16 +591,14 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
711
591
  *out->cur++ = ',';
712
592
  }
713
593
  *out->cur++ = '"';
714
- memcpy(out->cur, name, len);
715
- out->cur += len;
594
+ APPEND_CHARS(out->cur, name, len);
716
595
  *out->cur++ = '"';
717
596
  }
718
597
  *out->cur++ = ']';
719
598
  } else {
720
599
  fill_indent(out, d3);
721
600
  *out->cur++ = '"';
722
- memcpy(out->cur, class_name, len);
723
- out->cur += len;
601
+ APPEND_CHARS(out->cur, class_name, len);
724
602
  *out->cur++ = '"';
725
603
  }
726
604
  *out->cur++ = ',';
@@ -764,9 +642,8 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
764
642
  }
765
643
  #endif
766
644
  out->cur--;
767
- *out->cur++ = ']';
768
- *out->cur++ = '}';
769
- *out->cur = '\0';
645
+ APPEND_CHARS(out->cur, "]}", 2);
646
+ *out->cur = '\0';
770
647
  }
771
648
 
772
649
  static void dump_complex(VALUE obj, int depth, Out out, bool as_ok) {
@@ -805,9 +682,7 @@ static DumpFunc obj_funcs[] = {
805
682
  void oj_dump_obj_val(VALUE obj, int depth, Out out) {
806
683
  int type = rb_type(obj);
807
684
 
808
- if (Yes == out->opts->trace) {
809
- oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
810
- }
685
+ TRACE(out->opts->trace, "dump", obj, depth, TraceIn);
811
686
  if (MAX_DEPTH < depth) {
812
687
  rb_raise(rb_eNoMemError, "Too deeply nested.\n");
813
688
  }
@@ -816,14 +691,10 @@ void oj_dump_obj_val(VALUE obj, int depth, Out out) {
816
691
 
817
692
  if (NULL != f) {
818
693
  f(obj, depth, out, false);
819
- if (Yes == out->opts->trace) {
820
- oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
821
- }
694
+ TRACE(out->opts->trace, "dump", obj, depth, TraceOut);
822
695
  return;
823
696
  }
824
697
  }
825
698
  oj_dump_nil(Qnil, depth, out, false);
826
- if (Yes == out->opts->trace) {
827
- oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
828
- }
699
+ TRACE(out->opts->trace, "dump", Qnil, depth, TraceOut);
829
700
  }