oj 3.10.7

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 (167) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +104 -0
  4. data/ext/oj/buf.h +103 -0
  5. data/ext/oj/cache8.c +107 -0
  6. data/ext/oj/cache8.h +48 -0
  7. data/ext/oj/circarray.c +68 -0
  8. data/ext/oj/circarray.h +23 -0
  9. data/ext/oj/code.c +235 -0
  10. data/ext/oj/code.h +42 -0
  11. data/ext/oj/compat.c +299 -0
  12. data/ext/oj/custom.c +1218 -0
  13. data/ext/oj/dump.c +1249 -0
  14. data/ext/oj/dump.h +96 -0
  15. data/ext/oj/dump_compat.c +975 -0
  16. data/ext/oj/dump_leaf.c +252 -0
  17. data/ext/oj/dump_object.c +844 -0
  18. data/ext/oj/dump_strict.c +434 -0
  19. data/ext/oj/encode.h +45 -0
  20. data/ext/oj/err.c +57 -0
  21. data/ext/oj/err.h +70 -0
  22. data/ext/oj/extconf.rb +53 -0
  23. data/ext/oj/fast.c +1771 -0
  24. data/ext/oj/hash.c +163 -0
  25. data/ext/oj/hash.h +46 -0
  26. data/ext/oj/hash_test.c +512 -0
  27. data/ext/oj/mimic_json.c +890 -0
  28. data/ext/oj/object.c +775 -0
  29. data/ext/oj/odd.c +231 -0
  30. data/ext/oj/odd.h +44 -0
  31. data/ext/oj/oj.c +1723 -0
  32. data/ext/oj/oj.h +387 -0
  33. data/ext/oj/parse.c +1134 -0
  34. data/ext/oj/parse.h +112 -0
  35. data/ext/oj/rails.c +1528 -0
  36. data/ext/oj/rails.h +21 -0
  37. data/ext/oj/reader.c +231 -0
  38. data/ext/oj/reader.h +151 -0
  39. data/ext/oj/resolve.c +102 -0
  40. data/ext/oj/resolve.h +14 -0
  41. data/ext/oj/rxclass.c +147 -0
  42. data/ext/oj/rxclass.h +27 -0
  43. data/ext/oj/saj.c +714 -0
  44. data/ext/oj/scp.c +224 -0
  45. data/ext/oj/sparse.c +924 -0
  46. data/ext/oj/stream_writer.c +363 -0
  47. data/ext/oj/strict.c +212 -0
  48. data/ext/oj/string_writer.c +534 -0
  49. data/ext/oj/trace.c +79 -0
  50. data/ext/oj/trace.h +28 -0
  51. data/ext/oj/util.c +136 -0
  52. data/ext/oj/util.h +19 -0
  53. data/ext/oj/val_stack.c +118 -0
  54. data/ext/oj/val_stack.h +185 -0
  55. data/ext/oj/wab.c +631 -0
  56. data/lib/oj.rb +21 -0
  57. data/lib/oj/active_support_helper.rb +41 -0
  58. data/lib/oj/bag.rb +88 -0
  59. data/lib/oj/easy_hash.rb +52 -0
  60. data/lib/oj/error.rb +22 -0
  61. data/lib/oj/json.rb +176 -0
  62. data/lib/oj/mimic.rb +267 -0
  63. data/lib/oj/saj.rb +66 -0
  64. data/lib/oj/schandler.rb +142 -0
  65. data/lib/oj/state.rb +131 -0
  66. data/lib/oj/version.rb +5 -0
  67. data/pages/Advanced.md +22 -0
  68. data/pages/Compatibility.md +25 -0
  69. data/pages/Custom.md +23 -0
  70. data/pages/Encoding.md +65 -0
  71. data/pages/JsonGem.md +79 -0
  72. data/pages/Modes.md +155 -0
  73. data/pages/Options.md +287 -0
  74. data/pages/Rails.md +155 -0
  75. data/pages/Security.md +20 -0
  76. data/pages/WAB.md +13 -0
  77. data/test/_test_active.rb +76 -0
  78. data/test/_test_active_mimic.rb +96 -0
  79. data/test/_test_mimic_rails.rb +126 -0
  80. data/test/activerecord/result_test.rb +27 -0
  81. data/test/activesupport4/decoding_test.rb +108 -0
  82. data/test/activesupport4/encoding_test.rb +531 -0
  83. data/test/activesupport4/test_helper.rb +41 -0
  84. data/test/activesupport5/abstract_unit.rb +45 -0
  85. data/test/activesupport5/decoding_test.rb +133 -0
  86. data/test/activesupport5/encoding_test.rb +500 -0
  87. data/test/activesupport5/encoding_test_cases.rb +98 -0
  88. data/test/activesupport5/test_helper.rb +72 -0
  89. data/test/activesupport5/time_zone_test_helpers.rb +39 -0
  90. data/test/activesupport6/abstract_unit.rb +44 -0
  91. data/test/activesupport6/decoding_test.rb +133 -0
  92. data/test/activesupport6/encoding_test.rb +507 -0
  93. data/test/activesupport6/encoding_test_cases.rb +98 -0
  94. data/test/activesupport6/test_common.rb +17 -0
  95. data/test/activesupport6/test_helper.rb +163 -0
  96. data/test/activesupport6/time_zone_test_helpers.rb +39 -0
  97. data/test/bar.rb +35 -0
  98. data/test/baz.rb +16 -0
  99. data/test/files.rb +29 -0
  100. data/test/foo.rb +52 -0
  101. data/test/helper.rb +26 -0
  102. data/test/isolated/shared.rb +308 -0
  103. data/test/isolated/test_mimic_after.rb +13 -0
  104. data/test/isolated/test_mimic_alone.rb +12 -0
  105. data/test/isolated/test_mimic_as_json.rb +45 -0
  106. data/test/isolated/test_mimic_before.rb +13 -0
  107. data/test/isolated/test_mimic_define.rb +28 -0
  108. data/test/isolated/test_mimic_rails_after.rb +22 -0
  109. data/test/isolated/test_mimic_rails_before.rb +21 -0
  110. data/test/isolated/test_mimic_redefine.rb +15 -0
  111. data/test/json_gem/json_addition_test.rb +216 -0
  112. data/test/json_gem/json_common_interface_test.rb +148 -0
  113. data/test/json_gem/json_encoding_test.rb +107 -0
  114. data/test/json_gem/json_ext_parser_test.rb +20 -0
  115. data/test/json_gem/json_fixtures_test.rb +35 -0
  116. data/test/json_gem/json_generator_test.rb +383 -0
  117. data/test/json_gem/json_generic_object_test.rb +90 -0
  118. data/test/json_gem/json_parser_test.rb +470 -0
  119. data/test/json_gem/json_string_matching_test.rb +42 -0
  120. data/test/json_gem/test_helper.rb +18 -0
  121. data/test/perf.rb +107 -0
  122. data/test/perf_compat.rb +130 -0
  123. data/test/perf_fast.rb +164 -0
  124. data/test/perf_file.rb +64 -0
  125. data/test/perf_object.rb +138 -0
  126. data/test/perf_saj.rb +109 -0
  127. data/test/perf_scp.rb +151 -0
  128. data/test/perf_simple.rb +287 -0
  129. data/test/perf_strict.rb +145 -0
  130. data/test/perf_wab.rb +131 -0
  131. data/test/prec.rb +23 -0
  132. data/test/sample.rb +54 -0
  133. data/test/sample/change.rb +14 -0
  134. data/test/sample/dir.rb +19 -0
  135. data/test/sample/doc.rb +36 -0
  136. data/test/sample/file.rb +48 -0
  137. data/test/sample/group.rb +16 -0
  138. data/test/sample/hasprops.rb +16 -0
  139. data/test/sample/layer.rb +12 -0
  140. data/test/sample/line.rb +20 -0
  141. data/test/sample/oval.rb +10 -0
  142. data/test/sample/rect.rb +10 -0
  143. data/test/sample/shape.rb +35 -0
  144. data/test/sample/text.rb +20 -0
  145. data/test/sample_json.rb +37 -0
  146. data/test/test_compat.rb +502 -0
  147. data/test/test_custom.rb +527 -0
  148. data/test/test_debian.rb +53 -0
  149. data/test/test_fast.rb +470 -0
  150. data/test/test_file.rb +239 -0
  151. data/test/test_gc.rb +49 -0
  152. data/test/test_hash.rb +29 -0
  153. data/test/test_integer_range.rb +72 -0
  154. data/test/test_null.rb +376 -0
  155. data/test/test_object.rb +1027 -0
  156. data/test/test_rails.rb +26 -0
  157. data/test/test_saj.rb +186 -0
  158. data/test/test_scp.rb +433 -0
  159. data/test/test_strict.rb +433 -0
  160. data/test/test_various.rb +719 -0
  161. data/test/test_wab.rb +307 -0
  162. data/test/test_writer.rb +380 -0
  163. data/test/tests.rb +25 -0
  164. data/test/tests_mimic.rb +14 -0
  165. data/test/tests_mimic_addition.rb +7 -0
  166. data/test/zoo.rb +13 -0
  167. metadata +381 -0
@@ -0,0 +1,252 @@
1
+ /* dump_leaf.c
2
+ * Copyright (c) 2012, 2017, Peter Ohler
3
+ * All rights reserved.
4
+ */
5
+
6
+ #include <errno.h>
7
+
8
+ #include "oj.h"
9
+ #include "dump.h"
10
+
11
+ static void dump_leaf(Leaf leaf, int depth, Out out);
12
+
13
+ static void
14
+ grow(Out out, size_t len) {
15
+ size_t size = out->end - out->buf;
16
+ long pos = out->cur - out->buf;
17
+ char *buf;
18
+
19
+ size *= 2;
20
+ if (size <= len * 2 + pos) {
21
+ size += len;
22
+ }
23
+ if (out->allocated) {
24
+ buf = REALLOC_N(out->buf, char, (size + BUFFER_EXTRA));
25
+ } else {
26
+ buf = ALLOC_N(char, (size + BUFFER_EXTRA));
27
+ out->allocated = true;
28
+ memcpy(buf, out->buf, out->end - out->buf + BUFFER_EXTRA);
29
+ }
30
+ if (0 == buf) {
31
+ rb_raise(rb_eNoMemError, "Failed to create string. [%d:%s]\n", ENOSPC, strerror(ENOSPC));
32
+ }
33
+ out->buf = buf;
34
+ out->end = buf + size;
35
+ out->cur = out->buf + pos;
36
+ }
37
+
38
+
39
+ inline static void
40
+ dump_chars(const char *s, size_t size, Out out) {
41
+ if (out->end - out->cur <= (long)size) {
42
+ grow(out, size);
43
+ }
44
+ memcpy(out->cur, s, size);
45
+ out->cur += size;
46
+ *out->cur = '\0';
47
+ }
48
+
49
+ static void
50
+ dump_leaf_str(Leaf leaf, Out out) {
51
+ switch (leaf->value_type) {
52
+ case STR_VAL:
53
+ oj_dump_cstr(leaf->str, strlen(leaf->str), 0, 0, out);
54
+ break;
55
+ case RUBY_VAL:
56
+ oj_dump_cstr(rb_string_value_cstr(&leaf->value), (int)RSTRING_LEN(leaf->value), 0, 0, out);
57
+ break;
58
+ case COL_VAL:
59
+ default:
60
+ rb_raise(rb_eTypeError, "Unexpected value type %02x.\n", leaf->value_type);
61
+ break;
62
+ }
63
+ }
64
+
65
+ static void
66
+ dump_leaf_fixnum(Leaf leaf, Out out) {
67
+ switch (leaf->value_type) {
68
+ case STR_VAL:
69
+ dump_chars(leaf->str, strlen(leaf->str), out);
70
+ break;
71
+ case RUBY_VAL:
72
+ if (T_BIGNUM == rb_type(leaf->value)) {
73
+ oj_dump_bignum(leaf->value, 0, out, false);
74
+ } else {
75
+ oj_dump_fixnum(leaf->value, 0, out, false);
76
+ }
77
+ break;
78
+ case COL_VAL:
79
+ default:
80
+ rb_raise(rb_eTypeError, "Unexpected value type %02x.\n", leaf->value_type);
81
+ break;
82
+ }
83
+ }
84
+
85
+ static void
86
+ dump_leaf_float(Leaf leaf, Out out) {
87
+ switch (leaf->value_type) {
88
+ case STR_VAL:
89
+ dump_chars(leaf->str, strlen(leaf->str), out);
90
+ break;
91
+ case RUBY_VAL:
92
+ oj_dump_float(leaf->value, 0, out, false);
93
+ break;
94
+ case COL_VAL:
95
+ default:
96
+ rb_raise(rb_eTypeError, "Unexpected value type %02x.\n", leaf->value_type);
97
+ break;
98
+ }
99
+ }
100
+
101
+ static void
102
+ dump_leaf_array(Leaf leaf, int depth, Out out) {
103
+ size_t size;
104
+ int d2 = depth + 1;
105
+
106
+ size = 2;
107
+ if (out->end - out->cur <= (long)size) {
108
+ grow(out, size);
109
+ }
110
+ *out->cur++ = '[';
111
+ if (0 == leaf->elements) {
112
+ *out->cur++ = ']';
113
+ } else {
114
+ Leaf first = leaf->elements->next;
115
+ Leaf e = first;
116
+
117
+ size = d2 * out->indent + 2;
118
+ do {
119
+ if (out->end - out->cur <= (long)size) {
120
+ grow(out, size);
121
+ }
122
+ fill_indent(out, d2);
123
+ dump_leaf(e, d2, out);
124
+ if (e->next != first) {
125
+ *out->cur++ = ',';
126
+ }
127
+ e = e->next;
128
+ } while (e != first);
129
+ size = depth * out->indent + 1;
130
+ if (out->end - out->cur <= (long)size) {
131
+ grow(out, size);
132
+ }
133
+ fill_indent(out, depth);
134
+ *out->cur++ = ']';
135
+ }
136
+ *out->cur = '\0';
137
+ }
138
+
139
+ static void
140
+ dump_leaf_hash(Leaf leaf, int depth, Out out) {
141
+ size_t size;
142
+ int d2 = depth + 1;
143
+
144
+ size = 2;
145
+ if (out->end - out->cur <= (long)size) {
146
+ grow(out, size);
147
+ }
148
+ *out->cur++ = '{';
149
+ if (0 == leaf->elements) {
150
+ *out->cur++ = '}';
151
+ } else {
152
+ Leaf first = leaf->elements->next;
153
+ Leaf e = first;
154
+
155
+ size = d2 * out->indent + 2;
156
+ do {
157
+ if (out->end - out->cur <= (long)size) {
158
+ grow(out, size);
159
+ }
160
+ fill_indent(out, d2);
161
+ oj_dump_cstr(e->key, strlen(e->key), 0, 0, out);
162
+ *out->cur++ = ':';
163
+ dump_leaf(e, d2, out);
164
+ if (e->next != first) {
165
+ *out->cur++ = ',';
166
+ }
167
+ e = e->next;
168
+ } while (e != first);
169
+ size = depth * out->indent + 1;
170
+ if (out->end - out->cur <= (long)size) {
171
+ grow(out, size);
172
+ }
173
+ fill_indent(out, depth);
174
+ *out->cur++ = '}';
175
+ }
176
+ *out->cur = '\0';
177
+ }
178
+
179
+ static void
180
+ dump_leaf(Leaf leaf, int depth, Out out) {
181
+ switch (leaf->rtype) {
182
+ case T_NIL:
183
+ oj_dump_nil(Qnil, 0, out, false);
184
+ break;
185
+ case T_TRUE:
186
+ oj_dump_true(Qtrue, 0, out, false);
187
+ break;
188
+ case T_FALSE:
189
+ oj_dump_false(Qfalse, 0, out, false);
190
+ break;
191
+ case T_STRING:
192
+ dump_leaf_str(leaf, out);
193
+ break;
194
+ case T_FIXNUM:
195
+ dump_leaf_fixnum(leaf, out);
196
+ break;
197
+ case T_FLOAT:
198
+ dump_leaf_float(leaf, out);
199
+ break;
200
+ case T_ARRAY:
201
+ dump_leaf_array(leaf, depth, out);
202
+ break;
203
+ case T_HASH:
204
+ dump_leaf_hash(leaf, depth, out);
205
+ break;
206
+ default:
207
+ rb_raise(rb_eTypeError, "Unexpected type %02x.\n", leaf->rtype);
208
+ break;
209
+ }
210
+ }
211
+
212
+ void
213
+ oj_dump_leaf_to_json(Leaf leaf, Options copts, Out out) {
214
+ if (0 == out->buf) {
215
+ out->buf = ALLOC_N(char, 4096);
216
+ out->end = out->buf + 4095 - BUFFER_EXTRA; // 1 less than end plus extra for possible errors
217
+ out->allocated = true;
218
+ }
219
+ out->cur = out->buf;
220
+ out->circ_cnt = 0;
221
+ out->opts = copts;
222
+ out->hash_cnt = 0;
223
+ out->indent = copts->indent;
224
+ dump_leaf(leaf, 0, out);
225
+ }
226
+
227
+ void
228
+ oj_write_leaf_to_file(Leaf leaf, const char *path, Options copts) {
229
+ char buf[4096];
230
+ struct _out out;
231
+ size_t size;
232
+ FILE *f;
233
+
234
+ out.buf = buf;
235
+ out.end = buf + sizeof(buf) - BUFFER_EXTRA;
236
+ out.allocated = false;
237
+ out.omit_nil = copts->dump_opts.omit_nil;
238
+ oj_dump_leaf_to_json(leaf, copts, &out);
239
+ size = out.cur - out.buf;
240
+ if (0 == (f = fopen(path, "w"))) {
241
+ rb_raise(rb_eIOError, "%s\n", strerror(errno));
242
+ }
243
+ if (size != fwrite(out.buf, 1, size, f)) {
244
+ int err = ferror(f);
245
+
246
+ rb_raise(rb_eIOError, "Write failed. [%d:%s]\n", err, strerror(err));
247
+ }
248
+ if (out.allocated) {
249
+ xfree(out.buf);
250
+ }
251
+ fclose(f);
252
+ }
@@ -0,0 +1,844 @@
1
+ /* dump_object.c
2
+ * Copyright (c) 2012, 2017, Peter Ohler
3
+ * All rights reserved.
4
+ */
5
+
6
+ #include "dump.h"
7
+ #include "odd.h"
8
+ #include "trace.h"
9
+
10
+ static const char hex_chars[17] = "0123456789abcdef";
11
+
12
+ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out);
13
+
14
+ static void
15
+ dump_time(VALUE obj, Out out) {
16
+ switch (out->opts->time_format) {
17
+ case RubyTime:
18
+ case XmlTime: oj_dump_xml_time(obj, out); break;
19
+ case UnixZTime: oj_dump_time(obj, out, 1); break;
20
+ case UnixTime:
21
+ default: oj_dump_time(obj, out, 0); break;
22
+ }
23
+ }
24
+
25
+ static void
26
+ dump_data(VALUE obj, int depth, Out out, bool as_ok) {
27
+ VALUE clas = rb_obj_class(obj);
28
+
29
+ if (rb_cTime == clas) {
30
+ assure_size(out, 6);
31
+ *out->cur++ = '{';
32
+ *out->cur++ = '"';
33
+ *out->cur++ = '^';
34
+ *out->cur++ = 't';
35
+ *out->cur++ = '"';
36
+ *out->cur++ = ':';
37
+ dump_time(obj, out);
38
+ *out->cur++ = '}';
39
+ *out->cur = '\0';
40
+ } else {
41
+ if (oj_bigdecimal_class == clas) {
42
+ volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
43
+ const char *str = rb_string_value_ptr((VALUE*)&rstr);
44
+ int len = (int)RSTRING_LEN(rstr);
45
+
46
+ if (No != out->opts->bigdec_as_num) {
47
+ oj_dump_raw(str, len, out);
48
+ } else if (0 == strcasecmp("Infinity", str)) {
49
+ str = oj_nan_str(obj, out->opts->dump_opts.nan_dump, out->opts->mode, true, &len);
50
+ oj_dump_raw(str, len, out);
51
+ } else if (0 == strcasecmp("-Infinity", str)) {
52
+ str = oj_nan_str(obj, out->opts->dump_opts.nan_dump, out->opts->mode, false, &len);
53
+ oj_dump_raw(str, len, out);
54
+ } else {
55
+ oj_dump_cstr(str, len, 0, 0, out);
56
+ }
57
+ } else {
58
+ long id = oj_check_circular(obj, out);
59
+
60
+ if (0 <= id) {
61
+ dump_obj_attrs(obj, clas, id, depth, out);
62
+ }
63
+ }
64
+ }
65
+ }
66
+
67
+ static void
68
+ dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
69
+ VALUE clas = rb_obj_class(obj);
70
+
71
+ if (oj_bigdecimal_class == clas) {
72
+ volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
73
+ const char *str = rb_string_value_ptr((VALUE*)&rstr);
74
+ int len = (int)RSTRING_LEN(rstr);
75
+
76
+ if (0 == strcasecmp("Infinity", str)) {
77
+ str = oj_nan_str(obj, out->opts->dump_opts.nan_dump, out->opts->mode, true, &len);
78
+ oj_dump_raw(str, len, out);
79
+ } else if (0 == strcasecmp("-Infinity", str)) {
80
+ str = oj_nan_str(obj, out->opts->dump_opts.nan_dump, out->opts->mode, false, &len);
81
+ oj_dump_raw(str, len, out);
82
+ } else {
83
+ oj_dump_raw(str, len, out);
84
+ }
85
+ } else {
86
+ long id = oj_check_circular(obj, out);
87
+
88
+ if (0 <= id) {
89
+ dump_obj_attrs(obj, clas, id, depth, out);
90
+ }
91
+ }
92
+ }
93
+
94
+ static void
95
+ dump_class(VALUE obj, int depth, Out out, bool as_ok) {
96
+ const char *s = rb_class2name(obj);
97
+ size_t len = strlen(s);
98
+
99
+ assure_size(out, 6);
100
+ *out->cur++ = '{';
101
+ *out->cur++ = '"';
102
+ *out->cur++ = '^';
103
+ *out->cur++ = 'c';
104
+ *out->cur++ = '"';
105
+ *out->cur++ = ':';
106
+ oj_dump_cstr(s, len, 0, 0, out);
107
+ *out->cur++ = '}';
108
+ *out->cur = '\0';
109
+ }
110
+
111
+ static void
112
+ dump_array_class(VALUE a, VALUE clas, int depth, Out out) {
113
+ size_t size;
114
+ int i, cnt;
115
+ int d2 = depth + 1;
116
+ long id = oj_check_circular(a, out);
117
+
118
+ if (id < 0) {
119
+ return;
120
+ }
121
+ if (Qundef != clas && rb_cArray != clas && ObjectMode == out->opts->mode) {
122
+ dump_obj_attrs(a, clas, 0, depth, out);
123
+ return;
124
+ }
125
+ cnt = (int)RARRAY_LEN(a);
126
+ *out->cur++ = '[';
127
+ if (0 < id) {
128
+ assure_size(out, d2 * out->indent + 16);
129
+ fill_indent(out, d2);
130
+ *out->cur++ = '"';
131
+ *out->cur++ = '^';
132
+ *out->cur++ = 'i';
133
+ dump_ulong(id, out);
134
+ *out->cur++ = '"';
135
+ }
136
+ size = 2;
137
+ assure_size(out, 2);
138
+ if (0 == cnt) {
139
+ *out->cur++ = ']';
140
+ } else {
141
+ if (0 < id) {
142
+ *out->cur++ = ',';
143
+ }
144
+ if (out->opts->dump_opts.use) {
145
+ size = d2 * out->opts->dump_opts.indent_size + out->opts->dump_opts.array_size + 1;
146
+ } else {
147
+ size = d2 * out->indent + 2;
148
+ }
149
+ cnt--;
150
+ for (i = 0; i <= cnt; i++) {
151
+ assure_size(out, size);
152
+ if (out->opts->dump_opts.use) {
153
+ if (0 < out->opts->dump_opts.array_size) {
154
+ strcpy(out->cur, out->opts->dump_opts.array_nl);
155
+ out->cur += out->opts->dump_opts.array_size;
156
+ }
157
+ if (0 < out->opts->dump_opts.indent_size) {
158
+ int i;
159
+ for (i = d2; 0 < i; i--) {
160
+ strcpy(out->cur, out->opts->dump_opts.indent_str);
161
+ out->cur += out->opts->dump_opts.indent_size;
162
+ }
163
+ }
164
+ } else {
165
+ fill_indent(out, d2);
166
+ }
167
+ oj_dump_obj_val(rb_ary_entry(a, i), d2, out);
168
+ if (i < cnt) {
169
+ *out->cur++ = ',';
170
+ }
171
+ }
172
+ size = depth * out->indent + 1;
173
+ assure_size(out, size);
174
+ if (out->opts->dump_opts.use) {
175
+ //printf("*** d2: %u indent: %u '%s'\n", d2, out->opts->dump_opts->indent_size, out->opts->dump_opts->indent);
176
+ if (0 < out->opts->dump_opts.array_size) {
177
+ strcpy(out->cur, out->opts->dump_opts.array_nl);
178
+ out->cur += out->opts->dump_opts.array_size;
179
+ }
180
+ if (0 < out->opts->dump_opts.indent_size) {
181
+ int i;
182
+
183
+ for (i = depth; 0 < i; i--) {
184
+ strcpy(out->cur, out->opts->dump_opts.indent_str);
185
+ out->cur += out->opts->dump_opts.indent_size;
186
+ }
187
+ }
188
+ } else {
189
+ fill_indent(out, depth);
190
+ }
191
+ *out->cur++ = ']';
192
+ }
193
+ *out->cur = '\0';
194
+ }
195
+
196
+ static void
197
+ dump_array(VALUE obj, int depth, Out out, bool as_ok) {
198
+ dump_array_class(obj, rb_obj_class(obj), depth, out);
199
+ }
200
+
201
+ static void
202
+ dump_str_class(VALUE obj, VALUE clas, int depth, Out out) {
203
+ if (Qundef != clas && rb_cString != clas) {
204
+ dump_obj_attrs(obj, clas, 0, depth, out);
205
+ } else {
206
+ const char *s = rb_string_value_ptr((VALUE*)&obj);
207
+ size_t len = (int)RSTRING_LEN(obj);
208
+ char s1 = s[1];
209
+
210
+ oj_dump_cstr(s, len, 0, (':' == *s || ('^' == *s && ('r' == s1 || 'i' == s1))), out);
211
+ }
212
+ }
213
+
214
+ static void
215
+ dump_str(VALUE obj, int depth, Out out, bool as_ok) {
216
+ dump_str_class(obj, rb_obj_class(obj), depth, out);
217
+ }
218
+
219
+ static void
220
+ dump_sym(VALUE obj, int depth, Out out, bool as_ok) {
221
+ volatile VALUE s = rb_sym_to_s(obj);
222
+
223
+ oj_dump_cstr(rb_string_value_ptr((VALUE*)&s), (int)RSTRING_LEN(s), 1, 0, out);
224
+ }
225
+
226
+ static int
227
+ hash_cb(VALUE key, VALUE value, VALUE ov) {
228
+ Out out = (Out)ov;
229
+ int depth = out->depth;
230
+ long size = depth * out->indent + 1;
231
+
232
+ if (oj_dump_ignore(out->opts, value)) {
233
+ return ST_CONTINUE;
234
+ }
235
+ if (out->omit_nil && Qnil == value) {
236
+ return ST_CONTINUE;
237
+ }
238
+ assure_size(out, size);
239
+ fill_indent(out, depth);
240
+ if (rb_type(key) == T_STRING) {
241
+ dump_str_class(key, Qundef, depth, out);
242
+ *out->cur++ = ':';
243
+ oj_dump_obj_val(value, depth, out);
244
+ } else if (rb_type(key) == T_SYMBOL) {
245
+ dump_sym(key, 0, out, false);
246
+ *out->cur++ = ':';
247
+ oj_dump_obj_val(value, depth, out);
248
+ } else {
249
+ int d2 = depth + 1;
250
+ long s2 = size + out->indent + 1;
251
+ int i;
252
+ int started = 0;
253
+ uint8_t b;
254
+
255
+ assure_size(out, s2 + 15);
256
+ *out->cur++ = '"';
257
+ *out->cur++ = '^';
258
+ *out->cur++ = '#';
259
+ out->hash_cnt++;
260
+ for (i = 28; 0 <= i; i -= 4) {
261
+ b = (uint8_t)((out->hash_cnt >> i) & 0x0000000F);
262
+ if ('\0' != b) {
263
+ started = 1;
264
+ }
265
+ if (started) {
266
+ *out->cur++ = hex_chars[b];
267
+ }
268
+ }
269
+ *out->cur++ = '"';
270
+ *out->cur++ = ':';
271
+ *out->cur++ = '[';
272
+ fill_indent(out, d2);
273
+ oj_dump_obj_val(key, d2, out);
274
+ assure_size(out, s2);
275
+ *out->cur++ = ',';
276
+ fill_indent(out, d2);
277
+ oj_dump_obj_val(value, d2, out);
278
+ assure_size(out, size);
279
+ fill_indent(out, depth);
280
+ *out->cur++ = ']';
281
+ }
282
+ out->depth = depth;
283
+ *out->cur++ = ',';
284
+
285
+ return ST_CONTINUE;
286
+ }
287
+
288
+ static void
289
+ dump_hash_class(VALUE obj, VALUE clas, int depth, Out out) {
290
+ int cnt;
291
+ size_t size;
292
+
293
+ if (Qundef != clas && rb_cHash != clas) {
294
+ dump_obj_attrs(obj, clas, 0, depth, out);
295
+ return;
296
+ }
297
+ cnt = (int)RHASH_SIZE(obj);
298
+ size = depth * out->indent + 2;
299
+ assure_size(out, 2);
300
+ if (0 == cnt) {
301
+ *out->cur++ = '{';
302
+ *out->cur++ = '}';
303
+ } else {
304
+ long id = oj_check_circular(obj, out);
305
+
306
+ if (0 > id) {
307
+ return;
308
+ }
309
+ *out->cur++ = '{';
310
+ if (0 < id) {
311
+ assure_size(out, size + 16);
312
+ fill_indent(out, depth + 1);
313
+ *out->cur++ = '"';
314
+ *out->cur++ = '^';
315
+ *out->cur++ = 'i';
316
+ *out->cur++ = '"';
317
+ *out->cur++ = ':';
318
+ dump_ulong(id, out);
319
+ *out->cur++ = ',';
320
+ }
321
+ out->depth = depth + 1;
322
+ rb_hash_foreach(obj, hash_cb, (VALUE)out);
323
+ if (',' == *(out->cur - 1)) {
324
+ out->cur--; // backup to overwrite last comma
325
+ }
326
+ if (!out->opts->dump_opts.use) {
327
+ assure_size(out, size);
328
+ fill_indent(out, depth);
329
+ } else {
330
+ size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
331
+ assure_size(out, size);
332
+ if (0 < out->opts->dump_opts.hash_size) {
333
+ strcpy(out->cur, out->opts->dump_opts.hash_nl);
334
+ out->cur += out->opts->dump_opts.hash_size;
335
+ }
336
+ if (0 < out->opts->dump_opts.indent_size) {
337
+ int i;
338
+
339
+ for (i = depth; 0 < i; i--) {
340
+ strcpy(out->cur, out->opts->dump_opts.indent_str);
341
+ out->cur += out->opts->dump_opts.indent_size;
342
+ }
343
+ }
344
+ }
345
+ *out->cur++ = '}';
346
+ }
347
+ *out->cur = '\0';
348
+ }
349
+
350
+ #ifdef HAVE_RB_IVAR_FOREACH
351
+ static int
352
+ dump_attr_cb(ID key, VALUE value, VALUE ov) {
353
+ Out out = (Out)ov;
354
+ int depth = out->depth;
355
+ size_t size = depth * out->indent + 1;
356
+ const char *attr = rb_id2name(key);
357
+
358
+ if (oj_dump_ignore(out->opts, value)) {
359
+ return ST_CONTINUE;
360
+ }
361
+ if (out->omit_nil && Qnil == value) {
362
+ return ST_CONTINUE;
363
+ }
364
+ // Some exceptions such as NoMethodError have an invisible attribute where
365
+ // the key name is NULL. Not an empty string but NULL.
366
+ if (NULL == attr) {
367
+ attr = "";
368
+ } else if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
369
+ return ST_CONTINUE;
370
+ }
371
+ if (0 == strcmp("bt", attr) || 0 == strcmp("mesg", attr)) {
372
+ return ST_CONTINUE;
373
+ }
374
+ assure_size(out, size);
375
+ fill_indent(out, depth);
376
+ if ('@' == *attr) {
377
+ attr++;
378
+ oj_dump_cstr(attr, strlen(attr), 0, 0, out);
379
+ } else {
380
+ char buf[32];
381
+
382
+ *buf = '~';
383
+ strncpy(buf + 1, attr, sizeof(buf) - 2);
384
+ buf[sizeof(buf) - 1] = '\0';
385
+ oj_dump_cstr(buf, strlen(buf), 0, 0, out);
386
+ }
387
+ *out->cur++ = ':';
388
+ oj_dump_obj_val(value, depth, out);
389
+ out->depth = depth;
390
+ *out->cur++ = ',';
391
+
392
+ return ST_CONTINUE;
393
+ }
394
+ #endif
395
+
396
+ static void
397
+ dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
398
+ dump_hash_class(obj, rb_obj_class(obj), depth, out);
399
+ }
400
+
401
+ static void
402
+ dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
403
+ ID *idp;
404
+ AttrGetFunc *fp;
405
+ volatile VALUE v;
406
+ const char *name;
407
+ size_t size;
408
+ int d2 = depth + 1;
409
+
410
+ assure_size(out, 2);
411
+ *out->cur++ = '{';
412
+ if (Qundef != clas) {
413
+ const char *class_name = rb_class2name(clas);
414
+ int clen = (int)strlen(class_name);
415
+
416
+ size = d2 * out->indent + clen + 10;
417
+ assure_size(out, size);
418
+ fill_indent(out, d2);
419
+ *out->cur++ = '"';
420
+ *out->cur++ = '^';
421
+ *out->cur++ = 'O';
422
+ *out->cur++ = '"';
423
+ *out->cur++ = ':';
424
+ oj_dump_cstr(class_name, clen, 0, 0, out);
425
+ *out->cur++ = ',';
426
+ }
427
+ if (odd->raw) {
428
+ v = rb_funcall(obj, *odd->attrs, 0);
429
+ if (Qundef == v || T_STRING != rb_type(v)) {
430
+ rb_raise(rb_eEncodingError, "Invalid type for raw JSON.");
431
+ } else {
432
+ const char *s = rb_string_value_ptr((VALUE*)&v);
433
+ int len = (int)RSTRING_LEN(v);
434
+ const char *name = rb_id2name(*odd->attrs);
435
+ size_t nlen = strlen(name);
436
+
437
+ size = len + d2 * out->indent + nlen + 10;
438
+ assure_size(out, size);
439
+ fill_indent(out, d2);
440
+ *out->cur++ = '"';
441
+ memcpy(out->cur, name, nlen);
442
+ out->cur += nlen;
443
+ *out->cur++ = '"';
444
+ *out->cur++ = ':';
445
+ memcpy(out->cur, s, len);
446
+ out->cur += len;
447
+ *out->cur = '\0';
448
+ }
449
+ } else {
450
+ size = d2 * out->indent + 1;
451
+ for (idp = odd->attrs, fp = odd->attrFuncs; 0 != *idp; idp++, fp++) {
452
+ size_t nlen;
453
+
454
+ assure_size(out, size);
455
+ name = rb_id2name(*idp);
456
+ nlen = strlen(name);
457
+ if (0 != *fp) {
458
+ v = (*fp)(obj);
459
+ } else if (0 == strchr(name, '.')) {
460
+ v = rb_funcall(obj, *idp, 0);
461
+ } else {
462
+ char nbuf[256];
463
+ char *n2 = nbuf;
464
+ char *n;
465
+ char *end;
466
+ ID i;
467
+
468
+ if (sizeof(nbuf) <= nlen) {
469
+ if (NULL == (n2 = strdup(name))) {
470
+ rb_raise(rb_eNoMemError, "for attribute name.");
471
+ }
472
+ } else {
473
+ strcpy(n2, name);
474
+ }
475
+ n = n2;
476
+ v = obj;
477
+ while (0 != (end = strchr(n, '.'))) {
478
+ *end = '\0';
479
+ i = rb_intern(n);
480
+ v = rb_funcall(v, i, 0);
481
+ n = end + 1;
482
+ }
483
+ i = rb_intern(n);
484
+ v = rb_funcall(v, i, 0);
485
+ if (nbuf != n2) {
486
+ free(n2);
487
+ }
488
+ }
489
+ fill_indent(out, d2);
490
+ oj_dump_cstr(name, nlen, 0, 0, out);
491
+ *out->cur++ = ':';
492
+ oj_dump_obj_val(v, d2, out);
493
+ assure_size(out, 2);
494
+ *out->cur++ = ',';
495
+ }
496
+ out->cur--;
497
+ }
498
+ *out->cur++ = '}';
499
+ *out->cur = '\0';
500
+ }
501
+
502
+ static void
503
+ dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out) {
504
+ size_t size = 0;
505
+ int d2 = depth + 1;
506
+ int type = rb_type(obj);
507
+ Odd odd;
508
+
509
+ if (0 != (odd = oj_get_odd(clas))) {
510
+ dump_odd(obj, odd, clas, depth + 1, out);
511
+ return;
512
+ }
513
+ assure_size(out, 2);
514
+ *out->cur++ = '{';
515
+ if (Qundef != clas) {
516
+ const char *class_name = rb_class2name(clas);
517
+ int clen = (int)strlen(class_name);
518
+
519
+ assure_size(out, d2 * out->indent + clen + 10);
520
+ fill_indent(out, d2);
521
+ *out->cur++ = '"';
522
+ *out->cur++ = '^';
523
+ *out->cur++ = 'o';
524
+ *out->cur++ = '"';
525
+ *out->cur++ = ':';
526
+ oj_dump_cstr(class_name, clen, 0, 0, out);
527
+ }
528
+ if (0 < id) {
529
+ assure_size(out, d2 * out->indent + 16);
530
+ *out->cur++ = ',';
531
+ fill_indent(out, d2);
532
+ *out->cur++ = '"';
533
+ *out->cur++ = '^';
534
+ *out->cur++ = 'i';
535
+ *out->cur++ = '"';
536
+ *out->cur++ = ':';
537
+ dump_ulong(id, out);
538
+ }
539
+ switch (type) {
540
+ case T_STRING:
541
+ assure_size(out, d2 * out->indent + 14);
542
+ *out->cur++ = ',';
543
+ fill_indent(out, d2);
544
+ *out->cur++ = '"';
545
+ *out->cur++ = 's';
546
+ *out->cur++ = 'e';
547
+ *out->cur++ = 'l';
548
+ *out->cur++ = 'f';
549
+ *out->cur++ = '"';
550
+ *out->cur++ = ':';
551
+ oj_dump_cstr(rb_string_value_ptr((VALUE*)&obj), (int)RSTRING_LEN(obj), 0, 0, out);
552
+ break;
553
+ case T_ARRAY:
554
+ assure_size(out, d2 * out->indent + 14);
555
+ *out->cur++ = ',';
556
+ fill_indent(out, d2);
557
+ *out->cur++ = '"';
558
+ *out->cur++ = 's';
559
+ *out->cur++ = 'e';
560
+ *out->cur++ = 'l';
561
+ *out->cur++ = 'f';
562
+ *out->cur++ = '"';
563
+ *out->cur++ = ':';
564
+ dump_array_class(obj, Qundef, depth + 1, out);
565
+ break;
566
+ case T_HASH:
567
+ assure_size(out, d2 * out->indent + 14);
568
+ *out->cur++ = ',';
569
+ fill_indent(out, d2);
570
+ *out->cur++ = '"';
571
+ *out->cur++ = 's';
572
+ *out->cur++ = 'e';
573
+ *out->cur++ = 'l';
574
+ *out->cur++ = 'f';
575
+ *out->cur++ = '"';
576
+ *out->cur++ = ':';
577
+ dump_hash_class(obj, Qundef, depth + 1, out);
578
+ break;
579
+ default:
580
+ break;
581
+ }
582
+ {
583
+ int cnt;
584
+ #ifdef HAVE_RB_IVAR_COUNT
585
+ cnt = (int)rb_ivar_count(obj);
586
+ #else
587
+ volatile VALUE vars = rb_funcall2(obj, oj_instance_variables_id, 0, 0);
588
+ VALUE *np = RARRAY_PTR(vars);
589
+ ID vid;
590
+ const char *attr;
591
+ int i;
592
+ int first = 1;
593
+
594
+ cnt = (int)RARRAY_LEN(vars);
595
+ #endif
596
+ if (Qundef != clas && 0 < cnt) {
597
+ *out->cur++ = ',';
598
+ }
599
+ if (0 == cnt && Qundef == clas) {
600
+ // Might be something special like an Enumerable.
601
+ if (Qtrue == rb_obj_is_kind_of(obj, oj_enumerable_class)) {
602
+ out->cur--;
603
+ oj_dump_obj_val(rb_funcall(obj, rb_intern("entries"), 0), depth, out);
604
+ return;
605
+ }
606
+ }
607
+ out->depth = depth + 1;
608
+ #ifdef HAVE_RB_IVAR_FOREACH
609
+ rb_ivar_foreach(obj, dump_attr_cb, (VALUE)out);
610
+ if (',' == *(out->cur - 1)) {
611
+ out->cur--; // backup to overwrite last comma
612
+ }
613
+ #else
614
+ size = d2 * out->indent + 1;
615
+ for (i = cnt; 0 < i; i--, np++) {
616
+ VALUE value;
617
+
618
+ vid = rb_to_id(*np);
619
+ attr = rb_id2name(vid);
620
+ if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
621
+ continue;
622
+ }
623
+ value = rb_ivar_get(obj, vid);
624
+
625
+ if (oj_dump_ignore(out->opts, value)) {
626
+ continue;
627
+ }
628
+ if (out->omit_nil && Qnil == value) {
629
+ continue;
630
+ }
631
+ if (first) {
632
+ first = 0;
633
+ } else {
634
+ *out->cur++ = ',';
635
+ }
636
+ assure_size(out, size);
637
+ fill_indent(out, d2);
638
+ if ('@' == *attr) {
639
+ attr++;
640
+ oj_dump_cstr(attr, strlen(attr), 0, 0, out);
641
+ } else {
642
+ char buf[32];
643
+
644
+ *buf = '~';
645
+ strncpy(buf + 1, attr, sizeof(buf) - 2);
646
+ buf[sizeof(buf) - 1] = '\0';
647
+ oj_dump_cstr(buf, strlen(attr) + 1, 0, 0, out);
648
+ }
649
+ *out->cur++ = ':';
650
+ oj_dump_obj_val(value, d2, out);
651
+ assure_size(out, 2);
652
+ }
653
+ #endif
654
+ if (rb_obj_is_kind_of(obj, rb_eException)) {
655
+ volatile VALUE rv;
656
+
657
+ if (',' != *(out->cur - 1)) {
658
+ *out->cur++ = ',';
659
+ }
660
+ // message
661
+ assure_size(out, size);
662
+ fill_indent(out, d2);
663
+ oj_dump_cstr("~mesg", 5, 0, 0, out);
664
+ *out->cur++ = ':';
665
+ rv = rb_funcall2(obj, rb_intern("message"), 0, 0);
666
+ oj_dump_obj_val(rv, d2, out);
667
+ assure_size(out, 2);
668
+ *out->cur++ = ',';
669
+ // backtrace
670
+ assure_size(out, size);
671
+ fill_indent(out, d2);
672
+ oj_dump_cstr("~bt", 3, 0, 0, out);
673
+ *out->cur++ = ':';
674
+ rv = rb_funcall2(obj, rb_intern("backtrace"), 0, 0);
675
+ oj_dump_obj_val(rv, d2, out);
676
+ assure_size(out, 2);
677
+ }
678
+ out->depth = depth;
679
+ }
680
+ fill_indent(out, depth);
681
+ *out->cur++ = '}';
682
+ *out->cur = '\0';
683
+ }
684
+
685
+ static void
686
+ dump_regexp(VALUE obj, int depth, Out out, bool as_ok) {
687
+ dump_obj_attrs(obj, rb_obj_class(obj), 0, depth, out);
688
+ }
689
+
690
+ static void
691
+ dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
692
+ VALUE clas = rb_obj_class(obj);
693
+ const char *class_name = rb_class2name(clas);
694
+ int i;
695
+ int d2 = depth + 1;
696
+ int d3 = d2 + 1;
697
+ size_t len = strlen(class_name);
698
+ size_t size = d2 * out->indent + d3 * out->indent + 10 + len;
699
+
700
+ assure_size(out, size);
701
+ *out->cur++ = '{';
702
+ fill_indent(out, d2);
703
+ *out->cur++ = '"';
704
+ *out->cur++ = '^';
705
+ *out->cur++ = 'u';
706
+ *out->cur++ = '"';
707
+ *out->cur++ = ':';
708
+ *out->cur++ = '[';
709
+ if ('#' == *class_name) {
710
+ VALUE ma = rb_struct_s_members(clas);
711
+ const char *name;
712
+ int cnt = (int)RARRAY_LEN(ma);
713
+
714
+ *out->cur++ = '[';
715
+ for (i = 0; i < cnt; i++) {
716
+ volatile VALUE s = rb_sym_to_s(rb_ary_entry(ma, i));
717
+
718
+ name = rb_string_value_ptr((VALUE*)&s);
719
+ len = (int)RSTRING_LEN(s);
720
+ size = len + 3;
721
+ assure_size(out, size);
722
+ if (0 < i) {
723
+ *out->cur++ = ',';
724
+ }
725
+ *out->cur++ = '"';
726
+ memcpy(out->cur, name, len);
727
+ out->cur += len;
728
+ *out->cur++ = '"';
729
+ }
730
+ *out->cur++ = ']';
731
+ } else {
732
+ fill_indent(out, d3);
733
+ *out->cur++ = '"';
734
+ memcpy(out->cur, class_name, len);
735
+ out->cur += len;
736
+ *out->cur++ = '"';
737
+ }
738
+ *out->cur++ = ',';
739
+ size = d3 * out->indent + 2;
740
+ #ifdef RSTRUCT_LEN
741
+ {
742
+ VALUE v;
743
+ int cnt;
744
+ #if RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
745
+ cnt = (int)NUM2LONG(RSTRUCT_LEN(obj));
746
+ #else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
747
+ cnt = (int)RSTRUCT_LEN(obj);
748
+ #endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
749
+
750
+ for (i = 0; i < cnt; i++) {
751
+ v = RSTRUCT_GET(obj, i);
752
+ if (oj_dump_ignore(out->opts, v)) {
753
+ v = Qnil;
754
+ }
755
+ assure_size(out, size);
756
+ fill_indent(out, d3);
757
+ oj_dump_obj_val(v, d3, out);
758
+ *out->cur++ = ',';
759
+ }
760
+ }
761
+ #else
762
+ {
763
+ // This is a bit risky as a struct in C ruby is not the same as a Struct
764
+ // class in interpreted Ruby so length() may not be defined.
765
+ int slen = FIX2INT(rb_funcall2(obj, oj_length_id, 0, 0));
766
+
767
+ for (i = 0; i < slen; i++) {
768
+ assure_size(out, size);
769
+ fill_indent(out, d3);
770
+ if (oj_dump_ignore(out->opts, v)) {
771
+ v = Qnil;
772
+ }
773
+ oj_dump_obj_val(rb_struct_aref(obj, INT2FIX(i)), d3, out, 0, 0, true);
774
+ *out->cur++ = ',';
775
+ }
776
+ }
777
+ #endif
778
+ out->cur--;
779
+ *out->cur++ = ']';
780
+ *out->cur++ = '}';
781
+ *out->cur = '\0';
782
+ }
783
+
784
+ static void
785
+ dump_complex(VALUE obj, int depth, Out out, bool as_ok) {
786
+ dump_obj_attrs(obj, rb_obj_class(obj), 0, depth, out);
787
+ }
788
+
789
+ static void
790
+ dump_rational(VALUE obj, int depth, Out out, bool as_ok) {
791
+ dump_obj_attrs(obj, rb_obj_class(obj), 0, depth, out);
792
+ }
793
+
794
+ static DumpFunc obj_funcs[] = {
795
+ NULL, // RUBY_T_NONE = 0x00,
796
+ dump_obj, // RUBY_T_OBJECT = 0x01,
797
+ dump_class, // RUBY_T_CLASS = 0x02,
798
+ dump_class, // RUBY_T_MODULE = 0x03,
799
+ oj_dump_float, // RUBY_T_FLOAT = 0x04,
800
+ dump_str, // RUBY_T_STRING = 0x05,
801
+ dump_regexp, // RUBY_T_REGEXP = 0x06,
802
+ dump_array, // RUBY_T_ARRAY = 0x07,
803
+ dump_hash, // RUBY_T_HASH = 0x08,
804
+ dump_struct, // RUBY_T_STRUCT = 0x09,
805
+ oj_dump_bignum, // RUBY_T_BIGNUM = 0x0a,
806
+ NULL, // RUBY_T_FILE = 0x0b,
807
+ dump_data, // RUBY_T_DATA = 0x0c,
808
+ NULL, // RUBY_T_MATCH = 0x0d,
809
+ dump_complex, // RUBY_T_COMPLEX = 0x0e,
810
+ dump_rational, // RUBY_T_RATIONAL = 0x0f,
811
+ NULL, // 0x10
812
+ oj_dump_nil, // RUBY_T_NIL = 0x11,
813
+ oj_dump_true, // RUBY_T_TRUE = 0x12,
814
+ oj_dump_false, // RUBY_T_FALSE = 0x13,
815
+ dump_sym, // RUBY_T_SYMBOL = 0x14,
816
+ oj_dump_fixnum, // RUBY_T_FIXNUM = 0x15,
817
+ };
818
+
819
+ void
820
+ oj_dump_obj_val(VALUE obj, int depth, Out out) {
821
+ int type = rb_type(obj);
822
+
823
+ if (Yes == out->opts->trace) {
824
+ oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
825
+ }
826
+ if (MAX_DEPTH < depth) {
827
+ rb_raise(rb_eNoMemError, "Too deeply nested.\n");
828
+ }
829
+ if (0 < type && type <= RUBY_T_FIXNUM) {
830
+ DumpFunc f = obj_funcs[type];
831
+
832
+ if (NULL != f) {
833
+ f(obj, depth, out, false);
834
+ if (Yes == out->opts->trace) {
835
+ oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
836
+ }
837
+ return;
838
+ }
839
+ }
840
+ oj_dump_nil(Qnil, depth, out, false);
841
+ if (Yes == out->opts->trace) {
842
+ oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
843
+ }
844
+ }