package IO::Scalar;
use Carp;
use strict;
use vars qw($VERSION @ISA);
use IO::Handle;
use 5.005;
use overload '""' => sub { ${*{$_[0]}->{SR}} };
use overload 'bool' => sub { 1 };
$VERSION = "2.110";
@ISA = qw(IO::Handle);
require IO::WrapTie and push @ISA, 'IO::WrapTie::Slave' if ($] >= 5.004);
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = bless \do { local *FH }, $class;
tie *$self, $class, $self;
$self->open(@_); $self;
}
sub DESTROY {
shift->close;
}
sub open {
my ($self, $sref) = @_;
defined($sref) or do {my $s = ''; $sref = \$s};
(ref($sref) eq "SCALAR") or croak "open() needs a ref to a scalar";
*$self->{Pos} = 0; *$self->{SR} = $sref; $self;
}
sub opened {
*{shift()}->{SR};
}
sub close {
my $self = shift;
%{*$self} = ();
1;
}
sub flush { "0 but true" }
sub getc {
my $self = shift;
return undef if $self->eof;
substr(${*$self->{SR}}, *$self->{Pos}++, 1);
}
sub getline {
my $self = shift;
return undef if $self->eof;
my $sr = *$self->{SR};
my $i = *$self->{Pos};
if (!defined($/)) {
*$self->{Pos} = length $$sr;
return substr($$sr, $i);
}
elsif ($/ eq "\012") {
my $len = length($$sr);
for (; $i < $len; ++$i) {
last if ord (substr ($$sr, $i, 1)) == 10;
}
my $line;
if ($i < $len) { $line = substr ($$sr, *$self->{Pos}, $i - *$self->{Pos} + 1);
*$self->{Pos} = $i+1; }
else { $line = substr ($$sr, *$self->{Pos}, $i - *$self->{Pos});
*$self->{Pos} = $len;
}
return $line;
}
elsif (ref($/)) {
my $len = length($$sr);
my $i = ${$/} + 0;
my $line = substr ($$sr, *$self->{Pos}, $i);
*$self->{Pos} += $i;
*$self->{Pos} = $len if (*$self->{Pos} > $len);
return $line;
}
else {
pos($$sr) = $i;
length($/) or
(($$sr =~ m/\G\n*/g) and ($i = pos($$sr)));
if (length($/)
? $$sr =~ m,\Q$/\E,g : $$sr =~ m,\n\n,g ) {
*$self->{Pos} = pos $$sr;
return substr($$sr, $i, *$self->{Pos}-$i);
}
else {
*$self->{Pos} = length $$sr;
return substr($$sr, $i);
}
}
}
sub getlines {
my $self = shift;
wantarray or croak("can't call getlines in scalar context!");
my ($line, @lines);
push @lines, $line while (defined($line = $self->getline));
@lines;
}
sub print {
my $self = shift;
*$self->{Pos} = length(${*$self->{SR}} .= join('', @_) . (defined($\) ? $\ : ""));
1;
}
sub _unsafe_print {
my $self = shift;
my $append = join('', @_) . $\;
${*$self->{SR}} .= $append;
*$self->{Pos} += length($append);
1;
}
sub _old_print {
my $self = shift;
${*$self->{SR}} .= join('', @_) . $\;
*$self->{Pos} = length(${*$self->{SR}});
1;
}
sub read {
my $self = $_[0];
my $n = $_[2];
my $off = $_[3] || 0;
my $read = substr(${*$self->{SR}}, *$self->{Pos}, $n);
$n = length($read);
*$self->{Pos} += $n;
($off ? substr($_[1], $off) : $_[1]) = $read;
return $n;
}
sub write {
my $self = $_[0];
my $n = $_[2];
my $off = $_[3] || 0;
my $data = substr($_[1], $off, $n);
$n = length($data);
$self->print($data);
return $n;
}
sub sysread {
my $self = shift;
$self->read(@_);
}
sub syswrite {
my $self = shift;
$self->write(@_);
}
sub autoflush {}
sub binmode {}
sub clearerr { 1 }
sub eof {
my $self = shift;
(*$self->{Pos} >= length(${*$self->{SR}}));
}
sub seek {
my ($self, $pos, $whence) = @_;
my $eofpos = length(${*$self->{SR}});
if ($whence == 0) { *$self->{Pos} = $pos } elsif ($whence == 1) { *$self->{Pos} += $pos } elsif ($whence == 2) { *$self->{Pos} = $eofpos + $pos} else { croak "bad seek whence ($whence)" }
if (*$self->{Pos} < 0) { *$self->{Pos} = 0 }
if (*$self->{Pos} > $eofpos) { *$self->{Pos} = $eofpos }
return 1;
}
sub sysseek {
my $self = shift;
$self->seek (@_);
}
sub tell { *{shift()}->{Pos} }
sub use_RS {
my ($self, $yesno) = @_;
carp "use_RS is deprecated and ignored; \$/ is always consulted\n";
}
sub setpos { shift->seek($_[0],0) }
*getpos = \&tell;
sub sref { *{shift()}->{SR} }
sub TIEHANDLE {
((defined($_[1]) && UNIVERSAL::isa($_[1], "IO::Scalar"))
? $_[1]
: shift->new(@_));
}
sub GETC { shift->getc(@_) }
sub PRINT { shift->print(@_) }
sub PRINTF { shift->print(sprintf(shift, @_)) }
sub READ { shift->read(@_) }
sub READLINE { wantarray ? shift->getlines(@_) : shift->getline(@_) }
sub WRITE { shift->write(@_); }
sub CLOSE { shift->close(@_); }
sub SEEK { shift->seek(@_); }
sub TELL { shift->tell(@_); }
sub EOF { shift->eof(@_); }
1;
__END__