Name
Tie::Handle::Base - A base class for tied filehandles
Synopsis
package Tie::Handle::Mine;
use parent 'Tie::Handle::Base';
sub WRITE {
my $self = shift;
print STDERR "Debug: Output '$_[0]'\n";
return $self->SUPER::WRITE(@_);
}
Then use your custom tied handle:
open my $fh, '>', $filename or die $!;
$fh = Tie::Handle::Mine->new($fh); # replace orig. handle with tied
print $fh "Hello, World"; # debug message will be printed
close $fh;
Description
Tie::Handle::Base
is a base class for tied filehandles. It is similar to Tie::StdHandle, but provides a few more features, and is compatible down to Perl 5.8.1. It tries to be as transparent as possible (one limitation is that sysread
and syswrite
are only emulated, as described in "READ").
A few limitations that exist in Tie::StdHandle (at least versions up to and including 4.4) have been lifted: BINMODE
accepts the LAYER
argument, and WRITE
will return the length of the string written.
This documentation describes version 0.18 of this module.
See Also: perltie, "tie" in perlfunc, Tie::Handle, Tie::StdHandle
Examples
Debugging
This is a slightly "fancier" version of the example presented in the "Synopsis", this prints all calls on the tied handle using Class::Method::Modifiers's before
and Data::Dump.
package Tie::Handle::Debug;
use parent 'Tie::Handle::Base';
use Class::Method::Modifiers 'before';
use Data::Dump 'dd';
for my $method (@Tie::Handle::Base::ALL_METHODS) {
before $method => sub { dd $method, @_[1..$#_] };
}
Tee
Here is a simple "tee" implementation - anything written to the tied handle via print
, printf
, and syswrite
will end up being written to all handles given to new
(the first handle being the "main" handle that all the other I/O functions in this example, including close
, are performed on).
package Tie::Handle::Tee;
use parent 'Tie::Handle::Base';
sub TIEHANDLE {
my ($class,$main,@others) = @_;
my $self = $class->SUPER::TIEHANDLE($main);
$self->{others} = \@others;
return $self;
}
sub WRITE {
my $self = shift;
$self->inner_write($_, @_) for @{$self->{others}};
return $self->SUPER::WRITE(@_);
}
Note that you may wrap one tied handle in another - for example, my $fh = Tie::Handle::Debug->new( Tie::Handle::Tee->new(@handles) )
.
Methods
This section documents the methods of this class. Those methods that wrap/emulate Perl's functionality also attempt to emulate the return values of the original Perl functions.
new
new
will create a new lexical filehandle, tie
it to the class (thus invoking "TIEHANDLE"), and return that filehandle. Any arguments to new
are passed through to TIEHANDLE
, including the (optional) inner handle as the first argument.
It is recommended for subclasses to override TIEHANDLE
instead of new
, as this will provide a more consistent interface for users wishing to use Perl's tie
instead of new
.
TIEHANDLE
This method takes a single optional argument, which is the inner handle which is wrapped by the tied handle. If this inner handle is not given, the method will create a new lexical filehandle that is otherwise uninitialized. The method then creates a new hashref which will serve as the object of the specified class, and which implements the tied interface based on this class. This object is also what is returned by tied(*$handle)
.
Subclasses may store whatever they like in this hashref, except that keys beginning with two underscores (__
) are reserved for this base class. Subclasses overriding this method should still call it via the usual $class->SUPER::TIEHANDLE(...)
.
UNTIE
and DESTROY
These methods discard the inner handle which this class wraps. Subclasses overriding these methods should call the superclass methods.
innerhandle
This method returns the inner handle which is wrapped by this class.
Subclasses wishing to change the inner handle may do so with the set_inner_handle
method, which takes a single argument, the new inner handle.
OPEN
This implementation will first call the FILENO
method and check for defined
ness to see if the inner handle is still open, and if it is, call the CLOSE
method before calling Perl's open
to open the inner handle.
open_parse
This is a simple utility method that tries to parse a two-argument open
and return arguments corresponding to a three-argument open
. It currently does not do much validation, because it is assumed you will be implementing the code to act on the returned mode yourself.
sub OPEN {
my $self = shift;
croak "bad number of arguments to open" if @_<1||@_>2;
my ($mode,$filename) = Tie::Handle::Base::open_parse(@_);
...
Note that if you pass open_parse
two arguments instead of just one, they will simply be passed through. An open
with no arguments or more than two arguments is not (yet) supported by this function.
PRINT
, PRINTF
, and WRITE
The methods PRINT
and PRINTF
emulate the Perl functions by the same name by building the output strings and passing them to the WRITE
method. This means that subclasses can modify output behavior by overriding only the WRITE
method. WRITE
itself is simply a call to "inner_write".
inner_write
This function, intended for use by subclasses, may be called as either a simple function, or as a method on the object, so that subclasses may call $self->inner_write($handle, ...)
. In either case, the argument list must be the same as that of syswrite
, including the filehandle which to output on as the first argument. This function emulates syswrite
behavior using substr
and Perl's print
. It does not use syswrite
internally in order to be analogous to the "READ" implementation.
READ
Perl's tied filehandle interface will call this method for both read
and sysread
calls. This method calls Perl's read
, not sysread
, because the latter would bypass buffered I/O and cause confusion with other buffered I/O methods such as seek
, tell
, and eof
.
This means that one limitation of this base class is that, while users may call sysread
and syswrite
on the tied handles, these calls will not be translated into sysread/write
calls on the inner, wrapped handle. (See "inner_write" regarding syswrite
.)
All Other Methods
The methods BINMODE
, CLOSE
, EOF
, FILENO
, GETC
, READLINE
, SEEK
, and TELL
are implemented in this class by calling the Perl functions of the same name.
The full list of methods that tied handles can/should implement is as follows. The list of names is provided as @Tie::Handle::Base::ALL_METHODS
, and the list @Tie::Handle::Base::IO_METHODS
excludes TIEHANDLE
, UNTIE
, and DESTROY
.
-- Method of the "tie" Interface ------------+-- Perl Prototype* ----
BINMODE this | binmode (*;$)
CLOSE this | close (;*)
EOF this | eof (;*)
FILENO this | fileno (*)
GETC this | getc (;*)
OPEN this, filename / OPEN this, mode, LIST | open (*;$@)
PRINT this, LIST | print none*
PRINTF this, format, LIST | printf none*
READ this, scalar, length, offset | (sys)read (*\$$;$)
READLINE this | readline (;*)
SEEK this, offset, whence | seek (*$$)
TELL this | tell (;*)
WRITE this, scalar, length, offset | syswrite (*$;$$)
TIEHANDLE classname, LIST | tie (\[$@%*]$@)
UNTIE this | untie (\[$@%*])
DESTROY this | N/A
* Prototypes as reported by the prototype function as of Perl 5.26. Note that print
and printf
get special handling by Perl and therefore do not report a standard prototype.
Author, Copyright, and License
Copyright (c) 2017-2023 Hauke Daempfling (haukex@zero-g.net) at the Leibniz Institute of Freshwater Ecology and Inland Fisheries (IGB), Berlin, Germany, http://www.igb-berlin.de/
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.