File Coverage

src/xh_h2x.h
Criterion Covered Total %
statement 11 11 100.0
branch n/a
condition n/a
subroutine n/a
pod n/a
total 11 11 100.0


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             xh_h2x_call_method(SV *obj, GV *method)
32             {
33             int count;
34             SV *result = &PL_sv_undef;
35              
36             dSP;
37              
38             ENTER; SAVETMPS; PUSHMARK (SP);
39             XPUSHs(sv_2mortal(newRV_inc(obj)));
40             PUTBACK;
41              
42             count = call_sv((SV *) GvCV(method), G_SCALAR);
43              
44             SPAGAIN;
45              
46             if (count) {
47             result = POPs;
48             SvREFCNT_inc_void(result);
49             }
50              
51             PUTBACK;
52              
53             FREETMPS; LEAVE;
54              
55             return result;
56             }
57              
58             XH_INLINE SV *
59             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             *type = 0;
69              
70             while ( SvOK(value) && SvROK(value) ) {
71             if (++ctx->depth > ctx->opts.max_depth)
72             croak("Maximum recursion depth exceeded");
73              
74             rv = value;
75             value = SvRV(value);
76             *type = 0;
77              
78             if (SvOBJECT(value)) {
79             if (SvGMAGICAL(value))
80             mg_get(value);
81              
82             if (XH_AMAGIC(value) && (tmpsv = XH_AMG_CALL_STRING(rv)) != NULL) {
83             value = tmpsv;
84             SvREFCNT_inc_void(value);
85             xh_stash_push(&ctx->stash, value);
86             }
87             else if ((method = gv_fetchmethod_autoload(SvSTASH(value), "toString", 0)) != NULL) {
88             dSP;
89              
90             ENTER; SAVETMPS; PUSHMARK(SP);
91             XPUSHs(sv_2mortal(newRV_inc(value)));
92             PUTBACK;
93              
94             nitems = call_sv((SV *) GvCV(method), G_SCALAR);
95              
96             SPAGAIN;
97              
98             if (nitems == 1) {
99             value = POPs;
100             PUTBACK;
101              
102             SvREFCNT_inc_void(value);
103              
104             xh_stash_push(&ctx->stash, value);
105              
106             FREETMPS; LEAVE;
107             }
108             else {
109             value = &PL_sv_undef;
110             }
111              
112             *type |= XH_H2X_T_RAW;
113             }
114             }
115             else if( SvTYPE(value) == SVt_PVCV ) {
116             dSP;
117              
118             ENTER; SAVETMPS; PUSHMARK (SP);
119              
120             nitems = call_sv(value, G_SCALAR|G_NOARGS);
121              
122             SPAGAIN;
123              
124             if (nitems == 1) {
125             value = POPs;
126              
127             SvREFCNT_inc_void(value);
128              
129             xh_stash_push(&ctx->stash, value);
130              
131             PUTBACK;
132              
133             FREETMPS;
134             LEAVE;
135             }
136             else {
137             value = &PL_sv_undef;
138             }
139             }
140             }
141              
142             if (SvTYPE(value) == SVt_PVHV) {
143             *type |= XH_H2X_T_HASH;
144             }
145             else if (SvTYPE(value) == SVt_PVAV) {
146             *type |= XH_H2X_T_ARRAY;
147             }
148             else if (!SvOK(value)) {
149             *type = 0;
150             }
151             else {
152             *type |= XH_H2X_T_SCALAR;
153             }
154              
155             if (SvOBJECT(value))
156             *type |= XH_H2X_T_BLESSED;
157              
158             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 42           xh_h2x_destroy_ctx(xh_h2x_ctx_t *ctx)
175             {
176 42           xh_destroy_opts(&ctx->opts);
177 42           }
178              
179             XH_INLINE void
180 42           xh_h2x_init_ctx(xh_h2x_ctx_t *ctx, I32 ax, I32 items)
181             {
182 42           xh_opts_t *opts = NULL;
183 42           xh_int_t nparam = 0;
184              
185 42           memset(ctx, 0, sizeof(xh_h2x_ctx_t));
186              
187 42           opts = (xh_opts_t *) xh_get_obj_param(&nparam, ax, items, "XML::Hash::XS");
188 42           ctx->hash = xh_get_hash_param(&nparam, ax, items);
189 42           xh_merge_opts(&ctx->opts, opts, nparam, ax, items);
190 42           }
191              
192             #endif /* _XH_H2X_H_ */