From: Vincent Pit Date: Sun, 29 Jun 2008 16:24:49 +0000 (+0200) Subject: Importing Variable-Magic-0.15.tar.gz X-Git-Tag: v0.15^0 X-Git-Url: http://git.vpit.fr/?a=commitdiff_plain;h=91aec4cfae75e61ff8eeb79448501a8739b0d240;p=perl%2Fmodules%2FVariable-Magic.git Importing Variable-Magic-0.15.tar.gz --- diff --git a/Changes b/Changes index b4d14af..3471bcb 100644 --- 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. diff --git a/META.yml b/META.yml index c968d38..54c9a64 100644 --- 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: diff --git a/Magic.xs b/Magic.xs index b218de9..2cd4e7c 100644 --- 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 /* , va_{start,arg,end}, ... */ + #include /* sprintf() */ #define PERL_NO_GET_CONTEXT @@ -67,19 +69,25 @@ # 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 abca885..944ed19 100644 --- 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 => ..., diff --git a/lib/Variable/Magic.pm b/lib/Variable/Magic.pm index b91c084..e14283f 100644 --- a/lib/Variable/Magic.pm +++ b/lib/Variable/Magic.pm @@ -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 : 'len' magic is no longer invoked when calling C with a magical scalar. + +=back + =head1 CONSTANTS =head2 C @@ -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 + +True for perls that don't call 'len' magic when taking the C 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 ]; diff --git a/samples/vm_vs_tie.pl b/samples/vm_vs_tie.pl index 9c8cae4..cfb491c 100755 --- a/samples/vm_vs_tie.pl +++ b/samples/vm_vs_tie.pl @@ -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 } }; diff --git a/t/01-import.t b/t/01-import.t index 6b85849..9e0139f 100644 --- a/t/01-import.t +++ b/t/01-import.t @@ -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 ' . $_); } diff --git a/t/22-len.t b/t/22-len.t index 0a6dd59..8ea332c 100644 --- a/t/22-len.t +++ b/t/22-len.t @@ -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'); +}