1 package Test::Builder::IO::Scalar;
6 Test::Builder::IO::Scalar - A copy of IO::Scalar for Test::Builder
10 This is a copy of IO::Scalar which ships with Test::Builder to
11 support scalar references as filehandles on Perl 5.6.
15 # This is copied code, I don't care.
20 use vars qw($VERSION @ISA);
25 ### The package version, both in 1.23 style *and* usable by MakeMaker:
29 @ISA = qw(IO::Handle);
31 #==============================
39 #------------------------------
44 Return a new, unattached scalar handle.
45 If any arguments are given, they're sent to open().
51 my $class = ref($proto) || $proto;
52 my $self = bless \do { local *FH }, $class;
53 tie *$self, $class, $self;
54 $self->open(@_); ### open on anonymous by default
61 #------------------------------
63 =item open [SCALARREF]
66 Open the scalar handle on a new scalar, pointed to by SCALARREF.
67 If no SCALARREF is given, a "private" scalar is created to hold
70 Returns the self object on success, undefined on error.
75 my ($self, $sref) = @_;
78 defined($sref) or do {my $s = ''; $sref = \$s};
79 (ref($sref) eq "SCALAR") or croak "open() needs a ref to a scalar";
82 *$self->{Pos} = 0; ### seek position
83 *$self->{SR} = $sref; ### scalar reference
87 #------------------------------
92 Is the scalar handle opened on something?
100 #------------------------------
105 Disassociate the scalar handle from its underlying scalar.
106 Done automatically on destroy.
122 #==============================
124 =head2 Input and output
131 #------------------------------
136 No-op, provided for OO compatibility.
140 sub flush { "0 but true" }
142 #------------------------------
147 Return the next character, or undef if none remain.
154 ### Return undef right away if at EOF; else, move pos forward:
155 return undef if $self->eof;
156 substr(${*$self->{SR}}, *$self->{Pos}++, 1);
159 #------------------------------
164 Return the next line, or undef on end of string.
165 Can safely be called in an array context.
166 Currently, lines are delimited by "\n".
173 ### Return undef right away if at EOF:
174 return undef if $self->eof;
177 my $sr = *$self->{SR};
178 my $i = *$self->{Pos}; ### Start matching at this point.
180 ### Minimal impact implementation!
181 ### We do the fast fast thing (no regexps) if using the
182 ### classic input record separator.
184 ### Case 1: $/ is undef: slurp all...
186 *$self->{Pos} = length $$sr;
187 return substr($$sr, $i);
190 ### Case 2: $/ is "\n": zoom zoom zoom...
191 elsif ($/ eq "\012") {
193 ### Seek ahead for "\n"... yes, this really is faster than regexps.
194 my $len = length($$sr);
195 for (; $i < $len; ++$i) {
196 last if ord (substr ($$sr, $i, 1)) == 10;
199 ### Extract the line:
201 if ($i < $len) { ### We found a "\n":
202 $line = substr ($$sr, *$self->{Pos}, $i - *$self->{Pos} + 1);
203 *$self->{Pos} = $i+1; ### Remember where we finished up.
205 else { ### No "\n"; slurp the remainder:
206 $line = substr ($$sr, *$self->{Pos}, $i - *$self->{Pos});
207 *$self->{Pos} = $len;
212 ### Case 3: $/ is ref to int. Do fixed-size records.
213 ### (Thanks to Dominique Quatravaux.)
215 my $len = length($$sr);
217 my $line = substr ($$sr, *$self->{Pos}, $i);
219 *$self->{Pos} = $len if (*$self->{Pos} > $len);
223 ### Case 4: $/ is either "" (paragraphs) or something weird...
224 ### This is Graham's general-purpose stuff, which might be
225 ### a tad slower than Case 2 for typical data, because
230 ### If in paragraph mode, skip leading lines (and update i!):
232 (($$sr =~ m/\G\n*/g) and ($i = pos($$sr)));
234 ### If we see the separator in the buffer ahead...
236 ? $$sr =~ m,\Q$/\E,g ### (ordinary sep) TBD: precomp!
237 : $$sr =~ m,\n\n,g ### (a paragraph)
239 *$self->{Pos} = pos $$sr;
240 return substr($$sr, $i, *$self->{Pos}-$i);
242 ### Else if no separator remains, just slurp the rest:
244 *$self->{Pos} = length $$sr;
245 return substr($$sr, $i);
250 #------------------------------
255 Get all remaining lines.
256 It will croak() if accidentally called in a scalar context.
262 wantarray or croak("can't call getlines in scalar context!");
264 push @lines, $line while (defined($line = $self->getline));
268 #------------------------------
273 Print ARGS to the underlying scalar.
275 B<Warning:> this continues to always cause a seek to the end
276 of the string, but if you perform seek()s and tell()s, it is
277 still safer to explicitly seek-to-end before subsequent print()s.
283 *$self->{Pos} = length(${*$self->{SR}} .= join('', @_) . (defined($\) ? $\ : ""));
288 my $append = join('', @_) . $\;
289 ${*$self->{SR}} .= $append;
290 *$self->{Pos} += length($append);
295 ${*$self->{SR}} .= join('', @_) . $\;
296 *$self->{Pos} = length(${*$self->{SR}});
301 #------------------------------
303 =item read BUF, NBYTES, [OFFSET]
306 Read some bytes from the scalar.
307 Returns the number of bytes actually read, 0 on end-of-file, undef on error.
314 my $off = $_[3] || 0;
316 my $read = substr(${*$self->{SR}}, *$self->{Pos}, $n);
319 ($off ? substr($_[1], $off) : $_[1]) = $read;
323 #------------------------------
325 =item write BUF, NBYTES, [OFFSET]
328 Write some bytes to the scalar.
335 my $off = $_[3] || 0;
337 my $data = substr($_[1], $off, $n);
343 #------------------------------
345 =item sysread BUF, LEN, [OFFSET]
348 Read some bytes from the scalar.
349 Returns the number of bytes actually read, 0 on end-of-file, undef on error.
358 #------------------------------
360 =item syswrite BUF, NBYTES, [OFFSET]
363 Write some bytes to the scalar.
377 #==============================
379 =head2 Seeking/telling and other attributes
386 #------------------------------
391 No-op, provided for OO compatibility.
397 #------------------------------
402 No-op, provided for OO compatibility.
408 #------------------------------
412 I<Instance method.> Clear the error and EOF flags. A no-op.
418 #------------------------------
422 I<Instance method.> Are we at end of file?
428 (*$self->{Pos} >= length(${*$self->{SR}}));
431 #------------------------------
433 =item seek OFFSET, WHENCE
435 I<Instance method.> Seek to a given position in the stream.
440 my ($self, $pos, $whence) = @_;
441 my $eofpos = length(${*$self->{SR}});
444 if ($whence == 0) { *$self->{Pos} = $pos } ### SEEK_SET
445 elsif ($whence == 1) { *$self->{Pos} += $pos } ### SEEK_CUR
446 elsif ($whence == 2) { *$self->{Pos} = $eofpos + $pos} ### SEEK_END
447 else { croak "bad seek whence ($whence)" }
450 if (*$self->{Pos} < 0) { *$self->{Pos} = 0 }
451 if (*$self->{Pos} > $eofpos) { *$self->{Pos} = $eofpos }
455 #------------------------------
457 =item sysseek OFFSET, WHENCE
459 I<Instance method.> Identical to C<seek OFFSET, WHENCE>, I<q.v.>
468 #------------------------------
473 Return the current position in the stream, as a numeric offset.
477 sub tell { *{shift()}->{Pos} }
479 #------------------------------
484 B<Deprecated and ignored.>
485 Obey the curent setting of $/, like IO::Handle does?
486 Default is false in 1.x, but cold-welded true in 2.x and later.
491 my ($self, $yesno) = @_;
492 carp "use_RS is deprecated and ignored; \$/ is always consulted\n";
495 #------------------------------
500 Set the current position, using the opaque value returned by C<getpos()>.
504 sub setpos { shift->seek($_[0],0) }
506 #------------------------------
511 Return the current position in the string, as an opaque object.
518 #------------------------------
523 Return a reference to the underlying scalar.
527 sub sref { *{shift()}->{SR} }
530 #------------------------------
531 # Tied handle methods...
532 #------------------------------
534 # Conventional tiehandle interface:
536 ((defined($_[1]) && UNIVERSAL::isa($_[1], __PACKAGE__))
540 sub GETC { shift->getc(@_) }
541 sub PRINT { shift->print(@_) }
542 sub PRINTF { shift->print(sprintf(shift, @_)) }
543 sub READ { shift->read(@_) }
544 sub READLINE { wantarray ? shift->getlines(@_) : shift->getline(@_) }
545 sub WRITE { shift->write(@_); }
546 sub CLOSE { shift->close(@_); }
547 sub SEEK { shift->seek(@_); }
548 sub TELL { shift->tell(@_); }
549 sub EOF { shift->eof(@_); }
551 #------------------------------------------------------------
566 Perl's TIEHANDLE spec was incomplete prior to 5.005_57;
567 it was missing support for C<seek()>, C<tell()>, and C<eof()>.
568 Attempting to use these functions with an IO::Scalar will not work
569 prior to 5.005_57. IO::Scalar will not have the relevant methods
570 invoked; and even worse, this kind of bug can lie dormant for a while.
571 If you turn warnings on (via C<$^W> or C<perl -w>),
572 and you see something like this...
574 attempt to seek on unopened filehandle
576 ...then you are probably trying to use one of these functions
577 on an IO::Scalar with an old Perl. The remedy is to simply
578 use the OO version; e.g.:
580 $SH->seek(0,0); ### GOOD: will work on any 5.005
581 seek($SH,0,0); ### WARNING: will only work on 5.005_57 and beyond
586 $Id: Scalar.pm,v 1.6 2005/02/10 21:21:53 dfs Exp $
591 =head2 Primary Maintainer
593 David F. Skoll (F<dfs@roaringpenguin.com>).
595 =head2 Principal author
597 Eryq (F<eryq@zeegee.com>).
598 President, ZeeGee Software Inc (F<http://www.zeegee.com>).
601 =head2 Other contributors
603 The full set of contributors always includes the folks mentioned
604 in L<IO::Stringy/"CHANGE LOG">. But just the same, special
605 thanks to the following individuals for their invaluable contributions
606 (if I've forgotten or misspelled your name, please email me!):
609 for contributing C<getc()>.
612 for suggesting C<opened()>.
615 for finding and fixing the bug in C<PRINTF()>.
618 for his offset-using read() and write() implementations.
621 for his patches to massively improve the performance of C<getline()>
622 and add C<sysread> and C<syswrite>.
624 I<B. K. Oxley (binkley),>
625 for stringification and inheritance improvements,
626 and sundry good ideas.
629 for the IO::Handle inheritance and automatic tie-ing.
634 L<IO::String>, which is quite similar but which was designed
635 more-recently and with an IO::Handle-like interface in mind,
636 so you could mix OO- and native-filehandle usage without using tied().
638 I<Note:> as of version 2.x, these classes all work like
639 their IO::Handle counterparts, so we have comparable
640 functionality to IO::String.