=head1 VERSION
-Version 0.34
+Version 0.40
=cut
our $VERSION;
BEGIN {
- $VERSION = '0.34';
+ $VERSION = '0.40';
}
=head1 SYNOPSIS
C<get>
-This magic is invoked when the variable is evaluated (does not include array/hash subscripts and slices).
+This magic is invoked when the variable is evaluated.
+It is never called for arrays and hashes.
=item *
C<set>
-This one is triggered each time the value of the variable changes (includes array/hash subscripts and slices).
+This one is triggered each time the value of the variable changes.
+It is called for array subscripts and slices, but never for hashes.
=item *
=head2 C<wizard>
- wizard sig => ...,
- data => sub { ... },
+ wizard data => sub { ... },
get => sub { my ($ref, $data [, $op]) = @_; ... },
set => sub { my ($ref, $data [, $op]) = @_; ... },
len => sub { my ($ref, $data, $len [, $op]) = @_; ... ; return $newlen; },
=item *
-C<sig>
-
-The numerical signature.
-If not specified or undefined, a random signature is generated.
-If the signature matches an already defined magic, then the existant magic object is returned.
-
-=item *
-
C<data>
-A code reference to a private data constructor.
+A code (or string) reference to a private data constructor.
It is called each time this magic is cast on a variable, and the scalar returned is used as private data storage for it.
C<$_[0]> is a reference to the magic object and C<@_[1 .. @_-1]> are all extra arguments that were passed to L</cast>.
C<get>, C<set>, C<len>, C<clear>, C<free>, C<copy>, C<local>, C<fetch>, C<store>, C<exists> and C<delete>
-Code references to the corresponding magic callbacks.
+Code (or string) references to the corresponding magic callbacks.
You don't have to specify all of them : the magic associated with undefined entries simply won't be hooked.
In those callbacks, C<$_[0]> is always a reference to the magic object and C<$_[1]> is always the private data (or C<undef> when no private data constructor was supplied).
C<$_[2]> is an alias to the current key.
Nothing prevents you from changing it, but be aware that there lurk dangerous side effects.
-For example, it may righteously be readonly if the key was a bareword.
+For example, it may rightfully be readonly if the key was a bareword.
You can get a copy instead by passing C<< copy_key => 1 >> to L</wizard>, which allows you to safely assign to C<$_[2]> in order to e.g. redirect the action to another key.
This however has a little performance drawback because of the copy.
=back
+Each callback can be specified as a code or a string reference, in which case the function denoted by the string will be used as the callback.
+
+Note that C<free> callbacks are I<never> called during global destruction, as there's no way to ensure that the wizard and the C<free> callback weren't destroyed before the variable.
+
+Here's a simple usage example :
+
# A simple scalar tracer
my $wiz = wizard get => sub { print STDERR "got ${$_[0]}\n" },
set => sub { print STDERR "set to ${$_[0]}\n" },
free => sub { print STDERR "${$_[0]} was deleted\n" }
-Note that C<free> callbacks are I<never> called during global destruction, as there's no way to ensure that the wizard and the C<free> callback weren't destroyed before the variable.
-
=cut
sub wizard {
croak 'Wrong number of arguments for wizard()' if @_ % 2;
my %opts = @_;
- my @keys = qw/sig data op_info get set len clear free/;
+ my @keys = qw/data op_info get set len clear free/;
push @keys, 'copy' if MGf_COPY;
push @keys, 'dup' if MGf_DUP;
push @keys, 'local' if MGf_LOCAL;
return $ret;
}
-=head2 C<gensig>
-
-With this tool, you can manually generate random magic signature between SIG_MIN and SIG_MAX inclusive.
-That's the way L</wizard> creates them when no signature is supplied.
-
- # Generate a signature
- my $sig = gensig;
-
-=head2 C<getsig>
-
- getsig $wiz
-
-This accessor returns the magic signature of this wizard.
-
- # Get $wiz signature
- my $sig = getsig $wiz;
-
=head2 C<cast>
- cast [$@%&*]var, [$wiz|$sig], ...
+ cast [$@%&*]var, $wiz, ...
This function associates C<$wiz> magic to the variable supplied, without overwriting any other kind of magic.
-You can also supply the numeric signature C<$sig> instead of C<$wiz>.
-It returns true on success or when C<$wiz> magic is already present, and croaks on error or when no magic corresponds to the given signature (in case a C<$sig> was supplied).
+It returns true on success or when C<$wiz> magic is already present, and croaks on error.
All extra arguments specified after C<$wiz> are passed to the private data constructor in C<@_[1 .. @_-1]>.
If the variable isn't a hash, any C<uvar> callback of the wizard is safely ignored.
If you want to overcome the possible deletion of the C<'TZ'> entry, you have no choice but to rely on C<store> uvar magic.
-C<cast> can be called from any magical callback, and in particular from C<data>.
-This allows you to recursively cast magic on datastructures :
-
- my $wiz;
- $wiz = wizard
- data => sub {
- my ($var, $depth) = @_;
- $depth ||= 0;
- my $r = ref $var;
- if ($r eq 'ARRAY') {
- &cast((ref() ? $_ : \$_), $wiz, $depth + 1) for @$var;
- } elsif ($r eq 'HASH') {
- &cast((ref() ? $_ : \$_), $wiz, $depth + 1) for values %$var;
- }
- return $depth;
- },
- free => sub {
- my ($var, $depth) = @_;
- my $r = ref $var;
- print "free $r at depth $depth\n";
- ();
- };
-
- {
- my %h = (
- a => [ 1, 2 ],
- b => { c => 3 }
- );
- cast %h, $wiz;
- }
-
-When C<%h> goes out of scope, this will print something among the lines of :
-
- free HASH at depth 0
- free HASH at depth 1
- free SCALAR at depth 2
- free ARRAY at depth 1
- free SCALAR at depth 3
- free SCALAR at depth 3
-
-Of course, this example does nothing with the values that are added after the C<cast>.
-
=head2 C<getdata>
- getdata [$@%&*]var, [$wiz|$sig]
+ getdata [$@%&*]var, $wiz
-This accessor fetches the private data associated with the magic C<$wiz> (or the signature C<$sig>) in the variable.
-It croaks when C<$wiz> or C<$sig> do not represent a current valid magic object attached to the variable, and returns C<undef> when the wizard has no data constructor or when the data is actually C<undef>.
+This accessor fetches the private data associated with the magic C<$wiz> in the variable.
+It croaks when C<$wiz> do not represent a valid magic object, and returns an empty list if no such magic is attached to the variable or when the wizard has no data constructor.
# Get the attached data, or undef if the wizard does not attach any.
my $data = getdata $x, $wiz;
=head2 C<dispell>
- dispell [$@%&*]variable, [$wiz|$sig]
+ dispell [$@%&*]variable, $wiz
The exact opposite of L</cast> : it dissociates C<$wiz> magic from the variable.
-You can also pass the magic signature C<$sig> as the second argument.
-This function returns true on success, C<0> when no magic represented by C<$wiz> or C<$sig> could be found in the variable, and croaks if the supplied wizard or signature is invalid.
+This function returns true on success, C<0> when no magic represented by C<$wiz> could be found in the variable, and croaks if the supplied wizard is invalid.
# Dispell now.
die 'no such magic in $x' unless dispell $x, $wiz;
=head1 CONSTANTS
-=head2 C<SIG_MIN>
-
-The minimum integer used as a signature for user-defined magic.
-
-=head2 C<SIG_MAX>
-
-The maximum integer used as a signature for user-defined magic.
-
-=head2 C<SIG_NBR>
-
- SIG_NBR = SIG_MAX - SIG_MIN + 1
-
=head2 C<MGf_COPY>
Evaluates to true iff the 'copy' magic is available.
=head2 C<VMG_COMPAT_ARRAY_PUSH_NOLEN>
True for perls that don't call 'len' magic when you push an element in a magical array.
+Starting from perl 5.11.0, this only refers to pushes in non-void context and hence is false.
+
+=head2 C<VMG_COMPAT_ARRAY_PUSH_NOLEN_VOID>
+
+True for perls that don't call 'len' magic when you push in void context an element in a magical array.
=head2 C<VMG_COMPAT_ARRAY_UNSHIFT_NOLEN_VOID>
True iff this module could have been built with thread-safety features enabled.
+=head2 C<VMG_FORKSAFE>
+
+True iff this module could have been built with fork-safety features enabled.
+This will always be true except on Windows where it's false for perl 5.10.0 and below .
+
=head2 C<VMG_OP_INFO_NAME>
Value to pass with C<op_info> to get the current op name in the magic callbacks.
Value to pass with C<op_info> to get a C<B::OP> object representing the current op in the magic callbacks.
+=head1 COOKBOOK
+
+=head2 Associate an object to any perl variable
+
+This can be useful for passing user data through limited APIs.
+
+ {
+ package Magical::UserData;
+
+ use Variable::Magic qw/wizard cast getdata/;
+
+ my $wiz = wizard data => sub { \$_[1] };
+
+ sub ud (\[$@%*&]) : lvalue {
+ my ($var) = @_;
+ my $data = &getdata($var, $wiz);
+ unless (defined $data) {
+ &cast($var, $wiz);
+ $data = &getdata($var, $wiz);
+ die "Couldn't cast UserData magic onto the variable" unless defined $data;
+ }
+ $$data;
+ }
+ }
+
+ {
+ BEGIN { *ud = \&Magical::UserData::ud }
+
+ my $cb;
+ $cb = sub { print 'Hello, ', ud(&$cb), "!\n" };
+
+ ud(&$cb) = 'world';
+ $cb->(); # Hello, world!
+ }
+
+=head2 Recursively cast magic on datastructures
+
+C<cast> can be called from any magical callback, and in particular from C<data>.
+This allows you to recursively cast magic on datastructures :
+
+ my $wiz;
+ $wiz = wizard data => sub {
+ my ($var, $depth) = @_;
+ $depth ||= 0;
+ my $r = ref $var;
+ if ($r eq 'ARRAY') {
+ &cast((ref() ? $_ : \$_), $wiz, $depth + 1) for @$var;
+ } elsif ($r eq 'HASH') {
+ &cast((ref() ? $_ : \$_), $wiz, $depth + 1) for values %$var;
+ }
+ return $depth;
+ },
+ free => sub {
+ my ($var, $depth) = @_;
+ my $r = ref $var;
+ print "free $r at depth $depth\n";
+ ();
+ };
+
+ {
+ my %h = (
+ a => [ 1, 2 ],
+ b => { c => 3 }
+ );
+ cast %h, $wiz;
+ }
+
+When C<%h> goes out of scope, this will print something among the lines of :
+
+ free HASH at depth 0
+ free HASH at depth 1
+ free SCALAR at depth 2
+ free ARRAY at depth 1
+ free SCALAR at depth 3
+ free SCALAR at depth 3
+
+Of course, this example does nothing with the values that are added after the C<cast>.
+
=head1 PERL MAGIC HISTORY
The places where magic is invoked have changed a bit through perl history.
I<p34908> : 'len' magic is no longer called when pushing / unshifting an element into a magical array in void context.
The C<push> part was already covered by I<p25854>.
+I<g9cdcb38b> : 'len' magic is called again when pushing into a magical array in non-void context.
+
=back
=head1 EXPORT
-The functions L</wizard>, L</gensig>, L</getsig>, L</cast>, L</getdata> and L</dispell> are only exported on request.
+The functions L</wizard>, L</cast>, L</getdata> and L</dispell> are only exported on request.
All of them are exported by the tags C<':funcs'> and C<':all'>.
All the constants are also only exported on request, either individually or by the tags C<':consts'> and C<':all'>.
our @EXPORT = ();
our %EXPORT_TAGS = (
- 'funcs' => [ qw/wizard gensig getsig cast getdata dispell/ ],
+ 'funcs' => [ qw/wizard 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_UNSHIFT_NOLEN_VOID VMG_COMPAT_ARRAY_UNDEF_CLEAR VMG_COMPAT_SCALAR_LENGTH_NOLEN/,
+ qw/MGf_COPY MGf_DUP MGf_LOCAL VMG_UVAR/,
+ qw/VMG_COMPAT_ARRAY_PUSH_NOLEN VMG_COMPAT_ARRAY_PUSH_NOLEN_VOID/,
+ qw/VMG_COMPAT_ARRAY_UNSHIFT_NOLEN_VOID/,
+ qw/VMG_COMPAT_ARRAY_UNDEF_CLEAR/,
+ qw/VMG_COMPAT_SCALAR_LENGTH_NOLEN/,
qw/VMG_PERL_PATCHLEVEL/,
- qw/VMG_THREADSAFE/,
+ qw/VMG_THREADSAFE VMG_FORKSAFE/,
qw/VMG_OP_INFO_NAME VMG_OP_INFO_OBJECT/
]
);
=head1 COPYRIGHT & LICENSE
-Copyright 2007-2009 Vincent Pit, all rights reserved.
+Copyright 2007,2008,2009,2010 Vincent Pit, all rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.