fast-xml 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,56 @@
1
+ #ifndef _XH_ENCODER_H_
2
+ #define _XH_ENCODER_H_
3
+
4
+ #include "xh_config.h"
5
+ #include "xh_core.h"
6
+
7
+ #ifdef XH_HAVE_ENCODER
8
+
9
+ #ifdef XH_HAVE_ICONV
10
+ #if defined(__MINGW32__) || defined(_WIN32)
11
+ #define LIBICONV_STATIC
12
+ #endif
13
+ #include <iconv.h>
14
+ #endif
15
+ #ifdef XH_HAVE_ICU
16
+ #include <unicode/utypes.h>
17
+ #include <unicode/ucnv.h>
18
+ #endif
19
+
20
+ typedef enum {
21
+ XH_ENC_ICONV,
22
+ XH_ENC_ICU
23
+ } xh_encoder_type_t;
24
+
25
+ typedef enum {
26
+ XH_ENC_OK = 0,
27
+ XH_ENC_BUFFER_OVERFLOW,
28
+ XH_ENC_TRUNCATED_CHAR_FOUND
29
+ } xh_encoder_state_t;
30
+
31
+ typedef struct _xh_encoder_t xh_encoder_t;
32
+ struct _xh_encoder_t {
33
+ xh_encoder_type_t type;
34
+ xh_encoder_state_t state;
35
+ xh_char_t fromcode[XH_PARAM_LEN];
36
+ xh_char_t tocode[XH_PARAM_LEN];
37
+ #ifdef XH_HAVE_ICONV
38
+ iconv_t iconv;
39
+ #endif
40
+ #ifdef XH_HAVE_ICU
41
+ UConverter *uconv_from;
42
+ UConverter *uconv_to;
43
+ UChar pivotBuffer[1024];
44
+ const UChar *pivotLimit;
45
+ UChar *pivotSource, *pivotTarget, *pivotStart;
46
+ #endif
47
+ };
48
+
49
+ void xh_encoder_destroy(xh_encoder_t *encoder);
50
+ xh_encoder_t *xh_encoder_create(xh_char_t *tocode, xh_char_t *fromcode);
51
+ void xh_encoder_encode_ruby_buffer(xh_encoder_t *encoder, xh_ruby_buffer_t *main_buf, xh_ruby_buffer_t *enc_buf);
52
+ void xh_encoder_encode_string(xh_encoder_t *encoder, xh_char_t **src, size_t *src_left, xh_char_t **dst, size_t *dst_left);
53
+
54
+ #endif /* XH_HAVE_ENCODER */
55
+
56
+ #endif /* _XH_ENCODER_H_ */
@@ -0,0 +1,62 @@
1
+ #include "xh_config.h"
2
+ #include "xh_core.h"
3
+
4
+ static VALUE
5
+ xh_h2x_exec(VALUE arg)
6
+ {
7
+ xh_h2x_ctx_t *ctx = (xh_h2x_ctx_t *) arg;
8
+
9
+ xh_writer_init(&ctx->writer, ctx->opts.encoding, ctx->opts.output, ctx->opts.buf_size, ctx->opts.indent, ctx->opts.trim);
10
+
11
+ if (ctx->opts.xml_decl) {
12
+ xh_xml_write_xml_declaration(&ctx->writer, ctx->opts.version, ctx->opts.encoding);
13
+ }
14
+
15
+ switch (ctx->opts.method) {
16
+ case XH_METHOD_NATIVE:
17
+ if (ctx->opts.use_attr) {
18
+ xh_h2x_native_attr(ctx, ctx->opts.root, xh_strlen(ctx->opts.root), ctx->hash, XH_H2X_F_COMPLEX);
19
+ }
20
+ else {
21
+ xh_h2x_native(ctx, ctx->opts.root, xh_strlen(ctx->opts.root), ctx->hash);
22
+ }
23
+ break;
24
+ case XH_METHOD_LX:
25
+ //xh_h2x_lx(ctx, ctx->hash, NULL, 0, XH_H2X_F_NONE);
26
+ break;
27
+ default:
28
+ rb_raise(rb_eArgError, "Invalid method");
29
+ }
30
+
31
+ return Qnil;
32
+ }
33
+
34
+ VALUE
35
+ xh_h2x(xh_h2x_ctx_t *ctx)
36
+ {
37
+ VALUE result;
38
+ int state;
39
+
40
+ result = rb_protect(xh_h2x_exec, (VALUE) ctx, &state);
41
+
42
+ if (state) {
43
+ result = xh_writer_flush(&ctx->writer);
44
+ xh_writer_destroy(&ctx->writer);
45
+ rb_exc_raise(rb_errinfo());
46
+ }
47
+
48
+ result = xh_writer_flush(&ctx->writer);
49
+ if (result != Qnil && ctx->opts.utf8) {
50
+ #ifdef XH_HAVE_ENCODER
51
+ if (ctx->writer.encoder == NULL) {
52
+ XH_FORCE_UTF8(result);
53
+ }
54
+ #else
55
+ XH_FORCE_UTF8(result);
56
+ #endif
57
+ }
58
+
59
+ xh_writer_destroy(&ctx->writer);
60
+
61
+ return result;
62
+ }
@@ -0,0 +1,93 @@
1
+ #ifndef _XH_H2X_H_
2
+ #define _XH_H2X_H_
3
+
4
+ #include "xh_config.h"
5
+ #include "xh_core.h"
6
+
7
+ #define XH_H2X_F_NONE 0
8
+ #define XH_H2X_F_SIMPLE 1
9
+ #define XH_H2X_F_COMPLEX 2
10
+ #define XH_H2X_F_CONTENT 4
11
+ #define XH_H2X_F_ATTR_ONLY 8
12
+
13
+ #define XH_H2X_T_SCALAR 1
14
+ #define XH_H2X_T_HASH 2
15
+ #define XH_H2X_T_ARRAY 4
16
+ //#define XH_H2X_T_BLESSED 8
17
+ #define XH_H2X_T_RAW 16
18
+ #define XH_H2X_T_NOT_NULL (XH_H2X_T_SCALAR | XH_H2X_T_ARRAY | XH_H2X_T_HASH)
19
+
20
+ #define XH_H2X_STASH_SIZE 16
21
+
22
+ typedef struct {
23
+ xh_opts_t opts;
24
+ xh_int_t depth;
25
+ xh_writer_t writer;
26
+ xh_stack_t stash;
27
+ VALUE hash;
28
+ } xh_h2x_ctx_t;
29
+
30
+ XH_INLINE VALUE
31
+ xh_h2x_resolve_value(xh_h2x_ctx_t *ctx, VALUE value, xh_uint_t *type)
32
+ {
33
+ *type = 0;
34
+
35
+ while (RB_TYPE_P(value, RUBY_T_DATA) || RB_TYPE_P(value, RUBY_T_OBJECT)) {
36
+ if (rb_obj_is_kind_of(value, rb_cProc) || rb_obj_is_kind_of(value, rb_cMethod)) {
37
+ value = rb_funcall(value, rb_intern("call"), 0);
38
+ }
39
+ else {
40
+ break;
41
+ }
42
+
43
+ if (++ctx->depth > ctx->opts.max_depth)
44
+ rb_raise(xh_parse_error_class, "Maximum recursion depth exceeded");
45
+ }
46
+
47
+ if (rb_cHash == rb_obj_class(value)) {
48
+ *type |= XH_H2X_T_HASH;
49
+ }
50
+ else if (rb_cArray == rb_obj_class(value)) {
51
+ *type |= XH_H2X_T_ARRAY;
52
+ }
53
+ else if (!RTEST(value)) {
54
+ *type = 0;
55
+ }
56
+ else {
57
+ *type |= XH_H2X_T_SCALAR;
58
+ }
59
+
60
+ /*
61
+ if (SvOBJECT(value))
62
+ *type |= XH_H2X_T_BLESSED;
63
+ */
64
+ return value;
65
+ }
66
+
67
+ VALUE xh_h2x(xh_h2x_ctx_t *ctx);
68
+ void xh_h2x_native(xh_h2x_ctx_t *ctx, xh_char_t *key, size_t key_len, VALUE value);
69
+ xh_int_t xh_h2x_native_attr(xh_h2x_ctx_t *ctx, xh_char_t *key, size_t key_len, VALUE value, xh_int_t flag);
70
+ /*
71
+ void xh_h2x_lx(xh_h2x_ctx_t *ctx, SV *value, xh_char_t *key, I32 key_len, xh_int_t flag);
72
+ */
73
+
74
+ XH_INLINE void
75
+ xh_h2x_destroy_ctx(xh_h2x_ctx_t *ctx)
76
+ {
77
+ xh_destroy_opts(&ctx->opts);
78
+ }
79
+
80
+ XH_INLINE void
81
+ xh_h2x_init_ctx(xh_h2x_ctx_t *ctx, xh_int_t argc, VALUE *argv)
82
+ {
83
+ xh_opts_t *opts = NULL;
84
+ xh_int_t nparam = 0;
85
+
86
+ memset(ctx, 0, sizeof(xh_h2x_ctx_t));
87
+
88
+ //opts = (xh_opts_t *) xh_get_obj_param(&nparam, ax, items, "XML::Hash::XS");
89
+ ctx->hash = xh_get_hash_param(&nparam, argc, argv);
90
+ xh_merge_opts(&ctx->opts, opts, &nparam, argc, argv);
91
+ }
92
+
93
+ #endif /* _XH_H2X_H_ */
@@ -0,0 +1,89 @@
1
+ #include "xh_config.h"
2
+ #include "xh_core.h"
3
+
4
+ static int
5
+ xh_h2x_native_hash_iter(VALUE key, VALUE value, VALUE arg)
6
+ {
7
+ xh_h2x_ctx_t *ctx = (xh_h2x_ctx_t *) arg;
8
+
9
+ if (SYMBOL_P(key)) {
10
+ key = rb_sym2str(key);
11
+ }
12
+ else {
13
+ key = rb_obj_as_string(key);
14
+ }
15
+
16
+ xh_h2x_native(ctx, XH_CHAR_CAST RSTRING_PTR(key), RSTRING_LEN(key), value);
17
+
18
+ return ST_CONTINUE;
19
+ }
20
+
21
+ static VALUE
22
+ xh_h2x_native_call_next(VALUE obj)
23
+ {
24
+ return rb_funcall(obj, xh_id_next, 0);
25
+ }
26
+
27
+ static VALUE
28
+ xh_h2x_native_call_stop(VALUE obj)
29
+ {
30
+ return Qnil;
31
+ }
32
+
33
+ void
34
+ xh_h2x_native(xh_h2x_ctx_t *ctx, xh_char_t *key, size_t key_len, VALUE value)
35
+ {
36
+ xh_uint_t type;
37
+ size_t i, len;
38
+ VALUE next_value;
39
+ xh_sort_hash_t sorted_hash;
40
+
41
+ value = xh_h2x_resolve_value(ctx, value, &type);
42
+
43
+ if (rb_obj_is_kind_of(value, rb_cEnumerator)) {
44
+ while (1) {
45
+ next_value = rb_rescue2(xh_h2x_native_call_next, value, xh_h2x_native_call_stop, value, rb_eStopIteration, (VALUE) 0);
46
+ if (next_value == Qnil) break;
47
+ xh_h2x_native(ctx, key, key_len, next_value);
48
+ }
49
+ goto FINISH;
50
+ }
51
+
52
+ if (type & XH_H2X_T_SCALAR) {
53
+ xh_xml_write_node(&ctx->writer, key, key_len, value, type & XH_H2X_T_RAW);
54
+ }
55
+ else if (type & XH_H2X_T_HASH) {
56
+ len = RHASH_SIZE(value);
57
+ if (len == 0) goto ADD_EMPTY_NODE;
58
+
59
+ xh_xml_write_start_node(&ctx->writer, key, key_len);
60
+
61
+ if (len > 1 && ctx->opts.canonical) {
62
+ sorted_hash.elts = alloca(sizeof(xh_sort_hash_elt_t) * len);
63
+
64
+ xh_sort_hash(&sorted_hash, value);
65
+
66
+ for (i = 0; i < sorted_hash.nelts; i++) {
67
+ xh_h2x_native(ctx, sorted_hash.elts[i].key, sorted_hash.elts[i].key_len, sorted_hash.elts[i].value);
68
+ }
69
+ }
70
+ else {
71
+ rb_hash_foreach(value, xh_h2x_native_hash_iter, (VALUE) ctx);
72
+ }
73
+
74
+ xh_xml_write_end_node(&ctx->writer, key, key_len);
75
+ }
76
+ else if (type & XH_H2X_T_ARRAY) {
77
+ len = RARRAY_LEN(value);
78
+ for (i = 0; i < len; i++) {
79
+ xh_h2x_native(ctx, key, key_len, RARRAY_AREF(value, i));
80
+ }
81
+ }
82
+ else {
83
+ ADD_EMPTY_NODE:
84
+ xh_xml_write_empty_node(&ctx->writer, key, key_len);
85
+ }
86
+
87
+ FINISH:
88
+ ctx->depth--;
89
+ }
@@ -0,0 +1,161 @@
1
+ #include "xh_config.h"
2
+ #include "xh_core.h"
3
+
4
+ typedef struct {
5
+ xh_h2x_ctx_t *ctx;
6
+ xh_int_t flag;
7
+ size_t *done;
8
+ } xh_iter_ctx_t;
9
+
10
+ static int
11
+ xh_h2x_native_attr_hash_iter(VALUE key, VALUE value, VALUE arg)
12
+ {
13
+ xh_iter_ctx_t *iter_ctx = (xh_iter_ctx_t *) arg;
14
+
15
+ if (SYMBOL_P(key)) {
16
+ key = rb_sym2str(key);
17
+ }
18
+ else {
19
+ key = rb_obj_as_string(key);
20
+ }
21
+
22
+ *iter_ctx->done += xh_h2x_native_attr(iter_ctx->ctx, XH_CHAR_CAST RSTRING_PTR(key), RSTRING_LEN(key), value, iter_ctx->flag);
23
+
24
+ return ST_CONTINUE;
25
+ }
26
+
27
+ static VALUE
28
+ xh_h2x_native_attr_call_next(VALUE obj)
29
+ {
30
+ return rb_funcall(obj, xh_id_next, 0);
31
+ }
32
+
33
+ static VALUE
34
+ xh_h2x_native_attr_call_stop(VALUE obj)
35
+ {
36
+ return Qnil;
37
+ }
38
+
39
+ xh_int_t
40
+ xh_h2x_native_attr(xh_h2x_ctx_t *ctx, xh_char_t *key, size_t key_len, VALUE value, xh_int_t flag)
41
+ {
42
+ xh_uint_t type;
43
+ size_t len, i, nattrs, done;
44
+ xh_sort_hash_t sorted_hash;
45
+ VALUE next_value;
46
+ xh_iter_ctx_t iter_ctx;
47
+
48
+ nattrs = 0;
49
+
50
+ if (ctx->opts.content[0] != '\0' && xh_strcmp(key, ctx->opts.content) == 0)
51
+ flag = flag | XH_H2X_F_CONTENT;
52
+
53
+ value = xh_h2x_resolve_value(ctx, value, &type);
54
+
55
+ if (rb_obj_is_kind_of(value, rb_cEnumerator)) {
56
+ if (!(flag & XH_H2X_F_COMPLEX)) goto FINISH;
57
+
58
+ while (1) {
59
+ next_value = rb_rescue2(xh_h2x_native_attr_call_next, value, xh_h2x_native_attr_call_stop, value, rb_eStopIteration, (VALUE) 0);
60
+ if (next_value == Qnil) break;
61
+ (void) xh_h2x_native_attr(ctx, key, key_len, next_value, XH_H2X_F_SIMPLE | XH_H2X_F_COMPLEX);
62
+ }
63
+
64
+ nattrs++;
65
+
66
+ goto FINISH;
67
+ }
68
+
69
+ if (type & XH_H2X_T_SCALAR) {
70
+ if (flag & XH_H2X_F_COMPLEX && (flag & XH_H2X_F_SIMPLE || type & XH_H2X_T_RAW)) {
71
+ xh_xml_write_node(&ctx->writer, key, key_len, value, type & XH_H2X_T_RAW);
72
+ }
73
+ else if (flag & XH_H2X_F_COMPLEX && flag & XH_H2X_F_CONTENT) {
74
+ xh_xml_write_content(&ctx->writer, value);
75
+ }
76
+ else if (flag & XH_H2X_F_SIMPLE && !(flag & XH_H2X_F_CONTENT) && !(type & XH_H2X_T_RAW)) {
77
+ xh_xml_write_attribute(&ctx->writer, key, key_len, value);
78
+ nattrs++;
79
+ }
80
+ }
81
+ else if (type & XH_H2X_T_HASH) {
82
+ if (!(flag & XH_H2X_F_COMPLEX)) goto FINISH;
83
+
84
+ len = RHASH_SIZE(value);
85
+ if (len == 0) {
86
+ xh_xml_write_empty_node(&ctx->writer, key, key_len);
87
+ goto FINISH;
88
+ }
89
+
90
+ xh_xml_write_start_tag(&ctx->writer, key, key_len);
91
+
92
+ done = 0;
93
+ iter_ctx.ctx = ctx;
94
+ iter_ctx.done = &done;
95
+
96
+ if (len > 1 && ctx->opts.canonical) {
97
+ sorted_hash.elts = alloca(sizeof(xh_sort_hash_elt_t) * len);
98
+
99
+ xh_sort_hash(&sorted_hash, value);
100
+
101
+ for (i = 0; i < sorted_hash.nelts; i++) {
102
+ done += xh_h2x_native_attr(ctx, sorted_hash.elts[i].key, sorted_hash.elts[i].key_len, sorted_hash.elts[i].value, XH_H2X_F_SIMPLE);
103
+ }
104
+
105
+ if (done == len) {
106
+ xh_xml_write_closed_end_tag(&ctx->writer);
107
+ }
108
+ else {
109
+ xh_xml_write_end_tag(&ctx->writer);
110
+
111
+ for (i = 0; i < sorted_hash.nelts; i++) {
112
+ (void) xh_h2x_native_attr(ctx, sorted_hash.elts[i].key, sorted_hash.elts[i].key_len, sorted_hash.elts[i].value, XH_H2X_F_COMPLEX);
113
+ }
114
+
115
+ xh_xml_write_end_node(&ctx->writer, key, key_len);
116
+ }
117
+ }
118
+ else {
119
+ iter_ctx.flag = XH_H2X_F_SIMPLE;
120
+ rb_hash_foreach(value, xh_h2x_native_attr_hash_iter, (VALUE) &iter_ctx);
121
+
122
+ if (done == len) {
123
+ xh_xml_write_closed_end_tag(&ctx->writer);
124
+ }
125
+ else {
126
+ xh_xml_write_end_tag(&ctx->writer);
127
+
128
+ iter_ctx.flag = XH_H2X_F_COMPLEX;
129
+ rb_hash_foreach(value, xh_h2x_native_attr_hash_iter, (VALUE) &iter_ctx);
130
+
131
+ xh_xml_write_end_node(&ctx->writer, key, key_len);
132
+ }
133
+ }
134
+
135
+ nattrs++;
136
+ }
137
+ else if (type & XH_H2X_T_ARRAY) {
138
+ if (!(flag & XH_H2X_F_COMPLEX)) goto FINISH;
139
+
140
+ len = RARRAY_LEN(value);
141
+ for (i = 0; i < len; i++) {
142
+ (void) xh_h2x_native_attr(ctx, key, key_len, RARRAY_AREF(value, i), XH_H2X_F_SIMPLE | XH_H2X_F_COMPLEX);
143
+ }
144
+
145
+ nattrs++;
146
+ }
147
+ else {
148
+ if (flag & XH_H2X_F_SIMPLE && flag & XH_H2X_F_COMPLEX) {
149
+ xh_xml_write_empty_node(&ctx->writer, key, key_len);
150
+ }
151
+ else if (flag & XH_H2X_F_SIMPLE && !(flag & XH_H2X_F_CONTENT)) {
152
+ xh_xml_write_attribute(&ctx->writer, key, key_len, Qnil);
153
+ nattrs++;
154
+ }
155
+ }
156
+
157
+ FINISH:
158
+ ctx->depth--;
159
+
160
+ return nattrs;
161
+ }