fast-xml 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +164 -0
- data/ext/fastxml/extconf.rb +17 -0
- data/ext/fastxml/fastxml.c +67 -0
- data/ext/fastxml/fastxml.h +14 -0
- data/ext/fastxml/xh.c +338 -0
- data/ext/fastxml/xh.h +58 -0
- data/ext/fastxml/xh_buffer.c +40 -0
- data/ext/fastxml/xh_buffer.h +38 -0
- data/ext/fastxml/xh_buffer_helper.h +97 -0
- data/ext/fastxml/xh_config.h +74 -0
- data/ext/fastxml/xh_core.h +53 -0
- data/ext/fastxml/xh_encoder.c +193 -0
- data/ext/fastxml/xh_encoder.h +56 -0
- data/ext/fastxml/xh_h2x.c +62 -0
- data/ext/fastxml/xh_h2x.h +93 -0
- data/ext/fastxml/xh_h2x_native.c +89 -0
- data/ext/fastxml/xh_h2x_native_attr.c +161 -0
- data/ext/fastxml/xh_log.c +31 -0
- data/ext/fastxml/xh_log.h +100 -0
- data/ext/fastxml/xh_param.c +77 -0
- data/ext/fastxml/xh_param.h +56 -0
- data/ext/fastxml/xh_ruby_buffer.c +51 -0
- data/ext/fastxml/xh_ruby_buffer.h +30 -0
- data/ext/fastxml/xh_sort.c +40 -0
- data/ext/fastxml/xh_sort.h +20 -0
- data/ext/fastxml/xh_stack.c +19 -0
- data/ext/fastxml/xh_stack.h +41 -0
- data/ext/fastxml/xh_string.h +105 -0
- data/ext/fastxml/xh_writer.c +94 -0
- data/ext/fastxml/xh_writer.h +49 -0
- data/ext/fastxml/xh_xml.h +453 -0
- data/lib/fastxml.rb +59 -0
- data/lib/fastxml/error.rb +7 -0
- data/lib/fastxml/version.rb +3 -0
- metadata +139 -0
@@ -0,0 +1,105 @@
|
|
1
|
+
#ifndef _XH_STRING_H_
|
2
|
+
#define _XH_STRING_H_
|
3
|
+
|
4
|
+
#include "xh_config.h"
|
5
|
+
#include "xh_core.h"
|
6
|
+
|
7
|
+
#define xh_str_equal2(p, c0, c1) \
|
8
|
+
((((uint32_t *) (p))[0] & 0xffff) == ((c1 << 8) | c0))
|
9
|
+
|
10
|
+
#define xh_str_equal3(p, c0, c1, c2) \
|
11
|
+
((((uint32_t *) (p))[0] & 0xffffff) == ((c2 << 16) | (c1 << 8) | c0))
|
12
|
+
|
13
|
+
#define xh_str_equal4(p, c0, c1, c2, c3) \
|
14
|
+
(*(uint32_t *) (p) == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0))
|
15
|
+
|
16
|
+
#define xh_str_equal5(p, c0, c1, c2, c3, c4) \
|
17
|
+
(xh_str_equal4(p, c0, c1, c2, c3) && (p)[4] == c4)
|
18
|
+
|
19
|
+
#define xh_str_equal6(p, c0, c1, c2, c3, c4, c5) \
|
20
|
+
(xh_str_equal4(p, c0, c1, c2, c3) && xh_str_equal2(&p[4], c4, c5))
|
21
|
+
|
22
|
+
#define xh_str_equal7(p, c0, c1, c2, c3, c4, c5, c6) \
|
23
|
+
(xh_str_equal4(p, c0, c1, c2, c3) && xh_str_equal3(&p[4], c4, c5, c6))
|
24
|
+
|
25
|
+
#define xh_str_equal8(p, c0, c1, c2, c3, c4, c5, c6, c7) \
|
26
|
+
(xh_str_equal4(p, c0, c1, c2, c3) && xh_str_equal4(&p[4], c4, c5, c6, c7))
|
27
|
+
|
28
|
+
#define xh_str_equal9(p, c0, c1, c2, c3, c4, c5, c6, c7, c8) \
|
29
|
+
(xh_str_equal8(p, c0, c1, c2, c3, c4, c5, c6, c7) && (p)[8] == c8)
|
30
|
+
|
31
|
+
#define xh_str_equal10(p, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9) \
|
32
|
+
(xh_str_equal8(p, c0, c1, c2, c3, c4, c5, c6, c7) && xh_str_equal2(&p[8], c8, c9))
|
33
|
+
|
34
|
+
#define xh_str_equal11(p, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10) \
|
35
|
+
(xh_str_equal8(p, c0, c1, c2, c3, c4, c5, c6, c7) && xh_str_equal3(&p[8], c8, c9, c10))
|
36
|
+
|
37
|
+
#define xh_str_equal12(p, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11)\
|
38
|
+
(xh_str_equal8(p, c0, c1, c2, c3, c4, c5, c6, c7) && xh_str_equal4(&p[8], c8, c9, c10, c11))
|
39
|
+
|
40
|
+
#define xh_str_equal13(p, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12)\
|
41
|
+
(xh_str_equal8(p, c0, c1, c2, c3, c4, c5, c6, c7) && xh_str_equal5(&p[8], c8, c9, c10, c11, c12))
|
42
|
+
|
43
|
+
|
44
|
+
#define xh_strcmp(s1, s2) strcmp((const char *) (s1), (const char *) (s2))
|
45
|
+
#define xh_strcasecmp(s1, s2) strcasecmp((const char *) (s1), (const char *) (s2))
|
46
|
+
#define xh_strncmp(s1, s2, n) strncmp((const char *) (s1), (const char *) (s2), (n))
|
47
|
+
#define xh_strlen(s) strlen((const char *) (s))
|
48
|
+
#define xh_strcpy(d, s) strcpy((char *) (d), (const char *) (s))
|
49
|
+
#define xh_strncpy(d, s, n) strncpy((char *) (d), (const char *) (s), (n))
|
50
|
+
|
51
|
+
XH_INLINE xh_char_t *
|
52
|
+
xh_str_trim(xh_char_t *s, size_t *len)
|
53
|
+
{
|
54
|
+
xh_char_t *end, ch;
|
55
|
+
|
56
|
+
end = s + *len;
|
57
|
+
|
58
|
+
while ((ch = *s++) == ' ' || ch == '\t' || ch == '\n' || ch == '\r');
|
59
|
+
if (ch == '\0') {
|
60
|
+
*len = 0;
|
61
|
+
return s - 1;
|
62
|
+
}
|
63
|
+
|
64
|
+
s--;
|
65
|
+
|
66
|
+
while (--end != s && ((ch = *end) == ' ' || ch == '\t' || ch == '\n' || ch == '\r'));
|
67
|
+
|
68
|
+
*len = end - s + 1;
|
69
|
+
|
70
|
+
return s;
|
71
|
+
}
|
72
|
+
|
73
|
+
XH_INLINE xh_char_t *
|
74
|
+
xh_str_copy(xh_char_t *dest, const xh_char_t *src, size_t n)
|
75
|
+
{
|
76
|
+
dest[--n] = '\0';
|
77
|
+
return XH_CHAR_CAST strncpy((char *) dest, (const char *) src, n);
|
78
|
+
}
|
79
|
+
|
80
|
+
XH_INLINE xh_char_t *
|
81
|
+
xh_str_range_copy(xh_char_t *dest, const xh_char_t *src, size_t l, size_t n)
|
82
|
+
{
|
83
|
+
if (l < n) n = l + 1;
|
84
|
+
dest[--n] = '\0';
|
85
|
+
return XH_CHAR_CAST strncpy((char *) dest, (const char *) src, n);
|
86
|
+
}
|
87
|
+
|
88
|
+
XH_INLINE void
|
89
|
+
xh_memmove(xh_char_t *dest, const xh_char_t *src, size_t n)
|
90
|
+
{
|
91
|
+
while (n--) *dest++ = *src++;
|
92
|
+
}
|
93
|
+
|
94
|
+
XH_INLINE xh_bool_t
|
95
|
+
xh_str_is_xml(xh_char_t *s)
|
96
|
+
{
|
97
|
+
xh_char_t ch;
|
98
|
+
|
99
|
+
while ((ch = *s++) == ' ' || ch =='\t' || ch == '\n' || ch == '\r');
|
100
|
+
if (ch == '<') return TRUE;
|
101
|
+
|
102
|
+
return FALSE;
|
103
|
+
}
|
104
|
+
|
105
|
+
#endif /* _XH_STRING_H_ */
|
@@ -0,0 +1,94 @@
|
|
1
|
+
#include "xh_config.h"
|
2
|
+
#include "xh_core.h"
|
3
|
+
|
4
|
+
void
|
5
|
+
xh_writer_resize_buffer(xh_writer_t *writer, size_t inc)
|
6
|
+
{
|
7
|
+
(void) xh_writer_flush(writer);
|
8
|
+
|
9
|
+
xh_ruby_buffer_grow(&writer->main_buf, inc);
|
10
|
+
}
|
11
|
+
|
12
|
+
VALUE
|
13
|
+
xh_writer_flush_buffer(xh_writer_t *writer, xh_ruby_buffer_t *buf)
|
14
|
+
{
|
15
|
+
size_t use = xh_writer_flush_ruby_buffer(buf);
|
16
|
+
|
17
|
+
if (writer->ruby_io != Qnil) {
|
18
|
+
if (use > 0) xh_writer_flush_ruby_io(buf, writer->ruby_io, use);
|
19
|
+
return Qnil;
|
20
|
+
}
|
21
|
+
|
22
|
+
return buf->scalar;
|
23
|
+
}
|
24
|
+
|
25
|
+
#ifdef XH_HAVE_ENCODER
|
26
|
+
void
|
27
|
+
xh_writer_encode_buffer(xh_writer_t *writer, xh_ruby_buffer_t *main_buf, xh_ruby_buffer_t *enc_buf)
|
28
|
+
{
|
29
|
+
size_t len;
|
30
|
+
|
31
|
+
/* 1 char -> 4 chars and '\0' */
|
32
|
+
len = xh_buffer_use(main_buf) * 4 + 1;
|
33
|
+
|
34
|
+
if (len > (size_t) (enc_buf->end - enc_buf->cur)) {
|
35
|
+
xh_writer_flush_buffer(writer, enc_buf);
|
36
|
+
|
37
|
+
xh_ruby_buffer_grow(enc_buf, len);
|
38
|
+
}
|
39
|
+
|
40
|
+
xh_encoder_encode_ruby_buffer(writer->encoder, main_buf, enc_buf);
|
41
|
+
}
|
42
|
+
#endif
|
43
|
+
|
44
|
+
VALUE
|
45
|
+
xh_writer_flush(xh_writer_t *writer)
|
46
|
+
{
|
47
|
+
xh_ruby_buffer_t *buf;
|
48
|
+
|
49
|
+
#ifdef XH_HAVE_ENCODER
|
50
|
+
if (writer->encoder != NULL) {
|
51
|
+
xh_writer_encode_buffer(writer, &writer->main_buf, &writer->enc_buf);
|
52
|
+
buf = &writer->enc_buf;
|
53
|
+
}
|
54
|
+
else {
|
55
|
+
buf = &writer->main_buf;
|
56
|
+
}
|
57
|
+
#else
|
58
|
+
buf = &writer->main_buf;
|
59
|
+
#endif
|
60
|
+
|
61
|
+
return xh_writer_flush_buffer(writer, buf);
|
62
|
+
}
|
63
|
+
|
64
|
+
void
|
65
|
+
xh_writer_destroy(xh_writer_t *writer)
|
66
|
+
{
|
67
|
+
#ifdef XH_HAVE_ENCODER
|
68
|
+
xh_encoder_destroy(writer->encoder);
|
69
|
+
#endif
|
70
|
+
}
|
71
|
+
|
72
|
+
void
|
73
|
+
xh_writer_init(xh_writer_t *writer, xh_char_t *encoding, VALUE output, size_t size, xh_uint_t indent, xh_bool_t trim)
|
74
|
+
{
|
75
|
+
writer->indent = indent;
|
76
|
+
writer->trim = trim;
|
77
|
+
|
78
|
+
xh_ruby_buffer_init(&writer->main_buf, size);
|
79
|
+
|
80
|
+
if (encoding[0] != '\0' && xh_strcasecmp(encoding, XH_INTERNAL_ENCODING) != 0) {
|
81
|
+
#ifdef XH_HAVE_ENCODER
|
82
|
+
writer->encoder = xh_encoder_create(encoding, XH_CHAR_CAST XH_INTERNAL_ENCODING);
|
83
|
+
if (writer->encoder == NULL) {
|
84
|
+
rb_raise(xh_parse_error_class, "Can't create encoder for '%s'", encoding);
|
85
|
+
}
|
86
|
+
|
87
|
+
xh_ruby_buffer_init(&writer->enc_buf, size * 4);
|
88
|
+
#else
|
89
|
+
rb_raise(xh_parse_error_class, "Can't create encoder for '%s'", encoding);
|
90
|
+
#endif
|
91
|
+
}
|
92
|
+
|
93
|
+
writer->ruby_io = output;
|
94
|
+
}
|
@@ -0,0 +1,49 @@
|
|
1
|
+
#ifndef _XH_WRITER_H_
|
2
|
+
#define _XH_WRITER_H_
|
3
|
+
|
4
|
+
#include "xh_config.h"
|
5
|
+
#include "xh_core.h"
|
6
|
+
|
7
|
+
#define XH_WRITER_RESIZE_BUFFER(w, b, l) \
|
8
|
+
if (((l) + 1) > (size_t) xh_buffer_avail(b)) { \
|
9
|
+
xh_writer_resize_buffer(w, (l) + 1); \
|
10
|
+
}
|
11
|
+
|
12
|
+
typedef struct _xh_writer_t xh_writer_t;
|
13
|
+
struct _xh_writer_t {
|
14
|
+
#ifdef XH_HAVE_ENCODER
|
15
|
+
xh_encoder_t *encoder;
|
16
|
+
xh_ruby_buffer_t enc_buf;
|
17
|
+
#endif
|
18
|
+
VALUE ruby_io;
|
19
|
+
xh_ruby_buffer_t main_buf;
|
20
|
+
xh_int_t indent;
|
21
|
+
xh_int_t indent_count;
|
22
|
+
xh_bool_t trim;
|
23
|
+
};
|
24
|
+
|
25
|
+
VALUE xh_writer_flush_buffer(xh_writer_t *writer, xh_ruby_buffer_t *buf);
|
26
|
+
VALUE xh_writer_flush(xh_writer_t *writer);
|
27
|
+
void xh_writer_resize_buffer(xh_writer_t *writer, size_t inc);
|
28
|
+
void xh_writer_destroy(xh_writer_t *writer);
|
29
|
+
void xh_writer_init(xh_writer_t *writer, xh_char_t *encoding, VALUE output, size_t size, xh_uint_t indent, xh_bool_t trim);
|
30
|
+
|
31
|
+
XH_INLINE void
|
32
|
+
xh_writer_flush_ruby_io(xh_ruby_buffer_t *buf, VALUE ruby_io, size_t use)
|
33
|
+
{
|
34
|
+
rb_io_write(ruby_io, buf->scalar);
|
35
|
+
xh_buffer_reset(buf);
|
36
|
+
}
|
37
|
+
|
38
|
+
XH_INLINE size_t
|
39
|
+
xh_writer_flush_ruby_buffer(xh_ruby_buffer_t *buf)
|
40
|
+
{
|
41
|
+
size_t use = xh_buffer_use(buf);
|
42
|
+
|
43
|
+
*buf->cur = '\0';
|
44
|
+
rb_str_set_len(buf->scalar, use);
|
45
|
+
|
46
|
+
return use;
|
47
|
+
}
|
48
|
+
|
49
|
+
#endif /* _XH_WRITER_H_ */
|
@@ -0,0 +1,453 @@
|
|
1
|
+
#ifndef _XH_XML_H_
|
2
|
+
#define _XH_XML_H_
|
3
|
+
|
4
|
+
#include "xh_config.h"
|
5
|
+
#include "xh_core.h"
|
6
|
+
|
7
|
+
static const xh_char_t indent_string[60] = " ";
|
8
|
+
|
9
|
+
XH_INLINE void
|
10
|
+
xh_xml_write_xml_declaration(xh_writer_t *writer, xh_char_t *version, xh_char_t *encoding)
|
11
|
+
{
|
12
|
+
xh_ruby_buffer_t *buf;
|
13
|
+
size_t ver_len, enc_len;
|
14
|
+
|
15
|
+
buf = &writer->main_buf;
|
16
|
+
ver_len = xh_strlen(version);
|
17
|
+
if (encoding[0] == '\0')
|
18
|
+
encoding = XH_CHAR_CAST XH_INTERNAL_ENCODING;
|
19
|
+
enc_len = xh_strlen(encoding);
|
20
|
+
|
21
|
+
XH_WRITER_RESIZE_BUFFER(writer, buf, sizeof("<?xml version=\"\" encoding=\"\"?>\n") - 1 + ver_len * 6 + enc_len * 6)
|
22
|
+
|
23
|
+
XH_BUFFER_WRITE_CONSTANT(buf, "<?xml version=\"")
|
24
|
+
XH_BUFFER_WRITE_ESCAPE_ATTR(buf, version, ver_len);
|
25
|
+
XH_BUFFER_WRITE_CONSTANT(buf, "\" encoding=\"")
|
26
|
+
XH_BUFFER_WRITE_ESCAPE_ATTR(buf, encoding, enc_len);
|
27
|
+
XH_BUFFER_WRITE_CHAR4(buf, "\"?>\n");
|
28
|
+
|
29
|
+
}
|
30
|
+
|
31
|
+
XH_INLINE void
|
32
|
+
xh_xml_write_node(xh_writer_t *writer, xh_char_t *name, size_t name_len, VALUE value, xh_bool_t raw)
|
33
|
+
{
|
34
|
+
size_t indent_len;
|
35
|
+
xh_ruby_buffer_t *buf;
|
36
|
+
xh_char_t *content;
|
37
|
+
size_t content_len;
|
38
|
+
|
39
|
+
buf = &writer->main_buf;
|
40
|
+
value = rb_obj_as_string(value);
|
41
|
+
content = XH_CHAR_CAST RSTRING_PTR(value);
|
42
|
+
content_len = RSTRING_LEN(value);
|
43
|
+
|
44
|
+
if (writer->trim && content_len) {
|
45
|
+
content = xh_str_trim(content, &content_len);
|
46
|
+
}
|
47
|
+
|
48
|
+
if (writer->indent) {
|
49
|
+
indent_len = writer->indent_count * writer->indent;
|
50
|
+
if (indent_len > sizeof(indent_string)) {
|
51
|
+
indent_len = sizeof(indent_string);
|
52
|
+
}
|
53
|
+
|
54
|
+
/* "</" + "_" + ">" + "\n" */
|
55
|
+
XH_WRITER_RESIZE_BUFFER(writer, buf, indent_len + name_len * 2 + 10 + (raw ? content_len : content_len * 5))
|
56
|
+
|
57
|
+
XH_BUFFER_WRITE_LONG_STRING(buf, indent_string, indent_len);
|
58
|
+
}
|
59
|
+
else {
|
60
|
+
/* "</" + "_" + ">" + "\n" */
|
61
|
+
XH_WRITER_RESIZE_BUFFER(writer, buf, name_len * 2 + 10 + (raw ? content_len : content_len * 5))
|
62
|
+
}
|
63
|
+
|
64
|
+
XH_BUFFER_WRITE_CHAR(buf, '<')
|
65
|
+
|
66
|
+
if (name[0] >= '0' && name[0] <= '9') {
|
67
|
+
XH_BUFFER_WRITE_CHAR(buf, '_')
|
68
|
+
}
|
69
|
+
|
70
|
+
XH_BUFFER_WRITE_LONG_STRING(buf, name, name_len)
|
71
|
+
|
72
|
+
XH_BUFFER_WRITE_CHAR(buf, '>')
|
73
|
+
|
74
|
+
if (raw) {
|
75
|
+
XH_BUFFER_WRITE_LONG_STRING(buf, content, content_len)
|
76
|
+
}
|
77
|
+
else {
|
78
|
+
XH_BUFFER_WRITE_ESCAPE_STRING(buf, content, content_len)
|
79
|
+
}
|
80
|
+
|
81
|
+
XH_BUFFER_WRITE_CHAR2(buf, "</")
|
82
|
+
|
83
|
+
if (name[0] >= '0' && name[0] <= '9') {
|
84
|
+
XH_BUFFER_WRITE_CHAR(buf, '_')
|
85
|
+
}
|
86
|
+
|
87
|
+
XH_BUFFER_WRITE_LONG_STRING(buf, name, name_len)
|
88
|
+
|
89
|
+
XH_BUFFER_WRITE_CHAR(buf, '>')
|
90
|
+
|
91
|
+
if (writer->indent) {
|
92
|
+
XH_BUFFER_WRITE_CHAR(buf, '\n')
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
XH_INLINE void
|
97
|
+
xh_xml_write_empty_node(xh_writer_t *writer, xh_char_t *name, size_t name_len)
|
98
|
+
{
|
99
|
+
size_t indent_len;
|
100
|
+
xh_ruby_buffer_t *buf;
|
101
|
+
|
102
|
+
buf = &writer->main_buf;
|
103
|
+
|
104
|
+
if (writer->indent) {
|
105
|
+
indent_len = writer->indent_count * writer->indent;
|
106
|
+
if (indent_len > sizeof(indent_string)) {
|
107
|
+
indent_len = sizeof(indent_string);
|
108
|
+
}
|
109
|
+
|
110
|
+
/* "</" + "_" + ">" + "\n" */
|
111
|
+
XH_WRITER_RESIZE_BUFFER(writer, buf, indent_len + name_len + 5)
|
112
|
+
|
113
|
+
XH_BUFFER_WRITE_LONG_STRING(buf, indent_string, indent_len);
|
114
|
+
}
|
115
|
+
else {
|
116
|
+
/* "</" + "_" + ">" + "\n" */
|
117
|
+
XH_WRITER_RESIZE_BUFFER(writer, buf, name_len + 5)
|
118
|
+
}
|
119
|
+
|
120
|
+
XH_BUFFER_WRITE_CHAR(buf, '<')
|
121
|
+
|
122
|
+
if (name[0] >= '0' && name[0] <= '9') {
|
123
|
+
XH_BUFFER_WRITE_CHAR(buf, '_')
|
124
|
+
}
|
125
|
+
|
126
|
+
XH_BUFFER_WRITE_LONG_STRING(buf, name, name_len)
|
127
|
+
|
128
|
+
XH_BUFFER_WRITE_CHAR2(buf, "/>")
|
129
|
+
|
130
|
+
if (writer->indent) {
|
131
|
+
XH_BUFFER_WRITE_CHAR(buf, '\n')
|
132
|
+
}
|
133
|
+
}
|
134
|
+
|
135
|
+
XH_INLINE void
|
136
|
+
xh_xml_write_start_node(xh_writer_t *writer, xh_char_t *name, size_t name_len)
|
137
|
+
{
|
138
|
+
size_t indent_len;
|
139
|
+
xh_ruby_buffer_t *buf;
|
140
|
+
|
141
|
+
buf = &writer->main_buf;
|
142
|
+
|
143
|
+
if (writer->indent) {
|
144
|
+
indent_len = writer->indent_count++ * writer->indent;
|
145
|
+
if (indent_len > sizeof(indent_string)) {
|
146
|
+
indent_len = sizeof(indent_string);
|
147
|
+
}
|
148
|
+
|
149
|
+
/* "</" + "_" + ">" + "\n" */
|
150
|
+
XH_WRITER_RESIZE_BUFFER(writer, buf, indent_len + name_len + 5)
|
151
|
+
|
152
|
+
XH_BUFFER_WRITE_LONG_STRING(buf, indent_string, indent_len);
|
153
|
+
}
|
154
|
+
else {
|
155
|
+
/* "</" + "_" + ">" + "\n" */
|
156
|
+
XH_WRITER_RESIZE_BUFFER(writer, buf, name_len + 5)
|
157
|
+
}
|
158
|
+
|
159
|
+
XH_BUFFER_WRITE_CHAR(buf, '<')
|
160
|
+
|
161
|
+
if (name[0] >= '0' && name[0] <= '9') {
|
162
|
+
XH_BUFFER_WRITE_CHAR(buf, '_')
|
163
|
+
}
|
164
|
+
|
165
|
+
XH_BUFFER_WRITE_LONG_STRING(buf, name, name_len)
|
166
|
+
|
167
|
+
XH_BUFFER_WRITE_CHAR(buf, '>')
|
168
|
+
|
169
|
+
if (writer->indent) {
|
170
|
+
XH_BUFFER_WRITE_CHAR(buf, '\n')
|
171
|
+
}
|
172
|
+
}
|
173
|
+
|
174
|
+
XH_INLINE void
|
175
|
+
xh_xml_write_end_node(xh_writer_t *writer, xh_char_t *name, size_t name_len)
|
176
|
+
{
|
177
|
+
size_t indent_len;
|
178
|
+
xh_ruby_buffer_t *buf;
|
179
|
+
|
180
|
+
buf = &writer->main_buf;
|
181
|
+
|
182
|
+
if (writer->indent) {
|
183
|
+
indent_len = --writer->indent_count * writer->indent;
|
184
|
+
if (indent_len > sizeof(indent_string)) {
|
185
|
+
indent_len = sizeof(indent_string);
|
186
|
+
}
|
187
|
+
|
188
|
+
/* "</" + "_" + ">" + "\n" */
|
189
|
+
XH_WRITER_RESIZE_BUFFER(writer, buf, indent_len + name_len + 5)
|
190
|
+
|
191
|
+
XH_BUFFER_WRITE_LONG_STRING(buf, indent_string, indent_len);
|
192
|
+
}
|
193
|
+
else {
|
194
|
+
/* "</" + "_" + ">" + "\n" */
|
195
|
+
XH_WRITER_RESIZE_BUFFER(writer, buf, name_len + 5)
|
196
|
+
}
|
197
|
+
|
198
|
+
XH_BUFFER_WRITE_CHAR2(buf, "</")
|
199
|
+
|
200
|
+
if (name[0] >= '0' && name[0] <= '9') {
|
201
|
+
XH_BUFFER_WRITE_CHAR(buf, '_')
|
202
|
+
}
|
203
|
+
|
204
|
+
XH_BUFFER_WRITE_LONG_STRING(buf, name, name_len)
|
205
|
+
|
206
|
+
XH_BUFFER_WRITE_CHAR(buf, '>')
|
207
|
+
|
208
|
+
if (writer->indent) {
|
209
|
+
XH_BUFFER_WRITE_CHAR(buf, '\n')
|
210
|
+
}
|
211
|
+
}
|
212
|
+
|
213
|
+
XH_INLINE void
|
214
|
+
xh_xml_write_content(xh_writer_t *writer, VALUE value)
|
215
|
+
{
|
216
|
+
size_t indent_len;
|
217
|
+
xh_ruby_buffer_t *buf;
|
218
|
+
xh_char_t *content;
|
219
|
+
size_t content_len;
|
220
|
+
|
221
|
+
buf = &writer->main_buf;
|
222
|
+
value = rb_obj_as_string(value);
|
223
|
+
content = XH_CHAR_CAST RSTRING_PTR(value);
|
224
|
+
content_len = RSTRING_LEN(value);
|
225
|
+
|
226
|
+
if (writer->trim) {
|
227
|
+
content = xh_str_trim(content, &content_len);
|
228
|
+
}
|
229
|
+
|
230
|
+
if (writer->indent) {
|
231
|
+
indent_len = writer->indent_count * writer->indent;
|
232
|
+
if (indent_len > sizeof(indent_string)) {
|
233
|
+
indent_len = sizeof(indent_string);
|
234
|
+
}
|
235
|
+
|
236
|
+
XH_WRITER_RESIZE_BUFFER(writer, buf, indent_len + content_len * 5)
|
237
|
+
|
238
|
+
XH_BUFFER_WRITE_LONG_STRING(buf, indent_string, indent_len);
|
239
|
+
}
|
240
|
+
else {
|
241
|
+
XH_WRITER_RESIZE_BUFFER(writer, buf, content_len * 5)
|
242
|
+
}
|
243
|
+
|
244
|
+
XH_BUFFER_WRITE_ESCAPE_STRING(buf, content, content_len);
|
245
|
+
|
246
|
+
if (writer->indent) {
|
247
|
+
XH_BUFFER_WRITE_CHAR(buf, '\n')
|
248
|
+
}
|
249
|
+
}
|
250
|
+
|
251
|
+
XH_INLINE void
|
252
|
+
xh_xml_write_comment(xh_writer_t *writer, VALUE value)
|
253
|
+
{
|
254
|
+
size_t indent_len;
|
255
|
+
xh_ruby_buffer_t *buf;
|
256
|
+
xh_char_t *content;
|
257
|
+
size_t content_len;
|
258
|
+
|
259
|
+
buf = &writer->main_buf;
|
260
|
+
|
261
|
+
if (value == Qnil) {
|
262
|
+
content = XH_EMPTY_STRING;
|
263
|
+
content_len = 0;
|
264
|
+
}
|
265
|
+
else {
|
266
|
+
value = rb_obj_as_string(value);
|
267
|
+
content = XH_CHAR_CAST RSTRING_PTR(value);
|
268
|
+
content_len = RSTRING_LEN(value);
|
269
|
+
}
|
270
|
+
|
271
|
+
if (writer->trim && content_len) {
|
272
|
+
content = xh_str_trim(content, &content_len);
|
273
|
+
}
|
274
|
+
|
275
|
+
if (writer->indent) {
|
276
|
+
indent_len = writer->indent_count * writer->indent;
|
277
|
+
if (indent_len > sizeof(indent_string)) {
|
278
|
+
indent_len = sizeof(indent_string);
|
279
|
+
}
|
280
|
+
|
281
|
+
/* "<!--" + "-->" */
|
282
|
+
XH_WRITER_RESIZE_BUFFER(writer, buf, indent_len + content_len + 7)
|
283
|
+
|
284
|
+
XH_BUFFER_WRITE_LONG_STRING(buf, indent_string, indent_len);
|
285
|
+
}
|
286
|
+
else {
|
287
|
+
/* "<!--" + "-->" */
|
288
|
+
XH_WRITER_RESIZE_BUFFER(writer, buf, content_len + 7)
|
289
|
+
}
|
290
|
+
|
291
|
+
XH_BUFFER_WRITE_CHAR4(buf, "<!--")
|
292
|
+
XH_BUFFER_WRITE_LONG_STRING(buf, content, content_len);
|
293
|
+
XH_BUFFER_WRITE_CHAR3(buf, "-->")
|
294
|
+
|
295
|
+
if (writer->indent) {
|
296
|
+
XH_BUFFER_WRITE_CHAR(buf, '\n')
|
297
|
+
}
|
298
|
+
}
|
299
|
+
|
300
|
+
XH_INLINE void
|
301
|
+
xh_xml_write_cdata(xh_writer_t *writer, VALUE value)
|
302
|
+
{
|
303
|
+
size_t indent_len;
|
304
|
+
xh_ruby_buffer_t *buf;
|
305
|
+
xh_char_t *content;
|
306
|
+
size_t content_len;
|
307
|
+
|
308
|
+
buf = &writer->main_buf;
|
309
|
+
|
310
|
+
if (value == Qnil) {
|
311
|
+
content = XH_EMPTY_STRING;
|
312
|
+
content_len = 0;
|
313
|
+
}
|
314
|
+
else {
|
315
|
+
value = rb_obj_as_string(value);
|
316
|
+
content = XH_CHAR_CAST RSTRING_PTR(value);
|
317
|
+
content_len = RSTRING_LEN(value);
|
318
|
+
}
|
319
|
+
|
320
|
+
if (writer->trim && content_len) {
|
321
|
+
content = xh_str_trim(content, &content_len);
|
322
|
+
}
|
323
|
+
|
324
|
+
if (writer->indent) {
|
325
|
+
indent_len = writer->indent_count * writer->indent;
|
326
|
+
if (indent_len > sizeof(indent_string)) {
|
327
|
+
indent_len = sizeof(indent_string);
|
328
|
+
}
|
329
|
+
|
330
|
+
/* "<![CDATA[" + "]]>" */
|
331
|
+
XH_WRITER_RESIZE_BUFFER(writer, buf, indent_len + content_len + 12)
|
332
|
+
|
333
|
+
XH_BUFFER_WRITE_LONG_STRING(buf, indent_string, indent_len);
|
334
|
+
}
|
335
|
+
else {
|
336
|
+
/* "<![CDATA[" + "]]>" */
|
337
|
+
XH_WRITER_RESIZE_BUFFER(writer, buf, content_len + 12)
|
338
|
+
}
|
339
|
+
|
340
|
+
XH_BUFFER_WRITE_CHAR9(buf, "<![CDATA[")
|
341
|
+
XH_BUFFER_WRITE_LONG_STRING(buf, content, content_len);
|
342
|
+
XH_BUFFER_WRITE_CHAR3(buf, "]]>")
|
343
|
+
|
344
|
+
if (writer->indent) {
|
345
|
+
XH_BUFFER_WRITE_CHAR(buf, '\n')
|
346
|
+
}
|
347
|
+
}
|
348
|
+
|
349
|
+
XH_INLINE void
|
350
|
+
xh_xml_write_start_tag(xh_writer_t *writer, xh_char_t *name, size_t name_len)
|
351
|
+
{
|
352
|
+
size_t indent_len;
|
353
|
+
xh_ruby_buffer_t *buf;
|
354
|
+
|
355
|
+
buf = &writer->main_buf;
|
356
|
+
|
357
|
+
if (writer->indent) {
|
358
|
+
indent_len = writer->indent_count * writer->indent;
|
359
|
+
if (indent_len > sizeof(indent_string)) {
|
360
|
+
indent_len = sizeof(indent_string);
|
361
|
+
}
|
362
|
+
|
363
|
+
/* "<" + "_" */
|
364
|
+
XH_WRITER_RESIZE_BUFFER(writer, buf, indent_len + name_len + 2)
|
365
|
+
|
366
|
+
XH_BUFFER_WRITE_LONG_STRING(buf, indent_string, indent_len);
|
367
|
+
}
|
368
|
+
else {
|
369
|
+
/* "<" + "_" */
|
370
|
+
XH_WRITER_RESIZE_BUFFER(writer, buf, name_len + 2)
|
371
|
+
}
|
372
|
+
|
373
|
+
XH_BUFFER_WRITE_CHAR(buf, '<')
|
374
|
+
|
375
|
+
if (name[0] >= '0' && name[0] <= '9') {
|
376
|
+
XH_BUFFER_WRITE_CHAR(buf, '_')
|
377
|
+
}
|
378
|
+
|
379
|
+
XH_BUFFER_WRITE_LONG_STRING(buf, name, name_len)
|
380
|
+
}
|
381
|
+
|
382
|
+
XH_INLINE void
|
383
|
+
xh_xml_write_end_tag(xh_writer_t *writer)
|
384
|
+
{
|
385
|
+
xh_ruby_buffer_t *buf;
|
386
|
+
|
387
|
+
buf = &writer->main_buf;
|
388
|
+
|
389
|
+
XH_WRITER_RESIZE_BUFFER(writer, buf, 2)
|
390
|
+
|
391
|
+
if (writer->indent) {
|
392
|
+
XH_BUFFER_WRITE_CHAR2(buf, ">\n");
|
393
|
+
writer->indent_count++;
|
394
|
+
}
|
395
|
+
else {
|
396
|
+
XH_BUFFER_WRITE_CHAR(buf, '>')
|
397
|
+
}
|
398
|
+
}
|
399
|
+
|
400
|
+
XH_INLINE void
|
401
|
+
xh_xml_write_closed_end_tag(xh_writer_t *writer)
|
402
|
+
{
|
403
|
+
xh_ruby_buffer_t *buf;
|
404
|
+
|
405
|
+
buf = &writer->main_buf;
|
406
|
+
|
407
|
+
XH_WRITER_RESIZE_BUFFER(writer, buf, 3)
|
408
|
+
|
409
|
+
if (writer->indent) {
|
410
|
+
XH_BUFFER_WRITE_CHAR3(buf, "/>\n");
|
411
|
+
}
|
412
|
+
else {
|
413
|
+
XH_BUFFER_WRITE_CHAR2(buf, "/>");
|
414
|
+
}
|
415
|
+
}
|
416
|
+
|
417
|
+
XH_INLINE void
|
418
|
+
xh_xml_write_attribute(xh_writer_t *writer, xh_char_t *name, size_t name_len, VALUE value)
|
419
|
+
{
|
420
|
+
xh_ruby_buffer_t *buf;
|
421
|
+
xh_char_t *content;
|
422
|
+
size_t content_len;
|
423
|
+
|
424
|
+
buf = &writer->main_buf;
|
425
|
+
|
426
|
+
if (value == Qnil) {
|
427
|
+
content = XH_EMPTY_STRING;
|
428
|
+
content_len = 0;
|
429
|
+
}
|
430
|
+
else {
|
431
|
+
value = rb_obj_as_string(value);
|
432
|
+
content = XH_CHAR_CAST RSTRING_PTR(value);
|
433
|
+
content_len = RSTRING_LEN(value);
|
434
|
+
}
|
435
|
+
|
436
|
+
/* ' =""' */
|
437
|
+
XH_WRITER_RESIZE_BUFFER(writer, buf, name_len + content_len * 6 + 4)
|
438
|
+
|
439
|
+
XH_BUFFER_WRITE_CHAR(buf, ' ')
|
440
|
+
|
441
|
+
XH_BUFFER_WRITE_LONG_STRING(buf, name, name_len)
|
442
|
+
|
443
|
+
if (content_len == 0) {
|
444
|
+
XH_BUFFER_WRITE_CHAR3(buf, "=\"\"");
|
445
|
+
}
|
446
|
+
else {
|
447
|
+
XH_BUFFER_WRITE_CHAR2(buf, "=\"");
|
448
|
+
XH_BUFFER_WRITE_ESCAPE_ATTR(buf, content, content_len);
|
449
|
+
XH_BUFFER_WRITE_CHAR(buf, '"');
|
450
|
+
}
|
451
|
+
}
|
452
|
+
|
453
|
+
#endif /* _XH_XML_H_ */
|