accessor.pm
来自「视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.」· PM 代码 · 共 751 行 · 第 1/2 页
PM
751 行
# of 'some_accessor'See the C<SYNOPSIS> for more examples.=cut### custom 'can' as UNIVERSAL::can ignores autoloadsub can { my($self, $method) = @_; ### it's one of our regular methods if( $self->UNIVERSAL::can($method) ) { __PACKAGE__->___debug( "Can '$method' -- provided by package" ); return $self->UNIVERSAL::can($method); } ### it's an accessor we provide; if( UNIVERSAL::isa( $self, 'HASH' ) and exists $self->{$method} ) { __PACKAGE__->___debug( "Can '$method' -- provided by object" ); return sub { $self->$method(@_); } } ### we don't support it __PACKAGE__->___debug( "Cannot '$method'" ); return;}### don't autoload thissub DESTROY { 1 };### use autoload so we can have per-object accessors,### not per class, as that is incorrectsub AUTOLOAD { my $self = shift; my($method) = ($AUTOLOAD =~ /([^:']+$)/); my $val = $self->___autoload( $method, @_ ) or return; return $val->[0];}sub ___autoload { my $self = shift; my $method = shift; my $assign = scalar @_; # is this an assignment? ### a method on our object if( UNIVERSAL::isa( $self, 'HASH' ) ) { if ( not exists $self->{$method} ) { __PACKAGE__->___error("No such accessor '$method'", 1); return; } ### a method on something else, die with a descriptive error; } else { local $FATAL = 1; __PACKAGE__->___error( "You called '$AUTOLOAD' on '$self' which was interpreted by ". __PACKAGE__ . " as an object call. Did you mean to include ". "'$method' from somewhere else?", 1 ); } ### assign? my $val = $assign ? shift(@_) : $self->___get( $method ); if( $assign ) { ### any binding? if( $_[0] ) { if( ref $_[0] and UNIVERSAL::isa( $_[0], 'SCALAR' ) ) { ### tie the reference, so we get an object and ### we can use it's going out of scope to restore ### the old value my $cur = $self->{$method}->[VALUE]; tie ${$_[0]}, __PACKAGE__ . '::TIE', sub { $self->$method( $cur ) }; ${$_[0]} = $val; } else { __PACKAGE__->___error( "Can not bind '$method' to anything but a SCALAR", 1 ); } } ### need to check the value? if( exists $self->{$method}->[ALLOW] ) { ### double assignment due to 'used only once' warnings local $Params::Check::VERBOSE = 0; local $Params::Check::VERBOSE = 0; allow( $val, $self->{$method}->[ALLOW] ) or ( __PACKAGE__->___error( "'$val' is an invalid value for '$method'", 1), return ); } } ### callbacks? if( my $sub = $self->___callback ) { $val = eval { $sub->( $self, $method, ($assign ? [$val] : []) ) }; ### register the error $self->___error( $@, 1 ), return if $@; } ### now we can actually assign it if( $assign ) { $self->___set( $method, $val ) or return; } return [$val];}=head2 $val = $self->___get( METHOD_NAME );Method to directly access the value of the given accessor in theobject. It circumvents all calls to allow checks, callbakcs, etc.Use only if you C<Know What You Are Doing>! General usage for this functionality would be in your own custom callbacks.=cut### XXX O::A::lvalue is mirroring this behaviour! if this### changes, lvalue's autoload must be changed as wellsub ___get { my $self = shift; my $method = shift or return; return $self->{$method}->[VALUE];}=head2 $bool = $self->___set( METHOD_NAME => VALUE );Method to directly set the value of the given accessor in theobject. It circumvents all calls to allow checks, callbakcs, etc.Use only if you C<Know What You Are Doing>! General usage for this functionality would be in your own custom callbacks.=cut sub ___set { my $self = shift; my $method = shift or return; ### you didn't give us a value to set! exists $_[0] or return; my $val = shift; ### if there's more arguments than $self, then ### replace the method called by the accessor. ### XXX implement rw vs ro accessors! $self->{$method}->[VALUE] = $val; return 1;}sub ___debug { return unless $DEBUG; my $self = shift; my $msg = shift; my $lvl = shift || 0; local $Carp::CarpLevel += 1; carp($msg);}sub ___error { my $self = shift; my $msg = shift; my $lvl = shift || 0; local $Carp::CarpLevel += ($lvl + 1); $FATAL ? croak($msg) : carp($msg);}### objects might be overloaded.. if so, we can't trust what "$self"### will return, which might get *really* painful.. so check for that### and get their unoverloaded stringval if needed.sub ___callback { my $self = shift; my $sub = shift; my $mem = overload::Overloaded( $self ) ? overload::StrVal( $self ) : "$self"; $self->{$mem} = $sub if $sub; return $self->{$mem};}=head1 LVALUE ACCESSORSC<Object::Accessor> supports C<lvalue> attributes as well. To enablethese, you should create your objects in the designated namespace,C<Object::Accessor::Lvalue>. For example: my $obj = Object::Accessor::Lvalue->new('foo'); $obj->foo += 1; print $obj->foo; will actually print C<1> and work as expected. Since this is anoptional feature, that's not desirable in all cases, we requireyou to explicitly use the C<Object::Accessor::Lvalue> class.Doing the same on the standard C<Object>>Accessor> class wouldgenerate the following code & errors: my $obj = Object::Accessor->new('foo'); $obj->foo += 1; Can't modify non-lvalue subroutine callNote that C<lvalue> support on C<AUTOLOAD> routines is aC<perl 5.8.x> feature. See perldoc L<perl58delta> for details.=head2 CAVEATS=over 4=item * Allow handlersDue to the nature of C<lvalue subs>, we never get access to thevalue you are assigning, so we can not check it againt your allowhandler. Allow handlers are therefor unsupported under C<lvalue>conditions.See C<perldoc perlsub> for details.=item * CallbacksDue to the nature of C<lvalue subs>, we never get access to thevalue you are assigning, so we can not check provide this valueto your callback. Furthermore, we can not distinguish betweena C<get> and a C<set> call. Callbacks are therefor unsupported under C<lvalue> conditions.See C<perldoc perlsub> for details.=cut{ package Object::Accessor::Lvalue; use base 'Object::Accessor'; use strict; use vars qw[$AUTOLOAD]; ### constants needed to access values from the objects *VALUE = *Object::Accessor::VALUE; *ALLOW = *Object::Accessor::ALLOW; ### largely copied from O::A::Autoload sub AUTOLOAD : lvalue { my $self = shift; my($method) = ($AUTOLOAD =~ /([^:']+$)/); $self->___autoload( $method, @_ ) or return; ### *dont* add return to it, or it won't be stored ### see perldoc perlsub on lvalue subs ### XXX can't use $self->___get( ... ), as we MUST have ### the container that's used for the lvalue assign as ### the last statement... :( $self->{$method}->[ VALUE() ]; } sub mk_accessors { my $self = shift; my $is_hash = UNIVERSAL::isa( $_[0], 'HASH' ); $self->___error( "Allow handlers are not supported for '". __PACKAGE__ ."' objects" ) if $is_hash; return $self->SUPER::mk_accessors( @_ ); } sub register_callback { my $self = shift; $self->___error( "Callbacks are not supported for '". __PACKAGE__ ."' objects" ); return; } } ### standard tie class for bound attributes{ package Object::Accessor::TIE; use Tie::Scalar; use Data::Dumper; use base 'Tie::StdScalar'; my %local = (); sub TIESCALAR { my $class = shift; my $sub = shift; my $ref = undef; my $obj = bless \$ref, $class; ### store the restore sub $local{ $obj } = $sub; return $obj; } sub DESTROY { my $tied = shift; my $sub = delete $local{ $tied }; ### run the restore sub to set the old value back return $sub->(); } }=head1 GLOBAL VARIABLES=head2 $Object::Accessor::FATALSet this variable to true to make all attempted access to non-existantaccessors be fatal.This defaults to C<false>.=head2 $Object::Accessor::DEBUGSet this variable to enable debugging output.This defaults to C<false>.=head1 TODO=head2 Create read-only accessorsCurrently all accessors are read/write for everyone. Perhaps a futurerelease should make it possible to have read-only accessors as well.=head1 CAVEATSIf you use codereferences for your allow handlers, you will not be ableto freeze the data structures using C<Storable>.Due to a bug in storable (until at least version 2.15), C<qr//> compiled regexes also don't de-serialize properly. Although this bug has been reported, you should be aware of this issue when serializing your objects.You can track the bug here: http://rt.cpan.org/Ticket/Display.html?id=1827=head1 AUTHORThis module byJos Boumans E<lt>kane@cpan.orgE<gt>.=head1 COPYRIGHTThis module iscopyright (c) 2004-2005 Jos Boumans E<lt>kane@cpan.orgE<gt>.All rights reserved.This library is free software;you may redistribute and/or modify it under the sameterms as Perl itself.=cut1;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?