]> git.vpit.fr Git - perl/modules/Variable-Magic.git/commitdiff
Importing Variable-Magic-0.15.tar.gz v0.15
authorVincent Pit <vince@profvince.com>
Sun, 29 Jun 2008 16:24:49 +0000 (18:24 +0200)
committerVincent Pit <vince@profvince.com>
Sun, 29 Jun 2008 16:24:49 +0000 (18:24 +0200)
Changes
META.yml
Magic.xs
README
lib/Variable/Magic.pm
samples/vm_vs_tie.pl
t/01-import.t
t/22-len.t

diff --git a/Changes b/Changes
index b4d14af2c24cf31c527a9267382303666e44af96..3471bcb371b6a10a5f6ac6d0fd571f1cfed08f17 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,5 +1,12 @@
 Revision history for Variable-Magic
 
+0.15    2008-04-11 18:25 UTC
+        + Chg : Factor vmg_cb_call{1,2,3}() into one function.
+        + Fix : len magic is no longer called when taking the length() of a
+                magical scalar since p32969. The VMG_COMPAT_SCALAR_LENGTH_NOLEN
+                constant was added to cover this.
+        + Tst : More tests for t/22-len.t.
+
 0.14    2008-03-24 12:35 UTC
         + Fix : t/16-huf.t failures on Solaris and FreeBSD caused by not
                 updating mg->mg_ptr after Renew-ing it on dispell.
index c968d388d20ace58e2e045d3fe17f0eab0cc56f9..54c9a64bdc03eda11096f3ed6465ec70d5fef343 100644 (file)
--- a/META.yml
+++ b/META.yml
@@ -1,6 +1,6 @@
 --- #YAML:1.0
 name:                Variable-Magic
-version:             0.14
+version:             0.15
 abstract:            Associate user-defined magic to variables from Perl.
 license:             perl
 author:              
index b218de98cbc0bee835762d1d6d07b01b37f75971..2cd4e7cdd34a48c41b08491d8e7ed36e8a255002 100644 (file)
--- a/Magic.xs
+++ b/Magic.xs
@@ -1,6 +1,8 @@
 /* This file is part of the Variable::Magic Perl module.
  * See http://search.cpan.org/dist/Variable-Magic/ */
 
+#include <stdarg.h> /* <va_list>, va_{start,arg,end}, ... */
+
 #include <stdio.h>  /* sprintf() */
 
 #define PERL_NO_GET_CONTEXT
 # define VMG_UVAR 0
 #endif
 
-#if (VMG_PERL_PATCHLEVEL >= 25854) || PERL_VERSION_GE(5, 9, 3)
+#if (VMG_PERL_PATCHLEVEL >= 25854) || (!VMG_PERL_PATCHLEVEL && PERL_VERSION_GE(5, 9, 3))
 # define VMG_COMPAT_ARRAY_PUSH_NOLEN 1
 #else
 # define VMG_COMPAT_ARRAY_PUSH_NOLEN 0
 #endif
 
 /* since 5.9.5 - see #43357 */
-#if (VMG_PERL_PATCHLEVEL >= 31473) || PERL_VERSION_GE(5, 9, 5)
+#if (VMG_PERL_PATCHLEVEL >= 31473) || (!VMG_PERL_PATCHLEVEL && PERL_VERSION_GE(5, 9, 5))
 # define VMG_COMPAT_ARRAY_UNDEF_CLEAR 1
 #else
 # define VMG_COMPAT_ARRAY_UNDEF_CLEAR 0
 #endif
 
+#if (VMG_PERL_PATCHLEVEL >= 32969) || (!VMG_PERL_PATCHLEVEL && PERL_VERSION_GE(5, 11, 0))
+# define VMG_COMPAT_SCALAR_LENGTH_NOLEN 1
+#else
+# define VMG_COMPAT_SCALAR_LENGTH_NOLEN 0
+#endif
+
 #if VMG_UVAR
 
 /* Bug-free mg_magical - see http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2008-01/msg00036.html */
@@ -392,10 +400,11 @@ STATIC UV vmg_dispell(pTHX_ SV *sv, U16 sig) {
 
 /* ... svt callbacks ....................................................... */
 
-STATIC int vmg_cb_call(pTHX_ SV *cb, SV *sv, SV *data) {
-#define vmg_cb_call(I, S, D) vmg_cb_call(aTHX_ (I), (S), (D))
+STATIC int vmg_cb_call(pTHX_ SV *cb, SV *sv, SV *data, unsigned int args, ...) {
+ va_list ap;
  SV *svr;
  int ret;
+ unsigned int i;
 
  dSP;
  int count;
@@ -404,42 +413,15 @@ STATIC int vmg_cb_call(pTHX_ SV *cb, SV *sv, SV *data) {
  SAVETMPS;
 
  PUSHMARK(SP);
- XPUSHs(sv_2mortal(newRV_inc(sv)));
- if (data) { XPUSHs(data); }
- PUTBACK;
-
- count = call_sv(cb, G_SCALAR);
-
- SPAGAIN;
-
- if (count != 1) { croak("Callback needs to return 1 scalar\n"); }
- svr = POPs;
- ret = SvOK(svr) ? SvIV(svr) : 0;
-
- PUTBACK;
-
- FREETMPS;
- LEAVE;
-
- return ret;
-}
-
-#if VMG_UVAR
-STATIC int vmg_cb_call2(pTHX_ SV *cb, SV *sv, SV *data, SV *sv2) {
-#define vmg_cb_call2(I, S, D, S2) vmg_cb_call2(aTHX_ (I), (S), (D), (S2))
- SV *svr;
- int ret;
-
- dSP;
- int count;
-
- ENTER;
- SAVETMPS;
-
- PUSHMARK(SP);
- XPUSHs(sv_2mortal(newRV_inc(sv)));
- XPUSHs(data ? data : &PL_sv_undef);
- if (sv2) { XPUSHs(sv2); }
+ EXTEND(SP, args + 2);
+ PUSHs(sv_2mortal(newRV_inc(sv)));
+ PUSHs(data ? data : &PL_sv_undef);
+ va_start(ap, args);
+ for (i = 0; i < args; ++i) {
+  SV *sv = va_arg(ap, SV *);
+  PUSHs(sv ? sv : &PL_sv_undef);
+ }
+ va_end(ap);
  PUTBACK;
 
  count = call_sv(cb, G_SCALAR);
@@ -457,50 +439,17 @@ STATIC int vmg_cb_call2(pTHX_ SV *cb, SV *sv, SV *data, SV *sv2) {
 
  return ret;
 }
-#endif /* VMG_UVAR */
-
-#if MGf_COPY
-STATIC int vmg_cb_call3(pTHX_ SV *cb, SV *sv, SV *data, SV *sv2, SV *sv3) {
-#define vmg_cb_call3(I, S, D, S2, S3) vmg_cb_call3(aTHX_ (I), (S), (D), (S2), (S3))
- SV *svr;
- int ret;
-
- dSP;
- int count;
-
- ENTER;
- SAVETMPS;
-
- PUSHMARK(SP);
- XPUSHs(sv_2mortal(newRV_inc(sv)));
- XPUSHs(data ? data : &PL_sv_undef);
- XPUSHs(sv2  ? sv2  : &PL_sv_undef);
- if (sv3) { XPUSHs(sv3); }
- PUTBACK;
-
- count = call_sv(cb, G_SCALAR);
 
- SPAGAIN;
-
- if (count != 1) { croak("Callback needs to return 1 scalar\n"); }
- svr = POPs;
- ret = SvOK(svr) ? SvIV(svr) : 0;
-
- PUTBACK;
-
- FREETMPS;
- LEAVE;
-
- return ret;
-}
-#endif /* MGf_COPY */
+#define vmg_cb_call1(I, S, D)         vmg_cb_call(aTHX_ (I), (S), (D), 0)
+#define vmg_cb_call2(I, S, D, S2)     vmg_cb_call(aTHX_ (I), (S), (D), 1, (S2))
+#define vmg_cb_call3(I, S, D, S2, S3) vmg_cb_call(aTHX_ (I), (S), (D), 2, (S2), (S3))
 
 STATIC int vmg_svt_get(pTHX_ SV *sv, MAGIC *mg) {
- return vmg_cb_call(SV2MGWIZ(mg->mg_ptr)->cb_get, sv, mg->mg_obj);
+ return vmg_cb_call1(SV2MGWIZ(mg->mg_ptr)->cb_get, sv, mg->mg_obj);
 }
 
 STATIC int vmg_svt_set(pTHX_ SV *sv, MAGIC *mg) {
- return vmg_cb_call(SV2MGWIZ(mg->mg_ptr)->cb_set, sv, mg->mg_obj);
+ return vmg_cb_call1(SV2MGWIZ(mg->mg_ptr)->cb_set, sv, mg->mg_obj);
 }
 
 STATIC U32 vmg_svt_len(pTHX_ SV *sv, MAGIC *mg) {
@@ -515,11 +464,14 @@ STATIC U32 vmg_svt_len(pTHX_ SV *sv, MAGIC *mg) {
  SAVETMPS;
 
  PUSHMARK(SP);
- XPUSHs(sv_2mortal(newRV_inc(sv)));
- XPUSHs(mg->mg_obj ? mg->mg_obj : &PL_sv_undef);
+ EXTEND(SP, 3);
+ PUSHs(sv_2mortal(newRV_inc(sv)));
+ PUSHs(mg->mg_obj ? mg->mg_obj : &PL_sv_undef);
  if (SvTYPE(sv) == SVt_PVAV) {
   len = av_len((AV *) sv) + 1;
-  XPUSHs(sv_2mortal(newSViv(len)));
+  PUSHs(sv_2mortal(newSViv(len)));
+ } else {
+  PUSHs(&PL_sv_undef);
  }
  PUTBACK;
 
@@ -541,7 +493,7 @@ STATIC U32 vmg_svt_len(pTHX_ SV *sv, MAGIC *mg) {
 }
 
 STATIC int vmg_svt_clear(pTHX_ SV *sv, MAGIC *mg) {
- return vmg_cb_call(SV2MGWIZ(mg->mg_ptr)->cb_clear, sv, mg->mg_obj);
+ return vmg_cb_call1(SV2MGWIZ(mg->mg_ptr)->cb_clear, sv, mg->mg_obj);
 }
 
 STATIC int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) {
@@ -549,12 +501,12 @@ STATIC int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) {
  SvREFCNT_inc(sv);
  /* Perl_mg_free will get rid of the magic and decrement mg->mg_obj and
   * mg->mg_ptr reference count */
- return vmg_cb_call(SV2MGWIZ(mg->mg_ptr)->cb_free, sv, mg->mg_obj);
+ return vmg_cb_call1(SV2MGWIZ(mg->mg_ptr)->cb_free, sv, mg->mg_obj);
 }
 
 #if MGf_COPY
 STATIC int vmg_svt_copy(pTHX_ SV *sv, MAGIC *mg, SV *nsv, const char *key,
-# if PERL_API_VERSION_GE(5, 11, 0)
+# if (VMG_PERL_PATCHLEVEL >= 33256) || (!VMG_PERL_PATCHLEVEL && PERL_API_VERSION_GE(5, 11, 0))
   I32 keylen
 # else
   int keylen
@@ -587,7 +539,7 @@ STATIC int vmg_svt_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *param) {
 
 #if MGf_LOCAL
 STATIC int vmg_svt_local(pTHX_ SV *nsv, MAGIC *mg) {
- return vmg_cb_call(SV2MGWIZ(mg->mg_ptr)->cb_local, nsv, mg->mg_obj);
+ return vmg_cb_call1(SV2MGWIZ(mg->mg_ptr)->cb_local, nsv, mg->mg_obj);
 }
 #endif /* MGf_LOCAL */
 
@@ -615,12 +567,12 @@ STATIC I32 vmg_svt_val(pTHX_ IV action, SV *sv) {
   if (!w->uvar) { continue; }
   switch (action) {
    case 0:
-    if (w->cb_fetch) { vmg_cb_call2(w->cb_fetch, sv, mg->mg_obj, key); }
+    if (w->cb_fetch)  { vmg_cb_call2(w->cb_fetch,  sv, mg->mg_obj, key); }
     break;
    case HV_FETCH_ISSTORE:
    case HV_FETCH_LVALUE:
    case (HV_FETCH_ISSTORE|HV_FETCH_LVALUE):
-    if (w->cb_store) { vmg_cb_call2(w->cb_store, sv, mg->mg_obj, key); }
+    if (w->cb_store)  { vmg_cb_call2(w->cb_store,  sv, mg->mg_obj, key); }
     break;
    case HV_FETCH_ISEXISTS:
     if (w->cb_exists) { vmg_cb_call2(w->cb_exists, sv, mg->mg_obj, key); }
@@ -761,6 +713,8 @@ BOOT:
                     newSVuv(VMG_COMPAT_ARRAY_PUSH_NOLEN));
  newCONSTSUB(stash, "VMG_COMPAT_ARRAY_UNDEF_CLEAR",
                     newSVuv(VMG_COMPAT_ARRAY_UNDEF_CLEAR));
+ newCONSTSUB(stash, "VMG_COMPAT_SCALAR_LENGTH_NOLEN",
+                    newSVuv(VMG_COMPAT_SCALAR_LENGTH_NOLEN));
 }
 
 SV *_wizard(...)
diff --git a/README b/README
index abca8852c15c97d8f109598eb5624e6dde7f3ea3..944ed1936a9cce0c05590278aa8b6e9bc291d7b6 100644 (file)
--- a/README
+++ b/README
@@ -2,7 +2,7 @@ NAME
     Variable::Magic - Associate user-defined magic to variables from Perl.
 
 VERSION
-    Version 0.14
+    Version 0.15
 
 SYNOPSIS
         use Variable::Magic qw/wizard cast dispell/;
@@ -109,6 +109,10 @@ PERL MAGIC HISTORY
     'copy' magic on hash stores for (non-tied) hashes that also have 'uvar'
     magic.
 
+  5.11.x
+    *p32969* : 'len' magic is no longer invoked when calling "length" with a
+    magical scalar.
+
 CONSTANTS
   "SIG_MIN"
     The minimum integer used as a signature for user-defined magic.
@@ -139,6 +143,10 @@ CONSTANTS
   "VMG_COMPAT_ARRAY_UNDEF_CLEAR"
     True for perls that call 'clear' magic when undefining magical arrays.
 
+  "VMG_COMPAT_SCALAR_LENGTH_NOLEN"
+    True for perls that don't call 'len' magic when taking the "length" of a
+    magical scalar.
+
 FUNCTIONS
   "wizard"
         wizard sig    => ...,
index b91c0847ccefbe7930d01314e93701632c361adf..e14283f22dd58f36e1cd6e41061c43961bc7d3fb 100644 (file)
@@ -13,13 +13,13 @@ Variable::Magic - Associate user-defined magic to variables from Perl.
 
 =head1 VERSION
 
-Version 0.14
+Version 0.15
 
 =cut
 
 our $VERSION;
 BEGIN {
- $VERSION = '0.14';
+ $VERSION = '0.15';
 }
 
 =head1 SYNOPSIS
@@ -141,6 +141,14 @@ The places where magic is invoked have changed a bit through perl history. Here'
 
 =back
 
+=head2 B<5.11.x>
+
+=over 4
+
+=item I<p32969> : 'len' magic is no longer invoked when calling C<length> with a magical scalar.
+
+=back
+
 =head1 CONSTANTS
 
 =head2 C<SIG_MIN>
@@ -179,6 +187,10 @@ True for perls that don't call 'len' magic when you push an element in a magical
 
 True for perls that call 'clear' magic when undefining magical arrays.
 
+=head2 C<VMG_COMPAT_SCALAR_LENGTH_NOLEN>
+
+True for perls that don't call 'len' magic when taking the C<length> of a magical scalar.
+
 =head1 FUNCTIONS
 
 =cut
@@ -298,7 +310,8 @@ our @EXPORT         = ();
 our %EXPORT_TAGS    = (
  'funcs' =>  [ qw/wizard gensig getsig cast getdata dispell/ ],
  'consts' => [ qw/SIG_MIN SIG_MAX SIG_NBR MGf_COPY MGf_DUP MGf_LOCAL VMG_UVAR/,
-               qw/VMG_COMPAT_ARRAY_PUSH_NOLEN VMG_COMPAT_ARRAY_UNDEF_CLEAR/ ]
+               qw/VMG_COMPAT_ARRAY_PUSH_NOLEN VMG_COMPAT_ARRAY_UNDEF_CLEAR/,
+               qw/VMG_COMPAT_SCALAR_LENGTH_NOLEN/ ]
 );
 our @EXPORT_OK      = map { @$_ } values %EXPORT_TAGS;
 $EXPORT_TAGS{'all'} = [ @EXPORT_OK ];
index 9c8cae42e241b71b232f9617ba50c318caf34903..cfb491c55da6987e1b9e3b32b79db3bb343d9fc5 100755 (executable)
@@ -22,7 +22,9 @@ my %v;
 $v{$a[$_]} = $_ for 0 .. $#a;
 cast %v, $wiz;
 
+my $x = 0;
+
 cmpthese -3, {
- 'tie'  => sub { my ($x, $y) = map @a[rand @a], 1 .. 2; my $a = $t{$x}; $t{$y} = $a },
- 'v::m' => sub { my ($x, $y) = map @a[rand @a], 1 .. 2; my $a = $v{$x}; $v{$y} = $a }
+ 'tie'  => sub { my ($x, $y) = map @a[$x++ % @a], 1 .. 2; my $a = $t{$x}; $t{$y} = $a },
+ 'v::m' => sub { my ($x, $y) = map @a[$x++ % @a], 1 .. 2; my $a = $v{$x}; $v{$y} = $a }
 };
index 6b858496ee3102ea3eaf93077eb8ccc3ece46546..9e0139ff96201c6108bc239680dde1857fc5f1f4 100644 (file)
@@ -3,11 +3,11 @@
 use strict;
 use warnings;
 
-use Test::More tests => 15;
+use Test::More tests => 16;
 
 require Variable::Magic;
 
-for (qw/wizard gensig getsig cast getdata dispell SIG_MIN SIG_MAX SIG_NBR MGf_COPY MGf_DUP MGf_LOCAL VMG_UVAR VMG_COMPAT_ARRAY_PUSH_NOLEN VMG_COMPAT_ARRAY_UNDEF_CLEAR/) {
+for (qw/wizard gensig getsig cast getdata dispell SIG_MIN SIG_MAX SIG_NBR MGf_COPY MGf_DUP MGf_LOCAL VMG_UVAR VMG_COMPAT_ARRAY_PUSH_NOLEN VMG_COMPAT_ARRAY_UNDEF_CLEAR VMG_COMPAT_SCALAR_LENGTH_NOLEN/) {
  eval { Variable::Magic->import($_) };
  ok(!$@, 'import ' . $_);
 }
index 0a6dd59650611bbfc276beca4691c26d93bd54b8..8ea332c5fc8603ff3405370699604bcd62aba468 100644 (file)
@@ -3,9 +3,9 @@
 use strict;
 use warnings;
 
-use Test::More tests => 6;
+use Test::More tests => 11;
 
-use Variable::Magic qw/wizard cast/;
+use Variable::Magic qw/wizard cast VMG_COMPAT_SCALAR_LENGTH_NOLEN/;
 
 my $c = 0;
 my $n = int rand 1000;
@@ -15,13 +15,36 @@ is($c, 0, 'len : create wizard');
 my @a = qw/a b c/;
 
 cast @a, $wiz;
-is($c, 0, 'len : cast');
+is($c, 0, 'len : cast on array');
 
 my $b = scalar @a;
-is($c, 1,  'len : get length');
-is($b, $n, 'len : get length correctly');
+is($c, 1,  'len : get array length');
+is($b, $n, 'len : get array length correctly');
+
+$b = $#a;
+is($c, 2,      'len : get last array index');
+is($b, $n - 1, 'len : get last array index correctly');
 
 $n = 0;
 $b = scalar @a;
-is($c, 2, 'len : get length 0');
-is($b, 0, 'len : get length 0 correctly');
+is($c, 3, 'len : get array length 0');
+is($b, 0, 'len : get array length 0 correctly');
+
+$c = 0;
+$n = int rand 1000;
+# length magic on scalars needs also get magic to be triggered.
+$wiz = wizard get => sub { return 56478 },
+              len => sub { ++$c; return $n };
+
+my $x = int rand 1000;
+
+SKIP: {
+ skip 'length() no longer calls mg_len magic', 3 if VMG_COMPAT_SCALAR_LENGTH_NOLEN;
+
+ cast $x, $wiz;
+ is($c, 0, 'len : cast on scalar');
+
+ $b = length $x;
+ is($c, 1,      'len : get scalar length');
+ is($b, $n - 1, 'len : get scalar length correctly');
+}