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/saj.c
CHANGED
@@ -1,48 +1,47 @@
|
|
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
4
|
#if !IS_WINDOWS
|
7
|
-
#include <sys/resource.h>
|
5
|
+
#include <sys/resource.h> /* for getrlimit() on linux */
|
8
6
|
#endif
|
9
|
-
#include <
|
7
|
+
#include <math.h>
|
10
8
|
#include <stdio.h>
|
9
|
+
#include <stdlib.h>
|
11
10
|
#include <string.h>
|
12
|
-
#include <math.h>
|
13
11
|
#include <sys/types.h>
|
14
12
|
#include <unistd.h>
|
15
13
|
|
16
14
|
// Workaround in case INFINITY is not defined in math.h or if the OS is CentOS
|
17
|
-
#define OJ_INFINITY (1.0/0.0)
|
15
|
+
#define OJ_INFINITY (1.0 / 0.0)
|
18
16
|
|
19
|
-
#include "oj.h"
|
20
17
|
#include "encode.h"
|
18
|
+
#include "mem.h"
|
19
|
+
#include "oj.h"
|
21
20
|
|
22
21
|
typedef struct _parseInfo {
|
23
|
-
char
|
24
|
-
char
|
25
|
-
void
|
26
|
-
VALUE
|
27
|
-
int
|
28
|
-
int
|
29
|
-
int
|
30
|
-
int
|
31
|
-
int
|
32
|
-
int
|
22
|
+
char *str; /* buffer being read from */
|
23
|
+
char *s; /* current position in buffer */
|
24
|
+
void *stack_min;
|
25
|
+
VALUE handler;
|
26
|
+
int has_hash_start;
|
27
|
+
int has_hash_end;
|
28
|
+
int has_array_start;
|
29
|
+
int has_array_end;
|
30
|
+
int has_add_value;
|
31
|
+
int has_error;
|
33
32
|
} *ParseInfo;
|
34
33
|
|
35
|
-
static void
|
36
|
-
static void
|
37
|
-
static void
|
38
|
-
static void
|
39
|
-
static void
|
40
|
-
static void
|
41
|
-
static void
|
42
|
-
static void
|
43
|
-
static void
|
44
|
-
static char*
|
45
|
-
static void
|
34
|
+
static void read_next(ParseInfo pi, const char *key);
|
35
|
+
static void read_hash(ParseInfo pi, const char *key);
|
36
|
+
static void read_array(ParseInfo pi, const char *key);
|
37
|
+
static void read_str(ParseInfo pi, const char *key);
|
38
|
+
static void read_num(ParseInfo pi, const char *key);
|
39
|
+
static void read_true(ParseInfo pi, const char *key);
|
40
|
+
static void read_false(ParseInfo pi, const char *key);
|
41
|
+
static void read_nil(ParseInfo pi, const char *key);
|
42
|
+
static void next_non_white(ParseInfo pi);
|
43
|
+
static char *read_quoted_value(ParseInfo pi);
|
44
|
+
static void skip_comment(ParseInfo pi);
|
46
45
|
|
47
46
|
/* This JSON parser is a single pass, destructive, callback parser. It is a
|
48
47
|
* single pass parse since it only make one pass over the characters in the
|
@@ -57,126 +56,106 @@ static void skip_comment(ParseInfo pi);
|
|
57
56
|
* all cases to parse the string.
|
58
57
|
*/
|
59
58
|
|
60
|
-
inline static void
|
61
|
-
|
62
|
-
char
|
63
|
-
|
64
|
-
int
|
65
|
-
int col = 1;
|
59
|
+
inline static void call_error(const char *msg, ParseInfo pi, const char *file, int line) {
|
60
|
+
char buf[128];
|
61
|
+
const char *s = pi->s;
|
62
|
+
int jline = 1;
|
63
|
+
int col = 1;
|
66
64
|
|
67
65
|
for (; pi->str < s && '\n' != *s; s--) {
|
68
|
-
|
66
|
+
col++;
|
69
67
|
}
|
70
68
|
for (; pi->str < s; s--) {
|
71
|
-
|
72
|
-
|
73
|
-
|
69
|
+
if ('\n' == *s) {
|
70
|
+
jline++;
|
71
|
+
}
|
74
72
|
}
|
75
73
|
sprintf(buf, "%s at line %d, column %d [%s:%d]", msg, jline, col, file, line);
|
76
74
|
rb_funcall(pi->handler, oj_error_id, 3, rb_str_new2(buf), LONG2NUM(jline), LONG2NUM(col));
|
77
75
|
}
|
78
76
|
|
79
|
-
inline static void
|
80
|
-
next_non_white(ParseInfo pi) {
|
77
|
+
inline static void next_non_white(ParseInfo pi) {
|
81
78
|
for (; 1; pi->s++) {
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
break;
|
92
|
-
default:
|
93
|
-
return;
|
94
|
-
}
|
79
|
+
switch (*pi->s) {
|
80
|
+
case ' ':
|
81
|
+
case '\t':
|
82
|
+
case '\f':
|
83
|
+
case '\n':
|
84
|
+
case '\r': break;
|
85
|
+
case '/': skip_comment(pi); break;
|
86
|
+
default: return;
|
87
|
+
}
|
95
88
|
}
|
96
89
|
}
|
97
90
|
|
98
|
-
inline static void
|
99
|
-
|
100
|
-
volatile VALUE k;
|
91
|
+
inline static void call_add_value(VALUE handler, VALUE value, const char *key) {
|
92
|
+
volatile VALUE k;
|
101
93
|
|
102
94
|
if (0 == key) {
|
103
|
-
|
95
|
+
k = Qnil;
|
104
96
|
} else {
|
105
|
-
|
106
|
-
k = oj_encode(k);
|
97
|
+
k = rb_utf8_str_new_cstr(key);
|
107
98
|
}
|
108
99
|
rb_funcall(handler, oj_add_value_id, 2, value, k);
|
109
100
|
}
|
110
101
|
|
111
|
-
inline static void
|
112
|
-
|
113
|
-
volatile VALUE k;
|
102
|
+
inline static void call_no_value(VALUE handler, ID method, const char *key) {
|
103
|
+
volatile VALUE k;
|
114
104
|
|
115
105
|
if (0 == key) {
|
116
|
-
|
106
|
+
k = Qnil;
|
117
107
|
} else {
|
118
|
-
|
119
|
-
k = oj_encode(k);
|
108
|
+
k = rb_utf8_str_new_cstr(key);
|
120
109
|
}
|
121
110
|
rb_funcall(handler, method, 1, k);
|
122
111
|
}
|
123
112
|
|
124
|
-
static void
|
125
|
-
skip_comment(ParseInfo pi) {
|
113
|
+
static void skip_comment(ParseInfo pi) {
|
126
114
|
pi->s++; /* skip first / */
|
127
115
|
if ('*' == *pi->s) {
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
116
|
+
pi->s++;
|
117
|
+
for (; '\0' != *pi->s; pi->s++) {
|
118
|
+
if ('*' == *pi->s && '/' == *(pi->s + 1)) {
|
119
|
+
pi->s++;
|
120
|
+
return;
|
121
|
+
} else if ('\0' == *pi->s) {
|
122
|
+
if (pi->has_error) {
|
123
|
+
call_error("comment not terminated", pi, __FILE__, __LINE__);
|
124
|
+
} else {
|
125
|
+
raise_error("comment not terminated", pi->str, pi->s);
|
126
|
+
}
|
127
|
+
}
|
128
|
+
}
|
141
129
|
} else if ('/' == *pi->s) {
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
}
|
152
|
-
}
|
130
|
+
for (; 1; pi->s++) {
|
131
|
+
switch (*pi->s) {
|
132
|
+
case '\n':
|
133
|
+
case '\r':
|
134
|
+
case '\f':
|
135
|
+
case '\0': return;
|
136
|
+
default: break;
|
137
|
+
}
|
138
|
+
}
|
153
139
|
} else {
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
140
|
+
if (pi->has_error) {
|
141
|
+
call_error("invalid comment", pi, __FILE__, __LINE__);
|
142
|
+
} else {
|
143
|
+
raise_error("invalid comment", pi->str, pi->s);
|
144
|
+
}
|
159
145
|
}
|
160
146
|
}
|
161
147
|
|
162
|
-
static void
|
163
|
-
|
164
|
-
VALUE obj;
|
148
|
+
static void read_next(ParseInfo pi, const char *key) {
|
149
|
+
VALUE obj;
|
165
150
|
|
166
|
-
if ((void*)&obj < pi->stack_min) {
|
167
|
-
|
151
|
+
if ((void *)&obj < pi->stack_min) {
|
152
|
+
rb_raise(rb_eSysStackError, "JSON is too deeply nested");
|
168
153
|
}
|
169
|
-
next_non_white(pi);
|
154
|
+
next_non_white(pi); /* skip white space */
|
170
155
|
switch (*pi->s) {
|
171
|
-
case '{':
|
172
|
-
|
173
|
-
|
174
|
-
case '[':
|
175
|
-
read_array(pi, key);
|
176
|
-
break;
|
177
|
-
case '"':
|
178
|
-
read_str(pi, key);
|
179
|
-
break;
|
156
|
+
case '{': read_hash(pi, key); break;
|
157
|
+
case '[': read_array(pi, key); break;
|
158
|
+
case '"': read_str(pi, key); break;
|
180
159
|
case '+':
|
181
160
|
case '-':
|
182
161
|
case '0':
|
@@ -188,113 +167,97 @@ read_next(ParseInfo pi, const char *key) {
|
|
188
167
|
case '6':
|
189
168
|
case '7':
|
190
169
|
case '8':
|
191
|
-
case '9':
|
192
|
-
|
193
|
-
|
194
|
-
case '
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
read_true(pi, key);
|
199
|
-
break;
|
200
|
-
case 'f':
|
201
|
-
read_false(pi, key);
|
202
|
-
break;
|
203
|
-
case 'n':
|
204
|
-
read_nil(pi, key);
|
205
|
-
break;
|
206
|
-
case '\0':
|
207
|
-
return;
|
208
|
-
default:
|
209
|
-
return;
|
170
|
+
case '9': read_num(pi, key); break;
|
171
|
+
case 'I': read_num(pi, key); break;
|
172
|
+
case 't': read_true(pi, key); break;
|
173
|
+
case 'f': read_false(pi, key); break;
|
174
|
+
case 'n': read_nil(pi, key); break;
|
175
|
+
case '\0': return;
|
176
|
+
default: return;
|
210
177
|
}
|
211
178
|
}
|
212
179
|
|
213
|
-
static void
|
214
|
-
|
215
|
-
|
216
|
-
|
180
|
+
static void read_hash(ParseInfo pi, const char *key) {
|
181
|
+
const char *ks;
|
182
|
+
|
217
183
|
if (pi->has_hash_start) {
|
218
|
-
|
184
|
+
call_no_value(pi->handler, oj_hash_start_id, key);
|
219
185
|
}
|
220
186
|
pi->s++;
|
221
187
|
next_non_white(pi);
|
222
188
|
if ('}' == *pi->s) {
|
223
|
-
|
189
|
+
pi->s++;
|
224
190
|
} else {
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
191
|
+
while (1) {
|
192
|
+
next_non_white(pi);
|
193
|
+
ks = read_quoted_value(pi);
|
194
|
+
next_non_white(pi);
|
195
|
+
if (':' == *pi->s) {
|
196
|
+
pi->s++;
|
197
|
+
} else {
|
198
|
+
if (pi->has_error) {
|
199
|
+
call_error("invalid format, expected :", pi, __FILE__, __LINE__);
|
200
|
+
}
|
201
|
+
raise_error("invalid format, expected :", pi->str, pi->s);
|
202
|
+
}
|
203
|
+
read_next(pi, ks);
|
204
|
+
next_non_white(pi);
|
205
|
+
if ('}' == *pi->s) {
|
206
|
+
pi->s++;
|
207
|
+
break;
|
208
|
+
} else if (',' == *pi->s) {
|
209
|
+
pi->s++;
|
210
|
+
} else {
|
211
|
+
if (pi->has_error) {
|
212
|
+
call_error("invalid format, expected , or } while in an object", pi, __FILE__, __LINE__);
|
213
|
+
}
|
214
|
+
raise_error("invalid format, expected , or } while in an object", pi->str, pi->s);
|
215
|
+
}
|
216
|
+
}
|
251
217
|
}
|
252
218
|
if (pi->has_hash_end) {
|
253
|
-
|
219
|
+
call_no_value(pi->handler, oj_hash_end_id, key);
|
254
220
|
}
|
255
221
|
}
|
256
222
|
|
257
|
-
static void
|
258
|
-
read_array(ParseInfo pi, const char *key) {
|
223
|
+
static void read_array(ParseInfo pi, const char *key) {
|
259
224
|
if (pi->has_array_start) {
|
260
|
-
|
225
|
+
call_no_value(pi->handler, oj_array_start_id, key);
|
261
226
|
}
|
262
227
|
pi->s++;
|
263
228
|
next_non_white(pi);
|
264
229
|
if (']' == *pi->s) {
|
265
|
-
|
230
|
+
pi->s++;
|
266
231
|
} else {
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
232
|
+
while (1) {
|
233
|
+
read_next(pi, 0);
|
234
|
+
next_non_white(pi);
|
235
|
+
if (',' == *pi->s) {
|
236
|
+
pi->s++;
|
237
|
+
} else if (']' == *pi->s) {
|
238
|
+
pi->s++;
|
239
|
+
break;
|
240
|
+
} else {
|
241
|
+
if (pi->has_error) {
|
242
|
+
call_error("invalid format, expected , or ] while in an array", pi, __FILE__, __LINE__);
|
243
|
+
}
|
244
|
+
raise_error("invalid format, expected , or ] while in an array", pi->str, pi->s);
|
245
|
+
}
|
246
|
+
}
|
282
247
|
}
|
283
248
|
if (pi->has_array_end) {
|
284
|
-
|
249
|
+
call_no_value(pi->handler, oj_array_end_id, key);
|
285
250
|
}
|
286
251
|
}
|
287
252
|
|
288
|
-
static void
|
289
|
-
|
290
|
-
char *text;
|
253
|
+
static void read_str(ParseInfo pi, const char *key) {
|
254
|
+
char *text;
|
291
255
|
|
292
256
|
text = read_quoted_value(pi);
|
293
257
|
if (pi->has_add_value) {
|
294
|
-
|
258
|
+
VALUE s = rb_utf8_str_new_cstr(text);
|
295
259
|
|
296
|
-
|
297
|
-
call_add_value(pi->handler, s, key);
|
260
|
+
call_add_value(pi->handler, s, key);
|
298
261
|
}
|
299
262
|
}
|
300
263
|
|
@@ -304,230 +267,224 @@ read_str(ParseInfo pi, const char *key) {
|
|
304
267
|
#define NUM_MAX (FIXNUM_MAX >> 8)
|
305
268
|
#endif
|
306
269
|
|
307
|
-
static void
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
long
|
312
|
-
long
|
313
|
-
|
314
|
-
int
|
315
|
-
int
|
316
|
-
int big = 0;
|
270
|
+
static void read_num(ParseInfo pi, const char *key) {
|
271
|
+
char *start = pi->s;
|
272
|
+
int64_t n = 0;
|
273
|
+
long a = 0;
|
274
|
+
long div = 1;
|
275
|
+
long e = 0;
|
276
|
+
int neg = 0;
|
277
|
+
int eneg = 0;
|
278
|
+
int big = 0;
|
317
279
|
|
318
280
|
if ('-' == *pi->s) {
|
319
|
-
|
320
|
-
|
281
|
+
pi->s++;
|
282
|
+
neg = 1;
|
321
283
|
} else if ('+' == *pi->s) {
|
322
|
-
|
284
|
+
pi->s++;
|
323
285
|
}
|
324
286
|
if ('I' == *pi->s) {
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
287
|
+
if (0 != strncmp("Infinity", pi->s, 8)) {
|
288
|
+
if (pi->has_error) {
|
289
|
+
call_error("number or other value", pi, __FILE__, __LINE__);
|
290
|
+
}
|
291
|
+
raise_error("number or other value", pi->str, pi->s);
|
292
|
+
}
|
293
|
+
pi->s += 8;
|
294
|
+
if (neg) {
|
295
|
+
if (pi->has_add_value) {
|
296
|
+
call_add_value(pi->handler, rb_float_new(-OJ_INFINITY), key);
|
297
|
+
}
|
298
|
+
} else {
|
299
|
+
if (pi->has_add_value) {
|
300
|
+
call_add_value(pi->handler, rb_float_new(OJ_INFINITY), key);
|
301
|
+
}
|
302
|
+
}
|
303
|
+
return;
|
342
304
|
}
|
343
305
|
for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
306
|
+
if (big) {
|
307
|
+
big++;
|
308
|
+
} else {
|
309
|
+
n = n * 10 + (*pi->s - '0');
|
310
|
+
if (NUM_MAX <= n) {
|
311
|
+
big = 1;
|
312
|
+
}
|
313
|
+
}
|
352
314
|
}
|
353
315
|
if ('.' == *pi->s) {
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
316
|
+
pi->s++;
|
317
|
+
for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
|
318
|
+
a = a * 10 + (*pi->s - '0');
|
319
|
+
div *= 10;
|
320
|
+
if (NUM_MAX <= div) {
|
321
|
+
big = 1;
|
322
|
+
}
|
323
|
+
}
|
362
324
|
}
|
363
325
|
if ('e' == *pi->s || 'E' == *pi->s) {
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
326
|
+
pi->s++;
|
327
|
+
if ('-' == *pi->s) {
|
328
|
+
pi->s++;
|
329
|
+
eneg = 1;
|
330
|
+
} else if ('+' == *pi->s) {
|
331
|
+
pi->s++;
|
332
|
+
}
|
333
|
+
for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
|
334
|
+
e = e * 10 + (*pi->s - '0');
|
335
|
+
if (NUM_MAX <= e) {
|
336
|
+
big = 1;
|
337
|
+
}
|
338
|
+
}
|
377
339
|
}
|
378
340
|
if (0 == e && 0 == a && 1 == div) {
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
341
|
+
if (big) {
|
342
|
+
char c = *pi->s;
|
343
|
+
|
344
|
+
*pi->s = '\0';
|
345
|
+
if (pi->has_add_value) {
|
346
|
+
call_add_value(pi->handler, rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new2(start)), key);
|
347
|
+
}
|
348
|
+
*pi->s = c;
|
349
|
+
} else {
|
350
|
+
if (neg) {
|
351
|
+
n = -n;
|
352
|
+
}
|
353
|
+
if (pi->has_add_value) {
|
354
|
+
call_add_value(pi->handler, LONG2NUM(n), key);
|
355
|
+
}
|
356
|
+
}
|
357
|
+
return;
|
396
358
|
} else { /* decimal */
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
359
|
+
if (big) {
|
360
|
+
char c = *pi->s;
|
361
|
+
|
362
|
+
*pi->s = '\0';
|
363
|
+
if (pi->has_add_value) {
|
364
|
+
call_add_value(pi->handler, rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new2(start)), key);
|
365
|
+
}
|
366
|
+
*pi->s = c;
|
367
|
+
} else {
|
368
|
+
double d = (double)n + (double)a / (double)div;
|
369
|
+
|
370
|
+
if (neg) {
|
371
|
+
d = -d;
|
372
|
+
}
|
373
|
+
if (1 < big) {
|
374
|
+
e += big - 1;
|
375
|
+
}
|
376
|
+
if (0 != e) {
|
377
|
+
if (eneg) {
|
378
|
+
e = -e;
|
379
|
+
}
|
380
|
+
d *= pow(10.0, e);
|
381
|
+
}
|
382
|
+
if (pi->has_add_value) {
|
383
|
+
call_add_value(pi->handler, rb_float_new(d), key);
|
384
|
+
}
|
385
|
+
}
|
424
386
|
}
|
425
387
|
}
|
426
388
|
|
427
|
-
static void
|
428
|
-
read_true(ParseInfo pi, const char *key) {
|
389
|
+
static void read_true(ParseInfo pi, const char *key) {
|
429
390
|
pi->s++;
|
430
391
|
if ('r' != *pi->s || 'u' != *(pi->s + 1) || 'e' != *(pi->s + 2)) {
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
392
|
+
if (pi->has_error) {
|
393
|
+
call_error("invalid format, expected 'true'", pi, __FILE__, __LINE__);
|
394
|
+
}
|
395
|
+
raise_error("invalid format, expected 'true'", pi->str, pi->s);
|
435
396
|
}
|
436
397
|
pi->s += 3;
|
437
398
|
if (pi->has_add_value) {
|
438
|
-
|
399
|
+
call_add_value(pi->handler, Qtrue, key);
|
439
400
|
}
|
440
401
|
}
|
441
402
|
|
442
|
-
static void
|
443
|
-
read_false(ParseInfo pi, const char *key) {
|
403
|
+
static void read_false(ParseInfo pi, const char *key) {
|
444
404
|
pi->s++;
|
445
405
|
if ('a' != *pi->s || 'l' != *(pi->s + 1) || 's' != *(pi->s + 2) || 'e' != *(pi->s + 3)) {
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
406
|
+
if (pi->has_error) {
|
407
|
+
call_error("invalid format, expected 'false'", pi, __FILE__, __LINE__);
|
408
|
+
}
|
409
|
+
raise_error("invalid format, expected 'false'", pi->str, pi->s);
|
450
410
|
}
|
451
411
|
pi->s += 4;
|
452
412
|
if (pi->has_add_value) {
|
453
|
-
|
413
|
+
call_add_value(pi->handler, Qfalse, key);
|
454
414
|
}
|
455
415
|
}
|
456
416
|
|
457
|
-
static void
|
458
|
-
read_nil(ParseInfo pi, const char *key) {
|
417
|
+
static void read_nil(ParseInfo pi, const char *key) {
|
459
418
|
pi->s++;
|
460
419
|
if ('u' != *pi->s || 'l' != *(pi->s + 1) || 'l' != *(pi->s + 2)) {
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
420
|
+
if (pi->has_error) {
|
421
|
+
call_error("invalid format, expected 'null'", pi, __FILE__, __LINE__);
|
422
|
+
}
|
423
|
+
raise_error("invalid format, expected 'null'", pi->str, pi->s);
|
465
424
|
}
|
466
425
|
pi->s += 3;
|
467
426
|
if (pi->has_add_value) {
|
468
|
-
|
427
|
+
call_add_value(pi->handler, Qnil, key);
|
469
428
|
}
|
470
429
|
}
|
471
430
|
|
472
|
-
static uint32_t
|
473
|
-
|
474
|
-
|
475
|
-
int i;
|
431
|
+
static uint32_t read_hex(ParseInfo pi, char *h) {
|
432
|
+
uint32_t b = 0;
|
433
|
+
int i;
|
476
434
|
|
477
435
|
/* TBD this can be made faster with a table */
|
478
436
|
for (i = 0; i < 4; i++, h++) {
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
437
|
+
b = b << 4;
|
438
|
+
if ('0' <= *h && *h <= '9') {
|
439
|
+
b += *h - '0';
|
440
|
+
} else if ('A' <= *h && *h <= 'F') {
|
441
|
+
b += *h - 'A' + 10;
|
442
|
+
} else if ('a' <= *h && *h <= 'f') {
|
443
|
+
b += *h - 'a' + 10;
|
444
|
+
} else {
|
445
|
+
pi->s = h;
|
446
|
+
if (pi->has_error) {
|
447
|
+
call_error("invalid hex character", pi, __FILE__, __LINE__);
|
448
|
+
}
|
449
|
+
raise_error("invalid hex character", pi->str, pi->s);
|
450
|
+
}
|
493
451
|
}
|
494
452
|
return b;
|
495
453
|
}
|
496
454
|
|
497
|
-
static char*
|
498
|
-
unicode_to_chars(ParseInfo pi, char *t, uint32_t code) {
|
455
|
+
static char *unicode_to_chars(ParseInfo pi, char *t, uint32_t code) {
|
499
456
|
if (0x0000007F >= code) {
|
500
|
-
|
457
|
+
*t = (char)code;
|
501
458
|
} else if (0x000007FF >= code) {
|
502
|
-
|
503
|
-
|
459
|
+
*t++ = 0xC0 | (code >> 6);
|
460
|
+
*t = 0x80 | (0x3F & code);
|
504
461
|
} else if (0x0000FFFF >= code) {
|
505
|
-
|
506
|
-
|
507
|
-
|
462
|
+
*t++ = 0xE0 | (code >> 12);
|
463
|
+
*t++ = 0x80 | ((code >> 6) & 0x3F);
|
464
|
+
*t = 0x80 | (0x3F & code);
|
508
465
|
} else if (0x001FFFFF >= code) {
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
466
|
+
*t++ = 0xF0 | (code >> 18);
|
467
|
+
*t++ = 0x80 | ((code >> 12) & 0x3F);
|
468
|
+
*t++ = 0x80 | ((code >> 6) & 0x3F);
|
469
|
+
*t = 0x80 | (0x3F & code);
|
513
470
|
} else if (0x03FFFFFF >= code) {
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
471
|
+
*t++ = 0xF8 | (code >> 24);
|
472
|
+
*t++ = 0x80 | ((code >> 18) & 0x3F);
|
473
|
+
*t++ = 0x80 | ((code >> 12) & 0x3F);
|
474
|
+
*t++ = 0x80 | ((code >> 6) & 0x3F);
|
475
|
+
*t = 0x80 | (0x3F & code);
|
519
476
|
} else if (0x7FFFFFFF >= code) {
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
477
|
+
*t++ = 0xFC | (code >> 30);
|
478
|
+
*t++ = 0x80 | ((code >> 24) & 0x3F);
|
479
|
+
*t++ = 0x80 | ((code >> 18) & 0x3F);
|
480
|
+
*t++ = 0x80 | ((code >> 12) & 0x3F);
|
481
|
+
*t++ = 0x80 | ((code >> 6) & 0x3F);
|
482
|
+
*t = 0x80 | (0x3F & code);
|
526
483
|
} else {
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
484
|
+
if (pi->has_error) {
|
485
|
+
call_error("invalid Unicode", pi, __FILE__, __LINE__);
|
486
|
+
}
|
487
|
+
raise_error("invalid Unicode", pi->str, pi->s);
|
531
488
|
}
|
532
489
|
return t;
|
533
490
|
}
|
@@ -535,119 +492,117 @@ unicode_to_chars(ParseInfo pi, char *t, uint32_t code) {
|
|
535
492
|
/* Assume the value starts immediately and goes until the quote character is
|
536
493
|
* reached again. Do not read the character after the terminating quote.
|
537
494
|
*/
|
538
|
-
static char*
|
539
|
-
|
540
|
-
char
|
541
|
-
char
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
h++; /* skip quote character */
|
495
|
+
static char *read_quoted_value(ParseInfo pi) {
|
496
|
+
char *value = 0;
|
497
|
+
char *h = pi->s; /* head */
|
498
|
+
char *t = h; /* tail */
|
499
|
+
uint32_t code;
|
500
|
+
|
501
|
+
h++; /* skip quote character */
|
546
502
|
t++;
|
547
503
|
value = h;
|
548
504
|
for (; '"' != *h; h++, t++) {
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
}
|
599
|
-
*t
|
505
|
+
if ('\0' == *h) {
|
506
|
+
pi->s = h;
|
507
|
+
raise_error("quoted string not terminated", pi->str, pi->s);
|
508
|
+
} else if ('\\' == *h) {
|
509
|
+
h++;
|
510
|
+
switch (*h) {
|
511
|
+
case 'n': *t = '\n'; break;
|
512
|
+
case 'r': *t = '\r'; break;
|
513
|
+
case 't': *t = '\t'; break;
|
514
|
+
case 'f': *t = '\f'; break;
|
515
|
+
case 'b': *t = '\b'; break;
|
516
|
+
case '"': *t = '"'; break;
|
517
|
+
case '/': *t = '/'; break;
|
518
|
+
case '\\': *t = '\\'; break;
|
519
|
+
case 'u':
|
520
|
+
h++;
|
521
|
+
code = read_hex(pi, h);
|
522
|
+
h += 3;
|
523
|
+
if (0x0000D800 <= code && code <= 0x0000DFFF) {
|
524
|
+
uint32_t c1 = (code - 0x0000D800) & 0x000003FF;
|
525
|
+
uint32_t c2;
|
526
|
+
|
527
|
+
h++;
|
528
|
+
if ('\\' != *h || 'u' != *(h + 1)) {
|
529
|
+
pi->s = h;
|
530
|
+
if (pi->has_error) {
|
531
|
+
call_error("invalid escaped character", pi, __FILE__, __LINE__);
|
532
|
+
}
|
533
|
+
raise_error("invalid escaped character", pi->str, pi->s);
|
534
|
+
}
|
535
|
+
h += 2;
|
536
|
+
c2 = read_hex(pi, h);
|
537
|
+
h += 3;
|
538
|
+
c2 = (c2 - 0x0000DC00) & 0x000003FF;
|
539
|
+
code = ((c1 << 10) | c2) + 0x00010000;
|
540
|
+
}
|
541
|
+
t = unicode_to_chars(pi, t, code);
|
542
|
+
break;
|
543
|
+
default:
|
544
|
+
pi->s = h;
|
545
|
+
if (pi->has_error) {
|
546
|
+
call_error("invalid escaped character", pi, __FILE__, __LINE__);
|
547
|
+
}
|
548
|
+
raise_error("invalid escaped character", pi->str, pi->s);
|
549
|
+
break;
|
550
|
+
}
|
551
|
+
} else if (t != h) {
|
552
|
+
*t = *h;
|
553
|
+
}
|
554
|
+
}
|
555
|
+
*t = '\0'; /* terminate value */
|
600
556
|
pi->s = h + 1;
|
601
557
|
|
602
558
|
return value;
|
603
559
|
}
|
604
560
|
|
605
|
-
static void
|
606
|
-
|
607
|
-
|
608
|
-
struct _parseInfo pi;
|
561
|
+
static void saj_parse(VALUE handler, char *json) {
|
562
|
+
volatile VALUE obj = Qnil;
|
563
|
+
struct _parseInfo pi;
|
609
564
|
|
610
565
|
if (0 == json) {
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
566
|
+
if (pi.has_error) {
|
567
|
+
call_error("Invalid arg, xml string can not be null", &pi, __FILE__, __LINE__);
|
568
|
+
}
|
569
|
+
raise_error("Invalid arg, xml string can not be null", json, 0);
|
615
570
|
}
|
616
571
|
/* skip UTF-8 BOM if present */
|
617
572
|
if (0xEF == (uint8_t)*json && 0xBB == (uint8_t)json[1] && 0xBF == (uint8_t)json[2]) {
|
618
|
-
|
573
|
+
json += 3;
|
619
574
|
}
|
620
575
|
/* initialize parse info */
|
621
576
|
pi.str = json;
|
622
|
-
pi.s
|
623
|
-
#if IS_WINDOWS
|
624
|
-
pi.stack_min = (void*)((char*)&obj - (
|
577
|
+
pi.s = json;
|
578
|
+
#if IS_WINDOWS || !defined(HAVE_GETRLIMIT)
|
579
|
+
pi.stack_min = (void *)((char *)&obj - (512L * 1024L)); /* assume a 1M stack and give half to ruby */
|
625
580
|
#else
|
626
581
|
{
|
627
|
-
|
582
|
+
struct rlimit lim;
|
628
583
|
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
584
|
+
if (0 == getrlimit(RLIMIT_STACK, &lim) && RLIM_INFINITY != lim.rlim_cur) {
|
585
|
+
pi.stack_min = (void *)((char *)&obj - (lim.rlim_cur / 4 * 3)); /* let 3/4ths of the stack be used only */
|
586
|
+
} else {
|
587
|
+
pi.stack_min = 0; /* indicates not to check stack limit */
|
588
|
+
}
|
634
589
|
}
|
635
590
|
#endif
|
636
|
-
pi.handler
|
637
|
-
pi.has_hash_start
|
638
|
-
pi.has_hash_end
|
591
|
+
pi.handler = handler;
|
592
|
+
pi.has_hash_start = rb_respond_to(handler, oj_hash_start_id);
|
593
|
+
pi.has_hash_end = rb_respond_to(handler, oj_hash_end_id);
|
639
594
|
pi.has_array_start = rb_respond_to(handler, oj_array_start_id);
|
640
|
-
pi.has_array_end
|
641
|
-
pi.has_add_value
|
642
|
-
pi.has_error
|
595
|
+
pi.has_array_end = rb_respond_to(handler, oj_array_end_id);
|
596
|
+
pi.has_add_value = rb_respond_to(handler, oj_add_value_id);
|
597
|
+
pi.has_error = rb_respond_to(handler, oj_error_id);
|
643
598
|
read_next(&pi, 0);
|
644
599
|
next_non_white(&pi);
|
645
600
|
if ('\0' != *pi.s) {
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
601
|
+
if (pi.has_error) {
|
602
|
+
call_error("invalid format, extra characters", &pi, __FILE__, __LINE__);
|
603
|
+
} else {
|
604
|
+
raise_error("invalid format, extra characters", pi.str, pi.s);
|
605
|
+
}
|
651
606
|
}
|
652
607
|
}
|
653
608
|
|
@@ -659,56 +614,56 @@ saj_parse(VALUE handler, char *json) {
|
|
659
614
|
* @param [IO|String] io IO Object to read from
|
660
615
|
* @deprecated The sc_parse() method along with the ScHandler is the preferred
|
661
616
|
* callback parser. It is slightly faster and handles streams while the
|
662
|
-
* saj_parse()
|
617
|
+
* saj_parse() method requires a complete read before parsing.
|
663
618
|
* @see sc_parse
|
664
619
|
*/
|
665
620
|
VALUE
|
666
621
|
oj_saj_parse(int argc, VALUE *argv, VALUE self) {
|
667
|
-
char
|
668
|
-
size_t
|
669
|
-
VALUE
|
622
|
+
char *json = 0;
|
623
|
+
size_t len = 0;
|
624
|
+
VALUE input = argv[1];
|
670
625
|
|
671
626
|
if (argc < 2) {
|
672
|
-
|
627
|
+
rb_raise(rb_eArgError, "Wrong number of arguments to saj_parse.\n");
|
673
628
|
}
|
674
629
|
if (rb_type(input) == T_STRING) {
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
630
|
+
// the json string gets modified so make a copy of it
|
631
|
+
len = RSTRING_LEN(input) + 1;
|
632
|
+
json = OJ_R_ALLOC_N(char, len);
|
633
|
+
strcpy(json, StringValuePtr(input));
|
679
634
|
} else {
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
635
|
+
VALUE clas = rb_obj_class(input);
|
636
|
+
volatile VALUE s;
|
637
|
+
|
638
|
+
if (oj_stringio_class == clas) {
|
639
|
+
s = rb_funcall2(input, oj_string_id, 0, 0);
|
640
|
+
len = RSTRING_LEN(s) + 1;
|
641
|
+
json = OJ_R_ALLOC_N(char, len);
|
642
|
+
strcpy(json, StringValueCStr(s));
|
688
643
|
#if !IS_WINDOWS
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
644
|
+
} else if (rb_cFile == clas && 0 == FIX2INT(rb_funcall(input, oj_pos_id, 0))) {
|
645
|
+
int fd = FIX2INT(rb_funcall(input, oj_fileno_id, 0));
|
646
|
+
ssize_t cnt;
|
647
|
+
|
648
|
+
len = lseek(fd, 0, SEEK_END);
|
649
|
+
lseek(fd, 0, SEEK_SET);
|
650
|
+
json = OJ_R_ALLOC_N(char, len + 1);
|
651
|
+
if (0 >= (cnt = read(fd, json, len)) || cnt != (ssize_t)len) {
|
652
|
+
rb_raise(rb_eIOError, "failed to read from IO Object.");
|
653
|
+
}
|
654
|
+
json[len] = '\0';
|
700
655
|
#endif
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
656
|
+
} else if (rb_respond_to(input, oj_read_id)) {
|
657
|
+
s = rb_funcall2(input, oj_read_id, 0, 0);
|
658
|
+
len = RSTRING_LEN(s) + 1;
|
659
|
+
json = OJ_R_ALLOC_N(char, len);
|
660
|
+
strcpy(json, StringValueCStr(s));
|
661
|
+
} else {
|
662
|
+
rb_raise(rb_eArgError, "saj_parse() expected a String or IO Object.");
|
663
|
+
}
|
709
664
|
}
|
710
665
|
saj_parse(*argv, json);
|
711
|
-
|
666
|
+
OJ_R_FREE(json);
|
712
667
|
|
713
668
|
return Qnil;
|
714
669
|
}
|