Implement XS accessor generators
[gitmo/Mouse.git] / xs-src / mouse_simple_accessor.xs
CommitLineData
93540011 1#include "mouse.h"
2
43165725 3static MGVTBL mouse_simple_accessor_vtbl;
93540011 4
43165725 5/*
6static MAGIC*
7mouse_accessor_get_mg(pTHX_ CV* const xsub){
8 return moose_mg_find(aTHX_ (SV*)xsub, &mouse_simple_accessor_vtbl, MOOSEf_DIE_ON_FAIL);
93540011 9}
10*/
11
43165725 12CV*
13mouse_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:
93540011 27 * although we use MAGIC for gc, we also store mg to CvXSUBANY for efficiency (gfx)
43165725 28 */
93540011 29 CvXSUBANY(xsub).any_ptr = (void*)mg;
43165725 30
31 return xsub;
32}
93540011 33
43165725 34SV*
35mouse_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;
93540011 51}
43165725 52
53
54XS(mouse_xs_simple_reader)
55{
93540011 56 dVAR; dXSARGS;
43165725 57 dMOUSE_self;
93540011 58 SV* const slot = MOUSE_mg_slot((MAGIC*)XSANY.any_ptr);
43165725 59 SV* value;
60
61 if (items != 1) {
93540011 62 croak("Expected exactly one argument for a reader for '%"SVf"'", slot);
43165725 63 }
64
65 value = mouse_instance_get_slot(self, slot);
66 ST(0) = value ? value : &PL_sv_undef;
67 XSRETURN(1);
68}
69
70
71XS(mouse_xs_simple_writer)
72{
73 dVAR; dXSARGS;
74 dMOUSE_self;
93540011 75 SV* const slot = MOUSE_mg_slot((MAGIC*)XSANY.any_ptr);
76
43165725 77 if (items != 2) {
93540011 78 croak("Expected exactly two argument for a writer for '%"SVf"'", slot);
43165725 79 }
80
81 ST(0) = mouse_instance_set_slot(self, slot, ST(1));
82 XSRETURN(1);
83}
84
93540011 85XS(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}
43165725 100
101XS(mouse_xs_simple_predicate)
102{
103 dVAR; dXSARGS;
104 dMOUSE_self;
93540011 105 SV* const slot = MOUSE_mg_slot((MAGIC*)XSANY.any_ptr);
106
43165725 107 if (items != 1) {
93540011 108 croak("Expected exactly one argument for a predicate for '%"SVf"'", slot);
43165725 109 }
110
111 ST(0) = boolSV( mouse_instance_has_slot(self, slot) );
112 XSRETURN(1);
93540011 113}