#endif /* VMG_THREADSAFE */
+#define vmg_wizard_id(W) PTR2IV(vmg_vtable_vtbl((W)->vtable))
+
/* --- Wizard SV objects --------------------------------------------------- */
STATIC int vmg_wizard_sv_free(pTHX_ SV *sv, MAGIC *mg) {
return wiz;
}
-STATIC const SV *vmg_wizard_sv_validate(pTHX_ const SV *wiz) {
-#define vmg_wizard_sv_validate(W) vmg_wizard_sv_validate(aTHX_ (W))
- if (SvROK(wiz)) {
- wiz = SvRV_const(wiz);
#if VMG_THREADSAFE
- if (SvTYPE(wiz) >= SVt_PVMG && SvMAGIC(wiz))
-#else
- if (SvIOK(wiz))
-#endif
- return wiz;
- }
-
- croak(vmg_invalid_wiz);
- /* Not reached */
- return NULL;
-}
-#if VMG_THREADSAFE
+#define vmg_sv_has_wizard_type(S) (SvTYPE(S) >= SVt_PVMG)
-STATIC const vmg_wizard *vmg_wizard_from_sv(const SV *wiz) {
+STATIC const vmg_wizard *vmg_wizard_from_sv_nocheck(const SV *wiz) {
MAGIC *mg;
for (mg = SvMAGIC(wiz); mg; mg = mg->mg_moremagic) {
return NULL;
}
-#define vmg_wizard_from_sv(W) vmg_wizard_from_sv((const SV *) (W))
+#else /* VMG_THREADSAFE */
-#define vmg_wizard_sv_id(W) PTR2IV(vmg_vtable_vtbl(vmg_wizard_from_sv(W)->vtable))
+#define vmg_sv_has_wizard_type(S) SvIOK(S)
-#else
+#define vmg_wizard_from_sv_nocheck(W) INT2PTR(const vmg_wizard *, SvIVX(W))
-#define vmg_wizard_sv_id(W) SvIVX((const SV *) (W))
+#endif /* !VMG_THREADSAFE */
-#define vmg_wizard_from_sv(W) INT2PTR(const vmg_wizard *, vmg_wizard_sv_id(W))
+#define vmg_wizard_from_sv(W) (vmg_sv_has_wizard_type(W) ? vmg_wizard_from_sv_nocheck(W) : NULL)
-#endif
+STATIC const vmg_wizard *vmg_wizard_from_mg(const MAGIC *mg) {
+ if (mg->mg_type == PERL_MAGIC_ext && mg->mg_len == HEf_SVKEY) {
+ SV *sv = (SV *) mg->mg_ptr;
+
+ if (vmg_sv_has_wizard_type(sv))
+ return vmg_wizard_from_sv_nocheck(sv);
+ }
+
+ return NULL;
+}
+
+#define vmg_wizard_from_mg_nocheck(M) vmg_wizard_from_sv_nocheck((const SV *) (M)->mg_ptr)
/* --- User-level functions implementation --------------------------------- */
-STATIC const MAGIC *vmg_find(const SV *sv, const SV *wiz) {
- const MAGIC *mg, *moremagic;
+STATIC const MAGIC *vmg_find(const SV *sv, const vmg_wizard *w) {
+ const MAGIC *mg;
IV wid;
if (SvTYPE(sv) < SVt_PVMG)
return NULL;
- wid = vmg_wizard_sv_id(wiz);
- for (mg = SvMAGIC(sv); mg; mg = moremagic) {
- moremagic = mg->mg_moremagic;
- if (mg->mg_type == PERL_MAGIC_ext && mg->mg_private == SIG_WIZ) {
- IV zid = vmg_wizard_sv_id(mg->mg_ptr);
- if (zid == wid)
- return mg;
- }
+ wid = vmg_wizard_id(w);
+
+ for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
+ const vmg_wizard *z = vmg_wizard_from_mg(mg);
+
+ if (z && vmg_wizard_id(z) == wid)
+ return mg;
}
return NULL;
return nsv;
}
-STATIC SV *vmg_data_get(pTHX_ SV *sv, const SV *wiz) {
+STATIC SV *vmg_data_get(pTHX_ SV *sv, const vmg_wizard *w) {
#define vmg_data_get(S, W) vmg_data_get(aTHX_ (S), (W))
- const MAGIC *mg = vmg_find(sv, wiz);
+ const MAGIC *mg = vmg_find(sv, w);
+
return mg ? mg->mg_obj : NULL;
}
}
#endif /* VMG_UVAR */
-STATIC UV vmg_cast(pTHX_ SV *sv, const SV *wiz, SV **args, I32 items) {
-#define vmg_cast(S, W, A, I) vmg_cast(aTHX_ (S), (W), (A), (I))
- const vmg_wizard *w;
+STATIC UV vmg_cast(pTHX_ SV *sv, const vmg_wizard *w, const SV *wiz, SV **args, I32 items) {
+#define vmg_cast(S, W, WIZ, A, I) vmg_cast(aTHX_ (S), (W), (WIZ), (A), (I))
MAGIC *mg;
SV *data;
U32 oldgmg;
- if (vmg_find(sv, wiz))
+ if (vmg_find(sv, w))
return 1;
- w = vmg_wizard_from_sv(wiz);
oldgmg = SvGMAGICAL(sv);
data = (w->cb_data) ? vmg_data_new(w->cb_data, sv, args, items) : NULL;
return 1;
}
-STATIC UV vmg_dispell(pTHX_ SV *sv, const SV *wiz) {
+STATIC UV vmg_dispell(pTHX_ SV *sv, const vmg_wizard *w) {
#define vmg_dispell(S, W) vmg_dispell(aTHX_ (S), (W))
#if VMG_UVAR
U32 uvars = 0;
#endif /* VMG_UVAR */
MAGIC *mg, *prevmagic, *moremagic = NULL;
- IV wid = vmg_wizard_sv_id(wiz);
+ IV wid = vmg_wizard_id(w);
if (SvTYPE(sv) < SVt_PVMG)
return 0;
for (prevmagic = NULL, mg = SvMAGIC(sv); mg; prevmagic = mg, mg = moremagic) {
+ const vmg_wizard *z;
+
moremagic = mg->mg_moremagic;
- if (mg->mg_type == PERL_MAGIC_ext && mg->mg_private == SIG_WIZ) {
+
+ z = vmg_wizard_from_mg(mg);
+ if (z) {
+ IV zid = vmg_wizard_id(z);
+
#if VMG_UVAR
- const vmg_wizard *z = vmg_wizard_from_sv(mg->mg_ptr);
-#endif /* VMG_UVAR */
- IV zid = vmg_wizard_sv_id(mg->mg_ptr);
if (zid == wid) {
-#if VMG_UVAR
/* If the current has no uvar, short-circuit uvar deletion. */
uvars = z->uvar ? (uvars + 1) : 0;
-#endif /* VMG_UVAR */
break;
-#if VMG_UVAR
} else if (z->uvar) {
++uvars;
/* We can't break here since we need to find the ext magic to delete. */
-#endif /* VMG_UVAR */
}
+#else /* VMG_UVAR */
+ if (zid == wid)
+ break;
+#endif /* !VMG_UVAR */
}
}
if (!mg)
/* mg was the first ext magic in the chain that had uvar */
for (mg = moremagic; mg; mg = mg->mg_moremagic) {
- if (mg->mg_type == PERL_MAGIC_ext && mg->mg_private == SIG_WIZ) {
- const vmg_wizard *z = vmg_wizard_from_sv(mg->mg_ptr);
- if (z->uvar) {
- ++uvars;
- break;
- }
+ const vmg_wizard *z = vmg_wizard_from_mg(mg);
+
+ if (z && z->uvar) {
+ ++uvars;
+ break;
}
}
vmg_cb_call(aTHX_ (I), VMG_CB_FLAGS((OI), 3), (S), (A1), (A2), (A3))
STATIC int vmg_svt_get(pTHX_ SV *sv, MAGIC *mg) {
- const vmg_wizard *w = vmg_wizard_from_sv(mg->mg_ptr);
+ const vmg_wizard *w = vmg_wizard_from_mg_nocheck(mg);
+
return vmg_cb_call1(w->cb_get, w->opinfo, sv, mg->mg_obj);
}
STATIC int vmg_svt_set(pTHX_ SV *sv, MAGIC *mg) {
- const vmg_wizard *w = vmg_wizard_from_sv(mg->mg_ptr);
+ const vmg_wizard *w = vmg_wizard_from_mg_nocheck(mg);
+
return vmg_cb_call1(w->cb_set, w->opinfo, sv, mg->mg_obj);
}
STATIC U32 vmg_svt_len(pTHX_ SV *sv, MAGIC *mg) {
- const vmg_wizard *w = vmg_wizard_from_sv(mg->mg_ptr);
+ const vmg_wizard *w = vmg_wizard_from_mg_nocheck(mg);
unsigned int opinfo = w->opinfo;
U32 len, ret;
SV *svr;
}
STATIC int vmg_svt_clear(pTHX_ SV *sv, MAGIC *mg) {
- const vmg_wizard *w = vmg_wizard_from_sv(mg->mg_ptr);
+ const vmg_wizard *w = vmg_wizard_from_mg_nocheck(mg);
+
return vmg_cb_call1(w->cb_clear, w->opinfo, sv, mg->mg_obj);
}
if (PL_dirty)
return 0;
- w = vmg_wizard_from_sv(mg->mg_ptr);
+ w = vmg_wizard_from_mg_nocheck(mg);
/* So that it survives the temp cleanup below */
SvREFCNT_inc_simple_void(sv);
int keylen
# endif
) {
- const vmg_wizard *w = vmg_wizard_from_sv(mg->mg_ptr);
+ const vmg_wizard *w = vmg_wizard_from_mg_nocheck(mg);
SV *keysv;
int ret;
#if MGf_LOCAL
STATIC int vmg_svt_local(pTHX_ SV *nsv, MAGIC *mg) {
- const vmg_wizard *w = vmg_wizard_from_sv(mg->mg_ptr);
+ const vmg_wizard *w = vmg_wizard_from_mg_nocheck(mg);
+
return vmg_cb_call1(w->cb_local, w->opinfo, nsv, mg->mg_obj);
}
#endif /* MGf_LOCAL */
default:
continue;
}
- if (mg->mg_private != SIG_WIZ) continue;
- w = vmg_wizard_from_sv(mg->mg_ptr);
+ w = vmg_wizard_from_mg(mg);
+ if (!w) continue;
switch (w->uvar) {
case 0:
continue;
SV *cast(SV *sv, SV *wiz, ...)
PROTOTYPE: \[$@%&*]$@
PREINIT:
+ const vmg_wizard *w = NULL;
SV **args = NULL;
+ UV ret;
I32 i = 0;
CODE:
if (items > 2) {
i = items - 2;
args = &ST(2);
}
- RETVAL = newSVuv(vmg_cast(SvRV(sv), vmg_wizard_sv_validate(wiz), args, i));
+ if (SvROK(wiz)) {
+ wiz = SvRV_const(wiz);
+ w = vmg_wizard_from_sv(wiz);
+ }
+ if (!w)
+ croak(vmg_invalid_wiz);
+ RETVAL = newSVuv(vmg_cast(SvRV(sv), w, wiz, args, i));
OUTPUT:
RETVAL
getdata(SV *sv, SV *wiz)
PROTOTYPE: \[$@%&*]$
PREINIT:
+ const vmg_wizard *w = NULL;
SV *data;
PPCODE:
- data = vmg_data_get(SvRV(sv), vmg_wizard_sv_validate(wiz));
+ if (SvROK(wiz))
+ w = vmg_wizard_from_sv(SvRV_const(wiz));
+ if (!w)
+ croak(vmg_invalid_wiz);
+ data = vmg_data_get(SvRV(sv), w);
if (!data)
XSRETURN_EMPTY;
ST(0) = data;
SV *dispell(SV *sv, SV *wiz)
PROTOTYPE: \[$@%&*]$
+PREINIT:
+ const vmg_wizard *w = NULL;
CODE:
- RETVAL = newSVuv(vmg_dispell(SvRV(sv), vmg_wizard_sv_validate(wiz)));
+ if (SvROK(wiz))
+ w = vmg_wizard_from_sv(SvRV_const(wiz));
+ if (!w)
+ croak(vmg_invalid_wiz);
+ RETVAL = newSVuv(vmg_dispell(SvRV(sv), w));
OUTPUT:
RETVAL