X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=xs-src%2FMouseAccessor.xs;h=d3d046aa01d747deae0d53995821fea5c87ce1b7;hb=6e647cac2be257e5058f04188a5b1ff8b7281069;hp=5d6bcbf42fcf19e07a1df50e5e1aa4bf782e498b;hpb=2468f1d7c798da84418ca56ba71f69b6f921996d;p=gitmo%2FMouse.git diff --git a/xs-src/MouseAccessor.xs b/xs-src/MouseAccessor.xs index 5d6bcbf..d3d046a 100644 --- a/xs-src/MouseAccessor.xs +++ b/xs-src/MouseAccessor.xs @@ -1,9 +1,10 @@ #include "mouse.h" -#define CHECK_INSTANCE(instance) STMT_START{ \ - if(!(SvROK(instance) && SvTYPE(SvRV(instance)) == SVt_PVHV)){ \ - croak("Invalid object instance"); \ - } \ +#define CHECK_INSTANCE(instance) STMT_START{ \ + assert(instance); \ + if(!(SvROK(instance) && SvTYPE(SvRV(instance)) == SVt_PVHV)){ \ + croak("Invalid object instance: '%"SVf"'", instance); \ + } \ } STMT_END @@ -13,7 +14,7 @@ static MGVTBL mouse_accessor_vtbl; /* MAGIC identity */ #define dMOUSE_self SV* const self = mouse_accessor_get_self(aTHX_ ax, items, cv) -static inline SV* +STATIC_INLINE SV* mouse_accessor_get_self(pTHX_ I32 const ax, I32 const items, CV* const cv) { if(items < 1){ croak("Too few arguments for %s", GvNAME(CvGV(cv))); @@ -88,10 +89,12 @@ mouse_push_values(pTHX_ SV* const value, U16 const flags){ PUSHs(svp ? *svp : &PL_sv_undef); } } - else if(flags & MOUSEf_TC_IS_HASHREF){ + else{ HV* hv; HE* he; + assert(flags & MOUSEf_TC_IS_HASHREF); + if(!IsHashRef(value)){ croak("Mouse-panic: Not a HASH reference"); } @@ -132,7 +135,7 @@ mouse_attr_set(pTHX_ SV* const self, MAGIC* const mg, SV* value){ value = mouse_xa_apply_type_constraint(aTHX_ MOUSE_mg_xa(mg), value, flags); } - set_slot(self, slot, value); + value = set_slot(self, slot, value); if(flags & MOUSEf_ATTR_IS_WEAK_REF){ weaken_slot(self, slot); @@ -142,14 +145,22 @@ mouse_attr_set(pTHX_ SV* const self, MAGIC* const mg, SV* value){ 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); PUTBACK; - call_sv(trigger, G_VOID | G_DISCARD); + call_sv_safe(trigger, G_VOID | G_DISCARD); /* need not SPAGAIN */ + + assert(SvTYPE(value) != SVTYPEMASK); } PUSH_VALUE(value, flags); @@ -245,30 +256,6 @@ mouse_simple_accessor_generate(pTHX_ const char* const fq_name, const char* cons return xsub; } -XS(XS_Mouse_simple_accessor) -{ - dVAR; dXSARGS; - dMOUSE_self; - MAGIC* const mg = (MAGIC*)XSANY.any_ptr; - SV* value; - - if(items == 1){ /* reader */ - value = get_slot(self, MOUSE_mg_slot(mg)); - if(!value){ - value = &PL_sv_undef; - } - } - else if(items == 2){ /* writer */ - value = set_slot(self, MOUSE_mg_slot(mg), ST(1)); - } - else { - croak("Expected exactly one or two argument for an accessor for '%"SVf"'", MOUSE_mg_slot(mg)); - } - - ST(0) = value; - XSRETURN(1); -} - XS(XS_Mouse_simple_reader) { dVAR; dXSARGS; @@ -345,24 +332,26 @@ XS(XS_Mouse_simple_predicate) SV* mouse_instance_create(pTHX_ HV* const stash) { + SV* instance; assert(stash); assert(SvTYPE(stash) == SVt_PVHV); - return sv_bless( newRV_noinc((SV*)newHV()), stash ); + instance = sv_bless( newRV_noinc((SV*)newHV()), stash ); + return sv_2mortal(instance); } SV* mouse_instance_clone(pTHX_ SV* const instance) { - HV* proto; - assert(instance); - + SV* proto; CHECK_INSTANCE(instance); - proto = newHVhv((HV*)SvRV(instance)); - return sv_bless( newRV_noinc((SV*)proto), SvSTASH(SvRV(instance)) ); + assert(SvOBJECT(SvRV(instance))); + + proto = newRV_noinc((SV*)newHVhv((HV*)SvRV(instance))); + sv_bless(proto, SvSTASH(SvRV(instance))); + return sv_2mortal(proto); } bool mouse_instance_has_slot(pTHX_ SV* const instance, SV* const slot) { - assert(instance); assert(slot); CHECK_INSTANCE(instance); return hv_exists_ent((HV*)SvRV(instance), slot, 0U); @@ -371,7 +360,6 @@ mouse_instance_has_slot(pTHX_ SV* const instance, SV* const slot) { SV* mouse_instance_get_slot(pTHX_ SV* const instance, SV* const slot) { HE* he; - assert(instance); assert(slot); CHECK_INSTANCE(instance); he = hv_fetch_ent((HV*)SvRV(instance), slot, FALSE, 0U); @@ -382,7 +370,6 @@ SV* mouse_instance_set_slot(pTHX_ SV* const instance, SV* const slot, SV* const value) { HE* he; SV* sv; - assert(instance); assert(slot); assert(value); CHECK_INSTANCE(instance); @@ -404,7 +391,6 @@ mouse_instance_delete_slot(pTHX_ SV* const instance, SV* const slot) { void mouse_instance_weaken_slot(pTHX_ SV* const instance, SV* const slot) { HE* he; - assert(instance); assert(slot); CHECK_INSTANCE(instance); he = hv_fetch_ent((HV*)SvRV(instance), slot, FALSE, 0U); @@ -412,7 +398,7 @@ mouse_instance_weaken_slot(pTHX_ SV* const instance, SV* const slot) { sv_rvweaken(HeVAL(he)); } } - + MODULE = Mouse::Meta::Method::Accessor::XS PACKAGE = Mouse::Meta::Method::Accessor::XS PROTOTYPES: DISABLE @@ -449,7 +435,7 @@ CV* _generate_clearer(klass, SV* attr, metaclass) CODE: { - SV* const slot = mcall0s(attr, "name"); + SV* const slot = mcall0(attr, mouse_name); STRLEN len; const char* const pv = SvPV_const(slot, len); RETVAL = mouse_simple_accessor_generate(aTHX_ NULL, pv, len, XS_Mouse_simple_clearer, NULL, 0); @@ -461,7 +447,7 @@ CV* _generate_predicate(klass, SV* attr, metaclass) CODE: { - SV* const slot = mcall0s(attr, "name"); + SV* const slot = mcall0(attr, mouse_name); STRLEN len; const char* const pv = SvPV_const(slot, len); RETVAL = mouse_simple_accessor_generate(aTHX_ NULL, pv, len, XS_Mouse_simple_predicate, NULL, 0);