File Coverage

src/xh.c
Criterion Covered Total %
statement 141 204 69.1
branch 206 624 33.0
condition n/a
subroutine n/a
pod n/a
total 347 828 41.9


line stmt bran cond sub pod time code
1             #include "xh_config.h"
2             #include "xh_core.h"
3              
4             xh_bool_t
5 59           xh_init_opts(xh_opts_t *opts)
6             {
7             xh_char_t method[XH_PARAM_LEN];
8             xh_bool_t use_attr;
9              
10             XH_PARAM_READ_INIT
11              
12             /* native options */
13 59 50         XH_PARAM_READ_STRING (opts->root, "XML::Hash::XS::root", XH_DEF_ROOT);
    50          
    0          
    0          
    50          
14 59 50         XH_PARAM_READ_STRING (opts->version, "XML::Hash::XS::version", XH_DEF_VERSION);
    50          
    0          
    0          
    50          
15 59 50         XH_PARAM_READ_STRING (opts->encoding, "XML::Hash::XS::encoding", XH_DEF_ENCODING);
    50          
    0          
    0          
    50          
16 59 50         XH_PARAM_READ_INT (opts->indent, "XML::Hash::XS::indent", XH_DEF_INDENT);
    50          
17 59 50         XH_PARAM_READ_BOOL (opts->canonical, "XML::Hash::XS::canonical", XH_DEF_CANONICAL);
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
18 59 50         XH_PARAM_READ_STRING (opts->content, "XML::Hash::XS::content", XH_DEF_CONTENT);
    100          
    50          
    50          
    50          
19 59 50         XH_PARAM_READ_BOOL (opts->utf8, "XML::Hash::XS::utf8", XH_DEF_UTF8);
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
20 59 50         XH_PARAM_READ_BOOL (opts->xml_decl, "XML::Hash::XS::xml_decl", XH_DEF_XML_DECL);
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
21 59 50         XH_PARAM_READ_BOOL (opts->keep_root, "XML::Hash::XS::keep_root", XH_DEF_KEEP_ROOT);
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    50          
    0          
22             #ifdef XH_HAVE_DOM
23             XH_PARAM_READ_BOOL (opts->doc, "XML::Hash::XS::doc", XH_DEF_DOC);
24             #endif
25 59 50         XH_PARAM_READ_BOOL (use_attr, "XML::Hash::XS::use_attr", XH_DEF_USE_ATTR);
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
26 59 50         XH_PARAM_READ_INT (opts->max_depth, "XML::Hash::XS::max_depth", XH_DEF_MAX_DEPTH);
    50          
27 59 50         XH_PARAM_READ_INT (opts->buf_size, "XML::Hash::XS::buf_size", XH_DEF_BUF_SIZE);
    50          
28 59 50         XH_PARAM_READ_PATTERN(opts->force_array, "XML::Hash::XS::force_array", XH_DEF_FORCE_ARRAY);
29 59 50         XH_PARAM_READ_BOOL (opts->force_content, "XML::Hash::XS::force_content", XH_DEF_FORCE_CONTENT);
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    50          
    0          
30 59 50         XH_PARAM_READ_BOOL (opts->merge_text, "XML::Hash::XS::merge_text", XH_DEF_MERGE_TEXT);
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    50          
    0          
31              
32             /* XML::Hash::LX options */
33 59 50         XH_PARAM_READ_STRING (opts->attr, "XML::Hash::XS::attr", XH_DEF_ATTR);
    50          
    0          
    0          
    50          
34 59           opts->attr_len = xh_strlen(opts->attr);
35 59 50         XH_PARAM_READ_STRING (opts->text, "XML::Hash::XS::text", XH_DEF_TEXT);
    50          
    0          
    0          
    50          
36 59 50         XH_PARAM_READ_BOOL (opts->trim, "XML::Hash::XS::trim", XH_DEF_TRIM);
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
37 59 50         XH_PARAM_READ_STRING (opts->cdata, "XML::Hash::XS::cdata", XH_DEF_CDATA);
    50          
    50          
    50          
    0          
38 59 50         XH_PARAM_READ_STRING (opts->comm, "XML::Hash::XS::comm", XH_DEF_COMM);
    50          
    50          
    50          
    0          
39              
40             /* method */
41 59 50         XH_PARAM_READ_STRING (method, "XML::Hash::XS::method", XH_DEF_METHOD);
    50          
    0          
    0          
    50          
42 59 100         if (xh_strcmp(method, XH_CHAR_CAST "LX") == 0) {
43 15           opts->method = XH_METHOD_LX;
44             }
45 44 100         else if (use_attr) {
46 3           opts->method = XH_METHOD_NATIVE_ATTR_MODE;
47             }
48             else {
49 41           opts->method = XH_METHOD_NATIVE;
50             }
51              
52             /* output, NULL - to string */
53 59 50         XH_PARAM_READ_REF (opts->output, "XML::Hash::XS::output", XH_DEF_OUTPUT);
    50          
    50          
    50          
    0          
54              
55 59           return TRUE;
56             }
57              
58             xh_opts_t *
59 3           xh_create_opts(void)
60             {
61             xh_opts_t *opts;
62              
63 3 50         if ((opts = malloc(sizeof(xh_opts_t))) == NULL) {
64 0           return NULL;
65             }
66 3           memset(opts, 0, sizeof(xh_opts_t));
67              
68 3 50         if (! xh_init_opts(opts)) {
69 0           xh_destroy_opts(opts);
70 0           return NULL;
71             }
72              
73 3           return opts;
74             }
75              
76             void
77 60           xh_destroy_opts(xh_opts_t *opts)
78             {
79 60 50         if (opts->force_array.expr != NULL)
80 0           SvREFCNT_dec(opts->force_array.expr);
81              
82 60 100         if (opts->filter.expr != NULL)
83 6           SvREFCNT_dec(opts->filter.expr);
84              
85 60 100         if (opts->cb != NULL)
86 1           SvREFCNT_dec(opts->cb);
87 60           }
88              
89             void
90 1           xh_copy_opts(xh_opts_t *dst, xh_opts_t *src)
91             {
92 1           memcpy(dst, src, sizeof(xh_opts_t));
93 1 50         if (dst->force_array.expr != NULL) {
94 0           SvREFCNT_inc(dst->force_array.expr);
95             }
96 1           }
97              
98             void
99 31           xh_parse_param(xh_opts_t *opts, xh_int_t first, I32 ax, I32 items)
100             {
101             xh_int_t i;
102             xh_char_t *p, *cv;
103             SV *v;
104             STRLEN len;
105 31           xh_int_t use_attr = -1;
106              
107 31 50         if ((items - first) % 2 != 0) {
108 0           croak("Odd number of parameters in new()");
109             }
110              
111 79 100         for (i = first; i < items; i = i + 2) {
112 50           v = ST(i);
113 50 50         if (!SvOK(v)) {
    0          
    0          
114 0           croak("Parameter name is undefined");
115             }
116              
117 50 50         p = XH_CHAR_CAST SvPV(v, len);
118 50           v = ST(i + 1);
119              
120 50           switch (len) {
121             case 2:
122 1 50         if (xh_str_equal2(p, 'c', 'b')) {
123 1           opts->cb = xh_param_assign_cb("cb", v);
124 1           break;
125             }
126 0           goto error;
127             #ifdef XH_HAVE_DOM
128             case 3:
129             if (xh_str_equal3(p, 'd', 'o', 'c')) {
130             opts->doc = xh_param_assign_bool(v);
131             break;
132             }
133             goto error;
134             #endif
135             case 4:
136 18 100         if (xh_str_equal4(p, 'a', 't', 't', 'r')) {
137 1           xh_param_assign_string(opts->attr, v);
138 1 50         if (opts->attr[0] == '\0') {
139 0           opts->attr_len = 0;
140             }
141             else {
142 1           opts->attr_len = xh_strlen(opts->attr);
143             }
144 1           break;
145             }
146 17 100         if (xh_str_equal4(p, 'c', 'o', 'm', 'm')) {
147 2           xh_param_assign_string(opts->comm, v);
148 2           break;
149             }
150 15 50         if (xh_str_equal4(p, 'r', 'o', 'o', 't')) {
151 0           xh_param_assign_string(opts->root, v);
152 0           break;
153             }
154 15 100         if (xh_str_equal4(p, 't', 'r', 'i', 'm')) {
155 14           opts->trim = xh_param_assign_bool(v);
156 14           break;
157             }
158 1 50         if (xh_str_equal4(p, 't', 'e', 'x', 't')) {
159 1           xh_param_assign_string(opts->text, v);
160 1           break;
161             }
162 0 0         if (xh_str_equal4(p, 'u', 't', 'f', '8')) {
163 0           opts->utf8 = xh_param_assign_bool(v);
164 0           break;
165             }
166 0           goto error;
167             case 5:
168 2 50         if (xh_str_equal5(p, 'c', 'd', 'a', 't', 'a')) {
    50          
169 2           xh_param_assign_string(opts->cdata, v);
170 2           break;
171             }
172 0           goto error;
173             case 6:
174 11 100         if (xh_str_equal6(p, 'i', 'n', 'd', 'e', 'n', 't')) {
    50          
175 3           xh_param_assign_int(p, &opts->indent, v);
176 3           break;
177             }
178 8 50         if (xh_str_equal6(p, 'm', 'e', 't', 'h', 'o', 'd')) {
    0          
179 0 0         if (!SvOK(v)) {
    0          
    0          
180 0           croak("Parameter '%s' is undefined", p);
181             }
182 0 0         cv = XH_CHAR_CAST SvPV(v, len);
183 0           switch (len) {
184             case 6:
185 0 0         if (xh_str_equal6(cv, 'N', 'A', 'T', 'I', 'V', 'E')) {
    0          
186 0           opts->method = XH_METHOD_NATIVE;
187 0           break;
188             }
189 0           goto error_value;
190             case 2:
191 0 0         if (cv[0] == 'L' && cv[1] == 'X') {
    0          
192 0           opts->method = XH_METHOD_LX;
193 0           break;
194             }
195 0           goto error_value;
196             default:
197 0           goto error_value;
198             }
199 0           break;
200             }
201 8 100         if (xh_str_equal6(p, 'o', 'u', 't', 'p', 'u', 't')) {
    50          
202 2 50         if ( SvOK(v) && SvROK(v) ) {
    0          
    0          
    50          
203 2           opts->output = SvRV(v);
204             }
205             else {
206 0           opts->output = NULL;
207             }
208 2           break;
209             }
210 6 50         if (xh_str_equal6(p, 'f', 'i', 'l', 't', 'e', 'r')) {
    50          
211 6           xh_param_assign_filter(&opts->filter, v);
212 6           break;
213             }
214 0           goto error;
215             case 7:
216 2 50         if (xh_str_equal7(p, 'c', 'o', 'n', 't', 'e', 'n', 't')) {
    50          
217 2           xh_param_assign_string(opts->content, v);
218 2           break;
219             }
220 0 0         if (xh_str_equal7(p, 'v', 'e', 'r', 's', 'i', 'o', 'n')) {
    0          
221 0           xh_param_assign_string(opts->version, v);
222 0           break;
223             }
224 0           goto error;
225             case 8:
226 4 100         if (xh_str_equal8(p, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g')) {
    50          
227 2           xh_param_assign_string(opts->encoding, v);
228 2           break;
229             }
230 2 50         if (xh_str_equal8(p, 'u', 's', 'e', '_', 'a', 't', 't', 'r')) {
    50          
231 2           use_attr = xh_param_assign_bool(v);
232 2           break;
233             }
234 0 0         if (xh_str_equal8(p, 'x', 'm', 'l', '_', 'd', 'e', 'c', 'l')) {
    0          
235 0           opts->xml_decl = xh_param_assign_bool(v);
236 0           break;
237             }
238 0 0         if (xh_str_equal8(p, 'b', 'u', 'f', '_', 's', 'i', 'z', 'e')) {
    0          
239 0           xh_param_assign_int(p, &opts->buf_size, v);
240 0           break;
241             }
242 0           goto error;
243             case 9:
244 10 100         if (xh_str_equal9(p, 'c', 'a', 'n', 'o', 'n', 'i', 'c', 'a', 'l')) {
    50          
    50          
245 3           opts->canonical = xh_param_assign_bool(v);
246 3           break;
247             }
248 7 50         if (xh_str_equal9(p, 'm', 'a', 'x', '_', 'd', 'e', 'p', 't', 'h')) {
    0          
    0          
249 0           xh_param_assign_int(p, &opts->max_depth, v);
250 0           break;
251             }
252 7 50         if (xh_str_equal9(p, 'k', 'e', 'e', 'p', '_', 'r', 'o', 'o', 't')) {
    50          
    50          
253 7           opts->keep_root = xh_param_assign_bool(v);
254 7           break;
255             }
256 0           goto error;
257             case 10:
258 0 0         if (xh_str_equal10(p, 'm', 'e', 'r', 'g', 'e', '_', 't', 'e', 'x', 't')) {
    0          
    0          
259 0           opts->merge_text = xh_param_assign_bool(v);
260 0           break;
261             }
262             case 11:
263 0 0         if (xh_str_equal11(p, 'f', 'o', 'r', 'c', 'e', '_', 'a', 'r', 'r', 'a', 'y')) {
    0          
    0          
264 0           xh_param_assign_pattern(&opts->force_array, v);
265 0           break;
266             }
267             case 13:
268 0 0         if (xh_str_equal13(p, 'f', 'o', 'r', 'c', 'e', '_', 'c', 'o', 'n', 't', 'e', 'n', 't')) {
    0          
    0          
    0          
269 0           opts->force_content = xh_param_assign_bool(v);
270 0           break;
271             }
272             default:
273 2           goto error;
274             }
275             }
276              
277 29 100         if (use_attr != -1 && (opts->method == XH_METHOD_NATIVE || opts->method == XH_METHOD_NATIVE_ATTR_MODE)) {
    50          
    0          
278 2 50         if (use_attr == TRUE) {
279 2           opts->method = XH_METHOD_NATIVE_ATTR_MODE;
280             }
281             else {
282 0           opts->method = XH_METHOD_NATIVE;
283             }
284             }
285              
286 29           return;
287              
288             error_value:
289 0           croak("Invalid parameter value for '%s': %s", p, cv);
290             return;
291              
292             error:
293 31           croak("Invalid parameter '%s'", p);
294             }
295              
296             void *
297 57           xh_get_obj_param(xh_int_t *nparam, I32 ax, I32 items, char *class)
298             {
299             SV *param;
300 57           void *obj = NULL;
301              
302 57 50         if (*nparam >= items)
303 0           croak("Invalid parameters");
304              
305 57           param = ST(*nparam);
306 57 100         if ( sv_derived_from(param, class) ) {
307 1 50         if ( sv_isobject(param) ) {
308             /* reference to object */
309 1 50         IV tmp = SvIV((SV *) SvRV(param));
310 1           obj = INT2PTR(xh_opts_t *, tmp);
311             }
312 1           (*nparam)++;
313             }
314              
315 57           return obj;
316             }
317              
318             SV *
319 41           xh_get_hash_param(xh_int_t *nparam, I32 ax, I32 items)
320             {
321             SV *param;
322              
323 41 50         if (*nparam >= items)
324 0           croak("Invalid parameters");
325              
326 41           param = ST(*nparam);
327 41 50         if (!SvROK(param) || SvTYPE(SvRV(param)) != SVt_PVHV)
    50          
328 0           croak("Parameter is not hash reference");
329              
330 41           (*nparam)++;
331              
332 41           return param;
333             }
334              
335             SV *
336 16           xh_get_str_param(xh_int_t *nparam, I32 ax, I32 items)
337             {
338             SV *param;
339              
340 16 50         if (*nparam >= items)
341 0           croak("Invalid parameters");
342              
343 16           param = ST(*nparam);
344 16 100         if (SvROK(param))
345 3           param = SvRV(param);
346              
347 16 50         if (!SvOK(param))
    0          
    0          
348 0           croak("Invalid parameters");
349              
350 16 50         if (!SvPOK(param) && SvTYPE(param) != SVt_PVGV)
    0          
351 0           croak("Invalid parameters");
352              
353 16           (*nparam)++;
354              
355 16           return param;
356             }
357              
358             void
359 57           xh_merge_opts(xh_opts_t *ctx_opts, xh_opts_t *opts, xh_int_t nparam, I32 ax, I32 items)
360             {
361 57 100         if (opts == NULL) {
362             /* read global options */
363 56           xh_init_opts(ctx_opts);
364             }
365             else {
366             /* copy options from object */
367 1           xh_copy_opts(ctx_opts, opts);
368             }
369 57 100         if (nparam < items) {
370 28           xh_parse_param(ctx_opts, nparam, ax, items);
371             }
372 57           }
373