3 # Copyright 1998-2005 Gisle Aas.
5 # This library is free software; you can redistribute it and/or
6 # modify it under the same terms as Perl itself.
10 use vars qw($VERSION $DEBUG $IO_CONSTANTS);
11 $VERSION = "1.08"; # $Date: 2007/02/05 17:08:37 $
17 my $self = bless Symbol::gensym(), ref($class) || $class;
25 return $self->new(@_) unless ref($self);
28 my $bufref = ref( $_[0] ) ? $_[0] : \$_[0];
29 $$bufref = "" unless defined $$bufref;
30 *$self->{buf} = $bufref;
33 *$self->{buf} = \$buf;
42 my $old = *$self->{pad};
43 *$self->{pad} = substr( $_[0], 0, 1 ) if @_;
44 return "\0" unless defined($old) && length($old);
51 print Data::Dumper->Dump( [$self], ['*self'] );
52 print Data::Dumper->Dump( [ *$self{HASH} ], ['$self{HASH}'] );
57 print "TIEHANDLE @_\n" if $DEBUG;
58 return $_[0] if ref( $_[0] );
60 my $self = bless Symbol::gensym(), $class;
66 print "DESTROY @_\n" if $DEBUG;
74 undef *$self if $] eq "5.008"; # workaround for some bug
80 return defined *$self->{buf};
87 # XXX don't know much about layers yet :-(
94 return $buf if $self->read( $buf, 1 );
100 $self->setpos( $self->getpos() - 1 );
106 return length( ${ *$self->{buf} } ) <= *$self->{pos};
113 $self->write( join( $,, @_ ) . $\ );
115 $self->write( join( "", @_ ) . $\ );
119 $self->write( join( $,, @_ ) );
121 $self->write( join( "", @_ ) );
126 *printflush = \*print;
130 print "PRINTF(@_)\n" if $DEBUG;
132 $self->write( sprintf( $fmt, @_ ) );
136 my ( $SEEK_SET, $SEEK_CUR, $SEEK_END );
138 sub _init_seek_constants {
141 $SEEK_SET = &IO::Handle::SEEK_SET;
142 $SEEK_CUR = &IO::Handle::SEEK_CUR;
143 $SEEK_END = &IO::Handle::SEEK_END;
152 my ( $self, $off, $whence ) = @_;
153 my $buf = *$self->{buf} || return 0;
154 my $len = length($$buf);
155 my $pos = *$self->{pos};
157 _init_seek_constants() unless defined $SEEK_SET;
159 if ( $whence == $SEEK_SET ) { $pos = $off }
160 elsif ( $whence == $SEEK_CUR ) { $pos += $off }
161 elsif ( $whence == $SEEK_END ) { $pos = $len + $off }
162 else { die "Bad whence ($whence)" }
163 print "SEEK(POS=$pos,OFF=$off,LEN=$len)\n" if $DEBUG;
165 $pos = 0 if $pos < 0;
166 $self->truncate($pos) if $pos > $len; # extend file
167 *$self->{pos} = $pos;
173 my $old = *$self->{pos};
175 my $pos = shift || 0;
176 my $buf = *$self->{buf};
177 my $len = $buf ? length($$buf) : 0;
178 $pos = $len if $pos > $len;
179 *$self->{pos} = $pos;
184 sub getpos { shift->pos; }
192 my $buf = *$self->{buf} || return;
193 my $len = length($$buf);
194 my $pos = *$self->{pos};
195 return if $pos >= $len;
197 unless ( defined $/ ) { # slurp
198 *$self->{pos} = $len;
199 return substr( $$buf, $pos );
202 unless ( length $/ ) { # paragraph mode
203 # XXX slow&lazy implementation using getc()
207 while ( defined( $c = $self->getc ) ) {
211 } elsif ( $eol > 1 ) {
219 return $para; # XXX wantarray
222 my $idx = index( $$buf, $/, $pos );
226 *$self->{pos} = $len;
227 $. = ++*$self->{lno};
228 return substr( $$buf, $pos );
230 $len = $idx - $pos + length($/);
231 *$self->{pos} += $len;
232 $. = ++*$self->{lno};
233 return substr( $$buf, $pos, $len );
237 die "getlines() called in scalar context\n" unless wantarray;
239 my ( $line, @lines );
240 push( @lines, $line ) while defined( $line = $self->getline );
245 goto &getlines if wantarray;
249 sub input_line_number {
251 my $old = *$self->{lno};
252 *$self->{lno} = shift if @_;
258 my $len = shift || 0;
259 my $buf = *$self->{buf};
260 if ( length($$buf) >= $len ) {
261 substr( $$buf, $len ) = '';
262 *$self->{pos} = $len if $len < *$self->{pos};
264 $$buf .= ( $self->pad x ( $len - length($$buf) ) );
271 my $buf = *$self->{buf};
272 return undef unless $buf;
274 my $pos = *$self->{pos};
275 my $rem = length($$buf) - $pos;
277 $len = $rem if $len > $rem;
278 return undef if $len < 0;
279 if ( @_ > 2 ) { # read offset
280 substr( $_[0], $_[2] ) = substr( $$buf, $pos, $len );
282 $_[0] = substr( $$buf, $pos, $len );
284 *$self->{pos} += $len;
290 my $buf = *$self->{buf};
293 my $pos = *$self->{pos};
294 my $slen = length( $_[0] );
298 $len = $_[1] if $_[1] < $len;
301 die "Offset outside string" if $off > $slen;
304 die "Offset outside string" if $off < 0;
306 my $rem = $slen - $off;
307 $len = $rem if $rem < $len;
310 substr( $$buf, $pos, $len ) = substr( $_[0], $off, $len );
311 *$self->{pos} += $len;
320 return unless $self->opened;
321 return 1 unless wantarray;
322 my $len = length ${ *$self->{buf} };
325 undef, undef, # dev, ino
336 int( ( $len + 511 ) / 512 ) # blocks
341 return undef; # XXX perlfunc says this means the file is closed
346 my $old = *$self->{blocking} || 0;
347 *$self->{blocking} = shift if @_;
351 my $notmuch = sub { return };
355 *clearerr = $notmuch;
362 *autoflush = $notmuch;
375 *BINMODE = \&binmode;
379 return *$self->{buf};
381 *sref = \&string_ref;
389 IO::String - Emulate file interface for in-core strings
394 $io = IO::String->new;
395 $io = IO::String->new($var);
396 tie *IO, 'IO::String';
401 read($io, $buf, 100);
404 print $io "string\n";
406 syswrite($io, $buf, 100);
409 printf "Some text %s\n", $str;
413 $io->setpos(0); # rewind
419 The C<IO::String> module provides the C<IO::File> interface for in-core
420 strings. An C<IO::String> object can be attached to a string, and
421 makes it possible to use the normal file operations for reading or
422 writing data, as well as for seeking to various locations of the string.
423 This is useful when you want to use a library module that only
424 provides an interface to file handles on data that you have in a string
427 Note that perl-5.8 and better has built-in support for "in memory"
428 files, which are set up by passing a reference instead of a filename
429 to the open() call. The reason for using this module is that it
430 makes the code backwards compatible with older versions of Perl.
432 The C<IO::String> module provides an interface compatible with
433 C<IO::File> as distributed with F<IO-1.20>, but the following methods
434 are not available: new_from_fd, fdopen, format_write,
435 format_page_number, format_lines_per_page, format_lines_left,
436 format_name, format_top_name.
438 The following methods are specific to the C<IO::String> class:
442 =item $io = IO::String->new
444 =item $io = IO::String->new( $string )
446 The constructor returns a newly-created C<IO::String> object. It
447 takes an optional argument, which is the string to read from or write
448 into. If no $string argument is given, then an internal buffer
449 (initially empty) is allocated.
451 The C<IO::String> object returned is tied to itself. This means
452 that you can use most Perl I/O built-ins on it too: readline, <>, getc,
453 print, printf, syswrite, sysread, close.
457 =item $io->open( $string )
459 Attaches an existing IO::String object to some other $string, or
460 allocates a new internal buffer (if no argument is given). The
461 position is reset to 0.
463 =item $io->string_ref
465 Returns a reference to the string that is attached to
466 the C<IO::String> object. Most useful when you let the C<IO::String>
467 create an internal buffer to write into.
471 =item $io->pad( $char )
473 Specifies the padding to use if
474 the string is extended by either the seek() or truncate() methods. It
475 is a single character and defaults to "\0".
479 =item $io->pos( $newpos )
481 Yet another interface for reading and setting the current read/write
482 position within the string (the normal getpos/setpos/tell/seek
483 methods are also available). The pos() method always returns the
484 old position, and if you pass it an argument it sets the new
487 There is (deliberately) a difference between the setpos() and seek()
488 methods in that seek() extends the string (with the specified
489 padding) if you go to a location past the end, whereas setpos()
490 just snaps back to the end. If truncate() is used to extend the string,
491 then it works as seek().
497 In Perl versions < 5.6, the TIEHANDLE interface was incomplete.
498 If you use such a Perl, then seek(), tell(), eof(), fileno(), binmode() will
499 not do anything on an C<IO::String> handle. See L<perltie> for
504 L<IO::File>, L<IO::Stringy>, L<perlfunc/open>
508 Copyright 1998-2005 Gisle Aas.
510 This library is free software; you can redistribute it and/or
511 modify it under the same terms as Perl itself.