File Coverage

src/xh.c
Criterion Covered Total %
statement 184 237 77.6
branch 153 268 57.0
condition n/a
subroutine n/a
pod n/a
total 337 505 66.7


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