File Coverage

blib/lib/IO/Framed/Read.pm
Criterion Covered Total %
statement 35 38 92.1
branch 8 12 66.6
condition 2 3 66.6
subroutine 8 9 88.8
pod 0 4 0.0
total 53 66 80.3


line stmt bran cond sub pod time code
1             package IO::Framed::Read;
2              
3 4     4   68216 use strict;
  4         16  
  4         99  
4 4     4   18 use warnings;
  4         9  
  4         75  
5              
6 4     4   1390 use IO::Framed::X ();
  4         9  
  4         924  
7              
8             sub new {
9 5     5 0 1340 my ( $class, $in_fh, $initial_buffer ) = @_;
10              
11 5 50       22 if ( !defined $initial_buffer ) {
12 5         11 $initial_buffer = q<>;
13             }
14              
15 5         22 my $self = {
16             _in_fh => $in_fh,
17             _read_buffer => $initial_buffer,
18             _bytes_to_read => 0,
19             };
20              
21 5         21 return bless $self, $class;
22             }
23              
24 0     0 0 0 sub get_read_fh { return $_[0]->{'_in_fh'} }
25              
26             #----------------------------------------------------------------------
27             # IO subclass interface
28              
29             sub allow_empty_read {
30 1     1 0 509 my ($self) = @_;
31 1         3 $self->{'_ALLOW_EMPTY_READ'} = 1;
32 1         3 return $self;
33             }
34              
35             my $buf_len;
36              
37             sub READ {
38 2     2   400 require IO::SigGuard;
39 2         508 *READ = *IO::SigGuard::sysread;
40 2         8 goto &READ;
41             }
42              
43             #We assume here that whatever read may be incomplete at first
44             #will eventually be repeated so that we can complete it. e.g.:
45             #
46             # - read 4 bytes, receive 1, cache it - return q<>
47             # - select()
48             # - read 4 bytes again; since we already have 1 byte, only read 3
49             # … and now we get the remaining 3, so return the buffer.
50             #
51             sub read {
52 10     10 0 1057 my ( $self, $bytes ) = @_;
53              
54 10 50       26 die "I refuse to read zero!" if !$bytes;
55              
56 10 100       34 if ( $buf_len = length $self->{'_read_buffer'} ) {
57 1 50       6 if ( $buf_len + $self->{'_bytes_to_read'} != $bytes ) {
58 0         0 my $should_be = $buf_len + $self->{'_bytes_to_read'};
59 0         0 die "Continuation: should want “$should_be” bytes, not $bytes!";
60             }
61             }
62              
63 10 50       23 if ( $bytes > $buf_len ) {
64 10         19 $bytes -= $buf_len;
65              
66 10         32 local $!;
67              
68 10   66     59 $bytes -= $self->can('READ')->( $self->{'_in_fh'}, $self->{'_read_buffer'}, $bytes, $buf_len ) || do {
69             if ($!) {
70 3     3   1210 if ( !$!{'EAGAIN'} && !$!{'EWOULDBLOCK'}) {
  3         3433  
  3         20  
71             die IO::Framed::X->create( 'ReadError', $! );
72             }
73             }
74             elsif ($self->{'_ALLOW_EMPTY_READ'}) {
75             return q<>;
76             }
77             else {
78             die IO::Framed::X->create('EmptyRead');
79             }
80             };
81             }
82              
83 7         139 $self->{'_bytes_to_read'} = $bytes;
84              
85 7 100       18 if ($bytes) {
86 2         13 return undef;
87             }
88              
89 5         32 return substr( $self->{'_read_buffer'}, 0, length($self->{'_read_buffer'}), q<> );
90             }
91              
92             #----------------------------------------------------------------------
93              
94             1;