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   80886 use strict;
  4         17  
  4         115  
4 4     4   19 use warnings;
  4         7  
  4         91  
5              
6 4     4   1742 use IO::Framed::X ();
  4         14  
  4         1284  
7              
8             sub new {
9 5     5 0 1495 my ( $class, $in_fh, $initial_buffer ) = @_;
10              
11 5 50       20 if ( !defined $initial_buffer ) {
12 5         12 $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         26 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 554 my ($self) = @_;
31 1         3 $self->{'_ALLOW_EMPTY_READ'} = 1;
32 1         6 return $self;
33             }
34              
35             my $buf_len;
36              
37             sub READ {
38 2     2   467 require IO::SigGuard;
39 2         642 *READ = *IO::SigGuard::sysread;
40 2         11 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 1215 my ( $self, $bytes ) = @_;
53              
54 10 50       29 die "I refuse to read zero!" if !$bytes;
55              
56 10 100       38 if ( $buf_len = length $self->{'_read_buffer'} ) {
57 1 50       7 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       28 if ( $bytes > $buf_len ) {
64 10         16 $bytes -= $buf_len;
65              
66 10         35 local $!;
67              
68 10   66     67 $bytes -= $self->can('READ')->( $self->{'_in_fh'}, $self->{'_read_buffer'}, $bytes, $buf_len ) || do {
69             if ($!) {
70 3     3   1483 if ( !$!{'EAGAIN'} && !$!{'EWOULDBLOCK'}) {
  3         4430  
  3         27  
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         149 $self->{'_bytes_to_read'} = $bytes;
84              
85 7 100       20 if ($bytes) {
86 2         11 return undef;
87             }
88              
89 5         35 return substr( $self->{'_read_buffer'}, 0, length($self->{'_read_buffer'}), q<> );
90             }
91              
92             #----------------------------------------------------------------------
93              
94             1;