File Coverage

blib/lib/IO/Unread.pm
Criterion Covered Total %
statement 116 160 72.5
branch 36 64 56.2
condition 2 6 33.3
subroutine 22 27 81.4
pod 0 3 0.0
total 176 260 67.6


line stmt bran cond sub pod time code
1             package IO::Unread;
2              
3 1     1   23132 use 5.008001;
  1         4  
  1         49  
4              
5 1     1   6 use warnings;
  1         2  
  1         31  
6 1     1   5 use strict;
  1         7  
  1         41  
7              
8 1     1   21 use Carp;
  1         2  
  1         114  
9 1     1   5 use XSLoader;
  1         2  
  1         33  
10 1     1   958 use Symbol qw/qualify_to_ref/;
  1         1000  
  1         75  
11 1     1   7 use Scalar::Util qw/openhandle/;
  1         3  
  1         139  
12              
13             BEGIN {
14 1     1   2 our $VERSION = '1.04';
15 1         724 XSLoader::load __PACKAGE__, $VERSION;
16             }
17              
18             my $USE_PERLIO = HAVE_PERLIO_LAYERS;
19             my $Debug;
20              
21             sub debug {
22 145     145 0 835 my $func = (caller 1)[3];
23 145 50       409 $Debug and warn "$func: ", @_;
24             }
25              
26             sub import {
27 1     1   6 no strict 'refs';
  1         2  
  1         398  
28 3     3   1826 my $from = shift;
29 3         5 my $to = caller;
30 3         7 my @carp;
31            
32 3         13 while ($_ = shift) {
33 3 100       10 /^-tie$/ and do {
34 1         2 $USE_PERLIO = 0;
35 1         4 next;
36             };
37              
38 2 50       6 /^-debug$/ and do {
39 0         0 $Debug = 1;
40 0         0 debug "debugging on";
41 0         0 next;
42             };
43            
44 2         3 s/^&//;
45 2         11 !/^_/ and /[^[:upper:]]/ and
46             exists &{"$from\::$_"} and do
47 2 50 33     19 {
      33        
48 2         3 *{"$to\::$_"} = \&{"$from\::$_"};
  2         13  
  2         6  
49 2         7 next;
50             };
51              
52 0         0 push @carp, qq/"$_" is not exported by $from/;
53             }
54            
55 3 50       9 @carp and do {
56 0         0 carp $_ for @carp;
57 0         0 croak "can't continue after import errors";
58             };
59              
60 3         8 debug "import done";
61             }
62              
63             sub _get_fh {
64 38     38   36 my $fh = do {
65 38         103 local $^W = 0;
66 38         114 qualify_to_ref shift, caller 2;
67             };
68 36 100       596 openhandle $fh or return;
69 22         35 debug "fh open";
70 22 50       68 _check_fh $fh or return;
71 22         56 debug "fh mode good";
72 22         61 return $fh;
73             }
74              
75             sub unread (*@) {
76             {
77 1     1 0 6 no warnings 'uninitialized';
  1     34   1  
  1         357  
  34         28800  
78 34         129 debug '[', (join '][', @_), ']';
79             }
80            
81 34 100       76 my $fh = _get_fh shift or return;
82            
83 18 100       63 my $str = @_ ? (join "", reverse @_) : $_;
84 18 100       41 length $str or return "0 but true";
85              
86 16         15 my $rv;
87 16         25 undef $@;
88 16 100       30 if ($USE_PERLIO) {
89 8         15 debug "using PerlIO_unread";
90 8         11 $rv = eval { _PerlIO_unread $fh, $str };
  8         33  
91             }
92             else {
93 8         13 debug "using IO::Unread::Tied";
94 8         44 tie *$fh, 'IO::Unread::Tied' => $fh, $str;
95 8         15 $rv = length $str;
96             }
97              
98 16 50       31 if ($@) {
99 0 0       0 warnings::enabled "io" and carp $@;
100 0         0 return;
101             }
102 16 50       30 defined $rv or return;
103 16 50       29 $rv or return "0 but true";
104 16         43 return $rv;
105             }
106              
107             sub ungetc (*;$) {
108 4 50   4 0 3232 my $fh = _get_fh shift or return;
109            
110 4 100       13 my $str = @_ ? shift : $_;
111 4 100       14 length $str or return '';
112            
113 3         18 my $rv = _PerlIO_ungetc $fh, substr $str, 0, 1;
114 3 50       5769 defined $rv or return;
115 3         11 return $rv;
116             }
117              
118             {{
119              
120             package IO::Unread::Tied;
121              
122 1     1   908 use Tie::Handle 4.0;
  1         2556  
  1         32  
123 1     1   10 use base qw/Tie::Handle/;
  1         2  
  1         135  
124 1     1   6 use Carp;
  1         2  
  1         77  
125 1     1   925 BEGIN { *debug = \&IO::Unread::debug }
126              
127             sub TIEHANDLE {
128 8     8   12 my ($c, $handle, $data) = @_;
129 8         23 debug $data;
130 8 50       21 $handle eq 'RETIE' and (debug "retieing"), return $data;
131 8 50       15 length $data or croak __PACKAGE__."::TIEHANDLE called with null data";
132 8         41 return bless { handle => $handle, data => $data }, $c;
133             }
134              
135             sub WRITE {
136 0     0   0 my ($s, $data, $len, $off) = @_;
137 0         0 debug;
138 0         0 my $h = $s->{handle};
139 0         0 untie *$h;
140 0         0 my $rv = print $h substr $data, 0, $off;
141 0         0 tie *$h, ref $s => RETIE => $s;
142 0         0 return $rv;
143             }
144              
145             sub READ {
146 0     0   0 my ($s, undef, $len, $off) = @_;
147 0         0 my $h = $s->{handle};
148 0         0 my $rv = $len;
149              
150 0         0 debug;
151              
152 0         0 my $read = substr $s->{data}, 0, $len, '';
153 0         0 $len -= length $read;
154 0 0       0 unless (length $s->{data}) {
155 0         0 untie *$h;
156 0         0 $rv = read $h, $read, $len, length $read;
157 0 0       0 defined $rv and $rv += length $read;
158             }
159            
160 0         0 substr($_[1], $off, 0) = $read;
161 0         0 return $rv;
162             }
163              
164             sub READLINE {
165 8     8   4309 my $s = shift;
166 8         35 my $h = $s->{handle};
167 8         9 my $rv;
168              
169 8         14 debug;
170            
171 8 50       20 if (not defined $/) {
172 0         0 untie *$h;
173 0         0 return $s->{data} . <$h>;
174             }
175            
176 8 50       19 if ($/ eq '') {
177 0         0 $rv = $s->{data} =~ s!^ ([^\n]* \n+)!!x;
178 0 0       0 $rv = $rv ? $1 : undef;
179             }
180             else {
181 8         58 $rv = $s->{data} =~ s!^ (.*? \Q$/\E )!!x;
182 8 50       23 $rv = $rv ? $1 : undef;
183             }
184              
185 8 50       21 debug "rv = ", (defined $rv) ? (quotemeta $rv) : "(undef)";
186              
187 8 50       16 unless (defined $rv) {
188 8         13 $rv = $s->{data};
189 8         12 $s->{data} = '';
190             }
191              
192 8 50       19 if ($s->{data} eq '') {
193 8         29 untie *$h;
194            
195 8         73 my $done = $rv =~ m! \Q$/\E $ !x;
196 8 50       23 if ($/ eq '') {
197 0         0 my $chr = getc $h;
198 0         0 IO::Unread::ungetc $h, $chr;
199 0         0 $done = ($chr ne "\n");
200             }
201 8         32 debug "rv = |$rv|, \$/ = |$/|, done = $done";
202 8 50       73 $rv .= <$h> unless $done;
203             }
204 8         19 debug "rv = $rv";
205              
206 8         65 return $rv;
207             }
208              
209             sub CLOSE {
210 0     0   0 untie *{$_[0]{handle}};
  0         0  
211 0         0 close $_[0]{handle};
212             }
213              
214             sub SEEK {
215 0     0   0 my $s = shift;
216 0         0 untie *{$s->{handle}};
  0         0  
217 0         0 seek $s->{handle}, $_[0], $_[1];
218             }
219              
220             sub TELL {
221 0     0   0 untie *{$_[0]{handle}};
  0         0  
222 0         0 tell $_[0]{handle};
223             }
224              
225             sub UNTIE {
226 8     8   15 debug;
227             }
228              
229             }}
230              
231             42;
232              
233             =head1 NAME
234              
235             IO::Unread - push more than one character back onto a filehandle
236              
237             =head1 SYNOPSIS
238              
239             use IO::Unread;
240              
241             unread STDIN, "hello world\n";
242              
243             $_ = "goodbye";
244             unread ARGV;
245              
246             =head1 DESCRIPTION
247              
248             C exports one function, C, which will push data back
249             onto a filehandle. Any amount of data can be pushed: if your perl is
250             built with PerlIO layers, the data is stored in a special C<:pending>
251             layer; if not, the module Cs the filehandle to a class which
252             returns the unread data and unties itself.
253              
254             =head2 unread FILEHANDLE, LIST
255              
256             C unreads LIST onto FILEHANDLE. If LIST is omitted, C<$_> is unread.
257             Returns the number of characters unread on success, C on failure. Warnings
258             are produced under category C.
259              
260             Note that C is equivalent to
261              
262             unread $FH, 'a';
263             unread $FH, 'b';
264              
265             , ie. to C rather than C.
266              
267             =head2 ungetc FILEHANDLE, STRING
268              
269             C pushes the first character of STRING onto FILEHANDLE. Unlike
270             C, it does not use a C implementation if your perl doesn't
271             support PerlIO layers; rather it calls your I. This is only
272             guarenteed to support one character of pushback, and then only if it is
273             the last character that was read from the handle.
274              
275             =head1 EXPORTS
276              
277             None by default; C, C on request.
278              
279             =head1 BUGS
280              
281             C is subject to the whims of your libc if you're not using
282             perlio.
283              
284             =head1 COPYRIGHT
285              
286             Copyright 2003 Ben Morrow
287              
288             This library is free software; you can redistribute it and/or modify
289             it under the same terms as Perl itself.
290              
291             =head1 SEE ALSO
292              
293             L, L, L
294              
295             =cut