File Coverage

lib/Syntax/Operator/Equ.xs
Criterion Covered Total %
statement 49 49 100.0
branch 48 88 54.5
condition n/a
subroutine n/a
pod n/a
total 97 137 70.8


line stmt bran cond sub pod time code
1             /* You may distribute under the terms of either the GNU General Public License
2             * or the Artistic License (the same terms as Perl itself)
3             *
4             * (C) Paul Evans, 2016-2023 -- leonerd@leonerd.org.uk
5             */
6             #define PERL_NO_GET_CONTEXT
7              
8             #include "EXTERN.h"
9             #include "perl.h"
10             #include "XSUB.h"
11              
12             #include "XSParseInfix.h"
13              
14             #include "sv_numeq.c.inc"
15             #include "sv_streq.c.inc"
16              
17 5           static OP *pp_equ_numeric(pTHX)
18             {
19 5           dSP;
20             dTARG;
21 5           SV *lhs = TOPs, *rhs = TOPm1s;
22              
23 5 50         SvGETMAGIC(lhs);
24 5 50         SvGETMAGIC(rhs);
25              
26 5 100         bool lundef = !SvOK(lhs), rundef = !SvOK(rhs);
    50          
    50          
    100          
    50          
    50          
27              
28 5 100         if(lundef || rundef) {
29 3           POPs;
30 3 100         SETs(lundef && rundef ? &PL_sv_yes : &PL_sv_no);
31 3           RETURN;
32             }
33              
34 2           POPs;
35 2 100         SETs(sv_numeq_flags(lhs, rhs, 0) ? &PL_sv_yes : &PL_sv_no);
36 2           RETURN;
37             }
38              
39 9           static bool test_stringy_equ(pTHX_ SV *lhs, SV *rhs, bool test_rhs_regexp)
40             {
41 9 50         SvGETMAGIC(lhs);
42 9 50         SvGETMAGIC(rhs);
43              
44 9 100         bool lundef = !SvOK(lhs), rundef = !SvOK(rhs);
    50          
    50          
    100          
    50          
    50          
45              
46 9 100         if(lundef || rundef) {
47 3           return lundef && rundef;
48             }
49              
50 6 100         if(test_rhs_regexp && SvRXOK(rhs)) {
    100          
51             /* There isn't an API function for this so we'll have to do some
52             * PL_op and stack hackery. Stolen from
53             * https://metacpan.org/release/LEONT/Syntax-Infix-Smartmatch-0.001/source/lib/Syntax/Infix/Smartmatch.xs */
54 2           dSP;
55 2           REGEXP *re = (REGEXP *)SvRV(rhs);
56 2           PMOP *const matcher = cPMOPx(newPMOP(OP_MATCH, OPf_WANT_SCALAR | OPf_STACKED));
57 2           PM_SETRE(matcher, ReREFCNT_inc(re));
58              
59 2           ENTER;
60 2           SAVEFREEOP((OP *)matcher);
61 2           SAVEOP();
62              
63 2           PL_op = (OP *)matcher;
64              
65 2 50         XPUSHs(lhs);
66 2           PUTBACK;
67              
68 2           (void)PL_ppaddr[OP_MATCH](aTHX);
69              
70 2           SPAGAIN;
71 2 50         bool result = SvTRUEx(POPs);
    50          
    0          
    50          
    0          
    0          
    50          
    50          
    50          
    100          
    50          
    100          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
72              
73 2           LEAVE;
74              
75 2           return result;
76             }
77              
78 4           return sv_streq_flags(lhs, rhs, 0);
79             }
80              
81 5           static OP *pp_equ_stringy(pTHX)
82             {
83 5           dSP;
84             dTARG;
85 5           SV *lhs = TOPm1s, *rhs = TOPs;
86              
87 5           POPs;
88 5 100         SETs(test_stringy_equ(aTHX_ lhs, rhs, FALSE) ? &PL_sv_yes : &PL_sv_no);
89 5           RETURN;
90             }
91              
92 4           static OP *pp_eqr(pTHX)
93             {
94 4           dSP;
95             dTARG;
96 4           SV *lhs = TOPm1s, *rhs = TOPs;
97              
98 4           POPs;
99 4 100         SETs(test_stringy_equ(aTHX_ lhs, rhs, TRUE) ? &PL_sv_yes : &PL_sv_no);
100 4           RETURN;
101             }
102              
103             static const struct XSParseInfixHooks hooks_equ_numeric = {
104             .cls = XPI_CLS_EQUALITY,
105             .wrapper_func_name = "Syntax::Operator::Equ::is_numequ",
106             .permit_hintkey = "Syntax::Operator::Equ/equ",
107             .ppaddr = &pp_equ_numeric,
108             };
109              
110             static const struct XSParseInfixHooks hooks_equ_stringy = {
111             .cls = XPI_CLS_EQUALITY,
112             .wrapper_func_name = "Syntax::Operator::Equ::is_strequ",
113             .permit_hintkey = "Syntax::Operator::Equ/equ",
114             .ppaddr = &pp_equ_stringy,
115             };
116              
117             static const struct XSParseInfixHooks hooks_eqr = {
118             .cls = XPI_CLS_MATCH_MISC,
119             .wrapper_func_name = "Syntax::Operator::Eqr::is_eqr",
120             .permit_hintkey = "Syntax::Operator::Eqr/eqr",
121             .ppaddr = &pp_eqr,
122             };
123              
124             MODULE = Syntax::Operator::Equ PACKAGE = Syntax::Operator::Equ
125              
126             BOOT:
127 7           boot_xs_parse_infix(0.26);
128              
129             register_xs_parse_infix("===", &hooks_equ_numeric, NULL);
130             register_xs_parse_infix("equ", &hooks_equ_stringy, NULL);
131              
132             register_xs_parse_infix("eqr", &hooks_eqr, NULL);