5da40717a9b723441de9445159eb1b1fe947fcef
[gitmo/Mouse.git] / xs-src / mouse_util.xs
1 #include "mouse.h"
2
3 /* equivalent to "blessed($x) && $x->isa($klass)" */
4 bool
5 mouse_is_instance_of(pTHX_ SV* const sv, SV* const klass){
6     assert(sv);
7     assert(klass);
8
9     if(IsObject(sv) && SvOK(klass)){
10         bool ok;
11
12         ENTER;
13         SAVETMPS;
14
15         ok = SvTRUEx(mcall1s(sv, "isa", klass));
16
17         FREETMPS;
18         LEAVE;
19
20         return ok;
21     }
22
23     return FALSE;
24 }
25
26
27 bool
28 mouse_is_class_loaded(pTHX_ SV * const klass){
29     HV *stash;
30     GV** gvp;
31     HE* he;
32
33     if (!(SvPOKp(klass) && SvCUR(klass))) { /* XXX: SvPOK does not work with magical scalars */
34         return FALSE;
35     }
36
37     stash = gv_stashsv(klass, FALSE);
38     if (!stash) {
39         return FALSE;
40     }
41
42     if (( gvp = (GV**)hv_fetchs(stash, "VERSION", FALSE) )) {
43         if(isGV(*gvp) && GvSV(*gvp) && SvOK(GvSV(*gvp))){
44             return TRUE;
45         }
46     }
47
48     if (( gvp = (GV**)hv_fetchs(stash, "ISA", FALSE) )) {
49         if(isGV(*gvp) && GvAV(*gvp) && av_len(GvAV(*gvp)) != -1){
50             return TRUE;
51         }
52     }
53
54     hv_iterinit(stash);
55     while(( he = hv_iternext(stash) )){
56         GV* const gv = (GV*)HeVAL(he);
57
58         if(isGV(gv)){
59             if(GvCVu(gv)){
60                 return TRUE;
61             }
62         }
63         else if(SvOK(gv)){
64             return TRUE;
65         }
66     }
67     return FALSE;
68 }
69
70
71 SV *
72 mouse_call0 (pTHX_ SV *const self, SV *const method)
73 {
74     dSP;
75     SV *ret;
76
77     PUSHMARK(SP);
78     XPUSHs(self);
79     PUTBACK;
80
81     call_sv(method, G_SCALAR | G_METHOD);
82
83     SPAGAIN;
84     ret = POPs;
85     PUTBACK;
86
87     return ret;
88 }
89
90 SV *
91 mouse_call1 (pTHX_ SV *const self, SV *const method, SV* const arg1)
92 {
93     dSP;
94     SV *ret;
95
96     PUSHMARK(SP);
97     EXTEND(SP, 2);
98     PUSHs(self);
99     PUSHs(arg1);
100     PUTBACK;
101
102     call_sv(method, G_SCALAR | G_METHOD);
103
104     SPAGAIN;
105     ret = POPs;
106     PUTBACK;
107
108     return ret;
109 }
110
111 MAGIC*
112 mouse_mg_find(pTHX_ SV* const sv, const MGVTBL* const vtbl, I32 const flags){
113     MAGIC* mg;
114
115     assert(sv != NULL);
116     for(mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic){
117         if(mg->mg_virtual == vtbl){
118             return mg;
119         }
120     }
121
122     if(flags & MOUSEf_DIE_ON_FAIL){
123         croak("mouse_mg_find: no MAGIC found for %"SVf, sv_2mortal(newRV_inc(sv)));
124     }
125     return NULL;
126 }