File Coverage

lib/IO/Scalar.pm
Criterion Covered Total %
statement 105 156 67.3
branch 35 46 76.0
condition 6 13 46.1
subroutine 24 46 52.1
pod 23 24 95.8
total 193 285 67.7


line stmt bran cond sub pod time code
1             package IO::Scalar;
2              
3 4     4   12293 use strict;
  4         28  
  4         97  
4              
5 4     4   16 use Carp;
  4         6  
  4         494  
6 4     4   1454 use IO::Handle;
  4         17620  
  4         281  
7              
8             ### Stringification, courtesy of B. K. Oxley (binkley): :-)
9 4     4   4590 use overload '""' => sub { ${*{$_[0]}->{SR}} };
  4     3   3770  
  4         31  
  3         43  
  3         3  
  3         25  
10 4     4   262 use overload 'bool' => sub { 1 }; ### have to do this, so object is true!
  4     1   8  
  4         19  
  1         14  
11              
12             ### The package version, both in 1.23 style *and* usable by MakeMaker:
13             our $VERSION = "2.112";
14              
15             ### Inheritance:
16             our @ISA = qw(IO::Handle);
17              
18             ### This stuff should be got rid of ASAP.
19             require IO::WrapTie and push @ISA, 'IO::WrapTie::Slave' if ($] >= 5.004);
20              
21             #==============================
22              
23              
24              
25             =head1 NAME
26              
27             IO::Scalar - IO:: interface for reading/writing a scalar
28              
29              
30             =head1 SYNOPSIS
31              
32             Perform I/O on strings, using the basic OO interface...
33              
34             use 5.005;
35             use IO::Scalar;
36             $data = "My message:\n";
37              
38             ### Open a handle on a string, and append to it:
39             $SH = new IO::Scalar \$data;
40             $SH->print("Hello");
41             $SH->print(", world!\nBye now!\n");
42             print "The string is now: ", $data, "\n";
43              
44             ### Open a handle on a string, read it line-by-line, then close it:
45             $SH = new IO::Scalar \$data;
46             while (defined($_ = $SH->getline)) {
47             print "Got line: $_";
48             }
49             $SH->close;
50              
51             ### Open a handle on a string, and slurp in all the lines:
52             $SH = new IO::Scalar \$data;
53             print "All lines:\n", $SH->getlines;
54              
55             ### Get the current position (either of two ways):
56             $pos = $SH->getpos;
57             $offset = $SH->tell;
58              
59             ### Set the current position (either of two ways):
60             $SH->setpos($pos);
61             $SH->seek($offset, 0);
62              
63             ### Open an anonymous temporary scalar:
64             $SH = new IO::Scalar;
65             $SH->print("Hi there!");
66             print "I printed: ", ${$SH->sref}, "\n"; ### get at value
67              
68              
69             Don't like OO for your I/O? No problem.
70             Thanks to the magic of an invisible tie(), the following now
71             works out of the box, just as it does with IO::Handle:
72              
73             use 5.005;
74             use IO::Scalar;
75             $data = "My message:\n";
76              
77             ### Open a handle on a string, and append to it:
78             $SH = new IO::Scalar \$data;
79             print $SH "Hello";
80             print $SH ", world!\nBye now!\n";
81             print "The string is now: ", $data, "\n";
82              
83             ### Open a handle on a string, read it line-by-line, then close it:
84             $SH = new IO::Scalar \$data;
85             while (<$SH>) {
86             print "Got line: $_";
87             }
88             close $SH;
89              
90             ### Open a handle on a string, and slurp in all the lines:
91             $SH = new IO::Scalar \$data;
92             print "All lines:\n", <$SH>;
93              
94             ### Get the current position (WARNING: requires 5.6):
95             $offset = tell $SH;
96              
97             ### Set the current position (WARNING: requires 5.6):
98             seek $SH, $offset, 0;
99              
100             ### Open an anonymous temporary scalar:
101             $SH = new IO::Scalar;
102             print $SH "Hi there!";
103             print "I printed: ", ${$SH->sref}, "\n"; ### get at value
104              
105              
106             And for you folks with 1.x code out there: the old tie() style still works,
107             though this is I:
108              
109             use IO::Scalar;
110              
111             ### Writing to a scalar...
112             my $s;
113             tie *OUT, 'IO::Scalar', \$s;
114             print OUT "line 1\nline 2\n", "line 3\n";
115             print "String is now: $s\n"
116              
117             ### Reading and writing an anonymous scalar...
118             tie *OUT, 'IO::Scalar';
119             print OUT "line 1\nline 2\n", "line 3\n";
120             tied(OUT)->seek(0,0);
121             while () {
122             print "Got line: ", $_;
123             }
124              
125              
126             Stringification works, too!
127              
128             my $SH = new IO::Scalar \$data;
129             print $SH "Hello, ";
130             print $SH "world!";
131             print "I printed: $SH\n";
132              
133              
134              
135             =head1 DESCRIPTION
136              
137             This class is part of the IO::Stringy distribution;
138             see L for change log and general information.
139              
140             The IO::Scalar class implements objects which behave just like
141             IO::Handle (or FileHandle) objects, except that you may use them
142             to write to (or read from) scalars. These handles are
143             automatically tiehandle'd (though please see L<"WARNINGS">
144             for information relevant to your Perl version).
145              
146              
147             Basically, this:
148              
149             my $s;
150             $SH = new IO::Scalar \$s;
151             $SH->print("Hel", "lo, "); ### OO style
152             $SH->print("world!\n"); ### ditto
153              
154             Or this:
155              
156             my $s;
157             $SH = tie *OUT, 'IO::Scalar', \$s;
158             print OUT "Hel", "lo, "; ### non-OO style
159             print OUT "world!\n"; ### ditto
160              
161             Causes $s to be set to:
162              
163             "Hello, world!\n"
164              
165              
166             =head1 PUBLIC INTERFACE
167              
168             =head2 Construction
169              
170             =over 4
171              
172             =cut
173              
174             #------------------------------
175              
176             =item new [ARGS...]
177              
178             I
179             Return a new, unattached scalar handle.
180             If any arguments are given, they're sent to open().
181              
182             =cut
183              
184             sub new {
185 12     12 1 2002 my $proto = shift;
186 12   33     44 my $class = ref($proto) || $proto;
187 12         15 my $self = bless \do { local *FH }, $class;
  12         44  
188 12         269 tie *$self, $class, $self;
189 12         36 $self->open(@_); ### open on anonymous by default
190 12         25 $self;
191             }
192             sub DESTROY {
193 11     11   290 shift->close;
194             }
195              
196             #------------------------------
197              
198             =item open [SCALARREF]
199              
200             I
201             Open the scalar handle on a new scalar, pointed to by SCALARREF.
202             If no SCALARREF is given, a "private" scalar is created to hold
203             the file data.
204              
205             Returns the self object on success, undefined on error.
206              
207             =cut
208              
209             sub open {
210 12     12 1 18 my ($self, $sref) = @_;
211              
212             ### Sanity:
213 12 100       26 defined($sref) or do {my $s = ''; $sref = \$s};
  2         5  
  2         3  
214 12 50       31 (ref($sref) eq "SCALAR") or croak "open() needs a ref to a scalar";
215              
216             ### Setup:
217 12         27 *$self->{Pos} = 0; ### seek position
218 12         27 *$self->{SR} = $sref; ### scalar reference
219 12         16 $self;
220             }
221              
222             #------------------------------
223              
224             =item opened
225              
226             I
227             Is the scalar handle opened on something?
228              
229             =cut
230              
231             sub opened {
232 0     0 1 0 *{shift()}->{SR};
  0         0  
233             }
234              
235             #------------------------------
236              
237             =item close
238              
239             I
240             Disassociate the scalar handle from its underlying scalar.
241             Done automatically on destroy.
242              
243             =cut
244              
245             sub close {
246 11     11 1 11 my $self = shift;
247 11         12 %{*$self} = ();
  11         23  
248 11         25 1;
249             }
250              
251             =back
252              
253             =cut
254              
255              
256              
257             #==============================
258              
259             =head2 Input and output
260              
261             =over 4
262              
263             =cut
264              
265              
266             #------------------------------
267              
268             =item flush
269              
270             I
271             No-op, provided for OO compatibility.
272              
273             =cut
274              
275 0     0 1 0 sub flush { "0 but true" }
276              
277             #------------------------------
278              
279             =item fileno
280              
281             I
282             No-op, returns undef
283              
284             =cut
285              
286       1 1   sub fileno { }
287              
288             #------------------------------
289              
290             =item getc
291              
292             I
293             Return the next character, or undef if none remain.
294              
295             =cut
296              
297             sub getc {
298 3     3 1 12 my $self = shift;
299              
300             ### Return undef right away if at EOF; else, move pos forward:
301 3 50       7 return undef if $self->eof;
302 3         4 substr(${*$self->{SR}}, *$self->{Pos}++, 1);
  3         12  
303             }
304              
305             #------------------------------
306              
307             =item getline
308              
309             I
310             Return the next line, or undef on end of string.
311             Can safely be called in an array context.
312             Currently, lines are delimited by "\n".
313              
314             =cut
315              
316             sub getline {
317 49     49 1 1124 my $self = shift;
318              
319             ### Return undef right away if at EOF:
320 49 100       61 return undef if $self->eof;
321              
322             ### Get next line:
323 42         219 my $sr = *$self->{SR};
324 42         56 my $i = *$self->{Pos}; ### Start matching at this point.
325              
326             ### Minimal impact implementation!
327             ### We do the fast thing (no regexps) if using the
328             ### classic input record separator.
329              
330             ### Case 1: $/ is undef: slurp all...
331 42 100       99 if (!defined($/)) {
    100          
    50          
332 2         4 *$self->{Pos} = length $$sr;
333 2         12 return substr($$sr, $i);
334             }
335              
336             ### Case 2: $/ is "\n": zoom zoom zoom...
337             elsif ($/ eq "\012") {
338              
339             ### Seek ahead for "\n"... yes, this really is faster than regexps.
340 35         36 my $len = length($$sr);
341 35         49 for (; $i < $len; ++$i) {
342 797 100       1674 last if ord (substr ($$sr, $i, 1)) == 10;
343             }
344              
345             ### Extract the line:
346 35         28 my $line;
347 35 100       92 if ($i < $len) { ### We found a "\n":
348 34         142 $line = substr ($$sr, *$self->{Pos}, $i - *$self->{Pos} + 1);
349 34         64 *$self->{Pos} = $i+1; ### Remember where we finished up.
350             }
351             else { ### No "\n"; slurp the remainder:
352 1         4 $line = substr ($$sr, *$self->{Pos}, $i - *$self->{Pos});
353 1         2 *$self->{Pos} = $len;
354             }
355 35         155 return $line;
356             }
357              
358             ### Case 3: $/ is ref to int. Do fixed-size records.
359             ### (Thanks to Dominique Quatravaux.)
360             elsif (ref($/)) {
361 0         0 my $len = length($$sr);
362 0         0 my $i = ${$/} + 0;
  0         0  
363 0         0 my $line = substr ($$sr, *$self->{Pos}, $i);
364 0         0 *$self->{Pos} += $i;
365 0 0       0 *$self->{Pos} = $len if (*$self->{Pos} > $len);
366 0         0 return $line;
367             }
368              
369             ### Case 4: $/ is either "" (paragraphs) or something weird...
370             ### This is Graham's general-purpose stuff, which might be
371             ### a tad slower than Case 2 for typical data, because
372             ### of the regexps.
373             else {
374 5         11 pos($$sr) = $i;
375              
376             ### If in paragraph mode, skip leading lines (and update i!):
377 5 100 33     20 length($/) or
378             (($$sr =~ m/\G\n*/g) and ($i = pos($$sr)));
379              
380             ### If we see the separator in the buffer ahead...
381 5 100       35 if (length($/)
    100          
382             ? $$sr =~ m,\Q$/\E,g ### (ordinary sep) TBD: precomp!
383             : $$sr =~ m,\n\n,g ### (a paragraph)
384             ) {
385 4         8 *$self->{Pos} = pos $$sr;
386 4         38 return substr($$sr, $i, *$self->{Pos}-$i);
387             }
388             ### Else if no separator remains, just slurp the rest:
389             else {
390 1         2 *$self->{Pos} = length $$sr;
391 1         8 return substr($$sr, $i);
392             }
393             }
394             }
395              
396             #------------------------------
397              
398             =item getlines
399              
400             I
401             Get all remaining lines.
402             It will croak() if accidentally called in a scalar context.
403              
404             =cut
405              
406             sub getlines {
407 3     3 1 7 my $self = shift;
408 3 50       9 wantarray or croak("can't call getlines in scalar context!");
409 3         4 my ($line, @lines);
410 3         8 push @lines, $line while (defined($line = $self->getline));
411 3         13 @lines;
412             }
413              
414             #------------------------------
415              
416             =item print ARGS...
417              
418             I
419             Print ARGS to the underlying scalar.
420              
421             B this continues to always cause a seek to the end
422             of the string, but if you perform seek()s and tell()s, it is
423             still safer to explicitly seek-to-end before subsequent print()s.
424              
425             =cut
426              
427             sub print {
428 14     14 1 26 my $self = shift;
429 14 50       13 *$self->{Pos} = length(${*$self->{SR}} .= join('', @_) . (defined($\) ? $\ : ""));
  14         72  
430 14         30 1;
431             }
432             sub _unsafe_print {
433 0     0   0 my $self = shift;
434 0         0 my $append = join('', @_) . $\;
435 0         0 ${*$self->{SR}} .= $append;
  0         0  
436 0         0 *$self->{Pos} += length($append);
437 0         0 1;
438             }
439             sub _old_print {
440 0     0   0 my $self = shift;
441 0         0 ${*$self->{SR}} .= join('', @_) . $\;
  0         0  
442 0         0 *$self->{Pos} = length(${*$self->{SR}});
  0         0  
443 0         0 1;
444             }
445              
446              
447             #------------------------------
448              
449             =item read BUF, NBYTES, [OFFSET]
450              
451             I
452             Read some bytes from the scalar.
453             Returns the number of bytes actually read, 0 on end-of-file, undef on error.
454              
455             =cut
456              
457             sub read {
458 6     6 1 48 my $self = $_[0];
459 6         7 my $n = $_[2];
460 6   50     13 my $off = $_[3] || 0;
461              
462 6         7 my $read = substr(${*$self->{SR}}, *$self->{Pos}, $n);
  6         14  
463 6         7 $n = length($read);
464 6         39 *$self->{Pos} += $n;
465 6 50       13 ($off ? substr($_[1], $off) : $_[1]) = $read;
466 6         8 return $n;
467             }
468              
469             #------------------------------
470              
471             =item write BUF, NBYTES, [OFFSET]
472              
473             I
474             Write some bytes to the scalar.
475              
476             =cut
477              
478             sub write {
479 0     0 1 0 my $self = $_[0];
480 0         0 my $n = $_[2];
481 0   0     0 my $off = $_[3] || 0;
482              
483 0         0 my $data = substr($_[1], $off, $n);
484 0         0 $n = length($data);
485 0         0 $self->print($data);
486 0         0 return $n;
487             }
488              
489             #------------------------------
490              
491             =item sysread BUF, LEN, [OFFSET]
492              
493             I
494             Read some bytes from the scalar.
495             Returns the number of bytes actually read, 0 on end-of-file, undef on error.
496              
497             =cut
498              
499             sub sysread {
500 0     0 1 0 my $self = shift;
501 0         0 $self->read(@_);
502             }
503              
504             #------------------------------
505              
506             =item syswrite BUF, NBYTES, [OFFSET]
507              
508             I
509             Write some bytes to the scalar.
510              
511             =cut
512              
513             sub syswrite {
514 0     0 1 0 my $self = shift;
515 0         0 $self->write(@_);
516             }
517              
518             =back
519              
520             =cut
521              
522              
523             #==============================
524              
525             =head2 Seeking/telling and other attributes
526              
527             =over 4
528              
529             =cut
530              
531              
532             #------------------------------
533              
534             =item autoflush
535              
536             I
537             No-op, provided for OO compatibility.
538              
539             =cut
540              
541       0 1   sub autoflush {}
542              
543             #------------------------------
544              
545             =item binmode
546              
547             I
548             No-op, provided for OO compatibility.
549              
550             =cut
551              
552       0 1   sub binmode {}
553              
554             #------------------------------
555              
556             =item clearerr
557              
558             I Clear the error and EOF flags. A no-op.
559              
560             =cut
561              
562 0     0 1 0 sub clearerr { 1 }
563              
564             #------------------------------
565              
566             =item eof
567              
568             I Are we at end of file?
569              
570             =cut
571              
572             sub eof {
573 52     52 1 42 my $self = shift;
574 52         94 (*$self->{Pos} >= length(${*$self->{SR}}));
  52         211  
575             }
576              
577             #------------------------------
578              
579             =item seek OFFSET, WHENCE
580              
581             I Seek to a given position in the stream.
582              
583             =cut
584              
585             sub seek {
586 12     12 1 973 my ($self, $pos, $whence) = @_;
587 12         21 my $eofpos = length(${*$self->{SR}});
  12         33  
588              
589             ### Seek:
590 12 100       30 if ($whence == 0) { *$self->{Pos} = $pos } ### SEEK_SET
  10 100       17  
    50          
591 1         2 elsif ($whence == 1) { *$self->{Pos} += $pos } ### SEEK_CUR
592 1         3 elsif ($whence == 2) { *$self->{Pos} = $eofpos + $pos} ### SEEK_END
593 0         0 else { croak "bad seek whence ($whence)" }
594              
595             ### Fixup:
596 12 50       44 if (*$self->{Pos} < 0) { *$self->{Pos} = 0 }
  0         0  
597 12 50       35 if (*$self->{Pos} > $eofpos) { *$self->{Pos} = $eofpos }
  0         0  
598 12         24 return 1;
599             }
600              
601             #------------------------------
602              
603             =item sysseek OFFSET, WHENCE
604              
605             I Identical to C, I
606              
607             =cut
608              
609             sub sysseek {
610 0     0 1 0 my $self = shift;
611 0         0 $self->seek (@_);
612             }
613              
614             #------------------------------
615              
616             =item tell
617              
618             I
619             Return the current position in the stream, as a numeric offset.
620              
621             =cut
622              
623 1     1 1 31 sub tell { *{shift()}->{Pos} }
  1         4  
624              
625             #------------------------------
626             #
627             # use_RS [YESNO]
628             #
629             # I
630             # Obey the current setting of $/, like IO::Handle does?
631             # Default is false in 1.x, but cold-welded true in 2.x and later.
632             #
633             sub use_RS {
634 0     0 0 0 my ($self, $yesno) = @_;
635 0         0 carp "use_RS is deprecated and ignored; \$/ is always consulted\n";
636             }
637              
638             #------------------------------
639              
640             =item setpos POS
641              
642             I
643             Set the current position, using the opaque value returned by C.
644              
645             =cut
646              
647 0     0 1 0 sub setpos { shift->seek($_[0],0) }
648              
649             #------------------------------
650              
651             =item getpos
652              
653             I
654             Return the current position in the string, as an opaque object.
655              
656             =cut
657              
658             *getpos = \&tell;
659              
660              
661             #------------------------------
662              
663             =item sref
664              
665             I
666             Return a reference to the underlying scalar.
667              
668             =cut
669              
670 2     2 1 7 sub sref { *{shift()}->{SR} }
  2         9  
671              
672              
673             #------------------------------
674             # Tied handle methods...
675             #------------------------------
676              
677             # Conventional tiehandle interface:
678             sub TIEHANDLE {
679 14 100 100 14   102 ((defined($_[1]) && UNIVERSAL::isa($_[1], "IO::Scalar"))
680             ? $_[1]
681             : shift->new(@_));
682             }
683 0     0   0 sub GETC { shift->getc(@_) }
684 11     11   221 sub PRINT { shift->print(@_) }
685 0     0   0 sub PRINTF { shift->print(sprintf(shift, @_)) }
686 0     0   0 sub READ { shift->read(@_) }
687 9 100   9   70 sub READLINE { wantarray ? shift->getlines(@_) : shift->getline(@_) }
688 0     0     sub WRITE { shift->write(@_); }
689 0     0     sub CLOSE { shift->close(@_); }
690 0     0     sub SEEK { shift->seek(@_); }
691 0     0     sub TELL { shift->tell(@_); }
692 0     0     sub EOF { shift->eof(@_); }
693 0     0     sub BINMODE { 1; }
694              
695             #------------------------------------------------------------
696              
697             1;
698              
699             __END__