oj 3.7.4 → 3.13.23
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 +1360 -0
- data/README.md +31 -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 +790 -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 +1073 -1088
- data/ext/oj/intern.c +298 -0
- data/ext/oj/intern.h +26 -0
- data/ext/oj/mimic_json.c +469 -436
- data/ext/oj/object.c +532 -599
- data/ext/oj/odd.c +154 -138
- data/ext/oj/odd.h +37 -38
- data/ext/oj/oj.c +1333 -986
- data/ext/oj/oj.h +336 -316
- data/ext/oj/parse.c +1002 -846
- data/ext/oj/parse.h +92 -87
- data/ext/oj/parser.c +1587 -0
- data/ext/oj/parser.h +102 -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 +596 -0
- data/ext/oj/saj2.h +23 -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 +1207 -0
- data/ext/oj/usual.h +68 -0
- data/ext/oj/util.c +136 -0
- data/ext/oj/util.h +20 -0
- data/ext/oj/val_stack.c +60 -68
- 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 +9 -8
- 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 +78 -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 +21 -8
- data/test/json_gem/json_parser_test.rb +8 -1
- 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 +145 -7
- data/test/test_fast.rb +62 -2
- data/test/test_file.rb +23 -7
- data/test/test_gc.rb +11 -0
- data/test/test_generate.rb +21 -0
- data/test/test_hash.rb +11 -1
- data/test/test_integer_range.rb +1 -2
- data/test/test_object.rb +43 -12
- data/test/test_parser.rb +11 -0
- data/test/test_parser_debug.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 +3 -5
- data/test/test_strict.rb +26 -1
- data/test/test_various.rb +86 -65
- data/test/test_wab.rb +2 -0
- data/test/test_writer.rb +19 -2
- data/test/tests.rb +10 -1
- data/test/tests_mimic.rb +9 -0
- data/test/tests_mimic_addition.rb +9 -0
- data/test/zoo.rb +13 -0
- metadata +63 -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/custom.c
CHANGED
|
@@ -1,213 +1,215 @@
|
|
|
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
|
|
|
4
|
+
#include <stdint.h>
|
|
6
5
|
#include <stdio.h>
|
|
7
6
|
|
|
8
7
|
#include "code.h"
|
|
9
8
|
#include "dump.h"
|
|
10
9
|
#include "encode.h"
|
|
11
10
|
#include "err.h"
|
|
12
|
-
#include "
|
|
11
|
+
#include "intern.h"
|
|
13
12
|
#include "odd.h"
|
|
14
13
|
#include "oj.h"
|
|
15
14
|
#include "parse.h"
|
|
16
15
|
#include "resolve.h"
|
|
17
16
|
#include "trace.h"
|
|
17
|
+
#include "util.h"
|
|
18
18
|
|
|
19
|
-
extern void
|
|
20
|
-
extern VALUE
|
|
19
|
+
extern void oj_set_obj_ivar(Val parent, Val kval, VALUE value);
|
|
20
|
+
extern VALUE oj_parse_xml_time(const char *str, int len); // from object.c
|
|
21
21
|
|
|
22
|
-
static void
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
{ NULL, 0, Qnil },
|
|
22
|
+
static void dump_obj_str(VALUE obj, int depth, Out out) {
|
|
23
|
+
struct _attr attrs[] = {
|
|
24
|
+
{"s", 1, Qnil},
|
|
25
|
+
{NULL, 0, Qnil},
|
|
27
26
|
};
|
|
28
27
|
attrs->value = rb_funcall(obj, oj_to_s_id, 0);
|
|
29
28
|
|
|
30
29
|
oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
|
|
31
30
|
}
|
|
32
31
|
|
|
32
|
+
static void dump_obj_as_str(VALUE obj, int depth, Out out) {
|
|
33
|
+
volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
|
|
34
|
+
const char *str = RSTRING_PTR(rstr);
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
oj_dump_cstr(str, RSTRING_LEN(rstr), 0, 0, out);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static void bigdecimal_dump(VALUE obj, int depth, Out out) {
|
|
40
|
+
volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
|
|
41
|
+
const char *str = RSTRING_PTR(rstr);
|
|
42
|
+
int len = (int)RSTRING_LEN(rstr);
|
|
39
43
|
|
|
40
44
|
if (0 == strcasecmp("Infinity", str)) {
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
str = oj_nan_str(obj, out->opts->dump_opts.nan_dump, out->opts->mode, true, &len);
|
|
46
|
+
oj_dump_raw(str, len, out);
|
|
43
47
|
} else if (0 == strcasecmp("-Infinity", str)) {
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
str = oj_nan_str(obj, out->opts->dump_opts.nan_dump, out->opts->mode, false, &len);
|
|
49
|
+
oj_dump_raw(str, len, out);
|
|
46
50
|
} else if (No == out->opts->bigdec_as_num) {
|
|
47
|
-
|
|
51
|
+
oj_dump_cstr(str, len, 0, 0, out);
|
|
48
52
|
} else {
|
|
49
|
-
|
|
53
|
+
oj_dump_raw(str, len, out);
|
|
50
54
|
}
|
|
51
55
|
}
|
|
52
56
|
|
|
53
|
-
static ID
|
|
54
|
-
static ID
|
|
55
|
-
|
|
56
|
-
static void
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
57
|
+
static ID real_id = 0;
|
|
58
|
+
static ID imag_id = 0;
|
|
59
|
+
|
|
60
|
+
static void complex_dump(VALUE obj, int depth, Out out) {
|
|
61
|
+
if (NULL != out->opts->create_id) {
|
|
62
|
+
struct _attr attrs[] = {
|
|
63
|
+
{"real", 4, Qnil},
|
|
64
|
+
{"imag", 4, Qnil},
|
|
65
|
+
{NULL, 0, Qnil},
|
|
66
|
+
};
|
|
67
|
+
if (0 == real_id) {
|
|
68
|
+
real_id = rb_intern("real");
|
|
69
|
+
imag_id = rb_intern("imag");
|
|
70
|
+
}
|
|
71
|
+
attrs[0].value = rb_funcall(obj, real_id, 0);
|
|
72
|
+
attrs[1].value = rb_funcall(obj, imag_id, 0);
|
|
73
|
+
|
|
74
|
+
oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
|
|
75
|
+
} else {
|
|
76
|
+
dump_obj_as_str(obj, depth, out);
|
|
66
77
|
}
|
|
67
|
-
attrs[0].value = rb_funcall(obj, real_id, 0);
|
|
68
|
-
attrs[1].value = rb_funcall(obj, imag_id, 0);
|
|
69
|
-
|
|
70
|
-
oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
|
|
71
78
|
}
|
|
72
79
|
|
|
73
|
-
static VALUE
|
|
74
|
-
complex_load(VALUE clas, VALUE args) {
|
|
80
|
+
static VALUE complex_load(VALUE clas, VALUE args) {
|
|
75
81
|
if (0 == real_id) {
|
|
76
|
-
|
|
77
|
-
|
|
82
|
+
real_id = rb_intern("real");
|
|
83
|
+
imag_id = rb_intern("imag");
|
|
78
84
|
}
|
|
79
85
|
return rb_complex_new(rb_hash_aref(args, rb_id2str(real_id)), rb_hash_aref(args, rb_id2str(imag_id)));
|
|
80
86
|
}
|
|
81
87
|
|
|
82
|
-
static void
|
|
83
|
-
time_dump(VALUE obj, int depth, Out out) {
|
|
88
|
+
static void time_dump(VALUE obj, int depth, Out out) {
|
|
84
89
|
if (Yes == out->opts->create_ok) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
struct _attr attrs[] = {
|
|
91
|
+
{"time", 4, Qundef, 0, Qundef},
|
|
92
|
+
{NULL, 0, Qnil},
|
|
93
|
+
};
|
|
94
|
+
attrs->time = obj;
|
|
90
95
|
|
|
91
|
-
|
|
96
|
+
oj_code_attrs(obj, attrs, depth, out, true);
|
|
92
97
|
} else {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
switch (out->opts->time_format) {
|
|
99
|
+
case RubyTime: oj_dump_ruby_time(obj, out); break;
|
|
100
|
+
case XmlTime: oj_dump_xml_time(obj, out); break;
|
|
101
|
+
case UnixZTime: oj_dump_time(obj, out, true); break;
|
|
102
|
+
case UnixTime:
|
|
103
|
+
default: oj_dump_time(obj, out, false); break;
|
|
104
|
+
}
|
|
100
105
|
}
|
|
101
106
|
}
|
|
102
107
|
|
|
103
|
-
static void
|
|
104
|
-
date_dump(VALUE obj, int depth, Out out) {
|
|
108
|
+
static void date_dump(VALUE obj, int depth, Out out) {
|
|
105
109
|
if (Yes == out->opts->create_ok) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
110
|
+
struct _attr attrs[] = {
|
|
111
|
+
{"s", 1, Qnil},
|
|
112
|
+
{NULL, 0, Qnil},
|
|
113
|
+
};
|
|
114
|
+
attrs->value = rb_funcall(obj, rb_intern("iso8601"), 0);
|
|
111
115
|
|
|
112
|
-
|
|
116
|
+
oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
|
|
113
117
|
} else {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
118
|
+
volatile VALUE v;
|
|
119
|
+
volatile VALUE ov;
|
|
120
|
+
|
|
121
|
+
switch (out->opts->time_format) {
|
|
122
|
+
case RubyTime:
|
|
123
|
+
case XmlTime:
|
|
124
|
+
v = rb_funcall(obj, rb_intern("iso8601"), 0);
|
|
125
|
+
oj_dump_cstr(RSTRING_PTR(v), (int)RSTRING_LEN(v), 0, 0, out);
|
|
126
|
+
break;
|
|
127
|
+
case UnixZTime:
|
|
128
|
+
v = rb_funcall(obj, rb_intern("to_time"), 0);
|
|
129
|
+
if (oj_date_class == rb_obj_class(obj)) {
|
|
130
|
+
ov = rb_funcall(v, rb_intern("utc_offset"), 0);
|
|
131
|
+
v = rb_funcall(v, rb_intern("utc"), 0);
|
|
132
|
+
v = rb_funcall(v, rb_intern("+"), 1, ov);
|
|
133
|
+
oj_dump_time(v, out, false);
|
|
134
|
+
} else {
|
|
135
|
+
oj_dump_time(v, out, true);
|
|
136
|
+
}
|
|
137
|
+
break;
|
|
138
|
+
case UnixTime:
|
|
139
|
+
default:
|
|
140
|
+
v = rb_funcall(obj, rb_intern("to_time"), 0);
|
|
141
|
+
if (oj_date_class == rb_obj_class(obj)) {
|
|
142
|
+
ov = rb_funcall(v, rb_intern("utc_offset"), 0);
|
|
143
|
+
v = rb_funcall(v, rb_intern("utc"), 0);
|
|
144
|
+
v = rb_funcall(v, rb_intern("+"), 1, ov);
|
|
145
|
+
}
|
|
146
|
+
oj_dump_time(v, out, false);
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
145
149
|
}
|
|
146
150
|
}
|
|
147
151
|
|
|
148
|
-
static VALUE
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
+
static VALUE date_load(VALUE clas, VALUE args) {
|
|
153
|
+
volatile VALUE v;
|
|
154
|
+
|
|
152
155
|
if (Qnil != (v = rb_hash_aref(args, rb_str_new2("s")))) {
|
|
153
|
-
|
|
156
|
+
return rb_funcall(oj_date_class, rb_intern("parse"), 1, v);
|
|
154
157
|
}
|
|
155
158
|
return Qnil;
|
|
156
159
|
}
|
|
157
160
|
|
|
158
|
-
static VALUE
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
161
|
+
static VALUE datetime_load(VALUE clas, VALUE args) {
|
|
162
|
+
volatile VALUE v;
|
|
163
|
+
|
|
162
164
|
if (Qnil != (v = rb_hash_aref(args, rb_str_new2("s")))) {
|
|
163
|
-
|
|
165
|
+
return rb_funcall(oj_datetime_class, rb_intern("parse"), 1, v);
|
|
164
166
|
}
|
|
165
167
|
return Qnil;
|
|
166
168
|
}
|
|
167
169
|
|
|
168
|
-
static ID
|
|
170
|
+
static ID table_id = 0;
|
|
169
171
|
|
|
170
|
-
static void
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
{ NULL, 0, Qnil },
|
|
172
|
+
static void openstruct_dump(VALUE obj, int depth, Out out) {
|
|
173
|
+
struct _attr attrs[] = {
|
|
174
|
+
{"table", 5, Qnil},
|
|
175
|
+
{NULL, 0, Qnil},
|
|
175
176
|
};
|
|
176
177
|
if (0 == table_id) {
|
|
177
|
-
|
|
178
|
+
table_id = rb_intern("table");
|
|
178
179
|
}
|
|
179
180
|
attrs->value = rb_funcall(obj, table_id, 0);
|
|
180
181
|
|
|
181
182
|
oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
|
|
182
183
|
}
|
|
183
184
|
|
|
184
|
-
static VALUE
|
|
185
|
-
openstruct_load(VALUE clas, VALUE args) {
|
|
185
|
+
static VALUE openstruct_load(VALUE clas, VALUE args) {
|
|
186
186
|
if (0 == table_id) {
|
|
187
|
-
|
|
187
|
+
table_id = rb_intern("table");
|
|
188
188
|
}
|
|
189
189
|
return rb_funcall(clas, oj_new_id, 1, rb_hash_aref(args, rb_id2str(table_id)));
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
-
static void
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
192
|
+
static void range_dump(VALUE obj, int depth, Out out) {
|
|
193
|
+
if (NULL != out->opts->create_id) {
|
|
194
|
+
struct _attr attrs[] = {
|
|
195
|
+
{"begin", 5, Qnil},
|
|
196
|
+
{"end", 3, Qnil},
|
|
197
|
+
{"exclude", 7, Qnil},
|
|
198
|
+
{NULL, 0, Qnil},
|
|
199
|
+
};
|
|
200
|
+
attrs[0].value = rb_funcall(obj, oj_begin_id, 0);
|
|
201
|
+
attrs[1].value = rb_funcall(obj, oj_end_id, 0);
|
|
202
|
+
attrs[2].value = rb_funcall(obj, oj_exclude_end_id, 0);
|
|
203
|
+
|
|
204
|
+
oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
|
|
205
|
+
} else {
|
|
206
|
+
dump_obj_as_str(obj, depth, out);
|
|
207
|
+
}
|
|
205
208
|
}
|
|
206
209
|
|
|
207
|
-
static VALUE
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
210
|
+
static VALUE range_load(VALUE clas, VALUE args) {
|
|
211
|
+
VALUE nargs[3];
|
|
212
|
+
|
|
211
213
|
nargs[0] = rb_hash_aref(args, rb_id2str(oj_begin_id));
|
|
212
214
|
nargs[1] = rb_hash_aref(args, rb_id2str(oj_end_id));
|
|
213
215
|
nargs[2] = rb_hash_aref(args, rb_id2str(oj_exclude_end_id));
|
|
@@ -215,966 +217,888 @@ range_load(VALUE clas, VALUE args) {
|
|
|
215
217
|
return rb_class_new_instance(3, nargs, rb_cRange);
|
|
216
218
|
}
|
|
217
219
|
|
|
218
|
-
static ID
|
|
219
|
-
static ID
|
|
220
|
-
|
|
221
|
-
static void
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
220
|
+
static ID numerator_id = 0;
|
|
221
|
+
static ID denominator_id = 0;
|
|
222
|
+
|
|
223
|
+
static void rational_dump(VALUE obj, int depth, Out out) {
|
|
224
|
+
if (NULL != out->opts->create_id) {
|
|
225
|
+
struct _attr attrs[] = {
|
|
226
|
+
{"numerator", 9, Qnil},
|
|
227
|
+
{"denominator", 11, Qnil},
|
|
228
|
+
{NULL, 0, Qnil},
|
|
229
|
+
};
|
|
230
|
+
if (0 == numerator_id) {
|
|
231
|
+
numerator_id = rb_intern("numerator");
|
|
232
|
+
denominator_id = rb_intern("denominator");
|
|
233
|
+
}
|
|
234
|
+
attrs[0].value = rb_funcall(obj, numerator_id, 0);
|
|
235
|
+
attrs[1].value = rb_funcall(obj, denominator_id, 0);
|
|
236
|
+
|
|
237
|
+
oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
|
|
238
|
+
} else {
|
|
239
|
+
dump_obj_as_str(obj, depth, out);
|
|
231
240
|
}
|
|
232
|
-
attrs[0].value = rb_funcall(obj, numerator_id, 0);
|
|
233
|
-
attrs[1].value = rb_funcall(obj, denominator_id, 0);
|
|
234
|
-
|
|
235
|
-
oj_code_attrs(obj, attrs, depth, out, Yes == out->opts->create_ok);
|
|
236
241
|
}
|
|
237
242
|
|
|
238
|
-
static VALUE
|
|
239
|
-
rational_load(VALUE clas, VALUE args) {
|
|
243
|
+
static VALUE rational_load(VALUE clas, VALUE args) {
|
|
240
244
|
if (0 == numerator_id) {
|
|
241
|
-
|
|
242
|
-
|
|
245
|
+
numerator_id = rb_intern("numerator");
|
|
246
|
+
denominator_id = rb_intern("denominator");
|
|
243
247
|
}
|
|
244
|
-
return rb_rational_new(rb_hash_aref(args, rb_id2str(numerator_id)),
|
|
245
|
-
rb_hash_aref(args, rb_id2str(denominator_id)));
|
|
248
|
+
return rb_rational_new(rb_hash_aref(args, rb_id2str(numerator_id)), rb_hash_aref(args, rb_id2str(denominator_id)));
|
|
246
249
|
}
|
|
247
250
|
|
|
248
|
-
static VALUE
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
251
|
+
static VALUE regexp_load(VALUE clas, VALUE args) {
|
|
252
|
+
volatile VALUE v;
|
|
253
|
+
|
|
252
254
|
if (Qnil != (v = rb_hash_aref(args, rb_str_new2("s")))) {
|
|
253
|
-
|
|
255
|
+
return rb_funcall(rb_cRegexp, oj_new_id, 1, v);
|
|
254
256
|
}
|
|
255
257
|
return Qnil;
|
|
256
258
|
}
|
|
257
259
|
|
|
258
|
-
static VALUE
|
|
259
|
-
time_load(VALUE clas, VALUE args) {
|
|
260
|
+
static VALUE time_load(VALUE clas, VALUE args) {
|
|
260
261
|
// Value should have already been replaced in one of the hash_set_xxx
|
|
261
262
|
// functions.
|
|
262
263
|
return args;
|
|
263
264
|
}
|
|
264
265
|
|
|
265
|
-
static struct
|
|
266
|
-
{
|
|
267
|
-
{
|
|
268
|
-
{
|
|
269
|
-
{
|
|
270
|
-
{
|
|
271
|
-
{
|
|
272
|
-
{
|
|
273
|
-
{
|
|
274
|
-
{
|
|
275
|
-
{
|
|
266
|
+
static struct _code codes[] = {
|
|
267
|
+
{"BigDecimal", Qnil, bigdecimal_dump, NULL, true},
|
|
268
|
+
{"Complex", Qnil, complex_dump, complex_load, true},
|
|
269
|
+
{"Date", Qnil, date_dump, date_load, true},
|
|
270
|
+
{"DateTime", Qnil, date_dump, datetime_load, true},
|
|
271
|
+
{"OpenStruct", Qnil, openstruct_dump, openstruct_load, true},
|
|
272
|
+
{"Range", Qnil, range_dump, range_load, true},
|
|
273
|
+
{"Rational", Qnil, rational_dump, rational_load, true},
|
|
274
|
+
{"Regexp", Qnil, dump_obj_str, regexp_load, true},
|
|
275
|
+
{"Time", Qnil, time_dump, time_load, true},
|
|
276
|
+
{NULL, Qundef, NULL, NULL, false},
|
|
276
277
|
};
|
|
277
278
|
|
|
278
|
-
static int
|
|
279
|
-
|
|
280
|
-
int
|
|
279
|
+
static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
280
|
+
Out out = (Out)ov;
|
|
281
|
+
int depth = out->depth;
|
|
281
282
|
|
|
282
|
-
if (
|
|
283
|
-
|
|
283
|
+
if (dump_ignore(out->opts, value)) {
|
|
284
|
+
return ST_CONTINUE;
|
|
284
285
|
}
|
|
285
286
|
if (out->omit_nil && Qnil == value) {
|
|
286
|
-
|
|
287
|
+
return ST_CONTINUE;
|
|
287
288
|
}
|
|
288
289
|
if (!out->opts->dump_opts.use) {
|
|
289
|
-
|
|
290
|
-
|
|
290
|
+
assure_size(out, depth * out->indent + 1);
|
|
291
|
+
fill_indent(out, depth);
|
|
291
292
|
} else {
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
}
|
|
304
|
-
}
|
|
293
|
+
assure_size(out, depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1);
|
|
294
|
+
if (0 < out->opts->dump_opts.hash_size) {
|
|
295
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.hash_nl, out->opts->dump_opts.hash_size);
|
|
296
|
+
}
|
|
297
|
+
if (0 < out->opts->dump_opts.indent_size) {
|
|
298
|
+
int i;
|
|
299
|
+
|
|
300
|
+
for (i = depth; 0 < i; i--) {
|
|
301
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
305
304
|
}
|
|
306
305
|
switch (rb_type(key)) {
|
|
307
|
-
case T_STRING:
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
case T_SYMBOL:
|
|
311
|
-
oj_dump_sym(key, 0, out, false);
|
|
312
|
-
break;
|
|
313
|
-
default:
|
|
314
|
-
oj_dump_str(rb_funcall(key, oj_to_s_id, 0), 0, out, false);
|
|
315
|
-
break;
|
|
306
|
+
case T_STRING: oj_dump_str(key, 0, out, false); break;
|
|
307
|
+
case T_SYMBOL: oj_dump_sym(key, 0, out, false); break;
|
|
308
|
+
default: oj_dump_str(rb_funcall(key, oj_to_s_id, 0), 0, out, false); break;
|
|
316
309
|
}
|
|
317
310
|
if (!out->opts->dump_opts.use) {
|
|
318
|
-
|
|
311
|
+
*out->cur++ = ':';
|
|
319
312
|
} else {
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
out->cur += out->opts->dump_opts.after_size;
|
|
329
|
-
}
|
|
313
|
+
assure_size(out, out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2);
|
|
314
|
+
if (0 < out->opts->dump_opts.before_size) {
|
|
315
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
|
|
316
|
+
}
|
|
317
|
+
*out->cur++ = ':';
|
|
318
|
+
if (0 < out->opts->dump_opts.after_size) {
|
|
319
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
|
|
320
|
+
}
|
|
330
321
|
}
|
|
331
322
|
oj_dump_custom_val(value, depth, out, true);
|
|
332
|
-
out->depth
|
|
323
|
+
out->depth = depth;
|
|
333
324
|
*out->cur++ = ',';
|
|
334
325
|
|
|
335
326
|
return ST_CONTINUE;
|
|
336
327
|
}
|
|
337
328
|
|
|
338
|
-
static void
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
long id = oj_check_circular(obj, out);
|
|
329
|
+
static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
|
|
330
|
+
int cnt;
|
|
331
|
+
long id = oj_check_circular(obj, out);
|
|
342
332
|
|
|
343
333
|
if (0 > id) {
|
|
344
|
-
|
|
345
|
-
|
|
334
|
+
oj_dump_nil(Qnil, depth, out, false);
|
|
335
|
+
return;
|
|
346
336
|
}
|
|
347
337
|
cnt = (int)RHASH_SIZE(obj);
|
|
348
338
|
assure_size(out, 2);
|
|
349
339
|
if (0 == cnt) {
|
|
350
|
-
|
|
351
|
-
*out->cur++ = '}';
|
|
340
|
+
APPEND_CHARS(out->cur, "{}", 2);
|
|
352
341
|
} else {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
}
|
|
377
|
-
*out->cur++ = '}';
|
|
342
|
+
*out->cur++ = '{';
|
|
343
|
+
out->depth = depth + 1;
|
|
344
|
+
rb_hash_foreach(obj, hash_cb, (VALUE)out);
|
|
345
|
+
if (',' == *(out->cur - 1)) {
|
|
346
|
+
out->cur--; // backup to overwrite last comma
|
|
347
|
+
}
|
|
348
|
+
if (!out->opts->dump_opts.use) {
|
|
349
|
+
assure_size(out, depth * out->indent + 2);
|
|
350
|
+
fill_indent(out, depth);
|
|
351
|
+
} else {
|
|
352
|
+
assure_size(out, depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1);
|
|
353
|
+
if (0 < out->opts->dump_opts.hash_size) {
|
|
354
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.hash_nl, out->opts->dump_opts.hash_size);
|
|
355
|
+
}
|
|
356
|
+
if (0 < out->opts->dump_opts.indent_size) {
|
|
357
|
+
int i;
|
|
358
|
+
|
|
359
|
+
for (i = depth; 0 < i; i--) {
|
|
360
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
*out->cur++ = '}';
|
|
378
365
|
}
|
|
379
366
|
*out->cur = '\0';
|
|
380
367
|
}
|
|
381
368
|
|
|
382
|
-
static void
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
int d2 = depth + 1;
|
|
369
|
+
static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
|
|
370
|
+
ID *idp;
|
|
371
|
+
AttrGetFunc *fp;
|
|
372
|
+
volatile VALUE v;
|
|
373
|
+
const char *name;
|
|
374
|
+
size_t size;
|
|
375
|
+
int d2 = depth + 1;
|
|
390
376
|
|
|
391
377
|
assure_size(out, 2);
|
|
392
378
|
*out->cur++ = '{';
|
|
393
379
|
if (NULL != out->opts->create_id && Yes == out->opts->create_ok) {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
*out->cur++ = '"';
|
|
415
|
-
memcpy(out->cur, classname, clen);
|
|
416
|
-
out->cur += clen;
|
|
417
|
-
*out->cur++ = '"';
|
|
418
|
-
*out->cur++ = ',';
|
|
380
|
+
const char *classname = rb_class2name(clas);
|
|
381
|
+
int clen = (int)strlen(classname);
|
|
382
|
+
size_t sep_len = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
|
|
383
|
+
|
|
384
|
+
size = d2 * out->indent + 10 + clen + out->opts->create_id_len + sep_len;
|
|
385
|
+
assure_size(out, size);
|
|
386
|
+
fill_indent(out, d2);
|
|
387
|
+
*out->cur++ = '"';
|
|
388
|
+
APPEND_CHARS(out->cur, out->opts->create_id, out->opts->create_id_len);
|
|
389
|
+
*out->cur++ = '"';
|
|
390
|
+
if (0 < out->opts->dump_opts.before_size) {
|
|
391
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
|
|
392
|
+
}
|
|
393
|
+
*out->cur++ = ':';
|
|
394
|
+
if (0 < out->opts->dump_opts.after_size) {
|
|
395
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
|
|
396
|
+
}
|
|
397
|
+
*out->cur++ = '"';
|
|
398
|
+
APPEND_CHARS(out->cur, classname, clen);
|
|
399
|
+
APPEND_CHARS(out->cur, "\",", 2);
|
|
419
400
|
}
|
|
420
401
|
if (odd->raw) {
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
out->cur += len;
|
|
440
|
-
*out->cur = '\0';
|
|
441
|
-
}
|
|
402
|
+
v = rb_funcall(obj, *odd->attrs, 0);
|
|
403
|
+
if (Qundef == v || T_STRING != rb_type(v)) {
|
|
404
|
+
rb_raise(rb_eEncodingError, "Invalid type for raw JSON.\n");
|
|
405
|
+
} else {
|
|
406
|
+
const char *s = RSTRING_PTR(v);
|
|
407
|
+
int len = (int)RSTRING_LEN(v);
|
|
408
|
+
const char *name = rb_id2name(*odd->attrs);
|
|
409
|
+
size_t nlen = strlen(name);
|
|
410
|
+
|
|
411
|
+
size = len + d2 * out->indent + nlen + 10;
|
|
412
|
+
assure_size(out, size);
|
|
413
|
+
fill_indent(out, d2);
|
|
414
|
+
*out->cur++ = '"';
|
|
415
|
+
APPEND_CHARS(out->cur, name, nlen);
|
|
416
|
+
APPEND_CHARS(out->cur, "\":", 2);
|
|
417
|
+
APPEND_CHARS(out->cur, s, len);
|
|
418
|
+
*out->cur = '\0';
|
|
419
|
+
}
|
|
442
420
|
} else {
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
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
|
-
|
|
421
|
+
size = d2 * out->indent + 1;
|
|
422
|
+
for (idp = odd->attrs, fp = odd->attrFuncs; 0 != *idp; idp++, fp++) {
|
|
423
|
+
size_t nlen;
|
|
424
|
+
|
|
425
|
+
assure_size(out, size);
|
|
426
|
+
name = rb_id2name(*idp);
|
|
427
|
+
nlen = strlen(name);
|
|
428
|
+
if (0 != *fp) {
|
|
429
|
+
v = (*fp)(obj);
|
|
430
|
+
} else if (0 == strchr(name, '.')) {
|
|
431
|
+
v = rb_funcall(obj, *idp, 0);
|
|
432
|
+
} else {
|
|
433
|
+
char nbuf[256];
|
|
434
|
+
char *n2 = nbuf;
|
|
435
|
+
char *n;
|
|
436
|
+
char *end;
|
|
437
|
+
ID i;
|
|
438
|
+
|
|
439
|
+
if (sizeof(nbuf) <= nlen) {
|
|
440
|
+
if (NULL == (n2 = strdup(name))) {
|
|
441
|
+
rb_raise(rb_eNoMemError, "for attribute name.");
|
|
442
|
+
}
|
|
443
|
+
} else {
|
|
444
|
+
strcpy(n2, name);
|
|
445
|
+
}
|
|
446
|
+
n = n2;
|
|
447
|
+
v = obj;
|
|
448
|
+
while (0 != (end = strchr(n, '.'))) {
|
|
449
|
+
*end = '\0';
|
|
450
|
+
i = rb_intern(n);
|
|
451
|
+
v = rb_funcall(v, i, 0);
|
|
452
|
+
n = end + 1;
|
|
453
|
+
}
|
|
454
|
+
i = rb_intern(n);
|
|
455
|
+
v = rb_funcall(v, i, 0);
|
|
456
|
+
if (nbuf != n2) {
|
|
457
|
+
free(n2);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
fill_indent(out, d2);
|
|
461
|
+
oj_dump_cstr(name, nlen, 0, 0, out);
|
|
462
|
+
*out->cur++ = ':';
|
|
463
|
+
oj_dump_custom_val(v, d2, out, true);
|
|
464
|
+
assure_size(out, 2);
|
|
465
|
+
*out->cur++ = ',';
|
|
466
|
+
}
|
|
467
|
+
out->cur--;
|
|
488
468
|
}
|
|
489
469
|
*out->cur++ = '}';
|
|
490
|
-
*out->cur
|
|
470
|
+
*out->cur = '\0';
|
|
491
471
|
}
|
|
492
472
|
|
|
493
473
|
// Return class if still needs dumping.
|
|
494
|
-
static VALUE
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
474
|
+
static VALUE dump_common(VALUE obj, int depth, Out out) {
|
|
475
|
+
if (Yes == out->opts->raw_json && rb_respond_to(obj, oj_raw_json_id)) {
|
|
476
|
+
oj_dump_raw_json(obj, depth, out);
|
|
477
|
+
} else if (Yes == out->opts->to_json && rb_respond_to(obj, oj_to_json_id)) {
|
|
478
|
+
volatile VALUE rs;
|
|
479
|
+
const char *s;
|
|
480
|
+
int len;
|
|
481
|
+
|
|
482
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
|
483
|
+
oj_trace("to_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyIn);
|
|
484
|
+
}
|
|
485
|
+
if (0 == rb_obj_method_arity(obj, oj_to_json_id)) {
|
|
486
|
+
rs = rb_funcall(obj, oj_to_json_id, 0);
|
|
487
|
+
} else {
|
|
488
|
+
rs = rb_funcall2(obj, oj_to_json_id, out->argc, out->argv);
|
|
489
|
+
}
|
|
490
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
|
491
|
+
oj_trace("to_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyOut);
|
|
492
|
+
}
|
|
493
|
+
s = RSTRING_PTR(rs);
|
|
494
|
+
len = (int)RSTRING_LEN(rs);
|
|
495
|
+
|
|
496
|
+
assure_size(out, len + 1);
|
|
497
|
+
APPEND_CHARS(out->cur, s, len);
|
|
498
|
+
*out->cur = '\0';
|
|
519
499
|
} else if (Yes == out->opts->as_json && rb_respond_to(obj, oj_as_json_id)) {
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
500
|
+
volatile VALUE aj;
|
|
501
|
+
|
|
502
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
|
503
|
+
oj_trace("as_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyIn);
|
|
504
|
+
}
|
|
505
|
+
// Some classes elect to not take an options argument so check the arity
|
|
506
|
+
// of as_json.
|
|
507
|
+
if (0 == rb_obj_method_arity(obj, oj_as_json_id)) {
|
|
508
|
+
aj = rb_funcall(obj, oj_as_json_id, 0);
|
|
509
|
+
} else {
|
|
510
|
+
aj = rb_funcall2(obj, oj_as_json_id, out->argc, out->argv);
|
|
511
|
+
}
|
|
512
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
|
513
|
+
oj_trace("as_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyOut);
|
|
514
|
+
}
|
|
515
|
+
// Catch the obvious brain damaged recursive dumping.
|
|
516
|
+
if (aj == obj) {
|
|
517
|
+
volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
|
|
518
|
+
|
|
519
|
+
oj_dump_cstr(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), false, false, out);
|
|
520
|
+
} else {
|
|
521
|
+
oj_dump_custom_val(aj, depth, out, true);
|
|
522
|
+
}
|
|
543
523
|
} else if (Yes == out->opts->to_hash && rb_respond_to(obj, oj_to_hash_id)) {
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
524
|
+
volatile VALUE h = rb_funcall(obj, oj_to_hash_id, 0);
|
|
525
|
+
|
|
526
|
+
if (T_HASH != rb_type(h)) {
|
|
527
|
+
// It seems that ActiveRecord implemented to_hash so that it returns
|
|
528
|
+
// an Array and not a Hash. To get around that any value returned
|
|
529
|
+
// will be dumped.
|
|
530
|
+
|
|
531
|
+
// rb_raise(rb_eTypeError, "%s.to_hash() did not return a Hash.\n",
|
|
532
|
+
// rb_class2name(rb_obj_class(obj)));
|
|
533
|
+
oj_dump_custom_val(h, depth, out, false);
|
|
534
|
+
} else {
|
|
535
|
+
dump_hash(h, depth, out, true);
|
|
536
|
+
}
|
|
556
537
|
} else if (!oj_code_dump(codes, obj, depth, out)) {
|
|
557
|
-
|
|
558
|
-
|
|
538
|
+
VALUE clas = rb_obj_class(obj);
|
|
539
|
+
Odd odd = oj_get_odd(clas);
|
|
559
540
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
541
|
+
if (NULL == odd) {
|
|
542
|
+
return clas;
|
|
543
|
+
}
|
|
544
|
+
dump_odd(obj, odd, clas, depth + 1, out);
|
|
564
545
|
}
|
|
565
546
|
return Qnil;
|
|
566
547
|
}
|
|
567
548
|
|
|
568
|
-
static int
|
|
569
|
-
|
|
570
|
-
int
|
|
571
|
-
size_t
|
|
572
|
-
const char
|
|
549
|
+
static int dump_attr_cb(ID key, VALUE value, VALUE ov) {
|
|
550
|
+
Out out = (Out)ov;
|
|
551
|
+
int depth = out->depth;
|
|
552
|
+
size_t size;
|
|
553
|
+
const char *attr;
|
|
573
554
|
|
|
574
|
-
if (
|
|
575
|
-
|
|
555
|
+
if (dump_ignore(out->opts, value)) {
|
|
556
|
+
return ST_CONTINUE;
|
|
576
557
|
}
|
|
577
558
|
if (out->omit_nil && Qnil == value) {
|
|
578
|
-
|
|
559
|
+
return ST_CONTINUE;
|
|
579
560
|
}
|
|
580
561
|
size = depth * out->indent + 1;
|
|
581
562
|
attr = rb_id2name(key);
|
|
582
563
|
// Some exceptions such as NoMethodError have an invisible attribute where
|
|
583
564
|
// the key name is NULL. Not an empty string but NULL.
|
|
584
565
|
if (NULL == attr) {
|
|
585
|
-
|
|
566
|
+
attr = "";
|
|
567
|
+
} else if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
|
|
568
|
+
return ST_CONTINUE;
|
|
586
569
|
}
|
|
587
570
|
if (0 == strcmp("bt", attr) || 0 == strcmp("mesg", attr)) {
|
|
588
|
-
|
|
571
|
+
return ST_CONTINUE;
|
|
589
572
|
}
|
|
590
573
|
assure_size(out, size);
|
|
591
574
|
fill_indent(out, depth);
|
|
592
575
|
if ('@' == *attr) {
|
|
593
|
-
|
|
594
|
-
|
|
576
|
+
attr++;
|
|
577
|
+
oj_dump_cstr(attr, strlen(attr), 0, 0, out);
|
|
595
578
|
} else {
|
|
596
|
-
|
|
579
|
+
char buf[32];
|
|
597
580
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
581
|
+
*buf = '~';
|
|
582
|
+
strncpy(buf + 1, attr, sizeof(buf) - 2);
|
|
583
|
+
buf[sizeof(buf) - 1] = '\0';
|
|
584
|
+
oj_dump_cstr(buf, strlen(buf), 0, 0, out);
|
|
602
585
|
}
|
|
603
586
|
*out->cur++ = ':';
|
|
604
587
|
oj_dump_custom_val(value, depth, out, true);
|
|
605
|
-
out->depth
|
|
588
|
+
out->depth = depth;
|
|
606
589
|
*out->cur++ = ',';
|
|
607
|
-
|
|
590
|
+
|
|
608
591
|
return ST_CONTINUE;
|
|
609
592
|
}
|
|
610
593
|
|
|
611
|
-
static void
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
int
|
|
615
|
-
|
|
616
|
-
bool class_written = false;
|
|
594
|
+
static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out) {
|
|
595
|
+
size_t size = 0;
|
|
596
|
+
int d2 = depth + 1;
|
|
597
|
+
int cnt;
|
|
598
|
+
bool class_written = false;
|
|
617
599
|
|
|
618
600
|
assure_size(out, 2);
|
|
619
601
|
*out->cur++ = '{';
|
|
620
602
|
if (Qundef != clas && NULL != out->opts->create_id && Yes == out->opts->create_ok) {
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
memcpy(out->cur, classname, len);
|
|
643
|
-
out->cur += len;
|
|
644
|
-
*out->cur++ = '"';
|
|
645
|
-
class_written = true;
|
|
603
|
+
size_t sep_len = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
|
|
604
|
+
const char *classname = rb_obj_classname(obj);
|
|
605
|
+
size_t len = strlen(classname);
|
|
606
|
+
|
|
607
|
+
size = d2 * out->indent + 10 + len + out->opts->create_id_len + sep_len;
|
|
608
|
+
assure_size(out, size);
|
|
609
|
+
fill_indent(out, d2);
|
|
610
|
+
*out->cur++ = '"';
|
|
611
|
+
APPEND_CHARS(out->cur, out->opts->create_id, out->opts->create_id_len);
|
|
612
|
+
*out->cur++ = '"';
|
|
613
|
+
if (0 < out->opts->dump_opts.before_size) {
|
|
614
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
|
|
615
|
+
}
|
|
616
|
+
*out->cur++ = ':';
|
|
617
|
+
if (0 < out->opts->dump_opts.after_size) {
|
|
618
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
|
|
619
|
+
}
|
|
620
|
+
*out->cur++ = '"';
|
|
621
|
+
APPEND_CHARS(out->cur, classname, len);
|
|
622
|
+
*out->cur++ = '"';
|
|
623
|
+
class_written = true;
|
|
646
624
|
}
|
|
647
625
|
cnt = (int)rb_ivar_count(obj);
|
|
648
626
|
if (class_written) {
|
|
649
|
-
|
|
627
|
+
*out->cur++ = ',';
|
|
650
628
|
}
|
|
651
629
|
if (0 == cnt && Qundef == clas) {
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
630
|
+
// Might be something special like an Enumerable.
|
|
631
|
+
if (Qtrue == rb_obj_is_kind_of(obj, oj_enumerable_class)) {
|
|
632
|
+
out->cur--;
|
|
633
|
+
oj_dump_custom_val(rb_funcall(obj, rb_intern("entries"), 0), depth, out, false);
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
658
636
|
}
|
|
659
637
|
out->depth = depth + 1;
|
|
660
638
|
rb_ivar_foreach(obj, dump_attr_cb, (VALUE)out);
|
|
661
639
|
if (',' == *(out->cur - 1)) {
|
|
662
|
-
|
|
640
|
+
out->cur--; // backup to overwrite last comma
|
|
663
641
|
}
|
|
664
642
|
if (rb_obj_is_kind_of(obj, rb_eException)) {
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
643
|
+
volatile VALUE rv;
|
|
644
|
+
|
|
645
|
+
if (',' != *(out->cur - 1)) {
|
|
646
|
+
*out->cur++ = ',';
|
|
647
|
+
}
|
|
648
|
+
// message
|
|
649
|
+
assure_size(out, 2);
|
|
650
|
+
fill_indent(out, d2);
|
|
651
|
+
oj_dump_cstr("~mesg", 5, 0, 0, out);
|
|
652
|
+
*out->cur++ = ':';
|
|
653
|
+
rv = rb_funcall2(obj, rb_intern("message"), 0, 0);
|
|
654
|
+
oj_dump_custom_val(rv, d2, out, true);
|
|
655
|
+
assure_size(out, size + 2);
|
|
656
|
+
*out->cur++ = ',';
|
|
657
|
+
// backtrace
|
|
658
|
+
fill_indent(out, d2);
|
|
659
|
+
oj_dump_cstr("~bt", 3, 0, 0, out);
|
|
660
|
+
*out->cur++ = ':';
|
|
661
|
+
rv = rb_funcall2(obj, rb_intern("backtrace"), 0, 0);
|
|
662
|
+
oj_dump_custom_val(rv, d2, out, true);
|
|
663
|
+
assure_size(out, 2);
|
|
686
664
|
}
|
|
687
665
|
out->depth = depth;
|
|
688
666
|
|
|
689
667
|
fill_indent(out, depth);
|
|
690
668
|
*out->cur++ = '}';
|
|
691
|
-
*out->cur
|
|
669
|
+
*out->cur = '\0';
|
|
692
670
|
}
|
|
693
671
|
|
|
694
|
-
static void
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
VALUE clas;
|
|
672
|
+
static void dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
|
|
673
|
+
long id = oj_check_circular(obj, out);
|
|
674
|
+
VALUE clas;
|
|
698
675
|
|
|
699
676
|
if (0 > id) {
|
|
700
|
-
|
|
677
|
+
oj_dump_nil(Qnil, depth, out, false);
|
|
701
678
|
} else if (Qnil != (clas = dump_common(obj, depth, out))) {
|
|
702
|
-
|
|
679
|
+
dump_obj_attrs(obj, clas, 0, depth, out);
|
|
703
680
|
}
|
|
704
681
|
*out->cur = '\0';
|
|
705
682
|
}
|
|
706
683
|
|
|
707
|
-
static void
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
int
|
|
711
|
-
|
|
712
|
-
long id = oj_check_circular(a, out);
|
|
684
|
+
static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
|
|
685
|
+
size_t size;
|
|
686
|
+
int i, cnt;
|
|
687
|
+
int d2 = depth + 1;
|
|
688
|
+
long id = oj_check_circular(a, out);
|
|
713
689
|
|
|
714
690
|
if (0 > id) {
|
|
715
|
-
|
|
716
|
-
|
|
691
|
+
oj_dump_nil(Qnil, depth, out, false);
|
|
692
|
+
return;
|
|
717
693
|
}
|
|
718
|
-
cnt
|
|
694
|
+
cnt = (int)RARRAY_LEN(a);
|
|
719
695
|
*out->cur++ = '[';
|
|
720
696
|
assure_size(out, 2);
|
|
721
697
|
if (0 == cnt) {
|
|
722
|
-
|
|
698
|
+
*out->cur++ = ']';
|
|
723
699
|
} else {
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
} else {
|
|
768
|
-
fill_indent(out, depth);
|
|
769
|
-
}
|
|
770
|
-
*out->cur++ = ']';
|
|
700
|
+
if (out->opts->dump_opts.use) {
|
|
701
|
+
size = d2 * out->opts->dump_opts.indent_size + out->opts->dump_opts.array_size + 1;
|
|
702
|
+
} else {
|
|
703
|
+
size = d2 * out->indent + 2;
|
|
704
|
+
}
|
|
705
|
+
assure_size(out, size * cnt);
|
|
706
|
+
cnt--;
|
|
707
|
+
for (i = 0; i <= cnt; i++) {
|
|
708
|
+
if (out->opts->dump_opts.use) {
|
|
709
|
+
if (0 < out->opts->dump_opts.array_size) {
|
|
710
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
|
|
711
|
+
}
|
|
712
|
+
if (0 < out->opts->dump_opts.indent_size) {
|
|
713
|
+
int i;
|
|
714
|
+
for (i = d2; 0 < i; i--) {
|
|
715
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
} else {
|
|
719
|
+
fill_indent(out, d2);
|
|
720
|
+
}
|
|
721
|
+
oj_dump_custom_val(RARRAY_AREF(a, i), d2, out, true);
|
|
722
|
+
if (i < cnt) {
|
|
723
|
+
*out->cur++ = ',';
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
size = depth * out->indent + 1;
|
|
727
|
+
assure_size(out, size);
|
|
728
|
+
if (out->opts->dump_opts.use) {
|
|
729
|
+
if (0 < out->opts->dump_opts.array_size) {
|
|
730
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
|
|
731
|
+
}
|
|
732
|
+
if (0 < out->opts->dump_opts.indent_size) {
|
|
733
|
+
int i;
|
|
734
|
+
|
|
735
|
+
for (i = depth; 0 < i; i--) {
|
|
736
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
} else {
|
|
740
|
+
fill_indent(out, depth);
|
|
741
|
+
}
|
|
742
|
+
*out->cur++ = ']';
|
|
771
743
|
}
|
|
772
744
|
*out->cur = '\0';
|
|
773
745
|
}
|
|
774
746
|
|
|
775
|
-
static void
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
747
|
+
static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
|
|
748
|
+
long id = oj_check_circular(obj, out);
|
|
749
|
+
VALUE clas;
|
|
750
|
+
|
|
780
751
|
if (0 > id) {
|
|
781
|
-
|
|
752
|
+
oj_dump_nil(Qnil, depth, out, false);
|
|
782
753
|
} else if (Qnil != (clas = dump_common(obj, depth, out))) {
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
ma = rb_struct_s_members(clas);
|
|
754
|
+
VALUE ma = Qnil;
|
|
755
|
+
VALUE v;
|
|
756
|
+
char num_id[32];
|
|
757
|
+
int i;
|
|
758
|
+
int d2 = depth + 1;
|
|
759
|
+
int d3 = d2 + 1;
|
|
760
|
+
size_t size = d2 * out->indent + d3 * out->indent + 3;
|
|
761
|
+
const char *name;
|
|
762
|
+
int cnt;
|
|
763
|
+
size_t len;
|
|
764
|
+
|
|
765
|
+
assure_size(out, size);
|
|
766
|
+
if (clas == rb_cRange) {
|
|
767
|
+
*out->cur++ = '"';
|
|
768
|
+
oj_dump_custom_val(rb_funcall(obj, oj_begin_id, 0), d3, out, false);
|
|
769
|
+
assure_size(out, 3);
|
|
770
|
+
APPEND_CHARS(out->cur, "..", 2);
|
|
771
|
+
if (Qtrue == rb_funcall(obj, oj_exclude_end_id, 0)) {
|
|
772
|
+
*out->cur++ = '.';
|
|
773
|
+
}
|
|
774
|
+
oj_dump_custom_val(rb_funcall(obj, oj_end_id, 0), d3, out, false);
|
|
775
|
+
*out->cur++ = '"';
|
|
776
|
+
|
|
777
|
+
return;
|
|
778
|
+
}
|
|
779
|
+
*out->cur++ = '{';
|
|
780
|
+
fill_indent(out, d2);
|
|
781
|
+
size = d3 * out->indent + 2;
|
|
782
|
+
ma = rb_struct_s_members(clas);
|
|
813
783
|
|
|
814
784
|
#ifdef RSTRUCT_LEN
|
|
815
785
|
#if RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
|
|
816
|
-
|
|
817
|
-
#else
|
|
818
|
-
|
|
819
|
-
#endif
|
|
786
|
+
cnt = (int)NUM2LONG(RSTRUCT_LEN(obj));
|
|
787
|
+
#else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
|
|
788
|
+
cnt = (int)RSTRUCT_LEN(obj);
|
|
789
|
+
#endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
|
|
820
790
|
#else
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
791
|
+
// This is a bit risky as a struct in C ruby is not the same as a Struct
|
|
792
|
+
// class in interpreted Ruby so length() may not be defined.
|
|
793
|
+
cnt = FIX2INT(rb_funcall2(obj, oj_length_id, 0, 0));
|
|
824
794
|
#endif
|
|
825
|
-
|
|
795
|
+
for (i = 0; i < cnt; i++) {
|
|
826
796
|
#ifdef RSTRUCT_LEN
|
|
827
|
-
|
|
797
|
+
v = RSTRUCT_GET(obj, i);
|
|
828
798
|
#else
|
|
829
|
-
|
|
799
|
+
v = rb_struct_aref(obj, INT2FIX(i));
|
|
830
800
|
#endif
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
*out->cur++ = '}';
|
|
852
|
-
*out->cur = '\0';
|
|
801
|
+
if (ma != Qnil) {
|
|
802
|
+
volatile VALUE s = rb_sym2str(RARRAY_AREF(ma, i));
|
|
803
|
+
|
|
804
|
+
name = RSTRING_PTR(s);
|
|
805
|
+
len = (int)RSTRING_LEN(s);
|
|
806
|
+
} else {
|
|
807
|
+
len = snprintf(num_id, sizeof(num_id), "%d", i);
|
|
808
|
+
name = num_id;
|
|
809
|
+
}
|
|
810
|
+
assure_size(out, size + len + 3);
|
|
811
|
+
fill_indent(out, d3);
|
|
812
|
+
*out->cur++ = '"';
|
|
813
|
+
APPEND_CHARS(out->cur, name, len);
|
|
814
|
+
APPEND_CHARS(out->cur, "\":", 2);
|
|
815
|
+
oj_dump_custom_val(v, d3, out, true);
|
|
816
|
+
*out->cur++ = ',';
|
|
817
|
+
}
|
|
818
|
+
out->cur--;
|
|
819
|
+
*out->cur++ = '}';
|
|
820
|
+
*out->cur = '\0';
|
|
853
821
|
}
|
|
854
822
|
}
|
|
855
823
|
|
|
856
|
-
static void
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
VALUE clas;
|
|
824
|
+
static void dump_data(VALUE obj, int depth, Out out, bool as_ok) {
|
|
825
|
+
long id = oj_check_circular(obj, out);
|
|
826
|
+
VALUE clas;
|
|
860
827
|
|
|
861
828
|
if (0 > id) {
|
|
862
|
-
|
|
829
|
+
oj_dump_nil(Qnil, depth, out, false);
|
|
863
830
|
} else if (Qnil != (clas = dump_common(obj, depth, out))) {
|
|
864
|
-
|
|
831
|
+
dump_obj_attrs(obj, clas, id, depth, out);
|
|
865
832
|
}
|
|
866
833
|
}
|
|
867
834
|
|
|
868
|
-
static void
|
|
869
|
-
|
|
870
|
-
|
|
835
|
+
static void dump_regexp(VALUE obj, int depth, Out out, bool as_ok) {
|
|
836
|
+
if (NULL != out->opts->create_id) {
|
|
837
|
+
dump_obj_str(obj, depth, out);
|
|
838
|
+
} else {
|
|
839
|
+
dump_obj_as_str(obj, depth, out);
|
|
840
|
+
}
|
|
871
841
|
}
|
|
872
842
|
|
|
873
|
-
static void
|
|
874
|
-
dump_complex(VALUE obj, int depth, Out out, bool as_ok) {
|
|
843
|
+
static void dump_complex(VALUE obj, int depth, Out out, bool as_ok) {
|
|
875
844
|
complex_dump(obj, depth, out);
|
|
876
845
|
}
|
|
877
846
|
|
|
878
|
-
static void
|
|
879
|
-
dump_rational(VALUE obj, int depth, Out out, bool as_ok) {
|
|
847
|
+
static void dump_rational(VALUE obj, int depth, Out out, bool as_ok) {
|
|
880
848
|
rational_dump(obj, depth, out);
|
|
881
849
|
}
|
|
882
850
|
|
|
883
|
-
static DumpFunc
|
|
884
|
-
NULL,
|
|
885
|
-
dump_obj,
|
|
886
|
-
oj_dump_class,
|
|
887
|
-
oj_dump_class,
|
|
888
|
-
oj_dump_float,
|
|
889
|
-
oj_dump_str,
|
|
890
|
-
dump_regexp,
|
|
891
|
-
dump_array,
|
|
892
|
-
dump_hash,
|
|
893
|
-
dump_struct,
|
|
894
|
-
oj_dump_bignum,
|
|
895
|
-
NULL,
|
|
896
|
-
dump_data,
|
|
897
|
-
NULL,
|
|
898
|
-
dump_complex,
|
|
899
|
-
dump_rational,
|
|
900
|
-
NULL,
|
|
901
|
-
oj_dump_nil,
|
|
902
|
-
oj_dump_true,
|
|
903
|
-
oj_dump_false,
|
|
904
|
-
oj_dump_sym,
|
|
905
|
-
oj_dump_fixnum,
|
|
851
|
+
static DumpFunc custom_funcs[] = {
|
|
852
|
+
NULL, // RUBY_T_NONE = 0x00,
|
|
853
|
+
dump_obj, // RUBY_T_OBJECT = 0x01,
|
|
854
|
+
oj_dump_class, // RUBY_T_CLASS = 0x02,
|
|
855
|
+
oj_dump_class, // RUBY_T_MODULE = 0x03,
|
|
856
|
+
oj_dump_float, // RUBY_T_FLOAT = 0x04,
|
|
857
|
+
oj_dump_str, // RUBY_T_STRING = 0x05,
|
|
858
|
+
dump_regexp, // RUBY_T_REGEXP = 0x06,
|
|
859
|
+
dump_array, // RUBY_T_ARRAY = 0x07,
|
|
860
|
+
dump_hash, // RUBY_T_HASH = 0x08,
|
|
861
|
+
dump_struct, // RUBY_T_STRUCT = 0x09,
|
|
862
|
+
oj_dump_bignum, // RUBY_T_BIGNUM = 0x0a,
|
|
863
|
+
NULL, // RUBY_T_FILE = 0x0b,
|
|
864
|
+
dump_data, // RUBY_T_DATA = 0x0c,
|
|
865
|
+
NULL, // RUBY_T_MATCH = 0x0d,
|
|
866
|
+
dump_complex, // RUBY_T_COMPLEX = 0x0e,
|
|
867
|
+
dump_rational, // RUBY_T_RATIONAL = 0x0f,
|
|
868
|
+
NULL, // 0x10
|
|
869
|
+
oj_dump_nil, // RUBY_T_NIL = 0x11,
|
|
870
|
+
oj_dump_true, // RUBY_T_TRUE = 0x12,
|
|
871
|
+
oj_dump_false, // RUBY_T_FALSE = 0x13,
|
|
872
|
+
oj_dump_sym, // RUBY_T_SYMBOL = 0x14,
|
|
873
|
+
oj_dump_fixnum, // RUBY_T_FIXNUM = 0x15,
|
|
906
874
|
};
|
|
907
875
|
|
|
908
|
-
void
|
|
909
|
-
|
|
910
|
-
int type = rb_type(obj);
|
|
876
|
+
void oj_dump_custom_val(VALUE obj, int depth, Out out, bool as_ok) {
|
|
877
|
+
int type = rb_type(obj);
|
|
911
878
|
|
|
912
|
-
if (Yes == out->opts->trace) {
|
|
913
|
-
|
|
879
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
|
880
|
+
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
|
|
914
881
|
}
|
|
915
882
|
if (MAX_DEPTH < depth) {
|
|
916
|
-
|
|
883
|
+
rb_raise(rb_eNoMemError, "Too deeply nested.\n");
|
|
917
884
|
}
|
|
918
885
|
if (0 < type && type <= RUBY_T_FIXNUM) {
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
886
|
+
DumpFunc f = custom_funcs[type];
|
|
887
|
+
|
|
888
|
+
if (NULL != f) {
|
|
889
|
+
f(obj, depth, out, true);
|
|
890
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
|
891
|
+
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
|
|
892
|
+
}
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
928
895
|
}
|
|
929
896
|
oj_dump_nil(Qnil, depth, out, false);
|
|
930
|
-
if (Yes == out->opts->trace) {
|
|
931
|
-
|
|
897
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
|
898
|
+
oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
|
|
932
899
|
}
|
|
933
900
|
}
|
|
934
901
|
|
|
935
902
|
///// load functions /////
|
|
936
903
|
|
|
937
|
-
static void
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
if (!oj_code_has(codes, parent->clas, false)) {
|
|
955
|
-
parent->val = rb_obj_alloc(parent->clas);
|
|
956
|
-
}
|
|
957
|
-
}
|
|
958
|
-
}
|
|
904
|
+
static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
|
|
905
|
+
const char *key = kval->key;
|
|
906
|
+
int klen = kval->klen;
|
|
907
|
+
Val parent = stack_peek(&pi->stack);
|
|
908
|
+
volatile VALUE rkey = kval->key_val;
|
|
909
|
+
|
|
910
|
+
if (Qundef == rkey && Yes == pi->options.create_ok && NULL != pi->options.create_id &&
|
|
911
|
+
*pi->options.create_id == *key && (int)pi->options.create_id_len == klen &&
|
|
912
|
+
0 == strncmp(pi->options.create_id, key, klen)) {
|
|
913
|
+
parent->clas = oj_name2class(pi, str, len, false, rb_eArgError);
|
|
914
|
+
if (2 == klen && '^' == *key && 'o' == key[1]) {
|
|
915
|
+
if (Qundef != parent->clas) {
|
|
916
|
+
if (!oj_code_has(codes, parent->clas, false)) {
|
|
917
|
+
parent->val = rb_obj_alloc(parent->clas);
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
}
|
|
959
921
|
} else {
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
|
|
995
|
-
}
|
|
922
|
+
volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
|
|
923
|
+
// volatile VALUE rstr = rb_utf8_str_new(str, len);
|
|
924
|
+
|
|
925
|
+
if (Qundef == rkey) {
|
|
926
|
+
if (Yes == pi->options.sym_key) {
|
|
927
|
+
rkey = ID2SYM(rb_intern3(key, klen, oj_utf8_encoding));
|
|
928
|
+
} else {
|
|
929
|
+
rkey = rb_utf8_str_new(key, klen);
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
if (Yes == pi->options.create_ok && NULL != pi->options.str_rx.head) {
|
|
933
|
+
VALUE clas = oj_rxclass_match(&pi->options.str_rx, str, (int)len);
|
|
934
|
+
|
|
935
|
+
if (Qnil != clas) {
|
|
936
|
+
rstr = rb_funcall(clas, oj_json_create_id, 1, rstr);
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
switch (rb_type(parent->val)) {
|
|
940
|
+
case T_OBJECT: oj_set_obj_ivar(parent, kval, rstr); break;
|
|
941
|
+
case T_HASH:
|
|
942
|
+
if (4 == parent->klen && NULL != parent->key && rb_cTime == parent->clas &&
|
|
943
|
+
0 == strncmp("time", parent->key, 4)) {
|
|
944
|
+
if (Qnil == (parent->val = oj_parse_xml_time(str, (int)len))) {
|
|
945
|
+
parent->val = rb_funcall(rb_cTime, rb_intern("parse"), 1, rb_str_new(str, len));
|
|
946
|
+
}
|
|
947
|
+
} else {
|
|
948
|
+
rb_hash_aset(parent->val, rkey, rstr);
|
|
949
|
+
}
|
|
950
|
+
break;
|
|
951
|
+
default: break;
|
|
952
|
+
}
|
|
953
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
|
954
|
+
oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
|
|
955
|
+
}
|
|
996
956
|
}
|
|
997
957
|
}
|
|
998
958
|
|
|
999
|
-
static void
|
|
1000
|
-
|
|
1001
|
-
Val parent = stack_peek(&pi->stack);
|
|
959
|
+
static void end_hash(struct _parseInfo *pi) {
|
|
960
|
+
Val parent = stack_peek(&pi->stack);
|
|
1002
961
|
|
|
1003
962
|
if (Qundef != parent->clas && parent->clas != rb_obj_class(parent->val)) {
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
963
|
+
volatile VALUE obj = oj_code_load(codes, parent->clas, parent->val);
|
|
964
|
+
|
|
965
|
+
if (Qnil != obj) {
|
|
966
|
+
parent->val = obj;
|
|
967
|
+
} else {
|
|
968
|
+
parent->val = rb_funcall(parent->clas, oj_json_create_id, 1, parent->val);
|
|
969
|
+
}
|
|
970
|
+
parent->clas = Qundef;
|
|
1012
971
|
}
|
|
1013
|
-
if (Yes == pi->options.trace) {
|
|
1014
|
-
|
|
972
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
|
973
|
+
oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
|
|
1015
974
|
}
|
|
1016
975
|
}
|
|
1017
976
|
|
|
1018
|
-
static
|
|
1019
|
-
|
|
1020
|
-
volatile VALUE
|
|
1021
|
-
|
|
1022
|
-
if (Qundef == rkey) {
|
|
1023
|
-
rkey = rb_str_new(parent->key, parent->klen);
|
|
1024
|
-
}
|
|
1025
|
-
rkey = oj_encode(rkey);
|
|
1026
|
-
if (Yes == pi->options.sym_key) {
|
|
1027
|
-
rkey = rb_str_intern(rkey);
|
|
1028
|
-
}
|
|
1029
|
-
return rkey;
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
static void
|
|
1033
|
-
hash_set_num(struct _ParseInfo *pi, Val kval, NumInfo ni) {
|
|
1034
|
-
Val parent = stack_peek(&pi->stack);
|
|
1035
|
-
volatile VALUE rval = oj_num_as_value(ni);
|
|
977
|
+
static void hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) {
|
|
978
|
+
Val parent = stack_peek(&pi->stack);
|
|
979
|
+
volatile VALUE rval = oj_num_as_value(ni);
|
|
1036
980
|
|
|
1037
981
|
switch (rb_type(parent->val)) {
|
|
1038
|
-
case T_OBJECT:
|
|
1039
|
-
oj_set_obj_ivar(parent, kval, rval);
|
|
1040
|
-
break;
|
|
982
|
+
case T_OBJECT: oj_set_obj_ivar(parent, kval, rval); break;
|
|
1041
983
|
case T_HASH:
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
}
|
|
1074
|
-
rval = parent->val;
|
|
1075
|
-
} else {
|
|
1076
|
-
rb_hash_aset(parent->val, calc_hash_key(pi, kval), rval);
|
|
1077
|
-
}
|
|
1078
|
-
break;
|
|
1079
|
-
default:
|
|
1080
|
-
break;
|
|
984
|
+
if (4 == parent->klen && NULL != parent->key && rb_cTime == parent->clas && 0 != ni->div &&
|
|
985
|
+
0 == strncmp("time", parent->key, 4)) {
|
|
986
|
+
int64_t nsec = ni->num * 1000000000LL / ni->div;
|
|
987
|
+
|
|
988
|
+
if (ni->neg) {
|
|
989
|
+
ni->i = -ni->i;
|
|
990
|
+
if (0 < nsec) {
|
|
991
|
+
ni->i--;
|
|
992
|
+
nsec = 1000000000LL - nsec;
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
if (86400 == ni->exp) { // UTC time
|
|
996
|
+
parent->val = rb_time_nano_new(ni->i, (long)nsec);
|
|
997
|
+
// Since the ruby C routines always create local time, the
|
|
998
|
+
// offset and then a conversion to UTC keeps makes the time
|
|
999
|
+
// match the expected value.
|
|
1000
|
+
parent->val = rb_funcall2(parent->val, oj_utc_id, 0, 0);
|
|
1001
|
+
} else if (ni->has_exp) {
|
|
1002
|
+
struct timespec ts;
|
|
1003
|
+
ts.tv_sec = ni->i;
|
|
1004
|
+
ts.tv_nsec = nsec;
|
|
1005
|
+
parent->val = rb_time_timespec_new(&ts, (int)ni->exp);
|
|
1006
|
+
} else {
|
|
1007
|
+
parent->val = rb_time_nano_new(ni->i, (long)nsec);
|
|
1008
|
+
}
|
|
1009
|
+
rval = parent->val;
|
|
1010
|
+
} else {
|
|
1011
|
+
rb_hash_aset(parent->val, oj_calc_hash_key(pi, kval), rval);
|
|
1012
|
+
}
|
|
1013
|
+
break;
|
|
1014
|
+
default: break;
|
|
1081
1015
|
}
|
|
1082
|
-
if (Yes == pi->options.trace) {
|
|
1083
|
-
|
|
1016
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
|
1017
|
+
oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
|
|
1084
1018
|
}
|
|
1085
1019
|
}
|
|
1086
1020
|
|
|
1087
|
-
static void
|
|
1088
|
-
|
|
1089
|
-
Val parent = stack_peek(&pi->stack);
|
|
1021
|
+
static void hash_set_value(ParseInfo pi, Val kval, VALUE value) {
|
|
1022
|
+
Val parent = stack_peek(&pi->stack);
|
|
1090
1023
|
|
|
1091
1024
|
switch (rb_type(parent->val)) {
|
|
1092
|
-
case T_OBJECT:
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
case T_HASH:
|
|
1096
|
-
rb_hash_aset(parent->val, calc_hash_key(pi, kval), value);
|
|
1097
|
-
break;
|
|
1098
|
-
default:
|
|
1099
|
-
break;
|
|
1025
|
+
case T_OBJECT: oj_set_obj_ivar(parent, kval, value); break;
|
|
1026
|
+
case T_HASH: rb_hash_aset(parent->val, oj_calc_hash_key(pi, kval), value); break;
|
|
1027
|
+
default: break;
|
|
1100
1028
|
}
|
|
1101
|
-
if (Yes == pi->options.trace) {
|
|
1102
|
-
|
|
1029
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
|
1030
|
+
oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
|
|
1103
1031
|
}
|
|
1104
1032
|
}
|
|
1105
1033
|
|
|
1106
|
-
static void
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1034
|
+
static void array_append_num(ParseInfo pi, NumInfo ni) {
|
|
1035
|
+
Val parent = stack_peek(&pi->stack);
|
|
1036
|
+
volatile VALUE rval = oj_num_as_value(ni);
|
|
1037
|
+
|
|
1111
1038
|
rb_ary_push(parent->val, rval);
|
|
1112
|
-
if (Yes == pi->options.trace) {
|
|
1113
|
-
|
|
1039
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
|
1040
|
+
oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
|
|
1114
1041
|
}
|
|
1115
1042
|
}
|
|
1116
1043
|
|
|
1117
|
-
static void
|
|
1118
|
-
|
|
1119
|
-
volatile VALUE rstr = rb_str_new(str, len);
|
|
1044
|
+
static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
|
1045
|
+
volatile VALUE rstr = rb_utf8_str_new(str, len);
|
|
1120
1046
|
|
|
1121
|
-
rstr = oj_encode(rstr);
|
|
1122
1047
|
if (Yes == pi->options.create_ok && NULL != pi->options.str_rx.head) {
|
|
1123
|
-
|
|
1048
|
+
VALUE clas = oj_rxclass_match(&pi->options.str_rx, str, (int)len);
|
|
1124
1049
|
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1050
|
+
if (Qnil != clas) {
|
|
1051
|
+
rb_ary_push(stack_peek(&pi->stack)->val, rb_funcall(clas, oj_json_create_id, 1, rstr));
|
|
1052
|
+
return;
|
|
1053
|
+
}
|
|
1129
1054
|
}
|
|
1130
1055
|
rb_ary_push(stack_peek(&pi->stack)->val, rstr);
|
|
1131
|
-
if (Yes == pi->options.trace) {
|
|
1132
|
-
|
|
1056
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
|
1057
|
+
oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
|
|
1133
1058
|
}
|
|
1134
1059
|
}
|
|
1135
1060
|
|
|
1136
|
-
void
|
|
1137
|
-
oj_set_custom_callbacks(ParseInfo pi) {
|
|
1061
|
+
void oj_set_custom_callbacks(ParseInfo pi) {
|
|
1138
1062
|
oj_set_compat_callbacks(pi);
|
|
1139
|
-
pi->hash_set_cstr
|
|
1140
|
-
pi->end_hash
|
|
1141
|
-
pi->hash_set_num
|
|
1142
|
-
pi->hash_set_value
|
|
1063
|
+
pi->hash_set_cstr = hash_set_cstr;
|
|
1064
|
+
pi->end_hash = end_hash;
|
|
1065
|
+
pi->hash_set_num = hash_set_num;
|
|
1066
|
+
pi->hash_set_value = hash_set_value;
|
|
1143
1067
|
pi->array_append_cstr = array_append_cstr;
|
|
1144
|
-
pi->array_append_num
|
|
1068
|
+
pi->array_append_num = array_append_num;
|
|
1145
1069
|
}
|
|
1146
1070
|
|
|
1147
1071
|
VALUE
|
|
1148
1072
|
oj_custom_parse(int argc, VALUE *argv, VALUE self) {
|
|
1149
|
-
struct
|
|
1073
|
+
struct _parseInfo pi;
|
|
1150
1074
|
|
|
1151
1075
|
parse_info_init(&pi);
|
|
1152
|
-
pi.options
|
|
1153
|
-
pi.handler
|
|
1154
|
-
pi.err_class
|
|
1155
|
-
pi.max_depth
|
|
1076
|
+
pi.options = oj_default_options;
|
|
1077
|
+
pi.handler = Qnil;
|
|
1078
|
+
pi.err_class = Qnil;
|
|
1079
|
+
pi.max_depth = 0;
|
|
1156
1080
|
pi.options.allow_nan = Yes;
|
|
1157
|
-
pi.options.nilnil
|
|
1081
|
+
pi.options.nilnil = Yes;
|
|
1158
1082
|
oj_set_custom_callbacks(&pi);
|
|
1159
1083
|
|
|
1160
1084
|
if (T_STRING == rb_type(*argv)) {
|
|
1161
|
-
|
|
1085
|
+
return oj_pi_parse(argc, argv, &pi, 0, 0, false);
|
|
1162
1086
|
} else {
|
|
1163
|
-
|
|
1087
|
+
return oj_pi_sparse(argc, argv, &pi, 0);
|
|
1164
1088
|
}
|
|
1165
1089
|
}
|
|
1166
1090
|
|
|
1167
1091
|
VALUE
|
|
1168
1092
|
oj_custom_parse_cstr(int argc, VALUE *argv, char *json, size_t len) {
|
|
1169
|
-
struct
|
|
1093
|
+
struct _parseInfo pi;
|
|
1170
1094
|
|
|
1171
1095
|
parse_info_init(&pi);
|
|
1172
|
-
pi.options
|
|
1173
|
-
pi.handler
|
|
1174
|
-
pi.err_class
|
|
1175
|
-
pi.max_depth
|
|
1096
|
+
pi.options = oj_default_options;
|
|
1097
|
+
pi.handler = Qnil;
|
|
1098
|
+
pi.err_class = Qnil;
|
|
1099
|
+
pi.max_depth = 0;
|
|
1176
1100
|
pi.options.allow_nan = Yes;
|
|
1177
|
-
pi.options.nilnil
|
|
1101
|
+
pi.options.nilnil = Yes;
|
|
1178
1102
|
oj_set_custom_callbacks(&pi);
|
|
1179
1103
|
pi.end_hash = end_hash;
|
|
1180
1104
|
|