File Coverage

src/xh_h2x_native.c
Criterion Covered Total %
statement 34 35 97.1
branch 27 32 84.3
condition n/a
subroutine n/a
pod n/a
total 61 67 91.0


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