windows-nt/Source/XPSP1/NT/enduser/speech/lib/perl/io/handle.pm

540 lines
12 KiB
Perl
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
package IO::Handle;
=head1 NAME
IO::Handle - supply object methods for I/O handles
=head1 SYNOPSIS
use IO::Handle;
$fh = new IO::Handle;
if ($fh->fdopen(fileno(STDIN),"r")) {
print $fh->getline;
$fh->close;
}
$fh = new IO::Handle;
if ($fh->fdopen(fileno(STDOUT),"w")) {
$fh->print("Some text\n");
}
use IO::Handle '_IOLBF';
$fh->setvbuf($buffer_var, _IOLBF, 1024);
undef $fh; # automatically closes the file if it's open
autoflush STDOUT 1;
=head1 DESCRIPTION
C<IO::Handle> is the base class for all other IO handle classes. It is
not intended that objects of C<IO::Handle> would be created directly,
but instead C<IO::Handle> is inherited from by several other classes
in the IO hierarchy.
If you are reading this documentation, looking for a replacement for
the C<FileHandle> package, then I suggest you read the documentation
for C<IO::File>
A C<IO::Handle> object is a reference to a symbol (see the C<Symbol> package)
=head1 CONSTRUCTOR
=over 4
=item new ()
Creates a new C<IO::Handle> object.
=item new_from_fd ( FD, MODE )
Creates a C<IO::Handle> like C<new> does.
It requires two parameters, which are passed to the method C<fdopen>;
if the fdopen fails, the object is destroyed. Otherwise, it is returned
to the caller.
=back
=head1 METHODS
See L<perlfunc> for complete descriptions of each of the following
supported C<IO::Handle> methods, which are just front ends for the
corresponding built-in functions:
close
fileno
getc
eof
read
truncate
stat
print
printf
sysread
syswrite
See L<perlvar> for complete descriptions of each of the following
supported C<IO::Handle> 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
format_write
Furthermore, for doing normal I/O you might need these:
=over
=item $fh->fdopen ( FD, MODE )
C<fdopen> is like an ordinary C<open> except that its first parameter
is not a filename but rather a file handle name, a IO::Handle object,
or a file descriptor number.
=item $fh->opened
Returns true if the object is currently a valid file descriptor.
=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.
=item $fh->ungetc ( ORD )
Pushes a character with the given ordinal value back onto the given
handle's input stream.
=item $fh->write ( BUF, LEN [, OFFSET }\] )
This C<write> is like C<write> found in C, that is it is the
opposite of read. The wrapper for the perl C<write> function is
called C<format_write>.
=item $fh->flush
Flush the given handle's buffer.
=item $fh->error
Returns a true value if the given handle has experienced any errors
since it was opened or since the last call to C<clearerr>.
=item $fh->clearerr
Clear the given handle's error indicator.
=back
If the C functions setbuf() and/or setvbuf() are available, then
C<IO::Handle::setbuf> and C<IO::Handle::setvbuf> set the buffering
policy for an IO::Handle. The calling sequences for the Perl functions
are the same as their C counterparts--including the constants C<_IOFBF>,
C<_IOLBF>, and C<_IONBF> for setvbuf()--except that the buffer parameter
specifies a scalar variable to use as a buffer. WARNING: A variable
used as a buffer by C<setbuf> or C<setvbuf> must not be modified in any
way until the IO::Handle is closed or C<setbuf> or C<setvbuf> is called
again, or memory corruption may result! Note that you need to import
the constants C<_IOFBF>, C<_IOLBF>, and C<_IONBF> explicitly.
Lastly, there is a special method for working under B<-T> and setuid/gid
scripts:
=over
=item $fh->untaint
Marks the object as taint-clean, and as such data read from it will also
be considered taint-clean. Note that this is a very trusting action to
take, and appropriate consideration for the data source and potential
vulnerability should be kept in mind.
=back
=head1 NOTE
A C<IO::Handle> object is a GLOB reference. Some modules that
inherit from C<IO::Handle> may want to keep object related variables
in the hash table part of the GLOB. In an attempt to prevent modules
trampling on each other I propose the that any such module should prefix
its variables with its own name separated by _'s. For example the IO::Socket
module keeps a C<timeout> variable in 'io_socket_timeout'.
=head1 SEE ALSO
L<perlfunc>,
L<perlop/"I/O Operators">,
L<IO::File>
=head1 BUGS
Due to backwards compatibility, all filehandles resemble objects
of class C<IO::Handle>, or actually classes derived from that class.
They actually aren't. Which means you can't derive your own
class from C<IO::Handle> and inherit those methods.
=head1 HISTORY
Derived from FileHandle.pm by Graham Barr E<lt>F<bodg@tiuk.ti.com>E<gt>
=cut
require 5.000;
use strict;
use vars qw($VERSION $XS_VERSION @EXPORT_OK $AUTOLOAD @ISA);
use Carp;
use Symbol;
use SelectSaver;
require Exporter;
@ISA = qw(Exporter);
$VERSION = "1.1505";
$XS_VERSION = "1.15";
@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
format_write
print
printf
getline
getlines
SEEK_SET
SEEK_CUR
SEEK_END
_IOFBF
_IOLBF
_IONBF
);
################################################
## Interaction with the XS.
##
require DynaLoader;
@IO::ISA = qw(DynaLoader);
bootstrap IO $XS_VERSION;
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 IO::Handle macro";
no strict 'refs';
*$AUTOLOAD = sub { $val };
goto &$AUTOLOAD;
}
################################################
## Constructors, destructors.
##
sub new {
my $class = ref($_[0]) || $_[0] || "IO::Handle";
@_ == 1 or croak "usage: new $class";
my $fh = gensym;
bless $fh, $class;
}
sub new_from_fd {
my $class = ref($_[0]) || $_[0] || "IO::Handle";
@_ == 3 or croak "usage: new_from_fd $class FD, MODE";
my $fh = gensym;
shift;
IO::Handle::fdopen($fh, @_)
or return undef;
bless $fh, $class;
}
#
# There is no need for DESTROY to do anything, because when the
# last reference to an IO object is gone, Perl automatically
# closes its associated files (if any). However, to avoid any
# attempts to autoload DESTROY, we here define it to do nothing.
#
sub DESTROY {}
################################################
## Open and close.
##
sub _open_mode_string {
my ($mode) = @_;
$mode =~ /^\+?(<|>>?)$/
or $mode =~ s/^r(\+?)$/$1</
or $mode =~ s/^w(\+?)$/$1>/
or $mode =~ s/^a(\+?)$/$1>>/
or croak "IO::Handle: bad open mode: $mode";
$mode;
}
sub fdopen {
@_ == 3 or croak 'usage: $fh->fdopen(FD, MODE)';
my ($fh, $fd, $mode) = @_;
local(*GLOB);
if (ref($fd) && "".$fd =~ /GLOB\(/o) {
# It's a glob reference; Alias it as we cannot get name of anon GLOBs
my $n = qualify(*GLOB);
*GLOB = *{*$fd};
$fd = $n;
} elsif ($fd =~ m#^\d+$#) {
# It's an FD number; prefix with "=".
$fd = "=$fd";
}
open($fh, _open_mode_string($mode) . '&' . $fd)
? $fh : undef;
}
sub close {
@_ == 1 or croak 'usage: $fh->close()';
my($fh) = @_;
close($fh);
}
################################################
## Normal I/O functions.
##
# flock
# select
sub opened {
@_ == 1 or croak 'usage: $fh->opened()';
defined fileno($_[0]);
}
sub fileno {
@_ == 1 or croak 'usage: $fh->fileno()';
fileno($_[0]);
}
sub getc {
@_ == 1 or croak 'usage: $fh->getc()';
getc($_[0]);
}
sub eof {
@_ == 1 or croak 'usage: $fh->eof()';
eof($_[0]);
}
sub print {
@_ or croak 'usage: $fh->print([ARGS])';
my $this = shift;
print $this @_;
}
sub printf {
@_ >= 2 or croak 'usage: $fh->printf(FMT,[ARGS])';
my $this = shift;
printf $this @_;
}
sub getline {
@_ == 1 or croak 'usage: $fh->getline';
my $this = shift;
return scalar <$this>;
}
*gets = \&getline; # deprecated
sub getlines {
@_ == 1 or croak 'usage: $fh->getline()';
wantarray or
croak 'Can\'t call $fh->getlines in a scalar context, use $fh->getline';
my $this = shift;
return <$this>;
}
sub truncate {
@_ == 2 or croak 'usage: $fh->truncate(LEN)';
truncate($_[0], $_[1]);
}
sub read {
@_ == 3 || @_ == 4 or croak '$fh->read(BUF, LEN [, OFFSET])';
read($_[0], $_[1], $_[2], $_[3] || 0);
}
sub sysread {
@_ == 3 || @_ == 4 or croak '$fh->sysread(BUF, LEN [, OFFSET])';
sysread($_[0], $_[1], $_[2], $_[3] || 0);
}
sub write {
@_ == 3 || @_ == 4 or croak '$fh->write(BUF, LEN [, OFFSET])';
local($\) = "";
print { $_[0] } substr($_[1], $_[3] || 0, $_[2]);
}
sub syswrite {
@_ == 3 || @_ == 4 or croak '$fh->syswrite(BUF, LEN [, OFFSET])';
syswrite($_[0], $_[1], $_[2], $_[3] || 0);
}
sub stat {
@_ == 1 or croak 'usage: $fh->stat()';
stat($_[0]);
}
################################################
## State modification functions.
##
sub autoflush {
my $old = new SelectSaver qualify($_[0], caller) if ref($_[0]);
my $prev = $|;
$| = @_ > 1 ? $_[1] : 1;
$prev;
}
sub output_field_separator {
my $prev = $,;
$, = $_[1] if @_ > 1;
$prev;
}
sub output_record_separator {
my $prev = $\;
$\ = $_[1] if @_ > 1;
$prev;
}
sub input_record_separator {
my $prev = $/;
$/ = $_[1] if @_ > 1;
$prev;
}
sub input_line_number {
# localizing $. doesn't work as advertised. grrrrrr.
my $prev = $.;
$. = $_[1] if @_ > 1;
$prev;
}
sub format_page_number {
my $old = new SelectSaver qualify($_[0], caller) if ref($_[0]);
my $prev = $%;
$% = $_[1] if @_ > 1;
$prev;
}
sub format_lines_per_page {
my $old = new SelectSaver qualify($_[0], caller) if ref($_[0]);
my $prev = $=;
$= = $_[1] if @_ > 1;
$prev;
}
sub format_lines_left {
my $old = new SelectSaver qualify($_[0], caller) if ref($_[0]);
my $prev = $-;
$- = $_[1] if @_ > 1;
$prev;
}
sub format_name {
my $old = new SelectSaver qualify($_[0], caller) if ref($_[0]);
my $prev = $~;
$~ = qualify($_[1], caller) if @_ > 1;
$prev;
}
sub format_top_name {
my $old = new SelectSaver qualify($_[0], caller) if ref($_[0]);
my $prev = $^;
$^ = qualify($_[1], caller) if @_ > 1;
$prev;
}
sub format_line_break_characters {
my $prev = $:;
$: = $_[1] if @_ > 1;
$prev;
}
sub format_formfeed {
my $prev = $^L;
$^L = $_[1] if @_ > 1;
$prev;
}
sub formline {
my $fh = shift;
my $picture = shift;
local($^A) = $^A;
local($\) = "";
formline($picture, @_);
print $fh $^A;
}
sub format_write {
@_ < 3 || croak 'usage: $fh->write( [FORMAT_NAME] )';
if (@_ == 2) {
my ($fh, $fmt) = @_;
my $oldfmt = $fh->format_name($fmt);
CORE::write($fh);
$fh->format_name($oldfmt);
} else {
CORE::write($_[0]);
}
}
sub fcntl {
@_ == 3 || croak 'usage: $fh->fcntl( OP, VALUE );';
my ($fh, $op, $val) = @_;
my $r = fcntl($fh, $op, $val);
defined $r && $r eq "0 but true" ? 0 : $r;
}
sub ioctl {
@_ == 3 || croak 'usage: $fh->ioctl( OP, VALUE );';
my ($fh, $op, $val) = @_;
my $r = ioctl($fh, $op, $val);
defined $r && $r eq "0 but true" ? 0 : $r;
}
1;