]> git.vpit.fr Git - perl/modules/Variable-Magic.git/blobdiff - Magic.xs
Allow passing ref-to-undef as callbacks to install a noop callback
[perl/modules/Variable-Magic.git] / Magic.xs
index c8de4302383d714c9e14eb23a57afeb5bf233ff6..2829b9db99287731a75316ab920dc616ae2c4c53 100644 (file)
--- a/Magic.xs
+++ b/Magic.xs
@@ -1074,18 +1074,26 @@ STATIC int vmg_cb_call(pTHX_ SV *cb, unsigned int flags, SV *sv, ...) {
 #define vmg_cb_call3(I, OI, S, A1, A2, A3) \
         vmg_cb_call(aTHX_ (I), VMG_CB_FLAGS((OI), 3), (S), (A1), (A2), (A3))
 
+STATIC int vmg_svt_default_noop(pTHX_ SV *sv, MAGIC *mg) {
+ return 0;
+}
+
 STATIC int vmg_svt_get(pTHX_ SV *sv, MAGIC *mg) {
  const vmg_wizard *w = vmg_wizard_from_mg_nocheck(mg);
 
  return vmg_cb_call1(w->cb_get, w->opinfo, sv, mg->mg_obj);
 }
 
+#define vmg_svt_get_noop vmg_svt_default_noop
+
 STATIC int vmg_svt_set(pTHX_ SV *sv, MAGIC *mg) {
  const vmg_wizard *w = vmg_wizard_from_mg_nocheck(mg);
 
  return vmg_cb_call1(w->cb_set, w->opinfo, sv, mg->mg_obj);
 }
 
+#define vmg_svt_set_noop vmg_svt_default_noop
+
 STATIC U32 vmg_sv_len(pTHX_ SV *sv) {
 #define vmg_sv_len(S) vmg_sv_len(aTHX_ (S))
  STRLEN len;
@@ -1143,12 +1151,27 @@ STATIC U32 vmg_svt_len(pTHX_ SV *sv, MAGIC *mg) {
  return ret;
 }
 
+STATIC U32 vmg_svt_len_noop(pTHX_ SV *sv, MAGIC *mg) {
+ U32    len = 0;
+ svtype t   = SvTYPE(sv);
+
+ if (t < SVt_PVAV) {
+  len = vmg_sv_len(sv);
+ } else if (t == SVt_PVAV) {
+  len = (U32) av_len((AV *) sv);
+ }
+
+ return len;
+}
+
 STATIC int vmg_svt_clear(pTHX_ SV *sv, MAGIC *mg) {
  const vmg_wizard *w = vmg_wizard_from_mg_nocheck(mg);
 
  return vmg_cb_call1(w->cb_clear, w->opinfo, sv, mg->mg_obj);
 }
 
+#define vmg_svt_clear_noop vmg_svt_default_noop
+
 STATIC int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) {
  const vmg_wizard *w;
  int ret = 0;
@@ -1204,6 +1227,8 @@ STATIC int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) {
  return ret;
 }
 
+#define vmg_svt_free_noop vmg_svt_default_noop
+
 #if VMG_HAS_PERL_MAINT(5, 11, 0, 33256) || VMG_HAS_PERL(5, 12, 0)
 # define VMG_SVT_COPY_KEYLEN_TYPE I32
 #else
@@ -1230,18 +1255,27 @@ STATIC int vmg_svt_copy(pTHX_ SV *sv, MAGIC *mg, SV *nsv, const char *key, VMG_S
  return ret;
 }
 
+STATIC int vmg_svt_copy_noop(pTHX_ SV *sv, MAGIC *mg, SV *nsv, const char *key, VMG_SVT_COPY_KEYLEN_TYPE keylen) {
+ return 0;
+}
+
 #if 0
 STATIC int vmg_svt_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *param) {
  return 0;
 }
+#define vmg_svt_dup_noop vmg_svt_dup
 #endif
 
 #if MGf_LOCAL
+
 STATIC int vmg_svt_local(pTHX_ SV *nsv, MAGIC *mg) {
  const vmg_wizard *w = vmg_wizard_from_mg_nocheck(mg);
 
  return vmg_cb_call1(w->cb_local, w->opinfo, nsv, mg->mg_obj);
 }
+
+#define vmg_svt_local_noop vmg_svt_default_noop
+
 #endif /* MGf_LOCAL */
 
 #if VMG_UVAR
@@ -1339,19 +1373,46 @@ STATIC I32 vmg_svt_val(pTHX_ IV action, SV *sv) {
 
 /* --- Macros for the XS section ------------------------------------------- */
 
-#define VMG_SET_CB(S, N)              \
- cb = (S);                            \
- w->cb_ ## N = (SvOK(cb) && SvROK(cb)) ? SvREFCNT_inc(SvRV(cb)) : NULL;
-
-#define VMG_SET_SVT_CB(S, N)          \
- cb = (S);                            \
- if (SvOK(cb) && SvROK(cb)) {         \
-  t->svt_ ## N = vmg_svt_ ## N;       \
-  w->cb_  ## N = SvREFCNT_inc(SvRV(cb)); \
- } else {                             \
-  t->svt_ ## N = NULL;                \
-  w->cb_  ## N = NULL;                \
- }
+#ifdef CvISXSUB
+# define VMG_CVOK(C) \
+   ((CvISXSUB(C) ? (void *) CvXSUB(C) : (void *) CvROOT(C)) ? 1 : 0)
+#else
+# define VMG_CVOK(C) (CvROOT(C) || CvXSUB(C))
+#endif
+
+#define VMG_CBOK(S) ((SvTYPE(S) == SVt_PVCV) ? VMG_CVOK(S) : SvOK(S))
+
+#define VMG_SET_CB(S, N) {       \
+ SV *cb = (S);                   \
+ if (SvOK(cb) && SvROK(cb)) {    \
+  cb = SvRV(cb);                 \
+  if (VMG_CBOK(cb))              \
+   SvREFCNT_inc_simple_void(cb); \
+  else                           \
+   cb = NULL;                    \
+ } else {                        \
+  cb = NULL;                     \
+ }                               \
+ w->cb_ ## N = cb;               \
+}
+
+#define VMG_SET_SVT_CB(S, N) {   \
+ SV *cb = (S);                   \
+ if (SvOK(cb) && SvROK(cb)) {    \
+  cb = SvRV(cb);                 \
+  if (VMG_CBOK(cb)) {            \
+   t->svt_ ## N = vmg_svt_ ## N; \
+   SvREFCNT_inc_simple_void(cb); \
+  } else {                       \
+   t->svt_ ## N = vmg_svt_ ## N ## _noop; \
+   cb           = NULL;          \
+  }                              \
+ } else {                        \
+  t->svt_ ## N = NULL;           \
+  cb           = NULL;           \
+ }                               \
+ w->cb_ ## N = cb;               \
+}
 
 /* --- XS ------------------------------------------------------------------ */
 
@@ -1427,7 +1488,7 @@ PROTOTYPE: DISABLE
 PREINIT:
  vmg_wizard *w;
  MGVTBL *t;
- SV *cb, *op_info, *copy_key;
+ SV *op_info, *copy_key;
  I32 i = 0;
 CODE:
  if (items != 9