Move accessors into XS
[gitmo/Mouse.git] / xs-src / mouse_simple_accessor.xs
1 #include "mouse.h"\r
2 \r
3 static MGVTBL mouse_simple_accessor_vtbl;
4 \r\r
5 /*
6 static MAGIC*
7 mouse_accessor_get_mg(pTHX_ CV* const xsub){
8     return moose_mg_find(aTHX_ (SV*)xsub, &mouse_simple_accessor_vtbl, MOOSEf_DIE_ON_FAIL);
9 }\r
10 */\r
11 \r
12 CV*
13 mouse_install_simple_accessor(pTHX_ const char* const fq_name, const char* const key, I32 const keylen, XSUBADDR_t const accessor_impl){
14     CV* const xsub = newXS((char*)fq_name, accessor_impl, __FILE__);
15     SV* const slot = newSVpvn_share(key, keylen, 0U);
16     MAGIC* mg;
17
18     if(!fq_name){
19         /* anonymous xsubs need sv_2mortal */
20         sv_2mortal((SV*)xsub);
21     }
22
23     mg = sv_magicext((SV*)xsub, slot, PERL_MAGIC_ext, &mouse_simple_accessor_vtbl, NULL, 0);
24     SvREFCNT_dec(slot); /* sv_magicext() increases refcnt in mg_obj */
25
26     /* NOTE:
27      * although we use MAGIC for gc, we also store slot to CvXSUBANY slot for efficiency (gfx)
28      */
29     CvXSUBANY(xsub).any_ptr = (void*)slot;
30
31     return xsub;
32 }
33 \r
34 SV*
35 mouse_accessor_get_self(pTHX_ I32 const ax, I32 const items, CV* const cv) {
36     SV* self;
37
38     if(items < 1){
39         croak("Too few arguments for %s", GvNAME(CvGV(cv)));
40     }
41
42     /* NOTE: If self has GETMAGIC, $self->accessor will invoke GETMAGIC
43      *       before calling methods, so SvGETMAGIC(self) is not necessarily needed here.
44      */
45
46     self = ST(0);
47     if(!IsObject(self)){
48         croak("Cant call %s as a class method", GvNAME(CvGV(cv)));
49     }
50     return self;
51 }\r
52
53
54 XS(mouse_xs_simple_reader)
55 {
56     dVAR; dXSARGS;\r
57     dMOUSE_self;
58     SV* const slot = (SV*)XSANY.any_ptr;
59     SV* value;
60
61     if (items != 1) {
62         croak("Expected exactly one argument");
63     }
64
65     value = mouse_instance_get_slot(self, slot);
66     ST(0) = value ? value : &PL_sv_undef;
67     XSRETURN(1);
68 }
69
70
71 XS(mouse_xs_simple_writer)
72 {
73     dVAR; dXSARGS;
74     dMOUSE_self;
75     SV* const slot = (SV*)XSANY.any_ptr;
76 \r
77     if (items != 2) {
78         croak("Expected exactly two argument");
79     }
80
81     ST(0) = mouse_instance_set_slot(self, slot, ST(1));
82     XSRETURN(1);
83 }
84
85
86 XS(mouse_xs_simple_predicate)
87 {
88     dVAR; dXSARGS;
89     dMOUSE_self;
90     SV* const slot = (SV*)XSANY.any_ptr;
91 \r
92     if (items != 1) {
93         croak("Expected exactly one argument");
94     }
95
96     ST(0) = boolSV( mouse_instance_has_slot(self, slot) );
97     XSRETURN(1);
98 }\r