Fix XS so that Class::MOP::Method accessors blow up if called as class methods.
[gitmo/Class-MOP.git] / MOP.xs
CommitLineData
e0e4674a 1
2#include "EXTERN.h"
3#include "perl.h"
4#include "XSUB.h"
15273f3c 5
599791aa 6#define NEED_sv_2pv_flags
15273f3c 7#define NEED_sv_2pv_nolen
b0e94057 8#include "ppport.h"
e0e4674a 9
cc856b56 10SV *key_name;
11U32 hash_name;
12
13SV *key_package;
14U32 hash_package;
15
da88f307 16SV *key_package_name;
17U32 hash_package_name;
18
cc856b56 19SV *key_body;
20U32 hash_body;
21
e0e4674a 22/*
e0e4674a 23get_code_info:
24 Pass in a coderef, returns:
25 [ $pkg_name, $coderef_name ] ie:
26 [ 'Foo::Bar', 'new' ]
27*/
28
29MODULE = Class::MOP PACKAGE = Class::MOP
30
cc856b56 31BOOT:
32 key_name = newSVpvs("name");
33 key_body = newSVpvs("body");
34 key_package = newSVpvs("package");
da88f307 35 key_package_name = newSVpvs("package_name");
cc856b56 36
37 PERL_HASH(hash_name, "name", 4);
38 PERL_HASH(hash_body, "body", 4);
39 PERL_HASH(hash_package, "package", 7);
da88f307 40 PERL_HASH(hash_package_name, "package_name", 12);
cc856b56 41
42
d7bf3478 43PROTOTYPES: ENABLE
44
cc856b56 45
e0e4674a 46void
47get_code_info(coderef)
48 SV* coderef
49 PREINIT:
50 char* name;
51 char* pkg;
52 PPCODE:
e0e4674a 53 if( SvOK(coderef) && SvROK(coderef) && SvTYPE(SvRV(coderef)) == SVt_PVCV){
54 coderef = SvRV(coderef);
7b62d87f 55 /* I think this only gets triggered with a mangled coderef, but if
56 we hit it without the guard, we segfault. The slightly odd return
57 value strikes me as an improvement (mst)
58 */
a4f4221a 59#ifdef isGV_with_GP
60 if ( isGV_with_GP(CvGV(coderef))) {
61#endif
7b62d87f 62 pkg = HvNAME( GvSTASH(CvGV(coderef)) );
63 name = GvNAME( CvGV(coderef) );
a4f4221a 64#ifdef isGV_with_GP
65 } else {
66 pkg = "__UNKNOWN__";
67 name = "__ANON__";
68 }
69#endif
e0e4674a 70
71 EXTEND(SP, 2);
72 PUSHs(newSVpvn(pkg, strlen(pkg)));
73 PUSHs(newSVpvn(name, strlen(name)));
74 }
75
15273f3c 76
77MODULE = Class::MOP PACKAGE = Class::MOP::Package
78
79void
cc856b56 80get_all_package_symbols(self, ...)
81 SV *self
15273f3c 82 PROTOTYPE: $;$
83 PREINIT:
cc856b56 84 HV *stash = NULL;
15273f3c 85 SV *type_filter = NULL;
75705e60 86 register HE *he;
15273f3c 87 PPCODE:
88
89 switch ( GIMME_V ) {
90 case G_VOID: return; break;
91 case G_SCALAR: ST(0) = &PL_sv_undef; return; break;
92 }
93
94 if ( items > 1 ) type_filter = ST(1);
95
96 PUTBACK;
97
75705e60 98 if (SvROK(self) && (he = hv_fetch_ent((HV *)SvRV(self), key_package, 0, hash_package)))
99 stash = gv_stashsv(HeVAL(he),0);
15273f3c 100
101 if ( stash ) {
15273f3c 102
103 (void)hv_iterinit(stash);
104
105 if ( type_filter && SvPOK(type_filter) ) {
106 const char *const type = SvPV_nolen(type_filter);
107
75705e60 108 while ((he = hv_iternext(stash))) {
109 SV *const gv = HeVAL(he);
15273f3c 110 SV *sv;
75705e60 111 char *key;
112 STRLEN keylen;
9457b596 113 char *package;
fd27f6e9 114 SV *fq;
15273f3c 115
15273f3c 116 switch( SvTYPE(gv) ) {
117 case SVt_PVGV:
118 switch (*type) {
119 case 'C': sv = (SV *)GvCVu(gv); break; /* CODE */
120 case 'A': sv = (SV *)GvAV(gv); break; /* ARRAY */
121 case 'I': sv = (SV *)GvIO(gv); break; /* IO */
122 case 'H': sv = (SV *)GvHV(gv); break; /* HASH */
123 case 'S': sv = (SV *)GvSV(gv); break; /* SCALAR */
124 default:
125 croak("Unknown type %s\n", type);
126 }
127 break;
128 case SVt_RV:
129 /* BAH! constants are horrible */
fd27f6e9 130
131 /* we don't really care about the length,
132 but that's the API */
75705e60 133 key = HePV(he, keylen);
9457b596 134 package = HvNAME(stash);
fd27f6e9 135 fq = newSVpvf("%s::%s", package, key);
136 sv = sv_2mortal((SV*)get_cv(SvPV_nolen(fq), 0));
15273f3c 137 break;
138 default:
139 continue;
140 }
141
142 if ( sv ) {
75705e60 143 SV *key = hv_iterkeysv(he);
15273f3c 144 SPAGAIN;
145 EXTEND(SP, 2);
146 PUSHs(key);
66af67fe 147 PUSHs(sv_2mortal(newRV_inc(sv)));
15273f3c 148 PUTBACK;
149 }
150 }
151 } else {
152 EXTEND(SP, HvKEYS(stash) * 2);
153
75705e60 154 while ((he = hv_iternext(stash))) {
155 SV *key = hv_iterkeysv(he);
599791aa 156 SV *sv = HeVAL(he);
15273f3c 157 SPAGAIN;
0eb2957d 158 PUSHs(key);
15273f3c 159 PUSHs(sv);
160 PUTBACK;
161 }
162 }
163
164 }
165
cc856b56 166SV *
167name(self)
168 SV *self
169 PREINIT:
170 register HE *he;
171 PPCODE:
172 if (SvROK(self) && (he = hv_fetch_ent((HV *)SvRV(self), key_package, 0, hash_package)))
173 XPUSHs(HeVAL(he));
174 else
175 ST(0) = &PL_sv_undef;
176
dcbfe027 177MODULE = Class::MOP PACKAGE = Class::MOP::Attribute
cc856b56 178
179SV *
180name(self)
181 SV *self
182 PREINIT:
183 register HE *he;
184 PPCODE:
185 if (SvROK(self) && (he = hv_fetch_ent((HV *)SvRV(self), key_name, 0, hash_name)))
186 XPUSHs(HeVAL(he));
187 else
188 ST(0) = &PL_sv_undef;
189
dcbfe027 190MODULE = Class::MOP PACKAGE = Class::MOP::Method
cc856b56 191
192SV *
da88f307 193name(self)
194 SV *self
195 PREINIT:
196 register HE *he;
197 PPCODE:
198 if (! SvROK(self)) {
199 die("Cannot call name as a class method");
200 }
201
202 if (he = hv_fetch_ent((HV *)SvRV(self), key_name, 0, hash_name))
203 XPUSHs(HeVAL(he));
204 else
205 ST(0) = &PL_sv_undef;
206
207SV *
208package_name(self)
209 SV *self
210 PREINIT:
211 register HE *he;
212 PPCODE:
213 if (! SvROK(self)) {
214 die("Cannot call package_name as a class method");
215 }
216
217 if (he = hv_fetch_ent((HV *)SvRV(self), key_package_name, 0, hash_package_name))
218 XPUSHs(HeVAL(he));
219 else
220 ST(0) = &PL_sv_undef;
221
222SV *
cc856b56 223body(self)
224 SV *self
225 PREINIT:
226 register HE *he;
227 PPCODE:
da88f307 228 if (! SvROK(self)) {
229 die("Cannot call body as a class method");
230 }
231
232 if (he = hv_fetch_ent((HV *)SvRV(self), key_body, 0, hash_body))
cc856b56 233 XPUSHs(HeVAL(he));
234 else
235 ST(0) = &PL_sv_undef;