File Coverage

blib/lib/IO/Handle/Iterator.pm
Criterion Covered Total %
statement 62 94 65.9
branch 13 20 65.0
condition 2 3 66.6
subroutine 18 41 43.9
pod 0 27 0.0
total 95 185 51.3


line stmt bran cond sub pod time code
1             package IO::Handle::Iterator;
2              
3 1     1   13789 use strict;
  1         1  
  1         21  
4 1     1   3 use warnings;
  1         2  
  1         25  
5              
6 1     1   3 use Carp ();
  1         1  
  1         12  
7              
8 1     1   359 use parent qw(IO::Handle::Prototype);
  1         211  
  1         5  
9              
10             # error, clearerr, new_from_fd, fdopen
11              
12             sub new {
13 1     1 0 2 my ( $class, $cb ) = @_;
14              
15 1         4 bless {
16             cb => $cb,
17             }, $class;
18             }
19              
20 2     2 0 5 sub getline { shift->_cb }
21              
22             sub _cb {
23 9     9   8 my $self = shift;
24              
25 9 50       16 if ( my $cb = $self->{cb} ) {
26 9 100       18 if ( defined(my $next = $cb->()) ) {
27 8         24 return $next;
28             } else {
29 1         8 $self->close;
30             }
31             }
32              
33 1         4 return;
34             }
35              
36             sub _rebless_and {
37 2     2   2 my $self = shift;
38 2         3 my $method = shift;
39              
40 2         6 bless $self, "IO::Handle::Iterator::Buffered";
41              
42 2         6 $self->$method(@_);
43             }
44              
45 2     2 0 7 sub read { shift->_rebless_and( read => @_ ) }
46 0     0 0 0 sub sysread { shift->_rebless_and( sysread => @_ ) }
47 0     0 0 0 sub getc { shift->_rebless_and( getc => @_ ) }
48 0     0 0 0 sub ungetc { shift->_rebless_and( ungetc => @_ ) }
49              
50 0     0 0 0 sub open { Carp::croak("Can't open an iterator") }
51 0     0 0 0 sub print { Carp::croak("Can't print to iterator") }
52 0     0 0 0 sub printflush { Carp::croak("Can't print to iterator") }
53 0     0 0 0 sub printf { Carp::croak("Can't print to iterator") }
54 0     0 0 0 sub say { Carp::croak("Can't print to iterator") }
55 0     0 0 0 sub write { Carp::croak("Can't write to iterator") }
56 0     0 0 0 sub syswrite { Carp::croak("Can't write to iterator") }
57 0     0 0 0 sub format_write { Carp::croak("Can't write to iterator") }
58 0     0 0 0 sub ioctl { Carp::croak("Can't ioctl on iterator") }
59 0     0 0 0 sub fcntl { Carp::croak("Can't fcntl on iterator") }
60 0     0 0 0 sub truncate { Carp::croak("Can't truncate iterator") }
61 0     0 0 0 sub sync { Carp::croak("Can't sync an iterator") }
62 0     0 0 0 sub flush { Carp::croak("Can't flush an iterator") }
63              
64 0     0 0 0 sub autoflush { 1 }
65              
66 0     0 0 0 sub opened { 1 }
67              
68             sub blocking {
69 0     0 0 0 my ( $self, @args ) = @_;
70              
71 0 0       0 Carp::croak("Can't set blocking mode on iterator") if @args;
72              
73 0         0 return 1;
74             }
75              
76 0     0 0 0 sub stat { return undef }
77 0     0 0 0 sub fileno { return undef }
78              
79 1     1 0 3 sub close { delete $_[0]{cb} }
80 9     9 0 1034 sub eof { not exists $_[0]{cb} }
81              
82             sub getlines {
83 0     0 0 0 my $self = shift;
84              
85 0         0 my @accum;
86            
87 0         0 while ( defined(my $next = $self->getline) ) {
88 0         0 push @accum, $next;
89             }
90              
91 0         0 return @accum;
92             }
93              
94             package IO::Handle::Iterator::Buffered; # FIXME IO::Handle::BufferMixin?
95 1     1   458 use parent qw(IO::Handle::Iterator);
  1         1  
  1         4  
96              
97 1     1   54 no warnings 'uninitialized';
  1         1  
  1         322  
98              
99             sub eof {
100 13     13   13 my $self = shift;
101              
102 13 100       92 length($self->{buf}) == 0
103             and
104             $self->SUPER::eof;
105             }
106              
107             sub getc {
108 2     2   5 shift->read(my $c, 1);
109 2         6 return $c;
110             }
111              
112             sub ungetc {
113 1     1   1 my ( $self, $ord ) = @_;
114 1         6 substr($self->{buf}, 0, 0, chr($ord)); # yuck
115 1         2 return;
116             }
117              
118 0     0   0 sub sysread { shift->read(@_) }
119              
120             sub read {
121 6     6   12 my ( $self, undef, $length, $offset ) = @_;
122              
123 6 50       8 return 0 if $self->eof;
124              
125 6 100 66     17 if ( $offset and length($_[1]) < $offset ) {
126 1         3 $_[1] .= "\0" x ( $offset - length($_[1]) );
127             }
128              
129 6         11 while (length($self->{buf}) < $length) {
130 7 100       13 if ( defined(my $next = $self->_cb) ) {
131 6         15 $self->{buf} .= $next;
132             } else {
133             # data ended but still under $length, return all that remains and
134             # empty the buffer
135 1         3 my $ret = length($self->{buf});
136              
137 1 50       3 if ( $offset ) {
138 1         2 substr($_[1], $offset) = delete $self->{buf};
139             } else {
140 0         0 $_[1] = delete $self->{buf};
141             }
142              
143 1         4 return $ret;
144             }
145             }
146              
147 5         4 my $read;
148 5 50       8 if ( $length > length($self->{buf}) ) {
149 0         0 $read = delete $self->{buf};
150             } else {
151 5         10 $read = substr($self->{buf}, 0, $length, '');
152             }
153              
154 5 50       7 if ( $offset ) {
155 0         0 substr($_[1], $offset) = $read;
156             } else {
157 5         5 $_[1] = $read;
158             }
159              
160 5         11 return length($read);
161             }
162              
163             sub getline {
164 1     1   3 my $self = shift;
165              
166 1         2 my $line = delete $self->{buf};
167              
168 1         2 bless $self, 'IO::Handle::Iterator';
169              
170 1         4 return $line;
171             }
172              
173             __PACKAGE__
174              
175             # ex: set sw=4 et:
176              
177             __END__