X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=xs-src%2Fmouse_simple_accessor.xs;fp=xs-src%2Fmouse_simple_accessor.xs;h=cf835fb2cff023828fbd1017219f8c951be49477;hb=431657256f423bda264c0cb76c28de72fd879b20;hp=0000000000000000000000000000000000000000;hpb=6e64f8097e17ea8b7b950fee35046dfa43a5b4f3;p=gitmo%2FMouse.git diff --git a/xs-src/mouse_simple_accessor.xs b/xs-src/mouse_simple_accessor.xs new file mode 100644 index 0000000..cf835fb --- /dev/null +++ b/xs-src/mouse_simple_accessor.xs @@ -0,0 +1,98 @@ +#include "mouse.h" + +static MGVTBL mouse_simple_accessor_vtbl; + +/* +static MAGIC* +mouse_accessor_get_mg(pTHX_ CV* const xsub){ + return moose_mg_find(aTHX_ (SV*)xsub, &mouse_simple_accessor_vtbl, MOOSEf_DIE_ON_FAIL); +} +*/ + +CV* +mouse_install_simple_accessor(pTHX_ const char* const fq_name, const char* const key, I32 const keylen, XSUBADDR_t const accessor_impl){ + CV* const xsub = newXS((char*)fq_name, accessor_impl, __FILE__); + SV* const slot = newSVpvn_share(key, keylen, 0U); + MAGIC* mg; + + if(!fq_name){ + /* anonymous xsubs need sv_2mortal */ + sv_2mortal((SV*)xsub); + } + + mg = sv_magicext((SV*)xsub, slot, PERL_MAGIC_ext, &mouse_simple_accessor_vtbl, NULL, 0); + SvREFCNT_dec(slot); /* sv_magicext() increases refcnt in mg_obj */ + + /* NOTE: + * although we use MAGIC for gc, we also store slot to CvXSUBANY slot for efficiency (gfx) + */ + CvXSUBANY(xsub).any_ptr = (void*)slot; + + return xsub; +} + +SV* +mouse_accessor_get_self(pTHX_ I32 const ax, I32 const items, CV* const cv) { + SV* self; + + if(items < 1){ + croak("Too few arguments for %s", GvNAME(CvGV(cv))); + } + + /* NOTE: If self has GETMAGIC, $self->accessor will invoke GETMAGIC + * before calling methods, so SvGETMAGIC(self) is not necessarily needed here. + */ + + self = ST(0); + if(!IsObject(self)){ + croak("Cant call %s as a class method", GvNAME(CvGV(cv))); + } + return self; +} + + +XS(mouse_xs_simple_reader) +{ + dVAR; dXSARGS; + dMOUSE_self; + SV* const slot = (SV*)XSANY.any_ptr; + SV* value; + + if (items != 1) { + croak("Expected exactly one argument"); + } + + value = mouse_instance_get_slot(self, slot); + ST(0) = value ? value : &PL_sv_undef; + XSRETURN(1); +} + + +XS(mouse_xs_simple_writer) +{ + dVAR; dXSARGS; + dMOUSE_self; + SV* const slot = (SV*)XSANY.any_ptr; + + if (items != 2) { + croak("Expected exactly two argument"); + } + + ST(0) = mouse_instance_set_slot(self, slot, ST(1)); + XSRETURN(1); +} + + +XS(mouse_xs_simple_predicate) +{ + dVAR; dXSARGS; + dMOUSE_self; + SV* const slot = (SV*)XSANY.any_ptr; + + if (items != 1) { + croak("Expected exactly one argument"); + } + + ST(0) = boolSV( mouse_instance_has_slot(self, slot) ); + XSRETURN(1); +}