oj 3.13.9 → 3.16.1

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 (161) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +101 -0
  3. data/README.md +13 -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 +19 -33
  10. data/ext/oj/code.h +2 -2
  11. data/ext/oj/compat.c +20 -60
  12. data/ext/oj/custom.c +76 -155
  13. data/ext/oj/debug.c +3 -9
  14. data/ext/oj/dump.c +203 -213
  15. data/ext/oj/dump.h +26 -12
  16. data/ext/oj/dump_compat.c +565 -642
  17. data/ext/oj/dump_leaf.c +17 -63
  18. data/ext/oj/dump_object.c +59 -181
  19. data/ext/oj/dump_strict.c +24 -48
  20. data/ext/oj/encoder.c +43 -0
  21. data/ext/oj/err.c +2 -13
  22. data/ext/oj/err.h +9 -12
  23. data/ext/oj/extconf.rb +18 -7
  24. data/ext/oj/fast.c +83 -108
  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 +104 -81
  30. data/ext/oj/object.c +50 -67
  31. data/ext/oj/odd.c +89 -67
  32. data/ext/oj/odd.h +15 -15
  33. data/ext/oj/oj.c +171 -106
  34. data/ext/oj/oj.h +96 -74
  35. data/ext/oj/parse.c +169 -189
  36. data/ext/oj/parse.h +23 -24
  37. data/ext/oj/parser.c +89 -34
  38. data/ext/oj/parser.h +20 -9
  39. data/ext/oj/rails.c +86 -151
  40. data/ext/oj/rails.h +1 -1
  41. data/ext/oj/reader.c +12 -15
  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 +21 -32
  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 -22
  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 +32 -69
  62. data/lib/oj/active_support_helper.rb +1 -3
  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 +162 -150
  67. data/lib/oj/mimic.rb +6 -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/JsonGem.md +15 -0
  75. data/pages/Modes.md +6 -3
  76. data/pages/Options.md +10 -0
  77. data/pages/Rails.md +12 -0
  78. data/test/_test_active.rb +8 -9
  79. data/test/_test_active_mimic.rb +7 -8
  80. data/test/_test_mimic_rails.rb +17 -20
  81. data/test/activerecord/result_test.rb +5 -6
  82. data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
  83. data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
  84. data/test/{activesupport5 → activesupport7}/encoding_test.rb +20 -34
  85. data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
  86. data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
  87. data/test/files.rb +15 -15
  88. data/test/foo.rb +15 -15
  89. data/test/helper.rb +11 -8
  90. data/test/isolated/shared.rb +3 -2
  91. data/test/json_gem/json_addition_test.rb +2 -2
  92. data/test/json_gem/json_common_interface_test.rb +8 -6
  93. data/test/json_gem/json_encoding_test.rb +0 -0
  94. data/test/json_gem/json_ext_parser_test.rb +1 -0
  95. data/test/json_gem/json_fixtures_test.rb +3 -2
  96. data/test/json_gem/json_generator_test.rb +49 -37
  97. data/test/json_gem/json_generic_object_test.rb +11 -11
  98. data/test/json_gem/json_parser_test.rb +54 -47
  99. data/test/json_gem/json_string_matching_test.rb +9 -9
  100. data/test/json_gem/test_helper.rb +7 -3
  101. data/test/mem.rb +13 -12
  102. data/test/perf.rb +21 -26
  103. data/test/perf_compat.rb +31 -33
  104. data/test/perf_dump.rb +50 -0
  105. data/test/perf_fast.rb +80 -82
  106. data/test/perf_file.rb +27 -29
  107. data/test/perf_object.rb +65 -69
  108. data/test/perf_once.rb +12 -11
  109. data/test/perf_parser.rb +42 -48
  110. data/test/perf_saj.rb +46 -54
  111. data/test/perf_scp.rb +57 -69
  112. data/test/perf_simple.rb +41 -39
  113. data/test/perf_strict.rb +68 -70
  114. data/test/perf_wab.rb +67 -69
  115. data/test/prec.rb +3 -3
  116. data/test/sample/change.rb +0 -1
  117. data/test/sample/dir.rb +0 -1
  118. data/test/sample/doc.rb +0 -1
  119. data/test/sample/file.rb +0 -1
  120. data/test/sample/group.rb +0 -1
  121. data/test/sample/hasprops.rb +0 -1
  122. data/test/sample/layer.rb +0 -1
  123. data/test/sample/rect.rb +0 -1
  124. data/test/sample/shape.rb +0 -1
  125. data/test/sample/text.rb +0 -1
  126. data/test/sample.rb +16 -16
  127. data/test/sample_json.rb +8 -8
  128. data/test/test_compat.rb +95 -43
  129. data/test/test_custom.rb +72 -51
  130. data/test/test_debian.rb +7 -10
  131. data/test/test_fast.rb +102 -87
  132. data/test/test_file.rb +41 -30
  133. data/test/test_gc.rb +16 -5
  134. data/test/test_generate.rb +5 -5
  135. data/test/test_hash.rb +4 -4
  136. data/test/test_integer_range.rb +9 -9
  137. data/test/test_null.rb +20 -20
  138. data/test/test_object.rb +85 -96
  139. data/test/test_parser.rb +6 -22
  140. data/test/test_parser_debug.rb +27 -0
  141. data/test/test_parser_saj.rb +115 -23
  142. data/test/test_parser_usual.rb +6 -6
  143. data/test/test_rails.rb +2 -2
  144. data/test/test_saj.rb +10 -8
  145. data/test/test_scp.rb +37 -39
  146. data/test/test_strict.rb +40 -32
  147. data/test/test_various.rb +163 -84
  148. data/test/test_wab.rb +48 -44
  149. data/test/test_writer.rb +47 -47
  150. data/test/tests.rb +13 -5
  151. data/test/tests_mimic.rb +12 -3
  152. data/test/tests_mimic_addition.rb +12 -3
  153. metadata +34 -144
  154. data/test/activesupport4/decoding_test.rb +0 -108
  155. data/test/activesupport4/encoding_test.rb +0 -531
  156. data/test/activesupport4/test_helper.rb +0 -41
  157. data/test/activesupport5/test_helper.rb +0 -72
  158. data/test/bar.rb +0 -16
  159. data/test/baz.rb +0 -16
  160. data/test/bug.rb +0 -16
  161. data/test/zoo.rb +0 -13
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,25 +128,23 @@ 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 {
158
145
  fill_indent(out, d2);
159
146
  }
160
- oj_dump_obj_val(rb_ary_entry(a, i), d2, out);
147
+ oj_dump_obj_val(RARRAY_AREF(a, i), d2, out);
161
148
  if (i < cnt) {
162
149
  *out->cur++ = ',';
163
150
  }
@@ -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 {
@@ -218,7 +203,7 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
218
203
  int depth = out->depth;
219
204
  long size = depth * out->indent + 1;
220
205
 
221
- if (oj_dump_ignore(out->opts, value)) {
206
+ if (dump_ignore(out->opts, value)) {
222
207
  return ST_CONTINUE;
223
208
  }
224
209
  if (out->omit_nil && Qnil == value) {
@@ -226,15 +211,20 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
226
211
  }
227
212
  assure_size(out, size);
228
213
  fill_indent(out, depth);
229
- if (rb_type(key) == T_STRING) {
214
+ switch (rb_type(key)) {
215
+ case T_STRING:
230
216
  dump_str_class(key, Qundef, depth, out);
231
217
  *out->cur++ = ':';
232
218
  oj_dump_obj_val(value, depth, out);
233
- } else if (rb_type(key) == T_SYMBOL) {
219
+ break;
220
+
221
+ case T_SYMBOL:
234
222
  dump_sym(key, 0, out, false);
235
223
  *out->cur++ = ':';
236
224
  oj_dump_obj_val(value, depth, out);
237
- } else {
225
+ break;
226
+
227
+ default: {
238
228
  int d2 = depth + 1;
239
229
  long s2 = size + out->indent + 1;
240
230
  int i;
@@ -242,9 +232,7 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
242
232
  uint8_t b;
243
233
 
244
234
  assure_size(out, s2 + 15);
245
- *out->cur++ = '"';
246
- *out->cur++ = '^';
247
- *out->cur++ = '#';
235
+ APPEND_CHARS(out->cur, "\"^#", 3);
248
236
  out->hash_cnt++;
249
237
  for (i = 28; 0 <= i; i -= 4) {
250
238
  b = (uint8_t)((out->hash_cnt >> i) & 0x0000000F);
@@ -255,9 +243,7 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
255
243
  *out->cur++ = hex_chars[b];
256
244
  }
257
245
  }
258
- *out->cur++ = '"';
259
- *out->cur++ = ':';
260
- *out->cur++ = '[';
246
+ APPEND_CHARS(out->cur, "\":[", 3);
261
247
  fill_indent(out, d2);
262
248
  oj_dump_obj_val(key, d2, out);
263
249
  assure_size(out, s2);
@@ -268,6 +254,7 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
268
254
  fill_indent(out, depth);
269
255
  *out->cur++ = ']';
270
256
  }
257
+ }
271
258
  out->depth = depth;
272
259
  *out->cur++ = ',';
273
260
 
@@ -286,8 +273,7 @@ static void dump_hash_class(VALUE obj, VALUE clas, int depth, Out out) {
286
273
  size = depth * out->indent + 2;
287
274
  assure_size(out, 2);
288
275
  if (0 == cnt) {
289
- *out->cur++ = '{';
290
- *out->cur++ = '}';
276
+ APPEND_CHARS(out->cur, "{}", 2);
291
277
  } else {
292
278
  long id = oj_check_circular(obj, out);
293
279
 
@@ -298,11 +284,7 @@ static void dump_hash_class(VALUE obj, VALUE clas, int depth, Out out) {
298
284
  if (0 < id) {
299
285
  assure_size(out, size + 16);
300
286
  fill_indent(out, depth + 1);
301
- *out->cur++ = '"';
302
- *out->cur++ = '^';
303
- *out->cur++ = 'i';
304
- *out->cur++ = '"';
305
- *out->cur++ = ':';
287
+ APPEND_CHARS(out->cur, "\"^i\":", 5);
306
288
  dump_ulong(id, out);
307
289
  *out->cur++ = ',';
308
290
  }
@@ -318,15 +300,13 @@ static void dump_hash_class(VALUE obj, VALUE clas, int depth, Out out) {
318
300
  size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
319
301
  assure_size(out, size);
320
302
  if (0 < out->opts->dump_opts.hash_size) {
321
- strcpy(out->cur, out->opts->dump_opts.hash_nl);
322
- 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);
323
304
  }
324
305
  if (0 < out->opts->dump_opts.indent_size) {
325
306
  int i;
326
307
 
327
308
  for (i = depth; 0 < i; i--) {
328
- strcpy(out->cur, out->opts->dump_opts.indent_str);
329
- 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);
330
310
  }
331
311
  }
332
312
  }
@@ -335,14 +315,13 @@ static void dump_hash_class(VALUE obj, VALUE clas, int depth, Out out) {
335
315
  *out->cur = '\0';
336
316
  }
337
317
 
338
- #ifdef HAVE_RB_IVAR_FOREACH
339
318
  static int dump_attr_cb(ID key, VALUE value, VALUE ov) {
340
319
  Out out = (Out)ov;
341
320
  int depth = out->depth;
342
321
  size_t size = depth * out->indent + 1;
343
322
  const char *attr = rb_id2name(key);
344
323
 
345
- if (oj_dump_ignore(out->opts, value)) {
324
+ if (dump_ignore(out->opts, value)) {
346
325
  return ST_CONTINUE;
347
326
  }
348
327
  if (out->omit_nil && Qnil == value) {
@@ -378,17 +357,16 @@ static int dump_attr_cb(ID key, VALUE value, VALUE ov) {
378
357
 
379
358
  return ST_CONTINUE;
380
359
  }
381
- #endif
382
360
 
383
361
  static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
384
362
  dump_hash_class(obj, rb_obj_class(obj), depth, out);
385
363
  }
386
364
 
387
365
  static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
388
- ID * idp;
389
- AttrGetFunc * fp;
366
+ ID *idp;
367
+ AttrGetFunc *fp;
390
368
  volatile VALUE v;
391
- const char * name;
369
+ const char *name;
392
370
  size_t size;
393
371
  int d2 = depth + 1;
394
372
 
@@ -401,11 +379,7 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
401
379
  size = d2 * out->indent + clen + 10;
402
380
  assure_size(out, size);
403
381
  fill_indent(out, d2);
404
- *out->cur++ = '"';
405
- *out->cur++ = '^';
406
- *out->cur++ = 'O';
407
- *out->cur++ = '"';
408
- *out->cur++ = ':';
382
+ APPEND_CHARS(out->cur, "\"^O\":", 5);
409
383
  oj_dump_cstr(class_name, clen, 0, 0, out);
410
384
  *out->cur++ = ',';
411
385
  }
@@ -423,12 +397,9 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
423
397
  assure_size(out, size);
424
398
  fill_indent(out, d2);
425
399
  *out->cur++ = '"';
426
- memcpy(out->cur, name, nlen);
427
- out->cur += nlen;
428
- *out->cur++ = '"';
429
- *out->cur++ = ':';
430
- memcpy(out->cur, s, len);
431
- out->cur += len;
400
+ APPEND_CHARS(out->cur, name, nlen);
401
+ APPEND_CHARS(out->cur, "\":", 2);
402
+ APPEND_CHARS(out->cur, s, len);
432
403
  *out->cur = '\0';
433
404
  }
434
405
  } else {
@@ -439,7 +410,7 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
439
410
  assure_size(out, size);
440
411
  name = rb_id2name(*idp);
441
412
  nlen = strlen(name);
442
- if (0 != *fp) {
413
+ if (NULL != *fp) {
443
414
  v = (*fp)(obj);
444
415
  } else if (0 == strchr(name, '.')) {
445
416
  v = rb_funcall(obj, *idp, 0);
@@ -451,7 +422,7 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
451
422
  ID i;
452
423
 
453
424
  if (sizeof(nbuf) <= nlen) {
454
- if (NULL == (n2 = strdup(name))) {
425
+ if (NULL == (n2 = OJ_STRDUP(name))) {
455
426
  rb_raise(rb_eNoMemError, "for attribute name.");
456
427
  }
457
428
  } else {
@@ -468,7 +439,7 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
468
439
  i = rb_intern(n);
469
440
  v = rb_funcall(v, i, 0);
470
441
  if (nbuf != n2) {
471
- free(n2);
442
+ OJ_FREE(n2);
472
443
  }
473
444
  }
474
445
  fill_indent(out, d2);
@@ -502,22 +473,14 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
502
473
 
503
474
  assure_size(out, d2 * out->indent + clen + 10);
504
475
  fill_indent(out, d2);
505
- *out->cur++ = '"';
506
- *out->cur++ = '^';
507
- *out->cur++ = 'o';
508
- *out->cur++ = '"';
509
- *out->cur++ = ':';
476
+ APPEND_CHARS(out->cur, "\"^o\":", 5);
510
477
  oj_dump_cstr(class_name, clen, 0, 0, out);
511
478
  }
512
479
  if (0 < id) {
513
480
  assure_size(out, d2 * out->indent + 16);
514
481
  *out->cur++ = ',';
515
482
  fill_indent(out, d2);
516
- *out->cur++ = '"';
517
- *out->cur++ = '^';
518
- *out->cur++ = 'i';
519
- *out->cur++ = '"';
520
- *out->cur++ = ':';
483
+ APPEND_CHARS(out->cur, "\"^i\":", 5);
521
484
  dump_ulong(id, out);
522
485
  }
523
486
  switch (type) {
@@ -525,57 +488,28 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
525
488
  assure_size(out, d2 * out->indent + 14);
526
489
  *out->cur++ = ',';
527
490
  fill_indent(out, d2);
528
- *out->cur++ = '"';
529
- *out->cur++ = 's';
530
- *out->cur++ = 'e';
531
- *out->cur++ = 'l';
532
- *out->cur++ = 'f';
533
- *out->cur++ = '"';
534
- *out->cur++ = ':';
491
+ APPEND_CHARS(out->cur, "\"self\":", 7);
535
492
  oj_dump_cstr(RSTRING_PTR(obj), (int)RSTRING_LEN(obj), 0, 0, out);
536
493
  break;
537
494
  case T_ARRAY:
538
495
  assure_size(out, d2 * out->indent + 14);
539
496
  *out->cur++ = ',';
540
497
  fill_indent(out, d2);
541
- *out->cur++ = '"';
542
- *out->cur++ = 's';
543
- *out->cur++ = 'e';
544
- *out->cur++ = 'l';
545
- *out->cur++ = 'f';
546
- *out->cur++ = '"';
547
- *out->cur++ = ':';
498
+ APPEND_CHARS(out->cur, "\"self\":", 7);
548
499
  dump_array_class(obj, Qundef, depth + 1, out);
549
500
  break;
550
501
  case T_HASH:
551
502
  assure_size(out, d2 * out->indent + 14);
552
503
  *out->cur++ = ',';
553
504
  fill_indent(out, d2);
554
- *out->cur++ = '"';
555
- *out->cur++ = 's';
556
- *out->cur++ = 'e';
557
- *out->cur++ = 'l';
558
- *out->cur++ = 'f';
559
- *out->cur++ = '"';
560
- *out->cur++ = ':';
505
+ APPEND_CHARS(out->cur, "\"self\":", 7);
561
506
  dump_hash_class(obj, Qundef, depth + 1, out);
562
507
  break;
563
508
  default: break;
564
509
  }
565
510
  {
566
- int cnt;
567
- #ifdef HAVE_RB_IVAR_COUNT
568
- cnt = (int)rb_ivar_count(obj);
569
- #else
570
- volatile VALUE vars = rb_funcall2(obj, oj_instance_variables_id, 0, 0);
571
- VALUE * np = RARRAY_PTR(vars);
572
- ID vid;
573
- const char * attr;
574
- int i;
575
- int first = 1;
576
-
577
- cnt = (int)RARRAY_LEN(vars);
578
- #endif
511
+ int cnt = (int)rb_ivar_count(obj);
512
+
579
513
  if (Qundef != clas && 0 < cnt) {
580
514
  *out->cur++ = ',';
581
515
  }
@@ -588,52 +522,10 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
588
522
  }
589
523
  }
590
524
  out->depth = depth + 1;
591
- #ifdef HAVE_RB_IVAR_FOREACH
592
525
  rb_ivar_foreach(obj, dump_attr_cb, (VALUE)out);
593
526
  if (',' == *(out->cur - 1)) {
594
527
  out->cur--; // backup to overwrite last comma
595
528
  }
596
- #else
597
- size = d2 * out->indent + 1;
598
- for (i = cnt; 0 < i; i--, np++) {
599
- VALUE value;
600
-
601
- vid = rb_to_id(*np);
602
- attr = rb_id2name(vid);
603
- if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
604
- continue;
605
- }
606
- value = rb_ivar_get(obj, vid);
607
-
608
- if (oj_dump_ignore(out->opts, value)) {
609
- continue;
610
- }
611
- if (out->omit_nil && Qnil == value) {
612
- continue;
613
- }
614
- if (first) {
615
- first = 0;
616
- } else {
617
- *out->cur++ = ',';
618
- }
619
- assure_size(out, size);
620
- fill_indent(out, d2);
621
- if ('@' == *attr) {
622
- attr++;
623
- oj_dump_cstr(attr, strlen(attr), 0, 0, out);
624
- } else {
625
- char buf[32];
626
-
627
- *buf = '~';
628
- strncpy(buf + 1, attr, sizeof(buf) - 2);
629
- buf[sizeof(buf) - 1] = '\0';
630
- oj_dump_cstr(buf, strlen(attr) + 1, 0, 0, out);
631
- }
632
- *out->cur++ = ':';
633
- oj_dump_obj_val(value, d2, out);
634
- assure_size(out, 2);
635
- }
636
- #endif
637
529
  if (rb_obj_is_kind_of(obj, rb_eException)) {
638
530
  volatile VALUE rv;
639
531
 
@@ -681,12 +573,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
681
573
  assure_size(out, size);
682
574
  *out->cur++ = '{';
683
575
  fill_indent(out, d2);
684
- *out->cur++ = '"';
685
- *out->cur++ = '^';
686
- *out->cur++ = 'u';
687
- *out->cur++ = '"';
688
- *out->cur++ = ':';
689
- *out->cur++ = '[';
576
+ APPEND_CHARS(out->cur, "\"^u\":[", 6);
690
577
  if ('#' == *class_name) {
691
578
  VALUE ma = rb_struct_s_members(clas);
692
579
  const char *name;
@@ -694,7 +581,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
694
581
 
695
582
  *out->cur++ = '[';
696
583
  for (i = 0; i < cnt; i++) {
697
- volatile VALUE s = rb_sym2str(rb_ary_entry(ma, i));
584
+ volatile VALUE s = rb_sym2str(RARRAY_AREF(ma, i));
698
585
 
699
586
  name = RSTRING_PTR(s);
700
587
  len = (int)RSTRING_LEN(s);
@@ -704,16 +591,14 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
704
591
  *out->cur++ = ',';
705
592
  }
706
593
  *out->cur++ = '"';
707
- memcpy(out->cur, name, len);
708
- out->cur += len;
594
+ APPEND_CHARS(out->cur, name, len);
709
595
  *out->cur++ = '"';
710
596
  }
711
597
  *out->cur++ = ']';
712
598
  } else {
713
599
  fill_indent(out, d3);
714
600
  *out->cur++ = '"';
715
- memcpy(out->cur, class_name, len);
716
- out->cur += len;
601
+ APPEND_CHARS(out->cur, class_name, len);
717
602
  *out->cur++ = '"';
718
603
  }
719
604
  *out->cur++ = ',';
@@ -730,7 +615,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
730
615
 
731
616
  for (i = 0; i < cnt; i++) {
732
617
  v = RSTRUCT_GET(obj, i);
733
- if (oj_dump_ignore(out->opts, v)) {
618
+ if (dump_ignore(out->opts, v)) {
734
619
  v = Qnil;
735
620
  }
736
621
  assure_size(out, size);
@@ -748,7 +633,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
748
633
  for (i = 0; i < slen; i++) {
749
634
  assure_size(out, size);
750
635
  fill_indent(out, d3);
751
- if (oj_dump_ignore(out->opts, v)) {
636
+ if (dump_ignore(out->opts, v)) {
752
637
  v = Qnil;
753
638
  }
754
639
  oj_dump_obj_val(rb_struct_aref(obj, INT2FIX(i)), d3, out, 0, 0, true);
@@ -757,9 +642,8 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
757
642
  }
758
643
  #endif
759
644
  out->cur--;
760
- *out->cur++ = ']';
761
- *out->cur++ = '}';
762
- *out->cur = '\0';
645
+ APPEND_CHARS(out->cur, "]}", 2);
646
+ *out->cur = '\0';
763
647
  }
764
648
 
765
649
  static void dump_complex(VALUE obj, int depth, Out out, bool as_ok) {
@@ -798,9 +682,7 @@ static DumpFunc obj_funcs[] = {
798
682
  void oj_dump_obj_val(VALUE obj, int depth, Out out) {
799
683
  int type = rb_type(obj);
800
684
 
801
- if (Yes == out->opts->trace) {
802
- oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
803
- }
685
+ TRACE(out->opts->trace, "dump", obj, depth, TraceIn);
804
686
  if (MAX_DEPTH < depth) {
805
687
  rb_raise(rb_eNoMemError, "Too deeply nested.\n");
806
688
  }
@@ -809,14 +691,10 @@ void oj_dump_obj_val(VALUE obj, int depth, Out out) {
809
691
 
810
692
  if (NULL != f) {
811
693
  f(obj, depth, out, false);
812
- if (Yes == out->opts->trace) {
813
- oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
814
- }
694
+ TRACE(out->opts->trace, "dump", obj, depth, TraceOut);
815
695
  return;
816
696
  }
817
697
  }
818
698
  oj_dump_nil(Qnil, depth, out, false);
819
- if (Yes == out->opts->trace) {
820
- oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
821
- }
699
+ TRACE(out->opts->trace, "dump", Qnil, depth, TraceOut);
822
700
  }