oj 3.13.11 → 3.13.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +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
|