File Coverage

OptionalChain.xs
Criterion Covered Total %
statement 31 31 100.0
branch 24 30 80.0
condition n/a
subroutine n/a
pod n/a
total 55 61 90.1


line stmt bran cond sub pod time code
1             #include "EXTERN.h"
2             #include "perl.h"
3             #include "XSUB.h"
4             #include "ppport.h"
5              
6             static SV *
7 41           my_navigate(pTHX_ SV *obj, SV *key)
8             {
9 41 100         if (!SvOK(obj))
10 7           return newSV(0); /* undef */
11              
12 34 100         if (sv_isobject(obj)) {
13 20           HV *stash = SvSTASH(SvRV(obj));
14 20           GV *gv = gv_fetchmethod_autoload(stash, SvPV_nolen(key), FALSE);
15 20 100         if (gv && isGV(gv) && GvCV(gv)) {
    50          
    50          
16 17           dSP;
17             int count;
18             SV *out;
19 17           ENTER;
20 17           SAVETMPS;
21 17 50         PUSHMARK(SP);
22 17 50         XPUSHs(obj); /* the invocant */
23 17           PUTBACK;
24 17           count = call_sv((SV *)GvCV(gv), G_SCALAR);
25 17           SPAGAIN;
26 17 50         out = newSVsv(count ? POPs : &PL_sv_undef); /* copy out */
27 17           PUTBACK;
28 17 100         FREETMPS;
29 17           LEAVE;
30 17           return out;
31             }
32             /* blessed but no such method: fall through to structural access */
33             }
34              
35 17 100         if (SvROK(obj)) {
36 16           SV *rv = SvRV(obj);
37 16 100         if (SvTYPE(rv) == SVt_PVHV) {
38 9           HE *he = hv_fetch_ent((HV *)rv, key, 0, 0);
39 9 100         return he ? newSVsv(HeVAL(he)) : newSV(0);
40             }
41 7 100         if (SvTYPE(rv) == SVt_PVAV) {
42 6           SV **ele = av_fetch((AV *)rv, SvIV(key), 0);
43 6 100         return (ele && *ele) ? newSVsv(*ele) : newSV(0);
    50          
44             }
45 1           croak("Syntax::Infix::OptionalChain: cannot navigate '%" SVf
46             "' into a %s reference", SVfARG(key), sv_reftype(rv, 0));
47             }
48              
49 1           croak("Syntax::Infix::OptionalChain: cannot navigate '%" SVf
50             "' into a non-reference scalar", SVfARG(key));
51             }
52              
53             MODULE = Syntax::Infix::OptionalChain PACKAGE = Syntax::Infix::OptionalChain
54              
55             SV *
56             _nav(obj, key)
57             SV *obj
58             SV *key
59             CODE:
60 41           RETVAL = my_navigate(aTHX_ obj, key);
61             OUTPUT:
62             RETVAL