home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
perl-5.003-bin.lha
/
lib
/
perl5
/
FileHandle.pm
< prev
next >
Wrap
Text File
|
1996-10-09
|
10KB
|
468 lines
package FileHandle;
=head1 NAME
FileHandle - supply object methods for filehandles
=head1 SYNOPSIS
use FileHandle;
$fh = new FileHandle;
if ($fh->open "< file") {
print <$fh>;
$fh->close;
}
$fh = new FileHandle "> FOO";
if (defined $fh) {
print $fh "bar\n";
$fh->close;
}
$fh = new FileHandle "file", "r";
if (defined $fh) {
print <$fh>;
undef $fh; # automatically closes the file
}
$fh = new FileHandle "file", O_WRONLY|O_APPEND;
if (defined $fh) {
print $fh "corge\n";
undef $fh; # automatically closes the file
}
$pos = $fh->getpos;
$fh->setpos $pos;
$fh->setvbuf($buffer_var, _IOLBF, 1024);
($readfh, $writefh) = FileHandle::pipe;
autoflush STDOUT 1;
=head1 DESCRIPTION
C<FileHandle::new> creates a C<FileHandle>, which is a reference to a
newly created symbol (see the C<Symbol> package). If it receives any
parameters, they are passed to C<FileHandle::open>; if the open fails,
the C<FileHandle> object is destroyed. Otherwise, it is returned to
the caller.
C<FileHandle::new_from_fd> creates a C<FileHandle> like C<new> does.
It requires two parameters, which are passed to C<FileHandle::fdopen>;
if the fdopen fails, the C<FileHandle> object is destroyed.
Otherwise, it is returned to the caller.
C<FileHandle::open> accepts one parameter or two. With one parameter,
it is just a front end for the built-in C<open> function. With two
parameters, the first parameter is a filename that may include
whitespace or other special characters, and the second parameter is
the open mode in either Perl form (">", "+<", etc.) or POSIX form
("w", "r+", etc.).
C<FileHandle::fdopen> is like C<open> except that its first parameter
is not a filename but rather a file handle name, a FileHandle object,
or a file descriptor number.
If the C functions fgetpos() and fsetpos() are available, then
C<FileHandle::getpos> returns an opaque value that represents the
current position of the FileHandle, and C<FileHandle::setpos> uses
that value to return to a previously visited position.
If the C function setvbuf() is available, then C<FileHandle::setvbuf>
sets the buffering policy for the FileHandle. The calling sequence
for the Perl function is the same as its C counterpart, including the
macros C<_IOFBF>, C<_IOLBF>, and C<_IONBF>, except that the buffer
parameter specifies a scalar variable to use as a buffer. WARNING: A
variable used as a buffer by C<FileHandle::setvbuf> must not be
modified in any way until the FileHandle is closed or until
C<FileHandle::setvbuf> is called again, or memory corruption may
result!
See L<perlfunc> for complete descriptions of each of the following
supported C<FileHandle> methods, which are just front ends for the
corresponding built-in functions:
close
fileno
getc
gets
eof
clearerr
seek
tell
See L<perlvar> for complete descriptions of each of the following
supported C<FileHandle> methods:
autoflush
output_field_separator
output_record_separator
input_record_separator
input_line_number
format_page_number
format_lines_per_page
format_lines_left
format_name
format_top_name
format_line_break_characters
format_formfeed
Furthermore, for doing normal I/O you might need these:
=over
=item $fh->print
See L<perlfunc/print>.
=item $fh->printf
See L<perlfunc/printf>.
=item $fh->getline
This works like <$fh> described in L<perlop/"I/O Operators">
except that it's more readable and can be safely called in an
array context but still returns just one line.
=item $fh->getlines
This works like <$fh> when called in an array context to
read all the remaining lines in a file, except that it's more readable.
It will also croak() if accidentally called in a scalar context.
=back
=head1 SEE ALSO
L<perlfunc>,
L<perlop/"I/O Operators">,
L<POSIX/"FileHandle">
=head1 BUGS
Due to backwards compatibility, all filehandles resemble objects
of class C<FileHandle>, or actually classes derived from that class.
They actually aren't. Which means you can't derive your own
class from C<FileHandle> and inherit those methods.
=cut
require 5.000;
use vars qw($VERSION @EXPORT @EXPORT_OK $AUTOLOAD);
use Carp;
use Symbol;
use SelectSaver;
require Exporter;
require DynaLoader;
@ISA = qw(Exporter DynaLoader);
$VERSION = "1.00" ;
@EXPORT = qw(_IOFBF _IOLBF _IONBF);
@EXPORT_OK = qw(
autoflush
output_field_separator
output_record_separator
input_record_separator
input_line_number
format_page_number
format_lines_per_page
format_lines_left
format_name
format_top_name
format_line_break_characters
format_formfeed
print
printf
getline
getlines
);
################################################
## If the Fcntl extension is available,
## export its constants.
##
sub import {
my $pkg = shift;
my $callpkg = caller;
Exporter::export $pkg, $callpkg;
eval {
require Fcntl;
Exporter::export 'Fcntl', $callpkg;
};
};
################################################
## Interaction with the XS.
##
eval {
bootstrap FileHandle;
};
if ($@) {
*constant = sub { undef };
}
sub AUTOLOAD {
if ($AUTOLOAD =~ /::(_?[a-z])/) {
$AutoLoader::AUTOLOAD = $AUTOLOAD;
goto &AutoLoader::AUTOLOAD
}
my $constname = $AUTOLOAD;
$constname =~ s/.*:://;
my $val = constant($constname);
defined $val or croak "$constname is not a valid FileHandle macro";
*$AUTOLOAD = sub { $val };
goto &$AUTOLOAD;
}
################################################
## Constructors, destructors.
##
sub new {
@_ >= 1 && @_ <= 3 or croak 'usage: new FileHandle [FILENAME [,MODE]]';
my $class = shift;
my $fh = gensym;
if (@_) {
FileHandle::open($fh, @_)
or return undef;
}
bless $fh, $class;
}
sub new_from_fd {
@_ == 3 or croak 'usage: new_from_fd FileHandle FD, MODE';
my $class = shift;
my $fh = gensym;
FileHandle::fdopen($fh, @_)
or return undef;
bless $fh, $class;
}
sub DESTROY {
my ($fh) = @_;
close($fh);
}
################################################
## Open and close.
##
sub pipe {
@_ and croak 'usage: FileHandle::pipe()';
my $readfh = new FileHandle;
my $writefh = new FileHandle;
pipe($readfh, $writefh)
or return undef;
($readfh, $writefh);
}
sub _open_mode_string {
my ($mode) = @_;
$mode =~ /^\+?(<|>>?)$/
or $mode =~ s/^r(\+?)$/$1</
or $mode =~ s/^w(\+?)$/$1>/
or $mode =~ s/^a(\+?)$/$1>>/
or croak "FileHandle: bad open mode: $mode";
$mode;
}
sub open {
@_ >= 2 && @_ <= 4 or croak 'usage: $fh->open(FILENAME [,MODE [,PERMS]])';
my ($fh, $file) = @_;
if (@_ > 2) {
my ($mode, $perms) = @_[2, 3];
if ($mode =~ /^\d+$/) {
defined $perms or $perms = 0666;
return sysopen($fh, $file, $mode, $perms);
}
$file = "./" . $file unless $file =~ m#^/#;
$file = _open_mode_string($mode) . " $file\0";
}
open($fh, $file);
}
sub fdopen {
@_ == 3 or croak 'usage: $fh->fdopen(FD, MODE)';
my ($fh, $fd, $mode) = @_;
if (ref($fd) =~ /GLOB\(/) {
# It's a glob reference; remove the star from its name.
($fd = "".$$fd) =~ s/^\*//;
} elsif ($fd =~ m#^\d+$#) {
# It's an FD number; prefix with "=".
$fd = "=$fd";
}
open($fh, _open_mode_string($mode) . '&' . $fd);
}
sub close {
@_ == 1 or croak 'usage: $fh->close()';
close($_[0]);
}
################################################
## Normal I/O functions.
##
sub fileno {
@_ == 1 or croak 'usage: $fh->fileno()';
fileno($_[0]);
}
sub getc {
@_ == 1 or croak 'usage: $fh->getc()';
getc($_[0]);
}
sub gets {
@_ == 1 or croak 'usage: $fh->gets()';
my ($handle) = @_;
scalar <$handle>;
}
sub eof {
@_ == 1 or croak 'usage: $fh->eof()';
eof($_[0]);
}
sub clearerr {
@_ == 1 or croak 'usage: $fh->clearerr()';
seek($_[0], 0, 1);
}
sub seek {
@_ == 3 or croak 'usage: $fh->seek(POS, WHENCE)';
seek($_[0], $_[1], $_[2]);
}
sub tell {
@_ == 1 or croak 'usage: $fh->tell()';
tell($_[0]);
}
sub print {
@_ or croak 'usage: $fh->print([ARGS])';
my $this = shift;
print $this @_;
}
sub printf {
@_ or croak 'usage: $fh->printf([ARGS])';
my $this = shift;
printf $this @_;
}
sub getline {
@_ == 1 or croak 'usage: $fh->getline';
my $this = shift;
return scalar <$this>;
}
sub getlines {
@_ == 1 or croak 'usage: $fh->getline()';
my $this = shift;
wantarray or croak "Can't call FileHandle::getlines in a scalar context";
return <$this>;
}
################################################
## State modification functions.
##
sub autoflush {
my $old = new SelectSaver qualify($_[0], caller);
my $prev = $|;
$| = @_ > 1 ? $_[1] : 1;
$prev;
}
sub output_field_separator {
my $old = new SelectSaver qualify($_[0], caller);
my $prev = $,;
$, = $_[1] if @_ > 1;
$prev;
}
sub output_record_separator {
my $old = new SelectSaver qualify($_[0], caller);
my $prev = $\;
$\ = $_[1] if @_ > 1;
$prev;
}
sub input_record_separator {
my $old = new SelectSaver qualify($_[0], caller);
my $prev = $/;
$/ = $_[1] if @_ > 1;
$prev;
}
sub input_line_number {
my $old = new SelectSaver qualify($_[0], caller);
my $prev = $.;
$. = $_[1] if @_ > 1;
$prev;
}
sub format_page_number {
my $old = new SelectSaver qualify($_[0], caller);
my $prev = $%;
$% = $_[1] if @_ > 1;
$prev;
}
sub format_lines_per_page {
my $old = new SelectSaver qualify($_[0], caller);
my $prev = $=;
$= = $_[1] if @_ > 1;
$prev;
}
sub format_lines_left {
my $old = new SelectSaver qualify($_[0], caller);
my $prev = $-;
$- = $_[1] if @_ > 1;
$prev;
}
sub format_name {
my $old = new SelectSaver qualify($_[0], caller);
my $prev = $~;
$~ = qualify($_[1], caller) if @_ > 1;
$prev;
}
sub format_top_name {
my $old = new SelectSaver qualify($_[0], caller);
my $prev = $^;
$^ = qualify($_[1], caller) if @_ > 1;
$prev;
}
sub format_line_break_characters {
my $old = new SelectSaver qualify($_[0], caller);
my $prev = $:;
$: = $_[1] if @_ > 1;
$prev;
}
sub format_formfeed {
my $old = new SelectSaver qualify($_[0], caller);
my $prev = $^L;
$^L = $_[1] if @_ > 1;
$prev;
}
1;