Optimize is_class_loaded()
[gitmo/Class-MOP.git] / xs / MOP.xs
CommitLineData
d846ade3 1#include "mop.h"
2
7ec7b950 3SV *mop_method_metaclass;
4SV *mop_associated_metaclass;
daf9799b 5SV *mop_associated_attribute;
7ec7b950 6SV *mop_wrap;
1bc0cb6b 7SV *mop_methods;
8SV *mop_name;
9SV *mop_body;
10SV *mop_package;
11SV *mop_package_name;
12SV *mop_package_cache_flag;
87cfe982 13SV *mop_initialize;
14SV *mop_isa;
15SV *mop_can;
16SV *mop_Class;
1bc0cb6b 17SV *mop_VERSION;
18SV *mop_ISA;
7ec7b950 19
00370481 20/* equivalent to "blessed($x) && $x->isa($klass)" */
21bool
22mop_is_instance_of(pTHX_ SV* const sv, SV* const klass){
23 assert(sv);
24 assert(klass);
25
26 if(SvROK(sv) && SvOBJECT(SvRV(sv)) && SvOK(klass)){
27 bool ok;
28
29 ENTER;
30 SAVETMPS;
31
32 ok = SvTRUEx(mop_call1(aTHX_ sv, mop_isa, klass));
33
34 FREETMPS;
35 LEAVE;
36
e192207e 37 return ok;
00370481 38 }
39
40 return FALSE;
41}
eaca1141 42
d846ade3 43static bool
44find_method (const char *key, STRLEN keylen, SV *val, void *ud)
45{
eaca1141 46 bool * const found_method = (bool *)ud;
2dba318b 47 PERL_UNUSED_ARG(key);
48 PERL_UNUSED_ARG(keylen);
49 PERL_UNUSED_ARG(val);
d846ade3 50 *found_method = TRUE;
51 return FALSE;
52}
53
eaca1141 54
55bool
56mop_is_class_loaded(pTHX_ SV * const klass){
57 HV *stash;
2a30c752 58 HE* he;
eaca1141 59
60 if (!(SvPOKp(klass) && SvCUR(klass))) { /* XXX: SvPOK does not work with magical scalars */
61 return FALSE;
62 }
63
64 stash = gv_stashsv(klass, 0);
65 if (!stash) {
66 return FALSE;
67 }
68
2a30c752 69 if (( he = hv_fetch_ent (stash, mop_VERSION, FALSE, 0U) )) {
70 GV* const version_gv = (GV*)HeVAL(he);
71 if(isGV(version_gv) && GvSV(version_gv) && SvOK(GvSV(version_gv))){
72 return TRUE;
eaca1141 73 }
74 }
75
2a30c752 76 if (( he = hv_fetch_ent (stash, mop_ISA, FALSE, 0U) )) {
77 GV* const isa_gv = (GV*)HeVAL(he);
78 if(isGV(isa_gv) && GvAV(isa_gv) && av_len(GvAV(isa_gv)) != -1){
79 return TRUE;
eaca1141 80 }
81 }
82
83 {
84 bool found_method = FALSE;
85 mop_get_package_symbols(stash, TYPE_FILTER_CODE, find_method, &found_method);
2a30c752 86 return found_method;
eaca1141 87 }
88}
89
d846ade3 90MODULE = Class::MOP PACKAGE = Class::MOP
91
92PROTOTYPES: DISABLE
93
94BOOT:
1bc0cb6b 95 mop_method_metaclass = MAKE_KEYSV(method_metaclass);
1bc0cb6b 96 mop_associated_metaclass = MAKE_KEYSV(associated_metaclass);
daf9799b 97 mop_associated_attribute = MAKE_KEYSV(associated_attribute);
98 mop_wrap = MAKE_KEYSV(wrap);
1bc0cb6b 99 mop_methods = MAKE_KEYSV(methods);
100 mop_name = MAKE_KEYSV(name);
101 mop_body = MAKE_KEYSV(body);
102 mop_package = MAKE_KEYSV(package);
103 mop_package_name = MAKE_KEYSV(package_name);
104 mop_package_cache_flag = MAKE_KEYSV(_package_cache_flag);
87cfe982 105 mop_initialize = MAKE_KEYSV(initialize);
106 mop_Class = MAKE_KEYSV(Class::MOP::Class);
1bc0cb6b 107 mop_VERSION = MAKE_KEYSV(VERSION);
108 mop_ISA = MAKE_KEYSV(ISA);
00370481 109 mop_isa = MAKE_KEYSV(isa);
87cfe982 110 mop_can = MAKE_KEYSV(can);
d846ade3 111
c79ae27a 112 MOP_CALL_BOOT( Class__MOP__Package );
113 MOP_CALL_BOOT( Class__MOP__Class );
114 MOP_CALL_BOOT( Class__MOP__Attribute );
115 MOP_CALL_BOOT( Class__MOP__Instance );
116 MOP_CALL_BOOT( Class__MOP__Method );
117 MOP_CALL_BOOT( Class__MOP__Method__Accessor );
118 MOP_CALL_BOOT( Class__MOP__Method__Constructor );
d846ade3 119
120# use prototype here to be compatible with get_code_info from Sub::Identify
121void
122get_code_info(coderef)
123 SV *coderef
124 PROTOTYPE: $
125 PREINIT:
126 char *pkg = NULL;
127 char *name = NULL;
128 PPCODE:
704f58f9 129 SvGETMAGIC(coderef);
e1f52a8a 130 if (mop_get_code_info(coderef, &pkg, &name)) {
d846ade3 131 EXTEND(SP, 2);
efc98200 132 mPUSHs(newSVpv(pkg, 0));
133 mPUSHs(newSVpv(name, 0));
d846ade3 134 }
135
d846ade3 136
eaca1141 137bool
138is_class_loaded(SV* klass = &PL_sv_undef)
139INIT:
140 SvGETMAGIC(klass);
d846ade3 141
00370481 142
143
144#bool
145#is_instance_of(SV* sv, SV* klass)
146#INIT:
147# SvGETMAGIC(sv);
148# SvGETMAGIC(klass);
149#