oj 3.10.6 → 3.12.0
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/README.md +6 -1
- data/ext/oj/buf.h +36 -68
- data/ext/oj/cache8.c +59 -62
- data/ext/oj/cache8.h +9 -36
- data/ext/oj/circarray.c +36 -42
- data/ext/oj/circarray.h +12 -13
- data/ext/oj/code.c +172 -179
- data/ext/oj/code.h +22 -24
- data/ext/oj/compat.c +168 -181
- data/ext/oj/custom.c +800 -864
- data/ext/oj/dump.c +774 -776
- data/ext/oj/dump.h +50 -55
- data/ext/oj/dump_compat.c +2 -4
- data/ext/oj/dump_leaf.c +118 -162
- data/ext/oj/dump_object.c +610 -632
- data/ext/oj/dump_strict.c +319 -331
- data/ext/oj/encode.h +4 -33
- data/ext/oj/err.c +40 -29
- data/ext/oj/err.h +25 -44
- data/ext/oj/extconf.rb +2 -1
- data/ext/oj/fast.c +1054 -1081
- data/ext/oj/hash.c +78 -95
- data/ext/oj/hash.h +10 -35
- data/ext/oj/hash_test.c +451 -472
- data/ext/oj/mimic_json.c +415 -402
- data/ext/oj/object.c +588 -532
- data/ext/oj/odd.c +124 -132
- data/ext/oj/odd.h +28 -29
- data/ext/oj/oj.c +1178 -905
- data/ext/oj/oj.h +289 -298
- data/ext/oj/parse.c +946 -870
- data/ext/oj/parse.h +81 -79
- data/ext/oj/rails.c +837 -842
- data/ext/oj/rails.h +8 -11
- data/ext/oj/reader.c +139 -147
- data/ext/oj/reader.h +68 -84
- data/ext/oj/resolve.c +44 -47
- data/ext/oj/resolve.h +4 -6
- data/ext/oj/rxclass.c +69 -73
- data/ext/oj/rxclass.h +13 -14
- data/ext/oj/saj.c +453 -484
- data/ext/oj/scp.c +88 -113
- data/ext/oj/sparse.c +783 -714
- data/ext/oj/stream_writer.c +123 -157
- data/ext/oj/strict.c +133 -106
- data/ext/oj/string_writer.c +199 -247
- data/ext/oj/trace.c +34 -41
- data/ext/oj/trace.h +15 -15
- data/ext/oj/util.c +104 -104
- data/ext/oj/util.h +4 -3
- data/ext/oj/val_stack.c +48 -76
- data/ext/oj/val_stack.h +80 -115
- data/ext/oj/wab.c +317 -328
- data/lib/oj.rb +0 -8
- data/lib/oj/bag.rb +1 -0
- data/lib/oj/easy_hash.rb +5 -4
- data/lib/oj/mimic.rb +45 -13
- data/lib/oj/version.rb +1 -1
- data/pages/Modes.md +1 -0
- data/pages/Options.md +23 -11
- data/test/activerecord/result_test.rb +7 -2
- data/test/foo.rb +8 -40
- data/test/helper.rb +10 -0
- data/test/json_gem/json_common_interface_test.rb +8 -3
- data/test/json_gem/json_generator_test.rb +15 -3
- data/test/json_gem/test_helper.rb +8 -0
- data/test/perf.rb +1 -1
- data/test/perf_scp.rb +11 -10
- data/test/perf_strict.rb +17 -23
- data/test/prec.rb +23 -0
- data/test/sample_json.rb +1 -1
- data/test/test_compat.rb +16 -3
- data/test/test_custom.rb +11 -0
- data/test/test_fast.rb +32 -2
- data/test/test_generate.rb +21 -0
- data/test/test_hash.rb +10 -0
- data/test/test_rails.rb +9 -0
- data/test/test_scp.rb +1 -1
- data/test/test_various.rb +4 -2
- metadata +89 -85
data/ext/oj/object.c
CHANGED
@@ -1,414 +1,425 @@
|
|
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
|
#include <stdint.h>
|
7
5
|
#include <stdio.h>
|
8
6
|
#include <time.h>
|
9
7
|
|
10
|
-
#include "
|
8
|
+
#include "encode.h"
|
11
9
|
#include "err.h"
|
12
|
-
#include "parse.h"
|
13
|
-
#include "resolve.h"
|
14
10
|
#include "hash.h"
|
15
11
|
#include "odd.h"
|
16
|
-
#include "
|
12
|
+
#include "oj.h"
|
13
|
+
#include "parse.h"
|
14
|
+
#include "resolve.h"
|
17
15
|
#include "trace.h"
|
18
16
|
#include "util.h"
|
19
17
|
|
20
|
-
inline static long
|
21
|
-
|
22
|
-
long n = 0;
|
18
|
+
inline static long read_long(const char *str, size_t len) {
|
19
|
+
long n = 0;
|
23
20
|
|
24
21
|
for (; 0 < len; str++, len--) {
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
22
|
+
if ('0' <= *str && *str <= '9') {
|
23
|
+
n = n * 10 + (*str - '0');
|
24
|
+
} else {
|
25
|
+
return -1;
|
26
|
+
}
|
30
27
|
}
|
31
28
|
return n;
|
32
29
|
}
|
33
30
|
|
34
|
-
static VALUE
|
35
|
-
|
36
|
-
|
31
|
+
static VALUE calc_hash_key(ParseInfo pi, Val kval, char k1) {
|
32
|
+
volatile VALUE rkey;
|
33
|
+
#if 0
|
34
|
+
VALUE *slot;
|
37
35
|
|
38
36
|
if (':' == k1) {
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
if (Qnil == (rkey = oj_sym_hash_get(kval->key + 1, kval->klen - 1, &slot))) {
|
38
|
+
rkey = rb_str_new(kval->key + 1, kval->klen - 1);
|
39
|
+
rkey = oj_encode(rkey);
|
40
|
+
rkey = rb_str_intern(rkey);
|
41
|
+
*slot = rkey;
|
42
|
+
rb_gc_register_address(slot);
|
43
|
+
}
|
44
|
+
} else if (Yes == pi->options.sym_key) {
|
45
|
+
if (Qnil == (rkey = oj_sym_hash_get(kval->key, kval->klen, &slot))) {
|
46
|
+
rkey = rb_str_new(kval->key, kval->klen);
|
47
|
+
rkey = oj_encode(rkey);
|
48
|
+
rkey = rb_str_intern(rkey);
|
49
|
+
*slot = rkey;
|
50
|
+
rb_gc_register_address(slot);
|
51
|
+
}
|
52
|
+
} else {
|
53
|
+
if (Qnil == (rkey = oj_str_hash_get(kval->key, kval->klen, &slot))) {
|
54
|
+
rkey = rb_str_new(kval->key, kval->klen);
|
55
|
+
rkey = oj_encode(rkey);
|
56
|
+
*slot = rkey;
|
57
|
+
rb_gc_register_address(slot);
|
58
|
+
}
|
59
|
+
}
|
60
|
+
#else
|
61
|
+
if (':' == k1) {
|
62
|
+
rkey = rb_str_new(kval->key + 1, kval->klen - 1);
|
63
|
+
rkey = oj_encode(rkey);
|
64
|
+
rkey = rb_str_intern(rkey);
|
42
65
|
} else {
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
66
|
+
rkey = rb_str_new(kval->key, kval->klen);
|
67
|
+
rkey = oj_encode(rkey);
|
68
|
+
if (Yes == pi->options.sym_key) {
|
69
|
+
rkey = rb_str_intern(rkey);
|
70
|
+
}
|
48
71
|
}
|
72
|
+
#endif
|
49
73
|
return rkey;
|
50
74
|
}
|
51
75
|
|
52
|
-
static VALUE
|
53
|
-
|
54
|
-
volatile VALUE rstr = Qnil;
|
76
|
+
static VALUE str_to_value(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
77
|
+
volatile VALUE rstr = Qnil;
|
55
78
|
|
56
79
|
if (':' == *orig && 0 < len) {
|
57
|
-
|
58
|
-
|
59
|
-
|
80
|
+
rstr = rb_str_new(str + 1, len - 1);
|
81
|
+
rstr = oj_encode(rstr);
|
82
|
+
rstr = rb_funcall(rstr, oj_to_sym_id, 0);
|
60
83
|
} else if (pi->circ_array && 3 <= len && '^' == *orig && 'r' == orig[1]) {
|
61
|
-
|
84
|
+
long i = read_long(str + 2, len - 2);
|
62
85
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
86
|
+
if (0 > i) {
|
87
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a valid ID number");
|
88
|
+
return Qnil;
|
89
|
+
}
|
90
|
+
rstr = oj_circ_array_get(pi->circ_array, i);
|
68
91
|
} else {
|
69
|
-
|
70
|
-
|
92
|
+
rstr = rb_str_new(str, len);
|
93
|
+
rstr = oj_encode(rstr);
|
71
94
|
}
|
72
95
|
return rstr;
|
73
96
|
}
|
74
97
|
|
75
98
|
#if (RUBY_VERSION_MAJOR == 1 && RUBY_VERSION_MINOR == 8)
|
76
|
-
static VALUE
|
77
|
-
oj_parse_xml_time(const char *str, int len) {
|
99
|
+
static VALUE oj_parse_xml_time(const char *str, int len) {
|
78
100
|
return rb_funcall(rb_cTime, oj_parse_id, 1, rb_str_new(str, len));
|
79
101
|
}
|
80
102
|
#else
|
81
103
|
// The much faster approach (4x faster)
|
82
|
-
static int
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
int i;
|
104
|
+
static int parse_num(const char *str, const char *end, int cnt) {
|
105
|
+
int n = 0;
|
106
|
+
char c;
|
107
|
+
int i;
|
87
108
|
|
88
109
|
for (i = cnt; 0 < i; i--, str++) {
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
110
|
+
c = *str;
|
111
|
+
if (end <= str || c < '0' || '9' < c) {
|
112
|
+
return -1;
|
113
|
+
}
|
114
|
+
n = n * 10 + (c - '0');
|
94
115
|
}
|
95
116
|
return n;
|
96
117
|
}
|
97
118
|
|
98
119
|
VALUE
|
99
120
|
oj_parse_xml_time(const char *str, int len) {
|
100
|
-
VALUE
|
101
|
-
const char
|
102
|
-
int
|
121
|
+
VALUE args[8];
|
122
|
+
const char *end = str + len;
|
123
|
+
int n;
|
103
124
|
|
104
125
|
// year
|
105
126
|
if (0 > (n = parse_num(str, end, 4))) {
|
106
|
-
|
127
|
+
return Qnil;
|
107
128
|
}
|
108
129
|
str += 4;
|
109
130
|
args[0] = LONG2NUM(n);
|
110
131
|
if ('-' != *str++) {
|
111
|
-
|
132
|
+
return Qnil;
|
112
133
|
}
|
113
134
|
// month
|
114
135
|
if (0 > (n = parse_num(str, end, 2))) {
|
115
|
-
|
136
|
+
return Qnil;
|
116
137
|
}
|
117
138
|
str += 2;
|
118
139
|
args[1] = LONG2NUM(n);
|
119
140
|
if ('-' != *str++) {
|
120
|
-
|
141
|
+
return Qnil;
|
121
142
|
}
|
122
143
|
// day
|
123
144
|
if (0 > (n = parse_num(str, end, 2))) {
|
124
|
-
|
145
|
+
return Qnil;
|
125
146
|
}
|
126
147
|
str += 2;
|
127
148
|
args[2] = LONG2NUM(n);
|
128
149
|
if ('T' != *str++) {
|
129
|
-
|
150
|
+
return Qnil;
|
130
151
|
}
|
131
152
|
// hour
|
132
153
|
if (0 > (n = parse_num(str, end, 2))) {
|
133
|
-
|
154
|
+
return Qnil;
|
134
155
|
}
|
135
156
|
str += 2;
|
136
157
|
args[3] = LONG2NUM(n);
|
137
158
|
if (':' != *str++) {
|
138
|
-
|
159
|
+
return Qnil;
|
139
160
|
}
|
140
161
|
// minute
|
141
162
|
if (0 > (n = parse_num(str, end, 2))) {
|
142
|
-
|
163
|
+
return Qnil;
|
143
164
|
}
|
144
165
|
str += 2;
|
145
166
|
args[4] = LONG2NUM(n);
|
146
167
|
if (':' != *str++) {
|
147
|
-
|
168
|
+
return Qnil;
|
148
169
|
}
|
149
170
|
// second
|
150
171
|
if (0 > (n = parse_num(str, end, 2))) {
|
151
|
-
|
172
|
+
return Qnil;
|
152
173
|
}
|
153
174
|
str += 2;
|
154
175
|
if (str == end) {
|
155
|
-
|
156
|
-
|
176
|
+
args[5] = LONG2NUM(n);
|
177
|
+
args[6] = LONG2NUM(0);
|
157
178
|
} else {
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
179
|
+
char c = *str++;
|
180
|
+
|
181
|
+
if ('.' == c) {
|
182
|
+
long long nsec = 0;
|
183
|
+
|
184
|
+
for (; str < end; str++) {
|
185
|
+
c = *str;
|
186
|
+
if (c < '0' || '9' < c) {
|
187
|
+
str++;
|
188
|
+
break;
|
189
|
+
}
|
190
|
+
nsec = nsec * 10 + (c - '0');
|
191
|
+
}
|
192
|
+
args[5] = rb_float_new((double)n + ((double)nsec + 0.5) / 1000000000.0);
|
193
|
+
} else {
|
194
|
+
args[5] = rb_ll2inum(n);
|
195
|
+
}
|
196
|
+
if (end < str) {
|
197
|
+
args[6] = LONG2NUM(0);
|
198
|
+
} else {
|
199
|
+
if ('Z' == c) {
|
200
|
+
return rb_funcall2(rb_cTime, oj_utc_id, 6, args);
|
201
|
+
} else if ('+' == c) {
|
202
|
+
int hr = parse_num(str, end, 2);
|
203
|
+
int min;
|
204
|
+
|
205
|
+
str += 2;
|
206
|
+
if (0 > hr || ':' != *str++) {
|
207
|
+
return Qnil;
|
208
|
+
}
|
209
|
+
min = parse_num(str, end, 2);
|
210
|
+
if (0 > min) {
|
211
|
+
return Qnil;
|
212
|
+
}
|
213
|
+
args[6] = LONG2NUM(hr * 3600 + min * 60);
|
214
|
+
} else if ('-' == c) {
|
215
|
+
int hr = parse_num(str, end, 2);
|
216
|
+
int min;
|
217
|
+
|
218
|
+
str += 2;
|
219
|
+
if (0 > hr || ':' != *str++) {
|
220
|
+
return Qnil;
|
221
|
+
}
|
222
|
+
min = parse_num(str, end, 2);
|
223
|
+
if (0 > min) {
|
224
|
+
return Qnil;
|
225
|
+
}
|
226
|
+
args[6] = LONG2NUM(-(hr * 3600 + min * 60));
|
227
|
+
} else {
|
228
|
+
args[6] = LONG2NUM(0);
|
229
|
+
}
|
230
|
+
}
|
210
231
|
}
|
211
232
|
return rb_funcall2(rb_cTime, oj_new_id, 7, args);
|
212
233
|
}
|
213
234
|
#endif
|
214
235
|
|
215
|
-
static int
|
216
|
-
|
217
|
-
|
218
|
-
int klen = kval->klen;
|
236
|
+
static int hat_cstr(ParseInfo pi, Val parent, Val kval, const char *str, size_t len) {
|
237
|
+
const char *key = kval->key;
|
238
|
+
int klen = kval->klen;
|
219
239
|
|
220
240
|
if (2 == klen) {
|
221
|
-
|
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
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
default:
|
266
|
-
return 0;
|
267
|
-
break;
|
268
|
-
}
|
269
|
-
return 1; // handled
|
241
|
+
switch (key[1]) {
|
242
|
+
case 'o': // object
|
243
|
+
{ // name2class sets an error if the class is not found or created
|
244
|
+
VALUE clas = oj_name2class(pi, str, len, Yes == pi->options.auto_define, rb_eArgError);
|
245
|
+
|
246
|
+
if (Qundef != clas) {
|
247
|
+
parent->val = rb_obj_alloc(clas);
|
248
|
+
}
|
249
|
+
} break;
|
250
|
+
case 'O': // odd object
|
251
|
+
{
|
252
|
+
Odd odd = oj_get_oddc(str, len);
|
253
|
+
|
254
|
+
if (0 == odd) {
|
255
|
+
return 0;
|
256
|
+
}
|
257
|
+
parent->val = odd->clas;
|
258
|
+
parent->odd_args = oj_odd_alloc_args(odd);
|
259
|
+
} break;
|
260
|
+
case 'm':
|
261
|
+
parent->val = rb_str_new(str + 1, len - 1);
|
262
|
+
parent->val = oj_encode(parent->val);
|
263
|
+
parent->val = rb_funcall(parent->val, oj_to_sym_id, 0);
|
264
|
+
break;
|
265
|
+
case 's':
|
266
|
+
parent->val = rb_str_new(str, len);
|
267
|
+
parent->val = oj_encode(parent->val);
|
268
|
+
break;
|
269
|
+
case 'c': // class
|
270
|
+
{
|
271
|
+
VALUE clas = oj_name2class(pi, str, len, Yes == pi->options.auto_define, rb_eArgError);
|
272
|
+
|
273
|
+
if (Qundef == clas) {
|
274
|
+
return 0;
|
275
|
+
} else {
|
276
|
+
parent->val = clas;
|
277
|
+
}
|
278
|
+
} break;
|
279
|
+
case 't': // time
|
280
|
+
parent->val = oj_parse_xml_time(str, (int)len);
|
281
|
+
break;
|
282
|
+
default: return 0; break;
|
283
|
+
}
|
284
|
+
return 1; // handled
|
270
285
|
}
|
271
286
|
return 0;
|
272
287
|
}
|
273
288
|
|
274
|
-
static int
|
275
|
-
hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) {
|
289
|
+
static int hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) {
|
276
290
|
if (2 == kval->klen) {
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
return 1; // handled
|
291
|
+
switch (kval->key[1]) {
|
292
|
+
case 't': // time as a float
|
293
|
+
if (0 == ni->div || 9 < ni->di) {
|
294
|
+
rb_raise(rb_eArgError, "Invalid time decimal representation.");
|
295
|
+
// parent->val = rb_time_nano_new(0, 0);
|
296
|
+
} else {
|
297
|
+
int64_t nsec = ni->num * 1000000000LL / ni->div;
|
298
|
+
|
299
|
+
if (ni->neg) {
|
300
|
+
ni->i = -ni->i;
|
301
|
+
if (0 < nsec) {
|
302
|
+
ni->i--;
|
303
|
+
nsec = 1000000000LL - nsec;
|
304
|
+
}
|
305
|
+
}
|
306
|
+
if (86400 == ni->exp) { // UTC time
|
307
|
+
parent->val = rb_time_nano_new(ni->i, (long)nsec);
|
308
|
+
// Since the ruby C routines alway create local time, the
|
309
|
+
// offset and then a conversion to UTC keeps makes the time
|
310
|
+
// match the expected value.
|
311
|
+
parent->val = rb_funcall2(parent->val, oj_utc_id, 0, 0);
|
312
|
+
} else if (ni->has_exp) {
|
313
|
+
int64_t t = (int64_t)(ni->i + ni->exp);
|
314
|
+
struct _timeInfo ti;
|
315
|
+
VALUE args[8];
|
316
|
+
|
317
|
+
sec_as_time(t, &ti);
|
318
|
+
args[0] = LONG2NUM((long)(ti.year));
|
319
|
+
args[1] = LONG2NUM(ti.mon);
|
320
|
+
args[2] = LONG2NUM(ti.day);
|
321
|
+
args[3] = LONG2NUM(ti.hour);
|
322
|
+
args[4] = LONG2NUM(ti.min);
|
323
|
+
args[5] = rb_float_new((double)ti.sec + ((double)nsec + 0.5) / 1000000000.0);
|
324
|
+
args[6] = LONG2NUM(ni->exp);
|
325
|
+
parent->val = rb_funcall2(rb_cTime, oj_new_id, 7, args);
|
326
|
+
} else {
|
327
|
+
parent->val = rb_time_nano_new(ni->i, (long)nsec);
|
328
|
+
}
|
329
|
+
}
|
330
|
+
break;
|
331
|
+
case 'i': // circular index
|
332
|
+
if (!ni->infinity && !ni->neg && 1 == ni->div && 0 == ni->exp &&
|
333
|
+
0 != pi->circ_array) { // fixnum
|
334
|
+
if (Qnil == parent->val) {
|
335
|
+
parent->val = rb_hash_new();
|
336
|
+
}
|
337
|
+
oj_circ_array_set(pi->circ_array, parent->val, ni->i);
|
338
|
+
} else {
|
339
|
+
return 0;
|
340
|
+
}
|
341
|
+
break;
|
342
|
+
default: return 0; break;
|
343
|
+
}
|
344
|
+
return 1; // handled
|
332
345
|
}
|
333
346
|
return 0;
|
334
347
|
}
|
335
348
|
|
336
|
-
static int
|
337
|
-
hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, volatile VALUE value) {
|
349
|
+
static int hat_value(ParseInfo pi, Val parent, const char *key, size_t klen, volatile VALUE value) {
|
338
350
|
if (T_ARRAY == rb_type(value)) {
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
volatile VALUE
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
351
|
+
int len = (int)RARRAY_LEN(value);
|
352
|
+
|
353
|
+
if (2 == klen && 'u' == key[1]) {
|
354
|
+
volatile VALUE sc;
|
355
|
+
volatile VALUE e1;
|
356
|
+
int slen;
|
357
|
+
|
358
|
+
if (0 == len) {
|
359
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Invalid struct data");
|
360
|
+
return 1;
|
361
|
+
}
|
362
|
+
e1 = *RARRAY_PTR(value);
|
363
|
+
// check for anonymous Struct
|
364
|
+
if (T_ARRAY == rb_type(e1)) {
|
365
|
+
VALUE args[1024];
|
366
|
+
volatile VALUE rstr;
|
367
|
+
int i, cnt = (int)RARRAY_LEN(e1);
|
368
|
+
|
369
|
+
for (i = 0; i < cnt; i++) {
|
370
|
+
rstr = rb_ary_entry(e1, i);
|
371
|
+
args[i] = rb_funcall(rstr, oj_to_sym_id, 0);
|
372
|
+
}
|
373
|
+
sc = rb_funcall2(rb_cStruct, oj_new_id, cnt, args);
|
374
|
+
} else {
|
375
|
+
// If struct is not defined then we let this fail and raise an exception.
|
376
|
+
sc = oj_name2struct(pi, *RARRAY_PTR(value), rb_eArgError);
|
377
|
+
}
|
366
378
|
// Create a properly initialized struct instance without calling the initialize method.
|
367
379
|
parent->val = rb_obj_alloc(sc);
|
368
380
|
// If the JSON array has more entries than the struct class allows, we record an error.
|
369
381
|
#ifdef RSTRUCT_LEN
|
370
382
|
#if RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
|
371
|
-
|
372
|
-
#else
|
373
|
-
|
374
|
-
#endif
|
383
|
+
slen = (int)NUM2LONG(RSTRUCT_LEN(parent->val));
|
384
|
+
#else // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
|
385
|
+
slen = (int)RSTRUCT_LEN(parent->val);
|
386
|
+
#endif // RSTRUCT_LEN_RETURNS_INTEGER_OBJECT
|
375
387
|
#else
|
376
|
-
|
388
|
+
slen = FIX2INT(rb_funcall2(parent->val, oj_length_id, 0, 0));
|
377
389
|
#endif
|
378
390
|
// MRI >= 1.9
|
379
391
|
if (len - 1 > slen) {
|
380
|
-
|
392
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "Invalid struct data");
|
381
393
|
} else {
|
382
|
-
|
394
|
+
int i;
|
383
395
|
|
384
|
-
|
385
|
-
|
386
|
-
|
396
|
+
for (i = 0; i < len - 1; i++) {
|
397
|
+
rb_struct_aset(parent->val, INT2FIX(i), RARRAY_PTR(value)[i + 1]);
|
398
|
+
}
|
387
399
|
}
|
388
|
-
|
389
|
-
|
390
|
-
|
400
|
+
return 1;
|
401
|
+
} else if (3 <= klen && '#' == key[1]) {
|
402
|
+
volatile VALUE *a;
|
391
403
|
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
404
|
+
if (2 != len) {
|
405
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hash pair");
|
406
|
+
return 1;
|
407
|
+
}
|
408
|
+
parent->val = rb_hash_new();
|
409
|
+
a = RARRAY_PTR(value);
|
410
|
+
rb_hash_aset(parent->val, *a, a[1]);
|
399
411
|
|
400
|
-
|
401
|
-
|
412
|
+
return 1;
|
413
|
+
}
|
402
414
|
}
|
403
415
|
return 0;
|
404
416
|
}
|
405
417
|
|
406
|
-
void
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
ID
|
411
|
-
ID *slot;
|
418
|
+
void oj_set_obj_ivar(Val parent, Val kval, VALUE value) {
|
419
|
+
const char *key = kval->key;
|
420
|
+
int klen = kval->klen;
|
421
|
+
ID var_id;
|
422
|
+
ID * slot;
|
412
423
|
|
413
424
|
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
414
425
|
pthread_mutex_lock(&oj_cache_mutex);
|
@@ -416,33 +427,33 @@ oj_set_obj_ivar(Val parent, Val kval, VALUE value) {
|
|
416
427
|
rb_mutex_lock(oj_cache_mutex);
|
417
428
|
#endif
|
418
429
|
if (0 == (var_id = oj_attr_hash_get(key, klen, &slot))) {
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
430
|
+
char attr[256];
|
431
|
+
|
432
|
+
if ((int)sizeof(attr) <= klen + 2) {
|
433
|
+
char *buf = ALLOC_N(char, klen + 2);
|
434
|
+
|
435
|
+
if ('~' == *key) {
|
436
|
+
strncpy(buf, key + 1, klen - 1);
|
437
|
+
buf[klen - 1] = '\0';
|
438
|
+
} else {
|
439
|
+
*buf = '@';
|
440
|
+
strncpy(buf + 1, key, klen);
|
441
|
+
buf[klen + 1] = '\0';
|
442
|
+
}
|
443
|
+
var_id = rb_intern(buf);
|
444
|
+
xfree(buf);
|
445
|
+
} else {
|
446
|
+
if ('~' == *key) {
|
447
|
+
strncpy(attr, key + 1, klen - 1);
|
448
|
+
attr[klen - 1] = '\0';
|
449
|
+
} else {
|
450
|
+
*attr = '@';
|
451
|
+
strncpy(attr + 1, key, klen);
|
452
|
+
attr[klen + 1] = '\0';
|
453
|
+
}
|
454
|
+
var_id = rb_intern(attr);
|
455
|
+
}
|
456
|
+
*slot = var_id;
|
446
457
|
}
|
447
458
|
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
448
459
|
pthread_mutex_unlock(&oj_cache_mutex);
|
@@ -452,324 +463,369 @@ oj_set_obj_ivar(Val parent, Val kval, VALUE value) {
|
|
452
463
|
rb_ivar_set(parent->val, var_id, value);
|
453
464
|
}
|
454
465
|
|
455
|
-
static void
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
volatile VALUE rval = Qnil;
|
466
|
+
static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
|
467
|
+
const char * key = kval->key;
|
468
|
+
int klen = kval->klen;
|
469
|
+
Val parent = stack_peek(&pi->stack);
|
470
|
+
volatile VALUE rval = Qnil;
|
461
471
|
|
462
|
-
|
472
|
+
WHICH_TYPE:
|
463
473
|
switch (rb_type(parent->val)) {
|
464
474
|
case T_NIL:
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
475
|
+
parent->odd_args = NULL; // make sure it is NULL in case not odd
|
476
|
+
if ('^' != *key || !hat_cstr(pi, parent, kval, str, len)) {
|
477
|
+
parent->val = rb_hash_new();
|
478
|
+
goto WHICH_TYPE;
|
479
|
+
}
|
480
|
+
break;
|
471
481
|
case T_HASH:
|
472
|
-
|
473
|
-
|
482
|
+
rb_hash_aset(parent->val,
|
483
|
+
calc_hash_key(pi, kval, parent->k1),
|
484
|
+
str_to_value(pi, str, len, orig));
|
485
|
+
break;
|
474
486
|
case T_STRING:
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
487
|
+
rval = str_to_value(pi, str, len, orig);
|
488
|
+
if (4 == klen && 's' == *key && 'e' == key[1] && 'l' == key[2] && 'f' == key[3]) {
|
489
|
+
rb_funcall(parent->val, oj_replace_id, 1, rval);
|
490
|
+
} else {
|
491
|
+
oj_set_obj_ivar(parent, kval, rval);
|
492
|
+
}
|
493
|
+
break;
|
482
494
|
case T_OBJECT:
|
483
|
-
|
484
|
-
|
485
|
-
|
495
|
+
rval = str_to_value(pi, str, len, orig);
|
496
|
+
oj_set_obj_ivar(parent, kval, rval);
|
497
|
+
break;
|
486
498
|
case T_CLASS:
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
499
|
+
if (NULL == parent->odd_args) {
|
500
|
+
oj_set_error_at(pi,
|
501
|
+
oj_parse_error_class,
|
502
|
+
__FILE__,
|
503
|
+
__LINE__,
|
504
|
+
"%s is not an odd class",
|
505
|
+
rb_class2name(rb_obj_class(parent->val)));
|
506
|
+
return;
|
507
|
+
} else {
|
508
|
+
rval = str_to_value(pi, str, len, orig);
|
509
|
+
if (0 != oj_odd_set_arg(parent->odd_args, kval->key, kval->klen, rval)) {
|
510
|
+
char buf[256];
|
511
|
+
|
512
|
+
if ((int)sizeof(buf) - 1 <= klen) {
|
513
|
+
klen = sizeof(buf) - 2;
|
514
|
+
}
|
515
|
+
memcpy(buf, key, klen);
|
516
|
+
buf[klen] = '\0';
|
517
|
+
oj_set_error_at(pi,
|
518
|
+
oj_parse_error_class,
|
519
|
+
__FILE__,
|
520
|
+
__LINE__,
|
521
|
+
"%s is not an attribute of %s",
|
522
|
+
buf,
|
523
|
+
rb_class2name(rb_obj_class(parent->val)));
|
524
|
+
}
|
525
|
+
}
|
526
|
+
break;
|
504
527
|
default:
|
505
|
-
|
506
|
-
|
528
|
+
oj_set_error_at(pi,
|
529
|
+
oj_parse_error_class,
|
530
|
+
__FILE__,
|
531
|
+
__LINE__,
|
532
|
+
"can not add attributes to a %s",
|
533
|
+
rb_class2name(rb_obj_class(parent->val)));
|
534
|
+
return;
|
507
535
|
}
|
508
536
|
if (Yes == pi->options.trace) {
|
509
|
-
|
537
|
+
oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
|
510
538
|
}
|
511
539
|
}
|
512
540
|
|
513
|
-
static void
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
volatile VALUE rval = Qnil;
|
541
|
+
static void hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
|
542
|
+
const char * key = kval->key;
|
543
|
+
int klen = kval->klen;
|
544
|
+
Val parent = stack_peek(&pi->stack);
|
545
|
+
volatile VALUE rval = Qnil;
|
519
546
|
|
520
|
-
|
547
|
+
WHICH_TYPE:
|
521
548
|
switch (rb_type(parent->val)) {
|
522
549
|
case T_NIL:
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
550
|
+
parent->odd_args = NULL; // make sure it is NULL in case not odd
|
551
|
+
if ('^' != *key || !hat_num(pi, parent, kval, ni)) {
|
552
|
+
parent->val = rb_hash_new();
|
553
|
+
goto WHICH_TYPE;
|
554
|
+
}
|
555
|
+
break;
|
529
556
|
case T_HASH:
|
530
|
-
|
531
|
-
|
532
|
-
|
557
|
+
rval = oj_num_as_value(ni);
|
558
|
+
rb_hash_aset(parent->val, calc_hash_key(pi, kval, parent->k1), rval);
|
559
|
+
break;
|
533
560
|
case T_OBJECT:
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
561
|
+
if (2 == klen && '^' == *key && 'i' == key[1] && !ni->infinity && !ni->neg &&
|
562
|
+
1 == ni->div && 0 == ni->exp && 0 != pi->circ_array) { // fixnum
|
563
|
+
oj_circ_array_set(pi->circ_array, parent->val, ni->i);
|
564
|
+
} else {
|
565
|
+
rval = oj_num_as_value(ni);
|
566
|
+
oj_set_obj_ivar(parent, kval, rval);
|
567
|
+
}
|
568
|
+
break;
|
542
569
|
case T_CLASS:
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
570
|
+
if (NULL == parent->odd_args) {
|
571
|
+
oj_set_error_at(pi,
|
572
|
+
oj_parse_error_class,
|
573
|
+
__FILE__,
|
574
|
+
__LINE__,
|
575
|
+
"%s is not an odd class",
|
576
|
+
rb_class2name(rb_obj_class(parent->val)));
|
577
|
+
return;
|
578
|
+
} else {
|
579
|
+
rval = oj_num_as_value(ni);
|
580
|
+
if (0 != oj_odd_set_arg(parent->odd_args, key, klen, rval)) {
|
581
|
+
char buf[256];
|
582
|
+
|
583
|
+
if ((int)sizeof(buf) - 1 <= klen) {
|
584
|
+
klen = sizeof(buf) - 2;
|
585
|
+
}
|
586
|
+
memcpy(buf, key, klen);
|
587
|
+
buf[klen] = '\0';
|
588
|
+
oj_set_error_at(pi,
|
589
|
+
oj_parse_error_class,
|
590
|
+
__FILE__,
|
591
|
+
__LINE__,
|
592
|
+
"%s is not an attribute of %s",
|
593
|
+
buf,
|
594
|
+
rb_class2name(rb_obj_class(parent->val)));
|
595
|
+
}
|
596
|
+
}
|
597
|
+
break;
|
560
598
|
default:
|
561
|
-
|
562
|
-
|
599
|
+
oj_set_error_at(pi,
|
600
|
+
oj_parse_error_class,
|
601
|
+
__FILE__,
|
602
|
+
__LINE__,
|
603
|
+
"can not add attributes to a %s",
|
604
|
+
rb_class2name(rb_obj_class(parent->val)));
|
605
|
+
return;
|
563
606
|
}
|
564
607
|
if (Yes == pi->options.trace) {
|
565
|
-
|
608
|
+
oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, rval);
|
566
609
|
}
|
567
610
|
}
|
568
611
|
|
569
|
-
static void
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
Val parent = stack_peek(&pi->stack);
|
612
|
+
static void hash_set_value(ParseInfo pi, Val kval, VALUE value) {
|
613
|
+
const char *key = kval->key;
|
614
|
+
int klen = kval->klen;
|
615
|
+
Val parent = stack_peek(&pi->stack);
|
574
616
|
|
575
|
-
|
617
|
+
WHICH_TYPE:
|
576
618
|
switch (rb_type(parent->val)) {
|
577
619
|
case T_NIL:
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
620
|
+
parent->odd_args = NULL; // make sure it is NULL in case not odd
|
621
|
+
if ('^' != *key || !hat_value(pi, parent, key, klen, value)) {
|
622
|
+
parent->val = rb_hash_new();
|
623
|
+
goto WHICH_TYPE;
|
624
|
+
}
|
625
|
+
break;
|
584
626
|
case T_HASH:
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
627
|
+
if (rb_cHash != rb_obj_class(parent->val)) {
|
628
|
+
if (4 == klen && 's' == *key && 'e' == key[1] && 'l' == key[2] && 'f' == key[3]) {
|
629
|
+
rb_funcall(parent->val, oj_replace_id, 1, value);
|
630
|
+
} else {
|
631
|
+
oj_set_obj_ivar(parent, kval, value);
|
632
|
+
}
|
633
|
+
} else {
|
634
|
+
if (3 <= klen && '^' == *key && '#' == key[1] && T_ARRAY == rb_type(value)) {
|
635
|
+
long len = RARRAY_LEN(value);
|
636
|
+
volatile VALUE *a = RARRAY_PTR(value);
|
637
|
+
|
638
|
+
if (2 != len) {
|
639
|
+
oj_set_error_at(pi,
|
640
|
+
oj_parse_error_class,
|
641
|
+
__FILE__,
|
642
|
+
__LINE__,
|
643
|
+
"invalid hash pair");
|
644
|
+
return;
|
645
|
+
}
|
646
|
+
rb_hash_aset(parent->val, *a, a[1]);
|
647
|
+
} else {
|
648
|
+
rb_hash_aset(parent->val, calc_hash_key(pi, kval, parent->k1), value);
|
649
|
+
}
|
650
|
+
}
|
651
|
+
break;
|
606
652
|
case T_ARRAY:
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
case T_STRING:
|
614
|
-
case T_OBJECT:
|
615
|
-
oj_set_obj_ivar(parent, kval, value);
|
616
|
-
break;
|
653
|
+
if (4 == klen && 's' == *key && 'e' == key[1] && 'l' == key[2] && 'f' == key[3]) {
|
654
|
+
rb_funcall(parent->val, oj_replace_id, 1, value);
|
655
|
+
} else {
|
656
|
+
oj_set_obj_ivar(parent, kval, value);
|
657
|
+
}
|
658
|
+
break;
|
659
|
+
case T_STRING: // for subclassed strings
|
660
|
+
case T_OBJECT: oj_set_obj_ivar(parent, kval, value); break;
|
617
661
|
case T_MODULE:
|
618
662
|
case T_CLASS:
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
663
|
+
if (NULL == parent->odd_args) {
|
664
|
+
oj_set_error_at(pi,
|
665
|
+
oj_parse_error_class,
|
666
|
+
__FILE__,
|
667
|
+
__LINE__,
|
668
|
+
"%s is not an odd class",
|
669
|
+
rb_class2name(rb_obj_class(parent->val)));
|
670
|
+
return;
|
671
|
+
} else if (0 != oj_odd_set_arg(parent->odd_args, key, klen, value)) {
|
672
|
+
char buf[256];
|
673
|
+
|
674
|
+
if ((int)sizeof(buf) - 1 <= klen) {
|
675
|
+
klen = sizeof(buf) - 2;
|
676
|
+
}
|
677
|
+
memcpy(buf, key, klen);
|
678
|
+
buf[klen] = '\0';
|
679
|
+
oj_set_error_at(pi,
|
680
|
+
oj_parse_error_class,
|
681
|
+
__FILE__,
|
682
|
+
__LINE__,
|
683
|
+
"%s is not an attribute of %s",
|
684
|
+
buf,
|
685
|
+
rb_class2name(rb_obj_class(parent->val)));
|
686
|
+
}
|
687
|
+
break;
|
633
688
|
default:
|
634
|
-
|
635
|
-
|
689
|
+
oj_set_error_at(pi,
|
690
|
+
oj_parse_error_class,
|
691
|
+
__FILE__,
|
692
|
+
__LINE__,
|
693
|
+
"can not add attributes to a %s",
|
694
|
+
rb_class2name(rb_obj_class(parent->val)));
|
695
|
+
return;
|
636
696
|
}
|
637
697
|
if (Yes == pi->options.trace) {
|
638
|
-
|
698
|
+
oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, value);
|
639
699
|
}
|
640
700
|
}
|
641
701
|
|
642
|
-
static VALUE
|
643
|
-
start_hash(ParseInfo pi) {
|
702
|
+
static VALUE start_hash(ParseInfo pi) {
|
644
703
|
if (Yes == pi->options.trace) {
|
645
|
-
|
704
|
+
oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
|
646
705
|
}
|
647
706
|
return Qnil;
|
648
707
|
}
|
649
708
|
|
650
|
-
static void
|
651
|
-
|
652
|
-
Val parent = stack_peek(&pi->stack);
|
709
|
+
static void end_hash(ParseInfo pi) {
|
710
|
+
Val parent = stack_peek(&pi->stack);
|
653
711
|
|
654
712
|
if (Qnil == parent->val) {
|
655
|
-
|
713
|
+
parent->val = rb_hash_new();
|
656
714
|
} else if (NULL != parent->odd_args) {
|
657
|
-
|
715
|
+
OddArgs oa = parent->odd_args;
|
658
716
|
|
659
|
-
|
660
|
-
|
661
|
-
|
717
|
+
parent->val = rb_funcall2(oa->odd->create_obj,
|
718
|
+
oa->odd->create_op,
|
719
|
+
oa->odd->attr_cnt,
|
720
|
+
oa->args);
|
721
|
+
oj_odd_free(oa);
|
722
|
+
parent->odd_args = NULL;
|
662
723
|
}
|
663
724
|
if (Yes == pi->options.trace) {
|
664
|
-
|
725
|
+
oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
|
665
726
|
}
|
666
727
|
}
|
667
728
|
|
668
|
-
static void
|
669
|
-
|
670
|
-
volatile VALUE rval = Qnil;
|
729
|
+
static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
730
|
+
volatile VALUE rval = Qnil;
|
671
731
|
|
672
732
|
// orig lets us know whether the string was ^r1 or \u005er1
|
673
|
-
if (3 <= len && 0 != pi->circ_array && '^' == orig[0] &&
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
if (0 < i) {
|
685
|
-
rb_ary_push(stack_peek(&pi->stack)->val, oj_circ_array_get(pi->circ_array, i));
|
686
|
-
return;
|
687
|
-
}
|
733
|
+
if (3 <= len && 0 != pi->circ_array && '^' == orig[0] &&
|
734
|
+
0 == rb_array_len(stack_peek(&pi->stack)->val)) {
|
735
|
+
if ('i' == str[1]) {
|
736
|
+
long i = read_long(str + 2, len - 2);
|
737
|
+
|
738
|
+
if (0 < i) {
|
739
|
+
oj_circ_array_set(pi->circ_array, stack_peek(&pi->stack)->val, i);
|
740
|
+
return;
|
741
|
+
}
|
742
|
+
} else if ('r' == str[1]) {
|
743
|
+
long i = read_long(str + 2, len - 2);
|
688
744
|
|
689
|
-
|
745
|
+
if (0 < i) {
|
746
|
+
rb_ary_push(stack_peek(&pi->stack)->val, oj_circ_array_get(pi->circ_array, i));
|
747
|
+
return;
|
748
|
+
}
|
749
|
+
}
|
690
750
|
}
|
691
751
|
rval = str_to_value(pi, str, len, orig);
|
692
752
|
rb_ary_push(stack_peek(&pi->stack)->val, rval);
|
693
753
|
if (Yes == pi->options.trace) {
|
694
|
-
|
754
|
+
oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rval);
|
695
755
|
}
|
696
756
|
}
|
697
757
|
|
698
|
-
static void
|
699
|
-
|
700
|
-
volatile VALUE rval = oj_num_as_value(ni);
|
758
|
+
static void array_append_num(ParseInfo pi, NumInfo ni) {
|
759
|
+
volatile VALUE rval = oj_num_as_value(ni);
|
701
760
|
|
702
761
|
rb_ary_push(stack_peek(&pi->stack)->val, rval);
|
703
762
|
if (Yes == pi->options.trace) {
|
704
|
-
|
763
|
+
oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
|
705
764
|
}
|
706
765
|
}
|
707
766
|
|
708
|
-
static void
|
709
|
-
add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
767
|
+
static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
710
768
|
pi->stack.head->val = str_to_value(pi, str, len, orig);
|
711
769
|
if (Yes == pi->options.trace) {
|
712
|
-
|
770
|
+
oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, pi->stack.head->val);
|
713
771
|
}
|
714
772
|
}
|
715
773
|
|
716
|
-
static void
|
717
|
-
add_num(ParseInfo pi, NumInfo ni) {
|
774
|
+
static void add_num(ParseInfo pi, NumInfo ni) {
|
718
775
|
pi->stack.head->val = oj_num_as_value(ni);
|
719
776
|
if (Yes == pi->options.trace) {
|
720
|
-
|
777
|
+
oj_trace_parse_call("add_num", pi, __FILE__, __LINE__, pi->stack.head->val);
|
721
778
|
}
|
722
779
|
}
|
723
780
|
|
724
|
-
void
|
725
|
-
oj_set_object_callbacks(ParseInfo pi) {
|
781
|
+
void oj_set_object_callbacks(ParseInfo pi) {
|
726
782
|
oj_set_strict_callbacks(pi);
|
727
|
-
pi->end_hash
|
728
|
-
pi->start_hash
|
729
|
-
pi->hash_set_cstr
|
730
|
-
pi->hash_set_num
|
731
|
-
pi->hash_set_value
|
732
|
-
pi->add_cstr
|
733
|
-
pi->add_num
|
783
|
+
pi->end_hash = end_hash;
|
784
|
+
pi->start_hash = start_hash;
|
785
|
+
pi->hash_set_cstr = hash_set_cstr;
|
786
|
+
pi->hash_set_num = hash_set_num;
|
787
|
+
pi->hash_set_value = hash_set_value;
|
788
|
+
pi->add_cstr = add_cstr;
|
789
|
+
pi->add_num = add_num;
|
734
790
|
pi->array_append_cstr = array_append_cstr;
|
735
|
-
pi->array_append_num
|
791
|
+
pi->array_append_num = array_append_num;
|
736
792
|
}
|
737
793
|
|
738
794
|
VALUE
|
739
795
|
oj_object_parse(int argc, VALUE *argv, VALUE self) {
|
740
|
-
struct _parseInfo
|
796
|
+
struct _parseInfo pi;
|
741
797
|
|
742
798
|
parse_info_init(&pi);
|
743
|
-
pi.options
|
744
|
-
pi.handler
|
799
|
+
pi.options = oj_default_options;
|
800
|
+
pi.handler = Qnil;
|
745
801
|
pi.err_class = Qnil;
|
746
802
|
oj_set_object_callbacks(&pi);
|
747
803
|
|
748
804
|
if (T_STRING == rb_type(*argv)) {
|
749
|
-
|
805
|
+
return oj_pi_parse(argc, argv, &pi, 0, 0, 1);
|
750
806
|
} else {
|
751
|
-
|
807
|
+
return oj_pi_sparse(argc, argv, &pi, 0);
|
752
808
|
}
|
753
809
|
}
|
754
810
|
|
755
811
|
VALUE
|
756
812
|
oj_object_parse_cstr(int argc, VALUE *argv, char *json, size_t len) {
|
757
|
-
struct _parseInfo
|
813
|
+
struct _parseInfo pi;
|
758
814
|
|
759
815
|
parse_info_init(&pi);
|
760
|
-
pi.options
|
761
|
-
pi.handler
|
816
|
+
pi.options = oj_default_options;
|
817
|
+
pi.handler = Qnil;
|
762
818
|
pi.err_class = Qnil;
|
763
819
|
oj_set_strict_callbacks(&pi);
|
764
|
-
pi.end_hash
|
765
|
-
pi.start_hash
|
766
|
-
pi.hash_set_cstr
|
767
|
-
pi.hash_set_num
|
768
|
-
pi.hash_set_value
|
769
|
-
pi.add_cstr
|
770
|
-
pi.add_num
|
820
|
+
pi.end_hash = end_hash;
|
821
|
+
pi.start_hash = start_hash;
|
822
|
+
pi.hash_set_cstr = hash_set_cstr;
|
823
|
+
pi.hash_set_num = hash_set_num;
|
824
|
+
pi.hash_set_value = hash_set_value;
|
825
|
+
pi.add_cstr = add_cstr;
|
826
|
+
pi.add_num = add_num;
|
771
827
|
pi.array_append_cstr = array_append_cstr;
|
772
|
-
pi.array_append_num
|
828
|
+
pi.array_append_num = array_append_num;
|
773
829
|
|
774
830
|
return oj_pi_parse(argc, argv, &pi, json, len, 1);
|
775
831
|
}
|