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.
@@ -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
+ }