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