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