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