File Coverage

src/xh_h2x_native.c
Criterion Covered Total %
statement 31 31 100.0
branch 24 30 80.0
condition n/a
subroutine n/a
pod n/a
total 55 61 90.1


line stmt bran cond sub pod time code
1             #include "xh_config.h"
2             #include "xh_core.h"
3              
4             void
5 63           xh_h2x_native(xh_h2x_ctx_t *ctx, xh_char_t *key, I32 key_len, SV *value)
6             {
7             xh_uint_t type;
8             size_t i, len;
9             SV *item_value;
10             xh_char_t *item;
11             I32 item_len;
12             xh_sort_hash_t *sorted_hash;
13             GV *method;
14              
15 63           value = xh_h2x_resolve_value(ctx, value, &type);
16              
17 63 100         if (type & XH_H2X_T_BLESSED && (method = gv_fetchmethod_autoload(SvSTASH(value), "iternext", 0)) != NULL) {
    50          
18             while (1) {
19 5           item_value = xh_h2x_call_method(value, method);
20 5 100         if (!SvOK(item_value)) break;
    50          
    50          
21 4           (void) xh_h2x_native(ctx, key, key_len, item_value);
22 4           SvREFCNT_dec(item_value);
23 4           }
24 1           goto FINISH;
25             }
26              
27 62 100         if (type & XH_H2X_T_SCALAR) {
28 32           xh_xml_write_node(&ctx->writer, key, key_len, value, type & XH_H2X_T_RAW);
29             }
30 30 100         else if (type & XH_H2X_T_HASH) {
31 24 50         len = HvUSEDKEYS((HV *) value);
32 24 50         if (len == 0) goto ADD_EMPTY_NODE;
33              
34 24           xh_xml_write_start_node(&ctx->writer, key, key_len);
35              
36 24 100         if (len > 1 && ctx->opts.canonical) {
    50          
37 2           sorted_hash = xh_sort_hash((HV *) value, len);
38 7 100         for (i = 0; i < len; i++) {
39 5           xh_h2x_native(ctx, sorted_hash[i].key, sorted_hash[i].key_len, sorted_hash[i].value);
40             }
41 2           free(sorted_hash);
42             }
43             else {
44 22           hv_iterinit((HV *) value);
45 44 100         while ((item_value = hv_iternextsv((HV *) value, (char **) &item, &item_len))) {
46 22           xh_h2x_native(ctx, item, item_len, item_value);
47             }
48             }
49              
50 24           xh_xml_write_end_node(&ctx->writer, key, key_len);
51             }
52 6 100         else if (type & XH_H2X_T_ARRAY) {
53 5           len = av_len((AV *) value) + 1;
54 16 100         for (i = 0; i < len; i++) {
55 11           xh_h2x_native(ctx, key, key_len, *av_fetch((AV *) value, i, 0));
56             }
57             }
58             else {
59             ADD_EMPTY_NODE:
60 1           xh_xml_write_empty_node(&ctx->writer, key, key_len);
61             }
62              
63             FINISH:
64 63           ctx->depth--;
65 63           }
66              
67             #ifdef XH_HAVE_DOM
68             void
69             xh_h2d_native(xh_h2x_ctx_t *ctx, xmlNodePtr rootNode, xh_char_t *key, I32 key_len, SV *value)
70             {
71             xh_uint_t type;
72             size_t i, len;
73             SV *item_value;
74             xh_char_t *item;
75             I32 item_len;
76             xh_sort_hash_t *sorted_hash;
77             GV *method;
78              
79             value = xh_h2x_resolve_value(ctx, value, &type);
80              
81             if (type & XH_H2X_T_BLESSED && (method = gv_fetchmethod_autoload(SvSTASH(value), "iternext", 0)) != NULL) {
82             while (1) {
83             item_value = xh_h2x_call_method(value, method);
84             if (!SvOK(item_value)) break;
85             (void) xh_h2d_native(ctx, rootNode, key, key_len, item_value);
86             SvREFCNT_dec(item_value);
87             }
88             goto FINISH;
89             }
90              
91             if (type & XH_H2X_T_SCALAR) {
92             (void) xh_dom_new_node(ctx, rootNode, key, key_len, value, type & XH_H2X_T_RAW);
93             }
94             else if (type & XH_H2X_T_HASH) {
95             len = HvUSEDKEYS((HV *) value);
96             if (len == 0) goto ADD_EMPTY_NODE;
97              
98             rootNode = xh_dom_new_node(ctx, rootNode, key, key_len, NULL, FALSE);
99              
100             if (len > 1 && ctx->opts.canonical) {
101             sorted_hash = xh_sort_hash((HV *) value, len);
102             for (i = 0; i < len; i++) {
103             xh_h2d_native(ctx, rootNode, sorted_hash[i].key, sorted_hash[i].key_len, sorted_hash[i].value);
104             }
105             free(sorted_hash);
106             }
107             else {
108             hv_iterinit((HV *) value);
109             while ((item_value = hv_iternextsv((HV *) value, (char **) &item, &item_len))) {
110             xh_h2d_native(ctx, rootNode, item, item_len, item_value);
111             }
112             }
113             }
114             else if (type & XH_H2X_T_ARRAY) {
115             len = av_len((AV *) value) + 1;
116             for (i = 0; i < len; i++) {
117             (void) xh_h2d_native(ctx, rootNode, key, key_len, *av_fetch((AV *) value, i, 0));
118             }
119             }
120             else {
121             ADD_EMPTY_NODE:
122             xh_dom_new_node(ctx, rootNode, key, key_len, NULL, FALSE);
123             }
124              
125             FINISH:
126             ctx->depth--;
127             }
128             #endif