This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
API tests for pad_findmy_*()
[perl5.git] / ext / Tie-Hash-NamedCapture / NamedCapture.xs
CommitLineData
5322d43e 1#define PERL_NO_GET_CONTEXT /* we want efficiency */
8cf6f931
NC
2#include "EXTERN.h"
3#include "perl.h"
4#include "XSUB.h"
5
8dcfe2e9
NC
6/* These are tightly coupled to the RXapif_* flags defined in regexp.h */
7#define UNDEF_FATAL 0x80000
8#define DISCARD 0x40000
9#define EXPECT_SHIFT 24
10#define ACTION_MASK 0x000FF
11
12#define FETCH_ALIAS (RXapif_FETCH | (2 << EXPECT_SHIFT))
13#define STORE_ALIAS (RXapif_STORE | (3 << EXPECT_SHIFT) | UNDEF_FATAL | DISCARD)
14#define DELETE_ALIAS (RXapif_DELETE | (2 << EXPECT_SHIFT) | UNDEF_FATAL)
15#define CLEAR_ALIAS (RXapif_CLEAR | (1 << EXPECT_SHIFT) | UNDEF_FATAL | DISCARD)
16#define EXISTS_ALIAS (RXapif_EXISTS | (2 << EXPECT_SHIFT))
17#define SCALAR_ALIAS (RXapif_SCALAR | (1 << EXPECT_SHIFT))
18
3b9b32c9 19static void
63f281fa 20tie_it(pTHX_ const char name, UV flag, HV *const stash)
4b5ae309
NC
21{
22 GV *const gv = gv_fetchpvn(&name, 1, GV_ADDMULTI|GV_NOTQUAL, SVt_PVHV);
23 HV *const hv = GvHV(gv);
24 SV *rv = newSV_type(SVt_RV);
25
63f281fa
NC
26 SvRV_set(rv, newSVuv(flag));
27 SvROK_on(rv);
28 sv_bless(rv, stash);
4b5ae309
NC
29
30 sv_unmagic((SV *)hv, PERL_MAGIC_tied);
31 sv_magic((SV *)hv, rv, PERL_MAGIC_tied, NULL, 0);
32 SvREFCNT_dec(rv); /* As sv_magic increased it by one. */
33}
34
8cf6f931
NC
35MODULE = Tie::Hash::NamedCapture PACKAGE = Tie::Hash::NamedCapture
36PROTOTYPES: DISABLE
37
4b5ae309 38BOOT:
63f281fa
NC
39 {
40 HV *const stash = GvSTASH(CvGV(cv));
41 tie_it(aTHX_ '-', RXapif_ALL, stash);
42 tie_it(aTHX_ '+', RXapif_ONE, stash);
43 }
4b5ae309 44
f8088870
NC
45SV *
46TIEHASH(package, ...)
47 const char *package;
48 PREINIT:
49 UV flag = RXapif_ONE;
50 CODE:
51 mark += 2;
52 while(mark < sp) {
53 STRLEN len;
54 const char *p = SvPV_const(*mark, len);
55 if(memEQs(p, len, "all"))
56 flag = SvTRUE(mark[1]) ? RXapif_ALL : RXapif_ONE;
57 mark += 2;
58 }
59 RETVAL = newSV_type(SVt_RV);
60 sv_setuv(newSVrv(RETVAL, package), flag);
61 OUTPUT:
62 RETVAL
63
8cf6f931 64void
8dcfe2e9
NC
65FETCH(...)
66 ALIAS:
67 Tie::Hash::NamedCapture::FETCH = FETCH_ALIAS
68 Tie::Hash::NamedCapture::STORE = STORE_ALIAS
69 Tie::Hash::NamedCapture::DELETE = DELETE_ALIAS
70 Tie::Hash::NamedCapture::CLEAR = CLEAR_ALIAS
71 Tie::Hash::NamedCapture::EXISTS = EXISTS_ALIAS
72 Tie::Hash::NamedCapture::SCALAR = SCALAR_ALIAS
73 PREINIT:
74 REGEXP *const rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
75 U32 flags;
76 SV *ret;
77 const U32 action = ix & ACTION_MASK;
78 const int expect = ix >> EXPECT_SHIFT;
79 PPCODE:
80 if (items != expect)
81 croak_xs_usage(cv, expect == 2 ? "$key"
82 : (expect == 3 ? "$key, $value"
83 : ""));
84
85 if (!rx || !SvROK(ST(0))) {
86 if (ix & UNDEF_FATAL)
87 Perl_croak_no_modify(aTHX);
88 else
89 XSRETURN_UNDEF;
90 }
91
92 flags = (U32)SvUV(SvRV(MUTABLE_SV(ST(0))));
93
94 PUTBACK;
95 ret = RX_ENGINE(rx)->named_buff(aTHX_ (rx), expect >= 2 ? ST(1) : NULL,
96 expect >= 3 ? ST(2) : NULL, flags | action);
97 SPAGAIN;
98
99 if (ix & DISCARD) {
100 /* Called with G_DISCARD, so our return stack state is thrown away.
101 Hence if we were returned anything, free it immediately. */
102 SvREFCNT_dec(ret);
103 } else {
104 PUSHs(ret ? sv_2mortal(ret) : &PL_sv_undef);
105 }
106
107void
610f2345
NC
108FIRSTKEY(...)
109 ALIAS:
110 Tie::Hash::NamedCapture::NEXTKEY = 1
111 PREINIT:
112 REGEXP *const rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
113 U32 flags;
114 SV *ret;
115 const int expect = ix ? 2 : 1;
116 const U32 action = ix ? RXapif_NEXTKEY : RXapif_FIRSTKEY;
117 PPCODE:
118 if (items != expect)
119 croak_xs_usage(cv, expect == 2 ? "$lastkey" : "");
120
121 if (!rx || !SvROK(ST(0)))
122 XSRETURN_UNDEF;
123
124 flags = (U32)SvUV(SvRV(MUTABLE_SV(ST(0))));
125
126 PUTBACK;
127 ret = RX_ENGINE(rx)->named_buff_iter(aTHX_ (rx),
128 expect >= 2 ? ST(1) : NULL,
129 flags | action);
130 SPAGAIN;
131
132 PUSHs(ret ? sv_2mortal(ret) : &PL_sv_undef);
133
134void
8cf6f931
NC
135flags(...)
136 PPCODE:
137 EXTEND(SP, 2);
138 mPUSHu(RXapif_ONE);
139 mPUSHu(RXapif_ALL);