File Coverage

src/xh_h2x_native_attr.c
Criterion Covered Total %
statement 60 65 92.3
branch 56 72 77.7
condition n/a
subroutine n/a
pod n/a
total 116 137 84.6


line stmt bran cond sub pod time code
1             #include "xh_config.h"
2             #include "xh_core.h"
3              
4             xh_int_t
5 57           xh_h2x_native_attr(xh_h2x_ctx_t *ctx, xh_char_t *key, I32 key_len, SV *value, xh_int_t flag)
6             {
7             xh_uint_t type;
8             size_t len, i, nattrs, done;
9             xh_sort_hash_t *sorted_hash;
10             SV *item_value;
11             xh_char_t *item;
12             I32 item_len;
13             GV *method;
14              
15 57           nattrs = 0;
16              
17 57 100         if (ctx->opts.content[0] != '\0' && xh_strcmp(key, ctx->opts.content) == 0)
    100          
18 8           flag = flag | XH_H2X_F_CONTENT;
19              
20 57           value = xh_h2x_resolve_value(ctx, value, &type);
21              
22 57 100         if (type & XH_H2X_T_BLESSED && (method = gv_fetchmethod_autoload(SvSTASH(value), "iternext", 0)) != NULL) {
    50          
23 2 100         if (!(flag & XH_H2X_F_COMPLEX)) goto FINISH;
24              
25             while (1) {
26 5           item_value = xh_h2x_call_method(value, method);
27 5 100         if (!SvOK(item_value)) break;
    50          
    50          
28 4           (void) xh_h2x_native_attr(ctx, key, key_len, item_value, XH_H2X_F_SIMPLE | XH_H2X_F_COMPLEX);
29 4           SvREFCNT_dec(item_value);
30 4           }
31 1           nattrs++;
32              
33 1           goto FINISH;
34             }
35              
36 55 100         if (type & XH_H2X_T_SCALAR) {
37 30 100         if (flag & XH_H2X_F_COMPLEX && (flag & XH_H2X_F_SIMPLE || type & XH_H2X_T_RAW)) {
    100          
    50          
38 7           xh_xml_write_node(&ctx->writer, key, key_len, value, type & XH_H2X_T_RAW);
39             }
40 23 100         else if (flag & XH_H2X_F_COMPLEX && flag & XH_H2X_F_CONTENT) {
    100          
41 4           xh_xml_write_content(&ctx->writer, value);
42             }
43 19 100         else if (flag & XH_H2X_F_SIMPLE && !(flag & XH_H2X_F_CONTENT) && !(type & XH_H2X_T_RAW)) {
    100          
    50          
44 11           xh_xml_write_attribute(&ctx->writer, key, key_len, value);
45 30           nattrs++;
46             }
47             }
48 25 100         else if (type & XH_H2X_T_HASH) {
49 15 100         if (!(flag & XH_H2X_F_COMPLEX)) goto FINISH;
50              
51 13 50         len = HvUSEDKEYS((SV *) value);
52 13 100         if (len == 0) {
53 1           xh_xml_write_empty_node(&ctx->writer, key, key_len);
54 1           goto FINISH;
55             }
56              
57 12           xh_xml_write_start_tag(&ctx->writer, key, key_len);
58              
59 12           done = 0;
60              
61 12 100         if (len > 1 && ctx->opts.canonical) {
    50          
62 6           sorted_hash = xh_sort_hash((HV *) value, len);
63              
64 23 100         for (i = 0; i < len; i++) {
65 17           done += xh_h2x_native_attr(ctx, sorted_hash[i].key, sorted_hash[i].key_len, sorted_hash[i].value, XH_H2X_F_SIMPLE);
66             }
67              
68 6 100         if (done == len) {
69 1           xh_xml_write_closed_end_tag(&ctx->writer);
70             }
71             else {
72 5           xh_xml_write_end_tag(&ctx->writer);
73              
74 20 100         for (i = 0; i < len; i++) {
75 15           (void) xh_h2x_native_attr(ctx, sorted_hash[i].key, sorted_hash[i].key_len, sorted_hash[i].value, XH_H2X_F_COMPLEX);
76             }
77              
78 5           xh_xml_write_end_node(&ctx->writer, key, key_len);
79             }
80              
81 6           free(sorted_hash);
82             }
83             else {
84 6           hv_iterinit((HV *) value);
85 12 100         while ((item_value = hv_iternextsv((HV *) value, (char **) &item, &item_len))) {
86 6           done += xh_h2x_native_attr(ctx, item, item_len,item_value, XH_H2X_F_SIMPLE);
87             }
88              
89 6 100         if (done == len) {
90 5           xh_xml_write_closed_end_tag(&ctx->writer);
91             }
92             else {
93 1           xh_xml_write_end_tag(&ctx->writer);
94              
95 1           hv_iterinit((HV *) value);
96 2 100         while ((item_value = hv_iternextsv((HV *) value, (char **) &item, &item_len))) {
97 1           (void) xh_h2x_native_attr(ctx, item, item_len,item_value, XH_H2X_F_COMPLEX);
98             }
99              
100 1           xh_xml_write_end_node(&ctx->writer, key, key_len);
101             }
102             }
103              
104 12           nattrs++;
105             }
106 10 50         else if (type & XH_H2X_T_ARRAY) {
107 10 100         if (!(flag & XH_H2X_F_COMPLEX)) goto FINISH;
108              
109 5           len = av_len((AV *) value) + 1;
110 14 100         for (i = 0; i < len; i++) {
111 9           (void) xh_h2x_native_attr(ctx, key, key_len, *av_fetch((AV *) value, i, 0), XH_H2X_F_SIMPLE | XH_H2X_F_COMPLEX);
112             }
113              
114 5           nattrs++;
115             }
116             else {
117 0 0         if (flag & XH_H2X_F_SIMPLE && flag & XH_H2X_F_COMPLEX) {
    0          
118 0           xh_xml_write_empty_node(&ctx->writer, key, key_len);
119             }
120 0 0         else if (flag & XH_H2X_F_SIMPLE && !(flag & XH_H2X_F_CONTENT)) {
    0          
121 0           xh_xml_write_attribute(&ctx->writer, key, key_len, NULL);
122 0           nattrs++;
123             }
124             }
125              
126             FINISH:
127 57           ctx->depth--;
128              
129 57           return nattrs;
130             }
131              
132             #ifdef XH_HAVE_DOM
133             xh_int_t
134             xh_h2d_native_attr(xh_h2x_ctx_t *ctx, xmlNodePtr rootNode, xh_char_t *key, I32 key_len, SV *value, xh_int_t flag)
135             {
136             xh_uint_t type;
137             size_t len, i, nattrs, done;
138             xh_sort_hash_t *sorted_hash;
139             SV *item_value;
140             xh_char_t *item;
141             I32 item_len;
142             GV *method;
143              
144             nattrs = 0;
145              
146             if (ctx->opts.content[0] != '\0' && xh_strcmp(key, ctx->opts.content) == 0)
147             flag = flag | XH_H2X_F_CONTENT;
148              
149             value = xh_h2x_resolve_value(ctx, value, &type);
150              
151              
152             if (type & XH_H2X_T_BLESSED && (method = gv_fetchmethod_autoload(SvSTASH(value), "iternext", 0)) != NULL) {
153             if (!(flag & XH_H2X_F_COMPLEX)) goto FINISH;
154              
155             while (1) {
156             item_value = xh_h2x_call_method(value, method);
157             if (!SvOK(item_value)) break;
158             (void) xh_h2d_native_attr(ctx, rootNode, key, key_len, item_value, XH_H2X_F_SIMPLE | XH_H2X_F_COMPLEX);
159             SvREFCNT_dec(item_value);
160             }
161              
162             nattrs++;
163              
164             goto FINISH;
165             }
166              
167             if (type & XH_H2X_T_SCALAR) {
168             if (flag & XH_H2X_F_SIMPLE && flag & XH_H2X_F_COMPLEX) {
169             (void) xh_dom_new_node(ctx, rootNode, key, key_len, value, type & XH_H2X_T_RAW);
170             }
171             else if (flag & XH_H2X_F_COMPLEX && flag & XH_H2X_F_CONTENT) {
172             xh_dom_new_content(ctx, rootNode, value);
173             }
174             else if (flag & XH_H2X_F_SIMPLE && !(flag & XH_H2X_F_CONTENT)) {
175             xh_dom_new_attribute(ctx, rootNode, key, key_len, value);
176             nattrs++;
177             }
178             }
179             else if (type & XH_H2X_T_HASH) {
180             if (!(flag & XH_H2X_F_COMPLEX)) goto FINISH;
181              
182             rootNode = xh_dom_new_node(ctx, rootNode, key, key_len, NULL, type & XH_H2X_T_RAW);
183              
184             len = HvUSEDKEYS((SV *) value);
185             if (len == 0) goto FINISH;
186              
187             done = 0;
188              
189             if (len > 1 && ctx->opts.canonical) {
190             sorted_hash = xh_sort_hash((HV *) value, len);
191              
192             for (i = 0; i < len; i++) {
193             done += xh_h2d_native_attr(ctx, rootNode, sorted_hash[i].key, sorted_hash[i].key_len, sorted_hash[i].value, XH_H2X_F_SIMPLE);
194             }
195              
196             if (done != len) {
197             for (i = 0; i < len; i++) {
198             (void) xh_h2d_native_attr(ctx, rootNode, sorted_hash[i].key, sorted_hash[i].key_len, sorted_hash[i].value, XH_H2X_F_COMPLEX);
199             }
200             }
201              
202             free(sorted_hash);
203             }
204             else {
205             hv_iterinit((HV *) value);
206             while ((item_value = hv_iternextsv((HV *) value, (char **) &item, &item_len))) {
207             done += xh_h2d_native_attr(ctx, rootNode, item, item_len,item_value, XH_H2X_F_SIMPLE);
208             }
209              
210             if (done != len) {
211             hv_iterinit((HV *) value);
212             while ((item_value = hv_iternextsv((HV *) value, (char **) &item, &item_len))) {
213             (void) xh_h2d_native_attr(ctx, rootNode, item, item_len,item_value, XH_H2X_F_COMPLEX);
214             }
215             }
216             }
217              
218             nattrs++;
219             }
220             else if (type & XH_H2X_T_ARRAY) {
221             if (!(flag & XH_H2X_F_COMPLEX)) goto FINISH;
222              
223             len = av_len((AV *) value) + 1;
224             for (i = 0; i < len; i++) {
225             (void) xh_h2d_native_attr(ctx, rootNode, key, key_len, *av_fetch((AV *) value, i, 0), XH_H2X_F_SIMPLE | XH_H2X_F_COMPLEX);
226             }
227              
228             nattrs++;
229             }
230             else {
231             if (flag & XH_H2X_F_SIMPLE && flag & XH_H2X_F_COMPLEX) {
232             (void) xh_dom_new_node(ctx, rootNode, key, key_len, NULL, type & XH_H2X_T_RAW);
233             }
234             else if (flag & XH_H2X_F_SIMPLE && !(flag & XH_H2X_F_CONTENT)) {
235             xh_dom_new_attribute(ctx, rootNode, key, key_len, NULL);
236             nattrs++;
237             }
238             }
239              
240             FINISH:
241             ctx->depth--;
242              
243             return nattrs;
244             }
245             #endif