oj 3.7.4 → 3.13.21
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 +1352 -0
- data/README.md +29 -8
- data/RELEASE_NOTES.md +61 -0
- data/ext/oj/buf.h +53 -72
- data/ext/oj/cache.c +326 -0
- data/ext/oj/cache.h +21 -0
- data/ext/oj/cache8.c +61 -64
- data/ext/oj/cache8.h +12 -39
- data/ext/oj/circarray.c +37 -43
- data/ext/oj/circarray.h +16 -17
- data/ext/oj/code.c +165 -179
- data/ext/oj/code.h +27 -29
- data/ext/oj/compat.c +174 -194
- data/ext/oj/custom.c +809 -866
- data/ext/oj/debug.c +132 -0
- data/ext/oj/dump.c +848 -863
- data/ext/oj/dump.h +81 -67
- data/ext/oj/dump_compat.c +85 -123
- data/ext/oj/dump_leaf.c +100 -188
- data/ext/oj/dump_object.c +527 -656
- data/ext/oj/dump_strict.c +315 -338
- data/ext/oj/encode.h +7 -34
- data/ext/oj/encoder.c +43 -0
- data/ext/oj/err.c +40 -29
- data/ext/oj/err.h +48 -48
- data/ext/oj/extconf.rb +17 -4
- data/ext/oj/fast.c +1070 -1087
- data/ext/oj/intern.c +301 -0
- data/ext/oj/intern.h +26 -0
- data/ext/oj/mimic_json.c +469 -436
- data/ext/oj/object.c +525 -593
- data/ext/oj/odd.c +154 -138
- data/ext/oj/odd.h +37 -38
- data/ext/oj/oj.c +1325 -986
- data/ext/oj/oj.h +333 -316
- data/ext/oj/parse.c +1002 -846
- data/ext/oj/parse.h +92 -87
- data/ext/oj/parser.c +1557 -0
- data/ext/oj/parser.h +91 -0
- data/ext/oj/rails.c +888 -878
- data/ext/oj/rails.h +11 -14
- data/ext/oj/reader.c +141 -147
- data/ext/oj/reader.h +73 -89
- data/ext/oj/resolve.c +41 -62
- data/ext/oj/resolve.h +7 -9
- data/ext/oj/rxclass.c +71 -75
- data/ext/oj/rxclass.h +18 -19
- data/ext/oj/saj.c +443 -486
- data/ext/oj/saj2.c +602 -0
- data/ext/oj/scp.c +88 -113
- data/ext/oj/sparse.c +787 -709
- data/ext/oj/stream_writer.c +133 -159
- data/ext/oj/strict.c +127 -118
- data/ext/oj/string_writer.c +230 -249
- data/ext/oj/trace.c +34 -41
- data/ext/oj/trace.h +19 -19
- data/ext/oj/usual.c +1254 -0
- data/ext/oj/util.c +136 -0
- data/ext/oj/util.h +20 -0
- data/ext/oj/val_stack.c +59 -67
- data/ext/oj/val_stack.h +91 -129
- data/ext/oj/validate.c +46 -0
- data/ext/oj/wab.c +342 -353
- data/lib/oj/bag.rb +1 -0
- data/lib/oj/easy_hash.rb +5 -4
- data/lib/oj/error.rb +1 -1
- data/lib/oj/json.rb +1 -1
- data/lib/oj/mimic.rb +48 -14
- data/lib/oj/saj.rb +20 -6
- data/lib/oj/state.rb +8 -7
- data/lib/oj/version.rb +2 -2
- data/lib/oj.rb +0 -8
- data/pages/Compatibility.md +1 -1
- data/pages/JsonGem.md +15 -0
- data/pages/Modes.md +53 -46
- data/pages/Options.md +72 -11
- data/pages/Parser.md +309 -0
- data/pages/Rails.md +73 -22
- data/pages/Security.md +1 -1
- data/test/activerecord/result_test.rb +7 -2
- data/test/activesupport5/abstract_unit.rb +45 -0
- data/test/activesupport5/decoding_test.rb +68 -60
- data/test/activesupport5/encoding_test.rb +111 -96
- data/test/activesupport5/encoding_test_cases.rb +33 -25
- data/test/activesupport5/test_helper.rb +43 -21
- data/test/activesupport5/time_zone_test_helpers.rb +18 -3
- data/test/activesupport6/abstract_unit.rb +44 -0
- data/test/activesupport6/decoding_test.rb +133 -0
- data/test/activesupport6/encoding_test.rb +507 -0
- data/test/activesupport6/encoding_test_cases.rb +98 -0
- data/test/activesupport6/test_common.rb +17 -0
- data/test/activesupport6/test_helper.rb +163 -0
- data/test/activesupport6/time_zone_test_helpers.rb +39 -0
- data/test/activesupport7/abstract_unit.rb +49 -0
- data/test/activesupport7/decoding_test.rb +125 -0
- data/test/activesupport7/encoding_test.rb +486 -0
- data/test/activesupport7/encoding_test_cases.rb +104 -0
- data/test/activesupport7/time_zone_test_helpers.rb +47 -0
- data/test/bar.rb +6 -12
- data/test/baz.rb +16 -0
- data/test/bug.rb +16 -0
- data/test/foo.rb +69 -75
- data/test/helper.rb +16 -0
- data/test/json_gem/json_common_interface_test.rb +8 -3
- data/test/json_gem/json_generator_test.rb +18 -4
- data/test/json_gem/json_parser_test.rb +9 -0
- data/test/json_gem/test_helper.rb +12 -0
- data/test/mem.rb +33 -0
- data/test/perf.rb +1 -1
- data/test/perf_dump.rb +50 -0
- data/test/perf_once.rb +58 -0
- data/test/perf_parser.rb +189 -0
- 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 +46 -10
- data/test/test_custom.rb +147 -8
- data/test/test_fast.rb +62 -2
- data/test/test_file.rb +25 -2
- data/test/test_gc.rb +13 -0
- data/test/test_generate.rb +21 -0
- data/test/test_hash.rb +11 -1
- data/test/test_integer_range.rb +7 -2
- data/test/test_object.rb +85 -9
- data/test/test_parser.rb +27 -0
- data/test/test_parser_saj.rb +335 -0
- data/test/test_parser_usual.rb +217 -0
- data/test/test_rails.rb +35 -0
- data/test/test_saj.rb +1 -1
- data/test/test_scp.rb +5 -5
- data/test/test_strict.rb +26 -1
- data/test/test_various.rb +87 -65
- data/test/test_wab.rb +2 -0
- data/test/test_writer.rb +19 -2
- data/test/tests.rb +1 -1
- data/test/zoo.rb +13 -0
- metadata +60 -110
- data/ext/oj/hash.c +0 -163
- data/ext/oj/hash.h +0 -46
- data/ext/oj/hash_test.c +0 -512
data/ext/oj/dump_object.c
CHANGED
|
@@ -1,835 +1,706 @@
|
|
|
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
|
-
*out->cur++ = '"';
|
|
36
|
-
*out->cur++ = ':';
|
|
37
|
-
dump_time(obj, out);
|
|
38
|
-
*out->cur++ = '}';
|
|
39
|
-
*out->cur = '\0';
|
|
26
|
+
assure_size(out, 6);
|
|
27
|
+
APPEND_CHARS(out->cur, "{\"^t\":", 6);
|
|
28
|
+
dump_time(obj, out);
|
|
29
|
+
*out->cur++ = '}';
|
|
30
|
+
*out->cur = '\0';
|
|
40
31
|
} else {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
32
|
+
if (oj_bigdecimal_class == clas) {
|
|
33
|
+
volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
|
|
34
|
+
const char * str = RSTRING_PTR(rstr);
|
|
35
|
+
int len = (int)RSTRING_LEN(rstr);
|
|
36
|
+
|
|
37
|
+
if (No != out->opts->bigdec_as_num) {
|
|
38
|
+
oj_dump_raw(str, len, out);
|
|
39
|
+
} else if (0 == strcasecmp("Infinity", str)) {
|
|
40
|
+
str = oj_nan_str(obj, out->opts->dump_opts.nan_dump, out->opts->mode, true, &len);
|
|
41
|
+
oj_dump_raw(str, len, out);
|
|
42
|
+
} else if (0 == strcasecmp("-Infinity", str)) {
|
|
43
|
+
str = oj_nan_str(obj, out->opts->dump_opts.nan_dump, out->opts->mode, false, &len);
|
|
44
|
+
oj_dump_raw(str, len, out);
|
|
45
|
+
} else {
|
|
46
|
+
oj_dump_cstr(str, len, 0, 0, out);
|
|
47
|
+
}
|
|
48
|
+
} else {
|
|
49
|
+
long id = oj_check_circular(obj, out);
|
|
50
|
+
|
|
51
|
+
if (0 <= id) {
|
|
52
|
+
dump_obj_attrs(obj, clas, id, depth, out);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
64
55
|
}
|
|
65
56
|
}
|
|
66
57
|
|
|
67
|
-
static void
|
|
68
|
-
|
|
69
|
-
VALUE clas = rb_obj_class(obj);
|
|
58
|
+
static void dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
|
|
59
|
+
VALUE clas = rb_obj_class(obj);
|
|
70
60
|
|
|
71
61
|
if (oj_bigdecimal_class == clas) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
62
|
+
volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
|
|
63
|
+
const char * str = RSTRING_PTR(rstr);
|
|
64
|
+
int len = (int)RSTRING_LEN(rstr);
|
|
65
|
+
|
|
66
|
+
if (0 == strcasecmp("Infinity", str)) {
|
|
67
|
+
str = oj_nan_str(obj, out->opts->dump_opts.nan_dump, out->opts->mode, true, &len);
|
|
68
|
+
oj_dump_raw(str, len, out);
|
|
69
|
+
} else if (0 == strcasecmp("-Infinity", str)) {
|
|
70
|
+
str = oj_nan_str(obj, out->opts->dump_opts.nan_dump, out->opts->mode, false, &len);
|
|
71
|
+
oj_dump_raw(str, len, out);
|
|
72
|
+
} else {
|
|
73
|
+
oj_dump_raw(str, len, out);
|
|
74
|
+
}
|
|
85
75
|
} else {
|
|
86
|
-
|
|
76
|
+
long id = oj_check_circular(obj, out);
|
|
87
77
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
78
|
+
if (0 <= id) {
|
|
79
|
+
dump_obj_attrs(obj, clas, id, depth, out);
|
|
80
|
+
}
|
|
91
81
|
}
|
|
92
82
|
}
|
|
93
83
|
|
|
94
|
-
static void
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
size_t len = strlen(s);
|
|
84
|
+
static void dump_class(VALUE obj, int depth, Out out, bool as_ok) {
|
|
85
|
+
const char *s = rb_class2name(obj);
|
|
86
|
+
size_t len = strlen(s);
|
|
98
87
|
|
|
99
88
|
assure_size(out, 6);
|
|
100
|
-
|
|
101
|
-
*out->cur++ = '"';
|
|
102
|
-
*out->cur++ = '^';
|
|
103
|
-
*out->cur++ = 'c';
|
|
104
|
-
*out->cur++ = '"';
|
|
105
|
-
*out->cur++ = ':';
|
|
89
|
+
APPEND_CHARS(out->cur, "{\"^c\":", 6);
|
|
106
90
|
oj_dump_cstr(s, len, 0, 0, out);
|
|
107
91
|
*out->cur++ = '}';
|
|
108
|
-
*out->cur
|
|
92
|
+
*out->cur = '\0';
|
|
109
93
|
}
|
|
110
94
|
|
|
111
|
-
static void
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
int
|
|
115
|
-
|
|
116
|
-
long id = oj_check_circular(a, out);
|
|
95
|
+
static void dump_array_class(VALUE a, VALUE clas, int depth, Out out) {
|
|
96
|
+
size_t size;
|
|
97
|
+
int i, cnt;
|
|
98
|
+
int d2 = depth + 1;
|
|
99
|
+
long id = oj_check_circular(a, out);
|
|
117
100
|
|
|
118
101
|
if (id < 0) {
|
|
119
|
-
|
|
102
|
+
return;
|
|
120
103
|
}
|
|
121
104
|
if (Qundef != clas && rb_cArray != clas && ObjectMode == out->opts->mode) {
|
|
122
|
-
|
|
123
|
-
|
|
105
|
+
dump_obj_attrs(a, clas, 0, depth, out);
|
|
106
|
+
return;
|
|
124
107
|
}
|
|
125
|
-
cnt
|
|
108
|
+
cnt = (int)RARRAY_LEN(a);
|
|
126
109
|
*out->cur++ = '[';
|
|
127
110
|
if (0 < id) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
dump_ulong(id, out);
|
|
134
|
-
*out->cur++ = '"';
|
|
111
|
+
assure_size(out, d2 * out->indent + 16);
|
|
112
|
+
fill_indent(out, d2);
|
|
113
|
+
APPEND_CHARS(out->cur, "\"^i", 3);
|
|
114
|
+
dump_ulong(id, out);
|
|
115
|
+
*out->cur++ = '"';
|
|
135
116
|
}
|
|
136
117
|
size = 2;
|
|
137
118
|
assure_size(out, 2);
|
|
138
119
|
if (0 == cnt) {
|
|
139
|
-
|
|
120
|
+
*out->cur++ = ']';
|
|
140
121
|
} 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++ = ']';
|
|
122
|
+
if (0 < id) {
|
|
123
|
+
*out->cur++ = ',';
|
|
124
|
+
}
|
|
125
|
+
if (out->opts->dump_opts.use) {
|
|
126
|
+
size = d2 * out->opts->dump_opts.indent_size + out->opts->dump_opts.array_size + 1;
|
|
127
|
+
} else {
|
|
128
|
+
size = d2 * out->indent + 2;
|
|
129
|
+
}
|
|
130
|
+
assure_size(out, size * cnt);
|
|
131
|
+
cnt--;
|
|
132
|
+
for (i = 0; i <= cnt; i++) {
|
|
133
|
+
if (out->opts->dump_opts.use) {
|
|
134
|
+
if (0 < out->opts->dump_opts.array_size) {
|
|
135
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
|
|
136
|
+
}
|
|
137
|
+
if (0 < out->opts->dump_opts.indent_size) {
|
|
138
|
+
int i;
|
|
139
|
+
for (i = d2; 0 < i; i--) {
|
|
140
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
} else {
|
|
144
|
+
fill_indent(out, d2);
|
|
145
|
+
}
|
|
146
|
+
oj_dump_obj_val(RARRAY_AREF(a, i), d2, out);
|
|
147
|
+
if (i < cnt) {
|
|
148
|
+
*out->cur++ = ',';
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
size = depth * out->indent + 1;
|
|
152
|
+
assure_size(out, size);
|
|
153
|
+
if (out->opts->dump_opts.use) {
|
|
154
|
+
// printf("*** d2: %u indent: %u '%s'\n", d2, out->opts->dump_opts->indent_size,
|
|
155
|
+
// out->opts->dump_opts->indent);
|
|
156
|
+
if (0 < out->opts->dump_opts.array_size) {
|
|
157
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
|
|
158
|
+
}
|
|
159
|
+
if (0 < out->opts->dump_opts.indent_size) {
|
|
160
|
+
int i;
|
|
161
|
+
|
|
162
|
+
for (i = depth; 0 < i; i--) {
|
|
163
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
} else {
|
|
167
|
+
fill_indent(out, depth);
|
|
168
|
+
}
|
|
169
|
+
*out->cur++ = ']';
|
|
192
170
|
}
|
|
193
171
|
*out->cur = '\0';
|
|
194
172
|
}
|
|
195
173
|
|
|
196
|
-
static void
|
|
197
|
-
dump_array(VALUE obj, int depth, Out out, bool as_ok) {
|
|
174
|
+
static void dump_array(VALUE obj, int depth, Out out, bool as_ok) {
|
|
198
175
|
dump_array_class(obj, rb_obj_class(obj), depth, out);
|
|
199
176
|
}
|
|
200
177
|
|
|
201
|
-
static void
|
|
202
|
-
dump_str_class(VALUE obj, VALUE clas, int depth, Out out) {
|
|
178
|
+
static void dump_str_class(VALUE obj, VALUE clas, int depth, Out out) {
|
|
203
179
|
if (Qundef != clas && rb_cString != clas) {
|
|
204
|
-
|
|
180
|
+
dump_obj_attrs(obj, clas, 0, depth, out);
|
|
205
181
|
} else {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
182
|
+
const char *s = RSTRING_PTR(obj);
|
|
183
|
+
size_t len = (int)RSTRING_LEN(obj);
|
|
184
|
+
char s1 = s[1];
|
|
209
185
|
|
|
210
|
-
|
|
186
|
+
oj_dump_cstr(s, len, 0, (':' == *s || ('^' == *s && ('r' == s1 || 'i' == s1))), out);
|
|
211
187
|
}
|
|
212
188
|
}
|
|
213
189
|
|
|
214
|
-
static void
|
|
215
|
-
dump_str(VALUE obj, int depth, Out out, bool as_ok) {
|
|
190
|
+
static void dump_str(VALUE obj, int depth, Out out, bool as_ok) {
|
|
216
191
|
dump_str_class(obj, rb_obj_class(obj), depth, out);
|
|
217
192
|
}
|
|
218
193
|
|
|
219
|
-
static void
|
|
220
|
-
|
|
221
|
-
volatile VALUE s = rb_sym_to_s(obj);
|
|
194
|
+
static void dump_sym(VALUE obj, int depth, Out out, bool as_ok) {
|
|
195
|
+
volatile VALUE s = rb_sym2str(obj);
|
|
222
196
|
|
|
223
|
-
oj_dump_cstr(
|
|
197
|
+
oj_dump_cstr(RSTRING_PTR(s), (int)RSTRING_LEN(s), 1, 0, out);
|
|
224
198
|
}
|
|
225
199
|
|
|
226
|
-
static int
|
|
227
|
-
|
|
228
|
-
int
|
|
229
|
-
long
|
|
200
|
+
static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
201
|
+
Out out = (Out)ov;
|
|
202
|
+
int depth = out->depth;
|
|
203
|
+
long size = depth * out->indent + 1;
|
|
230
204
|
|
|
231
|
-
if (
|
|
232
|
-
|
|
205
|
+
if (dump_ignore(out->opts, value)) {
|
|
206
|
+
return ST_CONTINUE;
|
|
233
207
|
}
|
|
234
208
|
if (out->omit_nil && Qnil == value) {
|
|
235
|
-
|
|
209
|
+
return ST_CONTINUE;
|
|
236
210
|
}
|
|
237
211
|
assure_size(out, size);
|
|
238
212
|
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
|
-
|
|
213
|
+
switch (rb_type(key)) {
|
|
214
|
+
case T_STRING:
|
|
215
|
+
dump_str_class(key, Qundef, depth, out);
|
|
216
|
+
*out->cur++ = ':';
|
|
217
|
+
oj_dump_obj_val(value, depth, out);
|
|
218
|
+
break;
|
|
219
|
+
|
|
220
|
+
case T_SYMBOL:
|
|
221
|
+
dump_sym(key, 0, out, false);
|
|
222
|
+
*out->cur++ = ':';
|
|
223
|
+
oj_dump_obj_val(value, depth, out);
|
|
224
|
+
break;
|
|
225
|
+
|
|
226
|
+
default:
|
|
227
|
+
{
|
|
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;
|
|
282
259
|
*out->cur++ = ',';
|
|
283
|
-
|
|
260
|
+
|
|
284
261
|
return ST_CONTINUE;
|
|
285
262
|
}
|
|
286
263
|
|
|
287
|
-
static void
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
size_t size;
|
|
264
|
+
static void dump_hash_class(VALUE obj, VALUE clas, int depth, Out out) {
|
|
265
|
+
int cnt;
|
|
266
|
+
size_t size;
|
|
291
267
|
|
|
292
268
|
if (Qundef != clas && rb_cHash != clas) {
|
|
293
|
-
|
|
294
|
-
|
|
269
|
+
dump_obj_attrs(obj, clas, 0, depth, out);
|
|
270
|
+
return;
|
|
295
271
|
}
|
|
296
|
-
cnt
|
|
272
|
+
cnt = (int)RHASH_SIZE(obj);
|
|
297
273
|
size = depth * out->indent + 2;
|
|
298
274
|
assure_size(out, 2);
|
|
299
275
|
if (0 == cnt) {
|
|
300
|
-
|
|
301
|
-
*out->cur++ = '}';
|
|
276
|
+
APPEND_CHARS(out->cur, "{}", 2);
|
|
302
277
|
} 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++ = '}';
|
|
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++ = '}';
|
|
345
314
|
}
|
|
346
315
|
*out->cur = '\0';
|
|
347
316
|
}
|
|
348
317
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
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);
|
|
355
323
|
|
|
356
|
-
if (
|
|
357
|
-
|
|
324
|
+
if (dump_ignore(out->opts, value)) {
|
|
325
|
+
return ST_CONTINUE;
|
|
358
326
|
}
|
|
359
327
|
if (out->omit_nil && Qnil == value) {
|
|
360
|
-
|
|
328
|
+
return ST_CONTINUE;
|
|
361
329
|
}
|
|
362
330
|
// Some exceptions such as NoMethodError have an invisible attribute where
|
|
363
331
|
// the key name is NULL. Not an empty string but NULL.
|
|
364
332
|
if (NULL == attr) {
|
|
365
|
-
|
|
333
|
+
attr = "";
|
|
334
|
+
} else if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
|
|
335
|
+
return ST_CONTINUE;
|
|
366
336
|
}
|
|
367
337
|
if (0 == strcmp("bt", attr) || 0 == strcmp("mesg", attr)) {
|
|
368
|
-
|
|
338
|
+
return ST_CONTINUE;
|
|
369
339
|
}
|
|
370
340
|
assure_size(out, size);
|
|
371
341
|
fill_indent(out, depth);
|
|
372
342
|
if ('@' == *attr) {
|
|
373
|
-
|
|
374
|
-
|
|
343
|
+
attr++;
|
|
344
|
+
oj_dump_cstr(attr, strlen(attr), 0, 0, out);
|
|
375
345
|
} else {
|
|
376
|
-
|
|
346
|
+
char buf[32];
|
|
377
347
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
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);
|
|
382
352
|
}
|
|
383
353
|
*out->cur++ = ':';
|
|
384
354
|
oj_dump_obj_val(value, depth, out);
|
|
385
|
-
out->depth
|
|
355
|
+
out->depth = depth;
|
|
386
356
|
*out->cur++ = ',';
|
|
387
|
-
|
|
357
|
+
|
|
388
358
|
return ST_CONTINUE;
|
|
389
359
|
}
|
|
390
|
-
#endif
|
|
391
360
|
|
|
392
|
-
static void
|
|
393
|
-
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) {
|
|
394
362
|
dump_hash_class(obj, rb_obj_class(obj), depth, out);
|
|
395
363
|
}
|
|
396
364
|
|
|
397
|
-
static void
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
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;
|
|
405
372
|
|
|
406
373
|
assure_size(out, 2);
|
|
407
374
|
*out->cur++ = '{';
|
|
408
375
|
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++ = ',';
|
|
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++ = ',';
|
|
422
385
|
}
|
|
423
386
|
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
|
-
}
|
|
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
|
+
}
|
|
445
405
|
} 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
|
-
|
|
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 = 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
|
+
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--;
|
|
491
453
|
}
|
|
492
454
|
*out->cur++ = '}';
|
|
493
|
-
*out->cur
|
|
455
|
+
*out->cur = '\0';
|
|
494
456
|
}
|
|
495
457
|
|
|
496
|
-
static void
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
int
|
|
500
|
-
|
|
501
|
-
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;
|
|
502
463
|
|
|
503
464
|
if (0 != (odd = oj_get_odd(clas))) {
|
|
504
|
-
|
|
505
|
-
|
|
465
|
+
dump_odd(obj, odd, clas, depth + 1, out);
|
|
466
|
+
return;
|
|
506
467
|
}
|
|
507
468
|
assure_size(out, 2);
|
|
508
469
|
*out->cur++ = '{';
|
|
509
470
|
if (Qundef != clas) {
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
*out->cur++ = 'o';
|
|
518
|
-
*out->cur++ = '"';
|
|
519
|
-
*out->cur++ = ':';
|
|
520
|
-
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);
|
|
521
478
|
}
|
|
522
479
|
if (0 < id) {
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
*out->cur++ = 'i';
|
|
529
|
-
*out->cur++ = '"';
|
|
530
|
-
*out->cur++ = ':';
|
|
531
|
-
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);
|
|
532
485
|
}
|
|
533
486
|
switch (type) {
|
|
534
487
|
case T_STRING:
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
*out->cur++ = 'l';
|
|
542
|
-
*out->cur++ = 'f';
|
|
543
|
-
*out->cur++ = '"';
|
|
544
|
-
*out->cur++ = ':';
|
|
545
|
-
oj_dump_cstr(rb_string_value_ptr((VALUE*)&obj), (int)RSTRING_LEN(obj), 0, 0, out);
|
|
546
|
-
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;
|
|
547
494
|
case T_ARRAY:
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
*out->cur++ = 'l';
|
|
555
|
-
*out->cur++ = 'f';
|
|
556
|
-
*out->cur++ = '"';
|
|
557
|
-
*out->cur++ = ':';
|
|
558
|
-
dump_array_class(obj, Qundef, depth + 1, out);
|
|
559
|
-
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;
|
|
560
501
|
case T_HASH:
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
*out->cur++ = 'f';
|
|
569
|
-
*out->cur++ = '"';
|
|
570
|
-
*out->cur++ = ':';
|
|
571
|
-
dump_hash_class(obj, Qundef, depth + 1, out);
|
|
572
|
-
break;
|
|
573
|
-
default:
|
|
574
|
-
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;
|
|
575
509
|
}
|
|
576
510
|
{
|
|
577
|
-
|
|
578
|
-
|
|
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
|
-
continue;
|
|
621
|
-
}
|
|
622
|
-
if (first) {
|
|
623
|
-
first = 0;
|
|
624
|
-
} else {
|
|
625
|
-
*out->cur++ = ',';
|
|
626
|
-
}
|
|
627
|
-
assure_size(out, size);
|
|
628
|
-
fill_indent(out, d2);
|
|
629
|
-
if ('@' == *attr) {
|
|
630
|
-
attr++;
|
|
631
|
-
oj_dump_cstr(attr, strlen(attr), 0, 0, out);
|
|
632
|
-
} else {
|
|
633
|
-
char buf[32];
|
|
634
|
-
|
|
635
|
-
*buf = '~';
|
|
636
|
-
strncpy(buf + 1, attr, sizeof(buf) - 2);
|
|
637
|
-
buf[sizeof(buf) - 1] = '\0';
|
|
638
|
-
oj_dump_cstr(buf, strlen(attr) + 1, 0, 0, out);
|
|
639
|
-
}
|
|
640
|
-
*out->cur++ = ':';
|
|
641
|
-
oj_dump_obj_val(value, d2, out);
|
|
642
|
-
assure_size(out, 2);
|
|
643
|
-
}
|
|
644
|
-
#endif
|
|
645
|
-
if (rb_obj_is_kind_of(obj, rb_eException)) {
|
|
646
|
-
volatile VALUE rv;
|
|
647
|
-
|
|
648
|
-
if (',' != *(out->cur - 1)) {
|
|
649
|
-
*out->cur++ = ',';
|
|
650
|
-
}
|
|
651
|
-
// message
|
|
652
|
-
assure_size(out, size);
|
|
653
|
-
fill_indent(out, d2);
|
|
654
|
-
oj_dump_cstr("~mesg", 5, 0, 0, out);
|
|
655
|
-
*out->cur++ = ':';
|
|
656
|
-
rv = rb_funcall2(obj, rb_intern("message"), 0, 0);
|
|
657
|
-
oj_dump_obj_val(rv, d2, out);
|
|
658
|
-
assure_size(out, 2);
|
|
659
|
-
*out->cur++ = ',';
|
|
660
|
-
// backtrace
|
|
661
|
-
assure_size(out, size);
|
|
662
|
-
fill_indent(out, d2);
|
|
663
|
-
oj_dump_cstr("~bt", 3, 0, 0, out);
|
|
664
|
-
*out->cur++ = ':';
|
|
665
|
-
rv = rb_funcall2(obj, rb_intern("backtrace"), 0, 0);
|
|
666
|
-
oj_dump_obj_val(rv, d2, out);
|
|
667
|
-
assure_size(out, 2);
|
|
668
|
-
}
|
|
669
|
-
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;
|
|
670
554
|
}
|
|
671
555
|
fill_indent(out, depth);
|
|
672
556
|
*out->cur++ = '}';
|
|
673
|
-
*out->cur
|
|
557
|
+
*out->cur = '\0';
|
|
674
558
|
}
|
|
675
559
|
|
|
676
|
-
static void
|
|
677
|
-
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) {
|
|
678
561
|
dump_obj_attrs(obj, rb_obj_class(obj), 0, depth, out);
|
|
679
562
|
}
|
|
680
563
|
|
|
681
|
-
static void
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
int
|
|
686
|
-
int
|
|
687
|
-
|
|
688
|
-
size_t
|
|
689
|
-
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;
|
|
690
572
|
|
|
691
573
|
assure_size(out, size);
|
|
692
574
|
*out->cur++ = '{';
|
|
693
575
|
fill_indent(out, d2);
|
|
694
|
-
|
|
695
|
-
*out->cur++ = '^';
|
|
696
|
-
*out->cur++ = 'u';
|
|
697
|
-
*out->cur++ = '"';
|
|
698
|
-
*out->cur++ = ':';
|
|
699
|
-
*out->cur++ = '[';
|
|
576
|
+
APPEND_CHARS(out->cur, "\"^u\":[", 6);
|
|
700
577
|
if ('#' == *class_name) {
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
*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++ = ']';
|
|
722
598
|
} else {
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
*out->cur++ = '"';
|
|
599
|
+
fill_indent(out, d3);
|
|
600
|
+
*out->cur++ = '"';
|
|
601
|
+
APPEND_CHARS(out->cur, class_name, len);
|
|
602
|
+
*out->cur++ = '"';
|
|
728
603
|
}
|
|
729
604
|
*out->cur++ = ',';
|
|
730
|
-
size
|
|
605
|
+
size = d3 * out->indent + 2;
|
|
731
606
|
#ifdef RSTRUCT_LEN
|
|
732
607
|
{
|
|
733
|
-
|
|
734
|
-
|
|
608
|
+
VALUE v;
|
|
609
|
+
int cnt;
|
|
735
610
|
#if RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
|
|
736
|
-
|
|
737
|
-
#else
|
|
738
|
-
|
|
739
|
-
#endif
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
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
|
+
}
|
|
751
626
|
}
|
|
752
627
|
#else
|
|
753
628
|
{
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
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
|
+
}
|
|
767
642
|
}
|
|
768
643
|
#endif
|
|
769
644
|
out->cur--;
|
|
770
|
-
|
|
771
|
-
*out->cur
|
|
772
|
-
*out->cur = '\0';
|
|
645
|
+
APPEND_CHARS(out->cur, "]}", 2);
|
|
646
|
+
*out->cur = '\0';
|
|
773
647
|
}
|
|
774
648
|
|
|
775
|
-
static void
|
|
776
|
-
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) {
|
|
777
650
|
dump_obj_attrs(obj, rb_obj_class(obj), 0, depth, out);
|
|
778
651
|
}
|
|
779
652
|
|
|
780
|
-
static void
|
|
781
|
-
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) {
|
|
782
654
|
dump_obj_attrs(obj, rb_obj_class(obj), 0, depth, out);
|
|
783
655
|
}
|
|
784
656
|
|
|
785
|
-
static DumpFunc
|
|
786
|
-
NULL,
|
|
787
|
-
dump_obj,
|
|
788
|
-
dump_class,
|
|
789
|
-
dump_class,
|
|
790
|
-
oj_dump_float,
|
|
791
|
-
dump_str,
|
|
792
|
-
dump_regexp,
|
|
793
|
-
dump_array,
|
|
794
|
-
dump_hash,
|
|
795
|
-
dump_struct,
|
|
796
|
-
oj_dump_bignum,
|
|
797
|
-
NULL,
|
|
798
|
-
dump_data,
|
|
799
|
-
NULL,
|
|
800
|
-
dump_complex,
|
|
801
|
-
dump_rational,
|
|
802
|
-
NULL,
|
|
803
|
-
oj_dump_nil,
|
|
804
|
-
oj_dump_true,
|
|
805
|
-
oj_dump_false,
|
|
806
|
-
dump_sym,
|
|
807
|
-
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,
|
|
808
680
|
};
|
|
809
681
|
|
|
810
|
-
void
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
|
|
682
|
+
void oj_dump_obj_val(VALUE obj, int depth, Out out) {
|
|
683
|
+
int type = rb_type(obj);
|
|
684
|
+
|
|
685
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
|
686
|
+
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
|
|
816
687
|
}
|
|
817
688
|
if (MAX_DEPTH < depth) {
|
|
818
|
-
|
|
689
|
+
rb_raise(rb_eNoMemError, "Too deeply nested.\n");
|
|
819
690
|
}
|
|
820
691
|
if (0 < type && type <= RUBY_T_FIXNUM) {
|
|
821
|
-
|
|
692
|
+
DumpFunc f = obj_funcs[type];
|
|
822
693
|
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
694
|
+
if (NULL != f) {
|
|
695
|
+
f(obj, depth, out, false);
|
|
696
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
|
697
|
+
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
|
|
698
|
+
}
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
830
701
|
}
|
|
831
702
|
oj_dump_nil(Qnil, depth, out, false);
|
|
832
|
-
if (Yes == out->opts->trace) {
|
|
833
|
-
|
|
703
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
|
704
|
+
oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
|
|
834
705
|
}
|
|
835
706
|
}
|