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 )