oj 3.11.0 → 3.11.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -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 +1008 -1038
- 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 +413 -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 +1131 -924
- 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 -839
- 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/easy_hash.rb +5 -4
- 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 +35 -32
- data/test/helper.rb +10 -0
- data/test/json_gem/json_generator_test.rb +15 -3
- data/test/json_gem/test_helper.rb +8 -0
- data/test/test_compat.rb +2 -2
- data/test/test_generate.rb +21 -0
- data/test/test_hash.rb +10 -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,15 +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);
|
819
|
-
//oj_default_options.mode = RailsMode;
|
831
|
+
// oj_default_options.mode = RailsMode;
|
820
832
|
|
821
833
|
return Qnil;
|
822
834
|
}
|
@@ -828,9 +840,8 @@ rails_mimic_json(VALUE self) {
|
|
828
840
|
*
|
829
841
|
* - *classes* [_Class_] a list of classes to deoptimize
|
830
842
|
*/
|
831
|
-
static VALUE
|
832
|
-
|
833
|
-
Encoder e = (Encoder)DATA_PTR(self);
|
843
|
+
static VALUE encoder_deoptimize(int argc, VALUE *argv, VALUE self) {
|
844
|
+
Encoder e = (Encoder)DATA_PTR(self);
|
834
845
|
|
835
846
|
optimize(argc, argv, &e->ropts, false);
|
836
847
|
|
@@ -844,8 +855,7 @@ encoder_deoptimize(int argc, VALUE *argv, VALUE self) {
|
|
844
855
|
*
|
845
856
|
* - *classes* [_Class_] a list of classes to deoptimize
|
846
857
|
*/
|
847
|
-
static VALUE
|
848
|
-
rails_deoptimize(int argc, VALUE *argv, VALUE self) {
|
858
|
+
static VALUE rails_deoptimize(int argc, VALUE *argv, VALUE self) {
|
849
859
|
optimize(argc, argv, &ropts, false);
|
850
860
|
string_writer_optimized = false;
|
851
861
|
|
@@ -859,13 +869,12 @@ rails_deoptimize(int argc, VALUE *argv, VALUE self) {
|
|
859
869
|
*
|
860
870
|
* @return true if the class is being optimized for rails and false otherwise
|
861
871
|
*/
|
862
|
-
static VALUE
|
863
|
-
|
864
|
-
|
865
|
-
ROpt ro = oj_rails_get_opt(&e->ropts, clas);
|
872
|
+
static VALUE encoder_optimized(VALUE self, VALUE clas) {
|
873
|
+
Encoder e = (Encoder)DATA_PTR(self);
|
874
|
+
ROpt ro = oj_rails_get_opt(&e->ropts, clas);
|
866
875
|
|
867
876
|
if (NULL == ro) {
|
868
|
-
|
877
|
+
return Qfalse;
|
869
878
|
}
|
870
879
|
return (ro->on) ? Qtrue : Qfalse;
|
871
880
|
}
|
@@ -875,95 +884,89 @@ encoder_optimized(VALUE self, VALUE clas) {
|
|
875
884
|
*
|
876
885
|
* Returns true if the specified Class is being optimized.
|
877
886
|
*/
|
878
|
-
static VALUE
|
879
|
-
|
880
|
-
ROpt ro = oj_rails_get_opt(&ropts, clas);
|
887
|
+
static VALUE rails_optimized(VALUE self, VALUE clas) {
|
888
|
+
ROpt ro = oj_rails_get_opt(&ropts, clas);
|
881
889
|
|
882
890
|
if (NULL == ro) {
|
883
|
-
|
891
|
+
return Qfalse;
|
884
892
|
}
|
885
893
|
return (ro->on) ? Qtrue : Qfalse;
|
886
894
|
}
|
887
895
|
|
888
896
|
typedef struct _oo {
|
889
|
-
Out
|
890
|
-
VALUE
|
891
|
-
} *OO;
|
897
|
+
Out out;
|
898
|
+
VALUE obj;
|
899
|
+
} * OO;
|
892
900
|
|
893
|
-
static VALUE
|
894
|
-
|
895
|
-
OO oo = (OO)ov;
|
901
|
+
static VALUE protect_dump(VALUE ov) {
|
902
|
+
OO oo = (OO)ov;
|
896
903
|
|
897
904
|
dump_rails_val(oo->obj, 0, oo->out, true);
|
898
905
|
|
899
906
|
return Qnil;
|
900
907
|
}
|
901
908
|
|
902
|
-
static VALUE
|
903
|
-
|
904
|
-
|
905
|
-
struct
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
oo.
|
912
|
-
oo.obj = obj;
|
909
|
+
static VALUE encode(VALUE obj, ROptTable ropts, Options opts, int argc, VALUE *argv) {
|
910
|
+
char buf[4096];
|
911
|
+
struct _out out;
|
912
|
+
struct _options copts = *opts;
|
913
|
+
volatile VALUE rstr = Qnil;
|
914
|
+
struct _oo oo;
|
915
|
+
int line = 0;
|
916
|
+
|
917
|
+
oo.out = &out;
|
918
|
+
oo.obj = obj;
|
913
919
|
copts.str_rx.head = NULL;
|
914
920
|
copts.str_rx.tail = NULL;
|
915
|
-
copts.mode
|
921
|
+
copts.mode = RailsMode;
|
916
922
|
if (escape_html) {
|
917
|
-
|
923
|
+
copts.escape_mode = RailsXEsc;
|
918
924
|
} else {
|
919
|
-
|
925
|
+
copts.escape_mode = RailsEsc;
|
920
926
|
}
|
921
|
-
out.buf
|
922
|
-
out.end
|
927
|
+
out.buf = buf;
|
928
|
+
out.end = buf + sizeof(buf) - 10;
|
923
929
|
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
|
930
|
+
out.omit_nil = copts.dump_opts.omit_nil;
|
931
|
+
out.caller = 0;
|
932
|
+
out.cur = out.buf;
|
933
|
+
out.circ_cnt = 0;
|
934
|
+
out.opts = &copts;
|
935
|
+
out.hash_cnt = 0;
|
936
|
+
out.indent = copts.indent;
|
937
|
+
out.argc = argc;
|
938
|
+
out.argv = argv;
|
939
|
+
out.ropts = ropts;
|
934
940
|
if (Yes == copts.circular) {
|
935
|
-
|
941
|
+
oj_cache8_new(&out.circ_cache);
|
936
942
|
}
|
937
|
-
//dump_rails_val(*argv, 0, &out, true);
|
943
|
+
// dump_rails_val(*argv, 0, &out, true);
|
938
944
|
rb_protect(protect_dump, (VALUE)&oo, &line);
|
939
945
|
|
940
946
|
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);
|
947
|
+
if (0 < out.indent) {
|
948
|
+
switch (*(out.cur - 1)) {
|
949
|
+
case ']':
|
950
|
+
case '}': assure_size(&out, 2); *out.cur++ = '\n';
|
951
|
+
default: break;
|
952
|
+
}
|
953
|
+
}
|
954
|
+
*out.cur = '\0';
|
955
|
+
|
956
|
+
if (0 == out.buf) {
|
957
|
+
rb_raise(rb_eNoMemError, "Not enough memory.");
|
958
|
+
}
|
959
|
+
rstr = rb_str_new2(out.buf);
|
960
|
+
rstr = oj_encode(rstr);
|
958
961
|
}
|
959
962
|
if (Yes == copts.circular) {
|
960
|
-
|
963
|
+
oj_cache8_delete(out.circ_cache);
|
961
964
|
}
|
962
965
|
if (out.allocated) {
|
963
|
-
|
966
|
+
xfree(out.buf);
|
964
967
|
}
|
965
968
|
if (0 != line) {
|
966
|
-
|
969
|
+
rb_jump_tag(line);
|
967
970
|
}
|
968
971
|
return rstr;
|
969
972
|
}
|
@@ -975,14 +978,13 @@ encode(VALUE obj, ROptTable ropts, Options opts, int argc, VALUE *argv) {
|
|
975
978
|
*
|
976
979
|
* Returns encoded object as a JSON string.
|
977
980
|
*/
|
978
|
-
static VALUE
|
979
|
-
|
980
|
-
Encoder e = (Encoder)DATA_PTR(self);
|
981
|
+
static VALUE encoder_encode(VALUE self, VALUE obj) {
|
982
|
+
Encoder e = (Encoder)DATA_PTR(self);
|
981
983
|
|
982
984
|
if (Qnil != e->arg) {
|
983
|
-
|
985
|
+
VALUE argv[1] = {e->arg};
|
984
986
|
|
985
|
-
|
987
|
+
return encode(obj, &e->ropts, &e->opts, 1, argv);
|
986
988
|
}
|
987
989
|
return encode(obj, &e->ropts, &e->opts, 0, NULL);
|
988
990
|
}
|
@@ -997,26 +999,24 @@ encoder_encode(VALUE self, VALUE obj) {
|
|
997
999
|
*
|
998
1000
|
* Returns [_String_]
|
999
1001
|
*/
|
1000
|
-
static VALUE
|
1001
|
-
rails_encode(int argc, VALUE *argv, VALUE self) {
|
1002
|
+
static VALUE rails_encode(int argc, VALUE *argv, VALUE self) {
|
1002
1003
|
if (1 > argc) {
|
1003
|
-
|
1004
|
+
rb_raise(rb_eArgError, "wrong number of arguments (0 for 1).");
|
1004
1005
|
}
|
1005
1006
|
if (1 == argc) {
|
1006
|
-
|
1007
|
+
return encode(*argv, NULL, &oj_default_options, 0, NULL);
|
1007
1008
|
} else {
|
1008
|
-
|
1009
|
+
return encode(*argv, NULL, &oj_default_options, argc - 1, argv + 1);
|
1009
1010
|
}
|
1010
1011
|
}
|
1011
1012
|
|
1012
|
-
static VALUE
|
1013
|
-
rails_use_standard_json_time_format(VALUE self, VALUE state) {
|
1013
|
+
static VALUE rails_use_standard_json_time_format(VALUE self, VALUE state) {
|
1014
1014
|
if (Qtrue == state || Qfalse == state) {
|
1015
|
-
|
1015
|
+
// no change needed
|
1016
1016
|
} else if (Qnil == state) {
|
1017
|
-
|
1017
|
+
state = Qfalse;
|
1018
1018
|
} else {
|
1019
|
-
|
1019
|
+
state = Qtrue;
|
1020
1020
|
}
|
1021
1021
|
rb_iv_set(self, "@use_standard_json_time_format", state);
|
1022
1022
|
xml_time = Qtrue == state;
|
@@ -1024,28 +1024,24 @@ rails_use_standard_json_time_format(VALUE self, VALUE state) {
|
|
1024
1024
|
return state;
|
1025
1025
|
}
|
1026
1026
|
|
1027
|
-
static VALUE
|
1028
|
-
rails_use_standard_json_time_format_get(VALUE self) {
|
1027
|
+
static VALUE rails_use_standard_json_time_format_get(VALUE self) {
|
1029
1028
|
return xml_time ? Qtrue : Qfalse;
|
1030
1029
|
}
|
1031
1030
|
|
1032
|
-
static VALUE
|
1033
|
-
rails_escape_html_entities_in_json(VALUE self, VALUE state) {
|
1031
|
+
static VALUE rails_escape_html_entities_in_json(VALUE self, VALUE state) {
|
1034
1032
|
rb_iv_set(self, "@escape_html_entities_in_json", state);
|
1035
1033
|
escape_html = Qtrue == state;
|
1036
1034
|
|
1037
1035
|
return state;
|
1038
1036
|
}
|
1039
1037
|
|
1040
|
-
static VALUE
|
1041
|
-
rails_escape_html_entities_in_json_get(VALUE self) {
|
1038
|
+
static VALUE rails_escape_html_entities_in_json_get(VALUE self) {
|
1042
1039
|
return escape_html ? Qtrue : Qfalse;
|
1043
1040
|
}
|
1044
1041
|
|
1045
|
-
static VALUE
|
1046
|
-
rails_time_precision(VALUE self, VALUE prec) {
|
1042
|
+
static VALUE rails_time_precision(VALUE self, VALUE prec) {
|
1047
1043
|
rb_iv_set(self, "@time_precision", prec);
|
1048
|
-
oj_default_options.sec_prec
|
1044
|
+
oj_default_options.sec_prec = NUM2INT(prec);
|
1049
1045
|
oj_default_options.sec_prec_set = true;
|
1050
1046
|
|
1051
1047
|
return prec;
|
@@ -1058,27 +1054,26 @@ rails_time_precision(VALUE self, VALUE prec) {
|
|
1058
1054
|
* formatting globals used by ActiveSupport to allow the use of those globals
|
1059
1055
|
* in the Oj::Rails optimizations.
|
1060
1056
|
*/
|
1061
|
-
static VALUE
|
1062
|
-
|
1063
|
-
VALUE
|
1064
|
-
VALUE
|
1065
|
-
VALUE
|
1066
|
-
VALUE
|
1067
|
-
VALUE
|
1068
|
-
VALUE enc = resolve_classpath("ActiveSupport::JSON::Encoding");
|
1057
|
+
static VALUE rails_set_encoder(VALUE self) {
|
1058
|
+
VALUE active;
|
1059
|
+
VALUE json;
|
1060
|
+
VALUE encoding;
|
1061
|
+
VALUE pv;
|
1062
|
+
VALUE verbose;
|
1063
|
+
VALUE enc = resolve_classpath("ActiveSupport::JSON::Encoding");
|
1069
1064
|
|
1070
1065
|
if (Qnil != enc) {
|
1071
|
-
|
1072
|
-
|
1066
|
+
escape_html = Qtrue == rb_iv_get(self, "@escape_html_entities_in_json");
|
1067
|
+
xml_time = Qtrue == rb_iv_get(enc, "@use_standard_json_time_format");
|
1073
1068
|
}
|
1074
1069
|
if (rb_const_defined_at(rb_cObject, rb_intern("ActiveSupport"))) {
|
1075
|
-
|
1070
|
+
active = rb_const_get_at(rb_cObject, rb_intern("ActiveSupport"));
|
1076
1071
|
} else {
|
1077
|
-
|
1072
|
+
rb_raise(rb_eStandardError, "ActiveSupport not loaded.");
|
1078
1073
|
}
|
1079
1074
|
rb_funcall(active, rb_intern("json_encoder="), 1, encoder_class);
|
1080
1075
|
|
1081
|
-
json
|
1076
|
+
json = rb_const_get_at(active, rb_intern("JSON"));
|
1082
1077
|
encoding = rb_const_get_at(json, rb_intern("Encoding"));
|
1083
1078
|
|
1084
1079
|
// rb_undef_method doesn't work for modules or maybe sometimes
|
@@ -1086,19 +1081,31 @@ rails_set_encoder(VALUE self) {
|
|
1086
1081
|
verbose = rb_gv_get("$VERBOSE");
|
1087
1082
|
rb_gv_set("$VERBOSE", Qfalse);
|
1088
1083
|
rb_undef_method(encoding, "use_standard_json_time_format=");
|
1089
|
-
rb_define_module_function(encoding,
|
1084
|
+
rb_define_module_function(encoding,
|
1085
|
+
"use_standard_json_time_format=",
|
1086
|
+
rails_use_standard_json_time_format,
|
1087
|
+
1);
|
1090
1088
|
rb_undef_method(encoding, "use_standard_json_time_format");
|
1091
|
-
rb_define_module_function(encoding,
|
1089
|
+
rb_define_module_function(encoding,
|
1090
|
+
"use_standard_json_time_format",
|
1091
|
+
rails_use_standard_json_time_format_get,
|
1092
|
+
0);
|
1092
1093
|
|
1093
|
-
pv
|
1094
|
+
pv = rb_iv_get(encoding, "@escape_html_entities_in_json");
|
1094
1095
|
escape_html = Qtrue == pv;
|
1095
1096
|
rb_undef_method(encoding, "escape_html_entities_in_json=");
|
1096
|
-
rb_define_module_function(encoding,
|
1097
|
+
rb_define_module_function(encoding,
|
1098
|
+
"escape_html_entities_in_json=",
|
1099
|
+
rails_escape_html_entities_in_json,
|
1100
|
+
1);
|
1097
1101
|
rb_undef_method(encoding, "escape_html_entities_in_json");
|
1098
|
-
rb_define_module_function(encoding,
|
1102
|
+
rb_define_module_function(encoding,
|
1103
|
+
"escape_html_entities_in_json",
|
1104
|
+
rails_escape_html_entities_in_json_get,
|
1105
|
+
0);
|
1099
1106
|
|
1100
|
-
pv
|
1101
|
-
oj_default_options.sec_prec
|
1107
|
+
pv = rb_iv_get(encoding, "@time_precision");
|
1108
|
+
oj_default_options.sec_prec = NUM2INT(pv);
|
1102
1109
|
oj_default_options.sec_prec_set = true;
|
1103
1110
|
rb_undef_method(encoding, "time_precision=");
|
1104
1111
|
rb_define_module_function(encoding, "time_precision=", rails_time_precision, 1);
|
@@ -1113,16 +1120,15 @@ rails_set_encoder(VALUE self) {
|
|
1113
1120
|
* Sets the JSON.parse function to be the Oj::parse function which is json gem
|
1114
1121
|
* compatible.
|
1115
1122
|
*/
|
1116
|
-
static VALUE
|
1117
|
-
|
1118
|
-
VALUE
|
1119
|
-
VALUE
|
1120
|
-
VALUE verbose;
|
1123
|
+
static VALUE rails_set_decoder(VALUE self) {
|
1124
|
+
VALUE json;
|
1125
|
+
VALUE json_error;
|
1126
|
+
VALUE verbose;
|
1121
1127
|
|
1122
1128
|
if (rb_const_defined_at(rb_cObject, rb_intern("JSON"))) {
|
1123
|
-
|
1129
|
+
json = rb_const_get_at(rb_cObject, rb_intern("JSON"));
|
1124
1130
|
} else {
|
1125
|
-
|
1131
|
+
json = rb_define_module("JSON");
|
1126
1132
|
}
|
1127
1133
|
if (rb_const_defined_at(json, rb_intern("JSONError"))) {
|
1128
1134
|
json_error = rb_const_get(json, rb_intern("JSONError"));
|
@@ -1132,7 +1138,7 @@ rails_set_decoder(VALUE self) {
|
|
1132
1138
|
if (rb_const_defined_at(json, rb_intern("ParserError"))) {
|
1133
1139
|
oj_json_parser_error_class = rb_const_get(json, rb_intern("ParserError"));
|
1134
1140
|
} else {
|
1135
|
-
|
1141
|
+
oj_json_parser_error_class = rb_define_class_under(json, "ParserError", json_error);
|
1136
1142
|
}
|
1137
1143
|
// rb_undef_method doesn't work for modules or maybe sometimes
|
1138
1144
|
// doesn't. Anyway setting verbose should hide the warning.
|
@@ -1168,9 +1174,8 @@ oj_optimize_rails(VALUE self) {
|
|
1168
1174
|
*
|
1169
1175
|
* The Oj ActiveSupport compliant encoder.
|
1170
1176
|
*/
|
1171
|
-
void
|
1172
|
-
|
1173
|
-
VALUE rails = rb_define_module_under(Oj, "Rails");
|
1177
|
+
void oj_mimic_rails_init() {
|
1178
|
+
VALUE rails = rb_define_module_under(Oj, "Rails");
|
1174
1179
|
|
1175
1180
|
rb_define_module_function(rails, "encode", rails_encode, -1);
|
1176
1181
|
|
@@ -1190,336 +1195,328 @@ oj_mimic_rails_init() {
|
|
1190
1195
|
rb_define_method(encoder_class, "optimized?", encoder_optimized, 1);
|
1191
1196
|
}
|
1192
1197
|
|
1193
|
-
static void
|
1194
|
-
dump_to_hash(VALUE obj, int depth, Out out) {
|
1198
|
+
static void dump_to_hash(VALUE obj, int depth, Out out) {
|
1195
1199
|
dump_rails_val(rb_funcall(obj, oj_to_hash_id, 0), depth, out, true);
|
1196
1200
|
}
|
1197
1201
|
|
1198
|
-
static void
|
1199
|
-
|
1200
|
-
char
|
1201
|
-
|
1202
|
-
|
1203
|
-
int cnt = 0;
|
1202
|
+
static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
1203
|
+
char buf[64];
|
1204
|
+
char * b;
|
1205
|
+
double d = rb_num2dbl(obj);
|
1206
|
+
int cnt = 0;
|
1204
1207
|
|
1205
1208
|
if (0.0 == d) {
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1209
|
+
b = buf;
|
1210
|
+
*b++ = '0';
|
1211
|
+
*b++ = '.';
|
1212
|
+
*b++ = '0';
|
1213
|
+
*b++ = '\0';
|
1214
|
+
cnt = 3;
|
1212
1215
|
} else {
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1216
|
+
if (isnan(d) || OJ_INFINITY == d || -OJ_INFINITY == d) {
|
1217
|
+
strcpy(buf, "null");
|
1218
|
+
cnt = 4;
|
1219
|
+
} else if (d == (double)(long long int)d) {
|
1220
|
+
cnt = snprintf(buf, sizeof(buf), "%.1f", d);
|
1221
|
+
} else if (oj_rails_float_opt) {
|
1222
|
+
cnt = oj_dump_float_printf(buf, sizeof(buf), obj, d, "%0.16g");
|
1223
|
+
} else {
|
1224
|
+
volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
|
1225
|
+
|
1226
|
+
strcpy(buf, rb_string_value_ptr((VALUE *)&rstr));
|
1227
|
+
cnt = (int)RSTRING_LEN(rstr);
|
1228
|
+
}
|
1226
1229
|
}
|
1227
1230
|
assure_size(out, cnt);
|
1228
1231
|
for (b = buf; '\0' != *b; b++) {
|
1229
|
-
|
1232
|
+
*out->cur++ = *b;
|
1230
1233
|
}
|
1231
1234
|
*out->cur = '\0';
|
1232
1235
|
}
|
1233
1236
|
|
1234
|
-
static void
|
1235
|
-
|
1236
|
-
|
1237
|
-
int
|
1238
|
-
int d2 = depth + 1;
|
1237
|
+
static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
|
1238
|
+
size_t size;
|
1239
|
+
int i, cnt;
|
1240
|
+
int d2 = depth + 1;
|
1239
1241
|
|
1240
1242
|
if (Yes == out->opts->circular) {
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1243
|
+
if (0 > oj_check_circular(a, out)) {
|
1244
|
+
oj_dump_nil(Qnil, 0, out, false);
|
1245
|
+
return;
|
1246
|
+
}
|
1245
1247
|
}
|
1246
|
-
//if (!oj_rails_array_opt && as_ok && 0 < out->argc && rb_respond_to(a, oj_as_json_id)) {
|
1248
|
+
// if (!oj_rails_array_opt && as_ok && 0 < out->argc && rb_respond_to(a, oj_as_json_id)) {
|
1247
1249
|
if (as_ok && 0 < out->argc && rb_respond_to(a, oj_as_json_id)) {
|
1248
|
-
|
1249
|
-
|
1250
|
+
dump_as_json(a, depth, out, false);
|
1251
|
+
return;
|
1250
1252
|
}
|
1251
|
-
cnt
|
1253
|
+
cnt = (int)RARRAY_LEN(a);
|
1252
1254
|
*out->cur++ = '[';
|
1253
|
-
size
|
1255
|
+
size = 2;
|
1254
1256
|
assure_size(out, size);
|
1255
1257
|
if (0 == cnt) {
|
1256
|
-
|
1258
|
+
*out->cur++ = ']';
|
1257
1259
|
} 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
|
-
|
1260
|
+
if (out->opts->dump_opts.use) {
|
1261
|
+
size = d2 * out->opts->dump_opts.indent_size + out->opts->dump_opts.array_size + 1;
|
1262
|
+
} else {
|
1263
|
+
size = d2 * out->indent + 2;
|
1264
|
+
}
|
1265
|
+
cnt--;
|
1266
|
+
for (i = 0; i <= cnt; i++) {
|
1267
|
+
assure_size(out, size);
|
1268
|
+
if (out->opts->dump_opts.use) {
|
1269
|
+
if (0 < out->opts->dump_opts.array_size) {
|
1270
|
+
strcpy(out->cur, out->opts->dump_opts.array_nl);
|
1271
|
+
out->cur += out->opts->dump_opts.array_size;
|
1272
|
+
}
|
1273
|
+
if (0 < out->opts->dump_opts.indent_size) {
|
1274
|
+
int i;
|
1275
|
+
for (i = d2; 0 < i; i--) {
|
1276
|
+
strcpy(out->cur, out->opts->dump_opts.indent_str);
|
1277
|
+
out->cur += out->opts->dump_opts.indent_size;
|
1278
|
+
}
|
1279
|
+
}
|
1280
|
+
} else {
|
1281
|
+
fill_indent(out, d2);
|
1282
|
+
}
|
1283
|
+
dump_rails_val(rb_ary_entry(a, i), d2, out, true);
|
1284
|
+
if (i < cnt) {
|
1285
|
+
*out->cur++ = ',';
|
1286
|
+
}
|
1287
|
+
}
|
1288
|
+
size = depth * out->indent + 1;
|
1289
|
+
assure_size(out, size);
|
1290
|
+
if (out->opts->dump_opts.use) {
|
1291
|
+
if (0 < out->opts->dump_opts.array_size) {
|
1292
|
+
strcpy(out->cur, out->opts->dump_opts.array_nl);
|
1293
|
+
out->cur += out->opts->dump_opts.array_size;
|
1294
|
+
}
|
1295
|
+
if (0 < out->opts->dump_opts.indent_size) {
|
1296
|
+
int i;
|
1297
|
+
|
1298
|
+
for (i = depth; 0 < i; i--) {
|
1299
|
+
strcpy(out->cur, out->opts->dump_opts.indent_str);
|
1300
|
+
out->cur += out->opts->dump_opts.indent_size;
|
1301
|
+
}
|
1302
|
+
}
|
1303
|
+
} else {
|
1304
|
+
fill_indent(out, depth);
|
1305
|
+
}
|
1306
|
+
*out->cur++ = ']';
|
1305
1307
|
}
|
1306
1308
|
*out->cur = '\0';
|
1307
1309
|
}
|
1308
1310
|
|
1309
|
-
static int
|
1310
|
-
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
int rtype = rb_type(key);
|
1311
|
+
static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
1312
|
+
Out out = (Out)ov;
|
1313
|
+
int depth = out->depth;
|
1314
|
+
long size;
|
1315
|
+
int rtype = rb_type(key);
|
1315
1316
|
|
1316
1317
|
if (out->omit_nil && Qnil == value) {
|
1317
|
-
|
1318
|
+
return ST_CONTINUE;
|
1318
1319
|
}
|
1319
1320
|
if (rtype != T_STRING && rtype != T_SYMBOL) {
|
1320
|
-
|
1321
|
-
|
1321
|
+
key = rb_funcall(key, oj_to_s_id, 0);
|
1322
|
+
rtype = rb_type(key);
|
1322
1323
|
}
|
1323
1324
|
if (!out->opts->dump_opts.use) {
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1325
|
+
size = depth * out->indent + 1;
|
1326
|
+
assure_size(out, size);
|
1327
|
+
fill_indent(out, depth);
|
1328
|
+
if (rtype == T_STRING) {
|
1329
|
+
oj_dump_str(key, 0, out, false);
|
1330
|
+
} else {
|
1331
|
+
oj_dump_sym(key, 0, out, false);
|
1332
|
+
}
|
1333
|
+
*out->cur++ = ':';
|
1333
1334
|
} 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
|
-
|
1335
|
+
size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
|
1336
|
+
assure_size(out, size);
|
1337
|
+
if (0 < out->opts->dump_opts.hash_size) {
|
1338
|
+
strcpy(out->cur, out->opts->dump_opts.hash_nl);
|
1339
|
+
out->cur += out->opts->dump_opts.hash_size;
|
1340
|
+
}
|
1341
|
+
if (0 < out->opts->dump_opts.indent_size) {
|
1342
|
+
int i;
|
1343
|
+
for (i = depth; 0 < i; i--) {
|
1344
|
+
strcpy(out->cur, out->opts->dump_opts.indent_str);
|
1345
|
+
out->cur += out->opts->dump_opts.indent_size;
|
1346
|
+
}
|
1347
|
+
}
|
1348
|
+
if (rtype == T_STRING) {
|
1349
|
+
oj_dump_str(key, 0, out, false);
|
1350
|
+
} else {
|
1351
|
+
oj_dump_sym(key, 0, out, false);
|
1352
|
+
}
|
1353
|
+
size = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
|
1354
|
+
assure_size(out, size);
|
1355
|
+
if (0 < out->opts->dump_opts.before_size) {
|
1356
|
+
strcpy(out->cur, out->opts->dump_opts.before_sep);
|
1357
|
+
out->cur += out->opts->dump_opts.before_size;
|
1358
|
+
}
|
1359
|
+
*out->cur++ = ':';
|
1360
|
+
if (0 < out->opts->dump_opts.after_size) {
|
1361
|
+
strcpy(out->cur, out->opts->dump_opts.after_sep);
|
1362
|
+
out->cur += out->opts->dump_opts.after_size;
|
1363
|
+
}
|
1363
1364
|
}
|
1364
1365
|
dump_rails_val(value, depth, out, true);
|
1365
|
-
out->depth
|
1366
|
+
out->depth = depth;
|
1366
1367
|
*out->cur++ = ',';
|
1367
1368
|
|
1368
1369
|
return ST_CONTINUE;
|
1369
1370
|
}
|
1370
1371
|
|
1371
|
-
static void
|
1372
|
-
|
1373
|
-
|
1374
|
-
size_t size;
|
1372
|
+
static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
|
1373
|
+
int cnt;
|
1374
|
+
size_t size;
|
1375
1375
|
|
1376
1376
|
if (Yes == out->opts->circular) {
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1377
|
+
if (0 > oj_check_circular(obj, out)) {
|
1378
|
+
oj_dump_nil(Qnil, 0, out, false);
|
1379
|
+
return;
|
1380
|
+
}
|
1381
1381
|
}
|
1382
1382
|
if ((!oj_rails_hash_opt || 0 < out->argc) && as_ok && rb_respond_to(obj, oj_as_json_id)) {
|
1383
|
-
|
1384
|
-
|
1383
|
+
dump_as_json(obj, depth, out, false);
|
1384
|
+
return;
|
1385
1385
|
}
|
1386
|
-
cnt
|
1386
|
+
cnt = (int)RHASH_SIZE(obj);
|
1387
1387
|
size = depth * out->indent + 2;
|
1388
1388
|
assure_size(out, 2);
|
1389
1389
|
*out->cur++ = '{';
|
1390
1390
|
if (0 == cnt) {
|
1391
|
-
|
1391
|
+
*out->cur++ = '}';
|
1392
1392
|
} 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
|
-
|
1393
|
+
out->depth = depth + 1;
|
1394
|
+
rb_hash_foreach(obj, hash_cb, (VALUE)out);
|
1395
|
+
if (',' == *(out->cur - 1)) {
|
1396
|
+
out->cur--; // backup to overwrite last comma
|
1397
|
+
}
|
1398
|
+
if (!out->opts->dump_opts.use) {
|
1399
|
+
assure_size(out, size);
|
1400
|
+
fill_indent(out, depth);
|
1401
|
+
} else {
|
1402
|
+
size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
|
1403
|
+
assure_size(out, size);
|
1404
|
+
if (0 < out->opts->dump_opts.hash_size) {
|
1405
|
+
strcpy(out->cur, out->opts->dump_opts.hash_nl);
|
1406
|
+
out->cur += out->opts->dump_opts.hash_size;
|
1407
|
+
}
|
1408
|
+
if (0 < out->opts->dump_opts.indent_size) {
|
1409
|
+
int i;
|
1410
|
+
|
1411
|
+
for (i = depth; 0 < i; i--) {
|
1412
|
+
strcpy(out->cur, out->opts->dump_opts.indent_str);
|
1413
|
+
out->cur += out->opts->dump_opts.indent_size;
|
1414
|
+
}
|
1415
|
+
}
|
1416
|
+
}
|
1417
|
+
*out->cur++ = '}';
|
1418
1418
|
}
|
1419
1419
|
*out->cur = '\0';
|
1420
1420
|
}
|
1421
1421
|
|
1422
|
-
static void
|
1423
|
-
|
1424
|
-
VALUE clas;
|
1422
|
+
static void dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
|
1423
|
+
VALUE clas;
|
1425
1424
|
|
1426
1425
|
if (oj_code_dump(oj_compat_codes, obj, depth, out)) {
|
1427
|
-
|
1428
|
-
|
1426
|
+
out->argc = 0;
|
1427
|
+
return;
|
1429
1428
|
}
|
1430
1429
|
clas = rb_obj_class(obj);
|
1431
1430
|
if (as_ok) {
|
1432
|
-
|
1433
|
-
|
1434
|
-
|
1435
|
-
|
1436
|
-
|
1437
|
-
|
1438
|
-
|
1439
|
-
|
1440
|
-
|
1441
|
-
|
1442
|
-
|
1443
|
-
|
1444
|
-
|
1445
|
-
|
1446
|
-
|
1431
|
+
ROpt ro;
|
1432
|
+
|
1433
|
+
if (NULL != (ro = oj_rails_get_opt(out->ropts, clas)) && ro->on) {
|
1434
|
+
ro->dump(obj, depth, out, as_ok);
|
1435
|
+
} else if (Yes == out->opts->raw_json && rb_respond_to(obj, oj_raw_json_id)) {
|
1436
|
+
oj_dump_raw_json(obj, depth, out);
|
1437
|
+
} else if (rb_respond_to(obj, oj_as_json_id)) {
|
1438
|
+
dump_as_json(obj, depth, out, true);
|
1439
|
+
} else if (rb_respond_to(obj, oj_to_hash_id)) {
|
1440
|
+
dump_to_hash(obj, depth, out);
|
1441
|
+
} else if (oj_bigdecimal_class == clas) {
|
1442
|
+
dump_bigdecimal(obj, depth, out, false);
|
1443
|
+
} else {
|
1444
|
+
oj_dump_obj_to_s(obj, out);
|
1445
|
+
}
|
1447
1446
|
} else if (Yes == out->opts->raw_json && rb_respond_to(obj, oj_raw_json_id)) {
|
1448
|
-
|
1447
|
+
oj_dump_raw_json(obj, depth, out);
|
1449
1448
|
} else if (rb_respond_to(obj, oj_to_hash_id)) {
|
1450
|
-
|
1451
|
-
|
1449
|
+
// Always attempt to_hash.
|
1450
|
+
dump_to_hash(obj, depth, out);
|
1452
1451
|
} else if (oj_bigdecimal_class == clas) {
|
1453
|
-
|
1452
|
+
dump_bigdecimal(obj, depth, out, false);
|
1454
1453
|
} else {
|
1455
|
-
|
1454
|
+
oj_dump_obj_to_s(obj, out);
|
1456
1455
|
}
|
1457
1456
|
}
|
1458
1457
|
|
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,
|
1458
|
+
static DumpFunc rails_funcs[] = {
|
1459
|
+
NULL, // RUBY_T_NONE = 0x00,
|
1460
|
+
dump_obj, // RUBY_T_OBJECT = 0x01,
|
1461
|
+
oj_dump_class, // RUBY_T_CLASS = 0x02,
|
1462
|
+
oj_dump_class, // RUBY_T_MODULE = 0x03,
|
1463
|
+
dump_float, // RUBY_T_FLOAT = 0x04,
|
1464
|
+
oj_dump_str, // RUBY_T_STRING = 0x05,
|
1465
|
+
dump_regexp, // RUBY_T_REGEXP = 0x06,
|
1466
|
+
// dump_as_string, // RUBY_T_REGEXP = 0x06,
|
1467
|
+
dump_array, // RUBY_T_ARRAY = 0x07,
|
1468
|
+
dump_hash, // RUBY_T_HASH = 0x08,
|
1469
|
+
dump_obj, // RUBY_T_STRUCT = 0x09,
|
1470
|
+
oj_dump_bignum, // RUBY_T_BIGNUM = 0x0a,
|
1471
|
+
dump_as_string, // RUBY_T_FILE = 0x0b,
|
1472
|
+
dump_obj, // RUBY_T_DATA = 0x0c,
|
1473
|
+
NULL, // RUBY_T_MATCH = 0x0d,
|
1475
1474
|
// Rails raises a stack error on Complex and Rational. It also corrupts
|
1476
1475
|
// something which causes a segfault on the next call. Oj will not mimic
|
1477
1476
|
// 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,
|
1477
|
+
dump_as_string, // RUBY_T_COMPLEX = 0x0e,
|
1478
|
+
dump_as_string, // RUBY_T_RATIONAL = 0x0f,
|
1479
|
+
NULL, // 0x10
|
1480
|
+
oj_dump_nil, // RUBY_T_NIL = 0x11,
|
1481
|
+
oj_dump_true, // RUBY_T_TRUE = 0x12,
|
1482
|
+
oj_dump_false, // RUBY_T_FALSE = 0x13,
|
1483
|
+
oj_dump_sym, // RUBY_T_SYMBOL = 0x14,
|
1484
|
+
oj_dump_fixnum, // RUBY_T_FIXNUM = 0x15,
|
1486
1485
|
};
|
1487
1486
|
|
1488
|
-
static void
|
1489
|
-
|
1490
|
-
int type = rb_type(obj);
|
1487
|
+
static void dump_rails_val(VALUE obj, int depth, Out out, bool as_ok) {
|
1488
|
+
int type = rb_type(obj);
|
1491
1489
|
|
1492
1490
|
if (Yes == out->opts->trace) {
|
1493
|
-
|
1491
|
+
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
|
1494
1492
|
}
|
1495
1493
|
if (MAX_DEPTH < depth) {
|
1496
|
-
|
1494
|
+
rb_raise(rb_eNoMemError, "Too deeply nested.\n");
|
1497
1495
|
}
|
1498
1496
|
if (0 < type && type <= RUBY_T_FIXNUM) {
|
1499
|
-
|
1497
|
+
DumpFunc f = rails_funcs[type];
|
1500
1498
|
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
1504
|
-
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1499
|
+
if (NULL != f) {
|
1500
|
+
f(obj, depth, out, as_ok);
|
1501
|
+
if (Yes == out->opts->trace) {
|
1502
|
+
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
|
1503
|
+
}
|
1504
|
+
return;
|
1505
|
+
}
|
1508
1506
|
}
|
1509
1507
|
oj_dump_nil(Qnil, depth, out, false);
|
1510
1508
|
if (Yes == out->opts->trace) {
|
1511
|
-
|
1509
|
+
oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
|
1512
1510
|
}
|
1513
1511
|
}
|
1514
1512
|
|
1515
|
-
void
|
1516
|
-
oj_dump_rails_val(VALUE obj, int depth, Out out) {
|
1513
|
+
void oj_dump_rails_val(VALUE obj, int depth, Out out) {
|
1517
1514
|
out->opts->str_rx.head = NULL;
|
1518
1515
|
out->opts->str_rx.tail = NULL;
|
1519
1516
|
if (escape_html) {
|
1520
|
-
|
1517
|
+
out->opts->escape_mode = RailsXEsc;
|
1521
1518
|
} else {
|
1522
|
-
|
1519
|
+
out->opts->escape_mode = RailsEsc;
|
1523
1520
|
}
|
1524
1521
|
dump_rails_val(obj, depth, out, true);
|
1525
1522
|
}
|