oj 3.7.4 → 3.13.21
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 +1352 -0
- data/README.md +29 -8
- data/RELEASE_NOTES.md +61 -0
- data/ext/oj/buf.h +53 -72
- data/ext/oj/cache.c +326 -0
- data/ext/oj/cache.h +21 -0
- data/ext/oj/cache8.c +61 -64
- data/ext/oj/cache8.h +12 -39
- data/ext/oj/circarray.c +37 -43
- data/ext/oj/circarray.h +16 -17
- data/ext/oj/code.c +165 -179
- data/ext/oj/code.h +27 -29
- data/ext/oj/compat.c +174 -194
- data/ext/oj/custom.c +809 -866
- data/ext/oj/debug.c +132 -0
- data/ext/oj/dump.c +848 -863
- data/ext/oj/dump.h +81 -67
- data/ext/oj/dump_compat.c +85 -123
- data/ext/oj/dump_leaf.c +100 -188
- data/ext/oj/dump_object.c +527 -656
- data/ext/oj/dump_strict.c +315 -338
- data/ext/oj/encode.h +7 -34
- data/ext/oj/encoder.c +43 -0
- data/ext/oj/err.c +40 -29
- data/ext/oj/err.h +48 -48
- data/ext/oj/extconf.rb +17 -4
- data/ext/oj/fast.c +1070 -1087
- data/ext/oj/intern.c +301 -0
- data/ext/oj/intern.h +26 -0
- data/ext/oj/mimic_json.c +469 -436
- data/ext/oj/object.c +525 -593
- data/ext/oj/odd.c +154 -138
- data/ext/oj/odd.h +37 -38
- data/ext/oj/oj.c +1325 -986
- data/ext/oj/oj.h +333 -316
- data/ext/oj/parse.c +1002 -846
- data/ext/oj/parse.h +92 -87
- data/ext/oj/parser.c +1557 -0
- data/ext/oj/parser.h +91 -0
- data/ext/oj/rails.c +888 -878
- data/ext/oj/rails.h +11 -14
- data/ext/oj/reader.c +141 -147
- data/ext/oj/reader.h +73 -89
- data/ext/oj/resolve.c +41 -62
- data/ext/oj/resolve.h +7 -9
- data/ext/oj/rxclass.c +71 -75
- data/ext/oj/rxclass.h +18 -19
- data/ext/oj/saj.c +443 -486
- data/ext/oj/saj2.c +602 -0
- data/ext/oj/scp.c +88 -113
- data/ext/oj/sparse.c +787 -709
- data/ext/oj/stream_writer.c +133 -159
- data/ext/oj/strict.c +127 -118
- data/ext/oj/string_writer.c +230 -249
- data/ext/oj/trace.c +34 -41
- data/ext/oj/trace.h +19 -19
- data/ext/oj/usual.c +1254 -0
- data/ext/oj/util.c +136 -0
- data/ext/oj/util.h +20 -0
- data/ext/oj/val_stack.c +59 -67
- data/ext/oj/val_stack.h +91 -129
- data/ext/oj/validate.c +46 -0
- data/ext/oj/wab.c +342 -353
- data/lib/oj/bag.rb +1 -0
- data/lib/oj/easy_hash.rb +5 -4
- data/lib/oj/error.rb +1 -1
- data/lib/oj/json.rb +1 -1
- data/lib/oj/mimic.rb +48 -14
- data/lib/oj/saj.rb +20 -6
- data/lib/oj/state.rb +8 -7
- data/lib/oj/version.rb +2 -2
- data/lib/oj.rb +0 -8
- data/pages/Compatibility.md +1 -1
- data/pages/JsonGem.md +15 -0
- data/pages/Modes.md +53 -46
- data/pages/Options.md +72 -11
- data/pages/Parser.md +309 -0
- data/pages/Rails.md +73 -22
- data/pages/Security.md +1 -1
- data/test/activerecord/result_test.rb +7 -2
- data/test/activesupport5/abstract_unit.rb +45 -0
- data/test/activesupport5/decoding_test.rb +68 -60
- data/test/activesupport5/encoding_test.rb +111 -96
- data/test/activesupport5/encoding_test_cases.rb +33 -25
- data/test/activesupport5/test_helper.rb +43 -21
- data/test/activesupport5/time_zone_test_helpers.rb +18 -3
- data/test/activesupport6/abstract_unit.rb +44 -0
- data/test/activesupport6/decoding_test.rb +133 -0
- data/test/activesupport6/encoding_test.rb +507 -0
- data/test/activesupport6/encoding_test_cases.rb +98 -0
- data/test/activesupport6/test_common.rb +17 -0
- data/test/activesupport6/test_helper.rb +163 -0
- data/test/activesupport6/time_zone_test_helpers.rb +39 -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 +6 -12
- data/test/baz.rb +16 -0
- data/test/bug.rb +16 -0
- data/test/foo.rb +69 -75
- data/test/helper.rb +16 -0
- data/test/json_gem/json_common_interface_test.rb +8 -3
- data/test/json_gem/json_generator_test.rb +18 -4
- data/test/json_gem/json_parser_test.rb +9 -0
- data/test/json_gem/test_helper.rb +12 -0
- data/test/mem.rb +33 -0
- data/test/perf.rb +1 -1
- data/test/perf_dump.rb +50 -0
- data/test/perf_once.rb +58 -0
- data/test/perf_parser.rb +189 -0
- data/test/perf_scp.rb +11 -10
- data/test/perf_strict.rb +17 -23
- data/test/prec.rb +23 -0
- data/test/sample_json.rb +1 -1
- data/test/test_compat.rb +46 -10
- data/test/test_custom.rb +147 -8
- data/test/test_fast.rb +62 -2
- data/test/test_file.rb +25 -2
- data/test/test_gc.rb +13 -0
- data/test/test_generate.rb +21 -0
- data/test/test_hash.rb +11 -1
- data/test/test_integer_range.rb +7 -2
- data/test/test_object.rb +85 -9
- data/test/test_parser.rb +27 -0
- data/test/test_parser_saj.rb +335 -0
- data/test/test_parser_usual.rb +217 -0
- data/test/test_rails.rb +35 -0
- data/test/test_saj.rb +1 -1
- data/test/test_scp.rb +5 -5
- data/test/test_strict.rb +26 -1
- data/test/test_various.rb +87 -65
- data/test/test_wab.rb +2 -0
- data/test/test_writer.rb +19 -2
- data/test/tests.rb +1 -1
- data/test/zoo.rb +13 -0
- metadata +60 -110
- data/ext/oj/hash.c +0 -163
- data/ext/oj/hash.h +0 -46
- data/ext/oj/hash_test.c +0 -512
data/ext/oj/wab.c
CHANGED
@@ -1,25 +1,25 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
* All rights reserved.
|
4
|
-
*/
|
1
|
+
// Copyright (c) 2012 Peter Ohler. All rights reserved.
|
2
|
+
// Licensed under the MIT License. See LICENSE file in the project root for license details.
|
5
3
|
|
6
|
-
#include <stdlib.h>
|
7
4
|
#include <stdio.h>
|
5
|
+
#include <stdlib.h>
|
8
6
|
#include <string.h>
|
9
7
|
#include <time.h>
|
10
8
|
#include <unistd.h>
|
11
9
|
|
12
|
-
#include "
|
10
|
+
#include "dump.h"
|
11
|
+
#include "encode.h"
|
13
12
|
#include "err.h"
|
13
|
+
#include "intern.h"
|
14
|
+
#include "oj.h"
|
14
15
|
#include "parse.h"
|
15
|
-
#include "encode.h"
|
16
|
-
#include "dump.h"
|
17
16
|
#include "trace.h"
|
17
|
+
#include "util.h"
|
18
18
|
|
19
19
|
// Workaround in case INFINITY is not defined in math.h or if the OS is CentOS
|
20
|
-
#define OJ_INFINITY (1.0/0.0)
|
20
|
+
#define OJ_INFINITY (1.0 / 0.0)
|
21
21
|
|
22
|
-
static char
|
22
|
+
static char hex_chars[256] = "\
|
23
23
|
................................\
|
24
24
|
................xxxxxxxxxx......\
|
25
25
|
.xxxxxx.........................\
|
@@ -29,131 +29,128 @@ static char hex_chars[256] = "\
|
|
29
29
|
................................\
|
30
30
|
................................";
|
31
31
|
|
32
|
-
static VALUE
|
33
|
-
static VALUE
|
34
|
-
static VALUE
|
32
|
+
static VALUE wab_uuid_clas = Qundef;
|
33
|
+
static VALUE uri_clas = Qundef;
|
34
|
+
static VALUE uri_http_clas = Qundef;
|
35
35
|
|
36
36
|
///// dump functions /////
|
37
37
|
|
38
|
-
static VALUE
|
39
|
-
resolve_wab_uuid_class() {
|
38
|
+
static VALUE resolve_wab_uuid_class(void) {
|
40
39
|
if (Qundef == wab_uuid_clas) {
|
41
|
-
|
40
|
+
volatile VALUE wab_module;
|
42
41
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
42
|
+
wab_uuid_clas = Qnil;
|
43
|
+
if (rb_const_defined_at(rb_cObject, rb_intern("WAB"))) {
|
44
|
+
wab_module = rb_const_get_at(rb_cObject, rb_intern("WAB"));
|
45
|
+
if (rb_const_defined_at(wab_module, rb_intern("UUID"))) {
|
46
|
+
wab_uuid_clas = rb_const_get(wab_module, rb_intern("UUID"));
|
47
|
+
}
|
48
|
+
}
|
50
49
|
}
|
51
50
|
return wab_uuid_clas;
|
52
51
|
}
|
53
52
|
|
54
|
-
static VALUE
|
55
|
-
resolve_uri_class() {
|
53
|
+
static VALUE resolve_uri_class(void) {
|
56
54
|
if (Qundef == uri_clas) {
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
}
|
55
|
+
uri_clas = Qnil;
|
56
|
+
if (rb_const_defined_at(rb_cObject, rb_intern("URI"))) {
|
57
|
+
uri_clas = rb_const_get_at(rb_cObject, rb_intern("URI"));
|
58
|
+
}
|
62
59
|
}
|
63
60
|
return uri_clas;
|
64
61
|
}
|
65
62
|
|
66
|
-
static VALUE
|
67
|
-
resolve_uri_http_class() {
|
63
|
+
static VALUE resolve_uri_http_class(void) {
|
68
64
|
if (Qundef == uri_http_clas) {
|
69
|
-
|
65
|
+
volatile VALUE uri_module;
|
70
66
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
67
|
+
uri_http_clas = Qnil;
|
68
|
+
if (rb_const_defined_at(rb_cObject, rb_intern("URI"))) {
|
69
|
+
uri_module = rb_const_get_at(rb_cObject, rb_intern("URI"));
|
70
|
+
if (rb_const_defined_at(uri_module, rb_intern("HTTP"))) {
|
71
|
+
uri_http_clas = rb_const_get(uri_module, rb_intern("HTTP"));
|
72
|
+
}
|
73
|
+
}
|
78
74
|
}
|
79
75
|
return uri_http_clas;
|
80
76
|
}
|
81
77
|
|
82
|
-
static void
|
83
|
-
|
84
|
-
|
78
|
+
static void raise_wab(VALUE obj) {
|
79
|
+
rb_raise(rb_eTypeError,
|
80
|
+
"Failed to dump %s Object to JSON in wab mode.\n",
|
81
|
+
rb_class2name(rb_obj_class(obj)));
|
85
82
|
}
|
86
83
|
|
87
84
|
// Removed dependencies on math due to problems with CentOS 5.4.
|
88
|
-
static void
|
89
|
-
|
90
|
-
char
|
91
|
-
|
92
|
-
|
93
|
-
int cnt = 0;
|
85
|
+
static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
86
|
+
char buf[64];
|
87
|
+
char * b;
|
88
|
+
double d = rb_num2dbl(obj);
|
89
|
+
int cnt = 0;
|
94
90
|
|
95
91
|
if (0.0 == d) {
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
92
|
+
b = buf;
|
93
|
+
*b++ = '0';
|
94
|
+
*b++ = '.';
|
95
|
+
*b++ = '0';
|
96
|
+
*b++ = '\0';
|
97
|
+
cnt = 3;
|
102
98
|
} else {
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
99
|
+
if (OJ_INFINITY == d || -OJ_INFINITY == d || isnan(d)) {
|
100
|
+
raise_wab(obj);
|
101
|
+
} else if (d == (double)(long long int)d) {
|
102
|
+
cnt = snprintf(buf, sizeof(buf), "%.1f", d);
|
103
|
+
} else {
|
104
|
+
cnt = snprintf(buf, sizeof(buf), "%0.16g", d);
|
105
|
+
}
|
110
106
|
}
|
111
107
|
assure_size(out, cnt);
|
112
108
|
for (b = buf; '\0' != *b; b++) {
|
113
|
-
|
109
|
+
*out->cur++ = *b;
|
114
110
|
}
|
115
111
|
*out->cur = '\0';
|
116
112
|
}
|
117
113
|
|
118
|
-
static void
|
119
|
-
|
120
|
-
|
121
|
-
int
|
122
|
-
int d2 = depth + 1;
|
114
|
+
static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
|
115
|
+
size_t size;
|
116
|
+
int i, cnt;
|
117
|
+
int d2 = depth + 1;
|
123
118
|
|
124
|
-
cnt
|
119
|
+
cnt = (int)RARRAY_LEN(a);
|
125
120
|
*out->cur++ = '[';
|
126
|
-
size
|
121
|
+
size = 2;
|
127
122
|
assure_size(out, size);
|
128
123
|
if (0 == cnt) {
|
129
|
-
|
124
|
+
*out->cur++ = ']';
|
130
125
|
} else {
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
126
|
+
size = d2 * out->indent + 2;
|
127
|
+
assure_size(out, size * cnt);
|
128
|
+
cnt--;
|
129
|
+
for (i = 0; i <= cnt; i++) {
|
130
|
+
fill_indent(out, d2);
|
131
|
+
oj_dump_wab_val(RARRAY_AREF(a, i), d2, out);
|
132
|
+
if (i < cnt) {
|
133
|
+
*out->cur++ = ',';
|
134
|
+
}
|
135
|
+
}
|
136
|
+
size = depth * out->indent + 1;
|
137
|
+
assure_size(out, size);
|
138
|
+
fill_indent(out, depth);
|
139
|
+
*out->cur++ = ']';
|
145
140
|
}
|
146
141
|
*out->cur = '\0';
|
147
142
|
}
|
148
143
|
|
149
|
-
static int
|
150
|
-
|
151
|
-
int
|
152
|
-
long
|
153
|
-
int
|
154
|
-
|
144
|
+
static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
145
|
+
Out out = (Out)ov;
|
146
|
+
int depth = out->depth;
|
147
|
+
long size;
|
148
|
+
int rtype = rb_type(key);
|
149
|
+
|
155
150
|
if (rtype != T_SYMBOL) {
|
156
|
-
|
151
|
+
rb_raise(rb_eTypeError,
|
152
|
+
"In :wab mode all Hash keys must be Symbols, not %s.\n",
|
153
|
+
rb_class2name(rb_obj_class(key)));
|
157
154
|
}
|
158
155
|
size = depth * out->indent + 1;
|
159
156
|
assure_size(out, size);
|
@@ -161,265 +158,282 @@ hash_cb(VALUE key, VALUE value, Out out) {
|
|
161
158
|
oj_dump_sym(key, 0, out, false);
|
162
159
|
*out->cur++ = ':';
|
163
160
|
oj_dump_wab_val(value, depth, out);
|
164
|
-
out->depth
|
161
|
+
out->depth = depth;
|
165
162
|
*out->cur++ = ',';
|
166
163
|
|
167
164
|
return ST_CONTINUE;
|
168
165
|
}
|
169
166
|
|
170
|
-
static void
|
171
|
-
|
172
|
-
|
173
|
-
size_t size;
|
167
|
+
static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
|
168
|
+
int cnt;
|
169
|
+
size_t size;
|
174
170
|
|
175
|
-
cnt
|
171
|
+
cnt = (int)RHASH_SIZE(obj);
|
176
172
|
size = depth * out->indent + 2;
|
177
173
|
assure_size(out, 2);
|
178
174
|
*out->cur++ = '{';
|
179
175
|
if (0 == cnt) {
|
180
|
-
|
176
|
+
*out->cur++ = '}';
|
181
177
|
} else {
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
178
|
+
out->depth = depth + 1;
|
179
|
+
rb_hash_foreach(obj, hash_cb, (VALUE)out);
|
180
|
+
if (',' == *(out->cur - 1)) {
|
181
|
+
out->cur--; // backup to overwrite last comma
|
182
|
+
}
|
183
|
+
assure_size(out, size);
|
184
|
+
fill_indent(out, depth);
|
185
|
+
*out->cur++ = '}';
|
190
186
|
}
|
191
187
|
*out->cur = '\0';
|
192
188
|
}
|
193
189
|
|
194
|
-
static void
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
long long nsec;
|
190
|
+
static void dump_time(VALUE obj, Out out) {
|
191
|
+
char buf[64];
|
192
|
+
struct _timeInfo ti;
|
193
|
+
int len;
|
194
|
+
time_t sec;
|
195
|
+
long long nsec;
|
201
196
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
197
|
+
if (16 <= sizeof(struct timespec)) {
|
198
|
+
struct timespec ts = rb_time_timespec(obj);
|
199
|
+
|
200
|
+
sec = ts.tv_sec;
|
201
|
+
nsec = ts.tv_nsec;
|
202
|
+
} else {
|
203
|
+
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
204
|
+
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
207
205
|
}
|
208
|
-
#else
|
209
|
-
sec = rb_num2ll(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
210
|
-
nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
211
|
-
#endif
|
212
206
|
|
213
207
|
assure_size(out, 36);
|
214
208
|
// 2012-01-05T23:58:07.123456000Z
|
215
|
-
|
216
|
-
|
217
|
-
len = sprintf(buf,
|
218
|
-
|
219
|
-
|
209
|
+
sec_as_time(sec, &ti);
|
210
|
+
|
211
|
+
len = sprintf(buf,
|
212
|
+
"%04d-%02d-%02dT%02d:%02d:%02d.%09ldZ",
|
213
|
+
ti.year,
|
214
|
+
ti.mon,
|
215
|
+
ti.day,
|
216
|
+
ti.hour,
|
217
|
+
ti.min,
|
218
|
+
ti.sec,
|
219
|
+
(long)nsec);
|
220
220
|
oj_dump_cstr(buf, len, 0, 0, out);
|
221
221
|
}
|
222
222
|
|
223
|
-
static void
|
224
|
-
|
225
|
-
volatile VALUE clas = rb_obj_class(obj);
|
223
|
+
static void dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
|
224
|
+
volatile VALUE clas = rb_obj_class(obj);
|
226
225
|
|
227
226
|
if (rb_cTime == clas) {
|
228
|
-
|
227
|
+
dump_time(obj, out);
|
229
228
|
} else if (oj_bigdecimal_class == clas) {
|
230
|
-
|
229
|
+
volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
|
231
230
|
|
232
|
-
|
231
|
+
oj_dump_raw(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), out);
|
233
232
|
} else if (resolve_wab_uuid_class() == clas) {
|
234
|
-
|
233
|
+
oj_dump_str(rb_funcall(obj, oj_to_s_id, 0), depth, out, false);
|
235
234
|
} else if (resolve_uri_http_class() == clas) {
|
236
|
-
|
235
|
+
oj_dump_str(rb_funcall(obj, oj_to_s_id, 0), depth, out, false);
|
237
236
|
} else {
|
238
|
-
|
239
|
-
}
|
240
|
-
}
|
241
|
-
|
242
|
-
static DumpFunc
|
243
|
-
NULL,
|
244
|
-
dump_obj,
|
245
|
-
NULL,
|
246
|
-
NULL,
|
247
|
-
dump_float,
|
248
|
-
oj_dump_str,
|
249
|
-
NULL,
|
250
|
-
dump_array,
|
251
|
-
dump_hash,
|
252
|
-
NULL,
|
253
|
-
oj_dump_bignum,
|
254
|
-
NULL,
|
255
|
-
dump_obj,
|
256
|
-
NULL,
|
257
|
-
NULL,
|
258
|
-
NULL,
|
259
|
-
NULL,
|
260
|
-
oj_dump_nil,
|
261
|
-
oj_dump_true,
|
262
|
-
oj_dump_false,
|
263
|
-
oj_dump_sym,
|
264
|
-
oj_dump_fixnum,
|
237
|
+
raise_wab(obj);
|
238
|
+
}
|
239
|
+
}
|
240
|
+
|
241
|
+
static DumpFunc wab_funcs[] = {
|
242
|
+
NULL, // RUBY_T_NONE = 0x00,
|
243
|
+
dump_obj, // RUBY_T_OBJECT = 0x01,
|
244
|
+
NULL, // RUBY_T_CLASS = 0x02,
|
245
|
+
NULL, // RUBY_T_MODULE = 0x03,
|
246
|
+
dump_float, // RUBY_T_FLOAT = 0x04,
|
247
|
+
oj_dump_str, // RUBY_T_STRING = 0x05,
|
248
|
+
NULL, // RUBY_T_REGEXP = 0x06,
|
249
|
+
dump_array, // RUBY_T_ARRAY = 0x07,
|
250
|
+
dump_hash, // RUBY_T_HASH = 0x08,
|
251
|
+
NULL, // RUBY_T_STRUCT = 0x09,
|
252
|
+
oj_dump_bignum, // RUBY_T_BIGNUM = 0x0a,
|
253
|
+
NULL, // RUBY_T_FILE = 0x0b,
|
254
|
+
dump_obj, // RUBY_T_DATA = 0x0c,
|
255
|
+
NULL, // RUBY_T_MATCH = 0x0d,
|
256
|
+
NULL, // RUBY_T_COMPLEX = 0x0e,
|
257
|
+
NULL, // RUBY_T_RATIONAL = 0x0f,
|
258
|
+
NULL, // 0x10
|
259
|
+
oj_dump_nil, // RUBY_T_NIL = 0x11,
|
260
|
+
oj_dump_true, // RUBY_T_TRUE = 0x12,
|
261
|
+
oj_dump_false, // RUBY_T_FALSE = 0x13,
|
262
|
+
oj_dump_sym, // RUBY_T_SYMBOL = 0x14,
|
263
|
+
oj_dump_fixnum, // RUBY_T_FIXNUM = 0x15,
|
265
264
|
};
|
266
265
|
|
267
|
-
void
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
|
266
|
+
void oj_dump_wab_val(VALUE obj, int depth, Out out) {
|
267
|
+
int type = rb_type(obj);
|
268
|
+
|
269
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
270
|
+
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
|
273
271
|
}
|
274
272
|
if (MAX_DEPTH < depth) {
|
275
|
-
|
273
|
+
rb_raise(rb_eNoMemError, "Too deeply nested.\n");
|
276
274
|
}
|
277
275
|
if (0 < type && type <= RUBY_T_FIXNUM) {
|
278
|
-
|
276
|
+
DumpFunc f = wab_funcs[type];
|
279
277
|
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
278
|
+
if (NULL != f) {
|
279
|
+
f(obj, depth, out, false);
|
280
|
+
if (RB_UNLIKELY(Yes == out->opts->trace)) {
|
281
|
+
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
|
282
|
+
}
|
283
|
+
return;
|
284
|
+
}
|
287
285
|
}
|
288
286
|
raise_wab(obj);
|
289
287
|
}
|
290
288
|
|
291
289
|
///// load functions /////
|
292
290
|
|
293
|
-
static
|
294
|
-
|
295
|
-
|
296
|
-
|
291
|
+
static VALUE calc_hash_key(ParseInfo pi, Val parent) {
|
292
|
+
volatile VALUE rkey = parent->key_val;
|
293
|
+
|
294
|
+
if (Qundef != rkey) {
|
295
|
+
rkey = oj_encode(rkey);
|
296
|
+
rkey = rb_str_intern(rkey);
|
297
|
+
|
298
|
+
return rkey;
|
299
|
+
}
|
300
|
+
if (Yes == pi->options.cache_keys) {
|
301
|
+
rkey = oj_sym_intern(parent->key, parent->klen);
|
302
|
+
} else {
|
303
|
+
#if HAVE_RB_ENC_INTERNED_STR
|
304
|
+
rkey = rb_enc_interned_str(parent->key, parent->klen, oj_utf8_encoding);
|
305
|
+
#else
|
306
|
+
rkey = rb_utf8_str_new(parent->key, parent->klen);
|
307
|
+
rkey = rb_str_intern(rkey);
|
308
|
+
OBJ_FREEZE(rkey);
|
309
|
+
#endif
|
310
|
+
}
|
311
|
+
return rkey;
|
312
|
+
}
|
313
|
+
|
314
|
+
static void hash_end(ParseInfo pi) {
|
315
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
316
|
+
oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
|
297
317
|
}
|
298
318
|
}
|
299
319
|
|
300
|
-
static void
|
301
|
-
|
302
|
-
|
303
|
-
oj_trace_parse_array_end(pi, __FILE__, __LINE__);
|
320
|
+
static void array_end(ParseInfo pi) {
|
321
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
322
|
+
oj_trace_parse_array_end(pi, __FILE__, __LINE__);
|
304
323
|
}
|
305
324
|
}
|
306
325
|
|
307
|
-
static VALUE
|
308
|
-
noop_hash_key(struct _ParseInfo *pi, const char *key, size_t klen) {
|
326
|
+
static VALUE noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
|
309
327
|
return Qundef;
|
310
328
|
}
|
311
329
|
|
312
|
-
static void
|
313
|
-
|
314
|
-
|
315
|
-
oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, val);
|
330
|
+
static void add_value(ParseInfo pi, VALUE val) {
|
331
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
332
|
+
oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, val);
|
316
333
|
}
|
317
334
|
pi->stack.head->val = val;
|
318
335
|
}
|
319
336
|
|
320
337
|
// 123e4567-e89b-12d3-a456-426655440000
|
321
|
-
static bool
|
322
|
-
|
323
|
-
|
324
|
-
|
338
|
+
static bool uuid_check(const char *str, int len) {
|
339
|
+
int i;
|
340
|
+
|
325
341
|
for (i = 0; i < 8; i++, str++) {
|
326
|
-
|
327
|
-
|
328
|
-
|
342
|
+
if ('x' != hex_chars[*(uint8_t *)str]) {
|
343
|
+
return false;
|
344
|
+
}
|
329
345
|
}
|
330
346
|
str++;
|
331
347
|
for (i = 0; i < 4; i++, str++) {
|
332
|
-
|
333
|
-
|
334
|
-
|
348
|
+
if ('x' != hex_chars[*(uint8_t *)str]) {
|
349
|
+
return false;
|
350
|
+
}
|
335
351
|
}
|
336
352
|
str++;
|
337
353
|
for (i = 0; i < 4; i++, str++) {
|
338
|
-
|
339
|
-
|
340
|
-
|
354
|
+
if ('x' != hex_chars[*(uint8_t *)str]) {
|
355
|
+
return false;
|
356
|
+
}
|
341
357
|
}
|
342
358
|
str++;
|
343
359
|
for (i = 0; i < 4; i++, str++) {
|
344
|
-
|
345
|
-
|
346
|
-
|
360
|
+
if ('x' != hex_chars[*(uint8_t *)str]) {
|
361
|
+
return false;
|
362
|
+
}
|
347
363
|
}
|
348
364
|
str++;
|
349
365
|
for (i = 0; i < 12; i++, str++) {
|
350
|
-
|
351
|
-
|
352
|
-
|
366
|
+
if ('x' != hex_chars[*(uint8_t *)str]) {
|
367
|
+
return false;
|
368
|
+
}
|
353
369
|
}
|
354
370
|
return true;
|
355
371
|
}
|
356
372
|
|
357
|
-
static const char*
|
358
|
-
|
359
|
-
uint32_t v = 0;
|
373
|
+
static const char *read_num(const char *s, int len, int *vp) {
|
374
|
+
uint32_t v = 0;
|
360
375
|
|
361
376
|
for (; 0 < len; len--, s++) {
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
377
|
+
if ('0' <= *s && *s <= '9') {
|
378
|
+
v = v * 10 + *s - '0';
|
379
|
+
} else {
|
380
|
+
return NULL;
|
381
|
+
}
|
367
382
|
}
|
368
383
|
*vp = (int)v;
|
369
384
|
|
370
385
|
return s;
|
371
386
|
}
|
372
387
|
|
373
|
-
static VALUE
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
388
|
+
static VALUE time_parse(const char *s, int len) {
|
389
|
+
struct tm tm;
|
390
|
+
bool neg = false;
|
391
|
+
long nsecs = 0;
|
392
|
+
int i;
|
393
|
+
time_t secs;
|
394
|
+
|
381
395
|
memset(&tm, 0, sizeof(tm));
|
382
396
|
if ('-' == *s) {
|
383
|
-
|
384
|
-
|
397
|
+
s++;
|
398
|
+
neg = true;
|
385
399
|
}
|
386
400
|
if (NULL == (s = read_num(s, 4, &tm.tm_year))) {
|
387
|
-
|
401
|
+
return Qnil;
|
388
402
|
}
|
389
403
|
if (neg) {
|
390
|
-
|
391
|
-
|
404
|
+
tm.tm_year = -tm.tm_year;
|
405
|
+
neg = false;
|
392
406
|
}
|
393
407
|
tm.tm_year -= 1900;
|
394
408
|
s++;
|
395
409
|
if (NULL == (s = read_num(s, 2, &tm.tm_mon))) {
|
396
|
-
|
410
|
+
return Qnil;
|
397
411
|
}
|
398
412
|
tm.tm_mon--;
|
399
413
|
s++;
|
400
414
|
if (NULL == (s = read_num(s, 2, &tm.tm_mday))) {
|
401
|
-
|
415
|
+
return Qnil;
|
402
416
|
}
|
403
417
|
s++;
|
404
418
|
if (NULL == (s = read_num(s, 2, &tm.tm_hour))) {
|
405
|
-
|
419
|
+
return Qnil;
|
406
420
|
}
|
407
421
|
s++;
|
408
422
|
if (NULL == (s = read_num(s, 2, &tm.tm_min))) {
|
409
|
-
|
423
|
+
return Qnil;
|
410
424
|
}
|
411
425
|
s++;
|
412
426
|
if (NULL == (s = read_num(s, 2, &tm.tm_sec))) {
|
413
|
-
|
427
|
+
return Qnil;
|
414
428
|
}
|
415
429
|
s++;
|
416
430
|
|
417
431
|
for (i = 9; 0 < i; i--, s++) {
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
432
|
+
if ('0' <= *s && *s <= '9') {
|
433
|
+
nsecs = nsecs * 10 + *s - '0';
|
434
|
+
} else {
|
435
|
+
return Qnil;
|
436
|
+
}
|
423
437
|
}
|
424
438
|
#if IS_WINDOWS
|
425
439
|
secs = (time_t)mktime(&tm);
|
@@ -433,196 +447,171 @@ time_parse(const char *s, int len) {
|
|
433
447
|
return rb_funcall(rb_time_nano_new(secs, nsecs), oj_utc_id, 0);
|
434
448
|
}
|
435
449
|
|
436
|
-
static VALUE
|
437
|
-
protect_uri(VALUE rstr) {
|
450
|
+
static VALUE protect_uri(VALUE rstr) {
|
438
451
|
return rb_funcall(resolve_uri_class(), oj_parse_id, 1, rstr);
|
439
452
|
}
|
440
453
|
|
441
|
-
static VALUE
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
454
|
+
static VALUE cstr_to_rstr(ParseInfo pi, const char *str, size_t len) {
|
455
|
+
volatile VALUE v = Qnil;
|
456
|
+
|
457
|
+
if (30 == len && '-' == str[4] && '-' == str[7] && 'T' == str[10] && ':' == str[13] &&
|
458
|
+
':' == str[16] && '.' == str[19] && 'Z' == str[29]) {
|
459
|
+
if (Qnil != (v = time_parse(str, (int)len))) {
|
460
|
+
return v;
|
461
|
+
}
|
449
462
|
}
|
450
|
-
if (36 == len && '-' == str[8] && '-' == str[13] && '-' == str[18] && '-' == str[23] &&
|
451
|
-
|
463
|
+
if (36 == len && '-' == str[8] && '-' == str[13] && '-' == str[18] && '-' == str[23] &&
|
464
|
+
uuid_check(str, (int)len) && Qnil != resolve_wab_uuid_class()) {
|
465
|
+
return rb_funcall(wab_uuid_clas, oj_new_id, 1, rb_str_new(str, len));
|
452
466
|
}
|
453
|
-
v = rb_str_new(str, len);
|
454
467
|
if (7 < len && 0 == strncasecmp("http://", str, 7)) {
|
455
|
-
|
456
|
-
|
468
|
+
int err = 0;
|
469
|
+
v = rb_str_new(str, len);
|
470
|
+
volatile VALUE uri = rb_protect(protect_uri, v, &err);
|
457
471
|
|
458
|
-
|
459
|
-
|
460
|
-
|
472
|
+
if (0 == err) {
|
473
|
+
return uri;
|
474
|
+
}
|
461
475
|
}
|
462
|
-
return
|
476
|
+
return oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
|
463
477
|
}
|
464
478
|
|
465
|
-
static void
|
466
|
-
|
467
|
-
pi->
|
468
|
-
|
469
|
-
oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, pi->stack.head->val);
|
479
|
+
static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
480
|
+
pi->stack.head->val = cstr_to_rstr(pi, str, len);
|
481
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
482
|
+
oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, pi->stack.head->val);
|
470
483
|
}
|
471
484
|
}
|
472
485
|
|
473
|
-
static void
|
474
|
-
add_num(ParseInfo pi, NumInfo ni) {
|
486
|
+
static void add_num(ParseInfo pi, NumInfo ni) {
|
475
487
|
if (ni->infinity || ni->nan) {
|
476
|
-
|
488
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
|
477
489
|
}
|
478
490
|
pi->stack.head->val = oj_num_as_value(ni);
|
479
|
-
if (Yes == pi->options.trace) {
|
480
|
-
|
491
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
492
|
+
oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, pi->stack.head->val);
|
481
493
|
}
|
482
494
|
}
|
483
495
|
|
484
|
-
static VALUE
|
485
|
-
|
486
|
-
|
487
|
-
oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
|
496
|
+
static VALUE start_hash(ParseInfo pi) {
|
497
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
498
|
+
oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
|
488
499
|
}
|
489
500
|
if (Qnil != pi->options.hash_class) {
|
490
|
-
|
501
|
+
return rb_class_new_instance(0, NULL, pi->options.hash_class);
|
491
502
|
}
|
492
503
|
return rb_hash_new();
|
493
504
|
}
|
494
505
|
|
495
|
-
static
|
496
|
-
|
497
|
-
volatile VALUE rkey = parent->key_val;
|
498
|
-
|
499
|
-
if (Qundef == rkey) {
|
500
|
-
rkey = rb_str_new(parent->key, parent->klen);
|
501
|
-
}
|
502
|
-
rkey = oj_encode(rkey);
|
503
|
-
rkey = rb_str_intern(rkey);
|
504
|
-
|
505
|
-
return rkey;
|
506
|
-
}
|
507
|
-
|
508
|
-
static void
|
509
|
-
hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len, const char *orig) {
|
510
|
-
volatile VALUE rval = cstr_to_rstr(str, len);
|
506
|
+
static void hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len, const char *orig) {
|
507
|
+
volatile VALUE rval = cstr_to_rstr(pi, str, len);
|
511
508
|
|
512
509
|
rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), rval);
|
513
|
-
if (Yes == pi->options.trace) {
|
514
|
-
|
510
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
511
|
+
oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
|
515
512
|
}
|
516
513
|
}
|
517
514
|
|
518
|
-
static void
|
519
|
-
|
520
|
-
|
521
|
-
|
515
|
+
static void hash_set_num(ParseInfo pi, Val parent, NumInfo ni) {
|
516
|
+
volatile VALUE rval = Qnil;
|
517
|
+
|
522
518
|
if (ni->infinity || ni->nan) {
|
523
|
-
|
519
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
|
524
520
|
}
|
525
521
|
rval = oj_num_as_value(ni);
|
526
522
|
rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), rval);
|
527
|
-
if (Yes == pi->options.trace) {
|
528
|
-
|
523
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
524
|
+
oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, rval);
|
529
525
|
}
|
530
526
|
}
|
531
527
|
|
532
|
-
static void
|
533
|
-
hash_set_value(ParseInfo pi, Val parent, VALUE value) {
|
528
|
+
static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
|
534
529
|
rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), value);
|
535
|
-
if (Yes == pi->options.trace) {
|
536
|
-
|
530
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
531
|
+
oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
|
537
532
|
}
|
538
533
|
}
|
539
534
|
|
540
|
-
static VALUE
|
541
|
-
|
542
|
-
|
543
|
-
oj_trace_parse_in("start_array", pi, __FILE__, __LINE__);
|
535
|
+
static VALUE start_array(ParseInfo pi) {
|
536
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
537
|
+
oj_trace_parse_in("start_array", pi, __FILE__, __LINE__);
|
544
538
|
}
|
545
539
|
return rb_ary_new();
|
546
540
|
}
|
547
541
|
|
548
|
-
static void
|
549
|
-
|
550
|
-
|
551
|
-
|
542
|
+
static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
543
|
+
volatile VALUE rval = cstr_to_rstr(pi, str, len);
|
544
|
+
|
552
545
|
rb_ary_push(stack_peek(&pi->stack)->val, rval);
|
553
|
-
if (Yes == pi->options.trace) {
|
554
|
-
|
546
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
547
|
+
oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, rval);
|
555
548
|
}
|
556
549
|
}
|
557
550
|
|
558
|
-
static void
|
559
|
-
|
560
|
-
volatile VALUE rval = Qnil;
|
551
|
+
static void array_append_num(ParseInfo pi, NumInfo ni) {
|
552
|
+
volatile VALUE rval = Qnil;
|
561
553
|
|
562
554
|
if (ni->infinity || ni->nan) {
|
563
|
-
|
555
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
|
564
556
|
}
|
565
557
|
rval = oj_num_as_value(ni);
|
566
558
|
rb_ary_push(stack_peek(&pi->stack)->val, rval);
|
567
|
-
if (Yes == pi->options.trace) {
|
568
|
-
|
559
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
560
|
+
oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
|
569
561
|
}
|
570
562
|
}
|
571
563
|
|
572
|
-
static void
|
573
|
-
array_append_value(ParseInfo pi, VALUE value) {
|
564
|
+
static void array_append_value(ParseInfo pi, VALUE value) {
|
574
565
|
rb_ary_push(stack_peek(&pi->stack)->val, value);
|
575
|
-
if (Yes == pi->options.trace) {
|
576
|
-
|
577
|
-
}
|
578
|
-
}
|
579
|
-
|
580
|
-
void
|
581
|
-
|
582
|
-
pi->
|
583
|
-
pi->
|
584
|
-
pi->
|
585
|
-
pi->
|
586
|
-
pi->
|
587
|
-
pi->
|
588
|
-
pi->
|
589
|
-
pi->
|
590
|
-
pi->
|
591
|
-
pi->array_append_num = array_append_num;
|
566
|
+
if (RB_UNLIKELY(Yes == pi->options.trace)) {
|
567
|
+
oj_trace_parse_call("append_value", pi, __FILE__, __LINE__, value);
|
568
|
+
}
|
569
|
+
}
|
570
|
+
|
571
|
+
void oj_set_wab_callbacks(ParseInfo pi) {
|
572
|
+
pi->start_hash = start_hash;
|
573
|
+
pi->end_hash = hash_end;
|
574
|
+
pi->hash_key = noop_hash_key;
|
575
|
+
pi->hash_set_cstr = hash_set_cstr;
|
576
|
+
pi->hash_set_num = hash_set_num;
|
577
|
+
pi->hash_set_value = hash_set_value;
|
578
|
+
pi->start_array = start_array;
|
579
|
+
pi->end_array = array_end;
|
580
|
+
pi->array_append_cstr = array_append_cstr;
|
581
|
+
pi->array_append_num = array_append_num;
|
592
582
|
pi->array_append_value = array_append_value;
|
593
|
-
pi->add_cstr
|
594
|
-
pi->add_num
|
595
|
-
pi->add_value
|
596
|
-
pi->expect_value
|
583
|
+
pi->add_cstr = add_cstr;
|
584
|
+
pi->add_num = add_num;
|
585
|
+
pi->add_value = add_value;
|
586
|
+
pi->expect_value = 1;
|
597
587
|
}
|
598
588
|
|
599
589
|
VALUE
|
600
590
|
oj_wab_parse(int argc, VALUE *argv, VALUE self) {
|
601
|
-
struct
|
591
|
+
struct _parseInfo pi;
|
602
592
|
|
603
593
|
parse_info_init(&pi);
|
604
|
-
pi.options
|
605
|
-
pi.handler
|
594
|
+
pi.options = oj_default_options;
|
595
|
+
pi.handler = Qnil;
|
606
596
|
pi.err_class = Qnil;
|
607
597
|
oj_set_wab_callbacks(&pi);
|
608
598
|
|
609
599
|
if (T_STRING == rb_type(*argv)) {
|
610
|
-
|
600
|
+
return oj_pi_parse(argc, argv, &pi, 0, 0, true);
|
611
601
|
} else {
|
612
|
-
|
602
|
+
return oj_pi_sparse(argc, argv, &pi, 0);
|
613
603
|
}
|
614
604
|
}
|
615
605
|
|
616
606
|
VALUE
|
617
607
|
oj_wab_parse_cstr(int argc, VALUE *argv, char *json, size_t len) {
|
618
|
-
struct
|
608
|
+
struct _parseInfo pi;
|
619
609
|
|
620
610
|
parse_info_init(&pi);
|
621
|
-
pi.options
|
622
|
-
pi.handler
|
611
|
+
pi.options = oj_default_options;
|
612
|
+
pi.handler = Qnil;
|
623
613
|
pi.err_class = Qnil;
|
624
614
|
oj_set_wab_callbacks(&pi);
|
625
615
|
|
626
616
|
return oj_pi_parse(argc, argv, &pi, json, len, true);
|
627
617
|
}
|
628
|
-
|