oj 3.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (156) 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 +1191 -0
  13. data/ext/oj/dump.c +1252 -0
  14. data/ext/oj/dump.h +96 -0
  15. data/ext/oj/dump_compat.c +977 -0
  16. data/ext/oj/dump_leaf.c +252 -0
  17. data/ext/oj/dump_object.c +837 -0
  18. data/ext/oj/dump_strict.c +433 -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 +47 -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 +878 -0
  28. data/ext/oj/object.c +771 -0
  29. data/ext/oj/odd.c +231 -0
  30. data/ext/oj/odd.h +44 -0
  31. data/ext/oj/oj.c +1704 -0
  32. data/ext/oj/oj.h +385 -0
  33. data/ext/oj/parse.c +1086 -0
  34. data/ext/oj/parse.h +111 -0
  35. data/ext/oj/rails.c +1493 -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 +910 -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 +283 -0
  74. data/pages/Rails.md +116 -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/decoding_test.rb +125 -0
  85. data/test/activesupport5/encoding_test.rb +485 -0
  86. data/test/activesupport5/encoding_test_cases.rb +90 -0
  87. data/test/activesupport5/test_helper.rb +50 -0
  88. data/test/activesupport5/time_zone_test_helpers.rb +24 -0
  89. data/test/bar.rb +25 -0
  90. data/test/files.rb +29 -0
  91. data/test/foo.rb +167 -0
  92. data/test/helper.rb +26 -0
  93. data/test/isolated/shared.rb +308 -0
  94. data/test/isolated/test_mimic_after.rb +13 -0
  95. data/test/isolated/test_mimic_alone.rb +12 -0
  96. data/test/isolated/test_mimic_as_json.rb +45 -0
  97. data/test/isolated/test_mimic_before.rb +13 -0
  98. data/test/isolated/test_mimic_define.rb +28 -0
  99. data/test/isolated/test_mimic_rails_after.rb +22 -0
  100. data/test/isolated/test_mimic_rails_before.rb +21 -0
  101. data/test/isolated/test_mimic_redefine.rb +15 -0
  102. data/test/json_gem/json_addition_test.rb +216 -0
  103. data/test/json_gem/json_common_interface_test.rb +148 -0
  104. data/test/json_gem/json_encoding_test.rb +107 -0
  105. data/test/json_gem/json_ext_parser_test.rb +20 -0
  106. data/test/json_gem/json_fixtures_test.rb +35 -0
  107. data/test/json_gem/json_generator_test.rb +383 -0
  108. data/test/json_gem/json_generic_object_test.rb +90 -0
  109. data/test/json_gem/json_parser_test.rb +470 -0
  110. data/test/json_gem/json_string_matching_test.rb +42 -0
  111. data/test/json_gem/test_helper.rb +18 -0
  112. data/test/perf.rb +107 -0
  113. data/test/perf_compat.rb +130 -0
  114. data/test/perf_fast.rb +164 -0
  115. data/test/perf_file.rb +64 -0
  116. data/test/perf_object.rb +138 -0
  117. data/test/perf_saj.rb +109 -0
  118. data/test/perf_scp.rb +151 -0
  119. data/test/perf_simple.rb +287 -0
  120. data/test/perf_strict.rb +145 -0
  121. data/test/perf_wab.rb +131 -0
  122. data/test/sample.rb +54 -0
  123. data/test/sample/change.rb +14 -0
  124. data/test/sample/dir.rb +19 -0
  125. data/test/sample/doc.rb +36 -0
  126. data/test/sample/file.rb +48 -0
  127. data/test/sample/group.rb +16 -0
  128. data/test/sample/hasprops.rb +16 -0
  129. data/test/sample/layer.rb +12 -0
  130. data/test/sample/line.rb +20 -0
  131. data/test/sample/oval.rb +10 -0
  132. data/test/sample/rect.rb +10 -0
  133. data/test/sample/shape.rb +35 -0
  134. data/test/sample/text.rb +20 -0
  135. data/test/sample_json.rb +37 -0
  136. data/test/test_compat.rb +509 -0
  137. data/test/test_custom.rb +503 -0
  138. data/test/test_debian.rb +53 -0
  139. data/test/test_fast.rb +470 -0
  140. data/test/test_file.rb +239 -0
  141. data/test/test_gc.rb +49 -0
  142. data/test/test_hash.rb +29 -0
  143. data/test/test_integer_range.rb +73 -0
  144. data/test/test_null.rb +376 -0
  145. data/test/test_object.rb +1018 -0
  146. data/test/test_saj.rb +186 -0
  147. data/test/test_scp.rb +433 -0
  148. data/test/test_strict.rb +410 -0
  149. data/test/test_various.rb +741 -0
  150. data/test/test_wab.rb +307 -0
  151. data/test/test_writer.rb +380 -0
  152. data/test/tests.rb +24 -0
  153. data/test/tests_mimic.rb +14 -0
  154. data/test/tests_mimic_addition.rb +7 -0
  155. data/test/zoo.rb +13 -0
  156. metadata +359 -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,837 @@
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, Out out) {
228
+ int depth = out->depth;
229
+ long size = depth * out->indent + 1;
230
+
231
+ if (oj_dump_ignore(out->opts, value)) {
232
+ return ST_CONTINUE;
233
+ }
234
+ if (out->omit_nil && Qnil == value) {
235
+ return ST_CONTINUE;
236
+ }
237
+ assure_size(out, size);
238
+ fill_indent(out, depth);
239
+ if (rb_type(key) == T_STRING) {
240
+ dump_str_class(key, Qundef, depth, out);
241
+ *out->cur++ = ':';
242
+ oj_dump_obj_val(value, depth, out);
243
+ } else if (rb_type(key) == T_SYMBOL) {
244
+ dump_sym(key, 0, out, false);
245
+ *out->cur++ = ':';
246
+ oj_dump_obj_val(value, depth, out);
247
+ } else {
248
+ int d2 = depth + 1;
249
+ long s2 = size + out->indent + 1;
250
+ int i;
251
+ int started = 0;
252
+ uint8_t b;
253
+
254
+ assure_size(out, s2 + 15);
255
+ *out->cur++ = '"';
256
+ *out->cur++ = '^';
257
+ *out->cur++ = '#';
258
+ out->hash_cnt++;
259
+ for (i = 28; 0 <= i; i -= 4) {
260
+ b = (uint8_t)((out->hash_cnt >> i) & 0x0000000F);
261
+ if ('\0' != b) {
262
+ started = 1;
263
+ }
264
+ if (started) {
265
+ *out->cur++ = hex_chars[b];
266
+ }
267
+ }
268
+ *out->cur++ = '"';
269
+ *out->cur++ = ':';
270
+ *out->cur++ = '[';
271
+ fill_indent(out, d2);
272
+ oj_dump_obj_val(key, d2, out);
273
+ assure_size(out, s2);
274
+ *out->cur++ = ',';
275
+ fill_indent(out, d2);
276
+ oj_dump_obj_val(value, d2, out);
277
+ assure_size(out, size);
278
+ fill_indent(out, depth);
279
+ *out->cur++ = ']';
280
+ }
281
+ out->depth = depth;
282
+ *out->cur++ = ',';
283
+
284
+ return ST_CONTINUE;
285
+ }
286
+
287
+ static void
288
+ dump_hash_class(VALUE obj, VALUE clas, int depth, Out out) {
289
+ int cnt;
290
+ size_t size;
291
+
292
+ if (Qundef != clas && rb_cHash != clas) {
293
+ dump_obj_attrs(obj, clas, 0, depth, out);
294
+ return;
295
+ }
296
+ cnt = (int)RHASH_SIZE(obj);
297
+ size = depth * out->indent + 2;
298
+ assure_size(out, 2);
299
+ if (0 == cnt) {
300
+ *out->cur++ = '{';
301
+ *out->cur++ = '}';
302
+ } else {
303
+ long id = oj_check_circular(obj, out);
304
+
305
+ if (0 > id) {
306
+ return;
307
+ }
308
+ *out->cur++ = '{';
309
+ if (0 < id) {
310
+ assure_size(out, size + 16);
311
+ fill_indent(out, depth + 1);
312
+ *out->cur++ = '"';
313
+ *out->cur++ = '^';
314
+ *out->cur++ = 'i';
315
+ *out->cur++ = '"';
316
+ *out->cur++ = ':';
317
+ dump_ulong(id, out);
318
+ *out->cur++ = ',';
319
+ }
320
+ out->depth = depth + 1;
321
+ rb_hash_foreach(obj, hash_cb, (VALUE)out);
322
+ if (',' == *(out->cur - 1)) {
323
+ out->cur--; // backup to overwrite last comma
324
+ }
325
+ if (!out->opts->dump_opts.use) {
326
+ assure_size(out, size);
327
+ fill_indent(out, depth);
328
+ } else {
329
+ size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
330
+ assure_size(out, size);
331
+ if (0 < out->opts->dump_opts.hash_size) {
332
+ strcpy(out->cur, out->opts->dump_opts.hash_nl);
333
+ out->cur += out->opts->dump_opts.hash_size;
334
+ }
335
+ if (0 < out->opts->dump_opts.indent_size) {
336
+ int i;
337
+
338
+ for (i = depth; 0 < i; i--) {
339
+ strcpy(out->cur, out->opts->dump_opts.indent_str);
340
+ out->cur += out->opts->dump_opts.indent_size;
341
+ }
342
+ }
343
+ }
344
+ *out->cur++ = '}';
345
+ }
346
+ *out->cur = '\0';
347
+ }
348
+
349
+ #ifdef HAVE_RB_IVAR_FOREACH
350
+ static int
351
+ dump_attr_cb(ID key, VALUE value, Out out) {
352
+ int depth = out->depth;
353
+ size_t size = depth * out->indent + 1;
354
+ const char *attr = rb_id2name(key);
355
+
356
+ if (oj_dump_ignore(out->opts, value)) {
357
+ return ST_CONTINUE;
358
+ }
359
+ if (out->omit_nil && Qnil == value) {
360
+ return ST_CONTINUE;
361
+ }
362
+ // Some exceptions such as NoMethodError have an invisible attribute where
363
+ // the key name is NULL. Not an empty string but NULL.
364
+ if (NULL == attr) {
365
+ attr = "";
366
+ }
367
+ if (0 == strcmp("bt", attr) || 0 == strcmp("mesg", attr)) {
368
+ return ST_CONTINUE;
369
+ }
370
+ assure_size(out, size);
371
+ fill_indent(out, depth);
372
+ if ('@' == *attr) {
373
+ attr++;
374
+ oj_dump_cstr(attr, strlen(attr), 0, 0, out);
375
+ } else {
376
+ char buf[32];
377
+
378
+ *buf = '~';
379
+ strncpy(buf + 1, attr, sizeof(buf) - 2);
380
+ buf[sizeof(buf) - 1] = '\0';
381
+ oj_dump_cstr(buf, strlen(buf), 0, 0, out);
382
+ }
383
+ *out->cur++ = ':';
384
+ oj_dump_obj_val(value, depth, out);
385
+ out->depth = depth;
386
+ *out->cur++ = ',';
387
+
388
+ return ST_CONTINUE;
389
+ }
390
+ #endif
391
+
392
+ static void
393
+ dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
394
+ dump_hash_class(obj, rb_obj_class(obj), depth, out);
395
+ }
396
+
397
+ static void
398
+ dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
399
+ ID *idp;
400
+ AttrGetFunc *fp;
401
+ volatile VALUE v;
402
+ const char *name;
403
+ size_t size;
404
+ int d2 = depth + 1;
405
+
406
+ assure_size(out, 2);
407
+ *out->cur++ = '{';
408
+ if (Qundef != clas) {
409
+ const char *class_name = rb_class2name(clas);
410
+ int clen = (int)strlen(class_name);
411
+
412
+ size = d2 * out->indent + clen + 10;
413
+ assure_size(out, size);
414
+ fill_indent(out, d2);
415
+ *out->cur++ = '"';
416
+ *out->cur++ = '^';
417
+ *out->cur++ = 'O';
418
+ *out->cur++ = '"';
419
+ *out->cur++ = ':';
420
+ oj_dump_cstr(class_name, clen, 0, 0, out);
421
+ *out->cur++ = ',';
422
+ }
423
+ if (odd->raw) {
424
+ v = rb_funcall(obj, *odd->attrs, 0);
425
+ if (Qundef == v || T_STRING != rb_type(v)) {
426
+ rb_raise(rb_eEncodingError, "Invalid type for raw JSON.");
427
+ } else {
428
+ const char *s = rb_string_value_ptr((VALUE*)&v);
429
+ int len = (int)RSTRING_LEN(v);
430
+ const char *name = rb_id2name(*odd->attrs);
431
+ size_t nlen = strlen(name);
432
+
433
+ size = len + d2 * out->indent + nlen + 10;
434
+ assure_size(out, size);
435
+ fill_indent(out, d2);
436
+ *out->cur++ = '"';
437
+ memcpy(out->cur, name, nlen);
438
+ out->cur += nlen;
439
+ *out->cur++ = '"';
440
+ *out->cur++ = ':';
441
+ memcpy(out->cur, s, len);
442
+ out->cur += len;
443
+ *out->cur = '\0';
444
+ }
445
+ } else {
446
+ size = d2 * out->indent + 1;
447
+ for (idp = odd->attrs, fp = odd->attrFuncs; 0 != *idp; idp++, fp++) {
448
+ size_t nlen;
449
+
450
+ assure_size(out, size);
451
+ name = rb_id2name(*idp);
452
+ nlen = strlen(name);
453
+ if (0 != *fp) {
454
+ v = (*fp)(obj);
455
+ } else if (0 == strchr(name, '.')) {
456
+ v = rb_funcall(obj, *idp, 0);
457
+ } else {
458
+ char nbuf[256];
459
+ char *n2 = nbuf;
460
+ char *n;
461
+ char *end;
462
+ ID i;
463
+
464
+ if (sizeof(nbuf) <= nlen) {
465
+ if (NULL == (n2 = strdup(name))) {
466
+ rb_raise(rb_eNoMemError, "for attribute name.");
467
+ }
468
+ } else {
469
+ strcpy(n2, name);
470
+ }
471
+ n = n2;
472
+ v = obj;
473
+ while (0 != (end = strchr(n, '.'))) {
474
+ *end = '\0';
475
+ i = rb_intern(n);
476
+ v = rb_funcall(v, i, 0);
477
+ n = end + 1;
478
+ }
479
+ i = rb_intern(n);
480
+ v = rb_funcall(v, i, 0);
481
+ if (nbuf != n2) {
482
+ free(n2);
483
+ }
484
+ }
485
+ fill_indent(out, d2);
486
+ oj_dump_cstr(name, nlen, 0, 0, out);
487
+ *out->cur++ = ':';
488
+ oj_dump_obj_val(v, d2, out);
489
+ assure_size(out, 2);
490
+ *out->cur++ = ',';
491
+ }
492
+ out->cur--;
493
+ }
494
+ *out->cur++ = '}';
495
+ *out->cur = '\0';
496
+ }
497
+
498
+ static void
499
+ dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out) {
500
+ size_t size = 0;
501
+ int d2 = depth + 1;
502
+ int type = rb_type(obj);
503
+ Odd odd;
504
+
505
+ if (0 != (odd = oj_get_odd(clas))) {
506
+ dump_odd(obj, odd, clas, depth + 1, out);
507
+ return;
508
+ }
509
+ assure_size(out, 2);
510
+ *out->cur++ = '{';
511
+ if (Qundef != clas) {
512
+ const char *class_name = rb_class2name(clas);
513
+ int clen = (int)strlen(class_name);
514
+
515
+ assure_size(out, d2 * out->indent + clen + 10);
516
+ fill_indent(out, d2);
517
+ *out->cur++ = '"';
518
+ *out->cur++ = '^';
519
+ *out->cur++ = 'o';
520
+ *out->cur++ = '"';
521
+ *out->cur++ = ':';
522
+ oj_dump_cstr(class_name, clen, 0, 0, out);
523
+ }
524
+ if (0 < id) {
525
+ assure_size(out, d2 * out->indent + 16);
526
+ *out->cur++ = ',';
527
+ fill_indent(out, d2);
528
+ *out->cur++ = '"';
529
+ *out->cur++ = '^';
530
+ *out->cur++ = 'i';
531
+ *out->cur++ = '"';
532
+ *out->cur++ = ':';
533
+ dump_ulong(id, out);
534
+ }
535
+ switch (type) {
536
+ case T_STRING:
537
+ assure_size(out, d2 * out->indent + 14);
538
+ *out->cur++ = ',';
539
+ fill_indent(out, d2);
540
+ *out->cur++ = '"';
541
+ *out->cur++ = 's';
542
+ *out->cur++ = 'e';
543
+ *out->cur++ = 'l';
544
+ *out->cur++ = 'f';
545
+ *out->cur++ = '"';
546
+ *out->cur++ = ':';
547
+ oj_dump_cstr(rb_string_value_ptr((VALUE*)&obj), (int)RSTRING_LEN(obj), 0, 0, out);
548
+ break;
549
+ case T_ARRAY:
550
+ assure_size(out, d2 * out->indent + 14);
551
+ *out->cur++ = ',';
552
+ fill_indent(out, d2);
553
+ *out->cur++ = '"';
554
+ *out->cur++ = 's';
555
+ *out->cur++ = 'e';
556
+ *out->cur++ = 'l';
557
+ *out->cur++ = 'f';
558
+ *out->cur++ = '"';
559
+ *out->cur++ = ':';
560
+ dump_array_class(obj, Qundef, depth + 1, out);
561
+ break;
562
+ case T_HASH:
563
+ assure_size(out, d2 * out->indent + 14);
564
+ *out->cur++ = ',';
565
+ fill_indent(out, d2);
566
+ *out->cur++ = '"';
567
+ *out->cur++ = 's';
568
+ *out->cur++ = 'e';
569
+ *out->cur++ = 'l';
570
+ *out->cur++ = 'f';
571
+ *out->cur++ = '"';
572
+ *out->cur++ = ':';
573
+ dump_hash_class(obj, Qundef, depth + 1, out);
574
+ break;
575
+ default:
576
+ break;
577
+ }
578
+ {
579
+ int cnt;
580
+ #ifdef HAVE_RB_IVAR_COUNT
581
+ cnt = (int)rb_ivar_count(obj);
582
+ #else
583
+ volatile VALUE vars = rb_funcall2(obj, oj_instance_variables_id, 0, 0);
584
+ VALUE *np = RARRAY_PTR(vars);
585
+ ID vid;
586
+ const char *attr;
587
+ int i;
588
+ int first = 1;
589
+
590
+ cnt = (int)RARRAY_LEN(vars);
591
+ #endif
592
+ if (Qundef != clas && 0 < cnt) {
593
+ *out->cur++ = ',';
594
+ }
595
+ if (0 == cnt && Qundef == clas) {
596
+ // Might be something special like an Enumerable.
597
+ if (Qtrue == rb_obj_is_kind_of(obj, oj_enumerable_class)) {
598
+ out->cur--;
599
+ oj_dump_obj_val(rb_funcall(obj, rb_intern("entries"), 0), depth, out);
600
+ return;
601
+ }
602
+ }
603
+ out->depth = depth + 1;
604
+ #ifdef HAVE_RB_IVAR_FOREACH
605
+ rb_ivar_foreach(obj, dump_attr_cb, (VALUE)out);
606
+ if (',' == *(out->cur - 1)) {
607
+ out->cur--; // backup to overwrite last comma
608
+ }
609
+ #else
610
+ size = d2 * out->indent + 1;
611
+ for (i = cnt; 0 < i; i--, np++) {
612
+ VALUE value;
613
+
614
+ vid = rb_to_id(*np);
615
+ attr = rb_id2name(vid);
616
+ value = rb_ivar_get(obj, vid);
617
+
618
+ if (oj_dump_ignore(out->opts, value)) {
619
+ continue;
620
+ }
621
+ if (out->omit_nil && Qnil == value) {
622
+ continue;
623
+ }
624
+ if (first) {
625
+ first = 0;
626
+ } else {
627
+ *out->cur++ = ',';
628
+ }
629
+ assure_size(out, size);
630
+ fill_indent(out, d2);
631
+ if ('@' == *attr) {
632
+ attr++;
633
+ oj_dump_cstr(attr, strlen(attr), 0, 0, out);
634
+ } else {
635
+ char buf[32];
636
+
637
+ *buf = '~';
638
+ strncpy(buf + 1, attr, sizeof(buf) - 2);
639
+ buf[sizeof(buf) - 1] = '\0';
640
+ oj_dump_cstr(buf, strlen(attr) + 1, 0, 0, out);
641
+ }
642
+ *out->cur++ = ':';
643
+ oj_dump_obj_val(value, d2, out);
644
+ assure_size(out, 2);
645
+ }
646
+ #endif
647
+ if (rb_obj_is_kind_of(obj, rb_eException)) {
648
+ volatile VALUE rv;
649
+
650
+ if (',' != *(out->cur - 1)) {
651
+ *out->cur++ = ',';
652
+ }
653
+ // message
654
+ assure_size(out, size);
655
+ fill_indent(out, d2);
656
+ oj_dump_cstr("~mesg", 5, 0, 0, out);
657
+ *out->cur++ = ':';
658
+ rv = rb_funcall2(obj, rb_intern("message"), 0, 0);
659
+ oj_dump_obj_val(rv, d2, out);
660
+ assure_size(out, 2);
661
+ *out->cur++ = ',';
662
+ // backtrace
663
+ assure_size(out, size);
664
+ fill_indent(out, d2);
665
+ oj_dump_cstr("~bt", 3, 0, 0, out);
666
+ *out->cur++ = ':';
667
+ rv = rb_funcall2(obj, rb_intern("backtrace"), 0, 0);
668
+ oj_dump_obj_val(rv, d2, out);
669
+ assure_size(out, 2);
670
+ }
671
+ out->depth = depth;
672
+ }
673
+ fill_indent(out, depth);
674
+ *out->cur++ = '}';
675
+ *out->cur = '\0';
676
+ }
677
+
678
+ static void
679
+ dump_regexp(VALUE obj, int depth, Out out, bool as_ok) {
680
+ dump_obj_attrs(obj, rb_obj_class(obj), 0, depth, out);
681
+ }
682
+
683
+ static void
684
+ dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
685
+ VALUE clas = rb_obj_class(obj);
686
+ const char *class_name = rb_class2name(clas);
687
+ int i;
688
+ int d2 = depth + 1;
689
+ int d3 = d2 + 1;
690
+ size_t len = strlen(class_name);
691
+ size_t size = d2 * out->indent + d3 * out->indent + 10 + len;
692
+
693
+ assure_size(out, size);
694
+ *out->cur++ = '{';
695
+ fill_indent(out, d2);
696
+ *out->cur++ = '"';
697
+ *out->cur++ = '^';
698
+ *out->cur++ = 'u';
699
+ *out->cur++ = '"';
700
+ *out->cur++ = ':';
701
+ *out->cur++ = '[';
702
+ if ('#' == *class_name) {
703
+ VALUE ma = rb_struct_s_members(clas);
704
+ const char *name;
705
+ int cnt = (int)RARRAY_LEN(ma);
706
+
707
+ *out->cur++ = '[';
708
+ for (i = 0; i < cnt; i++) {
709
+ volatile VALUE s = rb_sym_to_s(rb_ary_entry(ma, i));
710
+
711
+ name = rb_string_value_ptr((VALUE*)&s);
712
+ len = (int)RSTRING_LEN(s);
713
+ size = len + 3;
714
+ assure_size(out, size);
715
+ if (0 < i) {
716
+ *out->cur++ = ',';
717
+ }
718
+ *out->cur++ = '"';
719
+ memcpy(out->cur, name, len);
720
+ out->cur += len;
721
+ *out->cur++ = '"';
722
+ }
723
+ *out->cur++ = ']';
724
+ } else {
725
+ fill_indent(out, d3);
726
+ *out->cur++ = '"';
727
+ memcpy(out->cur, class_name, len);
728
+ out->cur += len;
729
+ *out->cur++ = '"';
730
+ }
731
+ *out->cur++ = ',';
732
+ size = d3 * out->indent + 2;
733
+ #ifdef RSTRUCT_LEN
734
+ {
735
+ VALUE v;
736
+ int cnt;
737
+ #if RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
738
+ cnt = (int)NUM2LONG(RSTRUCT_LEN(obj));
739
+ #else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
740
+ cnt = (int)RSTRUCT_LEN(obj);
741
+ #endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
742
+
743
+ for (i = 0; i < cnt; i++) {
744
+ v = RSTRUCT_GET(obj, i);
745
+ if (oj_dump_ignore(out->opts, v)) {
746
+ v = Qnil;
747
+ }
748
+ assure_size(out, size);
749
+ fill_indent(out, d3);
750
+ oj_dump_obj_val(v, d3, out);
751
+ *out->cur++ = ',';
752
+ }
753
+ }
754
+ #else
755
+ {
756
+ // This is a bit risky as a struct in C ruby is not the same as a Struct
757
+ // class in interpreted Ruby so length() may not be defined.
758
+ int slen = FIX2INT(rb_funcall2(obj, oj_length_id, 0, 0));
759
+
760
+ for (i = 0; i < slen; i++) {
761
+ assure_size(out, size);
762
+ fill_indent(out, d3);
763
+ if (oj_dump_ignore(out->opts, v)) {
764
+ v = Qnil;
765
+ }
766
+ oj_dump_obj_val(rb_struct_aref(obj, INT2FIX(i)), d3, out, 0, 0, true);
767
+ *out->cur++ = ',';
768
+ }
769
+ }
770
+ #endif
771
+ out->cur--;
772
+ *out->cur++ = ']';
773
+ *out->cur++ = '}';
774
+ *out->cur = '\0';
775
+ }
776
+
777
+ static void
778
+ dump_complex(VALUE obj, int depth, Out out, bool as_ok) {
779
+ dump_obj_attrs(obj, rb_obj_class(obj), 0, depth, out);
780
+ }
781
+
782
+ static void
783
+ dump_rational(VALUE obj, int depth, Out out, bool as_ok) {
784
+ dump_obj_attrs(obj, rb_obj_class(obj), 0, depth, out);
785
+ }
786
+
787
+ static DumpFunc obj_funcs[] = {
788
+ NULL, // RUBY_T_NONE = 0x00,
789
+ dump_obj, // RUBY_T_OBJECT = 0x01,
790
+ dump_class, // RUBY_T_CLASS = 0x02,
791
+ dump_class, // RUBY_T_MODULE = 0x03,
792
+ oj_dump_float, // RUBY_T_FLOAT = 0x04,
793
+ dump_str, // RUBY_T_STRING = 0x05,
794
+ dump_regexp, // RUBY_T_REGEXP = 0x06,
795
+ dump_array, // RUBY_T_ARRAY = 0x07,
796
+ dump_hash, // RUBY_T_HASH = 0x08,
797
+ dump_struct, // RUBY_T_STRUCT = 0x09,
798
+ oj_dump_bignum, // RUBY_T_BIGNUM = 0x0a,
799
+ NULL, // RUBY_T_FILE = 0x0b,
800
+ dump_data, // RUBY_T_DATA = 0x0c,
801
+ NULL, // RUBY_T_MATCH = 0x0d,
802
+ dump_complex, // RUBY_T_COMPLEX = 0x0e,
803
+ dump_rational, // RUBY_T_RATIONAL = 0x0f,
804
+ NULL, // 0x10
805
+ oj_dump_nil, // RUBY_T_NIL = 0x11,
806
+ oj_dump_true, // RUBY_T_TRUE = 0x12,
807
+ oj_dump_false, // RUBY_T_FALSE = 0x13,
808
+ dump_sym, // RUBY_T_SYMBOL = 0x14,
809
+ oj_dump_fixnum, // RUBY_T_FIXNUM = 0x15,
810
+ };
811
+
812
+ void
813
+ oj_dump_obj_val(VALUE obj, int depth, Out out) {
814
+ int type = rb_type(obj);
815
+
816
+ if (Yes == out->opts->trace) {
817
+ oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
818
+ }
819
+ if (MAX_DEPTH < depth) {
820
+ rb_raise(rb_eNoMemError, "Too deeply nested.\n");
821
+ }
822
+ if (0 < type && type <= RUBY_T_FIXNUM) {
823
+ DumpFunc f = obj_funcs[type];
824
+
825
+ if (NULL != f) {
826
+ f(obj, depth, out, false);
827
+ if (Yes == out->opts->trace) {
828
+ oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
829
+ }
830
+ return;
831
+ }
832
+ }
833
+ oj_dump_nil(Qnil, depth, out, false);
834
+ if (Yes == out->opts->trace) {
835
+ oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
836
+ }
837
+ }