ox 2.14.14 → 2.14.17
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 +18 -0
- data/README.md +1 -1
- data/ext/ox/attr.h +33 -39
- data/ext/ox/base64.c +48 -42
- data/ext/ox/base64.h +4 -4
- data/ext/ox/buf.h +80 -86
- data/ext/ox/builder.c +377 -456
- data/ext/ox/cache.c +2 -2
- data/ext/ox/cache8.c +37 -40
- data/ext/ox/cache8.h +7 -7
- data/ext/ox/dump.c +811 -889
- data/ext/ox/err.c +16 -13
- data/ext/ox/err.h +11 -12
- data/ext/ox/extconf.rb +5 -10
- data/ext/ox/gen_load.c +135 -139
- data/ext/ox/hash_load.c +130 -148
- data/ext/ox/helper.h +32 -39
- data/ext/ox/intern.c +1 -2
- data/ext/ox/obj_load.c +586 -662
- data/ext/ox/ox.c +93 -132
- data/ext/ox/ox.h +5 -10
- data/ext/ox/parse.c +836 -874
- data/ext/ox/sax.c +56 -31
- data/ext/ox/sax.h +2 -2
- data/ext/ox/sax_as.c +78 -102
- data/ext/ox/sax_buf.c +85 -94
- data/ext/ox/sax_buf.h +101 -120
- data/ext/ox/sax_hint.c +175 -184
- data/ext/ox/sax_hint.h +19 -19
- data/ext/ox/sax_stack.h +59 -45
- data/ext/ox/slotcache.c +3 -3
- data/ext/ox/slotcache.h +4 -4
- data/ext/ox/special.c +320 -327
- data/ext/ox/special.h +2 -2
- data/ext/ox/type.h +19 -19
- data/lib/ox/bag.rb +13 -9
- data/lib/ox/cdata.rb +0 -2
- data/lib/ox/comment.rb +0 -2
- data/lib/ox/doctype.rb +0 -2
- data/lib/ox/document.rb +3 -5
- data/lib/ox/element.rb +41 -26
- data/lib/ox/error.rb +0 -3
- data/lib/ox/hasattrs.rb +7 -8
- data/lib/ox/instruct.rb +4 -6
- data/lib/ox/node.rb +3 -4
- data/lib/ox/raw.rb +0 -2
- data/lib/ox/sax.rb +20 -36
- data/lib/ox/version.rb +1 -2
- data/lib/ox/xmlrpc_adapter.rb +5 -6
- data/lib/ox.rb +15 -16
- metadata +27 -6
data/ext/ox/obj_load.c
CHANGED
@@ -3,518 +3,470 @@
|
|
3
3
|
* All rights reserved.
|
4
4
|
*/
|
5
5
|
|
6
|
-
#include <stdlib.h>
|
7
6
|
#include <errno.h>
|
7
|
+
#include <stdarg.h>
|
8
8
|
#include <stdio.h>
|
9
|
+
#include <stdlib.h>
|
9
10
|
#include <string.h>
|
10
|
-
#include <stdarg.h>
|
11
11
|
#include <time.h>
|
12
12
|
|
13
|
-
#include "ruby.h"
|
14
|
-
#include "ruby/encoding.h"
|
15
|
-
|
16
13
|
#include "base64.h"
|
17
|
-
#include "ox.h"
|
18
14
|
#include "intern.h"
|
15
|
+
#include "ox.h"
|
16
|
+
#include "ruby.h"
|
17
|
+
#include "ruby/encoding.h"
|
19
18
|
|
20
|
-
static void
|
21
|
-
static void
|
22
|
-
static void
|
23
|
-
static void
|
24
|
-
|
25
|
-
static VALUE
|
26
|
-
static VALUE
|
27
|
-
static VALUE
|
28
|
-
static VALUE
|
29
|
-
|
30
|
-
static ID
|
31
|
-
static VALUE
|
32
|
-
static VALUE
|
33
|
-
static VALUE
|
34
|
-
static unsigned long
|
35
|
-
static CircArray
|
36
|
-
static void
|
37
|
-
static void
|
38
|
-
static VALUE
|
39
|
-
|
40
|
-
static void
|
41
|
-
static void
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
0,
|
47
|
-
0,
|
48
|
-
0, // add_cdata,
|
19
|
+
static void instruct(PInfo pi, const char *target, Attr attrs, const char *content);
|
20
|
+
static void add_text(PInfo pi, char *text, int closed);
|
21
|
+
static void add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren);
|
22
|
+
static void end_element(PInfo pi, const char *ename);
|
23
|
+
|
24
|
+
static VALUE parse_time(const char *text, VALUE clas);
|
25
|
+
static VALUE parse_xsd_time(const char *text, VALUE clas);
|
26
|
+
static VALUE parse_double_time(const char *text, VALUE clas);
|
27
|
+
static VALUE parse_regexp(const char *text);
|
28
|
+
|
29
|
+
static ID get_var_sym_from_attrs(Attr a, void *encoding);
|
30
|
+
static VALUE get_obj_from_attrs(Attr a, PInfo pi, VALUE base_class);
|
31
|
+
static VALUE get_class_from_attrs(Attr a, PInfo pi, VALUE base_class);
|
32
|
+
static VALUE classname2class(const char *name, PInfo pi, VALUE base_class);
|
33
|
+
static unsigned long get_id_from_attrs(PInfo pi, Attr a);
|
34
|
+
static CircArray circ_array_new(void);
|
35
|
+
static void circ_array_free(CircArray ca);
|
36
|
+
static void circ_array_set(CircArray ca, VALUE obj, unsigned long id);
|
37
|
+
static VALUE circ_array_get(CircArray ca, unsigned long id);
|
38
|
+
|
39
|
+
static void debug_stack(PInfo pi, const char *comment);
|
40
|
+
static void fill_indent(PInfo pi, char *buf, size_t size);
|
41
|
+
|
42
|
+
struct _parseCallbacks _ox_obj_callbacks = {
|
43
|
+
instruct, // instruct,
|
44
|
+
0, // add_doctype,
|
45
|
+
0, // add_comment,
|
46
|
+
0, // add_cdata,
|
49
47
|
add_text,
|
50
48
|
add_element,
|
51
49
|
end_element,
|
52
50
|
NULL,
|
53
51
|
};
|
54
52
|
|
55
|
-
ParseCallbacks
|
53
|
+
ParseCallbacks ox_obj_callbacks = &_ox_obj_callbacks;
|
56
54
|
|
57
|
-
extern ParseCallbacks
|
55
|
+
extern ParseCallbacks ox_gen_callbacks;
|
58
56
|
|
59
|
-
inline static VALUE
|
60
|
-
|
61
|
-
|
62
|
-
ID ci = rb_intern(class_name);
|
57
|
+
inline static VALUE resolve_classname(VALUE mod, const char *class_name, Effort effort, VALUE base_class) {
|
58
|
+
VALUE clas;
|
59
|
+
ID ci = rb_intern(class_name);
|
63
60
|
|
64
61
|
switch (effort) {
|
65
62
|
case TolerantEffort:
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
63
|
+
if (rb_const_defined_at(mod, ci)) {
|
64
|
+
clas = rb_const_get_at(mod, ci);
|
65
|
+
} else {
|
66
|
+
clas = Qundef;
|
67
|
+
}
|
68
|
+
break;
|
72
69
|
case AutoEffort:
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
70
|
+
if (rb_const_defined_at(mod, ci)) {
|
71
|
+
clas = rb_const_get_at(mod, ci);
|
72
|
+
} else {
|
73
|
+
clas = rb_define_class_under(mod, class_name, base_class);
|
74
|
+
}
|
75
|
+
break;
|
79
76
|
case StrictEffort:
|
80
77
|
default:
|
81
|
-
|
82
|
-
|
83
|
-
|
78
|
+
// raise an error if name is not defined
|
79
|
+
clas = rb_const_get_at(mod, ci);
|
80
|
+
break;
|
84
81
|
}
|
85
82
|
return clas;
|
86
83
|
}
|
87
84
|
|
88
|
-
inline static VALUE
|
89
|
-
|
90
|
-
VALUE clas = classname2class(name, pi, base_class);
|
85
|
+
inline static VALUE classname2obj(const char *name, PInfo pi, VALUE base_class) {
|
86
|
+
VALUE clas = classname2class(name, pi, base_class);
|
91
87
|
|
92
88
|
if (Qundef == clas) {
|
93
|
-
|
89
|
+
return Qnil;
|
94
90
|
} else {
|
95
|
-
|
91
|
+
return rb_obj_alloc(clas);
|
96
92
|
}
|
97
93
|
}
|
98
94
|
|
99
|
-
inline static VALUE
|
100
|
-
|
101
|
-
|
102
|
-
const char *s = name;
|
95
|
+
inline static VALUE structname2obj(const char *name) {
|
96
|
+
VALUE ost;
|
97
|
+
const char *s = name;
|
103
98
|
|
104
99
|
for (; 1; s++) {
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
100
|
+
if ('\0' == *s) {
|
101
|
+
s = name;
|
102
|
+
break;
|
103
|
+
} else if (':' == *s) {
|
104
|
+
s += 2;
|
105
|
+
break;
|
106
|
+
}
|
112
107
|
}
|
113
108
|
ost = rb_const_get(ox_struct_class, rb_intern(s));
|
114
|
-
#if HAVE_RB_STRUCT_ALLOC_NOINIT
|
115
109
|
return rb_struct_alloc_noinit(ost);
|
116
|
-
#else
|
117
|
-
return rb_struct_new(ost);
|
118
|
-
#endif
|
119
110
|
}
|
120
111
|
|
121
|
-
inline static VALUE
|
122
|
-
|
123
|
-
unsigned long n = 0;
|
112
|
+
inline static VALUE parse_ulong(const char *s, PInfo pi) {
|
113
|
+
unsigned long n = 0;
|
124
114
|
|
125
115
|
for (; '\0' != *s; s++) {
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
116
|
+
if ('0' <= *s && *s <= '9') {
|
117
|
+
n = n * 10 + (*s - '0');
|
118
|
+
} else {
|
119
|
+
set_error(&pi->err, "Invalid number for a julian day", pi->str, pi->s);
|
120
|
+
return Qundef;
|
121
|
+
}
|
132
122
|
}
|
133
123
|
return ULONG2NUM(n);
|
134
124
|
}
|
135
125
|
|
136
126
|
// 2010-07-09T10:47:45.895826162+09:00
|
137
|
-
inline static VALUE
|
138
|
-
|
139
|
-
VALUE t;
|
127
|
+
inline static VALUE parse_time(const char *text, VALUE clas) {
|
128
|
+
VALUE t;
|
140
129
|
|
141
|
-
if (Qnil == (t = parse_double_time(text, clas)) &&
|
142
|
-
|
143
|
-
VALUE args[1];
|
130
|
+
if (Qnil == (t = parse_double_time(text, clas)) && Qnil == (t = parse_xsd_time(text, clas))) {
|
131
|
+
VALUE args[1];
|
144
132
|
|
145
|
-
|
146
|
-
|
133
|
+
*args = rb_str_new2(text);
|
134
|
+
t = rb_funcall2(ox_time_class, ox_parse_id, 1, args);
|
147
135
|
}
|
148
136
|
return t;
|
149
137
|
}
|
150
138
|
|
151
|
-
static VALUE
|
152
|
-
|
153
|
-
VALUE
|
154
|
-
VALUE clas;
|
139
|
+
static VALUE classname2class(const char *name, PInfo pi, VALUE base_class) {
|
140
|
+
VALUE *slot;
|
141
|
+
VALUE clas;
|
155
142
|
|
156
143
|
if (Qundef == (clas = slot_cache_get(ox_class_cache, name, &slot, 0))) {
|
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
|
-
|
144
|
+
char class_name[1024];
|
145
|
+
char *s;
|
146
|
+
const char *n = name;
|
147
|
+
|
148
|
+
clas = rb_cObject;
|
149
|
+
for (s = class_name; '\0' != *n; n++) {
|
150
|
+
if (':' == *n) {
|
151
|
+
*s = '\0';
|
152
|
+
n++;
|
153
|
+
if (':' != *n) {
|
154
|
+
set_error(&pi->err, "Invalid classname, expected another ':'", pi->str, pi->s);
|
155
|
+
return Qundef;
|
156
|
+
}
|
157
|
+
if (Qundef == (clas = resolve_classname(clas, class_name, pi->options->effort, base_class))) {
|
158
|
+
return Qundef;
|
159
|
+
}
|
160
|
+
s = class_name;
|
161
|
+
} else {
|
162
|
+
*s++ = *n;
|
163
|
+
}
|
164
|
+
}
|
165
|
+
*s = '\0';
|
166
|
+
if (Qundef != (clas = resolve_classname(clas, class_name, pi->options->effort, base_class))) {
|
167
|
+
*slot = clas;
|
168
|
+
rb_gc_register_address(slot);
|
169
|
+
}
|
183
170
|
}
|
184
171
|
return clas;
|
185
172
|
}
|
186
173
|
|
187
|
-
static ID
|
188
|
-
get_var_sym_from_attrs(Attr a, void *encoding) {
|
174
|
+
static ID get_var_sym_from_attrs(Attr a, void *encoding) {
|
189
175
|
for (; 0 != a->name; a++) {
|
190
|
-
|
191
|
-
|
176
|
+
if ('a' == *a->name && '\0' == *(a->name + 1)) {
|
177
|
+
const char *val = a->value;
|
192
178
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
179
|
+
if ('0' <= *val && *val <= '9') {
|
180
|
+
return INT2NUM(atoi(val));
|
181
|
+
}
|
182
|
+
return ox_id_intern(val, strlen(val));
|
183
|
+
}
|
198
184
|
}
|
199
185
|
return 0;
|
200
186
|
}
|
201
187
|
|
202
|
-
static VALUE
|
203
|
-
get_obj_from_attrs(Attr a, PInfo pi, VALUE base_class) {
|
188
|
+
static VALUE get_obj_from_attrs(Attr a, PInfo pi, VALUE base_class) {
|
204
189
|
for (; 0 != a->name; a++) {
|
205
|
-
|
206
|
-
|
207
|
-
|
190
|
+
if ('c' == *a->name && '\0' == *(a->name + 1)) {
|
191
|
+
return classname2obj(a->value, pi, base_class);
|
192
|
+
}
|
208
193
|
}
|
209
194
|
return Qundef;
|
210
195
|
}
|
211
196
|
|
212
|
-
static VALUE
|
213
|
-
get_struct_from_attrs(Attr a) {
|
197
|
+
static VALUE get_struct_from_attrs(Attr a) {
|
214
198
|
for (; 0 != a->name; a++) {
|
215
|
-
|
216
|
-
|
217
|
-
|
199
|
+
if ('c' == *a->name && '\0' == *(a->name + 1)) {
|
200
|
+
return structname2obj(a->value);
|
201
|
+
}
|
218
202
|
}
|
219
203
|
return Qundef;
|
220
204
|
}
|
221
205
|
|
222
|
-
static VALUE
|
223
|
-
get_class_from_attrs(Attr a, PInfo pi, VALUE base_class) {
|
206
|
+
static VALUE get_class_from_attrs(Attr a, PInfo pi, VALUE base_class) {
|
224
207
|
for (; 0 != a->name; a++) {
|
225
|
-
|
226
|
-
|
227
|
-
|
208
|
+
if ('c' == *a->name && '\0' == *(a->name + 1)) {
|
209
|
+
return classname2class(a->value, pi, base_class);
|
210
|
+
}
|
228
211
|
}
|
229
212
|
return Qundef;
|
230
213
|
}
|
231
214
|
|
232
|
-
static unsigned long
|
233
|
-
get_id_from_attrs(PInfo pi, Attr a) {
|
215
|
+
static unsigned long get_id_from_attrs(PInfo pi, Attr a) {
|
234
216
|
for (; 0 != a->name; a++) {
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
217
|
+
if ('i' == *a->name && '\0' == *(a->name + 1)) {
|
218
|
+
unsigned long id = 0;
|
219
|
+
const char *text = a->value;
|
220
|
+
char c;
|
221
|
+
|
222
|
+
for (; '\0' != *text; text++) {
|
223
|
+
c = *text;
|
224
|
+
if ('0' <= c && c <= '9') {
|
225
|
+
id = id * 10 + (c - '0');
|
226
|
+
} else {
|
227
|
+
set_error(&pi->err, "bad number format", pi->str, pi->s);
|
228
|
+
return 0;
|
229
|
+
}
|
230
|
+
}
|
231
|
+
return id;
|
232
|
+
}
|
251
233
|
}
|
252
234
|
return 0;
|
253
235
|
}
|
254
236
|
|
255
|
-
static CircArray
|
256
|
-
|
257
|
-
CircArray ca;
|
237
|
+
static CircArray circ_array_new() {
|
238
|
+
CircArray ca;
|
258
239
|
|
259
|
-
ca
|
240
|
+
ca = ALLOC(struct _circArray);
|
260
241
|
ca->objs = ca->obj_array;
|
261
242
|
ca->size = sizeof(ca->obj_array) / sizeof(VALUE);
|
262
|
-
ca->cnt
|
243
|
+
ca->cnt = 0;
|
263
244
|
|
264
245
|
return ca;
|
265
246
|
}
|
266
247
|
|
267
|
-
static void
|
268
|
-
circ_array_free(CircArray ca) {
|
248
|
+
static void circ_array_free(CircArray ca) {
|
269
249
|
if (ca->objs != ca->obj_array) {
|
270
|
-
|
250
|
+
xfree(ca->objs);
|
271
251
|
}
|
272
252
|
xfree(ca);
|
273
253
|
}
|
274
254
|
|
275
|
-
static void
|
276
|
-
circ_array_set(CircArray ca, VALUE obj, unsigned long id) {
|
255
|
+
static void circ_array_set(CircArray ca, VALUE obj, unsigned long id) {
|
277
256
|
if (0 < id) {
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
257
|
+
unsigned long i;
|
258
|
+
|
259
|
+
if (ca->size < id) {
|
260
|
+
unsigned long cnt = id + 512;
|
261
|
+
|
262
|
+
if (ca->objs == ca->obj_array) {
|
263
|
+
ca->objs = ALLOC_N(VALUE, cnt);
|
264
|
+
memcpy(ca->objs, ca->obj_array, sizeof(VALUE) * ca->cnt);
|
265
|
+
} else {
|
266
|
+
REALLOC_N(ca->objs, VALUE, cnt);
|
267
|
+
}
|
268
|
+
ca->size = cnt;
|
269
|
+
}
|
270
|
+
id--;
|
271
|
+
for (i = ca->cnt; i < id; i++) {
|
272
|
+
ca->objs[i] = Qundef;
|
273
|
+
}
|
274
|
+
ca->objs[id] = obj;
|
275
|
+
if (ca->cnt <= id) {
|
276
|
+
ca->cnt = id + 1;
|
277
|
+
}
|
299
278
|
}
|
300
279
|
}
|
301
280
|
|
302
|
-
static VALUE
|
303
|
-
|
304
|
-
VALUE obj = Qundef;
|
281
|
+
static VALUE circ_array_get(CircArray ca, unsigned long id) {
|
282
|
+
VALUE obj = Qundef;
|
305
283
|
|
306
284
|
if (id <= ca->cnt) {
|
307
|
-
|
285
|
+
obj = ca->objs[id - 1];
|
308
286
|
}
|
309
287
|
return obj;
|
310
288
|
}
|
311
289
|
|
312
|
-
static VALUE
|
313
|
-
|
314
|
-
|
315
|
-
int options = 0;
|
290
|
+
static VALUE parse_regexp(const char *text) {
|
291
|
+
const char *te;
|
292
|
+
int options = 0;
|
316
293
|
|
317
294
|
te = text + strlen(text) - 1;
|
318
295
|
#ifdef ONIG_OPTION_IGNORECASE
|
319
296
|
for (; text < te && '/' != *te; te--) {
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
297
|
+
switch (*te) {
|
298
|
+
case 'i': options |= ONIG_OPTION_IGNORECASE; break;
|
299
|
+
case 'm': options |= ONIG_OPTION_MULTILINE; break;
|
300
|
+
case 'x': options |= ONIG_OPTION_EXTEND; break;
|
301
|
+
default: break;
|
302
|
+
}
|
326
303
|
}
|
327
304
|
#endif
|
328
305
|
return rb_reg_new(text + 1, te - text - 1, options);
|
329
306
|
}
|
330
307
|
|
331
|
-
static void
|
332
|
-
instruct(PInfo pi, const char *target, Attr attrs, const char *content) {
|
308
|
+
static void instruct(PInfo pi, const char *target, Attr attrs, const char *content) {
|
333
309
|
if (0 == strcmp("xml", target)) {
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
310
|
+
for (; 0 != attrs->name; attrs++) {
|
311
|
+
if (0 == strcmp("encoding", attrs->name)) {
|
312
|
+
pi->options->rb_enc = rb_enc_find(attrs->value);
|
313
|
+
}
|
314
|
+
}
|
339
315
|
}
|
340
316
|
}
|
341
317
|
|
342
|
-
static void
|
343
|
-
|
344
|
-
Helper h = helper_stack_peek(&pi->helpers);
|
318
|
+
static void add_text(PInfo pi, char *text, int closed) {
|
319
|
+
Helper h = helper_stack_peek(&pi->helpers);
|
345
320
|
|
346
321
|
if (!closed) {
|
347
|
-
|
348
|
-
|
322
|
+
set_error(&pi->err, "Text not closed", pi->str, pi->s);
|
323
|
+
return;
|
349
324
|
}
|
350
325
|
if (0 == h) {
|
351
|
-
|
352
|
-
|
326
|
+
set_error(&pi->err, "Unexpected text", pi->str, pi->s);
|
327
|
+
return;
|
353
328
|
}
|
354
329
|
if (DEBUG <= pi->options->trace) {
|
355
|
-
|
330
|
+
char indent[128];
|
356
331
|
|
357
|
-
|
358
|
-
|
332
|
+
fill_indent(pi, indent, sizeof(indent));
|
333
|
+
printf("%s '%s' to type %c\n", indent, text, h->type);
|
359
334
|
}
|
360
335
|
switch (h->type) {
|
361
336
|
case NoCode:
|
362
337
|
case StringCode:
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
case FixnumCode:
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
case
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
break;
|
431
|
-
}
|
432
|
-
case Symbol64Code:
|
433
|
-
{
|
434
|
-
unsigned long str_size = b64_orig_size(text);
|
435
|
-
char *str = ALLOCA_N(char, str_size + 1);
|
436
|
-
|
437
|
-
from_base64(text, (uchar*)str);
|
438
|
-
h->obj = ox_sym_intern(str, strlen(str), NULL);
|
439
|
-
break;
|
338
|
+
h->obj = rb_str_new2(text);
|
339
|
+
if (0 != pi->options->rb_enc) {
|
340
|
+
rb_enc_associate(h->obj, pi->options->rb_enc);
|
341
|
+
}
|
342
|
+
if (0 != pi->circ_array) {
|
343
|
+
circ_array_set(pi->circ_array, h->obj, (unsigned long)pi->id);
|
344
|
+
}
|
345
|
+
break;
|
346
|
+
case FixnumCode: {
|
347
|
+
long n = 0;
|
348
|
+
char c;
|
349
|
+
int neg = 0;
|
350
|
+
|
351
|
+
if ('-' == *text) {
|
352
|
+
neg = 1;
|
353
|
+
text++;
|
354
|
+
}
|
355
|
+
for (; '\0' != *text; text++) {
|
356
|
+
c = *text;
|
357
|
+
if ('0' <= c && c <= '9') {
|
358
|
+
n = n * 10 + (c - '0');
|
359
|
+
} else {
|
360
|
+
set_error(&pi->err, "bad number format", pi->str, pi->s);
|
361
|
+
return;
|
362
|
+
}
|
363
|
+
}
|
364
|
+
if (neg) {
|
365
|
+
n = -n;
|
366
|
+
}
|
367
|
+
h->obj = LONG2NUM(n);
|
368
|
+
break;
|
369
|
+
}
|
370
|
+
case FloatCode: h->obj = rb_float_new(strtod(text, 0)); break;
|
371
|
+
case SymbolCode: h->obj = ox_sym_intern(text, strlen(text), NULL); break;
|
372
|
+
case DateCode: {
|
373
|
+
VALUE args[1];
|
374
|
+
|
375
|
+
if (Qundef == (*args = parse_ulong(text, pi))) {
|
376
|
+
return;
|
377
|
+
}
|
378
|
+
h->obj = rb_funcall2(ox_date_class, ox_jd_id, 1, args);
|
379
|
+
break;
|
380
|
+
}
|
381
|
+
case TimeCode: h->obj = parse_time(text, ox_time_class); break;
|
382
|
+
case String64Code: {
|
383
|
+
unsigned long str_size = b64_orig_size(text);
|
384
|
+
VALUE v;
|
385
|
+
char *str = ALLOCA_N(char, str_size + 1);
|
386
|
+
|
387
|
+
from_base64(text, (uchar *)str);
|
388
|
+
v = rb_str_new(str, str_size);
|
389
|
+
if (0 != pi->options->rb_enc) {
|
390
|
+
rb_enc_associate(v, pi->options->rb_enc);
|
391
|
+
}
|
392
|
+
if (0 != pi->circ_array) {
|
393
|
+
circ_array_set(pi->circ_array, v, (unsigned long)h->obj);
|
394
|
+
}
|
395
|
+
h->obj = v;
|
396
|
+
break;
|
397
|
+
}
|
398
|
+
case Symbol64Code: {
|
399
|
+
unsigned long str_size = b64_orig_size(text);
|
400
|
+
char *str = ALLOCA_N(char, str_size + 1);
|
401
|
+
|
402
|
+
from_base64(text, (uchar *)str);
|
403
|
+
h->obj = ox_sym_intern(str, strlen(str), NULL);
|
404
|
+
break;
|
440
405
|
}
|
441
406
|
case RegexpCode:
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
case BignumCode:
|
453
|
-
|
454
|
-
|
455
|
-
case BigDecimalCode:
|
456
|
-
h->obj = rb_funcall(rb_cObject, ox_bigdecimal_id, 1, rb_str_new2(text));
|
457
|
-
break;
|
458
|
-
default:
|
459
|
-
h->obj = Qnil;
|
460
|
-
break;
|
407
|
+
if ('/' == *text) {
|
408
|
+
h->obj = parse_regexp(text);
|
409
|
+
} else {
|
410
|
+
unsigned long str_size = b64_orig_size(text);
|
411
|
+
char *str = ALLOCA_N(char, str_size + 1);
|
412
|
+
|
413
|
+
from_base64(text, (uchar *)str);
|
414
|
+
h->obj = parse_regexp(str);
|
415
|
+
}
|
416
|
+
break;
|
417
|
+
case BignumCode: h->obj = rb_cstr_to_inum(text, 10, 1); break;
|
418
|
+
case BigDecimalCode: h->obj = rb_funcall(rb_cObject, ox_bigdecimal_id, 1, rb_str_new2(text)); break;
|
419
|
+
default: h->obj = Qnil; break;
|
461
420
|
}
|
462
421
|
}
|
463
422
|
|
464
|
-
static void
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
unsigned long id;
|
423
|
+
static void add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
424
|
+
Attr a;
|
425
|
+
Helper h;
|
426
|
+
unsigned long id;
|
469
427
|
|
470
428
|
if (TRACE <= pi->options->trace) {
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
}
|
490
|
-
if (helper_stack_empty(&pi->helpers)) {
|
491
|
-
|
492
|
-
|
493
|
-
|
429
|
+
char buf[1024];
|
430
|
+
char indent[128];
|
431
|
+
char *s = buf;
|
432
|
+
char *end = buf + sizeof(buf) - 2;
|
433
|
+
|
434
|
+
s += snprintf(s, end - s, " <%s%s", (hasChildren) ? "" : "/", ename);
|
435
|
+
for (a = attrs; 0 != a->name; a++) {
|
436
|
+
s += snprintf(s, end - s, " %s=%s", a->name, a->value);
|
437
|
+
}
|
438
|
+
*s++ = '>';
|
439
|
+
*s++ = '\0';
|
440
|
+
if (DEBUG <= pi->options->trace) {
|
441
|
+
printf("===== add element stack(%d) =====\n", helper_stack_depth(&pi->helpers));
|
442
|
+
debug_stack(pi, buf);
|
443
|
+
} else {
|
444
|
+
fill_indent(pi, indent, sizeof(indent));
|
445
|
+
printf("%s%s\n", indent, buf);
|
446
|
+
}
|
447
|
+
}
|
448
|
+
if (helper_stack_empty(&pi->helpers)) { // top level object
|
449
|
+
if (0 != (id = get_id_from_attrs(pi, attrs))) {
|
450
|
+
pi->circ_array = circ_array_new();
|
451
|
+
}
|
494
452
|
}
|
495
453
|
if ('\0' != ename[1]) {
|
496
|
-
|
497
|
-
|
454
|
+
set_error(&pi->err, "Invalid element name", pi->str, pi->s);
|
455
|
+
return;
|
498
456
|
}
|
499
|
-
h = helper_stack_push(&pi->helpers, get_var_sym_from_attrs(attrs, (void*)pi->options->rb_enc), Qundef, *ename);
|
457
|
+
h = helper_stack_push(&pi->helpers, get_var_sym_from_attrs(attrs, (void *)pi->options->rb_enc), Qundef, *ename);
|
500
458
|
switch (h->type) {
|
501
|
-
case NilClassCode:
|
502
|
-
|
503
|
-
|
504
|
-
case TrueClassCode:
|
505
|
-
h->obj = Qtrue;
|
506
|
-
break;
|
507
|
-
case FalseClassCode:
|
508
|
-
h->obj = Qfalse;
|
509
|
-
break;
|
459
|
+
case NilClassCode: h->obj = Qnil; break;
|
460
|
+
case TrueClassCode: h->obj = Qtrue; break;
|
461
|
+
case FalseClassCode: h->obj = Qfalse; break;
|
510
462
|
case StringCode:
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
463
|
+
// h->obj will be replaced by add_text if it is called
|
464
|
+
h->obj = ox_empty_string;
|
465
|
+
if (0 != pi->circ_array) {
|
466
|
+
pi->id = get_id_from_attrs(pi, attrs);
|
467
|
+
circ_array_set(pi->circ_array, h->obj, pi->id);
|
468
|
+
}
|
469
|
+
break;
|
518
470
|
case FixnumCode:
|
519
471
|
case FloatCode:
|
520
472
|
case SymbolCode:
|
@@ -525,361 +477,333 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
525
477
|
case ComplexCode:
|
526
478
|
case DateCode:
|
527
479
|
case TimeCode:
|
528
|
-
case RationalCode:
|
529
|
-
|
530
|
-
|
531
|
-
|
480
|
+
case RationalCode: // sub elements read next
|
481
|
+
// value will be read in the following add_text
|
482
|
+
h->obj = Qundef;
|
483
|
+
break;
|
532
484
|
case String64Code:
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
485
|
+
h->obj = Qundef;
|
486
|
+
if (0 != pi->circ_array) {
|
487
|
+
pi->id = get_id_from_attrs(pi, attrs);
|
488
|
+
}
|
489
|
+
break;
|
538
490
|
case ArrayCode:
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
491
|
+
h->obj = rb_ary_new();
|
492
|
+
if (0 != pi->circ_array) {
|
493
|
+
circ_array_set(pi->circ_array, h->obj, get_id_from_attrs(pi, attrs));
|
494
|
+
}
|
495
|
+
break;
|
544
496
|
case HashCode:
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
case RangeCode:
|
551
|
-
h->obj = rb_ary_new_from_args(3, Qnil, Qnil, Qfalse);
|
552
|
-
break;
|
497
|
+
h->obj = rb_hash_new();
|
498
|
+
if (0 != pi->circ_array) {
|
499
|
+
circ_array_set(pi->circ_array, h->obj, get_id_from_attrs(pi, attrs));
|
500
|
+
}
|
501
|
+
break;
|
502
|
+
case RangeCode: h->obj = rb_ary_new_from_args(3, Qnil, Qnil, Qfalse); break;
|
553
503
|
case RawCode:
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
504
|
+
if (hasChildren) {
|
505
|
+
h->obj = ox_parse(pi->s, pi->end - pi->s, ox_gen_callbacks, &pi->s, pi->options, &pi->err);
|
506
|
+
if (0 != pi->circ_array) {
|
507
|
+
circ_array_set(pi->circ_array, h->obj, get_id_from_attrs(pi, attrs));
|
508
|
+
}
|
509
|
+
} else {
|
510
|
+
h->obj = Qnil;
|
511
|
+
}
|
512
|
+
break;
|
563
513
|
case ExceptionCode:
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
514
|
+
if (Qundef == (h->obj = get_obj_from_attrs(attrs, pi, rb_eException))) {
|
515
|
+
return;
|
516
|
+
}
|
517
|
+
if (0 != pi->circ_array && Qnil != h->obj) {
|
518
|
+
circ_array_set(pi->circ_array, h->obj, get_id_from_attrs(pi, attrs));
|
519
|
+
}
|
520
|
+
break;
|
571
521
|
case ObjectCode:
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
522
|
+
if (Qundef == (h->obj = get_obj_from_attrs(attrs, pi, ox_bag_clas))) {
|
523
|
+
return;
|
524
|
+
}
|
525
|
+
if (0 != pi->circ_array && Qnil != h->obj) {
|
526
|
+
circ_array_set(pi->circ_array, h->obj, get_id_from_attrs(pi, attrs));
|
527
|
+
}
|
528
|
+
break;
|
579
529
|
case StructCode:
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
530
|
+
h->obj = get_struct_from_attrs(attrs);
|
531
|
+
if (0 != pi->circ_array) {
|
532
|
+
circ_array_set(pi->circ_array, h->obj, get_id_from_attrs(pi, attrs));
|
533
|
+
}
|
534
|
+
break;
|
585
535
|
case ClassCode:
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
536
|
+
if (Qundef == (h->obj = get_class_from_attrs(attrs, pi, ox_bag_clas))) {
|
537
|
+
return;
|
538
|
+
}
|
539
|
+
break;
|
590
540
|
case RefCode:
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
541
|
+
h->obj = Qundef;
|
542
|
+
if (0 != pi->circ_array) {
|
543
|
+
h->obj = circ_array_get(pi->circ_array, get_id_from_attrs(pi, attrs));
|
544
|
+
}
|
545
|
+
if (Qundef == h->obj) {
|
546
|
+
set_error(&pi->err, "Invalid circular reference", pi->str, pi->s);
|
547
|
+
return;
|
548
|
+
}
|
549
|
+
break;
|
600
550
|
default:
|
601
|
-
|
602
|
-
|
603
|
-
|
551
|
+
set_error(&pi->err, "Invalid element name", pi->str, pi->s);
|
552
|
+
return;
|
553
|
+
break;
|
604
554
|
}
|
605
555
|
if (DEBUG <= pi->options->trace) {
|
606
|
-
|
556
|
+
debug_stack(pi, " -----------");
|
607
557
|
}
|
608
558
|
}
|
609
559
|
|
610
|
-
static void
|
611
|
-
end_element(PInfo pi, const char *ename) {
|
560
|
+
static void end_element(PInfo pi, const char *ename) {
|
612
561
|
if (TRACE <= pi->options->trace) {
|
613
|
-
|
562
|
+
char indent[128];
|
614
563
|
|
615
|
-
|
616
|
-
|
564
|
+
if (DEBUG <= pi->options->trace) {
|
565
|
+
char buf[1024];
|
617
566
|
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
567
|
+
printf("===== end element stack(%d) =====\n", helper_stack_depth(&pi->helpers));
|
568
|
+
snprintf(buf, sizeof(buf) - 1, "</%s>", ename);
|
569
|
+
debug_stack(pi, buf);
|
570
|
+
} else {
|
571
|
+
fill_indent(pi, indent, sizeof(indent));
|
572
|
+
printf("%s</%s>\n", indent, ename);
|
573
|
+
}
|
625
574
|
}
|
626
575
|
if (!helper_stack_empty(&pi->helpers)) {
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
return;
|
712
|
-
}
|
713
|
-
#ifdef T_RATIONAL
|
714
|
-
if (Qundef == ph->obj) {
|
715
|
-
ph->obj = h->obj;
|
716
|
-
} else {
|
717
|
-
if (Qundef == ph->obj || RUBY_T_FIXNUM != rb_type(h->obj)) {
|
718
|
-
set_error(&pi->err, "Corrupt parse stack, container is wrong type", pi->str, pi->s);
|
719
|
-
return;
|
720
|
-
}
|
576
|
+
Helper h = helper_stack_pop(&pi->helpers);
|
577
|
+
Helper ph = helper_stack_peek(&pi->helpers);
|
578
|
+
|
579
|
+
if (ox_empty_string == h->obj) {
|
580
|
+
// special catch for empty strings
|
581
|
+
h->obj = rb_str_new2("");
|
582
|
+
} else if (Qundef == h->obj) {
|
583
|
+
set_error(&pi->err, "Invalid element for object mode", pi->str, pi->s);
|
584
|
+
return;
|
585
|
+
} else if (RangeCode == h->type) { // Expect an array of 3 elements.
|
586
|
+
const VALUE *ap = RARRAY_PTR(h->obj);
|
587
|
+
|
588
|
+
h->obj = rb_range_new(*ap, *(ap + 1), Qtrue == *(ap + 2));
|
589
|
+
}
|
590
|
+
pi->obj = h->obj;
|
591
|
+
if (0 != ph) {
|
592
|
+
switch (ph->type) {
|
593
|
+
case ArrayCode: rb_ary_push(ph->obj, h->obj); break;
|
594
|
+
case ExceptionCode:
|
595
|
+
case ObjectCode:
|
596
|
+
if (Qnil != ph->obj) {
|
597
|
+
if (0 == h->var || NULL == rb_id2name(h->var)) {
|
598
|
+
set_error(&pi->err, "Invalid element for object mode", pi->str, pi->s);
|
599
|
+
return;
|
600
|
+
}
|
601
|
+
if (RUBY_T_OBJECT != rb_type(ph->obj)) {
|
602
|
+
set_error(&pi->err, "Corrupt object encoding", pi->str, pi->s);
|
603
|
+
return;
|
604
|
+
}
|
605
|
+
rb_ivar_set(ph->obj, h->var, h->obj);
|
606
|
+
}
|
607
|
+
break;
|
608
|
+
case StructCode:
|
609
|
+
if (0 == h->var) {
|
610
|
+
set_error(&pi->err, "Invalid element for object mode", pi->str, pi->s);
|
611
|
+
return;
|
612
|
+
}
|
613
|
+
rb_struct_aset(ph->obj, h->var, h->obj);
|
614
|
+
break;
|
615
|
+
case HashCode:
|
616
|
+
// put back h
|
617
|
+
helper_stack_push(&pi->helpers, h->var, h->obj, KeyCode);
|
618
|
+
break;
|
619
|
+
case RangeCode:
|
620
|
+
if (ox_beg_id == h->var) {
|
621
|
+
rb_ary_store(ph->obj, 0, h->obj);
|
622
|
+
} else if (ox_end_id == h->var) {
|
623
|
+
rb_ary_store(ph->obj, 1, h->obj);
|
624
|
+
} else if (ox_excl_id == h->var) {
|
625
|
+
rb_ary_store(ph->obj, 2, h->obj);
|
626
|
+
} else {
|
627
|
+
set_error(&pi->err, "Invalid range attribute", pi->str, pi->s);
|
628
|
+
return;
|
629
|
+
}
|
630
|
+
break;
|
631
|
+
case KeyCode: {
|
632
|
+
Helper gh;
|
633
|
+
|
634
|
+
helper_stack_pop(&pi->helpers);
|
635
|
+
if (NULL == (gh = helper_stack_peek(&pi->helpers)) || Qundef == ph->obj || Qundef == h->obj) {
|
636
|
+
set_error(&pi->err, "Corrupt parse stack, container is wrong type", pi->str, pi->s);
|
637
|
+
return;
|
638
|
+
}
|
639
|
+
rb_hash_aset(gh->obj, ph->obj, h->obj);
|
640
|
+
} break;
|
641
|
+
case ComplexCode:
|
642
|
+
if (Qundef == ph->obj) {
|
643
|
+
ph->obj = h->obj;
|
644
|
+
} else {
|
645
|
+
ph->obj = rb_complex_new(ph->obj, h->obj);
|
646
|
+
}
|
647
|
+
break;
|
648
|
+
case RationalCode: {
|
649
|
+
if (Qundef == h->obj || RUBY_T_FIXNUM != rb_type(h->obj)) {
|
650
|
+
set_error(&pi->err, "Invalid object format", pi->str, pi->s);
|
651
|
+
return;
|
652
|
+
}
|
653
|
+
if (Qundef == ph->obj) {
|
654
|
+
ph->obj = h->obj;
|
655
|
+
} else {
|
656
|
+
if (Qundef == ph->obj || RUBY_T_FIXNUM != rb_type(ph->obj)) {
|
657
|
+
set_error(&pi->err, "Corrupt parse stack, container is wrong type", pi->str, pi->s);
|
658
|
+
return;
|
659
|
+
}
|
721
660
|
#ifdef RUBINIUS_RUBY
|
722
|
-
|
723
|
-
#else
|
724
|
-
ph->obj = rb_rational_new(ph->obj, h->obj);
|
725
|
-
#endif
|
726
|
-
}
|
661
|
+
ph->obj = rb_Rational(ph->obj, h->obj);
|
727
662
|
#else
|
728
|
-
|
729
|
-
return;
|
663
|
+
ph->obj = rb_rational_new(ph->obj, h->obj);
|
730
664
|
#endif
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
665
|
+
}
|
666
|
+
break;
|
667
|
+
}
|
668
|
+
default:
|
669
|
+
set_error(&pi->err, "Corrupt parse stack, container is wrong type", pi->str, pi->s);
|
670
|
+
return;
|
671
|
+
break;
|
672
|
+
}
|
673
|
+
}
|
739
674
|
}
|
740
675
|
if (0 != pi->circ_array && helper_stack_empty(&pi->helpers)) {
|
741
|
-
|
742
|
-
|
676
|
+
circ_array_free(pi->circ_array);
|
677
|
+
pi->circ_array = 0;
|
743
678
|
}
|
744
679
|
if (DEBUG <= pi->options->trace) {
|
745
|
-
|
680
|
+
debug_stack(pi, " ----------");
|
746
681
|
}
|
747
682
|
}
|
748
683
|
|
749
|
-
static VALUE
|
750
|
-
|
751
|
-
long
|
752
|
-
|
753
|
-
|
754
|
-
char c;
|
684
|
+
static VALUE parse_double_time(const char *text, VALUE clas) {
|
685
|
+
long v = 0;
|
686
|
+
long v2 = 0;
|
687
|
+
const char *dot = 0;
|
688
|
+
char c;
|
755
689
|
|
756
690
|
for (; '.' != *text; text++) {
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
691
|
+
c = *text;
|
692
|
+
if (c < '0' || '9' < c) {
|
693
|
+
return Qnil;
|
694
|
+
}
|
695
|
+
v = 10 * v + (long)(c - '0');
|
762
696
|
}
|
763
697
|
dot = text++;
|
764
698
|
for (; '\0' != *text && text - dot <= 6; text++) {
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
699
|
+
c = *text;
|
700
|
+
if (c < '0' || '9' < c) {
|
701
|
+
return Qnil;
|
702
|
+
}
|
703
|
+
v2 = 10 * v2 + (long)(c - '0');
|
770
704
|
}
|
771
705
|
for (; text - dot <= 9; text++) {
|
772
|
-
|
706
|
+
v2 *= 10;
|
773
707
|
}
|
774
|
-
#if HAVE_RB_TIME_NANO_NEW
|
775
708
|
return rb_time_nano_new(v, v2);
|
776
|
-
#else
|
777
|
-
return rb_time_new(v, v2 / 1000);
|
778
|
-
#endif
|
779
709
|
}
|
780
710
|
|
781
711
|
typedef struct _tp {
|
782
|
-
int
|
783
|
-
char
|
784
|
-
char
|
712
|
+
int cnt;
|
713
|
+
char end;
|
714
|
+
char alt;
|
785
715
|
} *Tp;
|
786
716
|
|
787
|
-
static VALUE
|
788
|
-
|
789
|
-
long
|
790
|
-
long
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
struct tm tm;
|
717
|
+
static VALUE parse_xsd_time(const char *text, VALUE clas) {
|
718
|
+
long cargs[10];
|
719
|
+
long *cp = cargs;
|
720
|
+
long v;
|
721
|
+
int i;
|
722
|
+
char c;
|
723
|
+
struct _tp tpa[10] = {{4, '-', '-'},
|
724
|
+
{2, '-', '-'},
|
725
|
+
{2, 'T', 'T'},
|
726
|
+
{2, ':', ':'},
|
727
|
+
{2, ':', ':'},
|
728
|
+
{2, '.', '.'},
|
729
|
+
{9, '+', '-'},
|
730
|
+
{2, ':', ':'},
|
731
|
+
{2, '\0', '\0'},
|
732
|
+
{0, '\0', '\0'}};
|
733
|
+
Tp tp = tpa;
|
734
|
+
struct tm tm;
|
806
735
|
|
807
736
|
for (; 0 != tp->cnt; tp++) {
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
737
|
+
for (i = tp->cnt, v = 0; 0 < i; text++, i--) {
|
738
|
+
c = *text;
|
739
|
+
if (c < '0' || '9' < c) {
|
740
|
+
if (tp->end == c || tp->alt == c) {
|
741
|
+
break;
|
742
|
+
}
|
743
|
+
return Qnil;
|
744
|
+
}
|
745
|
+
v = 10 * v + (long)(c - '0');
|
746
|
+
}
|
747
|
+
c = *text++;
|
748
|
+
if (tp->end != c && tp->alt != c) {
|
749
|
+
return Qnil;
|
750
|
+
}
|
751
|
+
*cp++ = v;
|
823
752
|
}
|
824
753
|
tm.tm_year = (int)cargs[0] - 1900;
|
825
|
-
tm.tm_mon
|
754
|
+
tm.tm_mon = (int)cargs[1] - 1;
|
826
755
|
tm.tm_mday = (int)cargs[2];
|
827
756
|
tm.tm_hour = (int)cargs[3];
|
828
|
-
tm.tm_min
|
829
|
-
tm.tm_sec
|
830
|
-
#if HAVE_RB_TIME_NANO_NEW
|
757
|
+
tm.tm_min = (int)cargs[4];
|
758
|
+
tm.tm_sec = (int)cargs[5];
|
831
759
|
return rb_time_nano_new(mktime(&tm), cargs[6]);
|
832
|
-
#else
|
833
|
-
return rb_time_new(mktime(&tm), cargs[6] / 1000);
|
834
|
-
#endif
|
835
760
|
}
|
836
761
|
|
837
762
|
// debug functions
|
838
|
-
static void
|
839
|
-
|
840
|
-
size_t cnt;
|
763
|
+
static void fill_indent(PInfo pi, char *buf, size_t size) {
|
764
|
+
size_t cnt;
|
841
765
|
|
842
766
|
if (0 < (cnt = helper_stack_depth(&pi->helpers))) {
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
767
|
+
cnt *= 2;
|
768
|
+
if (size < cnt + 1) {
|
769
|
+
cnt = size - 1;
|
770
|
+
}
|
771
|
+
memset(buf, ' ', cnt);
|
772
|
+
buf += cnt;
|
849
773
|
}
|
850
774
|
*buf = '\0';
|
851
775
|
}
|
852
776
|
|
853
|
-
static void
|
854
|
-
|
855
|
-
|
856
|
-
Helper h;
|
777
|
+
static void debug_stack(PInfo pi, const char *comment) {
|
778
|
+
char indent[128];
|
779
|
+
Helper h;
|
857
780
|
|
858
781
|
fill_indent(pi, indent, sizeof(indent));
|
859
782
|
printf("%s%s\n", indent, comment);
|
860
783
|
if (!helper_stack_empty(&pi->helpers)) {
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
784
|
+
for (h = pi->helpers.head; h < pi->helpers.tail; h++) {
|
785
|
+
const char *clas = "---";
|
786
|
+
const char *key = "---";
|
787
|
+
|
788
|
+
if (Qundef != h->obj) {
|
789
|
+
VALUE c = rb_obj_class(h->obj);
|
790
|
+
|
791
|
+
clas = rb_class2name(c);
|
792
|
+
}
|
793
|
+
if (0 != h->var) {
|
794
|
+
if (HashCode == h->type) {
|
795
|
+
VALUE v;
|
796
|
+
|
797
|
+
v = rb_String(h->var);
|
798
|
+
key = StringValuePtr(v);
|
799
|
+
} else if (ObjectCode == (h - 1)->type || ExceptionCode == (h - 1)->type ||
|
800
|
+
RangeCode == (h - 1)->type || StructCode == (h - 1)->type) {
|
801
|
+
key = rb_id2name(h->var);
|
802
|
+
} else {
|
803
|
+
printf("%s*** corrupt stack ***\n", indent);
|
804
|
+
}
|
805
|
+
}
|
806
|
+
printf("%s [%c] %s : %s\n", indent, h->type, clas, key);
|
807
|
+
}
|
884
808
|
}
|
885
809
|
}
|