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