overload.pm
来自「视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.」· PM 代码 · 共 1,462 行 · 第 1/4 页
PM
1,462 行
package overload;our $VERSION = '1.06';sub nil {}sub OVERLOAD { $package = shift; my %arg = @_; my ($sub, $fb); $ {$package . "::OVERLOAD"}{dummy}++; # Register with magic by touching. *{$package . "::()"} = \&nil; # Make it findable via fetchmethod. for (keys %arg) { if ($_ eq 'fallback') { $fb = $arg{$_}; } else { $sub = $arg{$_}; if (not ref $sub and $sub !~ /::/) { $ {$package . "::(" . $_} = $sub; $sub = \&nil; } #print STDERR "Setting `$ {'package'}::\cO$_' to \\&`$sub'.\n"; *{$package . "::(" . $_} = \&{ $sub }; } } ${$package . "::()"} = $fb; # Make it findable too (fallback only).}sub import { $package = (caller())[0]; # *{$package . "::OVERLOAD"} = \&OVERLOAD; shift; $package->overload::OVERLOAD(@_);}sub unimport { $package = (caller())[0]; ${$package . "::OVERLOAD"}{dummy}++; # Upgrade the table shift; for (@_) { if ($_ eq 'fallback') { undef $ {$package . "::()"}; } else { delete $ {$package . "::"}{"(" . $_}; } }}sub Overloaded { my $package = shift; $package = ref $package if ref $package; $package->can('()');}sub ov_method { my $globref = shift; return undef unless $globref; my $sub = \&{*$globref}; return $sub if $sub ne \&nil; return shift->can($ {*$globref});}sub OverloadedStringify { my $package = shift; $package = ref $package if ref $package; #$package->can('(""') ov_method mycan($package, '(""'), $package or ov_method mycan($package, '(0+'), $package or ov_method mycan($package, '(bool'), $package or ov_method mycan($package, '(nomethod'), $package;}sub Method { my $package = shift; if(ref $package) { local $@; local $!; require Scalar::Util; $package = Scalar::Util::blessed($package); return undef if !defined $package; } #my $meth = $package->can('(' . shift); ov_method mycan($package, '(' . shift), $package; #return $meth if $meth ne \&nil; #return $ {*{$meth}};}sub AddrRef { my $package = ref $_[0]; return "$_[0]" unless $package; local $@; local $!; require Scalar::Util; my $class = Scalar::Util::blessed($_[0]); my $class_prefix = defined($class) ? "$class=" : ""; my $type = Scalar::Util::reftype($_[0]); my $addr = Scalar::Util::refaddr($_[0]); return sprintf("$class_prefix$type(0x%x)", $addr);}*StrVal = *AddrRef;sub mycan { # Real can would leave stubs. my ($package, $meth) = @_; my $mro = mro::get_linear_isa($package); foreach my $p (@$mro) { my $fqmeth = $p . q{::} . $meth; return \*{$fqmeth} if defined &{$fqmeth}; } return undef;}%constants = ( 'integer' => 0x1000, # HINT_NEW_INTEGER 'float' => 0x2000, # HINT_NEW_FLOAT 'binary' => 0x4000, # HINT_NEW_BINARY 'q' => 0x8000, # HINT_NEW_STRING 'qr' => 0x10000, # HINT_NEW_RE );%ops = ( with_assign => "+ - * / % ** << >> x .", assign => "+= -= *= /= %= **= <<= >>= x= .=", num_comparison => "< <= > >= == !=", '3way_comparison'=> "<=> cmp", str_comparison => "lt le gt ge eq ne", binary => '& &= | |= ^ ^=', unary => "neg ! ~", mutators => '++ --', func => "atan2 cos sin exp abs log sqrt int", conversion => 'bool "" 0+', iterators => '<>', dereferencing => '${} @{} %{} &{} *{}', special => 'nomethod fallback =');use warnings::register;sub constant { # Arguments: what, sub while (@_) { if (@_ == 1) { warnings::warnif ("Odd number of arguments for overload::constant"); last; } elsif (!exists $constants {$_ [0]}) { warnings::warnif ("`$_[0]' is not an overloadable type"); } elsif (!ref $_ [1] || "$_[1]" !~ /CODE\(0x[\da-f]+\)$/) { # Can't use C<ref $_[1] eq "CODE"> above as code references can be # blessed, and C<ref> would return the package the ref is blessed into. if (warnings::enabled) { $_ [1] = "undef" unless defined $_ [1]; warnings::warn ("`$_[1]' is not a code reference"); } } else { $^H{$_[0]} = $_[1]; $^H |= $constants{$_[0]}; } shift, shift; }}sub remove_constant { # Arguments: what, sub while (@_) { delete $^H{$_[0]}; $^H &= ~ $constants{$_[0]}; shift, shift; }}1;__END__=head1 NAMEoverload - Package for overloading Perl operations=head1 SYNOPSIS package SomeThing; use overload '+' => \&myadd, '-' => \&mysub; # etc ... package main; $a = new SomeThing 57; $b=5+$a; ... if (overload::Overloaded $b) {...} ... $strval = overload::StrVal $b;=head1 DESCRIPTION=head2 Declaration of overloaded functionsThe compilation directive package Number; use overload "+" => \&add, "*=" => "muas";declares function Number::add() for addition, and method muas() inthe "class" C<Number> (or one of its base classes)for the assignment form C<*=> of multiplication.Arguments of this directive come in (key, value) pairs. Legal valuesare values legal inside a C<&{ ... }> call, so the name of asubroutine, a reference to a subroutine, or an anonymous subroutinewill all work. Note that values specified as strings areinterpreted as methods, not subroutines. Legal keys are listed below.The subroutine C<add> will be called to execute C<$a+$b> if $ais a reference to an object blessed into the package C<Number>, or if $a isnot an object from a package with defined mathemagic addition, but $b is areference to a C<Number>. It can also be called in other situations, likeC<$a+=7>, or C<$a++>. See L<MAGIC AUTOGENERATION>. (Mathemagicalmethods refer to methods triggered by an overloaded mathematicaloperator.)Since overloading respects inheritance via the @ISA hierarchy, theabove declaration would also trigger overloading of C<+> and C<*=> inall the packages which inherit from C<Number>.=head2 Calling Conventions for Binary OperationsThe functions specified in the C<use overload ...> directive are calledwith three (in one particular case with four, see L<Last Resort>)arguments. If the corresponding operation is binary, then the firsttwo arguments are the two arguments of the operation. However, due togeneral object calling conventions, the first argument should always bean object in the package, so in the situation of C<7+$a>, theorder of the arguments is interchanged. It probably does not matterwhen implementing the addition method, but whether the argumentsare reversed is vital to the subtraction method. The method canquery this information by examining the third argument, which can takethree different values:=over 7=item FALSEthe order of arguments is as in the current operation.=item TRUEthe arguments are reversed.=item C<undef>the current operation is an assignment variant (as inC<$a+=7>), but the usual function is called instead. This additionalinformation can be used to generate some optimizations. CompareL<Calling Conventions for Mutators>.=back=head2 Calling Conventions for Unary OperationsUnary operation are considered binary operations with the secondargument being C<undef>. Thus the functions that overloads C<{"++"}>is called with arguments C<($a,undef,'')> when $a++ is executed.=head2 Calling Conventions for MutatorsTwo types of mutators have different calling conventions:=over=item C<++> and C<-->The routines which implement these operators are expected to actuallyI<mutate> their arguments. So, assuming that $obj is a reference to anumber, sub incr { my $n = $ {$_[0]}; ++$n; $_[0] = bless \$n}is an appropriate implementation of overloaded C<++>. Note that sub incr { ++$ {$_[0]} ; shift }is OK if used with preincrement and with postincrement. (In the caseof postincrement a copying will be performed, see L<Copy Constructor>.)=item C<x=> and other assignment versionsThere is nothing special about these methods. They may change thevalue of their arguments, and may leave it as is. The result is goingto be assigned to the value in the left-hand-side if different fromthis value.This allows for the same method to be used as overloaded C<+=> andC<+>. Note that this is I<allowed>, but not recommended, since by thesemantic of L<"Fallback"> Perl will call the method for C<+> anyway,if C<+=> is not overloaded.=backB<Warning.> Due to the presence of assignment versions of operations,routines which may be called in assignment context may createself-referential structures. Currently Perl will not free self-referentialstructures until cycles are C<explicitly> broken. You may get problemswhen traversing your structures too.Say, use overload '+' => sub { bless [ \$_[0], \$_[1] ] };is asking for trouble, since for code C<$obj += $foo> the subroutineis called as C<$obj = add($obj, $foo, undef)>, or C<$obj = [\$obj,\$foo]>. If using such a subroutine is an important optimization, onecan overload C<+=> explicitly by a non-"optimized" version, or switchto non-optimized version if C<not defined $_[2]> (seeL<Calling Conventions for Binary Operations>).Even if no I<explicit> assignment-variants of operators are present inthe script, they may be generated by the optimizer. Say, C<",$obj,"> orC<',' . $obj . ','> may be both optimized to my $tmp = ',' . $obj; $tmp .= ',';=head2 Overloadable OperationsThe following symbols can be specified in C<use overload> directive:=over 5=item * I<Arithmetic operations> "+", "+=", "-", "-=", "*", "*=", "/", "/=", "%", "%=", "**", "**=", "<<", "<<=", ">>", ">>=", "x", "x=", ".", ".=",For these operations a substituted non-assignment variant can be called ifthe assignment variant is not available. Methods for operations C<+>,C<->, C<+=>, and C<-=> can be called to automatically generateincrement and decrement methods. The operation C<-> can be used toautogenerate missing methods for unary minus or C<abs>.See L<"MAGIC AUTOGENERATION">, L<"Calling Conventions for Mutators"> andL<"Calling Conventions for Binary Operations">) for details of thesesubstitutions.=item * I<Comparison operations> "<", "<=", ">", ">=", "==", "!=", "<=>", "lt", "le", "gt", "ge", "eq", "ne", "cmp",If the corresponding "spaceship" variant is available, it can beused to substitute for the missing operation. During C<sort>ingarrays, C<cmp> is used to compare values subject to C<use overload>.=item * I<Bit operations> "&", "&=", "^", "^=", "|", "|=", "neg", "!", "~",C<neg> stands for unary minus. If the method for C<neg> is notspecified, it can be autogenerated using the method forsubtraction. If the method for C<!> is not specified, it can be
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?