Sub-Attribute
view release on metacpan or search on metacpan
Attribute.xs view on Meta::CPAN
FREETMPS;
}
LEAVE;
av_clear(MY_CXT.queue);
return 0;
}
static SV*
sa_newSVsv_share(pTHX_ SV* const sv){
STRLEN len;
const char* const pv = SvPV_const(sv, len);
return newSVpvn_share(pv, len, 0U);
}
static MGVTBL hook_scope_vtbl = {
NULL, /* get */
NULL, /* set */
NULL, /* len */
NULL, /* clear */
sa_process_queue, /* free */
NULL, /* copy */
NULL, /* dup */
#ifdef MGf_LOCAL
NULL, /* local */
#endif
};
static MGVTBL attr_handler_vtbl;
MODULE = Sub::Attribute PACKAGE = Sub::Attribute
PROTOTYPES: DISABLE
BOOT:
{
const char* const d = PerlEnv_getenv("SUB_ATTRIBUTE_DEBUG");
MY_CXT_INIT;
MY_CXT.queue = newAV();
MY_CXT.debug = (d && *d != '\0' && strNE(d, "0"));
}
void
CLONE(...)
CODE:
MY_CXT_CLONE;
MY_CXT.queue = newAV();
PERL_UNUSED_VAR(items);
void
MODIFY_CODE_ATTRIBUTES(SV* klass, CV* code, ...)
PREINIT:
dMY_CXT;
HV* const hinthv = GvHVn(PL_hintgv);
HV* stash;
MAGIC* mg;
I32 i;
PPCODE:
mg = mg_find_by_vtbl((SV*)hinthv, &hook_scope_vtbl);
if(!mg){
sv_magicext((SV*)hinthv, NULL, PERL_MAGIC_ext, &hook_scope_vtbl, NULL, 0);
PL_hints |= HINT_LOCALIZE_HH;
}
stash = gv_stashsv(klass, TRUE);
klass = sa_newSVsv_share(aTHX_ klass);
for(i = 2; i < items; i++){
STRLEN attrlen;
const char* const attr = SvPV_const(ST(i), attrlen);
const char* data = strchr(attr, '(');
STRLEN datalen = attrlen - (data - attr) - 2;
STRLEN const namelen = data ? (STRLEN)(data - attr) : attrlen;
GV* meth;
if(data){
data++; /* skip '(' */
while(isSPACE(*data)){
data++;
datalen--;
}
while(isSPACE(data[datalen-1])){
datalen--;
}
}
if(strnEQ(attr, META_ATTR, sizeof(META_ATTR))){ /* meta attribute */
if(!MgFind((SV*)code, &attr_handler_vtbl)){
sv_magicext(
(SV*)code,
NULL, PERL_MAGIC_ext, &attr_handler_vtbl,
PACKAGE, 0
);
if(MY_CXT.debug){
warn("install attribute handler %"SVf"\n", PL_subname);
}
}
continue;
}
meth = gv_fetchmeth_autoload(stash, attr, namelen, 0 /* special zero */);
if(meth && MgFind((SV*)GvCV(meth), &attr_handler_vtbl)){
AV* const handler = newAV();
av_store(handler, SA_METHOD, SvREFCNT_inc_simple_NN((SV*)GvCV(meth)));
av_store(handler, SA_KLASS, SvREFCNT_inc_simple_NN(klass));
av_store(handler, SA_CODE, newRV_inc((SV*)code));
av_store(handler, SA_NAME, newSVpvn_share(attr, namelen, 0U));
if(data){
av_store(handler, SA_DATA, newSVpvn(data, datalen));
}
av_push(MY_CXT.queue, (SV*)handler);
}
else{
if(MY_CXT.debug){
warn("ignore unrecognized attribute :%"SVf"\n", ST(i));
( run in 1.593 second using v1.01-cache-2.11-cpan-5511b514fd6 )