File Coverage

src/xh_h2x.h
Criterion Covered Total %
statement 63 67 94.0
branch 39 56 69.6
condition n/a
subroutine n/a
pod n/a
total 102 123 82.9


line stmt bran cond sub pod time code
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             SV *hash;
28             } xh_h2x_ctx_t;
29              
30             XH_INLINE SV *
31 5           xh_h2x_call_method(SV *obj, GV *method)
32             {
33             int count;
34 5           SV *result = &PL_sv_undef;
35              
36 5           dSP;
37              
38 5 50         ENTER; SAVETMPS; PUSHMARK (SP);
39 5 50         XPUSHs(sv_2mortal(newRV_inc(obj)));
40 5           PUTBACK;
41              
42 5           count = call_sv((SV *) GvCV(method), G_SCALAR);
43              
44 5           SPAGAIN;
45              
46 5 50         if (count) {
47 5           result = POPs;
48 5           SvREFCNT_inc_void(result);
49             }
50              
51 5           PUTBACK;
52              
53 5 50         FREETMPS; LEAVE;
54              
55 5           return result;
56             }
57              
58             XH_INLINE SV *
59 63           xh_h2x_resolve_value(xh_h2x_ctx_t *ctx, SV *value, xh_uint_t *type)
60             {
61             xh_int_t nitems;
62             GV *method;
63             SV *tmpsv, *rv;
64             #if PERL_VERSION <= 8
65             MAGIC *mg;
66             #endif
67              
68 63           *type = 0;
69              
70 80 100         while ( SvOK(value) && SvROK(value) ) {
    50          
    50          
    100          
71 17 50         if (++ctx->depth > ctx->opts.max_depth)
72 0           croak("Maximum recursion depth exceeded");
73              
74 17           rv = value;
75 17           value = SvRV(value);
76 17           *type = 0;
77              
78 17 100         if (SvOBJECT(value)) {
79 3 50         if (SvGMAGICAL(value))
80 0           mg_get(value);
81              
82 3 100         if (XH_AMAGIC(value) && (tmpsv = XH_AMG_CALL_STRING(rv)) != NULL) {
    100          
83 1           value = tmpsv;
84 1           SvREFCNT_inc_void(value);
85 1           xh_stash_push(&ctx->stash, value);
86             }
87 2 100         else if ((method = gv_fetchmethod_autoload(SvSTASH(value), "toString", 0)) != NULL) {
88 1           dSP;
89              
90 1 50         ENTER; SAVETMPS; PUSHMARK(SP);
91 1 50         XPUSHs(sv_2mortal(newRV_inc(value)));
92 1           PUTBACK;
93              
94 1           nitems = call_sv((SV *) GvCV(method), G_SCALAR);
95              
96 1           SPAGAIN;
97              
98 1 50         if (nitems == 1) {
99 1           value = POPs;
100 1           PUTBACK;
101              
102 1           SvREFCNT_inc_void(value);
103              
104 1           xh_stash_push(&ctx->stash, value);
105              
106 1 50         FREETMPS; LEAVE;
107             }
108             else {
109 0           value = &PL_sv_undef;
110             }
111              
112 3           *type |= XH_H2X_T_RAW;
113             }
114             }
115 14 100         else if( SvTYPE(value) == SVt_PVCV ) {
116 5           dSP;
117              
118 5 50         ENTER; SAVETMPS; PUSHMARK (SP);
119              
120 5           nitems = call_sv(value, G_SCALAR|G_NOARGS);
121              
122 5           SPAGAIN;
123              
124 5 50         if (nitems == 1) {
125 5           value = POPs;
126              
127 5           SvREFCNT_inc_void(value);
128              
129 5           xh_stash_push(&ctx->stash, value);
130              
131 5           PUTBACK;
132              
133 5 50         FREETMPS;
134 5           LEAVE;
135             }
136             else {
137 0           value = &PL_sv_undef;
138             }
139             }
140             }
141              
142 63 100         if (SvTYPE(value) == SVt_PVHV) {
143 25           *type |= XH_H2X_T_HASH;
144             }
145 38 100         else if (SvTYPE(value) == SVt_PVAV) {
146 5           *type |= XH_H2X_T_ARRAY;
147             }
148 33 100         else if (!SvOK(value)) {
    50          
    50          
149 1           *type = 0;
150             }
151             else {
152 32           *type |= XH_H2X_T_SCALAR;
153             }
154              
155 63 100         if (SvOBJECT(value))
156 1           *type |= XH_H2X_T_BLESSED;
157              
158 63           return value;
159             }
160              
161             SV *xh_h2x(xh_h2x_ctx_t *ctx);
162             void xh_h2x_native(xh_h2x_ctx_t *ctx, xh_char_t *key, I32 key_len, SV *value);
163             xh_int_t xh_h2x_native_attr(xh_h2x_ctx_t *ctx, xh_char_t *key, I32 key_len, SV *value, xh_int_t flag);
164             void xh_h2x_lx(xh_h2x_ctx_t *ctx, SV *value, xh_char_t *key, I32 key_len, xh_int_t flag);
165              
166             #ifdef XH_HAVE_DOM
167             SV *xh_h2d(xh_h2x_ctx_t *ctx);
168             void xh_h2d_native(xh_h2x_ctx_t *ctx, xmlNodePtr rootNode, xh_char_t *key, I32 key_len, SV *value);
169             xh_int_t xh_h2d_native_attr(xh_h2x_ctx_t *ctx, xmlNodePtr rootNode, xh_char_t *key, I32 key_len, SV *value, xh_int_t flag);
170             void xh_h2d_lx(xh_h2x_ctx_t *ctx, xmlNodePtr rootNode, SV *value, xh_char_t *key, I32 key_len, xh_int_t flag);
171             #endif
172              
173             XH_INLINE void
174             xh_h2x_destroy_ctx(xh_h2x_ctx_t *ctx)
175             {
176             xh_destroy_opts(&ctx->opts);
177             }
178              
179             XH_INLINE void
180             xh_h2x_init_ctx(xh_h2x_ctx_t *ctx, I32 ax, I32 items)
181             {
182             xh_opts_t *opts = NULL;
183             xh_int_t nparam = 0;
184              
185             memset(ctx, 0, sizeof(xh_h2x_ctx_t));
186              
187             opts = (xh_opts_t *) xh_get_obj_param(&nparam, ax, items, "XML::Hash::XS");
188             ctx->hash = xh_get_hash_param(&nparam, ax, items);
189             xh_merge_opts(&ctx->opts, opts, nparam, ax, items);
190             }
191              
192             #endif /* _XH_H2X_H_ */