File Coverage

convert.c
Criterion Covered Total %
statement 39 39 100.0
branch 21 22 95.4
condition n/a
subroutine n/a
pod n/a
total 60 61 98.3


line stmt bran cond sub pod time code
1             /* vim:set ts=4 sw=4 et syntax=c.doxygen: */
2              
3             #include "EXTERN.h"
4             #include "perl.h"
5             #include "XSUB.h"
6              
7             #include "ppport.h"
8              
9             #include "convert.h"
10              
11             static SV *
12 24           _convert_struct(const ps_node *node, enum type_preference prefer, const char *prefix)
13             {
14 24           SV *result = NULL;
15 24           const union ps_nodeval *v = &node->val;
16 24           const struct ps_array *what =
17 24           node->type == NODE_OBJECT
18             ? &node->val.o.val
19 24 100         : &node->val.a;
20              
21 24 100         if (node->type != NODE_OBJECT && what->len == 0 && prefer == PREFER_UNDEF) {
    100          
    100          
22 3           result = newSVsv(&PL_sv_undef);
23             } else {
24 21           SV *a = NULL;
25 21 100         if (prefer == PREFER_HASH || !what->is_array) {
    100          
26             // len == 0 could be hash still
27 15           a = (SV*)newHV();
28 36 100         for (int i = 0; i < what->len; i++) {
29             STRLEN len;
30 21           char *key = SvPV(sv_2mortal(_convert_recurse(what->pairs[i].key, prefer, prefix)), len);
31 21           SV *val = _convert_recurse(what->pairs[i].val, prefer, prefix);
32              
33 21           hv_store((HV*)a, key, len, val, 0);
34             }
35             } else {
36 6           a = (SV*)newAV();
37 6           av_extend((AV*)a, what->len - 1);
38 16 100         for (int i = 0; i < what->len; i++)
39 10           av_push((AV*)a, _convert_recurse(what->pairs[i].val, prefer, prefix));
40             }
41              
42 21           result = newRV_noinc(a);
43 21 100         if (node->type == NODE_OBJECT) {
44 2           char *typename = v->o.type;
45 2 100         if (prefix) {
46 1           SV *built = sv_2mortal(newSVpvf("%s::%s", prefix, typename));
47 1           sv_bless(result, gv_stashsv(built, true));
48             } else {
49 1           sv_bless(result, gv_stashpv(typename, true));
50             }
51             }
52             }
53              
54 24           return result;
55             }
56              
57             SV *
58 68           _convert_recurse(const ps_node *node, enum type_preference prefer, const char *prefix)
59             {
60 68           SV *result = NULL;
61              
62 68           const union ps_nodeval *v = &node->val;
63 68           switch (node->type) {
64 25           case NODE_STRING: result = newSVpv(v->s.val, v->s.len); break;
65 15           case NODE_INT: result = newSViv(v->i); break;
66 2           case NODE_FLOAT: result = newSVnv(v->d); break;
67 1 50         case NODE_BOOL: result = newSVsv(v->b ? &PL_sv_yes : &PL_sv_no); break;
68 1           case NODE_NULL: result = newSVsv(&PL_sv_undef); break;
69 24           case NODE_OBJECT: /* FALLTHROUGH */
70 24           case NODE_ARRAY: result = _convert_struct(node, prefer, prefix); break;
71             }
72              
73 68           return result;
74             }
75