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