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