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