oj 3.10.7

Sign up to get free protection for your applications and to get access to all the features.
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
+ }