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