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/dump.c
CHANGED
@@ -3,84 +3,83 @@
|
|
3
3
|
* All rights reserved.
|
4
4
|
*/
|
5
5
|
|
6
|
-
#include <stdlib.h>
|
7
6
|
#include <errno.h>
|
8
|
-
#include <time.h>
|
9
7
|
#include <stdio.h>
|
8
|
+
#include <stdlib.h>
|
10
9
|
#include <string.h>
|
10
|
+
#include <time.h>
|
11
11
|
|
12
12
|
#include "base64.h"
|
13
13
|
#include "cache8.h"
|
14
14
|
#include "ox.h"
|
15
15
|
|
16
|
-
#define USE_B64
|
16
|
+
#define USE_B64 0
|
17
17
|
#define MAX_DEPTH 1000
|
18
18
|
|
19
|
-
typedef unsigned long
|
19
|
+
typedef unsigned long ulong;
|
20
20
|
|
21
21
|
typedef struct _str {
|
22
|
-
const char
|
23
|
-
size_t
|
22
|
+
const char *str;
|
23
|
+
size_t len;
|
24
24
|
} *Str;
|
25
25
|
|
26
26
|
typedef struct _element {
|
27
|
-
struct _str
|
28
|
-
struct _str
|
29
|
-
unsigned long
|
30
|
-
int
|
31
|
-
int
|
32
|
-
char
|
27
|
+
struct _str clas;
|
28
|
+
struct _str attr;
|
29
|
+
unsigned long id;
|
30
|
+
int indent; /* < 0 indicates no \n */
|
31
|
+
int closed;
|
32
|
+
char type;
|
33
33
|
} *Element;
|
34
34
|
|
35
35
|
typedef struct _out {
|
36
|
-
void
|
37
|
-
void
|
38
|
-
void
|
39
|
-
char
|
40
|
-
char
|
41
|
-
char
|
42
|
-
Cache8
|
43
|
-
unsigned long
|
44
|
-
int
|
45
|
-
int
|
46
|
-
Options
|
47
|
-
VALUE
|
36
|
+
void (*w_start)(struct _out *out, Element e);
|
37
|
+
void (*w_end)(struct _out *out, Element e);
|
38
|
+
void (*w_time)(struct _out *out, VALUE obj);
|
39
|
+
char *buf;
|
40
|
+
char *end;
|
41
|
+
char *cur;
|
42
|
+
Cache8 circ_cache;
|
43
|
+
unsigned long circ_cnt;
|
44
|
+
int indent;
|
45
|
+
int depth; /* used by dumpHash */
|
46
|
+
Options opts;
|
47
|
+
VALUE obj;
|
48
48
|
} *Out;
|
49
49
|
|
50
|
-
static void
|
50
|
+
static void dump_obj_to_xml(VALUE obj, Options copts, Out out);
|
51
51
|
|
52
|
-
static void
|
53
|
-
static void
|
54
|
-
static void
|
55
|
-
static void
|
56
|
-
static void
|
57
|
-
static int
|
58
|
-
static int
|
59
|
-
static void
|
60
|
-
|
61
|
-
const char *suf, size_t slen, Out out);
|
52
|
+
static void dump_first_obj(VALUE obj, Out out);
|
53
|
+
static void dump_obj(ID aid, VALUE obj, int depth, Out out);
|
54
|
+
static void dump_gen_doc(VALUE obj, int depth, Out out);
|
55
|
+
static void dump_gen_element(VALUE obj, int depth, Out out);
|
56
|
+
static void dump_gen_instruct(VALUE obj, int depth, Out out);
|
57
|
+
static int dump_gen_attr(VALUE key, VALUE value, VALUE ov);
|
58
|
+
static int dump_gen_nodes(VALUE obj, int depth, Out out);
|
59
|
+
static void
|
60
|
+
dump_gen_val_node(VALUE obj, int depth, const char *pre, size_t plen, const char *suf, size_t slen, Out out);
|
62
61
|
|
63
|
-
static void
|
64
|
-
static void
|
62
|
+
static void dump_start(Out out, Element e);
|
63
|
+
static void dump_end(Out out, Element e);
|
65
64
|
|
66
|
-
static void
|
65
|
+
static void grow(Out out, size_t len);
|
67
66
|
|
68
|
-
static void
|
69
|
-
static void
|
70
|
-
static int
|
71
|
-
static void
|
72
|
-
static void
|
73
|
-
static void
|
74
|
-
static void
|
75
|
-
static int
|
67
|
+
static void dump_value(Out out, const char *value, size_t size);
|
68
|
+
static void dump_str_value(Out out, const char *value, size_t size, const char *table);
|
69
|
+
static int dump_var(ID key, VALUE value, VALUE ov);
|
70
|
+
static void dump_num(Out out, VALUE obj);
|
71
|
+
static void dump_date(Out out, VALUE obj);
|
72
|
+
static void dump_time_thin(Out out, VALUE obj);
|
73
|
+
static void dump_time_xsd(Out out, VALUE obj);
|
74
|
+
static int dump_hash(VALUE key, VALUE value, VALUE ov);
|
76
75
|
|
77
|
-
static int
|
76
|
+
static int is_xml_friendly(const uchar *str, int len, const char *table);
|
78
77
|
|
79
|
-
static const char
|
78
|
+
static const char hex_chars[17] = "0123456789abcdef";
|
80
79
|
|
81
80
|
// The : character is equivalent to 10. Used for replacement characters up to 10
|
82
81
|
// characters long such as ''.
|
83
|
-
static const char
|
82
|
+
static const char xml_friendly_chars[257] = "\
|
84
83
|
:::::::::11::1::::::::::::::::::\
|
85
84
|
11611156111111111111111111114141\
|
86
85
|
11111111111111111111111111111111\
|
@@ -90,7 +89,7 @@ static const char xml_friendly_chars[257] = "\
|
|
90
89
|
11111111111111111111111111111111\
|
91
90
|
11111111111111111111111111111111";
|
92
91
|
|
93
|
-
static const char
|
92
|
+
static const char xml_quote_chars[257] = "\
|
94
93
|
:::::::::11::1::::::::::::::::::\
|
95
94
|
11611151111111111111111111114141\
|
96
95
|
11111111111111111111111111111111\
|
@@ -100,7 +99,7 @@ static const char xml_quote_chars[257] = "\
|
|
100
99
|
11111111111111111111111111111111\
|
101
100
|
11111111111111111111111111111111";
|
102
101
|
|
103
|
-
static const char
|
102
|
+
static const char xml_element_chars[257] = "\
|
104
103
|
:::::::::11::1::::::::::::::::::\
|
105
104
|
11111151111111111111111111114141\
|
106
105
|
11111111111111111111111111111111\
|
@@ -110,916 +109,853 @@ static const char xml_element_chars[257] = "\
|
|
110
109
|
11111111111111111111111111111111\
|
111
110
|
11111111111111111111111111111111";
|
112
111
|
|
113
|
-
inline static int
|
114
|
-
is_xml_friendly(const uchar *str, int len, const char *table) {
|
112
|
+
inline static int is_xml_friendly(const uchar *str, int len, const char *table) {
|
115
113
|
for (; 0 < len; str++, len--) {
|
116
|
-
|
117
|
-
|
118
|
-
|
114
|
+
if ('1' != table[*str]) {
|
115
|
+
return 0;
|
116
|
+
}
|
119
117
|
}
|
120
118
|
return 1;
|
121
119
|
}
|
122
120
|
|
123
|
-
inline static size_t
|
124
|
-
|
125
|
-
size_t size = 0;
|
121
|
+
inline static size_t xml_str_len(const uchar *str, size_t len, const char *table) {
|
122
|
+
size_t size = 0;
|
126
123
|
|
127
124
|
for (; 0 < len; str++, len--) {
|
128
|
-
|
125
|
+
size += xml_friendly_chars[*str];
|
129
126
|
}
|
130
127
|
return size - len * (size_t)'0';
|
131
128
|
}
|
132
129
|
|
133
|
-
inline static void
|
134
|
-
|
135
|
-
uchar d = (c >> 4) & 0x0F;
|
130
|
+
inline static void dump_hex(uchar c, Out out) {
|
131
|
+
uchar d = (c >> 4) & 0x0F;
|
136
132
|
|
137
133
|
*out->cur++ = hex_chars[d];
|
138
|
-
d
|
134
|
+
d = c & 0x0F;
|
139
135
|
*out->cur++ = hex_chars[d];
|
140
136
|
}
|
141
137
|
|
142
|
-
static Type
|
143
|
-
|
144
|
-
VALUE clas = rb_obj_class(obj);
|
138
|
+
static Type obj_class_code(VALUE obj) {
|
139
|
+
VALUE clas = rb_obj_class(obj);
|
145
140
|
|
146
141
|
switch (rb_type(obj)) {
|
147
|
-
case T_NIL:
|
148
|
-
case T_ARRAY:
|
149
|
-
case T_HASH:
|
150
|
-
case T_TRUE:
|
151
|
-
case T_FALSE:
|
152
|
-
case T_FIXNUM:
|
153
|
-
case T_FLOAT:
|
154
|
-
case T_STRING:
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
case
|
163
|
-
case
|
164
|
-
case
|
165
|
-
case
|
166
|
-
|
167
|
-
case T_COMPLEX:
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
#endif
|
172
|
-
case T_CLASS: return ClassCode;
|
173
|
-
default: return 0;
|
142
|
+
case T_NIL: return NilClassCode;
|
143
|
+
case T_ARRAY: return ArrayCode;
|
144
|
+
case T_HASH: return HashCode;
|
145
|
+
case T_TRUE: return TrueClassCode;
|
146
|
+
case T_FALSE: return FalseClassCode;
|
147
|
+
case T_FIXNUM: return FixnumCode;
|
148
|
+
case T_FLOAT: return FloatCode;
|
149
|
+
case T_STRING:
|
150
|
+
return (is_xml_friendly((uchar *)StringValuePtr(obj), (int)RSTRING_LEN(obj), xml_element_chars)) ? StringCode
|
151
|
+
: String64Code;
|
152
|
+
case T_SYMBOL: {
|
153
|
+
const char *sym = rb_id2name(SYM2ID(obj));
|
154
|
+
|
155
|
+
return (is_xml_friendly((uchar *)sym, (int)strlen(sym), xml_element_chars)) ? SymbolCode : Symbol64Code;
|
156
|
+
}
|
157
|
+
case T_DATA: return (rb_cTime == clas) ? TimeCode : ((ox_date_class == clas) ? DateCode : 0);
|
158
|
+
case T_STRUCT: return (rb_cRange == clas) ? RangeCode : StructCode;
|
159
|
+
case T_OBJECT: return (ox_document_clas == clas || ox_element_clas == clas) ? RawCode : ObjectCode;
|
160
|
+
case T_REGEXP: return RegexpCode;
|
161
|
+
case T_BIGNUM: return BignumCode;
|
162
|
+
case T_COMPLEX: return ComplexCode;
|
163
|
+
case T_RATIONAL: return RationalCode;
|
164
|
+
case T_CLASS: return ClassCode;
|
165
|
+
default: return 0;
|
174
166
|
}
|
175
167
|
}
|
176
168
|
|
177
|
-
inline static void
|
178
|
-
fill_indent(Out out, int cnt) {
|
169
|
+
inline static void fill_indent(Out out, int cnt) {
|
179
170
|
if (0 <= cnt) {
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
171
|
+
*out->cur++ = '\n';
|
172
|
+
if (0 < out->opts->margin_len) {
|
173
|
+
memcpy(out->cur, out->opts->margin, out->opts->margin_len);
|
174
|
+
out->cur += out->opts->margin_len;
|
175
|
+
}
|
176
|
+
for (; 0 < cnt; cnt--) {
|
177
|
+
*out->cur++ = ' ';
|
178
|
+
}
|
188
179
|
}
|
189
180
|
}
|
190
181
|
|
191
|
-
inline static void
|
192
|
-
fill_value(Out out, const char *value, size_t len) {
|
182
|
+
inline static void fill_value(Out out, const char *value, size_t len) {
|
193
183
|
if (6 < len) {
|
194
|
-
|
195
|
-
|
184
|
+
memcpy(out->cur, value, len);
|
185
|
+
out->cur += len;
|
196
186
|
} else {
|
197
|
-
|
198
|
-
|
199
|
-
|
187
|
+
for (; 0 < len; len--, value++) {
|
188
|
+
*out->cur++ = *value;
|
189
|
+
}
|
200
190
|
}
|
201
191
|
}
|
202
192
|
|
203
|
-
inline static void
|
204
|
-
fill_attr(Out out, char name, const char *value, size_t len) {
|
193
|
+
inline static void fill_attr(Out out, char name, const char *value, size_t len) {
|
205
194
|
*out->cur++ = ' ';
|
206
195
|
*out->cur++ = name;
|
207
196
|
*out->cur++ = '=';
|
208
197
|
*out->cur++ = '"';
|
209
198
|
if (6 < len) {
|
210
|
-
|
211
|
-
|
199
|
+
memcpy(out->cur, value, len);
|
200
|
+
out->cur += len;
|
212
201
|
} else {
|
213
|
-
|
214
|
-
|
215
|
-
|
202
|
+
for (; 0 < len; len--, value++) {
|
203
|
+
*out->cur++ = *value;
|
204
|
+
}
|
216
205
|
}
|
217
206
|
*out->cur++ = '"';
|
218
207
|
}
|
219
208
|
|
220
|
-
inline static const char*
|
221
|
-
|
222
|
-
char *b;
|
209
|
+
inline static const char *ulong2str(ulong num, char *end) {
|
210
|
+
char *b;
|
223
211
|
|
224
212
|
*end-- = '\0';
|
225
213
|
for (b = end; 0 < num || b == end; num /= 10, b--) {
|
226
|
-
|
214
|
+
*b = (num % 10) + '0';
|
227
215
|
}
|
228
216
|
b++;
|
229
217
|
|
230
218
|
return b;
|
231
219
|
}
|
232
220
|
|
233
|
-
static int
|
234
|
-
|
235
|
-
slot_t
|
236
|
-
|
237
|
-
int result;
|
221
|
+
static int check_circular(Out out, VALUE obj, Element e) {
|
222
|
+
slot_t *slot;
|
223
|
+
slot_t id;
|
224
|
+
int result;
|
238
225
|
|
239
226
|
if (0 == (id = ox_cache8_get(out->circ_cache, obj, &slot))) {
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
227
|
+
out->circ_cnt++;
|
228
|
+
id = out->circ_cnt;
|
229
|
+
*slot = id;
|
230
|
+
e->id = id;
|
231
|
+
result = 0;
|
245
232
|
} else {
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
233
|
+
e->type = RefCode;
|
234
|
+
e->clas.len = 0;
|
235
|
+
e->clas.str = 0;
|
236
|
+
e->closed = 1;
|
237
|
+
e->id = id;
|
238
|
+
out->w_start(out, e);
|
239
|
+
result = 1;
|
251
240
|
}
|
252
241
|
return result;
|
253
242
|
}
|
254
243
|
|
255
|
-
static void
|
256
|
-
|
257
|
-
|
258
|
-
long pos = out->cur - out->buf;
|
244
|
+
static void grow(Out out, size_t len) {
|
245
|
+
size_t size = out->end - out->buf;
|
246
|
+
long pos = out->cur - out->buf;
|
259
247
|
|
260
248
|
size *= 2;
|
261
249
|
if (size <= len * 2 + pos) {
|
262
|
-
|
250
|
+
size += len;
|
263
251
|
}
|
264
252
|
REALLOC_N(out->buf, char, size + 10); /* 10 extra for terminator character plus extra (paranoid) */
|
265
253
|
out->end = out->buf + size;
|
266
254
|
out->cur = out->buf + pos;
|
267
255
|
}
|
268
256
|
|
269
|
-
static void
|
270
|
-
|
271
|
-
size_t size = e->indent + 4 + out->opts->margin_len;
|
257
|
+
static void dump_start(Out out, Element e) {
|
258
|
+
size_t size = e->indent + 4 + out->opts->margin_len;
|
272
259
|
|
273
260
|
if (0 < e->attr.len) { /* a="attr" */
|
274
|
-
|
261
|
+
size += e->attr.len + 5;
|
275
262
|
}
|
276
263
|
if (0 < e->clas.len) { /* c="class" */
|
277
|
-
|
264
|
+
size += e->clas.len + 5;
|
278
265
|
}
|
279
266
|
if (0 < e->id) { /* i="id" */
|
280
|
-
|
267
|
+
size += 24; /* over estimate, 19 digits */
|
281
268
|
}
|
282
269
|
if (out->end - out->cur <= (long)size) {
|
283
|
-
|
270
|
+
grow(out, size);
|
284
271
|
}
|
285
272
|
if (out->buf + out->opts->margin_len < out->cur) {
|
286
|
-
|
273
|
+
fill_indent(out, e->indent);
|
287
274
|
}
|
288
275
|
*out->cur++ = '<';
|
289
276
|
*out->cur++ = e->type;
|
290
277
|
if (0 < e->attr.len) {
|
291
|
-
|
278
|
+
fill_attr(out, 'a', e->attr.str, e->attr.len);
|
292
279
|
}
|
293
|
-
if ((ObjectCode == e->type || ExceptionCode == e->type || StructCode == e->type || ClassCode == e->type) &&
|
294
|
-
|
280
|
+
if ((ObjectCode == e->type || ExceptionCode == e->type || StructCode == e->type || ClassCode == e->type) &&
|
281
|
+
0 < e->clas.len) {
|
282
|
+
fill_attr(out, 'c', e->clas.str, e->clas.len);
|
295
283
|
}
|
296
284
|
if (0 < e->id) {
|
297
|
-
|
298
|
-
|
299
|
-
|
285
|
+
char buf[32];
|
286
|
+
char *end = buf + sizeof(buf) - 1;
|
287
|
+
const char *s = ulong2str(e->id, end);
|
300
288
|
|
301
|
-
|
289
|
+
fill_attr(out, 'i', s, end - s);
|
302
290
|
}
|
303
291
|
if (e->closed) {
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
292
|
+
if (out->opts->no_empty) {
|
293
|
+
*out->cur++ = '>';
|
294
|
+
*out->cur++ = '<';
|
295
|
+
*out->cur++ = '/';
|
296
|
+
*out->cur++ = e->type;
|
297
|
+
} else {
|
298
|
+
*out->cur++ = '/';
|
299
|
+
}
|
312
300
|
}
|
313
301
|
*out->cur++ = '>';
|
314
|
-
*out->cur
|
302
|
+
*out->cur = '\0';
|
315
303
|
}
|
316
304
|
|
317
|
-
static void
|
318
|
-
|
319
|
-
size_t size = e->indent + 5 + out->opts->margin_len;
|
305
|
+
static void dump_end(Out out, Element e) {
|
306
|
+
size_t size = e->indent + 5 + out->opts->margin_len;
|
320
307
|
|
321
308
|
if (out->end - out->cur <= (long)size) {
|
322
|
-
|
309
|
+
grow(out, size);
|
323
310
|
}
|
324
311
|
fill_indent(out, e->indent);
|
325
312
|
*out->cur++ = '<';
|
326
313
|
*out->cur++ = '/';
|
327
314
|
*out->cur++ = e->type;
|
328
315
|
*out->cur++ = '>';
|
329
|
-
*out->cur
|
316
|
+
*out->cur = '\0';
|
330
317
|
}
|
331
318
|
|
332
|
-
inline static void
|
333
|
-
dump_value(Out out, const char *value, size_t size) {
|
319
|
+
inline static void dump_value(Out out, const char *value, size_t size) {
|
334
320
|
if (out->end - out->cur <= (long)size) {
|
335
|
-
|
321
|
+
grow(out, size);
|
336
322
|
}
|
337
323
|
if (6 < size) {
|
338
|
-
|
339
|
-
|
324
|
+
memcpy(out->cur, value, size);
|
325
|
+
out->cur += size;
|
340
326
|
} else {
|
341
|
-
|
342
|
-
|
343
|
-
|
327
|
+
for (; 0 < size; size--, value++) {
|
328
|
+
*out->cur++ = *value;
|
329
|
+
}
|
344
330
|
}
|
345
331
|
*out->cur = '\0';
|
346
332
|
}
|
347
333
|
|
348
|
-
inline static void
|
349
|
-
|
350
|
-
size_t xsize = xml_str_len((const uchar*)value, size, table);
|
334
|
+
inline static void dump_str_value(Out out, const char *value, size_t size, const char *table) {
|
335
|
+
size_t xsize = xml_str_len((const uchar *)value, size, table);
|
351
336
|
|
352
337
|
if (out->end - out->cur <= (long)xsize) {
|
353
|
-
|
338
|
+
grow(out, xsize);
|
354
339
|
}
|
355
340
|
for (; 0 < size; size--, value++) {
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
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
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
341
|
+
if ('1' == table[(uchar)*value]) {
|
342
|
+
*out->cur++ = *value;
|
343
|
+
} else {
|
344
|
+
switch (*value) {
|
345
|
+
case '"':
|
346
|
+
*out->cur++ = '&';
|
347
|
+
*out->cur++ = 'q';
|
348
|
+
*out->cur++ = 'u';
|
349
|
+
*out->cur++ = 'o';
|
350
|
+
*out->cur++ = 't';
|
351
|
+
*out->cur++ = ';';
|
352
|
+
break;
|
353
|
+
case '&':
|
354
|
+
*out->cur++ = '&';
|
355
|
+
*out->cur++ = 'a';
|
356
|
+
*out->cur++ = 'm';
|
357
|
+
*out->cur++ = 'p';
|
358
|
+
*out->cur++ = ';';
|
359
|
+
break;
|
360
|
+
case '\'':
|
361
|
+
*out->cur++ = '&';
|
362
|
+
*out->cur++ = 'a';
|
363
|
+
*out->cur++ = 'p';
|
364
|
+
*out->cur++ = 'o';
|
365
|
+
*out->cur++ = 's';
|
366
|
+
*out->cur++ = ';';
|
367
|
+
break;
|
368
|
+
case '<':
|
369
|
+
*out->cur++ = '&';
|
370
|
+
*out->cur++ = 'l';
|
371
|
+
*out->cur++ = 't';
|
372
|
+
*out->cur++ = ';';
|
373
|
+
break;
|
374
|
+
case '>':
|
375
|
+
*out->cur++ = '&';
|
376
|
+
*out->cur++ = 'g';
|
377
|
+
*out->cur++ = 't';
|
378
|
+
*out->cur++ = ';';
|
379
|
+
break;
|
380
|
+
default:
|
381
|
+
// Must be one of the invalid characters.
|
382
|
+
if (StrictEffort == out->opts->effort) {
|
383
|
+
rb_raise(ox_syntax_error_class, "'\\#x%02x' is not a valid XML character.", *value);
|
384
|
+
}
|
385
|
+
if (Yes == out->opts->allow_invalid) {
|
386
|
+
*out->cur++ = '&';
|
387
|
+
*out->cur++ = '#';
|
388
|
+
*out->cur++ = 'x';
|
389
|
+
*out->cur++ = '0';
|
390
|
+
*out->cur++ = '0';
|
391
|
+
dump_hex(*value, out);
|
392
|
+
*out->cur++ = ';';
|
393
|
+
} else if ('\0' != *out->opts->inv_repl) {
|
394
|
+
// If the empty string then ignore. The first character of
|
395
|
+
// the replacement is the length.
|
396
|
+
memcpy(out->cur, out->opts->inv_repl + 1, (size_t)*out->opts->inv_repl);
|
397
|
+
out->cur += *out->opts->inv_repl;
|
398
|
+
}
|
399
|
+
break;
|
400
|
+
}
|
401
|
+
}
|
417
402
|
}
|
418
403
|
*out->cur = '\0';
|
419
404
|
}
|
420
405
|
|
421
|
-
inline static void
|
422
|
-
|
423
|
-
char
|
424
|
-
|
425
|
-
|
426
|
-
int neg = 0;
|
406
|
+
inline static void dump_num(Out out, VALUE obj) {
|
407
|
+
char buf[32];
|
408
|
+
char *b = buf + sizeof(buf) - 1;
|
409
|
+
long num = NUM2LONG(obj);
|
410
|
+
int neg = 0;
|
427
411
|
|
428
412
|
if (0 > num) {
|
429
|
-
|
430
|
-
|
413
|
+
neg = 1;
|
414
|
+
num = -num;
|
431
415
|
}
|
432
416
|
*b-- = '\0';
|
433
417
|
if (0 < num) {
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
418
|
+
for (; 0 < num; num /= 10, b--) {
|
419
|
+
*b = (num % 10) + '0';
|
420
|
+
}
|
421
|
+
if (neg) {
|
422
|
+
*b = '-';
|
423
|
+
} else {
|
424
|
+
b++;
|
425
|
+
}
|
442
426
|
} else {
|
443
|
-
|
427
|
+
*b = '0';
|
444
428
|
}
|
445
429
|
if (out->end - out->cur <= (long)(sizeof(buf) - (b - buf))) {
|
446
|
-
|
430
|
+
grow(out, sizeof(buf) - (b - buf));
|
447
431
|
}
|
448
432
|
for (; '\0' != *b; b++) {
|
449
|
-
|
433
|
+
*out->cur++ = *b;
|
450
434
|
}
|
451
435
|
*out->cur = '\0';
|
452
436
|
}
|
453
437
|
|
454
|
-
static void
|
455
|
-
|
456
|
-
char
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
long
|
462
|
-
#else
|
463
|
-
time_t sec = NUM2LONG(rb_funcall2(obj, ox_tv_sec_id, 0, 0));
|
464
|
-
long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_nsec_id, 0, 0));
|
465
|
-
//long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_usec_id, 0, 0)) * 1000;
|
466
|
-
#endif
|
467
|
-
char *dot = b - 10;
|
468
|
-
long size;
|
438
|
+
static void dump_time_thin(Out out, VALUE obj) {
|
439
|
+
char buf[64];
|
440
|
+
char *b = buf + sizeof(buf) - 1;
|
441
|
+
struct timespec ts = rb_time_timespec(obj);
|
442
|
+
time_t sec = ts.tv_sec;
|
443
|
+
long nsec = ts.tv_nsec;
|
444
|
+
char *dot = b - 10;
|
445
|
+
long size;
|
469
446
|
|
470
447
|
*b-- = '\0';
|
471
448
|
for (; dot < b; b--, nsec /= 10) {
|
472
|
-
|
449
|
+
*b = '0' + (nsec % 10);
|
473
450
|
}
|
474
451
|
*b-- = '.';
|
475
452
|
for (; 0 < sec; b--, sec /= 10) {
|
476
|
-
|
453
|
+
*b = '0' + (sec % 10);
|
477
454
|
}
|
478
455
|
b++;
|
479
456
|
size = sizeof(buf) - (b - buf) - 1;
|
480
457
|
if (out->end - out->cur <= size) {
|
481
|
-
|
458
|
+
grow(out, size);
|
482
459
|
}
|
483
460
|
memcpy(out->cur, b, size);
|
484
461
|
out->cur += size;
|
485
462
|
}
|
486
463
|
|
487
|
-
static void
|
488
|
-
|
489
|
-
char
|
490
|
-
|
491
|
-
long
|
492
|
-
long size;
|
464
|
+
static void dump_date(Out out, VALUE obj) {
|
465
|
+
char buf[64];
|
466
|
+
char *b = buf + sizeof(buf) - 1;
|
467
|
+
long jd = NUM2LONG(rb_funcall2(obj, ox_jd_id, 0, 0));
|
468
|
+
long size;
|
493
469
|
|
494
470
|
*b-- = '\0';
|
495
471
|
for (; 0 < jd; b--, jd /= 10) {
|
496
|
-
|
472
|
+
*b = '0' + (jd % 10);
|
497
473
|
}
|
498
474
|
b++;
|
499
475
|
if ('\0' == *b) {
|
500
|
-
|
501
|
-
|
476
|
+
b--;
|
477
|
+
*b = '0';
|
502
478
|
}
|
503
479
|
size = sizeof(buf) - (b - buf) - 1;
|
504
480
|
if (out->end - out->cur <= size) {
|
505
|
-
|
481
|
+
grow(out, size);
|
506
482
|
}
|
507
483
|
memcpy(out->cur, b, size);
|
508
484
|
out->cur += size;
|
509
485
|
}
|
510
486
|
|
511
|
-
static void
|
512
|
-
|
513
|
-
struct
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
#else
|
519
|
-
time_t sec = NUM2LONG(rb_funcall2(obj, ox_tv_sec_id, 0, 0));
|
520
|
-
long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_nsec_id, 0, 0));
|
521
|
-
//long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_usec_id, 0, 0)) * 1000;
|
522
|
-
#endif
|
523
|
-
int tzhour, tzmin;
|
524
|
-
char tzsign = '+';
|
487
|
+
static void dump_time_xsd(Out out, VALUE obj) {
|
488
|
+
struct tm *tm;
|
489
|
+
struct timespec ts = rb_time_timespec(obj);
|
490
|
+
time_t sec = ts.tv_sec;
|
491
|
+
long nsec = ts.tv_nsec;
|
492
|
+
int tzhour, tzmin;
|
493
|
+
char tzsign = '+';
|
525
494
|
|
526
495
|
if (out->end - out->cur <= 33) {
|
527
|
-
|
496
|
+
grow(out, 33);
|
528
497
|
}
|
529
498
|
/* 2010-07-09T10:47:45.895826+09:00 */
|
530
499
|
tm = localtime(&sec);
|
531
500
|
#if HAVE_ST_TM_GMTOFF
|
532
501
|
if (0 > tm->tm_gmtoff) {
|
533
|
-
|
534
|
-
|
535
|
-
|
502
|
+
tzsign = '-';
|
503
|
+
tzhour = (int)(tm->tm_gmtoff / -3600);
|
504
|
+
tzmin = (int)(tm->tm_gmtoff / -60) - (tzhour * 60);
|
536
505
|
} else {
|
537
|
-
|
538
|
-
|
506
|
+
tzhour = (int)(tm->tm_gmtoff / 3600);
|
507
|
+
tzmin = (int)(tm->tm_gmtoff / 60) - (tzhour * 60);
|
539
508
|
}
|
540
509
|
#else
|
541
510
|
tzhour = 0;
|
542
|
-
tzmin
|
511
|
+
tzmin = 0;
|
543
512
|
#endif
|
544
513
|
/* TBD replace with more efficient printer */
|
545
|
-
out->cur += sprintf(out->cur,
|
546
|
-
|
547
|
-
|
548
|
-
|
514
|
+
out->cur += sprintf(out->cur,
|
515
|
+
"%04d-%02d-%02dT%02d:%02d:%02d.%06ld%c%02d:%02d",
|
516
|
+
tm->tm_year + 1900,
|
517
|
+
tm->tm_mon + 1,
|
518
|
+
tm->tm_mday,
|
519
|
+
tm->tm_hour,
|
520
|
+
tm->tm_min,
|
521
|
+
tm->tm_sec,
|
522
|
+
nsec / 1000,
|
523
|
+
tzsign,
|
524
|
+
tzhour,
|
525
|
+
tzmin);
|
549
526
|
}
|
550
527
|
|
551
|
-
static void
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
int cnt;
|
528
|
+
static void dump_first_obj(VALUE obj, Out out) {
|
529
|
+
char buf[128];
|
530
|
+
Options copts = out->opts;
|
531
|
+
int cnt;
|
556
532
|
|
557
533
|
if (Yes == copts->with_xml) {
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
534
|
+
if (0 < copts->margin_len) {
|
535
|
+
dump_value(out, copts->margin, copts->margin_len);
|
536
|
+
}
|
537
|
+
if ('\0' == *copts->encoding) {
|
538
|
+
dump_value(out, "<?xml version=\"1.0\"?>", 21);
|
539
|
+
} else {
|
540
|
+
cnt = snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"%s\"?>", copts->encoding);
|
541
|
+
dump_value(out, buf, cnt);
|
542
|
+
}
|
567
543
|
}
|
568
544
|
if (Yes == copts->with_instruct) {
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
545
|
+
if (out->buf < out->cur) {
|
546
|
+
dump_value(out, "\n", 1);
|
547
|
+
}
|
548
|
+
if (0 < copts->margin_len) {
|
549
|
+
dump_value(out, copts->margin, copts->margin_len);
|
550
|
+
}
|
551
|
+
cnt = snprintf(
|
552
|
+
buf,
|
553
|
+
sizeof(buf),
|
554
|
+
"<?ox version=\"1.0\" mode=\"object\"%s%s?>",
|
555
|
+
(Yes == copts->circular) ? " circular=\"yes\"" : ((No == copts->circular) ? " circular=\"no\"" : ""),
|
556
|
+
(Yes == copts->xsd_date) ? " xsd_date=\"yes\"" : ((No == copts->xsd_date) ? " xsd_date=\"no\"" : ""));
|
557
|
+
dump_value(out, buf, cnt);
|
579
558
|
}
|
580
559
|
if (Yes == copts->with_dtd) {
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
560
|
+
if (0 < copts->margin_len) {
|
561
|
+
dump_value(out, copts->margin, copts->margin_len);
|
562
|
+
}
|
563
|
+
cnt = snprintf(buf,
|
564
|
+
sizeof(buf),
|
565
|
+
"%s<!DOCTYPE %c SYSTEM \"ox.dtd\">",
|
566
|
+
(out->buf < out->cur) ? "\n" : "",
|
567
|
+
obj_class_code(obj));
|
568
|
+
dump_value(out, buf, cnt);
|
586
569
|
}
|
587
570
|
if (0 < copts->margin_len) {
|
588
|
-
|
571
|
+
dump_value(out, copts->margin, copts->margin_len);
|
589
572
|
}
|
590
573
|
dump_obj(0, obj, 0, out);
|
591
574
|
}
|
592
575
|
|
593
|
-
static void
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
int cnt;
|
576
|
+
static void dump_obj(ID aid, VALUE obj, int depth, Out out) {
|
577
|
+
struct _element e;
|
578
|
+
VALUE prev_obj = out->obj;
|
579
|
+
char value_buf[64];
|
580
|
+
int cnt;
|
599
581
|
|
600
582
|
if (MAX_DEPTH < depth) {
|
601
|
-
|
583
|
+
rb_raise(rb_eSysStackError, "maximum depth exceeded");
|
602
584
|
}
|
603
585
|
out->obj = obj;
|
604
586
|
if (0 == aid) {
|
605
|
-
|
606
|
-
|
587
|
+
e.attr.str = 0;
|
588
|
+
e.attr.len = 0;
|
607
589
|
} else {
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
590
|
+
e.attr.str = rb_id2name(aid);
|
591
|
+
// Ruby 2.3 started to return NULL for some IDs so check for
|
592
|
+
// NULL. Ignore if NULL aid.
|
593
|
+
if (NULL == e.attr.str) {
|
594
|
+
return;
|
595
|
+
}
|
596
|
+
e.attr.len = strlen(e.attr.str);
|
615
597
|
}
|
616
598
|
e.closed = 0;
|
617
599
|
if (0 == depth) {
|
618
|
-
|
600
|
+
e.indent = (0 <= out->indent) ? 0 : -1;
|
619
601
|
} else if (0 > out->indent) {
|
620
|
-
|
602
|
+
e.indent = -1;
|
621
603
|
} else if (0 == out->indent) {
|
622
|
-
|
604
|
+
e.indent = 0;
|
623
605
|
} else {
|
624
|
-
|
606
|
+
e.indent = depth * out->indent;
|
625
607
|
}
|
626
|
-
e.id
|
608
|
+
e.id = 0;
|
627
609
|
e.clas.len = 0;
|
628
610
|
e.clas.str = 0;
|
629
611
|
switch (rb_type(obj)) {
|
630
612
|
case T_NIL:
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
613
|
+
e.type = NilClassCode;
|
614
|
+
e.closed = 1;
|
615
|
+
out->w_start(out, &e);
|
616
|
+
break;
|
635
617
|
case T_ARRAY:
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
618
|
+
if (0 != out->circ_cache && check_circular(out, obj, &e)) {
|
619
|
+
break;
|
620
|
+
}
|
621
|
+
cnt = (int)RARRAY_LEN(obj);
|
622
|
+
e.type = ArrayCode;
|
623
|
+
e.closed = (0 >= cnt);
|
624
|
+
out->w_start(out, &e);
|
625
|
+
if (!e.closed) {
|
626
|
+
const VALUE *np = RARRAY_PTR(obj);
|
627
|
+
int i;
|
628
|
+
int d2 = depth + 1;
|
629
|
+
|
630
|
+
for (i = cnt; 0 < i; i--, np++) {
|
631
|
+
dump_obj(0, *np, d2, out);
|
632
|
+
}
|
633
|
+
out->w_end(out, &e);
|
634
|
+
}
|
635
|
+
break;
|
654
636
|
case T_HASH:
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
637
|
+
if (0 != out->circ_cache && check_circular(out, obj, &e)) {
|
638
|
+
break;
|
639
|
+
}
|
640
|
+
cnt = (int)RHASH_SIZE(obj);
|
641
|
+
e.type = HashCode;
|
642
|
+
e.closed = (0 >= cnt);
|
643
|
+
out->w_start(out, &e);
|
644
|
+
if (0 < cnt) {
|
645
|
+
unsigned int od = out->depth;
|
646
|
+
|
647
|
+
out->depth = depth + 1;
|
648
|
+
rb_hash_foreach(obj, dump_hash, (VALUE)out);
|
649
|
+
out->depth = od;
|
650
|
+
out->w_end(out, &e);
|
651
|
+
}
|
652
|
+
break;
|
671
653
|
case T_TRUE:
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
654
|
+
e.type = TrueClassCode;
|
655
|
+
e.closed = 1;
|
656
|
+
out->w_start(out, &e);
|
657
|
+
break;
|
676
658
|
case T_FALSE:
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
659
|
+
e.type = FalseClassCode;
|
660
|
+
e.closed = 1;
|
661
|
+
out->w_start(out, &e);
|
662
|
+
break;
|
681
663
|
case T_FIXNUM:
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
664
|
+
e.type = FixnumCode;
|
665
|
+
out->w_start(out, &e);
|
666
|
+
dump_num(out, obj);
|
667
|
+
e.indent = -1;
|
668
|
+
out->w_end(out, &e);
|
669
|
+
break;
|
688
670
|
case T_FLOAT:
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
case T_STRING:
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
cnt = (int)RSTRING_LEN(obj);
|
671
|
+
e.type = FloatCode;
|
672
|
+
cnt = snprintf(value_buf, sizeof(value_buf), "%0.16g", rb_num2dbl(obj));
|
673
|
+
out->w_start(out, &e);
|
674
|
+
dump_value(out, value_buf, cnt);
|
675
|
+
e.indent = -1;
|
676
|
+
out->w_end(out, &e);
|
677
|
+
break;
|
678
|
+
case T_STRING: {
|
679
|
+
const char *str;
|
680
|
+
|
681
|
+
if (0 != out->circ_cache && check_circular(out, obj, &e)) {
|
682
|
+
break;
|
683
|
+
}
|
684
|
+
str = StringValuePtr(obj);
|
685
|
+
cnt = (int)RSTRING_LEN(obj);
|
705
686
|
#if USE_B64
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
687
|
+
if (is_xml_friendly((uchar *)str, cnt)) {
|
688
|
+
e.type = StringCode;
|
689
|
+
out->w_start(out, &e);
|
690
|
+
dump_str_value(out, str, cnt, '<');
|
691
|
+
e.indent = -1;
|
692
|
+
out->w_end(out, &e);
|
693
|
+
} else {
|
694
|
+
ulong size = b64_size(cnt);
|
695
|
+
char *b64 = ALLOCA_N(char, size + 1);
|
696
|
+
|
697
|
+
e.type = String64Code;
|
698
|
+
to_base64((uchar *)str, cnt, b64);
|
699
|
+
out->w_start(out, &e);
|
700
|
+
dump_value(out, b64, size);
|
701
|
+
e.indent = -1;
|
702
|
+
out->w_end(out, &e);
|
703
|
+
}
|
723
704
|
#else
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
705
|
+
e.type = StringCode;
|
706
|
+
out->w_start(out, &e);
|
707
|
+
dump_str_value(out, str, cnt, xml_element_chars);
|
708
|
+
e.indent = -1;
|
709
|
+
out->w_end(out, &e);
|
729
710
|
#endif
|
730
|
-
|
711
|
+
break;
|
731
712
|
}
|
732
|
-
case T_SYMBOL:
|
733
|
-
|
734
|
-
const char *sym = rb_id2name(SYM2ID(obj));
|
713
|
+
case T_SYMBOL: {
|
714
|
+
const char *sym = rb_id2name(SYM2ID(obj));
|
735
715
|
|
736
|
-
|
716
|
+
cnt = (int)strlen(sym);
|
737
717
|
#if USE_B64
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
718
|
+
if (is_xml_friendly((uchar *)sym, cnt)) {
|
719
|
+
e.type = SymbolCode;
|
720
|
+
out->w_start(out, &e);
|
721
|
+
dump_str_value(out, sym, cnt, '<');
|
722
|
+
e.indent = -1;
|
723
|
+
out->w_end(out, &e);
|
724
|
+
} else {
|
725
|
+
ulong size = b64_size(cnt);
|
726
|
+
char *b64 = ALLOCA_N(char, size + 1);
|
727
|
+
|
728
|
+
e.type = Symbol64Code;
|
729
|
+
to_base64((uchar *)sym, cnt, b64);
|
730
|
+
out->w_start(out, &e);
|
731
|
+
dump_value(out, b64, size);
|
732
|
+
e.indent = -1;
|
733
|
+
out->w_end(out, &e);
|
734
|
+
}
|
755
735
|
#else
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
736
|
+
e.type = SymbolCode;
|
737
|
+
out->w_start(out, &e);
|
738
|
+
dump_str_value(out, sym, cnt, xml_element_chars);
|
739
|
+
e.indent = -1;
|
740
|
+
out->w_end(out, &e);
|
761
741
|
#endif
|
762
|
-
|
763
|
-
}
|
764
|
-
case T_DATA:
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
case T_STRUCT:
|
805
|
-
{
|
742
|
+
break;
|
743
|
+
}
|
744
|
+
case T_DATA: {
|
745
|
+
VALUE clas;
|
746
|
+
|
747
|
+
clas = rb_obj_class(obj);
|
748
|
+
if (rb_cTime == clas) {
|
749
|
+
e.type = TimeCode;
|
750
|
+
out->w_start(out, &e);
|
751
|
+
out->w_time(out, obj);
|
752
|
+
e.indent = -1;
|
753
|
+
out->w_end(out, &e);
|
754
|
+
} else {
|
755
|
+
const char *classname = rb_class2name(clas);
|
756
|
+
|
757
|
+
if (0 == strcmp("Date", classname)) {
|
758
|
+
e.type = DateCode;
|
759
|
+
out->w_start(out, &e);
|
760
|
+
dump_date(out, obj);
|
761
|
+
e.indent = -1;
|
762
|
+
out->w_end(out, &e);
|
763
|
+
} else if (0 == strcmp("BigDecimal", classname)) {
|
764
|
+
volatile VALUE rs = rb_String(obj);
|
765
|
+
|
766
|
+
e.type = BigDecimalCode;
|
767
|
+
out->w_start(out, &e);
|
768
|
+
dump_value(out, StringValuePtr(rs), RSTRING_LEN(rs));
|
769
|
+
e.indent = -1;
|
770
|
+
out->w_end(out, &e);
|
771
|
+
} else {
|
772
|
+
if (StrictEffort == out->opts->effort) {
|
773
|
+
rb_raise(rb_eNotImpError, "Failed to dump T_DATA %s\n", classname);
|
774
|
+
} else {
|
775
|
+
e.type = NilClassCode;
|
776
|
+
e.closed = 1;
|
777
|
+
out->w_start(out, &e);
|
778
|
+
}
|
779
|
+
}
|
780
|
+
}
|
781
|
+
break;
|
782
|
+
}
|
783
|
+
case T_STRUCT: {
|
806
784
|
#ifdef RSTRUCT_GET
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
}
|
844
|
-
out->w_end(out, &e);
|
845
|
-
}
|
785
|
+
VALUE clas;
|
786
|
+
|
787
|
+
if (0 != out->circ_cache && check_circular(out, obj, &e)) {
|
788
|
+
break;
|
789
|
+
}
|
790
|
+
clas = rb_obj_class(obj);
|
791
|
+
if (rb_cRange == clas) {
|
792
|
+
VALUE beg = RSTRUCT_GET(obj, 0);
|
793
|
+
VALUE end = RSTRUCT_GET(obj, 1);
|
794
|
+
VALUE excl = RSTRUCT_GET(obj, 2);
|
795
|
+
int d2 = depth + 1;
|
796
|
+
|
797
|
+
e.type = RangeCode;
|
798
|
+
e.clas.len = 5;
|
799
|
+
e.clas.str = "Range";
|
800
|
+
out->w_start(out, &e);
|
801
|
+
dump_obj(ox_beg_id, beg, d2, out);
|
802
|
+
dump_obj(ox_end_id, end, d2, out);
|
803
|
+
dump_obj(ox_excl_id, excl, d2, out);
|
804
|
+
out->w_end(out, &e);
|
805
|
+
} else {
|
806
|
+
char num_buf[16];
|
807
|
+
int d2 = depth + 1;
|
808
|
+
long i;
|
809
|
+
long cnt = NUM2LONG(rb_struct_size(obj));
|
810
|
+
e.type = StructCode;
|
811
|
+
e.clas.str = rb_class2name(clas);
|
812
|
+
e.clas.len = strlen(e.clas.str);
|
813
|
+
out->w_start(out, &e);
|
814
|
+
|
815
|
+
for (i = 0; i < cnt; i++) {
|
816
|
+
VALUE v = RSTRUCT_GET(obj, (int)(i));
|
817
|
+
dump_obj(rb_intern(ulong2str(i, num_buf + sizeof(num_buf) - 1)), v, d2, out);
|
818
|
+
}
|
819
|
+
out->w_end(out, &e);
|
820
|
+
}
|
846
821
|
#else
|
847
|
-
|
848
|
-
|
849
|
-
|
822
|
+
e.type = NilClassCode;
|
823
|
+
e.closed = 1;
|
824
|
+
out->w_start(out, &e);
|
850
825
|
#endif
|
851
|
-
|
852
|
-
}
|
853
|
-
case T_OBJECT:
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
826
|
+
break;
|
827
|
+
}
|
828
|
+
case T_OBJECT: {
|
829
|
+
VALUE clas;
|
830
|
+
|
831
|
+
if (0 != out->circ_cache && check_circular(out, obj, &e)) {
|
832
|
+
break;
|
833
|
+
}
|
834
|
+
clas = rb_obj_class(obj);
|
835
|
+
e.clas.str = rb_class2name(clas);
|
836
|
+
e.clas.len = strlen(e.clas.str);
|
837
|
+
if (ox_document_clas == clas) {
|
838
|
+
e.type = RawCode;
|
839
|
+
out->w_start(out, &e);
|
840
|
+
dump_gen_doc(obj, depth + 1, out);
|
841
|
+
out->w_end(out, &e);
|
842
|
+
} else if (ox_element_clas == clas) {
|
843
|
+
e.type = RawCode;
|
844
|
+
out->w_start(out, &e);
|
845
|
+
dump_gen_element(obj, depth + 1, out);
|
846
|
+
out->w_end(out, &e);
|
847
|
+
} else { /* Object */
|
848
|
+
e.type = (Qtrue == rb_obj_is_kind_of(obj, rb_eException)) ? ExceptionCode : ObjectCode;
|
849
|
+
cnt = (int)rb_ivar_count(obj);
|
850
|
+
e.closed = (0 >= cnt);
|
851
|
+
out->w_start(out, &e);
|
852
|
+
if (0 < cnt) {
|
853
|
+
unsigned int od = out->depth;
|
854
|
+
|
855
|
+
out->depth = depth + 1;
|
856
|
+
rb_ivar_foreach(obj, dump_var, (VALUE)out);
|
857
|
+
out->depth = od;
|
858
|
+
out->w_end(out, &e);
|
859
|
+
}
|
860
|
+
}
|
861
|
+
break;
|
862
|
+
}
|
863
|
+
case T_REGEXP: {
|
864
|
+
volatile VALUE rs = rb_funcall2(obj, ox_inspect_id, 0, 0);
|
865
|
+
const char *s = StringValuePtr(rs);
|
866
|
+
|
867
|
+
cnt = (int)RSTRING_LEN(rs);
|
868
|
+
e.type = RegexpCode;
|
869
|
+
out->w_start(out, &e);
|
870
|
+
#if USE_B64
|
871
|
+
if (is_xml_friendly((uchar *)s, cnt)) {
|
872
|
+
/*dump_value(out, "/", 1); */
|
873
|
+
dump_str_value(out, s, cnt, '<');
|
874
|
+
} else {
|
875
|
+
ulong size = b64_size(cnt);
|
876
|
+
char *b64 = ALLOCA_N(char, size + 1);
|
877
|
+
|
878
|
+
to_base64((uchar *)s, cnt, b64);
|
879
|
+
dump_value(out, b64, size);
|
880
|
+
}
|
887
881
|
#else
|
888
|
-
|
889
|
-
//volatile VALUE vars = rb_funcall2(obj, rb_intern("instance_variables"), 0, 0);
|
890
|
-
|
891
|
-
e.type = (Qtrue == rb_obj_is_kind_of(obj, rb_eException)) ? ExceptionCode : ObjectCode;
|
892
|
-
cnt = (int)RARRAY_LEN(vars);
|
893
|
-
e.closed = (0 >= cnt);
|
894
|
-
out->w_start(out, &e);
|
895
|
-
if (0 < cnt) {
|
896
|
-
const VALUE *np = RARRAY_PTR(vars);
|
897
|
-
ID vid;
|
898
|
-
unsigned int od = out->depth;
|
899
|
-
int i;
|
900
|
-
|
901
|
-
out->depth = depth + 1;
|
902
|
-
for (i = cnt; 0 < i; i--, np++) {
|
903
|
-
vid = rb_to_id(*np);
|
904
|
-
dump_var(vid, rb_ivar_get(obj, vid), out);
|
905
|
-
}
|
906
|
-
out->depth = od;
|
907
|
-
out->w_end(out, &e);
|
908
|
-
}
|
882
|
+
dump_str_value(out, s, cnt, xml_element_chars);
|
909
883
|
#endif
|
910
|
-
|
911
|
-
|
884
|
+
e.indent = -1;
|
885
|
+
out->w_end(out, &e);
|
886
|
+
break;
|
912
887
|
}
|
913
|
-
case
|
914
|
-
|
915
|
-
volatile VALUE rs = rb_funcall2(obj, ox_inspect_id, 0, 0);
|
916
|
-
const char *s = StringValuePtr(rs);
|
888
|
+
case T_BIGNUM: {
|
889
|
+
volatile VALUE rs = rb_big2str(obj, 10);
|
917
890
|
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
ulong size = b64_size(cnt);
|
927
|
-
char *b64 = ALLOCA_N(char, size + 1);
|
928
|
-
|
929
|
-
to_base64((uchar*)s, cnt, b64);
|
930
|
-
dump_value(out, b64, size);
|
931
|
-
}
|
932
|
-
#else
|
933
|
-
dump_str_value(out, s, cnt, xml_element_chars);
|
934
|
-
#endif
|
935
|
-
e.indent = -1;
|
936
|
-
out->w_end(out, &e);
|
937
|
-
break;
|
938
|
-
}
|
939
|
-
case T_BIGNUM:
|
940
|
-
{
|
941
|
-
volatile VALUE rs = rb_big2str(obj, 10);
|
942
|
-
|
943
|
-
e.type = BignumCode;
|
944
|
-
out->w_start(out, &e);
|
945
|
-
dump_value(out, StringValuePtr(rs), RSTRING_LEN(rs));
|
946
|
-
e.indent = -1;
|
947
|
-
out->w_end(out, &e);
|
948
|
-
break;
|
949
|
-
}
|
950
|
-
#ifdef T_COMPLEX
|
951
|
-
case T_COMPLEX:
|
952
|
-
e.type = ComplexCode;
|
953
|
-
out->w_start(out, &e);
|
891
|
+
e.type = BignumCode;
|
892
|
+
out->w_start(out, &e);
|
893
|
+
dump_value(out, StringValuePtr(rs), RSTRING_LEN(rs));
|
894
|
+
e.indent = -1;
|
895
|
+
out->w_end(out, &e);
|
896
|
+
break;
|
897
|
+
}
|
898
|
+
case T_COMPLEX: e.type = ComplexCode; out->w_start(out, &e);
|
954
899
|
#ifdef RCOMPLEX
|
955
|
-
|
956
|
-
|
900
|
+
dump_obj(0, RCOMPLEX(obj)->real, depth + 1, out);
|
901
|
+
dump_obj(0, RCOMPLEX(obj)->imag, depth + 1, out);
|
957
902
|
#else
|
958
|
-
|
959
|
-
|
903
|
+
dump_obj(0, rb_funcall2(obj, rb_intern("real"), 0, 0), depth + 1, out);
|
904
|
+
dump_obj(0, rb_funcall2(obj, rb_intern("imag"), 0, 0), depth + 1, out);
|
960
905
|
#endif
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
#ifdef T_RATIONAL
|
965
|
-
case T_RATIONAL:
|
966
|
-
e.type = RationalCode;
|
967
|
-
out->w_start(out, &e);
|
906
|
+
out->w_end(out, &e);
|
907
|
+
break;
|
908
|
+
case T_RATIONAL: e.type = RationalCode; out->w_start(out, &e);
|
968
909
|
#ifdef RRATIONAL
|
969
|
-
|
970
|
-
|
910
|
+
dump_obj(0, RRATIONAL(obj)->num, depth + 1, out);
|
911
|
+
dump_obj(0, RRATIONAL(obj)->den, depth + 1, out);
|
971
912
|
#else
|
972
|
-
|
973
|
-
|
974
|
-
#endif
|
975
|
-
out->w_end(out, &e);
|
976
|
-
break;
|
913
|
+
dump_obj(0, rb_funcall2(obj, rb_intern("numerator"), 0, 0), depth + 1, out);
|
914
|
+
dump_obj(0, rb_funcall2(obj, rb_intern("denominator"), 0, 0), depth + 1, out);
|
977
915
|
#endif
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
916
|
+
out->w_end(out, &e);
|
917
|
+
break;
|
918
|
+
case T_CLASS: {
|
919
|
+
e.type = ClassCode;
|
920
|
+
e.clas.str = rb_class2name(obj);
|
921
|
+
e.clas.len = strlen(e.clas.str);
|
922
|
+
e.closed = 1;
|
923
|
+
out->w_start(out, &e);
|
924
|
+
break;
|
986
925
|
}
|
987
926
|
default:
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
break;
|
927
|
+
if (StrictEffort == out->opts->effort) {
|
928
|
+
rb_raise(rb_eNotImpError, "Failed to dump %s Object (%02x)\n", rb_obj_classname(obj), rb_type(obj));
|
929
|
+
} else {
|
930
|
+
e.type = NilClassCode;
|
931
|
+
e.closed = 1;
|
932
|
+
out->w_start(out, &e);
|
933
|
+
}
|
934
|
+
break;
|
997
935
|
}
|
998
936
|
out->obj = prev_obj;
|
999
937
|
}
|
1000
938
|
|
1001
|
-
static int
|
1002
|
-
|
1003
|
-
Out out = (Out)ov;
|
939
|
+
static int dump_var(ID key, VALUE value, VALUE ov) {
|
940
|
+
Out out = (Out)ov;
|
1004
941
|
|
1005
942
|
if (T_DATA == rb_type(value) && key == ox_mesg_id) {
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
943
|
+
/* There is a secret recipe that keeps Exception mesg attributes as a
|
944
|
+
* T_DATA until it is needed. The safe way around this hack is to call
|
945
|
+
* the message() method and use the returned string as the
|
946
|
+
* message. Not pretty but it solves the most common use of this
|
947
|
+
* hack. If there are others they will have to be handled one at a
|
948
|
+
* time.
|
949
|
+
*/
|
950
|
+
value = rb_funcall(out->obj, ox_message_id, 0);
|
1014
951
|
}
|
1015
952
|
dump_obj(key, value, out->depth, out);
|
1016
953
|
|
1017
954
|
return ST_CONTINUE;
|
1018
955
|
}
|
1019
956
|
|
1020
|
-
static int
|
1021
|
-
|
1022
|
-
Out out = (Out)ov;
|
957
|
+
static int dump_hash(VALUE key, VALUE value, VALUE ov) {
|
958
|
+
Out out = (Out)ov;
|
1023
959
|
|
1024
960
|
dump_obj(0, key, out->depth, out);
|
1025
961
|
dump_obj(0, value, out->depth, out);
|
@@ -1027,199 +963,190 @@ dump_hash(VALUE key, VALUE value, VALUE ov) {
|
|
1027
963
|
return ST_CONTINUE;
|
1028
964
|
}
|
1029
965
|
|
1030
|
-
static void
|
1031
|
-
|
1032
|
-
volatile VALUE
|
1033
|
-
volatile VALUE nodes = rb_attr_get(obj, ox_nodes_id);
|
966
|
+
static void dump_gen_doc(VALUE obj, int depth, Out out) {
|
967
|
+
volatile VALUE attrs = rb_attr_get(obj, ox_attributes_id);
|
968
|
+
volatile VALUE nodes = rb_attr_get(obj, ox_nodes_id);
|
1034
969
|
|
1035
970
|
if ('\0' == *out->opts->encoding && Qnil != attrs) {
|
1036
|
-
|
971
|
+
volatile VALUE renc = rb_hash_lookup(attrs, ox_encoding_sym);
|
1037
972
|
|
1038
|
-
|
1039
|
-
|
973
|
+
if (Qnil != renc) {
|
974
|
+
const char *enc = StringValuePtr(renc);
|
1040
975
|
|
1041
|
-
|
1042
|
-
|
976
|
+
strncpy(out->opts->encoding, enc, sizeof(out->opts->encoding) - 1);
|
977
|
+
}
|
1043
978
|
}
|
1044
979
|
if (Yes == out->opts->with_xml) {
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
980
|
+
if (0 < out->opts->margin_len) {
|
981
|
+
dump_value(out, out->opts->margin, out->opts->margin_len);
|
982
|
+
}
|
983
|
+
dump_value(out, "<?xml", 5);
|
984
|
+
if (Qnil != attrs) {
|
985
|
+
rb_hash_foreach(attrs, dump_gen_attr, (VALUE)out);
|
986
|
+
}
|
987
|
+
dump_value(out, "?>", 2);
|
1053
988
|
}
|
1054
989
|
if (Yes == out->opts->with_instruct) {
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
990
|
+
if (out->buf < out->cur) {
|
991
|
+
dump_value(out, "\n", 1);
|
992
|
+
}
|
993
|
+
if (0 < out->opts->margin_len) {
|
994
|
+
dump_value(out, out->opts->margin, out->opts->margin_len);
|
995
|
+
}
|
996
|
+
dump_value(out, "<?ox version=\"1.0\" mode=\"generic\"?>", 35);
|
1062
997
|
}
|
1063
998
|
if (Qnil != nodes) {
|
1064
|
-
|
999
|
+
dump_gen_nodes(nodes, depth, out);
|
1065
1000
|
}
|
1066
1001
|
}
|
1067
1002
|
|
1068
|
-
static void
|
1069
|
-
|
1070
|
-
volatile VALUE
|
1071
|
-
volatile VALUE
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
int indent;
|
1003
|
+
static void dump_gen_element(VALUE obj, int depth, Out out) {
|
1004
|
+
volatile VALUE rname = rb_attr_get(obj, ox_at_value_id);
|
1005
|
+
volatile VALUE attrs = rb_attr_get(obj, ox_attributes_id);
|
1006
|
+
volatile VALUE nodes = rb_attr_get(obj, ox_nodes_id);
|
1007
|
+
const char *name = StringValuePtr(rname);
|
1008
|
+
long nlen = RSTRING_LEN(rname);
|
1009
|
+
size_t size;
|
1010
|
+
int indent;
|
1077
1011
|
|
1078
1012
|
if (0 > out->indent) {
|
1079
|
-
|
1013
|
+
indent = -1;
|
1080
1014
|
} else if (0 == out->indent) {
|
1081
|
-
|
1015
|
+
indent = 0;
|
1082
1016
|
} else {
|
1083
|
-
|
1017
|
+
indent = depth * out->indent;
|
1084
1018
|
}
|
1085
1019
|
size = indent + 4 + nlen + out->opts->margin_len;
|
1086
1020
|
if (out->end - out->cur <= (long)size) {
|
1087
|
-
|
1021
|
+
grow(out, size);
|
1088
1022
|
}
|
1089
1023
|
if (0 == depth && 0 < out->opts->margin_len && 0 < out->indent) {
|
1090
|
-
|
1091
|
-
|
1024
|
+
memcpy(out->cur, out->opts->margin, out->opts->margin_len);
|
1025
|
+
out->cur += out->opts->margin_len;
|
1092
1026
|
}
|
1093
1027
|
fill_indent(out, indent);
|
1094
1028
|
*out->cur++ = '<';
|
1095
1029
|
fill_value(out, name, nlen);
|
1096
1030
|
if (Qnil != attrs) {
|
1097
|
-
|
1031
|
+
rb_hash_foreach(attrs, dump_gen_attr, (VALUE)out);
|
1098
1032
|
}
|
1099
1033
|
if (Qnil != nodes && 0 < RARRAY_LEN(nodes)) {
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1034
|
+
int do_indent;
|
1035
|
+
|
1036
|
+
*out->cur++ = '>';
|
1037
|
+
do_indent = dump_gen_nodes(nodes, depth, out);
|
1038
|
+
if (out->end - out->cur <= (long)size) {
|
1039
|
+
grow(out, size);
|
1040
|
+
}
|
1041
|
+
if (do_indent) {
|
1042
|
+
fill_indent(out, indent);
|
1043
|
+
}
|
1044
|
+
*out->cur++ = '<';
|
1045
|
+
*out->cur++ = '/';
|
1046
|
+
fill_value(out, name, nlen);
|
1113
1047
|
} else if (out->opts->no_empty) {
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1048
|
+
*out->cur++ = '>';
|
1049
|
+
*out->cur++ = '<';
|
1050
|
+
*out->cur++ = '/';
|
1051
|
+
fill_value(out, name, nlen);
|
1118
1052
|
} else {
|
1119
|
-
|
1053
|
+
*out->cur++ = '/';
|
1120
1054
|
}
|
1121
1055
|
*out->cur++ = '>';
|
1122
|
-
*out->cur
|
1056
|
+
*out->cur = '\0';
|
1123
1057
|
}
|
1124
1058
|
|
1125
|
-
static void
|
1126
|
-
|
1127
|
-
volatile VALUE
|
1128
|
-
volatile VALUE
|
1129
|
-
|
1130
|
-
const char
|
1131
|
-
|
1132
|
-
long
|
1133
|
-
|
1134
|
-
size_t size;
|
1059
|
+
static void dump_gen_instruct(VALUE obj, int depth, Out out) {
|
1060
|
+
volatile VALUE rname = rb_attr_get(obj, ox_at_value_id);
|
1061
|
+
volatile VALUE attrs = rb_attr_get(obj, ox_attributes_id);
|
1062
|
+
volatile VALUE rcontent = rb_attr_get(obj, ox_at_content_id);
|
1063
|
+
const char *name = StringValuePtr(rname);
|
1064
|
+
const char *content = 0;
|
1065
|
+
long nlen = RSTRING_LEN(rname);
|
1066
|
+
long clen = 0;
|
1067
|
+
size_t size;
|
1135
1068
|
|
1136
1069
|
if (T_STRING == rb_type(rcontent)) {
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1070
|
+
content = StringValuePtr(rcontent);
|
1071
|
+
clen = RSTRING_LEN(rcontent);
|
1072
|
+
size = 4 + nlen + clen;
|
1140
1073
|
} else {
|
1141
|
-
|
1074
|
+
size = 4 + nlen;
|
1142
1075
|
}
|
1143
1076
|
if (out->end - out->cur <= (long)size) {
|
1144
|
-
|
1077
|
+
grow(out, size);
|
1145
1078
|
}
|
1146
1079
|
*out->cur++ = '<';
|
1147
1080
|
*out->cur++ = '?';
|
1148
1081
|
fill_value(out, name, nlen);
|
1149
1082
|
if (0 != content) {
|
1150
|
-
|
1083
|
+
fill_value(out, content, clen);
|
1151
1084
|
} else if (Qnil != attrs) {
|
1152
|
-
|
1085
|
+
rb_hash_foreach(attrs, dump_gen_attr, (VALUE)out);
|
1153
1086
|
}
|
1154
1087
|
*out->cur++ = '?';
|
1155
1088
|
*out->cur++ = '>';
|
1156
|
-
*out->cur
|
1089
|
+
*out->cur = '\0';
|
1157
1090
|
}
|
1158
1091
|
|
1159
|
-
static int
|
1160
|
-
|
1161
|
-
|
1162
|
-
int indent_needed = 1;
|
1092
|
+
static int dump_gen_nodes(VALUE obj, int depth, Out out) {
|
1093
|
+
long cnt = RARRAY_LEN(obj);
|
1094
|
+
int indent_needed = 1;
|
1163
1095
|
|
1164
1096
|
if (0 < cnt) {
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1097
|
+
const VALUE *np = RARRAY_PTR(obj);
|
1098
|
+
VALUE clas;
|
1099
|
+
int d2 = depth + 1;
|
1100
|
+
|
1101
|
+
if (MAX_DEPTH < depth) {
|
1102
|
+
rb_raise(rb_eSysStackError, "maximum depth exceeded");
|
1103
|
+
}
|
1104
|
+
for (; 0 < cnt; cnt--, np++) {
|
1105
|
+
clas = rb_obj_class(*np);
|
1106
|
+
if (ox_element_clas == clas) {
|
1107
|
+
dump_gen_element(*np, d2, out);
|
1108
|
+
} else if (ox_instruct_clas == clas) {
|
1109
|
+
dump_gen_instruct(*np, d2, out);
|
1110
|
+
indent_needed = (1 == cnt) ? 0 : 1;
|
1111
|
+
} else if (rb_cString == clas) {
|
1112
|
+
dump_str_value(out, StringValuePtr(*(VALUE *)np), RSTRING_LEN(*np), xml_element_chars);
|
1113
|
+
indent_needed = (1 == cnt) ? 0 : 1;
|
1114
|
+
} else if (ox_comment_clas == clas) {
|
1115
|
+
dump_gen_val_node(*np, d2, "<!-- ", 5, " -->", 4, out);
|
1116
|
+
} else if (ox_raw_clas == clas) {
|
1117
|
+
dump_gen_val_node(*np, d2, "", 0, "", 0, out);
|
1118
|
+
} else if (ox_cdata_clas == clas) {
|
1119
|
+
dump_gen_val_node(*np, d2, "<![CDATA[", 9, "]]>", 3, out);
|
1120
|
+
} else if (ox_doctype_clas == clas) {
|
1121
|
+
dump_gen_val_node(*np, d2, "<!DOCTYPE ", 10, ">", 1, out);
|
1122
|
+
} else {
|
1123
|
+
rb_raise(rb_eTypeError, "Unexpected class, %s, while dumping generic XML\n", rb_class2name(clas));
|
1124
|
+
}
|
1125
|
+
}
|
1194
1126
|
}
|
1195
1127
|
return indent_needed;
|
1196
1128
|
}
|
1197
1129
|
|
1198
|
-
static int
|
1199
|
-
|
1200
|
-
Out out = (Out)ov;
|
1130
|
+
static int dump_gen_attr(VALUE key, VALUE value, VALUE ov) {
|
1131
|
+
Out out = (Out)ov;
|
1201
1132
|
|
1202
|
-
const char
|
1203
|
-
size_t
|
1204
|
-
size_t
|
1133
|
+
const char *ks;
|
1134
|
+
size_t klen;
|
1135
|
+
size_t size;
|
1205
1136
|
|
1206
1137
|
switch (rb_type(key)) {
|
1207
|
-
case T_SYMBOL:
|
1208
|
-
|
1209
|
-
break;
|
1210
|
-
case T_STRING:
|
1211
|
-
ks = StringValuePtr(key);
|
1212
|
-
break;
|
1138
|
+
case T_SYMBOL: ks = rb_id2name(SYM2ID(key)); break;
|
1139
|
+
case T_STRING: ks = StringValuePtr(key); break;
|
1213
1140
|
default:
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1141
|
+
key = rb_String(key);
|
1142
|
+
ks = StringValuePtr(key);
|
1143
|
+
break;
|
1217
1144
|
}
|
1218
|
-
klen
|
1145
|
+
klen = strlen(ks);
|
1219
1146
|
value = rb_String(value);
|
1220
|
-
size
|
1147
|
+
size = 4 + klen + RSTRING_LEN(value);
|
1221
1148
|
if (out->end - out->cur <= (long)size) {
|
1222
|
-
|
1149
|
+
grow(out, size);
|
1223
1150
|
}
|
1224
1151
|
*out->cur++ = ' ';
|
1225
1152
|
fill_value(out, ks, klen);
|
@@ -1232,30 +1159,28 @@ dump_gen_attr(VALUE key, VALUE value, VALUE ov) {
|
|
1232
1159
|
}
|
1233
1160
|
|
1234
1161
|
static void
|
1235
|
-
dump_gen_val_node(VALUE obj, int depth,
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
size_t size;
|
1242
|
-
int indent;
|
1162
|
+
dump_gen_val_node(VALUE obj, int depth, const char *pre, size_t plen, const char *suf, size_t slen, Out out) {
|
1163
|
+
volatile VALUE v = rb_attr_get(obj, ox_at_value_id);
|
1164
|
+
const char *val;
|
1165
|
+
size_t vlen;
|
1166
|
+
size_t size;
|
1167
|
+
int indent;
|
1243
1168
|
|
1244
1169
|
if (T_STRING != rb_type(v)) {
|
1245
|
-
|
1170
|
+
return;
|
1246
1171
|
}
|
1247
|
-
val
|
1172
|
+
val = StringValuePtr(v);
|
1248
1173
|
vlen = RSTRING_LEN(v);
|
1249
1174
|
if (0 > out->indent) {
|
1250
|
-
|
1175
|
+
indent = -1;
|
1251
1176
|
} else if (0 == out->indent) {
|
1252
|
-
|
1177
|
+
indent = 0;
|
1253
1178
|
} else {
|
1254
|
-
|
1179
|
+
indent = depth * out->indent;
|
1255
1180
|
}
|
1256
1181
|
size = indent + plen + slen + vlen + out->opts->margin_len;
|
1257
1182
|
if (out->end - out->cur <= (long)size) {
|
1258
|
-
|
1183
|
+
grow(out, size);
|
1259
1184
|
}
|
1260
1185
|
fill_indent(out, indent);
|
1261
1186
|
fill_value(out, pre, plen);
|
@@ -1264,63 +1189,60 @@ dump_gen_val_node(VALUE obj, int depth,
|
|
1264
1189
|
*out->cur = '\0';
|
1265
1190
|
}
|
1266
1191
|
|
1267
|
-
static void
|
1268
|
-
|
1269
|
-
VALUE clas = rb_obj_class(obj);
|
1192
|
+
static void dump_obj_to_xml(VALUE obj, Options copts, Out out) {
|
1193
|
+
VALUE clas = rb_obj_class(obj);
|
1270
1194
|
|
1271
|
-
out->w_time
|
1272
|
-
out->buf
|
1273
|
-
out->end
|
1274
|
-
out->cur
|
1195
|
+
out->w_time = (Yes == copts->xsd_date) ? dump_time_xsd : dump_time_thin;
|
1196
|
+
out->buf = ALLOC_N(char, 65336);
|
1197
|
+
out->end = out->buf + 65325; /* 10 less than end plus extra for possible errors */
|
1198
|
+
out->cur = out->buf;
|
1275
1199
|
out->circ_cache = 0;
|
1276
|
-
out->circ_cnt
|
1277
|
-
out->opts
|
1278
|
-
out->obj
|
1279
|
-
*out->cur
|
1200
|
+
out->circ_cnt = 0;
|
1201
|
+
out->opts = copts;
|
1202
|
+
out->obj = obj;
|
1203
|
+
*out->cur = '\0';
|
1280
1204
|
if (Yes == copts->circular) {
|
1281
|
-
|
1205
|
+
ox_cache8_new(&out->circ_cache);
|
1282
1206
|
}
|
1283
1207
|
out->indent = copts->indent;
|
1284
1208
|
|
1285
1209
|
if (ox_document_clas == clas) {
|
1286
|
-
|
1210
|
+
dump_gen_doc(obj, -1, out);
|
1287
1211
|
} else if (ox_element_clas == clas) {
|
1288
|
-
|
1212
|
+
dump_gen_element(obj, 0, out);
|
1289
1213
|
} else {
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1214
|
+
out->w_start = dump_start;
|
1215
|
+
out->w_end = dump_end;
|
1216
|
+
dump_first_obj(obj, out);
|
1293
1217
|
}
|
1294
1218
|
if (0 <= out->indent) {
|
1295
|
-
|
1219
|
+
dump_value(out, "\n", 1);
|
1296
1220
|
}
|
1297
1221
|
if (Yes == copts->circular) {
|
1298
|
-
|
1222
|
+
ox_cache8_delete(out->circ_cache);
|
1299
1223
|
}
|
1300
1224
|
}
|
1301
1225
|
|
1302
|
-
char*
|
1303
|
-
ox_write_obj_to_str(VALUE obj, Options copts) {
|
1226
|
+
char *ox_write_obj_to_str(VALUE obj, Options copts) {
|
1304
1227
|
struct _out out;
|
1305
1228
|
|
1306
1229
|
dump_obj_to_xml(obj, copts, &out);
|
1307
1230
|
return out.buf;
|
1308
1231
|
}
|
1309
1232
|
|
1310
|
-
void
|
1311
|
-
ox_write_obj_to_file(VALUE obj, const char *path, Options copts) {
|
1233
|
+
void ox_write_obj_to_file(VALUE obj, const char *path, Options copts) {
|
1312
1234
|
struct _out out;
|
1313
|
-
size_t
|
1314
|
-
FILE
|
1235
|
+
size_t size;
|
1236
|
+
FILE *f;
|
1315
1237
|
|
1316
1238
|
dump_obj_to_xml(obj, copts, &out);
|
1317
1239
|
size = out.cur - out.buf;
|
1318
1240
|
if (0 == (f = fopen(path, "w"))) {
|
1319
|
-
|
1241
|
+
rb_raise(rb_eIOError, "%s\n", strerror(errno));
|
1320
1242
|
}
|
1321
1243
|
if (size != fwrite(out.buf, 1, size, f)) {
|
1322
|
-
|
1323
|
-
|
1244
|
+
int err = ferror(f);
|
1245
|
+
rb_raise(rb_eIOError, "Write failed. [%d:%s]\n", err, strerror(err));
|
1324
1246
|
}
|
1325
1247
|
xfree(out.buf);
|
1326
1248
|
fclose(f);
|