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