Mouse
view release on metacpan or search on metacpan
xs-src/MouseAccessor.xs view on Meta::CPAN
static void
mouse_attr_set(pTHX_ SV* const self, MAGIC* const mg, SV* value){
U16 const flags = MOUSE_mg_flags(mg);
SV* const slot = MOUSE_mg_slot(mg);
SV* old_value;
int has_old_value = 0;
/* Store the original value before we change it so it can be
passed to the trigger */
if(flags & MOUSEf_ATTR_HAS_TRIGGER && has_slot(self, slot)){
has_old_value = 1;
old_value = sv_mortalcopy( get_slot(self, slot) );
}
if(flags & MOUSEf_ATTR_HAS_TC){
value = mouse_xa_apply_type_constraint(aTHX_ MOUSE_mg_xa(mg), value, flags);
}
value = set_slot(self, slot, value);
if(flags & MOUSEf_ATTR_IS_WEAK_REF){
weaken_slot(self, slot);
}
if(flags & MOUSEf_ATTR_HAS_TRIGGER){
SV* const trigger = mcall0s(MOUSE_mg_attribute(mg), "trigger");
dSP;
/* NOTE: triggers can remove value, so
value must be copied here,
revealed by Net::Google::DataAPI (DANJOU).
*/
value = sv_mortalcopy(value);
PUSHMARK(SP);
EXTEND(SP, 2);
PUSHs(self);
PUSHs(value);
if( has_old_value ) {
EXTEND(SP, 1);
PUSHs(old_value);
}
PUTBACK;
call_sv_safe(trigger, G_VOID | G_DISCARD);
/* need not SPAGAIN */
/* wrong assert(SvFLAGS(value) > SVTYPEMASK); can be undef/SVt_NULL */
}
mouse_push_value(aTHX_ value, flags);
}
XS(XS_Mouse_accessor)
{
dVAR; dXSARGS;
dMOUSE_self;
MAGIC* const mg = MOUSE_get_magic(aTHX_ cv, &mouse_accessor_vtbl);
SP -= items; /* PPCODE */
PUTBACK;
if(items == 1){ /* reader */
mouse_attr_get(aTHX_ self, mg);
}
else if (items == 2){ /* writer */
mouse_attr_set(aTHX_ self, mg, ST(1));
}
else{
mouse_throw_error(MOUSE_mg_attribute(mg), NULL,
"Expected exactly one or two argument for an accessor of %"SVf,
MOUSE_mg_slot(mg));
}
}
XS(XS_Mouse_reader)
{
dVAR; dXSARGS;
dMOUSE_self;
MAGIC* const mg = MOUSE_get_magic(aTHX_ cv, &mouse_accessor_vtbl);
if (items != 1) {
mouse_throw_error(MOUSE_mg_attribute(mg), NULL,
"Cannot assign a value to a read-only accessor of %"SVf,
MOUSE_mg_slot(mg));
}
SP -= items; /* PPCODE */
PUTBACK;
mouse_attr_get(aTHX_ self, mg);
}
XS(XS_Mouse_writer)
{
dVAR; dXSARGS;
dMOUSE_self;
MAGIC* const mg = MOUSE_get_magic(aTHX_ cv, &mouse_accessor_vtbl);
if (items != 2) {
mouse_throw_error(MOUSE_mg_attribute(mg), NULL,
"Too few arguments for a write-only accessor of %"SVf,
MOUSE_mg_slot(mg));
}
SP -= items; /* PPCODE */
PUTBACK;
mouse_attr_set(aTHX_ self, mg, ST(1));
}
/* simple accessors */
/*
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_simple_accessor_generate(pTHX_
const char* const fq_name, const char* const key, I32 const keylen,
XSUBADDR_t const accessor_impl, void* const dptr, I32 const dlen) {
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_accessor_vtbl, (char*)dptr, dlen);
SvREFCNT_dec(slot); /* sv_magicext() increases refcnt in mg_obj */
if(dlen == HEf_SVKEY){
SvREFCNT_dec(dptr);
}
/* NOTE:
* although we use MAGIC for gc, we also store mg to CvXSUBANY
* for efficiency (gfx)
*/
#ifndef MULTIPLICITY
CvXSUBANY(xsub).any_ptr = (void*)mg;
#endif
return xsub;
}
XS(XS_Mouse_simple_reader)
{
dVAR; dXSARGS;
dMOUSE_self;
MAGIC* const mg = MOUSE_get_magic(aTHX_ cv, &mouse_accessor_vtbl);
SV* value;
if (items != 1) {
croak("Expected exactly one argument for a reader of %"SVf,
MOUSE_mg_slot(mg));
}
value = get_slot(self, MOUSE_mg_slot(mg));
if(!value) {
( run in 0.799 second using v1.01-cache-2.11-cpan-5511b514fd6 )