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