Object-Pad
view release on metacpan or search on metacpan
lib/Object/Pad.xs view on Meta::CPAN
dump_fieldmeta(aTHX_ ctx, fieldmeta);
}
for(i = 0; i < av_count(classmeta->direct_methods); i++) {
MethodMeta *methodmeta = MUST_METHODMETA(AvARRAY(classmeta->direct_methods)[i]);
dump_methodmeta(aTHX_ ctx, methodmeta);
}
HV *parammap;
if((parammap = classmeta->parammap)) {
hv_iterinit(parammap);
HE *iter;
while((iter = hv_iternext(parammap))) {
ParamMeta *parammeta = MUST_PARAMMETA(HeVAL(iter));
dump_parammeta(aTHX_ ctx, parammeta);
}
}
switch(classmeta->type) {
case METATYPE_CLASS:
for(i = 0; i < av_count(classmeta->cls.direct_roles); i++) {
RoleEmbedding *embedding = MUST_ROLEEMBEDDING(AvARRAY(classmeta->cls.direct_roles)[i]);
dump_roleembedding(aTHX_ ctx, embedding);
}
break;
case METATYPE_ROLE:
/* No need to dump the values of role.applied_classes because any class
* they're applied to will have done that already */
break;
}
}
static int dumppackage_class(pTHX_ DMDContext *ctx, const SV *sv)
{
int ret = 0;
ClassMeta *meta = MUST_CLASSMETA(SvUV((SV *)sv));
dump_classmeta(aTHX_ ctx, meta);
ret += DMD_ANNOTATE_SV(sv, (SV *)meta, "the Object::Pad class");
return ret;
}
#endif
/*********************
* Custom FieldHooks *
*********************/
struct CustomFieldHookData
{
SV *apply_cb;
};
static bool fieldhook_custom_apply(pTHX_ FieldMeta *fieldmeta, SV *value, SV **hookdata_ptr, void *_funcdata)
{
struct CustomFieldHookData *funcdata = _funcdata;
SV *cb;
if((cb = funcdata->apply_cb)) {
dSP;
ENTER;
SAVETMPS;
SV *fieldmetasv = sv_newmortal();
sv_setref_uv(fieldmetasv, "Object::Pad::MOP::Field", PTR2UV(fieldmeta));
PUSHMARK(SP);
EXTEND(SP, 2);
PUSHs(fieldmetasv);
PUSHs(value);
PUTBACK;
call_sv(cb, G_SCALAR);
SPAGAIN;
SV *ret = POPs;
*hookdata_ptr = SvREFCNT_inc(ret);
FREETMPS;
LEAVE;
}
return TRUE;
}
/* internal function shared by various *.c files */
void ObjectPad__need_PLparser(pTHX)
{
if(!PL_parser) {
/* We need to generate just enough of a PL_parser to keep newSTATEOP()
* happy, otherwise it will SIGSEGV (RT133258)
*/
SAVEVPTR(PL_parser);
Newxz(PL_parser, 1, yy_parser);
SAVEFREEPV(PL_parser);
PL_parser->copline = NOLINE;
#if HAVE_PERL_VERSION(5, 20, 0)
PL_parser->preambling = NOLINE;
#endif
}
}
/* used by XSUB deconstruct_object */
#define deconstruct_object_class(fieldstore, classmeta, offset) S_deconstruct_object_class(aTHX_ fieldstore, classmeta, offset)
static U32 S_deconstruct_object_class(pTHX_ SV *fieldstore, ClassMeta *classmeta, FIELDOFFSET offset)
{
dSP;
U32 retcount = 0;
AV *fields = classmeta->fields;
U32 nfields = av_count(fields);
EXTEND(SP, nfields * 2);
SV **fieldsvs = fieldstore_fields(fieldstore);
FIELDOFFSET i;
for(i = 0; i < nfields; i++) {
FieldMeta *fieldmeta = MUST_FIELDMETA(AvARRAY(fields)[i]);
lib/Object/Pad.xs view on Meta::CPAN
/* Handy functions for MOP wrapper methods */
#define MUST_CLASSMETA_FROM_RV(self) S_must_classmeta_from_rv(aTHX_ self)
static ClassMeta *S_must_classmeta_from_rv(pTHX_ SV *self)
{
if(!(SvROK(self) && sv_derived_from(self, "Object::Pad::MOP::Class")))
croak("Expected an Object::Pad::MOP::Class instance");
return MUST_CLASSMETA(NUM2PTR(ClassMeta *, SvUV(SvRV(self))));
}
#define MUST_FIELDMETA_FROM_RV(self) S_must_fieldmeta_from_rv(aTHX_ self)
static FieldMeta *S_must_fieldmeta_from_rv(pTHX_ SV *self)
{
if(!(SvROK(self) && sv_derived_from(self, "Object::Pad::MOP::Field")))
croak("Expected an Object::Pad::MOP::Field instance");
return MUST_FIELDMETA(NUM2PTR(FieldMeta *, SvUV(SvRV(self))));
}
#define MUST_METHODMETA_FROM_RV(self) S_must_methodmeta_from_rv(aTHX_ self)
static MethodMeta *S_must_methodmeta_from_rv(pTHX_ SV *self)
{
if(!(SvROK(self) && sv_derived_from(self, "Object::Pad::MOP::Method")))
croak("Expected an Object::Pad::MOP::Method instance");
return MUST_METHODMETA(NUM2PTR(MethodMeta *, SvUV(SvRV(self))));
}
MODULE = Object::Pad PACKAGE = Object::Pad::MOP::Class
INCLUDE: mop-class.xsi
MODULE = Object::Pad PACKAGE = Object::Pad::MOP::Method
INCLUDE: mop-method.xsi
MODULE = Object::Pad PACKAGE = Object::Pad::MOP::Field
INCLUDE: mop-field.xsi
MODULE = Object::Pad PACKAGE = Object::Pad::MOP::FieldAttr
void
register(class, name, ...)
SV *class
SV *name
CODE:
{
PERL_UNUSED_VAR(class);
dKWARG(2);
{
if(!cophh_exists_pvs(CopHINTHASH_get(PL_curcop), "Object::Pad/experimental(custom_field_attr)", 0))
Perl_ck_warner(aTHX_ packWARN(WARN_EXPERIMENTAL),
"Object::Pad::MOP::FieldAttr is experimental and may be changed or removed without notice");
}
struct FieldHookFuncs funcs = {};
struct CustomFieldHookData funcdata = {};
funcs.ver = OBJECTPAD_ABIVERSION;
funcs.apply = &fieldhook_custom_apply;
static const char *args[] = {
"permit_hintkey",
"apply",
"no_value",
"must_value",
NULL,
};
while(KWARG_NEXT(args)) {
switch(kwarg) {
case 0: /* permit_hintkey */
funcs.permit_hintkey = SvPV_nolen(kwval);
break;
case 1: /* apply */
funcdata.apply_cb = kwval;
break;
case 2: /* no_value */
if(SvTRUE(kwval))
funcs.flags |= OBJECTPAD_FLAG_ATTR_NO_VALUE;
break;
case 3: /* must_value */
if(SvTRUE(kwval))
funcs.flags |= OBJECTPAD_FLAG_ATTR_MUST_VALUE;
break;
}
}
if((funcs.flags & OBJECTPAD_FLAG_ATTR_NO_VALUE) &&
(funcs.flags & OBJECTPAD_FLAG_ATTR_MUST_VALUE))
croak("Cannot register a FieldAttr with both 'no_value' and 'must_value'");
struct FieldHookFuncs *_funcs;
Newxz(_funcs, 1, struct FieldHookFuncs);
Copy(&funcs, _funcs, 1, struct FieldHookFuncs);
if(_funcs->permit_hintkey)
_funcs->permit_hintkey = savepv(_funcs->permit_hintkey);
struct CustomFieldHookData *_funcdata;
Newxz(_funcdata, 1, struct CustomFieldHookData);
Copy(&funcdata, _funcdata, 1, struct CustomFieldHookData);
if(_funcdata->apply_cb)
_funcdata->apply_cb = newSVsv(_funcdata->apply_cb);
register_field_attribute(savepv(SvPV_nolen(name)), _funcs, _funcdata);
}
MODULE = Object::Pad PACKAGE = Object::Pad::MetaFunctions
SV *
metaclass(SV *obj)
CODE:
{
if(!SvROK(obj) || !SvOBJECT(SvRV(obj)))
croak("Expected an object reference to metaclass");
HV *stash = SvSTASH(SvRV(obj));
GV **gvp = (GV **)hv_fetchs(stash, "META", 0);
if(!gvp)
croak("Unable to find ClassMeta for %" HEKf, HEKfARG(HvNAME_HEK(stash)));
RETVAL = newSVsv(GvSV(*gvp));
}
OUTPUT:
RETVAL
void
deconstruct_object(SV *obj)
PPCODE:
{
if(!SvROK(obj) || !SvOBJECT(SvRV(obj)))
croak("Expected an object reference to deconstruct_object");
ClassMeta *classmeta = mop_get_class_for_stash(SvSTASH(SvRV(obj)));
SV *fieldstore = get_obj_fieldstore(obj, classmeta->repr, true);
U32 retcount = 0;
PUSHs(sv_mortalcopy(classmeta->name));
retcount++;
PUTBACK;
while(classmeta) {
retcount += deconstruct_object_class(fieldstore, classmeta, 0);
AV *roles = classmeta->cls.direct_roles;
U32 nroles = av_count(roles);
for(U32 i = 0; i < nroles; i++) {
RoleEmbedding *embedding = MUST_ROLEEMBEDDING(AvARRAY(roles)[i]);
retcount += deconstruct_object_class(fieldstore, embedding->rolemeta, embedding->offset);
}
classmeta = classmeta->cls.supermeta;
}
SPAGAIN;
XSRETURN(retcount);
}
SV *
ref_field(SV *fieldname, SV *obj)
( run in 1.770 second using v1.01-cache-2.11-cpan-39bf76dae61 )