File Coverage

blib/lib/Proc/Hevy/Reader.pm
Criterion Covered Total %
statement 63 68 92.6
branch 26 36 72.2
condition 3 6 50.0
subroutine 12 12 100.0
pod 4 4 100.0
total 108 126 85.7


line stmt bran cond sub pod time code
1             package Proc::Hevy::Reader;
2              
3 25     25   136 use strict;
  25         49  
  25         881  
4 25     25   135 use warnings;
  25         46  
  25         775  
5              
6 25     25   144 use Carp;
  25         39  
  25         1804  
7 25     25   134 use Errno qw( EWOULDBLOCK );
  25         49  
  25         946  
8 25     25   125 use IO::Pipe;
  25         42  
  25         576  
9 25     25   23711 use POSIX ();
  25         206338  
  25         19565  
10              
11              
12             sub new {
13 134     134 1 304 my ( $class, $name, $buffer ) = @_;
14              
15 134         330 my $pipe;
16 134 100 66     1949 $pipe = IO::Pipe->new
17             if defined $buffer and ref $buffer ne 'GLOB';
18              
19 134         13396 bless { name => $name, buffer => $buffer, pipe => $pipe }, $class;
20             }
21              
22             sub child {
23 40     40 1 221 my ( $self, $std_h, $fileno ) = @_;
24              
25 40         106 my $handle;
26              
27 40 100       575 if( defined $self->{pipe} ) {
    50          
28 32         528 $handle = $self->{pipe}->writer;
29             }
30             elsif( ref $self->{buffer} eq 'GLOB' ) {
31 0         0 $handle = $self->{buffer};
32             }
33             else {
34 8 50       770 open $handle, '>', '/dev/null'
35             or confess "$self->{name}: open: /dev/null: $!\n";
36             }
37              
38 40         4027 $handle->autoflush;
39              
40 40 50 33     6648 POSIX::dup2( $handle->fileno, $fileno )
41             or confess "$self->{name}: dup2: $!\n"
42             if $std_h != $handle;
43             }
44              
45             sub parent {
46 94     94 1 356 my ( $self, $select ) = @_;
47              
48 94 100       801 unless( defined $self->{pipe} ) {
49 20 50       179 delete $self->{buffer}
50             if defined $self->{buffer};
51              
52 20         214 return;
53             }
54              
55 74         780 $self->{scratch} = undef;
56              
57 74         908 my $handle = $self->{pipe}->reader;
58 74         16304 $handle->blocking( 0 );
59              
60 74         476 $select->add( $handle );
61 74         6575 $self->{select} = $select;
62              
63 74         772 return ( $handle, $self );
64             }
65              
66             sub read {
67 116     116 1 2552 my ( $self ) = @_;
68              
69 116         316 my $handle = $self->{pipe};
70 116         1092 my $rc = $handle->sysread( my $data, 4096 );
71              
72 116 50       4110 if( not defined $rc ) {
    100          
73 0 0       0 if( $! != EWOULDBLOCK ) {
74 0         0 $self->_flush( $self->{scratch} );
75 0         0 confess "$self->{name}: sysread: $!\n";
76             }
77             }
78             elsif( $rc == 0 ) {
79 74         503 $self->_flush( $self->{scratch} );
80              
81 74         449 $self->{select}->remove( $handle );
82 74 50       3871 $handle->close
83             or confess "$self->{name}: close: $!\n";
84             }
85             else {
86 42         839 $self->_pack( $data );
87             }
88             }
89              
90             sub _pack {
91 42     42   223 my ( $self, $data ) = @_;
92              
93 42 100       359 if( ref $self->{buffer} eq 'SCALAR' ) {
94 14         38 ${ $self->{buffer} } .= $data;
  14         140  
95             }
96             else {
97 28 50       224 my $scratch = ( defined $self->{scratch} ? $self->{scratch} : '' ) . $data;
98              
99 28 100       242 if( defined $/ ) {
100 26         364 while( index( $scratch, $/ ) != -1 ) {
101 52         957 ( my $line, $scratch ) = split m#$/#, $scratch, 2;
102 52         275 $self->_flush( $line );
103             }
104             }
105              
106 28 100       423 $self->{scratch} = length $scratch ? $scratch : undef;
107             }
108             }
109              
110             sub _flush {
111 126     126   784 my ( $self, $data ) = @_;
112              
113             return
114 126 100       595 unless defined $data;
115              
116 56         190 my $buffer = $self->{buffer};
117              
118 56 100       265 if( ref $buffer eq 'ARRAY' ) {
    50          
119 38         323 push @$buffer, $data;
120             }
121             elsif( ref $buffer eq 'CODE' ) {
122 18         108 $buffer->( $data );
123             }
124             else {
125 0           confess "$self->{name}: API error\n";
126             }
127             }
128              
129              
130             1
131             __END__