X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=xs-src%2FMouseAccessor.xs;h=1dad5e65d90b05bab94a1065337fe1d684eb119c;hb=3a2ccd7713de9817b51e135f9e7c5b1b91ce8772;hp=ddd6333887b2a19766874c9f76439c94f69d9c42;hpb=542f20adaffff1539921032f24c8c1893080fc8c;p=gitmo%2FMouse.git diff --git a/xs-src/MouseAccessor.xs b/xs-src/MouseAccessor.xs index ddd6333..1dad5e6 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 @@ -28,7 +29,7 @@ mouse_accessor_get_self(pTHX_ I32 const ax, I32 const items, CV* const cv) { CV* -mouse_instantiate_xs_accessor(pTHX_ SV* const attr, XSUBADDR_t const accessor_impl){ +mouse_accessor_generate(pTHX_ SV* const attr, XSUBADDR_t const accessor_impl){ AV* const xa = mouse_get_xa(aTHX_ attr); CV* xsub; MAGIC* mg; @@ -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); @@ -221,7 +232,7 @@ mouse_accessor_get_mg(pTHX_ CV* const xsub){ */ CV* -mouse_install_simple_accessor(pTHX_ const char* const fq_name, const char* const key, I32 const keylen, XSUBADDR_t const accessor_impl, void* const dptr, I32 const dlen){ +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; @@ -245,37 +256,6 @@ mouse_install_simple_accessor(pTHX_ const char* const fq_name, const char* const 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) { - if(MOUSE_mg_ptr(mg)){ - /* the default value must be a SV */ - assert(MOUSE_mg_len(mg) == HEf_SVKEY); - value = (SV*)MOUSE_mg_ptr(mg); - } - else{ - 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; @@ -288,7 +268,18 @@ XS(XS_Mouse_simple_reader) } value = get_slot(self, MOUSE_mg_slot(mg)); - ST(0) = value ? value : &PL_sv_undef; + if(!value) { + if(MOUSE_mg_ptr(mg)){ + /* the default value must be a SV */ + assert(MOUSE_mg_len(mg) == HEf_SVKEY); + value = (SV*)MOUSE_mg_ptr(mg); + } + else{ + value = &PL_sv_undef; + } + } + + ST(0) = value; XSRETURN(1); } @@ -341,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); @@ -367,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); @@ -378,13 +370,13 @@ 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); he = hv_fetch_ent((HV*)SvRV(instance), slot, TRUE, 0U); sv = HeVAL(he); - sv_setsv_mg(sv, value); + sv_setsv(sv, value); + SvSETMAGIC(sv); return sv; } @@ -399,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); @@ -407,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 @@ -417,7 +408,7 @@ CV* _generate_accessor(klass, SV* attr, metaclass) CODE: { - RETVAL = mouse_instantiate_xs_accessor(aTHX_ attr, XS_Mouse_accessor); + RETVAL = mouse_accessor_generate(aTHX_ attr, XS_Mouse_accessor); } OUTPUT: RETVAL @@ -426,7 +417,7 @@ CV* _generate_reader(klass, SV* attr, metaclass) CODE: { - RETVAL = mouse_instantiate_xs_accessor(aTHX_ attr, XS_Mouse_reader); + RETVAL = mouse_accessor_generate(aTHX_ attr, XS_Mouse_reader); } OUTPUT: RETVAL @@ -435,7 +426,7 @@ CV* _generate_writer(klass, SV* attr, metaclass) CODE: { - RETVAL = mouse_instantiate_xs_accessor(aTHX_ attr, XS_Mouse_writer); + RETVAL = mouse_accessor_generate(aTHX_ attr, XS_Mouse_writer); } OUTPUT: RETVAL @@ -444,10 +435,10 @@ 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_install_simple_accessor(aTHX_ NULL, pv, len, XS_Mouse_simple_clearer, NULL, 0); + RETVAL = mouse_simple_accessor_generate(aTHX_ NULL, pv, len, XS_Mouse_simple_clearer, NULL, 0); } OUTPUT: RETVAL @@ -456,10 +447,10 @@ 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_install_simple_accessor(aTHX_ NULL, pv, len, XS_Mouse_simple_predicate, NULL, 0); + RETVAL = mouse_simple_accessor_generate(aTHX_ NULL, pv, len, XS_Mouse_simple_predicate, NULL, 0); } OUTPUT: RETVAL