oj 3.13.11 → 3.13.23
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +50 -0
- data/README.md +2 -0
- data/ext/oj/buf.h +4 -0
- data/ext/oj/circarray.c +1 -1
- data/ext/oj/code.c +15 -22
- data/ext/oj/compat.c +10 -10
- data/ext/oj/custom.c +62 -108
- data/ext/oj/dump.c +85 -97
- data/ext/oj/dump.h +12 -8
- data/ext/oj/dump_compat.c +46 -88
- data/ext/oj/dump_leaf.c +14 -58
- data/ext/oj/dump_object.c +33 -156
- data/ext/oj/dump_strict.c +17 -29
- data/ext/oj/extconf.rb +5 -4
- data/ext/oj/fast.c +24 -22
- data/ext/oj/intern.c +15 -11
- data/ext/oj/intern.h +1 -1
- data/ext/oj/mimic_json.c +44 -32
- data/ext/oj/object.c +42 -41
- data/ext/oj/odd.c +83 -63
- data/ext/oj/odd.h +13 -13
- data/ext/oj/oj.c +57 -22
- data/ext/oj/oj.h +24 -3
- data/ext/oj/parse.c +114 -78
- data/ext/oj/parse.h +2 -0
- data/ext/oj/parser.c +77 -21
- data/ext/oj/parser.h +12 -0
- data/ext/oj/rails.c +41 -65
- data/ext/oj/rails.h +1 -1
- data/ext/oj/reader.c +2 -0
- data/ext/oj/saj.c +11 -23
- data/ext/oj/saj2.c +333 -85
- data/ext/oj/saj2.h +23 -0
- data/ext/oj/sparse.c +4 -0
- data/ext/oj/stream_writer.c +3 -1
- data/ext/oj/strict.c +13 -13
- data/ext/oj/string_writer.c +12 -5
- data/ext/oj/usual.c +82 -129
- data/ext/oj/usual.h +68 -0
- data/ext/oj/val_stack.c +1 -1
- data/ext/oj/validate.c +21 -26
- data/ext/oj/wab.c +21 -26
- data/lib/oj/saj.rb +20 -6
- data/lib/oj/state.rb +1 -1
- data/lib/oj/version.rb +1 -1
- data/pages/Compatibility.md +1 -1
- data/pages/Options.md +6 -0
- data/test/activesupport7/abstract_unit.rb +49 -0
- data/test/activesupport7/decoding_test.rb +125 -0
- data/test/activesupport7/encoding_test.rb +486 -0
- data/test/activesupport7/encoding_test_cases.rb +104 -0
- data/test/activesupport7/time_zone_test_helpers.rb +47 -0
- data/test/bar.rb +3 -8
- data/test/foo.rb +3 -3
- data/test/helper.rb +8 -2
- data/test/json_gem/json_generator_test.rb +5 -4
- data/test/json_gem/json_parser_test.rb +8 -1
- data/test/json_gem/test_helper.rb +7 -3
- data/test/perf_dump.rb +50 -0
- data/test/test_compat.rb +25 -0
- data/test/test_custom.rb +13 -2
- data/test/test_file.rb +23 -7
- data/test/test_gc.rb +11 -0
- data/test/test_object.rb +8 -10
- data/test/test_parser.rb +3 -19
- data/test/test_parser_debug.rb +27 -0
- data/test/test_parser_saj.rb +92 -2
- data/test/test_scp.rb +2 -4
- data/test/test_strict.rb +2 -0
- data/test/test_various.rb +8 -3
- data/test/test_wab.rb +2 -0
- data/test/tests.rb +9 -0
- data/test/tests_mimic.rb +9 -0
- data/test/tests_mimic_addition.rb +9 -0
- metadata +13 -116
data/ext/oj/odd.c
CHANGED
@@ -5,28 +5,27 @@
|
|
5
5
|
|
6
6
|
#include <string.h>
|
7
7
|
|
8
|
-
static
|
9
|
-
static
|
10
|
-
static
|
11
|
-
static ID
|
12
|
-
static ID
|
13
|
-
static ID
|
14
|
-
static ID
|
15
|
-
static ID denominator_id;
|
16
|
-
static ID rational_id;
|
17
|
-
static VALUE rational_class;
|
8
|
+
static Odd odds = NULL;
|
9
|
+
static ID sec_id;
|
10
|
+
static ID sec_fraction_id;
|
11
|
+
static ID to_f_id;
|
12
|
+
static ID numerator_id;
|
13
|
+
static ID denominator_id;
|
14
|
+
static ID rational_id;
|
18
15
|
|
19
16
|
static void set_class(Odd odd, const char *classname) {
|
20
17
|
const char **np;
|
21
|
-
ID
|
18
|
+
ID *idp;
|
22
19
|
|
23
|
-
odd->classname
|
24
|
-
odd->clen
|
25
|
-
odd->clas
|
20
|
+
odd->classname = classname;
|
21
|
+
odd->clen = strlen(classname);
|
22
|
+
odd->clas = rb_const_get(rb_cObject, rb_intern(classname));
|
23
|
+
rb_gc_register_mark_object(odd->clas);
|
26
24
|
odd->create_obj = odd->clas;
|
27
|
-
odd->
|
28
|
-
odd->
|
29
|
-
odd->
|
25
|
+
rb_gc_register_mark_object(odd->create_obj);
|
26
|
+
odd->create_op = rb_intern("new");
|
27
|
+
odd->is_module = (T_MODULE == rb_type(odd->clas));
|
28
|
+
odd->raw = 0;
|
30
29
|
for (np = odd->attr_names, idp = odd->attrs; 0 != *np; np++, idp++) {
|
31
30
|
*idp = rb_intern(*np);
|
32
31
|
}
|
@@ -37,15 +36,48 @@ static VALUE get_datetime_secs(VALUE obj) {
|
|
37
36
|
volatile VALUE rsecs = rb_funcall(obj, sec_id, 0);
|
38
37
|
volatile VALUE rfrac = rb_funcall(obj, sec_fraction_id, 0);
|
39
38
|
long sec = NUM2LONG(rsecs);
|
40
|
-
long long num =
|
41
|
-
long long den =
|
39
|
+
long long num = NUM2LL(rb_funcall(rfrac, numerator_id, 0));
|
40
|
+
long long den = NUM2LL(rb_funcall(rfrac, denominator_id, 0));
|
42
41
|
|
43
42
|
num += sec * den;
|
44
43
|
|
45
44
|
return rb_funcall(rb_cObject, rational_id, 2, rb_ll2inum(num), rb_ll2inum(den));
|
46
45
|
}
|
47
46
|
|
48
|
-
void
|
47
|
+
static void print_odd(Odd odd) {
|
48
|
+
const char **np;
|
49
|
+
int i;
|
50
|
+
|
51
|
+
printf(" %s {\n", odd->classname);
|
52
|
+
printf(" attr_cnt: %d %p\n", odd->attr_cnt, (void *)odd->attr_names);
|
53
|
+
printf(" attr_names: %p\n", (void *)*odd->attr_names);
|
54
|
+
printf(" attr_names: %c\n", **odd->attr_names);
|
55
|
+
for (i = odd->attr_cnt, np = odd->attr_names; 0 < i; i--, np++) {
|
56
|
+
printf(" %d %s\n", i, *np);
|
57
|
+
}
|
58
|
+
printf(" }\n");
|
59
|
+
}
|
60
|
+
|
61
|
+
void print_all_odds(const char *label) {
|
62
|
+
Odd odd;
|
63
|
+
printf("@ %s {\n", label);
|
64
|
+
for (odd = odds; NULL != odd; odd = odd->next) {
|
65
|
+
print_odd(odd);
|
66
|
+
}
|
67
|
+
printf("}\n");
|
68
|
+
}
|
69
|
+
|
70
|
+
static Odd odd_create(void) {
|
71
|
+
Odd odd = ALLOC(struct _odd);
|
72
|
+
|
73
|
+
memset(odd, 0, sizeof(struct _odd));
|
74
|
+
odd->next = odds;
|
75
|
+
odds = odd;
|
76
|
+
|
77
|
+
return odd;
|
78
|
+
}
|
79
|
+
|
80
|
+
void oj_odd_init(void) {
|
49
81
|
Odd odd;
|
50
82
|
const char **np;
|
51
83
|
|
@@ -55,11 +87,9 @@ void oj_odd_init() {
|
|
55
87
|
numerator_id = rb_intern("numerator");
|
56
88
|
denominator_id = rb_intern("denominator");
|
57
89
|
rational_id = rb_intern("Rational");
|
58
|
-
rational_class = rb_const_get(rb_cObject, rational_id);
|
59
90
|
|
60
|
-
memset(_odds, 0, sizeof(_odds));
|
61
|
-
odd = odds;
|
62
91
|
// Rational
|
92
|
+
odd = odd_create();
|
63
93
|
np = odd->attr_names;
|
64
94
|
*np++ = "numerator";
|
65
95
|
*np++ = "denominator";
|
@@ -68,8 +98,9 @@ void oj_odd_init() {
|
|
68
98
|
odd->create_obj = rb_cObject;
|
69
99
|
odd->create_op = rational_id;
|
70
100
|
odd->attr_cnt = 2;
|
101
|
+
|
71
102
|
// Date
|
72
|
-
odd
|
103
|
+
odd = odd_create();
|
73
104
|
np = odd->attr_names;
|
74
105
|
*np++ = "year";
|
75
106
|
*np++ = "month";
|
@@ -78,8 +109,9 @@ void oj_odd_init() {
|
|
78
109
|
*np++ = 0;
|
79
110
|
set_class(odd, "Date");
|
80
111
|
odd->attr_cnt = 4;
|
112
|
+
|
81
113
|
// DateTime
|
82
|
-
odd
|
114
|
+
odd = odd_create();
|
83
115
|
np = odd->attr_names;
|
84
116
|
*np++ = "year";
|
85
117
|
*np++ = "month";
|
@@ -93,8 +125,9 @@ void oj_odd_init() {
|
|
93
125
|
set_class(odd, "DateTime");
|
94
126
|
odd->attr_cnt = 8;
|
95
127
|
odd->attrFuncs[5] = get_datetime_secs;
|
128
|
+
|
96
129
|
// Range
|
97
|
-
odd
|
130
|
+
odd = odd_create();
|
98
131
|
np = odd->attr_names;
|
99
132
|
*np++ = "begin";
|
100
133
|
*np++ = "end";
|
@@ -102,15 +135,13 @@ void oj_odd_init() {
|
|
102
135
|
*np++ = 0;
|
103
136
|
set_class(odd, "Range");
|
104
137
|
odd->attr_cnt = 3;
|
105
|
-
|
106
|
-
odd_cnt = odd - odds + 1;
|
107
138
|
}
|
108
139
|
|
109
140
|
Odd oj_get_odd(VALUE clas) {
|
110
141
|
Odd odd;
|
111
142
|
const char *classname = NULL;
|
112
143
|
|
113
|
-
for (odd = odds
|
144
|
+
for (odd = odds; NULL != odd; odd = odd->next) {
|
114
145
|
if (clas == odd->clas) {
|
115
146
|
return odd;
|
116
147
|
}
|
@@ -129,21 +160,20 @@ Odd oj_get_odd(VALUE clas) {
|
|
129
160
|
Odd oj_get_oddc(const char *classname, size_t len) {
|
130
161
|
Odd odd;
|
131
162
|
|
132
|
-
for (odd = odds
|
163
|
+
for (odd = odds; NULL != odd; odd = odd->next) {
|
133
164
|
if (len == odd->clen && 0 == strncmp(classname, odd->classname, len)) {
|
134
165
|
return odd;
|
135
166
|
}
|
136
|
-
if (odd->is_module && 0 == strncmp(odd->classname, classname, odd->clen) &&
|
137
|
-
':' == classname[odd->clen]) {
|
167
|
+
if (odd->is_module && 0 == strncmp(odd->classname, classname, odd->clen) && ':' == classname[odd->clen]) {
|
138
168
|
return odd;
|
139
169
|
}
|
140
170
|
}
|
141
|
-
return
|
171
|
+
return NULL;
|
142
172
|
}
|
143
173
|
|
144
174
|
OddArgs oj_odd_alloc_args(Odd odd) {
|
145
175
|
OddArgs oa = ALLOC_N(struct _oddArgs, 1);
|
146
|
-
VALUE
|
176
|
+
VALUE *a;
|
147
177
|
int i;
|
148
178
|
|
149
179
|
oa->odd = odd;
|
@@ -159,11 +189,10 @@ void oj_odd_free(OddArgs args) {
|
|
159
189
|
|
160
190
|
int oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value) {
|
161
191
|
const char **np;
|
162
|
-
VALUE
|
192
|
+
VALUE *vp;
|
163
193
|
int i;
|
164
194
|
|
165
|
-
for (i = args->odd->attr_cnt, np = args->odd->attr_names, vp = args->args; 0 < i;
|
166
|
-
i--, np++, vp++) {
|
195
|
+
for (i = args->odd->attr_cnt, np = args->odd->attr_names, vp = args->args; 0 < i; i--, np++, vp++) {
|
167
196
|
if (0 == strncmp(key, *np, klen) && '\0' == *((*np) + klen)) {
|
168
197
|
*vp = value;
|
169
198
|
return 0;
|
@@ -172,37 +201,26 @@ int oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value) {
|
|
172
201
|
return -1;
|
173
202
|
}
|
174
203
|
|
175
|
-
void oj_reg_odd(VALUE
|
176
|
-
VALUE create_object,
|
177
|
-
VALUE create_method,
|
178
|
-
int mcnt,
|
179
|
-
VALUE *members,
|
180
|
-
bool raw) {
|
204
|
+
void oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt, VALUE *members, bool raw) {
|
181
205
|
Odd odd;
|
182
206
|
const char **np;
|
183
|
-
ID
|
207
|
+
ID *ap;
|
184
208
|
AttrGetFunc *fp;
|
185
209
|
|
186
|
-
|
187
|
-
odds = ALLOC_N(struct _odd, odd_cnt + 1);
|
188
|
-
|
189
|
-
memcpy(odds, _odds, sizeof(struct _odd) * odd_cnt);
|
190
|
-
} else {
|
191
|
-
REALLOC_N(odds, struct _odd, odd_cnt + 1);
|
192
|
-
}
|
193
|
-
odd = odds + odd_cnt;
|
210
|
+
odd = odd_create();
|
194
211
|
odd->clas = clas;
|
212
|
+
rb_gc_register_mark_object(odd->clas);
|
195
213
|
if (NULL == (odd->classname = strdup(rb_class2name(clas)))) {
|
196
|
-
rb_raise(rb_eNoMemError, "for
|
214
|
+
rb_raise(rb_eNoMemError, "for class name.");
|
197
215
|
}
|
198
216
|
odd->clen = strlen(odd->classname);
|
199
217
|
odd->create_obj = create_object;
|
200
|
-
odd->
|
201
|
-
odd->
|
202
|
-
odd->
|
203
|
-
odd->
|
204
|
-
|
205
|
-
|
218
|
+
rb_gc_register_mark_object(odd->create_obj);
|
219
|
+
odd->create_op = SYM2ID(create_method);
|
220
|
+
odd->attr_cnt = mcnt;
|
221
|
+
odd->is_module = (T_MODULE == rb_type(clas));
|
222
|
+
odd->raw = raw;
|
223
|
+
for (ap = odd->attrs, np = odd->attr_names, fp = odd->attrFuncs; 0 < mcnt; mcnt--, ap++, np++, members++, fp++) {
|
206
224
|
*fp = 0;
|
207
225
|
switch (rb_type(*members)) {
|
208
226
|
case T_STRING:
|
@@ -210,14 +228,16 @@ void oj_reg_odd(VALUE clas,
|
|
210
228
|
rb_raise(rb_eNoMemError, "for attribute name.");
|
211
229
|
}
|
212
230
|
break;
|
213
|
-
case T_SYMBOL:
|
214
|
-
|
215
|
-
|
231
|
+
case T_SYMBOL:
|
232
|
+
// The symbol can move and invalidate the name so make a copy.
|
233
|
+
if (NULL == (*np = strdup(rb_id2name(SYM2ID(*members))))) {
|
234
|
+
rb_raise(rb_eNoMemError, "for attribute name.");
|
235
|
+
}
|
216
236
|
break;
|
237
|
+
default: rb_raise(rb_eArgError, "registered member identifiers must be Strings or Symbols."); break;
|
217
238
|
}
|
218
239
|
*ap = rb_intern(*np);
|
219
240
|
}
|
220
241
|
*np = 0;
|
221
242
|
*ap = 0;
|
222
|
-
odd_cnt++;
|
223
243
|
}
|
data/ext/oj/odd.h
CHANGED
@@ -13,17 +13,18 @@
|
|
13
13
|
typedef VALUE (*AttrGetFunc)(VALUE obj);
|
14
14
|
|
15
15
|
typedef struct _odd {
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
VALUE
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
bool
|
24
|
-
|
25
|
-
|
26
|
-
|
16
|
+
struct _odd *next;
|
17
|
+
const char * classname;
|
18
|
+
size_t clen;
|
19
|
+
VALUE clas; // Ruby class or module
|
20
|
+
VALUE create_obj;
|
21
|
+
ID create_op;
|
22
|
+
int attr_cnt;
|
23
|
+
bool is_module;
|
24
|
+
bool raw;
|
25
|
+
const char * attr_names[MAX_ODD_ARGS]; // NULL terminated attr names
|
26
|
+
ID attrs[MAX_ODD_ARGS]; // 0 terminated attr IDs
|
27
|
+
AttrGetFunc attrFuncs[MAX_ODD_ARGS];
|
27
28
|
} * Odd;
|
28
29
|
|
29
30
|
typedef struct _oddArgs {
|
@@ -37,7 +38,6 @@ extern Odd oj_get_oddc(const char *classname, size_t len);
|
|
37
38
|
extern OddArgs oj_odd_alloc_args(Odd odd);
|
38
39
|
extern void oj_odd_free(OddArgs args);
|
39
40
|
extern int oj_odd_set_arg(OddArgs args, const char *key, size_t klen, VALUE value);
|
40
|
-
extern void
|
41
|
-
oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt, VALUE *members, bool raw);
|
41
|
+
extern void oj_reg_odd(VALUE clas, VALUE create_object, VALUE create_method, int mcnt, VALUE *members, bool raw);
|
42
42
|
|
43
43
|
#endif /* OJ_ODD_H */
|
data/ext/oj/oj.c
CHANGED
@@ -32,6 +32,7 @@ ID oj_array_append_id;
|
|
32
32
|
ID oj_array_end_id;
|
33
33
|
ID oj_array_start_id;
|
34
34
|
ID oj_as_json_id;
|
35
|
+
ID oj_at_id;
|
35
36
|
ID oj_begin_id;
|
36
37
|
ID oj_bigdecimal_id;
|
37
38
|
ID oj_end_id;
|
@@ -45,7 +46,6 @@ ID oj_hash_key_id;
|
|
45
46
|
ID oj_hash_set_id;
|
46
47
|
ID oj_hash_start_id;
|
47
48
|
ID oj_iconv_id;
|
48
|
-
ID oj_instance_variables_id;
|
49
49
|
ID oj_json_create_id;
|
50
50
|
ID oj_length_id;
|
51
51
|
ID oj_new_id;
|
@@ -90,7 +90,9 @@ VALUE oj_array_class_sym;
|
|
90
90
|
VALUE oj_create_additions_sym;
|
91
91
|
VALUE oj_decimal_class_sym;
|
92
92
|
VALUE oj_hash_class_sym;
|
93
|
+
VALUE oj_in_sym;
|
93
94
|
VALUE oj_indent_sym;
|
95
|
+
VALUE oj_nanosecond_sym;
|
94
96
|
VALUE oj_object_class_sym;
|
95
97
|
VALUE oj_quirks_mode_sym;
|
96
98
|
VALUE oj_safe_sym;
|
@@ -137,6 +139,7 @@ static VALUE rails_sym;
|
|
137
139
|
static VALUE raise_sym;
|
138
140
|
static VALUE ruby_sym;
|
139
141
|
static VALUE sec_prec_sym;
|
142
|
+
static VALUE slash_sym;
|
140
143
|
static VALUE strict_sym;
|
141
144
|
static VALUE symbol_keys_sym;
|
142
145
|
static VALUE time_format_sym;
|
@@ -153,6 +156,7 @@ static VALUE xmlschema_sym;
|
|
153
156
|
static VALUE xss_safe_sym;
|
154
157
|
|
155
158
|
rb_encoding *oj_utf8_encoding = 0;
|
159
|
+
int oj_utf8_encoding_index = 0;
|
156
160
|
|
157
161
|
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
158
162
|
pthread_mutex_t oj_cache_mutex;
|
@@ -239,7 +243,7 @@ struct _options oj_default_options = {
|
|
239
243
|
*references
|
240
244
|
* - *:auto_define* [_Boolean_|_nil_] automatically define classes if they do not exist
|
241
245
|
* - *:symbol_keys* [_Boolean_|_nil_] use symbols instead of strings for hash keys
|
242
|
-
* - *:escape_mode* [_:newline_|_:json_|_:xss_safe_|_:ascii_|
|
246
|
+
* - *:escape_mode* [_:newline_|_:json_|_:slash_|_:xss_safe_|_:ascii_|_:unicode_xss_|_nil_] determines the
|
243
247
|
*characters to escape
|
244
248
|
* - *:class_cache* [_Boolean_|_nil_] cache classes for faster parsing (if dynamically modifying
|
245
249
|
*classes or reloading classes then don't use this)
|
@@ -247,7 +251,7 @@ struct _options oj_default_options = {
|
|
247
251
|
*to use for JSON
|
248
252
|
* - *:time_format* [_:unix_|_:unix_zone_|_:xmlschema_|_:ruby_] time format when dumping
|
249
253
|
* - *:bigdecimal_as_decimal* [_Boolean_|_nil_] dump BigDecimal as a decimal number or as a String
|
250
|
-
* - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_|_:fast_] load decimals as BigDecimal instead
|
254
|
+
* - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_|_:fast_|_:ruby_] load decimals as BigDecimal instead
|
251
255
|
*of as a Float. :auto pick the most precise for the number of digits. :float should be the same as
|
252
256
|
*ruby. :fast may require rounding but is must faster.
|
253
257
|
* - *:compat_bigdecimal* [_true_|_false_] load decimals as BigDecimal instead of as a Float when in
|
@@ -404,6 +408,7 @@ static VALUE get_def_opts(VALUE self) {
|
|
404
408
|
switch (oj_default_options.escape_mode) {
|
405
409
|
case NLEsc: rb_hash_aset(opts, escape_mode_sym, newline_sym); break;
|
406
410
|
case JSONEsc: rb_hash_aset(opts, escape_mode_sym, json_sym); break;
|
411
|
+
case SlashEsc: rb_hash_aset(opts, escape_mode_sym, slash_sym); break;
|
407
412
|
case XSSEsc: rb_hash_aset(opts, escape_mode_sym, xss_safe_sym); break;
|
408
413
|
case ASCIIEsc: rb_hash_aset(opts, escape_mode_sym, ascii_sym); break;
|
409
414
|
case JXEsc: rb_hash_aset(opts, escape_mode_sym, unicode_xss_sym); break;
|
@@ -733,6 +738,8 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
|
|
733
738
|
copts->escape_mode = NLEsc;
|
734
739
|
} else if (json_sym == v) {
|
735
740
|
copts->escape_mode = JSONEsc;
|
741
|
+
} else if (slash_sym == v) {
|
742
|
+
copts->escape_mode = SlashEsc;
|
736
743
|
} else if (xss_safe_sym == v) {
|
737
744
|
copts->escape_mode = XSSEsc;
|
738
745
|
} else if (ascii_sym == v) {
|
@@ -925,7 +932,7 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
|
|
925
932
|
if (Qnil == v) {
|
926
933
|
return ST_CONTINUE;
|
927
934
|
}
|
928
|
-
if (
|
935
|
+
if (rb_obj_class(v) == rb_cRange) {
|
929
936
|
VALUE min = rb_funcall(v, oj_begin_id, 0);
|
930
937
|
VALUE max = rb_funcall(v, oj_end_id, 0);
|
931
938
|
|
@@ -1147,7 +1154,17 @@ static VALUE load_file(int argc, VALUE *argv, VALUE self) {
|
|
1147
1154
|
}
|
1148
1155
|
}
|
1149
1156
|
path = StringValuePtr(*argv);
|
1150
|
-
|
1157
|
+
#ifdef _WIN32
|
1158
|
+
{
|
1159
|
+
WCHAR *wide_path;
|
1160
|
+
wide_path = rb_w32_mbstr_to_wstr(CP_UTF8, path, -1, NULL);
|
1161
|
+
fd = rb_w32_wopen(wide_path, O_RDONLY);
|
1162
|
+
free(wide_path);
|
1163
|
+
}
|
1164
|
+
#else
|
1165
|
+
fd = open(path, O_RDONLY);
|
1166
|
+
#endif
|
1167
|
+
if (0 == fd) {
|
1151
1168
|
rb_raise(rb_eIOError, "%s", strerror(errno));
|
1152
1169
|
}
|
1153
1170
|
switch (mode) {
|
@@ -1243,9 +1260,8 @@ static VALUE dump_body(VALUE a) {
|
|
1243
1260
|
static VALUE dump_ensure(VALUE a) {
|
1244
1261
|
volatile struct dump_arg *arg = (void *)a;
|
1245
1262
|
|
1246
|
-
|
1247
|
-
|
1248
|
-
}
|
1263
|
+
oj_out_free(arg->out);
|
1264
|
+
|
1249
1265
|
return Qnil;
|
1250
1266
|
}
|
1251
1267
|
|
@@ -1257,7 +1273,6 @@ static VALUE dump_ensure(VALUE a) {
|
|
1257
1273
|
* - *options* [_Hash_] same as default_options
|
1258
1274
|
*/
|
1259
1275
|
static VALUE dump(int argc, VALUE *argv, VALUE self) {
|
1260
|
-
char buf[4096];
|
1261
1276
|
struct dump_arg arg;
|
1262
1277
|
struct _out out;
|
1263
1278
|
struct _options copts = oj_default_options;
|
@@ -1279,9 +1294,8 @@ static VALUE dump(int argc, VALUE *argv, VALUE self) {
|
|
1279
1294
|
arg.argc = argc;
|
1280
1295
|
arg.argv = argv;
|
1281
1296
|
|
1282
|
-
arg.out
|
1283
|
-
|
1284
|
-
arg.out->allocated = false;
|
1297
|
+
oj_out_init(arg.out);
|
1298
|
+
|
1285
1299
|
arg.out->omit_nil = copts.dump_opts.omit_nil;
|
1286
1300
|
arg.out->caller = CALLER_DUMP;
|
1287
1301
|
|
@@ -1313,7 +1327,6 @@ static VALUE dump(int argc, VALUE *argv, VALUE self) {
|
|
1313
1327
|
* Returns [_String_] the encoded JSON.
|
1314
1328
|
*/
|
1315
1329
|
static VALUE to_json(int argc, VALUE *argv, VALUE self) {
|
1316
|
-
char buf[4096];
|
1317
1330
|
struct _out out;
|
1318
1331
|
struct _options copts = oj_default_options;
|
1319
1332
|
VALUE rstr;
|
@@ -1328,9 +1341,9 @@ static VALUE to_json(int argc, VALUE *argv, VALUE self) {
|
|
1328
1341
|
}
|
1329
1342
|
copts.mode = CompatMode;
|
1330
1343
|
copts.to_json = Yes;
|
1331
|
-
|
1332
|
-
out
|
1333
|
-
|
1344
|
+
|
1345
|
+
oj_out_init(&out);
|
1346
|
+
|
1334
1347
|
out.omit_nil = copts.dump_opts.omit_nil;
|
1335
1348
|
// For obj.to_json or generate nan is not allowed but if called from dump
|
1336
1349
|
// it is.
|
@@ -1341,9 +1354,9 @@ static VALUE to_json(int argc, VALUE *argv, VALUE self) {
|
|
1341
1354
|
}
|
1342
1355
|
rstr = rb_str_new2(out.buf);
|
1343
1356
|
rstr = oj_encode(rstr);
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1357
|
+
|
1358
|
+
oj_out_free(&out);
|
1359
|
+
|
1347
1360
|
return rstr;
|
1348
1361
|
}
|
1349
1362
|
|
@@ -1703,6 +1716,15 @@ static VALUE protect_require(VALUE x) {
|
|
1703
1716
|
return Qnil;
|
1704
1717
|
}
|
1705
1718
|
|
1719
|
+
extern void print_all_odds(const char *label);
|
1720
|
+
|
1721
|
+
static VALUE
|
1722
|
+
debug_odd(VALUE self, VALUE label) {
|
1723
|
+
print_all_odds(RSTRING_PTR(label));
|
1724
|
+
return Qnil;
|
1725
|
+
}
|
1726
|
+
|
1727
|
+
|
1706
1728
|
/* Document-module: Oj
|
1707
1729
|
*
|
1708
1730
|
* Optimized JSON (Oj), as the name implies was written to provide speed
|
@@ -1731,15 +1753,19 @@ static VALUE protect_require(VALUE x) {
|
|
1731
1753
|
*
|
1732
1754
|
* - *:wab* specifically for WAB data exchange.
|
1733
1755
|
*/
|
1734
|
-
void Init_oj() {
|
1756
|
+
void Init_oj(void) {
|
1735
1757
|
int err = 0;
|
1736
1758
|
|
1737
1759
|
#if HAVE_RB_EXT_RACTOR_SAFE
|
1738
1760
|
rb_ext_ractor_safe(true);
|
1739
1761
|
#endif
|
1740
1762
|
Oj = rb_define_module("Oj");
|
1763
|
+
rb_gc_register_address(&Oj);
|
1741
1764
|
|
1742
1765
|
oj_cstack_class = rb_define_class_under(Oj, "CStack", rb_cObject);
|
1766
|
+
rb_gc_register_address(&oj_cstack_class);
|
1767
|
+
|
1768
|
+
rb_undef_alloc_func(oj_cstack_class);
|
1743
1769
|
|
1744
1770
|
oj_string_writer_init();
|
1745
1771
|
oj_stream_writer_init();
|
@@ -1748,9 +1774,11 @@ void Init_oj() {
|
|
1748
1774
|
// On Rubinius the require fails but can be done from a ruby file.
|
1749
1775
|
rb_protect(protect_require, Qnil, &err);
|
1750
1776
|
rb_require("stringio");
|
1751
|
-
|
1777
|
+
oj_utf8_encoding_index = rb_enc_find_index("UTF-8");
|
1778
|
+
oj_utf8_encoding = rb_enc_from_index(oj_utf8_encoding_index);
|
1752
1779
|
|
1753
1780
|
// rb_define_module_function(Oj, "hash_test", hash_test, 0);
|
1781
|
+
rb_define_module_function(Oj, "debug_odd", debug_odd, 1);
|
1754
1782
|
|
1755
1783
|
rb_define_module_function(Oj, "default_options", get_def_opts, 0);
|
1756
1784
|
rb_define_module_function(Oj, "default_options=", set_def_opts, 1);
|
@@ -1789,6 +1817,7 @@ void Init_oj() {
|
|
1789
1817
|
oj_array_end_id = rb_intern("array_end");
|
1790
1818
|
oj_array_start_id = rb_intern("array_start");
|
1791
1819
|
oj_as_json_id = rb_intern("as_json");
|
1820
|
+
oj_at_id = rb_intern("at");
|
1792
1821
|
oj_begin_id = rb_intern("begin");
|
1793
1822
|
oj_bigdecimal_id = rb_intern("BigDecimal");
|
1794
1823
|
oj_end_id = rb_intern("end");
|
@@ -1802,7 +1831,6 @@ void Init_oj() {
|
|
1802
1831
|
oj_hash_set_id = rb_intern("hash_set");
|
1803
1832
|
oj_hash_start_id = rb_intern("hash_start");
|
1804
1833
|
oj_iconv_id = rb_intern("iconv");
|
1805
|
-
oj_instance_variables_id = rb_intern("instance_variables");
|
1806
1834
|
oj_json_create_id = rb_intern("json_create");
|
1807
1835
|
oj_length_id = rb_intern("length");
|
1808
1836
|
oj_new_id = rb_intern("new");
|
@@ -1937,10 +1965,14 @@ void Init_oj() {
|
|
1937
1965
|
rb_gc_register_address(&oj_decimal_class_sym);
|
1938
1966
|
oj_hash_class_sym = ID2SYM(rb_intern("hash_class"));
|
1939
1967
|
rb_gc_register_address(&oj_hash_class_sym);
|
1968
|
+
oj_in_sym = ID2SYM(rb_intern("in"));
|
1969
|
+
rb_gc_register_address(&oj_in_sym);
|
1940
1970
|
oj_indent_sym = ID2SYM(rb_intern("indent"));
|
1941
1971
|
rb_gc_register_address(&oj_indent_sym);
|
1942
1972
|
oj_max_nesting_sym = ID2SYM(rb_intern("max_nesting"));
|
1943
1973
|
rb_gc_register_address(&oj_max_nesting_sym);
|
1974
|
+
oj_nanosecond_sym = ID2SYM(rb_intern("nanosecond"));
|
1975
|
+
rb_gc_register_address(&oj_nanosecond_sym);
|
1944
1976
|
oj_object_class_sym = ID2SYM(rb_intern("object_class"));
|
1945
1977
|
rb_gc_register_address(&oj_object_class_sym);
|
1946
1978
|
oj_object_nl_sym = ID2SYM(rb_intern("object_nl"));
|
@@ -1965,6 +1997,8 @@ void Init_oj() {
|
|
1965
1997
|
rb_gc_register_address(&ruby_sym);
|
1966
1998
|
sec_prec_sym = ID2SYM(rb_intern("second_precision"));
|
1967
1999
|
rb_gc_register_address(&sec_prec_sym);
|
2000
|
+
slash_sym = ID2SYM(rb_intern("slash"));
|
2001
|
+
rb_gc_register_address(&slash_sym);
|
1968
2002
|
strict_sym = ID2SYM(rb_intern("strict"));
|
1969
2003
|
rb_gc_register_address(&strict_sym);
|
1970
2004
|
symbol_keys_sym = ID2SYM(rb_intern("symbol_keys"));
|
@@ -2017,4 +2051,5 @@ void Init_oj() {
|
|
2017
2051
|
oj_init_doc();
|
2018
2052
|
|
2019
2053
|
oj_parser_init();
|
2054
|
+
oj_scanner_init();
|
2020
2055
|
}
|
data/ext/oj/oj.h
CHANGED
@@ -39,6 +39,16 @@ enum st_retval { ST_CONTINUE = 0, ST_STOP = 1, ST_DELETE = 2, ST_CHECK };
|
|
39
39
|
#define NINF_VAL "-3.0e14159265358979323846"
|
40
40
|
#define NAN_VAL "3.3e14159265358979323846"
|
41
41
|
|
42
|
+
#if __STDC_VERSION__ >= 199901L
|
43
|
+
// To avoid using ruby_snprintf with C99.
|
44
|
+
#undef snprintf
|
45
|
+
#include <stdio.h>
|
46
|
+
#endif
|
47
|
+
|
48
|
+
// To avoid using ruby_nonempty_memcpy().
|
49
|
+
#undef memcpy
|
50
|
+
#include <string.h>
|
51
|
+
|
42
52
|
typedef enum { Yes = 'y', No = 'n', NotSet = 0 } YesNo;
|
43
53
|
|
44
54
|
typedef enum {
|
@@ -56,6 +66,7 @@ typedef enum { UnixTime = 'u', UnixZTime = 'z', XmlTime = 'x', RubyTime = 'r' }
|
|
56
66
|
typedef enum {
|
57
67
|
NLEsc = 'n',
|
58
68
|
JSONEsc = 'j',
|
69
|
+
SlashEsc = 's',
|
59
70
|
XSSEsc = 'x',
|
60
71
|
ASCIIEsc = 'a',
|
61
72
|
JXEsc = 'g', // json gem
|
@@ -176,6 +187,7 @@ typedef struct _rOptTable {
|
|
176
187
|
} * ROptTable;
|
177
188
|
|
178
189
|
typedef struct _out {
|
190
|
+
char stack_buffer[4096];
|
179
191
|
char * buf;
|
180
192
|
char * end;
|
181
193
|
char * cur;
|
@@ -265,8 +277,8 @@ extern void oj_str_writer_pop(StrWriter sw);
|
|
265
277
|
extern void oj_str_writer_pop_all(StrWriter sw);
|
266
278
|
|
267
279
|
extern void oj_init_doc(void);
|
268
|
-
extern void oj_string_writer_init();
|
269
|
-
extern void oj_stream_writer_init();
|
280
|
+
extern void oj_string_writer_init(void);
|
281
|
+
extern void oj_stream_writer_init(void);
|
270
282
|
extern void oj_str_writer_init(StrWriter sw, int buf_size);
|
271
283
|
extern VALUE oj_define_mimic_json(int argc, VALUE *argv, VALUE self);
|
272
284
|
extern VALUE oj_mimic_generate(int argc, VALUE *argv, VALUE self);
|
@@ -282,6 +294,7 @@ extern VALUE oj_rails_encode(int argc, VALUE *argv, VALUE self);
|
|
282
294
|
extern VALUE Oj;
|
283
295
|
extern struct _options oj_default_options;
|
284
296
|
extern rb_encoding * oj_utf8_encoding;
|
297
|
+
extern int oj_utf8_encoding_index;
|
285
298
|
|
286
299
|
extern VALUE oj_bag_class;
|
287
300
|
extern VALUE oj_bigdecimal_class;
|
@@ -304,7 +317,9 @@ extern VALUE oj_ascii_only_sym;
|
|
304
317
|
extern VALUE oj_create_additions_sym;
|
305
318
|
extern VALUE oj_decimal_class_sym;
|
306
319
|
extern VALUE oj_hash_class_sym;
|
320
|
+
extern VALUE oj_in_sym;
|
307
321
|
extern VALUE oj_indent_sym;
|
322
|
+
extern VALUE oj_nanosecond_sym;
|
308
323
|
extern VALUE oj_max_nesting_sym;
|
309
324
|
extern VALUE oj_object_class_sym;
|
310
325
|
extern VALUE oj_object_nl_sym;
|
@@ -321,6 +336,7 @@ extern ID oj_array_append_id;
|
|
321
336
|
extern ID oj_array_end_id;
|
322
337
|
extern ID oj_array_start_id;
|
323
338
|
extern ID oj_as_json_id;
|
339
|
+
extern ID oj_at_id;
|
324
340
|
extern ID oj_begin_id;
|
325
341
|
extern ID oj_bigdecimal_id;
|
326
342
|
extern ID oj_end_id;
|
@@ -334,7 +350,6 @@ extern ID oj_hash_key_id;
|
|
334
350
|
extern ID oj_hash_set_id;
|
335
351
|
extern ID oj_hash_start_id;
|
336
352
|
extern ID oj_iconv_id;
|
337
|
-
extern ID oj_instance_variables_id;
|
338
353
|
extern ID oj_json_create_id;
|
339
354
|
extern ID oj_length_id;
|
340
355
|
extern ID oj_new_id;
|
@@ -364,6 +379,12 @@ extern bool oj_use_hash_alt;
|
|
364
379
|
extern bool oj_use_array_alt;
|
365
380
|
extern bool string_writer_optimized;
|
366
381
|
|
382
|
+
#define APPEND_CHARS(buffer, chars, size) \
|
383
|
+
{ \
|
384
|
+
memcpy(buffer, chars, size); \
|
385
|
+
buffer += size; \
|
386
|
+
}
|
387
|
+
|
367
388
|
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
368
389
|
extern pthread_mutex_t oj_cache_mutex;
|
369
390
|
#else
|