ox 2.0.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ox might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +121 -128
- data/ext/ox/attr.h +109 -0
- data/ext/ox/err.c +64 -0
- data/ext/ox/err.h +61 -0
- data/ext/ox/gen_load.c +32 -33
- data/ext/ox/helper.h +116 -0
- data/ext/ox/obj_load.c +551 -518
- data/ext/ox/ox.c +43 -20
- data/ext/ox/ox.h +9 -47
- data/ext/ox/parse.c +146 -70
- data/ext/ox/sax.c +19 -1
- data/ext/ox/sax_buf.c +5 -4
- data/ext/ox/sax_has.h +2 -0
- data/ext/ox/sax_stack.h +3 -3
- data/ext/ox/type.h +63 -0
- data/lib/ox/sax.rb +12 -6
- data/lib/ox/version.rb +1 -1
- metadata +8 -4
data/ext/ox/err.h
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
/* err.h
|
2
|
+
* Copyright (c) 2011, Peter Ohler
|
3
|
+
* All rights reserved.
|
4
|
+
*
|
5
|
+
* Redistribution and use in source and binary forms, with or without
|
6
|
+
* modification, are permitted provided that the following conditions are met:
|
7
|
+
*
|
8
|
+
* - Redistributions of source code must retain the above copyright notice, this
|
9
|
+
* list of conditions and the following disclaimer.
|
10
|
+
*
|
11
|
+
* - Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
* this list of conditions and the following disclaimer in the documentation
|
13
|
+
* and/or other materials provided with the distribution.
|
14
|
+
*
|
15
|
+
* - Neither the name of Peter Ohler nor the names of its contributors may be
|
16
|
+
* used to endorse or promote products derived from this software without
|
17
|
+
* specific prior written permission.
|
18
|
+
*
|
19
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
22
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
23
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
25
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
26
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
27
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
*/
|
30
|
+
|
31
|
+
#ifndef __OX_ERR_H__
|
32
|
+
#define __OX_ERR_H__
|
33
|
+
|
34
|
+
#include "ruby.h"
|
35
|
+
|
36
|
+
#define set_error(err, msg, xml, current) _ox_err_set_with_location(err, msg, xml, current, __FILE__, __LINE__)
|
37
|
+
|
38
|
+
typedef struct _Err {
|
39
|
+
VALUE clas;
|
40
|
+
char msg[128];
|
41
|
+
} *Err;
|
42
|
+
|
43
|
+
extern VALUE ox_arg_error_class;
|
44
|
+
extern VALUE ox_parse_error_class;
|
45
|
+
|
46
|
+
extern void ox_err_set(Err e, VALUE clas, const char *format, ...);
|
47
|
+
extern void _ox_err_set_with_location(Err err, const char *msg, const char *xml, const char *current, const char* file, int line);
|
48
|
+
extern void ox_err_raise(Err e);
|
49
|
+
|
50
|
+
inline static void
|
51
|
+
err_init(Err e) {
|
52
|
+
e->clas = Qnil;
|
53
|
+
*e->msg = '\0';
|
54
|
+
}
|
55
|
+
|
56
|
+
inline static int
|
57
|
+
err_has(Err e) {
|
58
|
+
return (Qnil != e->clas);
|
59
|
+
}
|
60
|
+
|
61
|
+
#endif /* __OX_ERR_H__ */
|
data/ext/ox/gen_load.c
CHANGED
@@ -92,12 +92,12 @@ create_doc(PInfo pi) {
|
|
92
92
|
VALUE doc;
|
93
93
|
VALUE nodes;
|
94
94
|
|
95
|
-
pi->
|
95
|
+
helper_stack_init(&pi->helpers);
|
96
96
|
doc = rb_obj_alloc(ox_document_clas);
|
97
97
|
nodes = rb_ary_new();
|
98
98
|
rb_ivar_set(doc, ox_attributes_id, rb_hash_new());
|
99
99
|
rb_ivar_set(doc, ox_nodes_id, nodes);
|
100
|
-
pi->
|
100
|
+
helper_stack_push(&pi->helpers, 0, nodes, NoCode);
|
101
101
|
pi->obj = doc;
|
102
102
|
}
|
103
103
|
|
@@ -108,10 +108,10 @@ create_prolog_doc(PInfo pi, const char *target, Attr attrs) {
|
|
108
108
|
VALUE nodes;
|
109
109
|
VALUE sym;
|
110
110
|
|
111
|
-
if (
|
112
|
-
|
111
|
+
if (!helper_stack_empty(&pi->helpers)) { /* top level object */
|
112
|
+
ox_err_set(&pi->err, rb_eSyntaxError, "Prolog must be the first element in an XML document.\n");
|
113
|
+
return;
|
113
114
|
}
|
114
|
-
pi->h = pi->helpers;
|
115
115
|
doc = rb_obj_alloc(ox_document_clas);
|
116
116
|
ah = rb_hash_new();
|
117
117
|
for (; 0 != attrs->name; attrs++) {
|
@@ -165,7 +165,7 @@ create_prolog_doc(PInfo pi, const char *target, Attr attrs) {
|
|
165
165
|
nodes = rb_ary_new();
|
166
166
|
rb_ivar_set(doc, ox_attributes_id, ah);
|
167
167
|
rb_ivar_set(doc, ox_nodes_id, nodes);
|
168
|
-
pi->
|
168
|
+
helper_stack_push(&pi->helpers, 0, nodes, ArrayCode);
|
169
169
|
pi->obj = doc;
|
170
170
|
}
|
171
171
|
|
@@ -177,7 +177,8 @@ instruct(PInfo pi, const char *target, Attr attrs, const char *content) {
|
|
177
177
|
for (; 0 != attrs->name; attrs++) {
|
178
178
|
if (0 == strcmp("version", attrs->name)) {
|
179
179
|
if (0 != strcmp("1.0", attrs->value)) {
|
180
|
-
|
180
|
+
ox_err_set(&pi->err, rb_eSyntaxError, "Only Ox XML Object version 1.0 supported, not %s.\n", attrs->value);
|
181
|
+
return;
|
181
182
|
}
|
182
183
|
}
|
183
184
|
/* ignore other instructions */
|
@@ -195,21 +196,23 @@ nomode_instruct(PInfo pi, const char *target, Attr attrs, const char *content) {
|
|
195
196
|
for (; 0 != attrs->name; attrs++) {
|
196
197
|
if (0 == strcmp("version", attrs->name)) {
|
197
198
|
if (0 != strcmp("1.0", attrs->value)) {
|
198
|
-
|
199
|
+
ox_err_set(&pi->err, rb_eSyntaxError, "Only Ox XML Object version 1.0 supported, not %s.\n", attrs->value);
|
200
|
+
return;
|
199
201
|
}
|
200
202
|
} else if (0 == strcmp("mode", attrs->name)) {
|
201
203
|
if (0 == strcmp("object", attrs->value)) {
|
202
204
|
pi->pcb = ox_obj_callbacks;
|
203
205
|
pi->obj = Qnil;
|
204
|
-
|
206
|
+
helper_stack_init(&pi->helpers);
|
205
207
|
} else if (0 == strcmp("generic", attrs->value)) {
|
206
208
|
pi->pcb = ox_gen_callbacks;
|
207
209
|
} else if (0 == strcmp("limited", attrs->value)) {
|
208
210
|
pi->pcb = ox_limited_callbacks;
|
209
211
|
pi->obj = Qnil;
|
210
|
-
|
212
|
+
helper_stack_init(&pi->helpers);
|
211
213
|
} else {
|
212
|
-
|
214
|
+
ox_err_set(&pi->err, rb_eSyntaxError, "%s is not a valid processing instruction mode.\n", attrs->value);
|
215
|
+
return;
|
213
216
|
}
|
214
217
|
}
|
215
218
|
}
|
@@ -235,10 +238,10 @@ add_doctype(PInfo pi, const char *docType) {
|
|
235
238
|
}
|
236
239
|
#endif
|
237
240
|
rb_ivar_set(n, ox_at_value_id, s);
|
238
|
-
if (
|
241
|
+
if (helper_stack_empty(&pi->helpers)) { /* top level object */
|
239
242
|
create_doc(pi);
|
240
243
|
}
|
241
|
-
rb_ary_push(pi->
|
244
|
+
rb_ary_push(helper_stack_peek(&pi->helpers)->obj, n);
|
242
245
|
}
|
243
246
|
|
244
247
|
static void
|
@@ -256,10 +259,10 @@ add_comment(PInfo pi, const char *comment) {
|
|
256
259
|
}
|
257
260
|
#endif
|
258
261
|
rb_ivar_set(n, ox_at_value_id, s);
|
259
|
-
if (
|
262
|
+
if (helper_stack_empty(&pi->helpers)) { /* top level object */
|
260
263
|
create_doc(pi);
|
261
264
|
}
|
262
|
-
rb_ary_push(pi->
|
265
|
+
rb_ary_push(helper_stack_peek(&pi->helpers)->obj, n);
|
263
266
|
}
|
264
267
|
|
265
268
|
static void
|
@@ -277,10 +280,10 @@ add_cdata(PInfo pi, const char *cdata, size_t len) {
|
|
277
280
|
}
|
278
281
|
#endif
|
279
282
|
rb_ivar_set(n, ox_at_value_id, s);
|
280
|
-
if (
|
283
|
+
if (helper_stack_empty(&pi->helpers)) { /* top level object */
|
281
284
|
create_doc(pi);
|
282
285
|
}
|
283
|
-
rb_ary_push(pi->
|
286
|
+
rb_ary_push(helper_stack_peek(&pi->helpers)->obj, n);
|
284
287
|
}
|
285
288
|
|
286
289
|
static void
|
@@ -296,10 +299,10 @@ add_text(PInfo pi, char *text, int closed) {
|
|
296
299
|
rb_funcall(s, ox_force_encoding_id, 1, pi->options->rb_enc);
|
297
300
|
}
|
298
301
|
#endif
|
299
|
-
if (
|
302
|
+
if (helper_stack_empty(&pi->helpers)) { /* top level object */
|
300
303
|
create_doc(pi);
|
301
304
|
}
|
302
|
-
rb_ary_push(pi->
|
305
|
+
rb_ary_push(helper_stack_peek(&pi->helpers)->obj, s);
|
303
306
|
}
|
304
307
|
|
305
308
|
static void
|
@@ -376,29 +379,25 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
376
379
|
}
|
377
380
|
rb_ivar_set(e, ox_attributes_id, ah);
|
378
381
|
}
|
379
|
-
if (
|
380
|
-
|
381
|
-
pi->obj = e;
|
382
|
+
if (helper_stack_empty(&pi->helpers)) { /* top level object */
|
383
|
+
pi->obj = e;
|
382
384
|
} else {
|
383
|
-
|
384
|
-
pi->h++;
|
385
|
+
rb_ary_push(helper_stack_peek(&pi->helpers)->obj, e);
|
385
386
|
}
|
386
387
|
if (hasChildren) {
|
387
388
|
VALUE nodes = rb_ary_new();
|
388
389
|
|
389
390
|
rb_ivar_set(e, ox_nodes_id, nodes);
|
390
|
-
|
391
|
+
helper_stack_push(&pi->helpers, 0, nodes, NoCode);
|
392
|
+
} else {
|
393
|
+
helper_stack_push(&pi->helpers, 0, Qnil, NoCode); // will be popped in end_element
|
391
394
|
}
|
392
395
|
}
|
393
396
|
|
394
397
|
static void
|
395
398
|
end_element(PInfo pi, const char *ename) {
|
396
|
-
if (
|
397
|
-
|
398
|
-
pi->h--;
|
399
|
-
} else {
|
400
|
-
pi->h = 0;
|
401
|
-
}
|
399
|
+
if (!helper_stack_empty(&pi->helpers)) {
|
400
|
+
helper_stack_pop(&pi->helpers);
|
402
401
|
}
|
403
402
|
}
|
404
403
|
|
@@ -488,8 +487,8 @@ add_instruct(PInfo pi, const char *name, Attr attrs, const char *content) {
|
|
488
487
|
}
|
489
488
|
rb_ivar_set(inst, ox_attributes_id, ah);
|
490
489
|
}
|
491
|
-
if (
|
490
|
+
if (helper_stack_empty(&pi->helpers)) { /* top level object */
|
492
491
|
create_doc(pi);
|
493
492
|
}
|
494
|
-
rb_ary_push(pi->
|
493
|
+
rb_ary_push(helper_stack_peek(&pi->helpers)->obj, inst);
|
495
494
|
}
|
data/ext/ox/helper.h
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
/* helper.h
|
2
|
+
* Copyright (c) 2011, Peter Ohler
|
3
|
+
* All rights reserved.
|
4
|
+
*
|
5
|
+
* Redistribution and use in source and binary forms, with or without
|
6
|
+
* modification, are permitted provided that the following conditions are met:
|
7
|
+
*
|
8
|
+
* - Redistributions of source code must retain the above copyright notice, this
|
9
|
+
* list of conditions and the following disclaimer.
|
10
|
+
*
|
11
|
+
* - Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
* this list of conditions and the following disclaimer in the documentation
|
13
|
+
* and/or other materials provided with the distribution.
|
14
|
+
*
|
15
|
+
* - Neither the name of Peter Ohler nor the names of its contributors may be
|
16
|
+
* used to endorse or promote products derived from this software without
|
17
|
+
* specific prior written permission.
|
18
|
+
*
|
19
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
22
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
23
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
25
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
26
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
27
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
*/
|
30
|
+
|
31
|
+
#ifndef __OX_HELPER_H__
|
32
|
+
#define __OX_HELPER_H__
|
33
|
+
|
34
|
+
#include "type.h"
|
35
|
+
|
36
|
+
#define HELPER_STACK_INC 16
|
37
|
+
|
38
|
+
typedef struct _Helper {
|
39
|
+
ID var; /* Object var ID */
|
40
|
+
VALUE obj; /* object created or Qundef if not appropriate */
|
41
|
+
Type type; /* type of object in obj */
|
42
|
+
} *Helper;
|
43
|
+
|
44
|
+
typedef struct _HelperStack {
|
45
|
+
struct _Helper base[HELPER_STACK_INC];
|
46
|
+
Helper head; /* current stack */
|
47
|
+
Helper end; /* stack end */
|
48
|
+
Helper tail; /* pointer to one past last element name on stack */
|
49
|
+
} *HelperStack;
|
50
|
+
|
51
|
+
inline static void
|
52
|
+
helper_stack_init(HelperStack stack) {
|
53
|
+
stack->head = stack->base;
|
54
|
+
stack->end = stack->base + sizeof(stack->base) / sizeof(struct _Helper);
|
55
|
+
stack->tail = stack->head;
|
56
|
+
}
|
57
|
+
|
58
|
+
inline static int
|
59
|
+
helper_stack_empty(HelperStack stack) {
|
60
|
+
return (stack->head == stack->tail);
|
61
|
+
}
|
62
|
+
|
63
|
+
inline static int
|
64
|
+
helper_stack_depth(HelperStack stack) {
|
65
|
+
return (int)(stack->tail - stack->head);
|
66
|
+
}
|
67
|
+
|
68
|
+
inline static void
|
69
|
+
helper_stack_cleanup(HelperStack stack) {
|
70
|
+
if (stack->base != stack->head) {
|
71
|
+
xfree(stack->head);
|
72
|
+
stack->head = stack->base;
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
inline static Helper
|
77
|
+
helper_stack_push(HelperStack stack, ID var, VALUE obj, Type type) {
|
78
|
+
if (stack->end <= stack->tail) {
|
79
|
+
size_t len = stack->end - stack->head;
|
80
|
+
size_t toff = stack->tail - stack->head;
|
81
|
+
|
82
|
+
if (stack->base == stack->head) {
|
83
|
+
stack->head = ALLOC_N(struct _Helper, len + HELPER_STACK_INC);
|
84
|
+
memcpy(stack->head, stack->base, sizeof(struct _Helper) * len);
|
85
|
+
} else {
|
86
|
+
REALLOC_N(stack->head, struct _Helper, len + HELPER_STACK_INC);
|
87
|
+
}
|
88
|
+
stack->tail = stack->head + toff;
|
89
|
+
stack->end = stack->head + len + HELPER_STACK_INC;
|
90
|
+
}
|
91
|
+
stack->tail->var = var;
|
92
|
+
stack->tail->obj = obj;
|
93
|
+
stack->tail->type = type;
|
94
|
+
stack->tail++;
|
95
|
+
|
96
|
+
return stack->tail - 1;
|
97
|
+
}
|
98
|
+
|
99
|
+
inline static Helper
|
100
|
+
helper_stack_peek(HelperStack stack) {
|
101
|
+
if (stack->head < stack->tail) {
|
102
|
+
return stack->tail - 1;
|
103
|
+
}
|
104
|
+
return 0;
|
105
|
+
}
|
106
|
+
|
107
|
+
inline static Helper
|
108
|
+
helper_stack_pop(HelperStack stack) {
|
109
|
+
if (stack->head < stack->tail) {
|
110
|
+
stack->tail--;
|
111
|
+
return stack->tail;
|
112
|
+
}
|
113
|
+
return 0;
|
114
|
+
}
|
115
|
+
|
116
|
+
#endif /* __OX_HELPER_H__ */
|
data/ext/ox/obj_load.c
CHANGED
@@ -39,31 +39,31 @@
|
|
39
39
|
#include "base64.h"
|
40
40
|
#include "ox.h"
|
41
41
|
|
42
|
-
static void
|
43
|
-
static void
|
44
|
-
static void
|
45
|
-
static void
|
46
|
-
|
47
|
-
static VALUE
|
48
|
-
static VALUE
|
49
|
-
static VALUE
|
50
|
-
static VALUE
|
51
|
-
|
52
|
-
static VALUE
|
53
|
-
static VALUE
|
54
|
-
static VALUE
|
55
|
-
static VALUE
|
56
|
-
static unsigned long
|
57
|
-
static CircArray
|
58
|
-
static void
|
59
|
-
static void
|
60
|
-
static VALUE
|
61
|
-
|
62
|
-
static void
|
63
|
-
static void
|
64
|
-
|
65
|
-
|
66
|
-
struct _ParseCallbacks
|
42
|
+
static void instruct(PInfo pi, const char *target, Attr attrs, const char *content);
|
43
|
+
static void add_text(PInfo pi, char *text, int closed);
|
44
|
+
static void add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren);
|
45
|
+
static void end_element(PInfo pi, const char *ename);
|
46
|
+
|
47
|
+
static VALUE parse_time(const char *text, VALUE clas);
|
48
|
+
static VALUE parse_xsd_time(const char *text, VALUE clas);
|
49
|
+
static VALUE parse_double_time(const char *text, VALUE clas);
|
50
|
+
static VALUE parse_regexp(const char *text);
|
51
|
+
|
52
|
+
static VALUE get_var_sym_from_attrs(Attr a, void *encoding);
|
53
|
+
static VALUE get_obj_from_attrs(Attr a, PInfo pi, VALUE base_class);
|
54
|
+
static VALUE get_class_from_attrs(Attr a, PInfo pi, VALUE base_class);
|
55
|
+
static VALUE classname2class(const char *name, PInfo pi, VALUE base_class);
|
56
|
+
static unsigned long get_id_from_attrs(PInfo pi, Attr a);
|
57
|
+
static CircArray circ_array_new(void);
|
58
|
+
static void circ_array_free(CircArray ca);
|
59
|
+
static void circ_array_set(CircArray ca, VALUE obj, unsigned long id);
|
60
|
+
static VALUE circ_array_get(CircArray ca, unsigned long id);
|
61
|
+
|
62
|
+
static void debug_stack(PInfo pi, const char *comment);
|
63
|
+
static void fill_indent(PInfo pi, char *buf, size_t size);
|
64
|
+
|
65
|
+
|
66
|
+
struct _ParseCallbacks _ox_obj_callbacks = {
|
67
67
|
instruct, /* instruct, */
|
68
68
|
0, /* add_doctype, */
|
69
69
|
0, /* add_comment, */
|
@@ -73,9 +73,9 @@ struct _ParseCallbacks _ox_obj_callbacks = {
|
|
73
73
|
end_element,
|
74
74
|
};
|
75
75
|
|
76
|
-
ParseCallbacks
|
76
|
+
ParseCallbacks ox_obj_callbacks = &_ox_obj_callbacks;
|
77
77
|
|
78
|
-
extern ParseCallbacks
|
78
|
+
extern ParseCallbacks ox_gen_callbacks;
|
79
79
|
|
80
80
|
|
81
81
|
inline static VALUE
|
@@ -99,11 +99,11 @@ str2sym(const char *str, void *encoding) {
|
|
99
99
|
|
100
100
|
inline static ID
|
101
101
|
name2var(const char *name, void *encoding) {
|
102
|
-
VALUE
|
103
|
-
ID
|
102
|
+
VALUE *slot;
|
103
|
+
ID var_id;
|
104
104
|
|
105
105
|
if ('0' <= *name && *name <= '9') {
|
106
|
-
|
106
|
+
var_id = INT2NUM(atoi(name));
|
107
107
|
} else if (Qundef == (var_id = ox_cache_get(ox_attr_cache, name, &slot, 0))) {
|
108
108
|
#ifdef HAVE_RUBY_ENCODING_H
|
109
109
|
if (0 != encoding) {
|
@@ -119,36 +119,36 @@ name2var(const char *name, void *encoding) {
|
|
119
119
|
#else
|
120
120
|
var_id = rb_intern(name);
|
121
121
|
#endif
|
122
|
-
|
122
|
+
*slot = var_id;
|
123
123
|
}
|
124
124
|
return var_id;
|
125
125
|
}
|
126
126
|
|
127
127
|
inline static VALUE
|
128
128
|
resolve_classname(VALUE mod, const char *class_name, Effort effort, VALUE base_class) {
|
129
|
-
VALUE
|
130
|
-
ID
|
129
|
+
VALUE clas;
|
130
|
+
ID ci = rb_intern(class_name);
|
131
131
|
|
132
132
|
switch (effort) {
|
133
133
|
case TolerantEffort:
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
134
|
+
if (rb_const_defined_at(mod, ci)) {
|
135
|
+
clas = rb_const_get_at(mod, ci);
|
136
|
+
} else {
|
137
|
+
clas = Qundef;
|
138
|
+
}
|
139
|
+
break;
|
140
140
|
case AutoEffort:
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
141
|
+
if (rb_const_defined_at(mod, ci)) {
|
142
|
+
clas = rb_const_get_at(mod, ci);
|
143
|
+
} else {
|
144
|
+
clas = rb_define_class_under(mod, class_name, base_class);
|
145
|
+
}
|
146
|
+
break;
|
147
147
|
case StrictEffort:
|
148
148
|
default:
|
149
|
-
|
150
|
-
|
151
|
-
|
149
|
+
/* raise an error if name is not defined */
|
150
|
+
clas = rb_const_get_at(mod, ci);
|
151
|
+
break;
|
152
152
|
}
|
153
153
|
return clas;
|
154
154
|
}
|
@@ -158,26 +158,26 @@ classname2obj(const char *name, PInfo pi, VALUE base_class) {
|
|
158
158
|
VALUE clas = classname2class(name, pi, base_class);
|
159
159
|
|
160
160
|
if (Qundef == clas) {
|
161
|
-
|
161
|
+
return Qnil;
|
162
162
|
} else {
|
163
|
-
|
163
|
+
return rb_obj_alloc(clas);
|
164
164
|
}
|
165
165
|
}
|
166
166
|
|
167
167
|
#if HAS_RSTRUCT
|
168
168
|
inline static VALUE
|
169
169
|
structname2obj(const char *name) {
|
170
|
-
VALUE
|
171
|
-
const char
|
170
|
+
VALUE ost;
|
171
|
+
const char *s = name;
|
172
172
|
|
173
173
|
for (; 1; s++) {
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
174
|
+
if ('\0' == *s) {
|
175
|
+
s = name;
|
176
|
+
break;
|
177
|
+
} else if (':' == *s) {
|
178
|
+
s += 2;
|
179
|
+
break;
|
180
|
+
}
|
181
181
|
}
|
182
182
|
ost = rb_const_get(ox_struct_class, rb_intern(s));
|
183
183
|
/* use encoding as the indicator for Ruby 1.8.7 or 1.9.x */
|
@@ -199,7 +199,8 @@ parse_ulong(const char *s, PInfo pi) {
|
|
199
199
|
if ('0' <= *s && *s <= '9') {
|
200
200
|
n = n * 10 + (*s - '0');
|
201
201
|
} else {
|
202
|
-
|
202
|
+
set_error(&pi->err, "Invalid number for a julian day", pi->str, pi->s);
|
203
|
+
return Qundef;
|
203
204
|
}
|
204
205
|
}
|
205
206
|
return ULONG2NUM(n);
|
@@ -208,49 +209,50 @@ parse_ulong(const char *s, PInfo pi) {
|
|
208
209
|
/* 2010-07-09T10:47:45.895826162+09:00 */
|
209
210
|
inline static VALUE
|
210
211
|
parse_time(const char *text, VALUE clas) {
|
211
|
-
VALUE
|
212
|
+
VALUE t;
|
212
213
|
|
213
214
|
if (Qnil == (t = parse_double_time(text, clas)) &&
|
214
|
-
|
215
|
-
|
215
|
+
Qnil == (t = parse_xsd_time(text, clas))) {
|
216
|
+
VALUE args[1];
|
216
217
|
|
217
|
-
|
218
|
-
|
219
|
-
|
218
|
+
/*printf("**** time parse\n"); */
|
219
|
+
*args = rb_str_new2(text);
|
220
|
+
t = rb_funcall2(ox_time_class, ox_parse_id, 1, args);
|
220
221
|
}
|
221
222
|
return t;
|
222
223
|
}
|
223
224
|
|
224
225
|
static VALUE
|
225
226
|
classname2class(const char *name, PInfo pi, VALUE base_class) {
|
226
|
-
VALUE
|
227
|
-
VALUE
|
228
|
-
|
227
|
+
VALUE *slot;
|
228
|
+
VALUE clas;
|
229
|
+
|
229
230
|
if (Qundef == (clas = ox_cache_get(ox_class_cache, name, &slot, 0))) {
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
231
|
+
char class_name[1024];
|
232
|
+
char *s;
|
233
|
+
const char *n = name;
|
234
|
+
|
235
|
+
clas = rb_cObject;
|
236
|
+
for (s = class_name; '\0' != *n; n++) {
|
237
|
+
if (':' == *n) {
|
238
|
+
*s = '\0';
|
239
|
+
n++;
|
239
240
|
if (':' != *n) {
|
240
|
-
|
241
|
+
set_error(&pi->err, "Invalid classname, expected another ':'", pi->str, pi->s);
|
242
|
+
return Qundef;
|
241
243
|
}
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
244
|
+
if (Qundef == (clas = resolve_classname(clas, class_name, pi->options->effort, base_class))) {
|
245
|
+
return Qundef;
|
246
|
+
}
|
247
|
+
s = class_name;
|
248
|
+
} else {
|
249
|
+
*s++ = *n;
|
250
|
+
}
|
251
|
+
}
|
252
|
+
*s = '\0';
|
253
|
+
if (Qundef != (clas = resolve_classname(clas, class_name, pi->options->effort, base_class))) {
|
254
|
+
*slot = clas;
|
255
|
+
}
|
254
256
|
}
|
255
257
|
return clas;
|
256
258
|
}
|
@@ -258,9 +260,9 @@ classname2class(const char *name, PInfo pi, VALUE base_class) {
|
|
258
260
|
static VALUE
|
259
261
|
get_var_sym_from_attrs(Attr a, void *encoding) {
|
260
262
|
for (; 0 != a->name; a++) {
|
261
|
-
|
262
|
-
|
263
|
-
|
263
|
+
if ('a' == *a->name && '\0' == *(a->name + 1)) {
|
264
|
+
return name2var(a->value, encoding);
|
265
|
+
}
|
264
266
|
}
|
265
267
|
return Qundef;
|
266
268
|
}
|
@@ -268,9 +270,9 @@ get_var_sym_from_attrs(Attr a, void *encoding) {
|
|
268
270
|
static VALUE
|
269
271
|
get_obj_from_attrs(Attr a, PInfo pi, VALUE base_class) {
|
270
272
|
for (; 0 != a->name; a++) {
|
271
|
-
|
272
|
-
|
273
|
-
|
273
|
+
if ('c' == *a->name && '\0' == *(a->name + 1)) {
|
274
|
+
return classname2obj(a->value, pi, base_class);
|
275
|
+
}
|
274
276
|
}
|
275
277
|
return Qundef;
|
276
278
|
}
|
@@ -279,9 +281,9 @@ get_obj_from_attrs(Attr a, PInfo pi, VALUE base_class) {
|
|
279
281
|
static VALUE
|
280
282
|
get_struct_from_attrs(Attr a) {
|
281
283
|
for (; 0 != a->name; a++) {
|
282
|
-
|
283
|
-
|
284
|
-
|
284
|
+
if ('c' == *a->name && '\0' == *(a->name + 1)) {
|
285
|
+
return structname2obj(a->value);
|
286
|
+
}
|
285
287
|
}
|
286
288
|
return Qundef;
|
287
289
|
}
|
@@ -290,9 +292,9 @@ get_struct_from_attrs(Attr a) {
|
|
290
292
|
static VALUE
|
291
293
|
get_class_from_attrs(Attr a, PInfo pi, VALUE base_class) {
|
292
294
|
for (; 0 != a->name; a++) {
|
293
|
-
|
294
|
-
|
295
|
-
|
295
|
+
if ('c' == *a->name && '\0' == *(a->name + 1)) {
|
296
|
+
return classname2class(a->value, pi, base_class);
|
297
|
+
}
|
296
298
|
}
|
297
299
|
return Qundef;
|
298
300
|
}
|
@@ -300,28 +302,29 @@ get_class_from_attrs(Attr a, PInfo pi, VALUE base_class) {
|
|
300
302
|
static unsigned long
|
301
303
|
get_id_from_attrs(PInfo pi, Attr a) {
|
302
304
|
for (; 0 != a->name; a++) {
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
305
|
+
if ('i' == *a->name && '\0' == *(a->name + 1)) {
|
306
|
+
unsigned long id = 0;
|
307
|
+
const char *text = a->value;
|
308
|
+
char c;
|
309
|
+
|
310
|
+
for (; '\0' != *text; text++) {
|
311
|
+
c = *text;
|
312
|
+
if ('0' <= c && c <= '9') {
|
313
|
+
id = id * 10 + (c - '0');
|
314
|
+
} else {
|
315
|
+
set_error(&pi->err, "bad number format", pi->str, pi->s);
|
316
|
+
return 0;
|
317
|
+
}
|
318
|
+
}
|
319
|
+
return id;
|
320
|
+
}
|
318
321
|
}
|
319
322
|
return 0;
|
320
323
|
}
|
321
324
|
|
322
325
|
static CircArray
|
323
326
|
circ_array_new() {
|
324
|
-
CircArray
|
327
|
+
CircArray ca;
|
325
328
|
|
326
329
|
ca = ALLOC(struct _CircArray);
|
327
330
|
ca->objs = ca->obj_array;
|
@@ -334,7 +337,7 @@ circ_array_new() {
|
|
334
337
|
static void
|
335
338
|
circ_array_free(CircArray ca) {
|
336
339
|
if (ca->objs != ca->obj_array) {
|
337
|
-
|
340
|
+
xfree(ca->objs);
|
338
341
|
}
|
339
342
|
xfree(ca);
|
340
343
|
}
|
@@ -342,54 +345,54 @@ circ_array_free(CircArray ca) {
|
|
342
345
|
static void
|
343
346
|
circ_array_set(CircArray ca, VALUE obj, unsigned long id) {
|
344
347
|
if (0 < id) {
|
345
|
-
|
348
|
+
unsigned long i;
|
346
349
|
|
347
|
-
|
348
|
-
|
350
|
+
if (ca->size < id) {
|
351
|
+
unsigned long cnt = id + 512;
|
349
352
|
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
353
|
+
if (ca->objs == ca->obj_array) {
|
354
|
+
ca->objs = ALLOC_N(VALUE, cnt);
|
355
|
+
memcpy(ca->objs, ca->obj_array, sizeof(VALUE) * ca->cnt);
|
356
|
+
} else {
|
354
357
|
REALLOC_N(ca->objs, VALUE, cnt);
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
358
|
+
}
|
359
|
+
ca->size = cnt;
|
360
|
+
}
|
361
|
+
id--;
|
362
|
+
for (i = ca->cnt; i < id; i++) {
|
363
|
+
ca->objs[i] = Qundef;
|
364
|
+
}
|
365
|
+
ca->objs[id] = obj;
|
366
|
+
if (ca->cnt <= id) {
|
367
|
+
ca->cnt = id + 1;
|
368
|
+
}
|
366
369
|
}
|
367
370
|
}
|
368
371
|
|
369
372
|
static VALUE
|
370
373
|
circ_array_get(CircArray ca, unsigned long id) {
|
371
|
-
VALUE
|
374
|
+
VALUE obj = Qundef;
|
372
375
|
|
373
376
|
if (id <= ca->cnt) {
|
374
|
-
|
377
|
+
obj = ca->objs[id - 1];
|
375
378
|
}
|
376
379
|
return obj;
|
377
380
|
}
|
378
381
|
|
379
382
|
static VALUE
|
380
383
|
parse_regexp(const char *text) {
|
381
|
-
const char
|
382
|
-
int
|
383
|
-
|
384
|
+
const char *te;
|
385
|
+
int options = 0;
|
386
|
+
|
384
387
|
te = text + strlen(text) - 1;
|
385
388
|
#if HAS_ONIG
|
386
389
|
for (; text < te && '/' != *te; te--) {
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
390
|
+
switch (*te) {
|
391
|
+
case 'i': options |= ONIG_OPTION_IGNORECASE; break;
|
392
|
+
case 'm': options |= ONIG_OPTION_MULTILINE; break;
|
393
|
+
case 'x': options |= ONIG_OPTION_EXTEND; break;
|
394
|
+
default: break;
|
395
|
+
}
|
393
396
|
}
|
394
397
|
#endif
|
395
398
|
return rb_reg_new(text + 1, te - text - 1, options);
|
@@ -399,214 +402,221 @@ static void
|
|
399
402
|
instruct(PInfo pi, const char *target, Attr attrs, const char *content) {
|
400
403
|
if (0 == strcmp("xml", target)) {
|
401
404
|
#if HAS_ENCODING_SUPPORT
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
405
|
+
for (; 0 != attrs->name; attrs++) {
|
406
|
+
if (0 == strcmp("encoding", attrs->name)) {
|
407
|
+
pi->options->rb_enc = rb_enc_find(attrs->value);
|
408
|
+
}
|
409
|
+
}
|
407
410
|
#elif HAS_PRIVATE_ENCODING
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
411
|
+
for (; 0 != attrs->name; attrs++) {
|
412
|
+
if (0 == strcmp("encoding", attrs->name)) {
|
413
|
+
pi->options->rb_enc = rb_str_new2(attrs->value);
|
414
|
+
}
|
415
|
+
}
|
413
416
|
#endif
|
414
417
|
}
|
415
418
|
}
|
416
419
|
|
417
420
|
static void
|
418
421
|
add_text(PInfo pi, char *text, int closed) {
|
422
|
+
Helper h = helper_stack_peek(&pi->helpers);
|
423
|
+
|
419
424
|
if (!closed) {
|
420
|
-
|
425
|
+
set_error(&pi->err, "Text not closed", pi->str, pi->s);
|
426
|
+
return;
|
427
|
+
}
|
428
|
+
if (0 == h) {
|
429
|
+
set_error(&pi->err, "Unexpected text", pi->str, pi->s);
|
430
|
+
return;
|
421
431
|
}
|
422
432
|
if (DEBUG <= pi->options->trace) {
|
423
|
-
|
433
|
+
char indent[128];
|
424
434
|
|
425
|
-
|
426
|
-
|
435
|
+
fill_indent(pi, indent, sizeof(indent));
|
436
|
+
printf("%s '%s' to type %c\n", indent, text, h->type);
|
427
437
|
}
|
428
|
-
switch (
|
438
|
+
switch (h->type) {
|
429
439
|
case NoCode:
|
430
440
|
case StringCode:
|
431
|
-
|
441
|
+
h->obj = rb_str_new2(text);
|
432
442
|
#if HAS_ENCODING_SUPPORT
|
433
|
-
|
434
|
-
|
435
|
-
|
443
|
+
if (0 != pi->options->rb_enc) {
|
444
|
+
rb_enc_associate(h->obj, pi->options->rb_enc);
|
445
|
+
}
|
436
446
|
#elif HAS_PRIVATE_ENCODING
|
437
|
-
|
438
|
-
rb_funcall(
|
439
|
-
|
447
|
+
if (Qnil != pi->options->rb_enc) {
|
448
|
+
rb_funcall(h->obj, ox_force_encoding_id, 1, pi->options->rb_enc);
|
449
|
+
}
|
440
450
|
#endif
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
451
|
+
if (0 != pi->circ_array) {
|
452
|
+
circ_array_set(pi->circ_array, h->obj, (unsigned long)pi->id);
|
453
|
+
}
|
454
|
+
break;
|
445
455
|
case FixnumCode:
|
446
456
|
{
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
457
|
+
long n = 0;
|
458
|
+
char c;
|
459
|
+
int neg = 0;
|
460
|
+
|
461
|
+
if ('-' == *text) {
|
462
|
+
neg = 1;
|
463
|
+
text++;
|
464
|
+
}
|
465
|
+
for (; '\0' != *text; text++) {
|
466
|
+
c = *text;
|
467
|
+
if ('0' <= c && c <= '9') {
|
468
|
+
n = n * 10 + (c - '0');
|
469
|
+
} else {
|
470
|
+
set_error(&pi->err, "bad number format", pi->str, pi->s);
|
471
|
+
return;
|
472
|
+
}
|
473
|
+
}
|
474
|
+
if (neg) {
|
475
|
+
n = -n;
|
476
|
+
}
|
477
|
+
h->obj = LONG2NUM(n);
|
478
|
+
break;
|
468
479
|
}
|
469
480
|
case FloatCode:
|
470
|
-
|
471
|
-
|
481
|
+
h->obj = rb_float_new(strtod(text, 0));
|
482
|
+
break;
|
472
483
|
case SymbolCode:
|
473
484
|
{
|
474
|
-
|
475
|
-
|
485
|
+
VALUE sym;
|
486
|
+
VALUE *slot;
|
476
487
|
|
477
|
-
|
488
|
+
if (Qundef == (sym = ox_cache_get(ox_symbol_cache, text, &slot, 0))) {
|
478
489
|
sym = str2sym(text, (void*)pi->options->rb_enc);
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
490
|
+
*slot = sym;
|
491
|
+
}
|
492
|
+
h->obj = sym;
|
493
|
+
break;
|
483
494
|
}
|
484
495
|
case DateCode:
|
485
496
|
{
|
486
497
|
VALUE args[1];
|
487
498
|
|
488
|
-
*args = parse_ulong(text, pi)
|
489
|
-
|
490
|
-
|
499
|
+
if (Qundef == (*args = parse_ulong(text, pi))) {
|
500
|
+
return;
|
501
|
+
}
|
502
|
+
h->obj = rb_funcall2(ox_date_class, ox_jd_id, 1, args);
|
503
|
+
break;
|
491
504
|
}
|
492
505
|
case TimeCode:
|
493
|
-
|
494
|
-
|
506
|
+
h->obj = parse_time(text, ox_time_class);
|
507
|
+
break;
|
495
508
|
case String64Code:
|
496
509
|
{
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
510
|
+
unsigned long str_size = b64_orig_size(text);
|
511
|
+
VALUE v;
|
512
|
+
char *str = ALLOCA_N(char, str_size + 1);
|
513
|
+
|
514
|
+
from_base64(text, (uchar*)str);
|
515
|
+
v = rb_str_new(str, str_size);
|
503
516
|
#if HAS_ENCODING_SUPPORT
|
504
|
-
|
505
|
-
|
506
|
-
|
517
|
+
if (0 != pi->options->rb_enc) {
|
518
|
+
rb_enc_associate(v, pi->options->rb_enc);
|
519
|
+
}
|
507
520
|
#elif HAS_PRIVATE_ENCODING
|
508
|
-
|
521
|
+
if (0 != pi->options->rb_enc) {
|
509
522
|
rb_funcall(v, ox_force_encoding_id, 1, pi->options->rb_enc);
|
510
|
-
|
523
|
+
}
|
511
524
|
#endif
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
525
|
+
if (0 != pi->circ_array) {
|
526
|
+
circ_array_set(pi->circ_array, v, (unsigned long)h->obj);
|
527
|
+
}
|
528
|
+
h->obj = v;
|
529
|
+
break;
|
517
530
|
}
|
518
531
|
case Symbol64Code:
|
519
532
|
{
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
533
|
+
VALUE sym;
|
534
|
+
VALUE *slot;
|
535
|
+
unsigned long str_size = b64_orig_size(text);
|
536
|
+
char *str = ALLOCA_N(char, str_size + 1);
|
537
|
+
|
538
|
+
from_base64(text, (uchar*)str);
|
539
|
+
if (Qundef == (sym = ox_cache_get(ox_symbol_cache, str, &slot, 0))) {
|
527
540
|
sym = str2sym(str, (void*)pi->options->rb_enc);
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
541
|
+
*slot = sym;
|
542
|
+
}
|
543
|
+
h->obj = sym;
|
544
|
+
break;
|
532
545
|
}
|
533
546
|
case RegexpCode:
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
547
|
+
if ('/' == *text) {
|
548
|
+
h->obj = parse_regexp(text);
|
549
|
+
} else {
|
550
|
+
unsigned long str_size = b64_orig_size(text);
|
538
551
|
char *str = ALLOCA_N(char, str_size + 1);
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
552
|
+
|
553
|
+
from_base64(text, (uchar*)str);
|
554
|
+
h->obj = parse_regexp(str);
|
555
|
+
}
|
556
|
+
break;
|
544
557
|
case BignumCode:
|
545
|
-
|
546
|
-
|
558
|
+
h->obj = rb_cstr_to_inum(text, 10, 1);
|
559
|
+
break;
|
547
560
|
default:
|
548
|
-
|
549
|
-
|
561
|
+
h->obj = Qnil;
|
562
|
+
break;
|
550
563
|
}
|
551
564
|
}
|
552
565
|
|
553
566
|
static void
|
554
567
|
add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
555
|
-
Attr
|
556
|
-
Helper
|
557
|
-
unsigned long
|
568
|
+
Attr a;
|
569
|
+
Helper h;
|
570
|
+
unsigned long id;
|
558
571
|
|
559
572
|
if (TRACE <= pi->options->trace) {
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
} else {
|
584
|
-
pi->h++;
|
573
|
+
char buf[1024];
|
574
|
+
char indent[128];
|
575
|
+
char *s = buf;
|
576
|
+
char *end = buf + sizeof(buf) - 2;
|
577
|
+
|
578
|
+
s += snprintf(s, end - s, " <%s%s", (hasChildren) ? "" : "/", ename);
|
579
|
+
for (a = attrs; 0 != a->name; a++) {
|
580
|
+
s += snprintf(s, end - s, " %s=%s", a->name, a->value);
|
581
|
+
}
|
582
|
+
*s++ = '>';
|
583
|
+
*s++ = '\0';
|
584
|
+
if (DEBUG <= pi->options->trace) {
|
585
|
+
printf("===== add element stack(%d) =====\n", helper_stack_depth(&pi->helpers));
|
586
|
+
debug_stack(pi, buf);
|
587
|
+
} else {
|
588
|
+
fill_indent(pi, indent, sizeof(indent));
|
589
|
+
printf("%s%s\n", indent, buf);
|
590
|
+
}
|
591
|
+
}
|
592
|
+
if (helper_stack_empty(&pi->helpers)) { /* top level object */
|
593
|
+
if (0 != (id = get_id_from_attrs(pi, attrs))) {
|
594
|
+
pi->circ_array = circ_array_new();
|
595
|
+
}
|
585
596
|
}
|
586
597
|
if ('\0' != ename[1]) {
|
587
|
-
|
598
|
+
set_error(&pi->err, "Invalid element name", pi->str, pi->s);
|
599
|
+
return;
|
588
600
|
}
|
589
|
-
h = pi->
|
590
|
-
h->type = *ename;
|
591
|
-
h->var = get_var_sym_from_attrs(attrs, (void*)pi->options->rb_enc);
|
601
|
+
h = helper_stack_push(&pi->helpers, get_var_sym_from_attrs(attrs, (void*)pi->options->rb_enc), Qundef, *ename);
|
592
602
|
switch (h->type) {
|
593
603
|
case NilClassCode:
|
594
|
-
|
595
|
-
|
604
|
+
h->obj = Qnil;
|
605
|
+
break;
|
596
606
|
case TrueClassCode:
|
597
|
-
|
598
|
-
|
607
|
+
h->obj = Qtrue;
|
608
|
+
break;
|
599
609
|
case FalseClassCode:
|
600
|
-
|
601
|
-
|
610
|
+
h->obj = Qfalse;
|
611
|
+
break;
|
602
612
|
case StringCode:
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
613
|
+
/* h->obj will be replaced by add_text if it is called */
|
614
|
+
h->obj = ox_empty_string;
|
615
|
+
if (0 != pi->circ_array) {
|
616
|
+
pi->id = get_id_from_attrs(pi, attrs);
|
617
|
+
circ_array_set(pi->circ_array, h->obj, pi->id);
|
618
|
+
}
|
619
|
+
break;
|
610
620
|
case FixnumCode:
|
611
621
|
case FloatCode:
|
612
622
|
case SymbolCode:
|
@@ -617,213 +627,235 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
617
627
|
case DateCode:
|
618
628
|
case TimeCode:
|
619
629
|
case RationalCode: /* sub elements read next */
|
620
|
-
|
621
|
-
|
622
|
-
|
630
|
+
/* value will be read in the following add_text */
|
631
|
+
h->obj = Qundef;
|
632
|
+
break;
|
623
633
|
case String64Code:
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
634
|
+
h->obj = Qundef;
|
635
|
+
if (0 != pi->circ_array) {
|
636
|
+
pi->id = get_id_from_attrs(pi, attrs);
|
637
|
+
}
|
638
|
+
break;
|
629
639
|
case ArrayCode:
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
640
|
+
h->obj = rb_ary_new();
|
641
|
+
if (0 != pi->circ_array) {
|
642
|
+
circ_array_set(pi->circ_array, h->obj, get_id_from_attrs(pi, attrs));
|
643
|
+
}
|
644
|
+
break;
|
635
645
|
case HashCode:
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
646
|
+
h->obj = rb_hash_new();
|
647
|
+
if (0 != pi->circ_array) {
|
648
|
+
circ_array_set(pi->circ_array, h->obj, get_id_from_attrs(pi, attrs));
|
649
|
+
}
|
650
|
+
break;
|
641
651
|
case RangeCode:
|
642
|
-
|
643
|
-
|
652
|
+
h->obj = rb_range_new(ox_zero_fixnum, ox_zero_fixnum, Qfalse);
|
653
|
+
break;
|
644
654
|
case RawCode:
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
655
|
+
if (hasChildren) {
|
656
|
+
h->obj = ox_parse(pi->s, ox_gen_callbacks, &pi->s, pi->options, &pi->err);
|
657
|
+
if (0 != pi->circ_array) {
|
658
|
+
circ_array_set(pi->circ_array, h->obj, get_id_from_attrs(pi, attrs));
|
659
|
+
}
|
660
|
+
} else {
|
661
|
+
h->obj = Qnil;
|
662
|
+
}
|
663
|
+
break;
|
654
664
|
case ExceptionCode:
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
665
|
+
if (Qundef == (h->obj = get_obj_from_attrs(attrs, pi, rb_eException))) {
|
666
|
+
return;
|
667
|
+
}
|
668
|
+
if (0 != pi->circ_array && Qnil != h->obj) {
|
669
|
+
circ_array_set(pi->circ_array, h->obj, get_id_from_attrs(pi, attrs));
|
670
|
+
}
|
671
|
+
break;
|
660
672
|
case ObjectCode:
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
673
|
+
if (Qundef == (h->obj = get_obj_from_attrs(attrs, pi, ox_bag_clas))) {
|
674
|
+
return;
|
675
|
+
}
|
676
|
+
if (0 != pi->circ_array && Qnil != h->obj) {
|
677
|
+
circ_array_set(pi->circ_array, h->obj, get_id_from_attrs(pi, attrs));
|
678
|
+
}
|
679
|
+
break;
|
666
680
|
case StructCode:
|
667
681
|
#if HAS_RSTRUCT
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
682
|
+
h->obj = get_struct_from_attrs(attrs);
|
683
|
+
if (0 != pi->circ_array) {
|
684
|
+
circ_array_set(pi->circ_array, h->obj, get_id_from_attrs(pi, attrs));
|
685
|
+
}
|
672
686
|
#else
|
673
|
-
|
687
|
+
set_error(&pi->err, "Ruby structs not supported with this verion of Ruby", pi->str, pi->s);
|
688
|
+
return;
|
674
689
|
#endif
|
675
|
-
|
690
|
+
break;
|
676
691
|
case ClassCode:
|
677
|
-
|
678
|
-
|
692
|
+
if (Qundef == (h->obj = get_class_from_attrs(attrs, pi, ox_bag_clas))) {
|
693
|
+
return;
|
694
|
+
}
|
695
|
+
break;
|
679
696
|
case RefCode:
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
697
|
+
h->obj = Qundef;
|
698
|
+
if (0 != pi->circ_array) {
|
699
|
+
h->obj = circ_array_get(pi->circ_array, get_id_from_attrs(pi, attrs));
|
700
|
+
}
|
701
|
+
if (Qundef == h->obj) {
|
702
|
+
set_error(&pi->err, "Invalid circular reference", pi->str, pi->s);
|
703
|
+
return;
|
704
|
+
}
|
705
|
+
break;
|
688
706
|
default:
|
689
|
-
|
690
|
-
|
707
|
+
set_error(&pi->err, "Invalid element name", pi->str, pi->s);
|
708
|
+
return;
|
709
|
+
break;
|
691
710
|
}
|
692
711
|
if (DEBUG <= pi->options->trace) {
|
693
|
-
|
712
|
+
debug_stack(pi, " -----------");
|
694
713
|
}
|
695
714
|
}
|
696
715
|
|
697
716
|
static void
|
698
717
|
end_element(PInfo pi, const char *ename) {
|
699
718
|
if (TRACE <= pi->options->trace) {
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
719
|
+
char indent[128];
|
720
|
+
|
721
|
+
if (DEBUG <= pi->options->trace) {
|
722
|
+
char buf[1024];
|
723
|
+
|
724
|
+
printf("===== end element stack(%d) =====\n", helper_stack_depth(&pi->helpers));
|
725
|
+
snprintf(buf, sizeof(buf) - 1, "</%s>", ename);
|
726
|
+
debug_stack(pi, buf);
|
727
|
+
} else {
|
728
|
+
fill_indent(pi, indent, sizeof(indent));
|
729
|
+
printf("%s</%s>\n", indent, ename);
|
730
|
+
}
|
731
|
+
}
|
732
|
+
if (!helper_stack_empty(&pi->helpers)) {
|
733
|
+
Helper h = helper_stack_pop(&pi->helpers);
|
734
|
+
Helper ph = helper_stack_peek(&pi->helpers);
|
735
|
+
|
736
|
+
if (ox_empty_string == h->obj) {
|
737
|
+
/* special catch for empty strings */
|
738
|
+
h->obj = rb_str_new2("");
|
739
|
+
}
|
740
|
+
pi->obj = h->obj;
|
741
|
+
if (0 != ph) {
|
742
|
+
switch (ph->type) {
|
743
|
+
case ArrayCode:
|
744
|
+
rb_ary_push(ph->obj, h->obj);
|
745
|
+
break;
|
746
|
+
case ExceptionCode:
|
747
|
+
case ObjectCode:
|
748
|
+
if (Qnil != ph->obj) {
|
749
|
+
rb_ivar_set(ph->obj, h->var, h->obj);
|
750
|
+
}
|
751
|
+
break;
|
752
|
+
case StructCode:
|
733
753
|
#if HAS_RSTRUCT
|
734
|
-
|
754
|
+
rb_struct_aset(ph->obj, h->var, h->obj);
|
735
755
|
#else
|
736
|
-
|
756
|
+
set_error(&pi->err, "Ruby structs not supported with this verion of Ruby", pi->str, pi->s);
|
757
|
+
return;
|
737
758
|
#endif
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
759
|
+
break;
|
760
|
+
case HashCode:
|
761
|
+
// put back h
|
762
|
+
helper_stack_push(&pi->helpers, h->var, h->obj, KeyCode);
|
763
|
+
break;
|
764
|
+
case RangeCode:
|
744
765
|
#if HAS_RSTRUCT
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
766
|
+
if (ox_beg_id == h->var) {
|
767
|
+
RSTRUCT_PTR(ph->obj)[0] = h->obj;
|
768
|
+
} else if (ox_end_id == h->var) {
|
769
|
+
RSTRUCT_PTR(ph->obj)[1] = h->obj;
|
770
|
+
} else if (ox_excl_id == h->var) {
|
771
|
+
RSTRUCT_PTR(ph->obj)[2] = h->obj;
|
772
|
+
} else {
|
773
|
+
set_error(&pi->err, "Invalid range attribute", pi->str, pi->s);
|
774
|
+
return;
|
775
|
+
}
|
754
776
|
#else
|
755
|
-
|
777
|
+
set_error(&pi->err, "Ruby structs not supported with this verion of Ruby", pi->str, pi->s);
|
778
|
+
return;
|
756
779
|
#endif
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
780
|
+
break;
|
781
|
+
case KeyCode:
|
782
|
+
{
|
783
|
+
Helper gh;
|
784
|
+
|
785
|
+
helper_stack_pop(&pi->helpers);
|
786
|
+
gh = helper_stack_peek(&pi->helpers);
|
787
|
+
|
788
|
+
rb_hash_aset(gh->obj, ph->obj, h->obj);
|
789
|
+
}
|
790
|
+
break;
|
791
|
+
case ComplexCode:
|
763
792
|
#ifdef T_COMPLEX
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
793
|
+
if (Qundef == ph->obj) {
|
794
|
+
ph->obj = h->obj;
|
795
|
+
} else {
|
796
|
+
ph->obj = rb_complex_new(ph->obj, h->obj);
|
797
|
+
}
|
769
798
|
#else
|
770
|
-
|
799
|
+
set_error(&pi->err, "Complex Objects not implemented in Ruby 1.8.7", pi->str, pi->s);
|
800
|
+
return;
|
771
801
|
#endif
|
772
|
-
|
773
|
-
|
802
|
+
break;
|
803
|
+
case RationalCode:
|
774
804
|
#ifdef T_RATIONAL
|
775
|
-
|
776
|
-
|
777
|
-
|
805
|
+
if (Qundef == ph->obj) {
|
806
|
+
ph->obj = h->obj;
|
807
|
+
} else {
|
778
808
|
#ifdef RUBINIUS_RUBY
|
779
|
-
|
809
|
+
ph->obj = rb_Rational(ph->obj, h->obj);
|
780
810
|
#else
|
781
|
-
|
811
|
+
ph->obj = rb_rational_new(ph->obj, h->obj);
|
782
812
|
#endif
|
783
|
-
|
813
|
+
}
|
784
814
|
#else
|
785
|
-
|
815
|
+
set_error(&pi->err, "Rational Objects not implemented in Ruby 1.8.7", pi->str, pi->s);
|
816
|
+
return;
|
786
817
|
#endif
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
818
|
+
break;
|
819
|
+
default:
|
820
|
+
set_error(&pi->err, "Corrupt parse stack, container is wrong type", pi->str, pi->s);
|
821
|
+
return;
|
822
|
+
break;
|
823
|
+
}
|
824
|
+
}
|
793
825
|
}
|
794
|
-
if (0 != pi->circ_array && pi->helpers
|
795
|
-
|
796
|
-
|
826
|
+
if (0 != pi->circ_array && helper_stack_empty(&pi->helpers)) {
|
827
|
+
circ_array_free(pi->circ_array);
|
828
|
+
pi->circ_array = 0;
|
797
829
|
}
|
798
830
|
if (DEBUG <= pi->options->trace) {
|
799
|
-
|
831
|
+
debug_stack(pi, " ----------");
|
800
832
|
}
|
801
833
|
}
|
802
834
|
|
803
835
|
static VALUE
|
804
836
|
parse_double_time(const char *text, VALUE clas) {
|
805
|
-
long
|
806
|
-
long
|
807
|
-
const char
|
808
|
-
char
|
837
|
+
long v = 0;
|
838
|
+
long v2 = 0;
|
839
|
+
const char *dot = 0;
|
840
|
+
char c;
|
809
841
|
|
810
842
|
for (; '.' != *text; text++) {
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
843
|
+
c = *text;
|
844
|
+
if (c < '0' || '9' < c) {
|
845
|
+
return Qnil;
|
846
|
+
}
|
847
|
+
v = 10 * v + (long)(c - '0');
|
816
848
|
}
|
817
849
|
dot = text++;
|
818
850
|
for (; '\0' != *text && text - dot <= 6; text++) {
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
851
|
+
c = *text;
|
852
|
+
if (c < '0' || '9' < c) {
|
853
|
+
return Qnil;
|
854
|
+
}
|
855
|
+
v2 = 10 * v2 + (long)(c - '0');
|
824
856
|
}
|
825
857
|
for (; text - dot <= 9; text++) {
|
826
|
-
|
858
|
+
v2 *= 10;
|
827
859
|
}
|
828
860
|
#if HAS_NANO_TIME
|
829
861
|
return rb_time_nano_new(v, v2);
|
@@ -833,47 +865,47 @@ parse_double_time(const char *text, VALUE clas) {
|
|
833
865
|
}
|
834
866
|
|
835
867
|
typedef struct _Tp {
|
836
|
-
int
|
837
|
-
char
|
838
|
-
char
|
868
|
+
int cnt;
|
869
|
+
char end;
|
870
|
+
char alt;
|
839
871
|
} *Tp;
|
840
872
|
|
841
873
|
static VALUE
|
842
874
|
parse_xsd_time(const char *text, VALUE clas) {
|
843
|
-
long
|
844
|
-
long
|
845
|
-
long
|
846
|
-
int
|
847
|
-
char
|
848
|
-
struct _Tp
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
Tp
|
859
|
-
struct tm
|
875
|
+
long cargs[10];
|
876
|
+
long *cp = cargs;
|
877
|
+
long v;
|
878
|
+
int i;
|
879
|
+
char c;
|
880
|
+
struct _Tp tpa[10] = { { 4, '-', '-' },
|
881
|
+
{ 2, '-', '-' },
|
882
|
+
{ 2, 'T', 'T' },
|
883
|
+
{ 2, ':', ':' },
|
884
|
+
{ 2, ':', ':' },
|
885
|
+
{ 2, '.', '.' },
|
886
|
+
{ 9, '+', '-' },
|
887
|
+
{ 2, ':', ':' },
|
888
|
+
{ 2, '\0', '\0' },
|
889
|
+
{ 0, '\0', '\0' } };
|
890
|
+
Tp tp = tpa;
|
891
|
+
struct tm tm;
|
860
892
|
|
861
893
|
for (; 0 != tp->cnt; tp++) {
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
894
|
+
for (i = tp->cnt, v = 0; 0 < i ; text++, i--) {
|
895
|
+
c = *text;
|
896
|
+
if (c < '0' || '9' < c) {
|
897
|
+
if (tp->end == c || tp->alt == c) {
|
898
|
+
break;
|
899
|
+
}
|
900
|
+
return Qnil;
|
901
|
+
}
|
902
|
+
v = 10 * v + (long)(c - '0');
|
903
|
+
}
|
904
|
+
c = *text++;
|
905
|
+
if (tp->end != c && tp->alt != c) {
|
906
|
+
return Qnil;
|
907
|
+
}
|
908
|
+
*cp++ = v;
|
877
909
|
}
|
878
910
|
tm.tm_year = (int)cargs[0] - 1900;
|
879
911
|
tm.tm_mon = (int)cargs[1] - 1;
|
@@ -891,48 +923,49 @@ parse_xsd_time(const char *text, VALUE clas) {
|
|
891
923
|
/* debug functions */
|
892
924
|
static void
|
893
925
|
fill_indent(PInfo pi, char *buf, size_t size) {
|
894
|
-
|
895
|
-
size_t cnt = pi->h - pi->helpers + 1;
|
926
|
+
size_t cnt;
|
896
927
|
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
928
|
+
if (0 < (cnt = helper_stack_depth(&pi->helpers))) {
|
929
|
+
cnt *= 2;
|
930
|
+
if (size < cnt + 1) {
|
931
|
+
cnt = size - 1;
|
932
|
+
}
|
933
|
+
memset(buf, ' ', cnt);
|
934
|
+
buf += cnt;
|
902
935
|
}
|
903
936
|
*buf = '\0';
|
904
937
|
}
|
905
938
|
|
906
939
|
static void
|
907
940
|
debug_stack(PInfo pi, const char *comment) {
|
908
|
-
char
|
909
|
-
Helper
|
941
|
+
char indent[128];
|
942
|
+
Helper h;
|
910
943
|
|
911
944
|
fill_indent(pi, indent, sizeof(indent));
|
912
945
|
printf("%s%s\n", indent, comment);
|
913
|
-
if (
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
946
|
+
if (!helper_stack_empty(&pi->helpers)) {
|
947
|
+
for (h = pi->helpers.head; h < pi->helpers.tail; h++) {
|
948
|
+
const char *clas = "---";
|
949
|
+
const char *key = "---";
|
950
|
+
|
951
|
+
if (Qundef != h->obj) {
|
952
|
+
VALUE c = rb_obj_class(h->obj);
|
953
|
+
|
954
|
+
clas = rb_class2name(c);
|
955
|
+
}
|
956
|
+
if (Qundef != h->var) {
|
957
|
+
if (HashCode == h->type) {
|
958
|
+
VALUE v;
|
959
|
+
|
960
|
+
v = rb_funcall2(h->var, rb_intern("to_s"), 0, 0);
|
961
|
+
key = StringValuePtr(v);
|
962
|
+
} else if (ObjectCode == (h - 1)->type || ExceptionCode == (h - 1)->type || RangeCode == (h - 1)->type || StructCode == (h - 1)->type) {
|
963
|
+
key = rb_id2name(h->var);
|
964
|
+
} else {
|
965
|
+
printf("%s*** corrupt stack ***\n", indent);
|
966
|
+
}
|
967
|
+
}
|
968
|
+
printf("%s [%c] %s : %s\n", indent, h->type, clas, key);
|
969
|
+
}
|
937
970
|
}
|
938
971
|
}
|