285f3cbb33ab689876d5fbf2c1dac9971f37f3da
[gitmo/Mouse.git] / xs-src / mouse_simple_accessor.xs
1 #include "mouse.h"
2
3 static MGVTBL mouse_simple_accessor_vtbl;
4
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 }
10 */
11
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 mg to CvXSUBANY for efficiency (gfx)
28      */
29     CvXSUBANY(xsub).any_ptr = (void*)mg;
30
31     return xsub;
32 }
33
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 }
52
53
54 XS(mouse_xs_simple_reader)
55 {
56     dVAR; dXSARGS;
57     dMOUSE_self;
58     SV* const slot = MOUSE_mg_slot((MAGIC*)XSANY.any_ptr);
59     SV* value;
60
61     if (items != 1) {
62         croak("Expected exactly one argument for a reader for '%"SVf"'", slot);
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 = MOUSE_mg_slot((MAGIC*)XSANY.any_ptr);
76
77     if (items != 2) {
78         croak("Expected exactly two argument for a writer for '%"SVf"'", slot);
79     }
80
81     ST(0) = mouse_instance_set_slot(self, slot, ST(1));
82     XSRETURN(1);
83 }
84
85 XS(mouse_xs_simple_clearer)
86 {
87     dVAR; dXSARGS;
88     dMOUSE_self;
89     SV* const slot = MOUSE_mg_slot((MAGIC*)XSANY.any_ptr);
90     SV* value;
91
92     if (items != 1) {
93         croak("Expected exactly one argument for a clearer for '%"SVf"'", slot);
94     }
95
96     value = mouse_instance_delete_slot(aTHX_ self, slot);
97     ST(0) = value ? value : &PL_sv_undef;
98     XSRETURN(1);
99 }
100
101 XS(mouse_xs_simple_predicate)
102 {
103     dVAR; dXSARGS;
104     dMOUSE_self;
105     SV* const slot = MOUSE_mg_slot((MAGIC*)XSANY.any_ptr);
106
107     if (items != 1) {
108         croak("Expected exactly one argument for a predicate for '%"SVf"'", slot);
109     }
110
111     ST(0) = boolSV( mouse_instance_has_slot(self, slot) );
112     XSRETURN(1);
113 }