oj 3.11.0 → 3.16.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1421 -0
- data/README.md +20 -5
- data/RELEASE_NOTES.md +61 -0
- data/ext/oj/buf.h +48 -38
- data/ext/oj/cache.c +329 -0
- data/ext/oj/cache.h +22 -0
- data/ext/oj/cache8.c +60 -62
- data/ext/oj/cache8.h +8 -7
- data/ext/oj/circarray.c +35 -35
- data/ext/oj/circarray.h +11 -9
- data/ext/oj/code.c +156 -174
- data/ext/oj/code.h +19 -18
- data/ext/oj/compat.c +140 -197
- data/ext/oj/custom.c +737 -879
- data/ext/oj/debug.c +126 -0
- data/ext/oj/dump.c +830 -835
- data/ext/oj/dump.h +65 -53
- data/ext/oj/dump_compat.c +566 -642
- data/ext/oj/dump_leaf.c +95 -182
- data/ext/oj/dump_object.c +518 -659
- data/ext/oj/dump_strict.c +301 -334
- data/ext/oj/encode.h +3 -4
- data/ext/oj/encoder.c +43 -0
- data/ext/oj/err.c +27 -24
- data/ext/oj/err.h +38 -13
- data/ext/oj/extconf.rb +23 -7
- data/ext/oj/fast.c +1043 -1073
- data/ext/oj/intern.c +313 -0
- data/ext/oj/intern.h +22 -0
- data/ext/oj/mem.c +318 -0
- data/ext/oj/mem.h +53 -0
- data/ext/oj/mimic_json.c +449 -423
- data/ext/oj/object.c +530 -576
- data/ext/oj/odd.c +155 -138
- data/ext/oj/odd.h +24 -22
- data/ext/oj/oj.c +1331 -993
- data/ext/oj/oj.h +306 -292
- data/ext/oj/parse.c +934 -938
- data/ext/oj/parse.h +73 -70
- data/ext/oj/parser.c +1600 -0
- data/ext/oj/parser.h +101 -0
- data/ext/oj/rails.c +795 -845
- data/ext/oj/rails.h +7 -7
- data/ext/oj/reader.c +132 -140
- data/ext/oj/reader.h +67 -78
- data/ext/oj/resolve.c +40 -59
- data/ext/oj/resolve.h +3 -2
- data/ext/oj/rxclass.c +67 -67
- data/ext/oj/rxclass.h +11 -9
- data/ext/oj/saj.c +441 -480
- data/ext/oj/saj2.c +584 -0
- data/ext/oj/saj2.h +23 -0
- data/ext/oj/scp.c +78 -111
- data/ext/oj/sparse.c +726 -730
- data/ext/oj/stream_writer.c +146 -165
- data/ext/oj/strict.c +103 -123
- data/ext/oj/string_writer.c +241 -253
- data/ext/oj/trace.c +29 -33
- data/ext/oj/trace.h +41 -11
- data/ext/oj/usual.c +1218 -0
- data/ext/oj/usual.h +69 -0
- data/ext/oj/util.c +103 -103
- data/ext/oj/util.h +3 -2
- data/ext/oj/val_stack.c +60 -49
- data/ext/oj/val_stack.h +79 -85
- data/ext/oj/validate.c +46 -0
- data/ext/oj/wab.c +307 -350
- data/lib/oj/active_support_helper.rb +1 -3
- data/lib/oj/bag.rb +8 -1
- data/lib/oj/easy_hash.rb +9 -9
- data/lib/oj/error.rb +1 -2
- data/lib/oj/json.rb +162 -150
- data/lib/oj/mimic.rb +9 -19
- data/lib/oj/saj.rb +20 -6
- data/lib/oj/schandler.rb +5 -4
- data/lib/oj/state.rb +12 -8
- data/lib/oj/version.rb +1 -2
- data/lib/oj.rb +2 -0
- data/pages/Compatibility.md +1 -1
- data/pages/InstallOptions.md +20 -0
- data/pages/JsonGem.md +15 -0
- data/pages/Modes.md +8 -3
- data/pages/Options.md +43 -5
- data/pages/Parser.md +309 -0
- data/pages/Rails.md +14 -2
- data/test/_test_active.rb +8 -9
- data/test/_test_active_mimic.rb +7 -8
- data/test/_test_mimic_rails.rb +17 -20
- data/test/activerecord/result_test.rb +12 -8
- data/test/activesupport6/encoding_test.rb +63 -28
- data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
- data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
- data/test/{activesupport5 → activesupport7}/encoding_test.rb +86 -50
- data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
- data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
- data/test/files.rb +15 -15
- data/test/foo.rb +17 -43
- data/test/helper.rb +16 -3
- data/test/isolated/shared.rb +3 -2
- data/test/json_gem/json_addition_test.rb +2 -2
- data/test/json_gem/json_common_interface_test.rb +8 -6
- data/test/json_gem/json_encoding_test.rb +0 -0
- data/test/json_gem/json_ext_parser_test.rb +1 -0
- data/test/json_gem/json_fixtures_test.rb +3 -2
- data/test/json_gem/json_generator_test.rb +71 -41
- data/test/json_gem/json_generic_object_test.rb +11 -11
- data/test/json_gem/json_parser_test.rb +54 -47
- data/test/json_gem/json_string_matching_test.rb +9 -9
- data/test/json_gem/test_helper.rb +12 -0
- data/test/mem.rb +34 -0
- data/test/perf.rb +22 -27
- data/test/perf_compat.rb +31 -33
- data/test/perf_dump.rb +50 -0
- data/test/perf_fast.rb +80 -82
- data/test/perf_file.rb +27 -29
- data/test/perf_object.rb +65 -69
- data/test/perf_once.rb +59 -0
- data/test/perf_parser.rb +183 -0
- data/test/perf_saj.rb +46 -54
- data/test/perf_scp.rb +58 -69
- data/test/perf_simple.rb +41 -39
- data/test/perf_strict.rb +74 -82
- data/test/perf_wab.rb +67 -69
- data/test/prec.rb +5 -5
- data/test/sample/change.rb +0 -1
- data/test/sample/dir.rb +0 -1
- data/test/sample/doc.rb +0 -1
- data/test/sample/file.rb +0 -1
- data/test/sample/group.rb +0 -1
- data/test/sample/hasprops.rb +0 -1
- data/test/sample/layer.rb +0 -1
- data/test/sample/rect.rb +0 -1
- data/test/sample/shape.rb +0 -1
- data/test/sample/text.rb +0 -1
- data/test/sample.rb +16 -16
- data/test/sample_json.rb +8 -8
- data/test/test_compat.rb +97 -45
- data/test/test_custom.rb +73 -51
- data/test/test_debian.rb +7 -10
- data/test/test_fast.rb +135 -79
- data/test/test_file.rb +41 -30
- data/test/test_gc.rb +16 -5
- data/test/test_generate.rb +21 -0
- data/test/test_hash.rb +15 -5
- data/test/test_integer_range.rb +9 -9
- data/test/test_null.rb +20 -20
- data/test/test_object.rb +99 -96
- data/test/test_parser.rb +11 -0
- data/test/test_parser_debug.rb +27 -0
- data/test/test_parser_saj.rb +337 -0
- data/test/test_parser_usual.rb +251 -0
- data/test/test_rails.rb +2 -2
- data/test/test_saj.rb +10 -8
- data/test/test_scp.rb +38 -40
- data/test/test_strict.rb +40 -32
- data/test/test_various.rb +165 -84
- data/test/test_wab.rb +48 -44
- data/test/test_writer.rb +47 -47
- data/test/tests.rb +13 -5
- data/test/tests_mimic.rb +12 -3
- data/test/tests_mimic_addition.rb +12 -3
- metadata +75 -127
- data/ext/oj/hash.c +0 -135
- data/ext/oj/hash.h +0 -18
- data/ext/oj/hash_test.c +0 -484
- data/test/activesupport4/decoding_test.rb +0 -108
- data/test/activesupport4/encoding_test.rb +0 -531
- data/test/activesupport4/test_helper.rb +0 -41
- data/test/activesupport5/test_helper.rb +0 -72
- data/test/bar.rb +0 -35
- data/test/baz.rb +0 -16
- data/test/zoo.rb +0 -13
data/ext/oj/rails.c
CHANGED
@@ -1,157 +1,154 @@
|
|
1
1
|
// Copyright (c) 2017 Peter Ohler. All rights reserved.
|
2
|
+
// Licensed under the MIT License. See LICENSE file in the project root for license details.
|
2
3
|
|
3
4
|
#include "rails.h"
|
4
|
-
|
5
|
+
|
5
6
|
#include "code.h"
|
6
7
|
#include "encode.h"
|
8
|
+
#include "mem.h"
|
7
9
|
#include "trace.h"
|
8
10
|
#include "util.h"
|
9
11
|
|
10
|
-
#define OJ_INFINITY (1.0/0.0)
|
12
|
+
#define OJ_INFINITY (1.0 / 0.0)
|
11
13
|
|
12
14
|
// TBD keep static array of strings and functions to help with rails optimization
|
13
15
|
typedef struct _encoder {
|
14
|
-
struct _rOptTable
|
15
|
-
struct _options
|
16
|
-
VALUE
|
16
|
+
struct _rOptTable ropts;
|
17
|
+
struct _options opts;
|
18
|
+
VALUE arg;
|
17
19
|
} *Encoder;
|
18
20
|
|
19
|
-
bool
|
20
|
-
bool
|
21
|
-
bool
|
21
|
+
bool oj_rails_hash_opt = false;
|
22
|
+
bool oj_rails_array_opt = false;
|
23
|
+
bool oj_rails_float_opt = false;
|
22
24
|
|
23
|
-
extern void
|
25
|
+
extern void oj_mimic_json_methods(VALUE json);
|
24
26
|
|
25
|
-
static void
|
27
|
+
static void dump_rails_val(VALUE obj, int depth, Out out, bool as_ok);
|
26
28
|
|
27
|
-
extern VALUE
|
29
|
+
extern VALUE Oj;
|
28
30
|
|
29
|
-
static struct _rOptTable
|
31
|
+
static struct _rOptTable ropts = {0, 0, NULL};
|
30
32
|
|
31
|
-
static VALUE
|
32
|
-
static bool
|
33
|
-
static bool
|
33
|
+
static VALUE encoder_class = Qnil;
|
34
|
+
static bool escape_html = true;
|
35
|
+
static bool xml_time = true;
|
34
36
|
|
35
|
-
static ROpt
|
37
|
+
static ROpt create_opt(ROptTable rot, VALUE clas);
|
36
38
|
|
37
|
-
ROpt
|
38
|
-
oj_rails_get_opt(ROptTable rot, VALUE clas) {
|
39
|
+
ROpt oj_rails_get_opt(ROptTable rot, VALUE clas) {
|
39
40
|
if (NULL == rot) {
|
40
|
-
|
41
|
+
rot = &ropts;
|
41
42
|
}
|
42
43
|
if (0 < rot->len) {
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
44
|
+
int lo = 0;
|
45
|
+
int hi = rot->len - 1;
|
46
|
+
int mid;
|
47
|
+
VALUE v;
|
48
|
+
|
49
|
+
if (clas < rot->table->clas || rot->table[hi].clas < clas) {
|
50
|
+
return NULL;
|
51
|
+
}
|
52
|
+
if (rot->table[lo].clas == clas) {
|
53
|
+
return rot->table;
|
54
|
+
}
|
55
|
+
if (rot->table[hi].clas == clas) {
|
56
|
+
return &rot->table[hi];
|
57
|
+
}
|
58
|
+
while (2 <= hi - lo) {
|
59
|
+
mid = (hi + lo) / 2;
|
60
|
+
v = rot->table[mid].clas;
|
61
|
+
if (v == clas) {
|
62
|
+
return &rot->table[mid];
|
63
|
+
}
|
64
|
+
if (v < clas) {
|
65
|
+
lo = mid;
|
66
|
+
} else {
|
67
|
+
hi = mid;
|
68
|
+
}
|
69
|
+
}
|
69
70
|
}
|
70
71
|
return NULL;
|
71
72
|
}
|
72
73
|
|
73
|
-
static ROptTable
|
74
|
-
|
75
|
-
dest->len = src->len;
|
74
|
+
static ROptTable copy_opts(ROptTable src, ROptTable dest) {
|
75
|
+
dest->len = src->len;
|
76
76
|
dest->alen = src->alen;
|
77
77
|
if (NULL == src->table) {
|
78
|
-
|
78
|
+
dest->table = NULL;
|
79
79
|
} else {
|
80
|
-
|
81
|
-
|
80
|
+
dest->table = OJ_R_ALLOC_N(struct _rOpt, dest->alen);
|
81
|
+
memcpy(dest->table, src->table, sizeof(struct _rOpt) * dest->alen);
|
82
82
|
}
|
83
83
|
return NULL;
|
84
84
|
}
|
85
85
|
|
86
|
-
static int
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
const char *attr = rb_id2name(key);
|
86
|
+
static int dump_attr_cb(ID key, VALUE value, VALUE ov) {
|
87
|
+
Out out = (Out)ov;
|
88
|
+
int depth = out->depth;
|
89
|
+
size_t size = depth * out->indent + 1;
|
90
|
+
const char *attr = rb_id2name(key);
|
92
91
|
|
93
92
|
// Some exceptions such as NoMethodError have an invisible attribute where
|
94
93
|
// the key name is NULL. Not an empty string but NULL.
|
95
94
|
if (NULL == attr) {
|
96
|
-
|
95
|
+
attr = "";
|
97
96
|
}
|
98
97
|
if (0 == strcmp("bt", attr) || 0 == strcmp("mesg", attr)) {
|
99
|
-
|
98
|
+
return ST_CONTINUE;
|
100
99
|
}
|
101
100
|
assure_size(out, size);
|
102
101
|
fill_indent(out, depth);
|
103
102
|
if ('@' == *attr) {
|
104
|
-
|
105
|
-
|
103
|
+
attr++;
|
104
|
+
oj_dump_cstr(attr, strlen(attr), 0, 0, out);
|
106
105
|
} else {
|
107
|
-
|
106
|
+
char buf[32];
|
108
107
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
108
|
+
*buf = '~';
|
109
|
+
strncpy(buf + 1, attr, sizeof(buf) - 2);
|
110
|
+
buf[sizeof(buf) - 1] = '\0';
|
111
|
+
oj_dump_cstr(buf, strlen(buf), 0, 0, out);
|
113
112
|
}
|
114
113
|
*out->cur++ = ':';
|
115
114
|
dump_rails_val(value, depth, out, true);
|
116
|
-
out->depth
|
115
|
+
out->depth = depth;
|
117
116
|
*out->cur++ = ',';
|
118
117
|
|
119
118
|
return ST_CONTINUE;
|
120
119
|
}
|
121
120
|
|
122
|
-
static void
|
123
|
-
dump_obj_attrs(VALUE obj, int depth, Out out, bool as_ok) {
|
121
|
+
static void dump_obj_attrs(VALUE obj, int depth, Out out, bool as_ok) {
|
124
122
|
assure_size(out, 2);
|
125
123
|
*out->cur++ = '{';
|
126
|
-
out->depth
|
124
|
+
out->depth = depth + 1;
|
127
125
|
rb_ivar_foreach(obj, dump_attr_cb, (VALUE)out);
|
128
126
|
if (',' == *(out->cur - 1)) {
|
129
|
-
|
127
|
+
out->cur--; // backup to overwrite last comma
|
130
128
|
}
|
131
129
|
out->depth = depth;
|
132
130
|
fill_indent(out, depth);
|
133
131
|
*out->cur++ = '}';
|
134
|
-
*out->cur
|
132
|
+
*out->cur = '\0';
|
135
133
|
}
|
136
134
|
|
137
|
-
static void
|
138
|
-
|
139
|
-
|
140
|
-
size_t
|
141
|
-
|
142
|
-
volatile VALUE
|
143
|
-
|
144
|
-
int
|
145
|
-
int
|
146
|
-
|
147
|
-
const char *name;
|
135
|
+
static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
|
136
|
+
int d3 = depth + 2;
|
137
|
+
size_t size = d3 * out->indent + 2;
|
138
|
+
size_t sep_len = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
|
139
|
+
volatile VALUE ma;
|
140
|
+
volatile VALUE v;
|
141
|
+
int cnt;
|
142
|
+
int i;
|
143
|
+
int len;
|
144
|
+
const char *name;
|
148
145
|
|
149
146
|
#ifdef RSTRUCT_LEN
|
150
147
|
#if RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
|
151
148
|
cnt = (int)NUM2LONG(RSTRUCT_LEN(obj));
|
152
|
-
#else
|
149
|
+
#else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
|
153
150
|
cnt = (int)RSTRUCT_LEN(obj);
|
154
|
-
#endif
|
151
|
+
#endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
|
155
152
|
#else
|
156
153
|
// This is a bit risky as a struct in C ruby is not the same as a Struct
|
157
154
|
// class in interpreted Ruby so length() may not be defined.
|
@@ -161,91 +158,85 @@ dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
|
|
161
158
|
assure_size(out, 2);
|
162
159
|
*out->cur++ = '{';
|
163
160
|
for (i = 0; i < cnt; i++) {
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
strcpy(out->cur, out->opts->dump_opts.after_sep);
|
184
|
-
out->cur += out->opts->dump_opts.after_size;
|
185
|
-
}
|
161
|
+
volatile VALUE s = rb_sym2str(RARRAY_AREF(ma, i));
|
162
|
+
|
163
|
+
name = RSTRING_PTR(s);
|
164
|
+
len = (int)RSTRING_LEN(s);
|
165
|
+
assure_size(out, size + sep_len + 6);
|
166
|
+
if (0 < i) {
|
167
|
+
*out->cur++ = ',';
|
168
|
+
}
|
169
|
+
fill_indent(out, d3);
|
170
|
+
*out->cur++ = '"';
|
171
|
+
APPEND_CHARS(out->cur, name, len);
|
172
|
+
*out->cur++ = '"';
|
173
|
+
if (0 < out->opts->dump_opts.before_size) {
|
174
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
|
175
|
+
}
|
176
|
+
*out->cur++ = ':';
|
177
|
+
if (0 < out->opts->dump_opts.after_size) {
|
178
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
|
179
|
+
}
|
186
180
|
#ifdef RSTRUCT_LEN
|
187
|
-
|
181
|
+
v = RSTRUCT_GET(obj, i);
|
188
182
|
#else
|
189
|
-
|
183
|
+
v = rb_struct_aref(obj, INT2FIX(i));
|
190
184
|
#endif
|
191
|
-
|
185
|
+
dump_rails_val(v, d3, out, true);
|
192
186
|
}
|
193
187
|
fill_indent(out, depth);
|
194
188
|
*out->cur++ = '}';
|
195
|
-
*out->cur
|
189
|
+
*out->cur = '\0';
|
196
190
|
}
|
197
191
|
|
198
|
-
static ID
|
192
|
+
static ID to_a_id = 0;
|
199
193
|
|
200
|
-
static void
|
201
|
-
dump_enumerable(VALUE obj, int depth, Out out, bool as_ok) {
|
194
|
+
static void dump_enumerable(VALUE obj, int depth, Out out, bool as_ok) {
|
202
195
|
if (0 == to_a_id) {
|
203
|
-
|
196
|
+
to_a_id = rb_intern("to_a");
|
204
197
|
}
|
205
198
|
dump_rails_val(rb_funcall(obj, to_a_id, 0), depth, out, false);
|
206
199
|
}
|
207
200
|
|
208
|
-
static void
|
209
|
-
|
210
|
-
|
211
|
-
const char *str = rb_string_value_ptr((VALUE*)&rstr);
|
201
|
+
static void dump_bigdecimal(VALUE obj, int depth, Out out, bool as_ok) {
|
202
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
203
|
+
const char *str = RSTRING_PTR(rstr);
|
212
204
|
|
213
205
|
if ('I' == *str || 'N' == *str || ('-' == *str && 'I' == str[1])) {
|
214
|
-
|
206
|
+
oj_dump_nil(Qnil, depth, out, false);
|
215
207
|
} else if (out->opts->int_range_max != 0 || out->opts->int_range_min != 0) {
|
216
|
-
|
208
|
+
oj_dump_cstr(str, (int)RSTRING_LEN(rstr), 0, 0, out);
|
217
209
|
} else if (Yes == out->opts->bigdec_as_num) {
|
218
|
-
|
210
|
+
oj_dump_raw(str, (int)RSTRING_LEN(rstr), out);
|
219
211
|
} else {
|
220
|
-
|
212
|
+
oj_dump_cstr(str, (int)RSTRING_LEN(rstr), 0, 0, out);
|
221
213
|
}
|
222
214
|
}
|
223
215
|
|
224
|
-
static void
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
long
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
int len;
|
216
|
+
static void dump_sec_nano(VALUE obj, int64_t sec, long nsec, Out out) {
|
217
|
+
char buf[64];
|
218
|
+
struct _timeInfo ti;
|
219
|
+
long one = 1000000000;
|
220
|
+
long tzsecs = NUM2LONG(rb_funcall2(obj, oj_utc_offset_id, 0, 0));
|
221
|
+
int tzhour, tzmin;
|
222
|
+
char tzsign = '+';
|
223
|
+
int len;
|
233
224
|
|
234
225
|
if (out->end - out->cur <= 36) {
|
235
|
-
|
226
|
+
assure_size(out, 36);
|
236
227
|
}
|
237
228
|
if (9 > out->opts->sec_prec) {
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
229
|
+
int i;
|
230
|
+
|
231
|
+
// Rails does not round when reducing precision but instead floors,
|
232
|
+
for (i = 9 - out->opts->sec_prec; 0 < i; i--) {
|
233
|
+
nsec = nsec / 10;
|
234
|
+
one /= 10;
|
235
|
+
}
|
236
|
+
if (one <= nsec) {
|
237
|
+
nsec -= one;
|
238
|
+
sec++;
|
239
|
+
}
|
249
240
|
}
|
250
241
|
// 2012-01-05T23:58:07.123456000+09:00 or 2012/01/05 23:58:07 +0900
|
251
242
|
sec += tzsecs;
|
@@ -253,509 +244,505 @@ dump_sec_nano(VALUE obj, int64_t sec, long nsec, Out out) {
|
|
253
244
|
if (0 > tzsecs) {
|
254
245
|
tzsign = '-';
|
255
246
|
tzhour = (int)(tzsecs / -3600);
|
256
|
-
tzmin
|
247
|
+
tzmin = (int)(tzsecs / -60) - (tzhour * 60);
|
257
248
|
} else {
|
258
249
|
tzhour = (int)(tzsecs / 3600);
|
259
|
-
tzmin
|
250
|
+
tzmin = (int)(tzsecs / 60) - (tzhour * 60);
|
260
251
|
}
|
261
252
|
if (!xml_time) {
|
262
|
-
|
253
|
+
len = sprintf(buf,
|
254
|
+
"%04d/%02d/%02d %02d:%02d:%02d %c%02d%02d",
|
255
|
+
ti.year,
|
256
|
+
ti.mon,
|
257
|
+
ti.day,
|
258
|
+
ti.hour,
|
259
|
+
ti.min,
|
260
|
+
ti.sec,
|
261
|
+
tzsign,
|
262
|
+
tzhour,
|
263
|
+
tzmin);
|
263
264
|
} else if (0 == out->opts->sec_prec) {
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
265
|
+
if (0 == tzsecs && rb_funcall2(obj, oj_utcq_id, 0, 0)) {
|
266
|
+
len = sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02dZ", ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec);
|
267
|
+
} else {
|
268
|
+
len = sprintf(buf,
|
269
|
+
"%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
|
270
|
+
ti.year,
|
271
|
+
ti.mon,
|
272
|
+
ti.day,
|
273
|
+
ti.hour,
|
274
|
+
ti.min,
|
275
|
+
ti.sec,
|
276
|
+
tzsign,
|
277
|
+
tzhour,
|
278
|
+
tzmin);
|
279
|
+
}
|
269
280
|
} else if (0 == tzsecs && rb_funcall2(obj, oj_utcq_id, 0, 0)) {
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
281
|
+
char format[64] = "%04d-%02d-%02dT%02d:%02d:%02d.%09ldZ";
|
282
|
+
|
283
|
+
len = 30;
|
284
|
+
if (9 > out->opts->sec_prec) {
|
285
|
+
format[32] = '0' + out->opts->sec_prec;
|
286
|
+
len -= 9 - out->opts->sec_prec;
|
287
|
+
}
|
288
|
+
len = sprintf(buf, format, ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, nsec);
|
278
289
|
} else {
|
279
|
-
|
290
|
+
char format[64] = "%04d-%02d-%02dT%02d:%02d:%02d.%09ld%c%02d:%02d";
|
280
291
|
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
292
|
+
len = 35;
|
293
|
+
if (9 > out->opts->sec_prec) {
|
294
|
+
format[32] = '0' + out->opts->sec_prec;
|
295
|
+
len -= 9 - out->opts->sec_prec;
|
296
|
+
}
|
297
|
+
len = sprintf(buf, format, ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, nsec, tzsign, tzhour, tzmin);
|
287
298
|
}
|
288
299
|
oj_dump_cstr(buf, len, 0, 0, out);
|
289
300
|
}
|
290
301
|
|
291
|
-
static void
|
292
|
-
|
293
|
-
long long
|
294
|
-
long long nsec;
|
302
|
+
static void dump_time(VALUE obj, int depth, Out out, bool as_ok) {
|
303
|
+
long long sec;
|
304
|
+
long long nsec;
|
295
305
|
|
296
|
-
#ifdef HAVE_RB_TIME_TIMESPEC
|
297
306
|
if (16 <= sizeof(struct timespec)) {
|
298
|
-
|
307
|
+
struct timespec ts = rb_time_timespec(obj);
|
299
308
|
|
300
|
-
|
301
|
-
|
309
|
+
sec = (long long)ts.tv_sec;
|
310
|
+
nsec = ts.tv_nsec;
|
302
311
|
} else {
|
303
|
-
|
304
|
-
|
312
|
+
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
313
|
+
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
305
314
|
}
|
306
|
-
#else
|
307
|
-
sec = rb_num2ll(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
308
|
-
nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
309
|
-
#endif
|
310
315
|
dump_sec_nano(obj, sec, nsec, out);
|
311
316
|
}
|
312
317
|
|
313
|
-
static void
|
314
|
-
|
315
|
-
|
316
|
-
long long nsec = 0;
|
318
|
+
static void dump_timewithzone(VALUE obj, int depth, Out out, bool as_ok) {
|
319
|
+
int64_t sec = NUM2LONG(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
320
|
+
long long nsec = 0;
|
317
321
|
|
318
322
|
if (rb_respond_to(obj, oj_tv_nsec_id)) {
|
319
|
-
|
323
|
+
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
320
324
|
} else if (rb_respond_to(obj, oj_tv_usec_id)) {
|
321
|
-
|
325
|
+
nsec = NUM2LL(rb_funcall2(obj, oj_tv_usec_id, 0, 0)) * 1000;
|
322
326
|
}
|
323
327
|
dump_sec_nano(obj, sec, nsec, out);
|
324
328
|
}
|
325
329
|
|
326
|
-
static void
|
327
|
-
|
328
|
-
volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
|
330
|
+
static void dump_to_s(VALUE obj, int depth, Out out, bool as_ok) {
|
331
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
329
332
|
|
330
|
-
oj_dump_cstr(
|
333
|
+
oj_dump_cstr(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), 0, 0, out);
|
331
334
|
}
|
332
335
|
|
333
|
-
static ID
|
336
|
+
static ID parameters_id = 0;
|
334
337
|
|
335
338
|
typedef struct _strLen {
|
336
|
-
const char
|
337
|
-
int
|
339
|
+
const char *str;
|
340
|
+
int len;
|
338
341
|
} *StrLen;
|
339
342
|
|
340
|
-
static void
|
341
|
-
dump_actioncontroller_parameters(VALUE obj, int depth, Out out, bool as_ok) {
|
343
|
+
static void dump_actioncontroller_parameters(VALUE obj, int depth, Out out, bool as_ok) {
|
342
344
|
if (0 == parameters_id) {
|
343
|
-
|
345
|
+
parameters_id = rb_intern("@parameters");
|
344
346
|
}
|
345
347
|
out->argc = 0;
|
346
348
|
dump_rails_val(rb_ivar_get(obj, parameters_id), depth, out, true);
|
347
349
|
}
|
348
350
|
|
349
|
-
static StrLen
|
350
|
-
|
351
|
-
|
352
|
-
StrLen
|
353
|
-
|
354
|
-
int
|
355
|
-
int cnt = (int)RARRAY_LEN(rcols);
|
351
|
+
static StrLen columns_array(VALUE rcols, int *ccnt) {
|
352
|
+
volatile VALUE v;
|
353
|
+
StrLen cp;
|
354
|
+
StrLen cols;
|
355
|
+
int i;
|
356
|
+
int cnt = (int)RARRAY_LEN(rcols);
|
356
357
|
|
357
358
|
*ccnt = cnt;
|
358
|
-
cols
|
359
|
+
cols = OJ_R_ALLOC_N(struct _strLen, cnt);
|
359
360
|
for (i = 0, cp = cols; i < cnt; i++, cp++) {
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
361
|
+
v = RARRAY_AREF(rcols, i);
|
362
|
+
if (T_STRING != rb_type(v)) {
|
363
|
+
v = oj_safe_string_convert(v);
|
364
|
+
}
|
365
|
+
cp->str = StringValuePtr(v);
|
366
|
+
cp->len = (int)RSTRING_LEN(v);
|
366
367
|
}
|
367
368
|
return cols;
|
368
369
|
}
|
369
370
|
|
370
|
-
static void
|
371
|
-
|
372
|
-
|
373
|
-
int
|
374
|
-
int i;
|
371
|
+
static void dump_row(VALUE row, StrLen cols, int ccnt, int depth, Out out) {
|
372
|
+
size_t size;
|
373
|
+
int d2 = depth + 1;
|
374
|
+
int i;
|
375
375
|
|
376
376
|
assure_size(out, 2);
|
377
377
|
*out->cur++ = '{';
|
378
|
-
size
|
378
|
+
size = depth * out->indent + 3;
|
379
379
|
for (i = 0; i < ccnt; i++, cols++) {
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
*out->cur++ = ',';
|
401
|
-
}
|
380
|
+
assure_size(out, size);
|
381
|
+
if (out->opts->dump_opts.use) {
|
382
|
+
if (0 < out->opts->dump_opts.array_size) {
|
383
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
|
384
|
+
}
|
385
|
+
if (0 < out->opts->dump_opts.indent_size) {
|
386
|
+
int i;
|
387
|
+
for (i = d2; 0 < i; i--) {
|
388
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
389
|
+
}
|
390
|
+
}
|
391
|
+
} else {
|
392
|
+
fill_indent(out, d2);
|
393
|
+
}
|
394
|
+
oj_dump_cstr(cols->str, cols->len, 0, 0, out);
|
395
|
+
*out->cur++ = ':';
|
396
|
+
dump_rails_val(RARRAY_AREF(row, i), depth, out, true);
|
397
|
+
if (i < ccnt - 1) {
|
398
|
+
*out->cur++ = ',';
|
399
|
+
}
|
402
400
|
}
|
403
401
|
size = depth * out->indent + 1;
|
404
402
|
assure_size(out, size);
|
405
403
|
if (out->opts->dump_opts.use) {
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
}
|
417
|
-
}
|
404
|
+
if (0 < out->opts->dump_opts.array_size) {
|
405
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
|
406
|
+
}
|
407
|
+
if (0 < out->opts->dump_opts.indent_size) {
|
408
|
+
int i;
|
409
|
+
|
410
|
+
for (i = depth; 0 < i; i--) {
|
411
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
412
|
+
}
|
413
|
+
}
|
418
414
|
} else {
|
419
|
-
|
415
|
+
fill_indent(out, depth);
|
420
416
|
}
|
421
417
|
*out->cur++ = '}';
|
422
418
|
}
|
423
419
|
|
424
|
-
static ID
|
425
|
-
static ID
|
420
|
+
static ID rows_id = 0;
|
421
|
+
static ID columns_id = 0;
|
426
422
|
|
427
|
-
static void
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
int
|
432
|
-
|
433
|
-
|
434
|
-
int d2 = depth + 1;
|
423
|
+
static void dump_activerecord_result(VALUE obj, int depth, Out out, bool as_ok) {
|
424
|
+
volatile VALUE rows;
|
425
|
+
StrLen cols;
|
426
|
+
int ccnt = 0;
|
427
|
+
int i, rcnt;
|
428
|
+
size_t size;
|
429
|
+
int d2 = depth + 1;
|
435
430
|
|
436
431
|
if (0 == rows_id) {
|
437
|
-
|
438
|
-
|
432
|
+
rows_id = rb_intern("@rows");
|
433
|
+
columns_id = rb_intern("@columns");
|
439
434
|
}
|
440
435
|
out->argc = 0;
|
441
|
-
cols
|
442
|
-
rows
|
443
|
-
rcnt
|
436
|
+
cols = columns_array(rb_ivar_get(obj, columns_id), &ccnt);
|
437
|
+
rows = rb_ivar_get(obj, rows_id);
|
438
|
+
rcnt = (int)RARRAY_LEN(rows);
|
444
439
|
assure_size(out, 2);
|
445
440
|
*out->cur++ = '[';
|
446
441
|
if (out->opts->dump_opts.use) {
|
447
|
-
|
442
|
+
size = d2 * out->opts->dump_opts.indent_size + out->opts->dump_opts.array_size + 1;
|
448
443
|
} else {
|
449
|
-
|
444
|
+
size = d2 * out->indent + 2;
|
450
445
|
}
|
451
446
|
assure_size(out, 2);
|
452
447
|
for (i = 0; i < rcnt; i++) {
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
}
|
474
|
-
xfree(cols);
|
448
|
+
assure_size(out, size);
|
449
|
+
if (out->opts->dump_opts.use) {
|
450
|
+
if (0 < out->opts->dump_opts.array_size) {
|
451
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
|
452
|
+
}
|
453
|
+
if (0 < out->opts->dump_opts.indent_size) {
|
454
|
+
int i;
|
455
|
+
for (i = d2; 0 < i; i--) {
|
456
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
457
|
+
}
|
458
|
+
}
|
459
|
+
} else {
|
460
|
+
fill_indent(out, d2);
|
461
|
+
}
|
462
|
+
dump_row(RARRAY_AREF(rows, i), cols, ccnt, d2, out);
|
463
|
+
if (i < rcnt - 1) {
|
464
|
+
*out->cur++ = ',';
|
465
|
+
}
|
466
|
+
}
|
467
|
+
OJ_R_FREE(cols);
|
475
468
|
size = depth * out->indent + 1;
|
476
469
|
assure_size(out, size);
|
477
470
|
if (out->opts->dump_opts.use) {
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
}
|
489
|
-
}
|
471
|
+
if (0 < out->opts->dump_opts.array_size) {
|
472
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
|
473
|
+
}
|
474
|
+
if (0 < out->opts->dump_opts.indent_size) {
|
475
|
+
int i;
|
476
|
+
|
477
|
+
for (i = depth; 0 < i; i--) {
|
478
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
479
|
+
}
|
480
|
+
}
|
490
481
|
} else {
|
491
|
-
|
482
|
+
fill_indent(out, depth);
|
492
483
|
}
|
493
484
|
*out->cur++ = ']';
|
494
485
|
}
|
495
486
|
|
496
487
|
typedef struct _namedFunc {
|
497
|
-
const char
|
498
|
-
DumpFunc
|
488
|
+
const char *name;
|
489
|
+
DumpFunc func;
|
499
490
|
} *NamedFunc;
|
500
491
|
|
501
|
-
static void
|
502
|
-
dump_as_string(VALUE obj, int depth, Out out, bool as_ok) {
|
492
|
+
static void dump_as_string(VALUE obj, int depth, Out out, bool as_ok) {
|
503
493
|
if (oj_code_dump(oj_compat_codes, obj, depth, out)) {
|
504
|
-
|
505
|
-
|
494
|
+
out->argc = 0;
|
495
|
+
return;
|
506
496
|
}
|
507
497
|
oj_dump_obj_to_s(obj, out);
|
508
498
|
}
|
509
499
|
|
510
|
-
static void
|
511
|
-
|
512
|
-
volatile VALUE ja;
|
500
|
+
static void dump_as_json(VALUE obj, int depth, Out out, bool as_ok) {
|
501
|
+
volatile VALUE ja;
|
513
502
|
|
514
|
-
|
515
|
-
oj_trace("as_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyIn);
|
516
|
-
}
|
503
|
+
TRACE(out->opts->trace, "as_json", obj, depth + 1, TraceRubyIn);
|
517
504
|
// Some classes elect to not take an options argument so check the arity
|
518
505
|
// of as_json.
|
519
506
|
if (0 == rb_obj_method_arity(obj, oj_as_json_id)) {
|
520
|
-
|
507
|
+
ja = rb_funcall(obj, oj_as_json_id, 0);
|
521
508
|
} else {
|
522
|
-
|
523
|
-
}
|
524
|
-
if (Yes == out->opts->trace) {
|
525
|
-
oj_trace("as_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyOut);
|
509
|
+
ja = rb_funcall2(obj, oj_as_json_id, out->argc, out->argv);
|
526
510
|
}
|
511
|
+
TRACE(out->opts->trace, "as_json", obj, depth + 1, TraceRubyOut);
|
527
512
|
|
528
513
|
out->argc = 0;
|
529
514
|
if (ja == obj || !as_ok) {
|
530
|
-
|
531
|
-
|
532
|
-
|
515
|
+
// Once as_json is called it should never be called again on the same
|
516
|
+
// object with as_ok.
|
517
|
+
dump_rails_val(ja, depth, out, false);
|
533
518
|
} else {
|
534
|
-
|
519
|
+
int type = rb_type(ja);
|
535
520
|
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
521
|
+
if (T_HASH == type || T_ARRAY == type) {
|
522
|
+
dump_rails_val(ja, depth, out, true);
|
523
|
+
} else {
|
524
|
+
dump_rails_val(ja, depth, out, true);
|
525
|
+
}
|
541
526
|
}
|
542
527
|
}
|
543
528
|
|
544
|
-
static void
|
545
|
-
dump_regexp(VALUE obj, int depth, Out out, bool as_ok) {
|
529
|
+
static void dump_regexp(VALUE obj, int depth, Out out, bool as_ok) {
|
546
530
|
if (as_ok && rb_respond_to(obj, oj_as_json_id)) {
|
547
|
-
|
548
|
-
|
531
|
+
dump_as_json(obj, depth, out, false);
|
532
|
+
return;
|
549
533
|
}
|
550
534
|
dump_as_string(obj, depth, out, as_ok);
|
551
535
|
}
|
552
536
|
|
553
|
-
static struct _namedFunc
|
554
|
-
{
|
555
|
-
{
|
556
|
-
{
|
557
|
-
{
|
558
|
-
{
|
559
|
-
{
|
537
|
+
static struct _namedFunc dump_map[] = {
|
538
|
+
{"ActionController::Parameters", dump_actioncontroller_parameters},
|
539
|
+
{"ActiveRecord::Result", dump_activerecord_result},
|
540
|
+
{"ActiveSupport::TimeWithZone", dump_timewithzone},
|
541
|
+
{"BigDecimal", dump_bigdecimal},
|
542
|
+
{"Range", dump_to_s},
|
543
|
+
{"Regexp", dump_regexp},
|
560
544
|
//{ "Regexp", dump_to_s },
|
561
|
-
{
|
562
|
-
{
|
545
|
+
{"Time", dump_time},
|
546
|
+
{NULL, NULL},
|
563
547
|
};
|
564
548
|
|
565
|
-
static VALUE
|
566
|
-
static ID
|
549
|
+
static VALUE activerecord_base = Qundef;
|
550
|
+
static ID attributes_id = 0;
|
567
551
|
|
568
|
-
static void
|
569
|
-
dump_activerecord(VALUE obj, int depth, Out out, bool as_ok) {
|
552
|
+
static void dump_activerecord(VALUE obj, int depth, Out out, bool as_ok) {
|
570
553
|
if (0 == attributes_id) {
|
571
|
-
|
554
|
+
attributes_id = rb_intern("@attributes");
|
572
555
|
}
|
573
556
|
out->argc = 0;
|
574
557
|
dump_rails_val(rb_ivar_get(obj, attributes_id), depth, out, true);
|
575
558
|
}
|
576
559
|
|
577
|
-
static ROpt
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
int olen = rot->len;
|
560
|
+
static ROpt create_opt(ROptTable rot, VALUE clas) {
|
561
|
+
ROpt ro;
|
562
|
+
NamedFunc nf;
|
563
|
+
const char *classname = rb_class2name(clas);
|
564
|
+
int olen = rot->len;
|
583
565
|
|
584
566
|
rot->len++;
|
585
567
|
if (NULL == rot->table) {
|
586
|
-
|
587
|
-
|
588
|
-
|
568
|
+
rot->alen = 256;
|
569
|
+
rot->table = OJ_R_ALLOC_N(struct _rOpt, rot->alen);
|
570
|
+
memset(rot->table, 0, sizeof(struct _rOpt) * rot->alen);
|
589
571
|
} else if (rot->alen <= rot->len) {
|
590
|
-
|
591
|
-
|
592
|
-
|
572
|
+
rot->alen *= 2;
|
573
|
+
OJ_R_REALLOC_N(rot->table, struct _rOpt, rot->alen);
|
574
|
+
memset(rot->table + olen, 0, sizeof(struct _rOpt) * olen);
|
593
575
|
}
|
594
576
|
if (0 == olen) {
|
595
|
-
|
577
|
+
ro = rot->table;
|
596
578
|
} else if (rot->table[olen - 1].clas < clas) {
|
597
|
-
|
579
|
+
ro = &rot->table[olen];
|
598
580
|
} else {
|
599
|
-
|
581
|
+
int i;
|
600
582
|
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
583
|
+
for (i = 0, ro = rot->table; i < olen; i++, ro++) {
|
584
|
+
if (clas < ro->clas) {
|
585
|
+
memmove(ro + 1, ro, sizeof(struct _rOpt) * (olen - i));
|
586
|
+
break;
|
587
|
+
}
|
588
|
+
}
|
607
589
|
}
|
608
590
|
ro->clas = clas;
|
609
|
-
ro->on
|
591
|
+
ro->on = true;
|
610
592
|
ro->dump = dump_obj_attrs;
|
611
593
|
for (nf = dump_map; NULL != nf->name; nf++) {
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
594
|
+
if (0 == strcmp(nf->name, classname)) {
|
595
|
+
ro->dump = nf->func;
|
596
|
+
break;
|
597
|
+
}
|
616
598
|
}
|
617
599
|
if (ro->dump == dump_obj_attrs) {
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
600
|
+
if (Qundef == activerecord_base) {
|
601
|
+
// If not defined let an exception be raised.
|
602
|
+
VALUE ar = rb_const_get_at(rb_cObject, rb_intern("ActiveRecord"));
|
603
|
+
|
604
|
+
if (Qundef != ar) {
|
605
|
+
activerecord_base = rb_const_get_at(ar, rb_intern("Base"));
|
606
|
+
}
|
607
|
+
}
|
608
|
+
if (Qundef != activerecord_base && Qtrue == rb_class_inherited_p(clas, activerecord_base)) {
|
609
|
+
ro->dump = dump_activerecord;
|
610
|
+
} else if (Qtrue == rb_class_inherited_p(clas, rb_cStruct)) { // check before enumerable
|
611
|
+
ro->dump = dump_struct;
|
612
|
+
} else if (Qtrue == rb_class_inherited_p(clas, rb_mEnumerable)) {
|
613
|
+
ro->dump = dump_enumerable;
|
614
|
+
} else if (Qtrue == rb_class_inherited_p(clas, rb_eException)) {
|
615
|
+
ro->dump = dump_to_s;
|
616
|
+
}
|
635
617
|
}
|
636
618
|
return ro;
|
637
619
|
}
|
638
620
|
|
639
|
-
static void
|
640
|
-
encoder_free(void *ptr) {
|
621
|
+
static void encoder_free(void *ptr) {
|
641
622
|
if (NULL != ptr) {
|
642
|
-
|
623
|
+
Encoder e = (Encoder)ptr;
|
643
624
|
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
625
|
+
if (NULL != e->ropts.table) {
|
626
|
+
OJ_R_FREE(e->ropts.table);
|
627
|
+
}
|
628
|
+
OJ_R_FREE(ptr);
|
648
629
|
}
|
649
630
|
}
|
650
631
|
|
651
|
-
static void
|
652
|
-
encoder_mark(void *ptr) {
|
632
|
+
static void encoder_mark(void *ptr) {
|
653
633
|
if (NULL != ptr) {
|
654
|
-
|
634
|
+
Encoder e = (Encoder)ptr;
|
655
635
|
|
656
|
-
|
657
|
-
|
658
|
-
|
636
|
+
if (Qnil != e->arg) {
|
637
|
+
rb_gc_mark(e->arg);
|
638
|
+
}
|
659
639
|
}
|
660
640
|
}
|
661
641
|
|
642
|
+
static const rb_data_type_t oj_encoder_type = {
|
643
|
+
"Oj/encoder",
|
644
|
+
{
|
645
|
+
encoder_mark,
|
646
|
+
encoder_free,
|
647
|
+
NULL,
|
648
|
+
},
|
649
|
+
0,
|
650
|
+
0,
|
651
|
+
};
|
652
|
+
|
662
653
|
/* Document-method: new
|
663
654
|
* call-seq: new(options=nil)
|
664
655
|
*
|
665
656
|
* Creates a new Encoder.
|
666
657
|
* - *options* [_Hash_] formatting options
|
667
658
|
*/
|
668
|
-
static VALUE
|
669
|
-
|
670
|
-
Encoder e = ALLOC(struct _encoder);
|
659
|
+
static VALUE encoder_new(int argc, VALUE *argv, VALUE self) {
|
660
|
+
Encoder e = OJ_R_ALLOC(struct _encoder);
|
671
661
|
|
672
662
|
e->opts = oj_default_options;
|
673
|
-
e->arg
|
663
|
+
e->arg = Qnil;
|
674
664
|
copy_opts(&ropts, &e->ropts);
|
675
665
|
|
676
666
|
if (1 <= argc && Qnil != *argv) {
|
677
|
-
|
678
|
-
|
667
|
+
oj_parse_options(*argv, &e->opts);
|
668
|
+
e->arg = *argv;
|
679
669
|
}
|
680
|
-
return
|
670
|
+
return TypedData_Wrap_Struct(encoder_class, &oj_encoder_type, e);
|
681
671
|
}
|
682
672
|
|
683
|
-
static VALUE
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
char
|
688
|
-
char
|
689
|
-
|
690
|
-
ID cid;
|
673
|
+
static VALUE resolve_classpath(const char *name) {
|
674
|
+
char class_name[1024];
|
675
|
+
VALUE clas;
|
676
|
+
char *end = class_name + sizeof(class_name) - 1;
|
677
|
+
char *s;
|
678
|
+
const char *n = name;
|
679
|
+
ID cid;
|
691
680
|
|
692
681
|
clas = rb_cObject;
|
693
682
|
for (s = class_name; '\0' != *n; n++) {
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
}
|
712
|
-
*s
|
683
|
+
if (':' == *n) {
|
684
|
+
*s = '\0';
|
685
|
+
n++;
|
686
|
+
if (':' != *n) {
|
687
|
+
return Qnil;
|
688
|
+
}
|
689
|
+
cid = rb_intern(class_name);
|
690
|
+
if (!rb_const_defined_at(clas, cid)) {
|
691
|
+
return Qnil;
|
692
|
+
}
|
693
|
+
clas = rb_const_get_at(clas, cid);
|
694
|
+
s = class_name;
|
695
|
+
} else if (end <= s) {
|
696
|
+
return Qnil;
|
697
|
+
} else {
|
698
|
+
*s++ = *n;
|
699
|
+
}
|
700
|
+
}
|
701
|
+
*s = '\0';
|
713
702
|
cid = rb_intern(class_name);
|
714
703
|
if (!rb_const_defined_at(clas, cid)) {
|
715
|
-
|
704
|
+
return Qnil;
|
716
705
|
}
|
717
706
|
clas = rb_const_get_at(clas, cid);
|
718
707
|
|
719
708
|
return clas;
|
720
709
|
}
|
721
710
|
|
722
|
-
static void
|
723
|
-
|
724
|
-
ROpt ro;
|
711
|
+
static void optimize(int argc, VALUE *argv, ROptTable rot, bool on) {
|
712
|
+
ROpt ro;
|
725
713
|
|
726
714
|
if (0 == argc) {
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
715
|
+
int i;
|
716
|
+
NamedFunc nf;
|
717
|
+
VALUE clas;
|
718
|
+
|
719
|
+
oj_rails_hash_opt = on;
|
720
|
+
oj_rails_array_opt = on;
|
721
|
+
oj_rails_float_opt = on;
|
722
|
+
|
723
|
+
for (nf = dump_map; NULL != nf->name; nf++) {
|
724
|
+
if (Qnil != (clas = resolve_classpath(nf->name))) {
|
725
|
+
if (NULL == oj_rails_get_opt(rot, clas)) {
|
726
|
+
create_opt(rot, clas);
|
727
|
+
}
|
728
|
+
}
|
729
|
+
}
|
730
|
+
for (i = 0; i < rot->len; i++) {
|
731
|
+
rot->table[i].on = on;
|
732
|
+
}
|
745
733
|
}
|
746
734
|
for (; 0 < argc; argc--, argv++) {
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
}
|
735
|
+
if (rb_cHash == *argv) {
|
736
|
+
oj_rails_hash_opt = on;
|
737
|
+
} else if (rb_cArray == *argv) {
|
738
|
+
oj_rails_array_opt = on;
|
739
|
+
} else if (rb_cFloat == *argv) {
|
740
|
+
oj_rails_float_opt = on;
|
741
|
+
} else if (oj_string_writer_class == *argv) {
|
742
|
+
string_writer_optimized = on;
|
743
|
+
} else if (NULL != (ro = oj_rails_get_opt(rot, *argv)) || NULL != (ro = create_opt(rot, *argv))) {
|
744
|
+
ro->on = on;
|
745
|
+
}
|
759
746
|
}
|
760
747
|
}
|
761
748
|
|
@@ -771,9 +758,9 @@ optimize(int argc, VALUE *argv, ROptTable rot, bool on) {
|
|
771
758
|
*
|
772
759
|
* - *classes* [_Class_] a list of classes to optimize
|
773
760
|
*/
|
774
|
-
static VALUE
|
775
|
-
|
776
|
-
|
761
|
+
static VALUE encoder_optimize(int argc, VALUE *argv, VALUE self) {
|
762
|
+
Encoder e;
|
763
|
+
TypedData_Get_Struct(self, struct _encoder, &oj_encoder_type, e);
|
777
764
|
|
778
765
|
optimize(argc, argv, &e->ropts, true);
|
779
766
|
|
@@ -792,8 +779,7 @@ encoder_optimize(int argc, VALUE *argv, VALUE self) {
|
|
792
779
|
*
|
793
780
|
* - *classes* [_Class_] a list of classes to optimize
|
794
781
|
*/
|
795
|
-
static VALUE
|
796
|
-
rails_optimize(int argc, VALUE *argv, VALUE self) {
|
782
|
+
static VALUE rails_optimize(int argc, VALUE *argv, VALUE self) {
|
797
783
|
optimize(argc, argv, &ropts, true);
|
798
784
|
string_writer_optimized = true;
|
799
785
|
|
@@ -808,15 +794,16 @@ rails_optimize(int argc, VALUE *argv, VALUE self) {
|
|
808
794
|
*/
|
809
795
|
VALUE
|
810
796
|
rails_mimic_json(VALUE self) {
|
811
|
-
VALUE
|
797
|
+
VALUE json;
|
812
798
|
|
813
799
|
if (rb_const_defined_at(rb_cObject, rb_intern("JSON"))) {
|
814
|
-
|
800
|
+
json = rb_const_get_at(rb_cObject, rb_intern("JSON"));
|
815
801
|
} else {
|
816
|
-
|
802
|
+
json = rb_define_module("JSON");
|
817
803
|
}
|
818
804
|
oj_mimic_json_methods(json);
|
819
|
-
//
|
805
|
+
// Setting the default mode breaks the prmoise in the docs not to.
|
806
|
+
// oj_default_options.mode = RailsMode;
|
820
807
|
|
821
808
|
return Qnil;
|
822
809
|
}
|
@@ -828,9 +815,9 @@ rails_mimic_json(VALUE self) {
|
|
828
815
|
*
|
829
816
|
* - *classes* [_Class_] a list of classes to deoptimize
|
830
817
|
*/
|
831
|
-
static VALUE
|
832
|
-
|
833
|
-
|
818
|
+
static VALUE encoder_deoptimize(int argc, VALUE *argv, VALUE self) {
|
819
|
+
Encoder e;
|
820
|
+
TypedData_Get_Struct(self, struct _encoder, &oj_encoder_type, e);
|
834
821
|
|
835
822
|
optimize(argc, argv, &e->ropts, false);
|
836
823
|
|
@@ -844,8 +831,7 @@ encoder_deoptimize(int argc, VALUE *argv, VALUE self) {
|
|
844
831
|
*
|
845
832
|
* - *classes* [_Class_] a list of classes to deoptimize
|
846
833
|
*/
|
847
|
-
static VALUE
|
848
|
-
rails_deoptimize(int argc, VALUE *argv, VALUE self) {
|
834
|
+
static VALUE rails_deoptimize(int argc, VALUE *argv, VALUE self) {
|
849
835
|
optimize(argc, argv, &ropts, false);
|
850
836
|
string_writer_optimized = false;
|
851
837
|
|
@@ -859,13 +845,15 @@ rails_deoptimize(int argc, VALUE *argv, VALUE self) {
|
|
859
845
|
*
|
860
846
|
* @return true if the class is being optimized for rails and false otherwise
|
861
847
|
*/
|
862
|
-
static VALUE
|
863
|
-
|
864
|
-
|
865
|
-
|
848
|
+
static VALUE encoder_optimized(VALUE self, VALUE clas) {
|
849
|
+
Encoder e;
|
850
|
+
ROpt ro;
|
851
|
+
|
852
|
+
TypedData_Get_Struct(self, struct _encoder, &oj_encoder_type, e);
|
853
|
+
ro = oj_rails_get_opt(&e->ropts, clas);
|
866
854
|
|
867
855
|
if (NULL == ro) {
|
868
|
-
|
856
|
+
return Qfalse;
|
869
857
|
}
|
870
858
|
return (ro->on) ? Qtrue : Qfalse;
|
871
859
|
}
|
@@ -875,95 +863,87 @@ encoder_optimized(VALUE self, VALUE clas) {
|
|
875
863
|
*
|
876
864
|
* Returns true if the specified Class is being optimized.
|
877
865
|
*/
|
878
|
-
static VALUE
|
879
|
-
|
880
|
-
ROpt ro = oj_rails_get_opt(&ropts, clas);
|
866
|
+
static VALUE rails_optimized(VALUE self, VALUE clas) {
|
867
|
+
ROpt ro = oj_rails_get_opt(&ropts, clas);
|
881
868
|
|
882
869
|
if (NULL == ro) {
|
883
|
-
|
870
|
+
return Qfalse;
|
884
871
|
}
|
885
872
|
return (ro->on) ? Qtrue : Qfalse;
|
886
873
|
}
|
887
874
|
|
888
875
|
typedef struct _oo {
|
889
|
-
Out
|
890
|
-
VALUE
|
876
|
+
Out out;
|
877
|
+
VALUE obj;
|
891
878
|
} *OO;
|
892
879
|
|
893
|
-
static VALUE
|
894
|
-
|
895
|
-
OO oo = (OO)ov;
|
880
|
+
static VALUE protect_dump(VALUE ov) {
|
881
|
+
OO oo = (OO)ov;
|
896
882
|
|
897
883
|
dump_rails_val(oo->obj, 0, oo->out, true);
|
898
884
|
|
899
885
|
return Qnil;
|
900
886
|
}
|
901
887
|
|
902
|
-
static VALUE
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
struct
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
oo.out = &out;
|
912
|
-
oo.obj = obj;
|
888
|
+
static VALUE encode(VALUE obj, ROptTable ropts, Options opts, int argc, VALUE *argv) {
|
889
|
+
struct _out out;
|
890
|
+
struct _options copts = *opts;
|
891
|
+
volatile VALUE rstr = Qnil;
|
892
|
+
struct _oo oo;
|
893
|
+
int line = 0;
|
894
|
+
|
895
|
+
oo.out = &out;
|
896
|
+
oo.obj = obj;
|
913
897
|
copts.str_rx.head = NULL;
|
914
898
|
copts.str_rx.tail = NULL;
|
915
|
-
copts.mode
|
899
|
+
copts.mode = RailsMode;
|
916
900
|
if (escape_html) {
|
917
|
-
|
901
|
+
copts.escape_mode = RailsXEsc;
|
918
902
|
} else {
|
919
|
-
|
903
|
+
copts.escape_mode = RailsEsc;
|
920
904
|
}
|
921
|
-
|
922
|
-
out
|
923
|
-
|
905
|
+
|
906
|
+
oj_out_init(&out);
|
907
|
+
|
924
908
|
out.omit_nil = copts.dump_opts.omit_nil;
|
925
|
-
out.
|
926
|
-
out.cur = out.buf;
|
909
|
+
out.cur = out.buf;
|
927
910
|
out.circ_cnt = 0;
|
928
|
-
out.opts
|
911
|
+
out.opts = &copts;
|
929
912
|
out.hash_cnt = 0;
|
930
|
-
out.indent
|
931
|
-
out.argc
|
932
|
-
out.argv
|
933
|
-
out.ropts
|
913
|
+
out.indent = copts.indent;
|
914
|
+
out.argc = argc;
|
915
|
+
out.argv = argv;
|
916
|
+
out.ropts = ropts;
|
934
917
|
if (Yes == copts.circular) {
|
935
|
-
|
918
|
+
oj_cache8_new(&out.circ_cache);
|
936
919
|
}
|
937
|
-
//dump_rails_val(*argv, 0, &out, true);
|
920
|
+
// dump_rails_val(*argv, 0, &out, true);
|
938
921
|
rb_protect(protect_dump, (VALUE)&oo, &line);
|
939
922
|
|
940
923
|
if (0 == line) {
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
}
|
956
|
-
rstr = rb_str_new2(out.buf);
|
957
|
-
rstr = oj_encode(rstr);
|
924
|
+
if (0 < out.indent) {
|
925
|
+
switch (*(out.cur - 1)) {
|
926
|
+
case ']':
|
927
|
+
case '}': assure_size(&out, 2); *out.cur++ = '\n';
|
928
|
+
default: break;
|
929
|
+
}
|
930
|
+
}
|
931
|
+
*out.cur = '\0';
|
932
|
+
|
933
|
+
if (0 == out.buf) {
|
934
|
+
rb_raise(rb_eNoMemError, "Not enough memory.");
|
935
|
+
}
|
936
|
+
rstr = rb_str_new2(out.buf);
|
937
|
+
rstr = oj_encode(rstr);
|
958
938
|
}
|
959
939
|
if (Yes == copts.circular) {
|
960
|
-
|
961
|
-
}
|
962
|
-
if (out.allocated) {
|
963
|
-
xfree(out.buf);
|
940
|
+
oj_cache8_delete(out.circ_cache);
|
964
941
|
}
|
942
|
+
|
943
|
+
oj_out_free(&out);
|
944
|
+
|
965
945
|
if (0 != line) {
|
966
|
-
|
946
|
+
rb_jump_tag(line);
|
967
947
|
}
|
968
948
|
return rstr;
|
969
949
|
}
|
@@ -975,14 +955,14 @@ encode(VALUE obj, ROptTable ropts, Options opts, int argc, VALUE *argv) {
|
|
975
955
|
*
|
976
956
|
* Returns encoded object as a JSON string.
|
977
957
|
*/
|
978
|
-
static VALUE
|
979
|
-
|
980
|
-
|
958
|
+
static VALUE encoder_encode(VALUE self, VALUE obj) {
|
959
|
+
Encoder e;
|
960
|
+
TypedData_Get_Struct(self, struct _encoder, &oj_encoder_type, e);
|
981
961
|
|
982
962
|
if (Qnil != e->arg) {
|
983
|
-
|
963
|
+
VALUE argv[1] = {e->arg};
|
984
964
|
|
985
|
-
|
965
|
+
return encode(obj, &e->ropts, &e->opts, 1, argv);
|
986
966
|
}
|
987
967
|
return encode(obj, &e->ropts, &e->opts, 0, NULL);
|
988
968
|
}
|
@@ -997,26 +977,24 @@ encoder_encode(VALUE self, VALUE obj) {
|
|
997
977
|
*
|
998
978
|
* Returns [_String_]
|
999
979
|
*/
|
1000
|
-
static VALUE
|
1001
|
-
rails_encode(int argc, VALUE *argv, VALUE self) {
|
980
|
+
static VALUE rails_encode(int argc, VALUE *argv, VALUE self) {
|
1002
981
|
if (1 > argc) {
|
1003
|
-
|
982
|
+
rb_raise(rb_eArgError, "wrong number of arguments (0 for 1).");
|
1004
983
|
}
|
1005
984
|
if (1 == argc) {
|
1006
|
-
|
985
|
+
return encode(*argv, NULL, &oj_default_options, 0, NULL);
|
1007
986
|
} else {
|
1008
|
-
|
987
|
+
return encode(*argv, NULL, &oj_default_options, argc - 1, argv + 1);
|
1009
988
|
}
|
1010
989
|
}
|
1011
990
|
|
1012
|
-
static VALUE
|
1013
|
-
rails_use_standard_json_time_format(VALUE self, VALUE state) {
|
991
|
+
static VALUE rails_use_standard_json_time_format(VALUE self, VALUE state) {
|
1014
992
|
if (Qtrue == state || Qfalse == state) {
|
1015
|
-
|
993
|
+
// no change needed
|
1016
994
|
} else if (Qnil == state) {
|
1017
|
-
|
995
|
+
state = Qfalse;
|
1018
996
|
} else {
|
1019
|
-
|
997
|
+
state = Qtrue;
|
1020
998
|
}
|
1021
999
|
rb_iv_set(self, "@use_standard_json_time_format", state);
|
1022
1000
|
xml_time = Qtrue == state;
|
@@ -1024,28 +1002,24 @@ rails_use_standard_json_time_format(VALUE self, VALUE state) {
|
|
1024
1002
|
return state;
|
1025
1003
|
}
|
1026
1004
|
|
1027
|
-
static VALUE
|
1028
|
-
rails_use_standard_json_time_format_get(VALUE self) {
|
1005
|
+
static VALUE rails_use_standard_json_time_format_get(VALUE self) {
|
1029
1006
|
return xml_time ? Qtrue : Qfalse;
|
1030
1007
|
}
|
1031
1008
|
|
1032
|
-
static VALUE
|
1033
|
-
rails_escape_html_entities_in_json(VALUE self, VALUE state) {
|
1009
|
+
static VALUE rails_escape_html_entities_in_json(VALUE self, VALUE state) {
|
1034
1010
|
rb_iv_set(self, "@escape_html_entities_in_json", state);
|
1035
1011
|
escape_html = Qtrue == state;
|
1036
1012
|
|
1037
1013
|
return state;
|
1038
1014
|
}
|
1039
1015
|
|
1040
|
-
static VALUE
|
1041
|
-
rails_escape_html_entities_in_json_get(VALUE self) {
|
1016
|
+
static VALUE rails_escape_html_entities_in_json_get(VALUE self) {
|
1042
1017
|
return escape_html ? Qtrue : Qfalse;
|
1043
1018
|
}
|
1044
1019
|
|
1045
|
-
static VALUE
|
1046
|
-
rails_time_precision(VALUE self, VALUE prec) {
|
1020
|
+
static VALUE rails_time_precision(VALUE self, VALUE prec) {
|
1047
1021
|
rb_iv_set(self, "@time_precision", prec);
|
1048
|
-
oj_default_options.sec_prec
|
1022
|
+
oj_default_options.sec_prec = NUM2INT(prec);
|
1049
1023
|
oj_default_options.sec_prec_set = true;
|
1050
1024
|
|
1051
1025
|
return prec;
|
@@ -1058,27 +1032,26 @@ rails_time_precision(VALUE self, VALUE prec) {
|
|
1058
1032
|
* formatting globals used by ActiveSupport to allow the use of those globals
|
1059
1033
|
* in the Oj::Rails optimizations.
|
1060
1034
|
*/
|
1061
|
-
static VALUE
|
1062
|
-
|
1063
|
-
VALUE
|
1064
|
-
VALUE
|
1065
|
-
VALUE
|
1066
|
-
VALUE
|
1067
|
-
VALUE
|
1068
|
-
VALUE enc = resolve_classpath("ActiveSupport::JSON::Encoding");
|
1035
|
+
static VALUE rails_set_encoder(VALUE self) {
|
1036
|
+
VALUE active;
|
1037
|
+
VALUE json;
|
1038
|
+
VALUE encoding;
|
1039
|
+
VALUE pv;
|
1040
|
+
VALUE verbose;
|
1041
|
+
VALUE enc = resolve_classpath("ActiveSupport::JSON::Encoding");
|
1069
1042
|
|
1070
1043
|
if (Qnil != enc) {
|
1071
|
-
|
1072
|
-
|
1044
|
+
escape_html = Qtrue == rb_iv_get(self, "@escape_html_entities_in_json");
|
1045
|
+
xml_time = Qtrue == rb_iv_get(enc, "@use_standard_json_time_format");
|
1073
1046
|
}
|
1074
1047
|
if (rb_const_defined_at(rb_cObject, rb_intern("ActiveSupport"))) {
|
1075
|
-
|
1048
|
+
active = rb_const_get_at(rb_cObject, rb_intern("ActiveSupport"));
|
1076
1049
|
} else {
|
1077
|
-
|
1050
|
+
rb_raise(rb_eStandardError, "ActiveSupport not loaded.");
|
1078
1051
|
}
|
1079
1052
|
rb_funcall(active, rb_intern("json_encoder="), 1, encoder_class);
|
1080
1053
|
|
1081
|
-
json
|
1054
|
+
json = rb_const_get_at(active, rb_intern("JSON"));
|
1082
1055
|
encoding = rb_const_get_at(json, rb_intern("Encoding"));
|
1083
1056
|
|
1084
1057
|
// rb_undef_method doesn't work for modules or maybe sometimes
|
@@ -1090,15 +1063,15 @@ rails_set_encoder(VALUE self) {
|
|
1090
1063
|
rb_undef_method(encoding, "use_standard_json_time_format");
|
1091
1064
|
rb_define_module_function(encoding, "use_standard_json_time_format", rails_use_standard_json_time_format_get, 0);
|
1092
1065
|
|
1093
|
-
pv
|
1066
|
+
pv = rb_iv_get(encoding, "@escape_html_entities_in_json");
|
1094
1067
|
escape_html = Qtrue == pv;
|
1095
1068
|
rb_undef_method(encoding, "escape_html_entities_in_json=");
|
1096
1069
|
rb_define_module_function(encoding, "escape_html_entities_in_json=", rails_escape_html_entities_in_json, 1);
|
1097
1070
|
rb_undef_method(encoding, "escape_html_entities_in_json");
|
1098
1071
|
rb_define_module_function(encoding, "escape_html_entities_in_json", rails_escape_html_entities_in_json_get, 0);
|
1099
1072
|
|
1100
|
-
pv
|
1101
|
-
oj_default_options.sec_prec
|
1073
|
+
pv = rb_iv_get(encoding, "@time_precision");
|
1074
|
+
oj_default_options.sec_prec = NUM2INT(pv);
|
1102
1075
|
oj_default_options.sec_prec_set = true;
|
1103
1076
|
rb_undef_method(encoding, "time_precision=");
|
1104
1077
|
rb_define_module_function(encoding, "time_precision=", rails_time_precision, 1);
|
@@ -1113,16 +1086,15 @@ rails_set_encoder(VALUE self) {
|
|
1113
1086
|
* Sets the JSON.parse function to be the Oj::parse function which is json gem
|
1114
1087
|
* compatible.
|
1115
1088
|
*/
|
1116
|
-
static VALUE
|
1117
|
-
|
1118
|
-
VALUE
|
1119
|
-
VALUE
|
1120
|
-
VALUE verbose;
|
1089
|
+
static VALUE rails_set_decoder(VALUE self) {
|
1090
|
+
VALUE json;
|
1091
|
+
VALUE json_error;
|
1092
|
+
VALUE verbose;
|
1121
1093
|
|
1122
1094
|
if (rb_const_defined_at(rb_cObject, rb_intern("JSON"))) {
|
1123
|
-
|
1095
|
+
json = rb_const_get_at(rb_cObject, rb_intern("JSON"));
|
1124
1096
|
} else {
|
1125
|
-
|
1097
|
+
json = rb_define_module("JSON");
|
1126
1098
|
}
|
1127
1099
|
if (rb_const_defined_at(json, rb_intern("JSONError"))) {
|
1128
1100
|
json_error = rb_const_get(json, rb_intern("JSONError"));
|
@@ -1132,7 +1104,7 @@ rails_set_decoder(VALUE self) {
|
|
1132
1104
|
if (rb_const_defined_at(json, rb_intern("ParserError"))) {
|
1133
1105
|
oj_json_parser_error_class = rb_const_get(json, rb_intern("ParserError"));
|
1134
1106
|
} else {
|
1135
|
-
|
1107
|
+
oj_json_parser_error_class = rb_define_class_under(json, "ParserError", json_error);
|
1136
1108
|
}
|
1137
1109
|
// rb_undef_method doesn't work for modules or maybe sometimes
|
1138
1110
|
// doesn't. Anyway setting verbose should hide the warning.
|
@@ -1168,13 +1140,15 @@ oj_optimize_rails(VALUE self) {
|
|
1168
1140
|
*
|
1169
1141
|
* The Oj ActiveSupport compliant encoder.
|
1170
1142
|
*/
|
1171
|
-
void
|
1172
|
-
|
1173
|
-
VALUE rails = rb_define_module_under(Oj, "Rails");
|
1143
|
+
void oj_mimic_rails_init(void) {
|
1144
|
+
VALUE rails = rb_define_module_under(Oj, "Rails");
|
1174
1145
|
|
1175
1146
|
rb_define_module_function(rails, "encode", rails_encode, -1);
|
1176
1147
|
|
1177
1148
|
encoder_class = rb_define_class_under(rails, "Encoder", rb_cObject);
|
1149
|
+
rb_gc_register_address(&encoder_class);
|
1150
|
+
rb_undef_alloc_func(encoder_class);
|
1151
|
+
|
1178
1152
|
rb_define_module_function(encoder_class, "new", encoder_new, -1);
|
1179
1153
|
rb_define_module_function(rails, "optimize", rails_optimize, -1);
|
1180
1154
|
rb_define_module_function(rails, "deoptimize", rails_deoptimize, -1);
|
@@ -1190,336 +1164,312 @@ oj_mimic_rails_init() {
|
|
1190
1164
|
rb_define_method(encoder_class, "optimized?", encoder_optimized, 1);
|
1191
1165
|
}
|
1192
1166
|
|
1193
|
-
static void
|
1194
|
-
dump_to_hash(VALUE obj, int depth, Out out) {
|
1167
|
+
static void dump_to_hash(VALUE obj, int depth, Out out) {
|
1195
1168
|
dump_rails_val(rb_funcall(obj, oj_to_hash_id, 0), depth, out, true);
|
1196
1169
|
}
|
1197
1170
|
|
1198
|
-
static void
|
1199
|
-
|
1200
|
-
char
|
1201
|
-
|
1202
|
-
|
1203
|
-
int cnt = 0;
|
1171
|
+
static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
1172
|
+
char buf[64];
|
1173
|
+
char *b;
|
1174
|
+
double d = rb_num2dbl(obj);
|
1175
|
+
int cnt = 0;
|
1204
1176
|
|
1205
1177
|
if (0.0 == d) {
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1178
|
+
b = buf;
|
1179
|
+
*b++ = '0';
|
1180
|
+
*b++ = '.';
|
1181
|
+
*b++ = '0';
|
1182
|
+
*b++ = '\0';
|
1183
|
+
cnt = 3;
|
1212
1184
|
} else {
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1185
|
+
if (isnan(d) || OJ_INFINITY == d || -OJ_INFINITY == d) {
|
1186
|
+
strcpy(buf, "null");
|
1187
|
+
cnt = 4;
|
1188
|
+
} else if (d == (double)(long long int)d) {
|
1189
|
+
cnt = snprintf(buf, sizeof(buf), "%.1f", d);
|
1190
|
+
} else if (oj_rails_float_opt) {
|
1191
|
+
cnt = oj_dump_float_printf(buf, sizeof(buf), obj, d, "%0.16g");
|
1192
|
+
} else {
|
1193
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
1194
|
+
|
1195
|
+
strcpy(buf, RSTRING_PTR(rstr));
|
1196
|
+
cnt = (int)RSTRING_LEN(rstr);
|
1197
|
+
}
|
1226
1198
|
}
|
1227
1199
|
assure_size(out, cnt);
|
1228
1200
|
for (b = buf; '\0' != *b; b++) {
|
1229
|
-
|
1201
|
+
*out->cur++ = *b;
|
1230
1202
|
}
|
1231
1203
|
*out->cur = '\0';
|
1232
1204
|
}
|
1233
1205
|
|
1234
|
-
static void
|
1235
|
-
|
1236
|
-
|
1237
|
-
int
|
1238
|
-
int d2 = depth + 1;
|
1206
|
+
static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
|
1207
|
+
size_t size;
|
1208
|
+
int i, cnt;
|
1209
|
+
int d2 = depth + 1;
|
1239
1210
|
|
1240
1211
|
if (Yes == out->opts->circular) {
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1212
|
+
if (0 > oj_check_circular(a, out)) {
|
1213
|
+
oj_dump_nil(Qnil, 0, out, false);
|
1214
|
+
return;
|
1215
|
+
}
|
1245
1216
|
}
|
1246
|
-
//if (!oj_rails_array_opt && as_ok && 0 < out->argc && rb_respond_to(a, oj_as_json_id)) {
|
1217
|
+
// if (!oj_rails_array_opt && as_ok && 0 < out->argc && rb_respond_to(a, oj_as_json_id)) {
|
1247
1218
|
if (as_ok && 0 < out->argc && rb_respond_to(a, oj_as_json_id)) {
|
1248
|
-
|
1249
|
-
|
1219
|
+
dump_as_json(a, depth, out, false);
|
1220
|
+
return;
|
1250
1221
|
}
|
1251
|
-
cnt
|
1222
|
+
cnt = (int)RARRAY_LEN(a);
|
1252
1223
|
*out->cur++ = '[';
|
1253
|
-
size
|
1224
|
+
size = 2;
|
1254
1225
|
assure_size(out, size);
|
1255
1226
|
if (0 == cnt) {
|
1256
|
-
|
1227
|
+
*out->cur++ = ']';
|
1257
1228
|
} else {
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1265
|
-
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1296
|
-
|
1297
|
-
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1301
|
-
} else {
|
1302
|
-
fill_indent(out, depth);
|
1303
|
-
}
|
1304
|
-
*out->cur++ = ']';
|
1229
|
+
if (out->opts->dump_opts.use) {
|
1230
|
+
size = d2 * out->opts->dump_opts.indent_size + out->opts->dump_opts.array_size + 1;
|
1231
|
+
} else {
|
1232
|
+
size = d2 * out->indent + 2;
|
1233
|
+
}
|
1234
|
+
assure_size(out, size * cnt);
|
1235
|
+
cnt--;
|
1236
|
+
for (i = 0; i <= cnt; i++) {
|
1237
|
+
if (out->opts->dump_opts.use) {
|
1238
|
+
if (0 < out->opts->dump_opts.array_size) {
|
1239
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
|
1240
|
+
}
|
1241
|
+
if (0 < out->opts->dump_opts.indent_size) {
|
1242
|
+
int i;
|
1243
|
+
for (i = d2; 0 < i; i--) {
|
1244
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
1245
|
+
}
|
1246
|
+
}
|
1247
|
+
} else {
|
1248
|
+
fill_indent(out, d2);
|
1249
|
+
}
|
1250
|
+
dump_rails_val(RARRAY_AREF(a, i), d2, out, true);
|
1251
|
+
if (i < cnt) {
|
1252
|
+
*out->cur++ = ',';
|
1253
|
+
}
|
1254
|
+
}
|
1255
|
+
size = depth * out->indent + 1;
|
1256
|
+
assure_size(out, size);
|
1257
|
+
if (out->opts->dump_opts.use) {
|
1258
|
+
if (0 < out->opts->dump_opts.array_size) {
|
1259
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
|
1260
|
+
}
|
1261
|
+
if (0 < out->opts->dump_opts.indent_size) {
|
1262
|
+
int i;
|
1263
|
+
|
1264
|
+
for (i = depth; 0 < i; i--) {
|
1265
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
1266
|
+
}
|
1267
|
+
}
|
1268
|
+
} else {
|
1269
|
+
fill_indent(out, depth);
|
1270
|
+
}
|
1271
|
+
*out->cur++ = ']';
|
1305
1272
|
}
|
1306
1273
|
*out->cur = '\0';
|
1307
1274
|
}
|
1308
1275
|
|
1309
|
-
static int
|
1310
|
-
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
int rtype = rb_type(key);
|
1276
|
+
static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
1277
|
+
Out out = (Out)ov;
|
1278
|
+
int depth = out->depth;
|
1279
|
+
long size;
|
1280
|
+
int rtype = rb_type(key);
|
1315
1281
|
|
1316
1282
|
if (out->omit_nil && Qnil == value) {
|
1317
|
-
|
1283
|
+
return ST_CONTINUE;
|
1318
1284
|
}
|
1319
1285
|
if (rtype != T_STRING && rtype != T_SYMBOL) {
|
1320
|
-
|
1321
|
-
|
1286
|
+
key = oj_safe_string_convert(key);
|
1287
|
+
rtype = rb_type(key);
|
1322
1288
|
}
|
1323
1289
|
if (!out->opts->dump_opts.use) {
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1290
|
+
size = depth * out->indent + 1;
|
1291
|
+
assure_size(out, size);
|
1292
|
+
fill_indent(out, depth);
|
1293
|
+
if (rtype == T_STRING) {
|
1294
|
+
oj_dump_str(key, 0, out, false);
|
1295
|
+
} else {
|
1296
|
+
oj_dump_sym(key, 0, out, false);
|
1297
|
+
}
|
1298
|
+
*out->cur++ = ':';
|
1333
1299
|
} else {
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
if (0 < out->opts->dump_opts.after_size) {
|
1360
|
-
strcpy(out->cur, out->opts->dump_opts.after_sep);
|
1361
|
-
out->cur += out->opts->dump_opts.after_size;
|
1362
|
-
}
|
1300
|
+
size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
|
1301
|
+
assure_size(out, size);
|
1302
|
+
if (0 < out->opts->dump_opts.hash_size) {
|
1303
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.hash_nl, out->opts->dump_opts.hash_size);
|
1304
|
+
}
|
1305
|
+
if (0 < out->opts->dump_opts.indent_size) {
|
1306
|
+
int i;
|
1307
|
+
for (i = depth; 0 < i; i--) {
|
1308
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
1309
|
+
}
|
1310
|
+
}
|
1311
|
+
if (rtype == T_STRING) {
|
1312
|
+
oj_dump_str(key, 0, out, false);
|
1313
|
+
} else {
|
1314
|
+
oj_dump_sym(key, 0, out, false);
|
1315
|
+
}
|
1316
|
+
size = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
|
1317
|
+
assure_size(out, size);
|
1318
|
+
if (0 < out->opts->dump_opts.before_size) {
|
1319
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
|
1320
|
+
}
|
1321
|
+
*out->cur++ = ':';
|
1322
|
+
if (0 < out->opts->dump_opts.after_size) {
|
1323
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
|
1324
|
+
}
|
1363
1325
|
}
|
1364
1326
|
dump_rails_val(value, depth, out, true);
|
1365
|
-
out->depth
|
1327
|
+
out->depth = depth;
|
1366
1328
|
*out->cur++ = ',';
|
1367
1329
|
|
1368
1330
|
return ST_CONTINUE;
|
1369
1331
|
}
|
1370
1332
|
|
1371
|
-
static void
|
1372
|
-
|
1373
|
-
|
1374
|
-
size_t size;
|
1333
|
+
static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
|
1334
|
+
int cnt;
|
1335
|
+
size_t size;
|
1375
1336
|
|
1376
1337
|
if (Yes == out->opts->circular) {
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1338
|
+
if (0 > oj_check_circular(obj, out)) {
|
1339
|
+
oj_dump_nil(Qnil, 0, out, false);
|
1340
|
+
return;
|
1341
|
+
}
|
1381
1342
|
}
|
1382
1343
|
if ((!oj_rails_hash_opt || 0 < out->argc) && as_ok && rb_respond_to(obj, oj_as_json_id)) {
|
1383
|
-
|
1384
|
-
|
1344
|
+
dump_as_json(obj, depth, out, false);
|
1345
|
+
return;
|
1385
1346
|
}
|
1386
|
-
cnt
|
1347
|
+
cnt = (int)RHASH_SIZE(obj);
|
1387
1348
|
size = depth * out->indent + 2;
|
1388
1349
|
assure_size(out, 2);
|
1389
1350
|
*out->cur++ = '{';
|
1390
1351
|
if (0 == cnt) {
|
1391
|
-
|
1352
|
+
*out->cur++ = '}';
|
1392
1353
|
} else {
|
1393
|
-
|
1394
|
-
|
1395
|
-
|
1396
|
-
|
1397
|
-
|
1398
|
-
|
1399
|
-
|
1400
|
-
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
|
1408
|
-
|
1409
|
-
|
1410
|
-
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1414
|
-
|
1415
|
-
|
1416
|
-
}
|
1417
|
-
*out->cur++ = '}';
|
1354
|
+
out->depth = depth + 1;
|
1355
|
+
rb_hash_foreach(obj, hash_cb, (VALUE)out);
|
1356
|
+
if (',' == *(out->cur - 1)) {
|
1357
|
+
out->cur--; // backup to overwrite last comma
|
1358
|
+
}
|
1359
|
+
if (!out->opts->dump_opts.use) {
|
1360
|
+
assure_size(out, size);
|
1361
|
+
fill_indent(out, depth);
|
1362
|
+
} else {
|
1363
|
+
size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
|
1364
|
+
assure_size(out, size);
|
1365
|
+
if (0 < out->opts->dump_opts.hash_size) {
|
1366
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.hash_nl, out->opts->dump_opts.hash_size);
|
1367
|
+
}
|
1368
|
+
if (0 < out->opts->dump_opts.indent_size) {
|
1369
|
+
int i;
|
1370
|
+
|
1371
|
+
for (i = depth; 0 < i; i--) {
|
1372
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
1373
|
+
}
|
1374
|
+
}
|
1375
|
+
}
|
1376
|
+
*out->cur++ = '}';
|
1418
1377
|
}
|
1419
1378
|
*out->cur = '\0';
|
1420
1379
|
}
|
1421
1380
|
|
1422
|
-
static void
|
1423
|
-
|
1424
|
-
VALUE clas;
|
1381
|
+
static void dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
|
1382
|
+
VALUE clas;
|
1425
1383
|
|
1426
1384
|
if (oj_code_dump(oj_compat_codes, obj, depth, out)) {
|
1427
|
-
|
1428
|
-
|
1385
|
+
out->argc = 0;
|
1386
|
+
return;
|
1429
1387
|
}
|
1430
1388
|
clas = rb_obj_class(obj);
|
1431
1389
|
if (as_ok) {
|
1432
|
-
|
1433
|
-
|
1434
|
-
|
1435
|
-
|
1436
|
-
|
1437
|
-
|
1438
|
-
|
1439
|
-
|
1440
|
-
|
1441
|
-
|
1442
|
-
|
1443
|
-
|
1444
|
-
|
1445
|
-
|
1446
|
-
|
1390
|
+
ROpt ro;
|
1391
|
+
|
1392
|
+
if (NULL != (ro = oj_rails_get_opt(out->ropts, clas)) && ro->on) {
|
1393
|
+
ro->dump(obj, depth, out, as_ok);
|
1394
|
+
} else if (Yes == out->opts->raw_json && rb_respond_to(obj, oj_raw_json_id)) {
|
1395
|
+
oj_dump_raw_json(obj, depth, out);
|
1396
|
+
} else if (rb_respond_to(obj, oj_as_json_id)) {
|
1397
|
+
dump_as_json(obj, depth, out, true);
|
1398
|
+
} else if (rb_respond_to(obj, oj_to_hash_id)) {
|
1399
|
+
dump_to_hash(obj, depth, out);
|
1400
|
+
} else if (oj_bigdecimal_class == clas) {
|
1401
|
+
dump_bigdecimal(obj, depth, out, false);
|
1402
|
+
} else {
|
1403
|
+
oj_dump_obj_to_s(obj, out);
|
1404
|
+
}
|
1447
1405
|
} else if (Yes == out->opts->raw_json && rb_respond_to(obj, oj_raw_json_id)) {
|
1448
|
-
|
1406
|
+
oj_dump_raw_json(obj, depth, out);
|
1449
1407
|
} else if (rb_respond_to(obj, oj_to_hash_id)) {
|
1450
|
-
|
1451
|
-
|
1408
|
+
// Always attempt to_hash.
|
1409
|
+
dump_to_hash(obj, depth, out);
|
1452
1410
|
} else if (oj_bigdecimal_class == clas) {
|
1453
|
-
|
1411
|
+
dump_bigdecimal(obj, depth, out, false);
|
1454
1412
|
} else {
|
1455
|
-
|
1413
|
+
oj_dump_obj_to_s(obj, out);
|
1456
1414
|
}
|
1457
1415
|
}
|
1458
1416
|
|
1459
|
-
static DumpFunc
|
1460
|
-
NULL,
|
1461
|
-
dump_obj,
|
1462
|
-
oj_dump_class,
|
1463
|
-
oj_dump_class,
|
1464
|
-
dump_float,
|
1465
|
-
oj_dump_str,
|
1466
|
-
dump_regexp,
|
1467
|
-
//dump_as_string, // RUBY_T_REGEXP = 0x06,
|
1468
|
-
dump_array,
|
1469
|
-
dump_hash,
|
1470
|
-
dump_obj,
|
1471
|
-
oj_dump_bignum,
|
1472
|
-
dump_as_string,
|
1473
|
-
dump_obj,
|
1474
|
-
NULL,
|
1417
|
+
static DumpFunc rails_funcs[] = {
|
1418
|
+
NULL, // RUBY_T_NONE = 0x00,
|
1419
|
+
dump_obj, // RUBY_T_OBJECT = 0x01,
|
1420
|
+
oj_dump_class, // RUBY_T_CLASS = 0x02,
|
1421
|
+
oj_dump_class, // RUBY_T_MODULE = 0x03,
|
1422
|
+
dump_float, // RUBY_T_FLOAT = 0x04,
|
1423
|
+
oj_dump_str, // RUBY_T_STRING = 0x05,
|
1424
|
+
dump_regexp, // RUBY_T_REGEXP = 0x06,
|
1425
|
+
// dump_as_string, // RUBY_T_REGEXP = 0x06,
|
1426
|
+
dump_array, // RUBY_T_ARRAY = 0x07,
|
1427
|
+
dump_hash, // RUBY_T_HASH = 0x08,
|
1428
|
+
dump_obj, // RUBY_T_STRUCT = 0x09,
|
1429
|
+
oj_dump_bignum, // RUBY_T_BIGNUM = 0x0a,
|
1430
|
+
dump_as_string, // RUBY_T_FILE = 0x0b,
|
1431
|
+
dump_obj, // RUBY_T_DATA = 0x0c,
|
1432
|
+
NULL, // RUBY_T_MATCH = 0x0d,
|
1475
1433
|
// Rails raises a stack error on Complex and Rational. It also corrupts
|
1476
1434
|
// something which causes a segfault on the next call. Oj will not mimic
|
1477
1435
|
// that behavior.
|
1478
|
-
dump_as_string,
|
1479
|
-
dump_as_string,
|
1480
|
-
NULL,
|
1481
|
-
oj_dump_nil,
|
1482
|
-
oj_dump_true,
|
1483
|
-
oj_dump_false,
|
1484
|
-
oj_dump_sym,
|
1485
|
-
oj_dump_fixnum,
|
1436
|
+
dump_as_string, // RUBY_T_COMPLEX = 0x0e,
|
1437
|
+
dump_as_string, // RUBY_T_RATIONAL = 0x0f,
|
1438
|
+
NULL, // 0x10
|
1439
|
+
oj_dump_nil, // RUBY_T_NIL = 0x11,
|
1440
|
+
oj_dump_true, // RUBY_T_TRUE = 0x12,
|
1441
|
+
oj_dump_false, // RUBY_T_FALSE = 0x13,
|
1442
|
+
oj_dump_sym, // RUBY_T_SYMBOL = 0x14,
|
1443
|
+
oj_dump_fixnum, // RUBY_T_FIXNUM = 0x15,
|
1486
1444
|
};
|
1487
1445
|
|
1488
|
-
static void
|
1489
|
-
|
1490
|
-
int type = rb_type(obj);
|
1446
|
+
static void dump_rails_val(VALUE obj, int depth, Out out, bool as_ok) {
|
1447
|
+
int type = rb_type(obj);
|
1491
1448
|
|
1492
|
-
|
1493
|
-
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
|
1494
|
-
}
|
1449
|
+
TRACE(out->opts->trace, "dump", obj, depth, TraceIn);
|
1495
1450
|
if (MAX_DEPTH < depth) {
|
1496
|
-
|
1451
|
+
rb_raise(rb_eNoMemError, "Too deeply nested.\n");
|
1497
1452
|
}
|
1498
1453
|
if (0 < type && type <= RUBY_T_FIXNUM) {
|
1499
|
-
|
1454
|
+
DumpFunc f = rails_funcs[type];
|
1500
1455
|
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
1504
|
-
|
1505
|
-
|
1506
|
-
return;
|
1507
|
-
}
|
1456
|
+
if (NULL != f) {
|
1457
|
+
f(obj, depth, out, as_ok);
|
1458
|
+
TRACE(out->opts->trace, "dump", obj, depth, TraceOut);
|
1459
|
+
return;
|
1460
|
+
}
|
1508
1461
|
}
|
1509
1462
|
oj_dump_nil(Qnil, depth, out, false);
|
1510
|
-
|
1511
|
-
oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
|
1512
|
-
}
|
1463
|
+
TRACE(out->opts->trace, "dump", Qnil, depth, TraceOut);
|
1513
1464
|
}
|
1514
1465
|
|
1515
|
-
void
|
1516
|
-
oj_dump_rails_val(VALUE obj, int depth, Out out) {
|
1466
|
+
void oj_dump_rails_val(VALUE obj, int depth, Out out) {
|
1517
1467
|
out->opts->str_rx.head = NULL;
|
1518
1468
|
out->opts->str_rx.tail = NULL;
|
1519
1469
|
if (escape_html) {
|
1520
|
-
|
1470
|
+
out->opts->escape_mode = RailsXEsc;
|
1521
1471
|
} else {
|
1522
|
-
|
1472
|
+
out->opts->escape_mode = RailsEsc;
|
1523
1473
|
}
|
1524
1474
|
dump_rails_val(obj, depth, out, true);
|
1525
1475
|
}
|