File Coverage

blib/lib/IO/React.pm
Criterion Covered Total %
statement 22 68 32.3
branch 10 40 25.0
condition 7 15 46.6
subroutine 8 14 57.1
pod 0 7 0.0
total 47 144 32.6


line stmt bran cond sub pod time code
1              
2             require 5.6.0;
3             package IO::React;
4 1     1   576 use strict;
  1         2  
  1         90  
5 1     1   6 use Carp;
  1         1  
  1         91  
6 1     1   1030 use IO::File;
  1         11891  
  1         1041  
7              
8             ## Module Version
9             our $VERSION = 1.03;
10              
11              
12             ### Constructor
13              
14             sub new ($) {
15 11     11 0 393 my ($class, $handle) = @_;
16             return bless {
17             Handle => $handle,
18             Display => 1,
19             Wait => undef,
20 0     0   0 Timeout => sub { },
21 0     0   0 EOF => sub { },
22 11         99 }, $class;
23             }
24              
25              
26             ### Methods
27              
28             # Set the wait interval
29             sub set_wait ($) {
30 4     4 0 18 my ($self, $wait) = @_;
31 4 100 100     219 croak "non-numeric wait value: $wait"
32             if ( defined $wait and $wait !~ /^\d+$/ );
33 3         20 $self->{Wait} = $wait;
34             }
35              
36             # Set the timeout behaviour
37             sub set_timeout ($) {
38 2     2 0 12 my ($self, $timeout) = @_;
39 2 100 66     119 croak "non-numeric timeout callback: $timeout"
40             if ( defined $timeout and "$timeout" !~ /^CODE/ );
41 1 50   0   7 $self->{Timeout} = $timeout ? $timeout : sub { };
  0         0  
42             }
43              
44             # Set the eof behaviour
45             sub set_eof ($) {
46 2     2 0 11 my ($self, $eof) = @_;
47 2 100 66     101 croak "non-numeric eof callback: $eof"
48             if ( defined $eof and "$eof" !~ /^CODE/ );
49 1 50   0   8 $self->{EOF} = $eof ? $eof : sub { };
  0         0  
50             }
51              
52             # Control the display
53             sub set_display ($) {
54 2     2 0 9 my ($self, $display) = @_;
55 2 100       13 $self->{Display} = $display ? 1 : 0;
56             }
57              
58             # Write to the handle
59             sub write ($$) {
60 0     0 0   my ($self, $data) = @_;
61 0           my $handle = $self->{Handle};
62 0           return syswrite($handle, $data, length($data));
63             }
64              
65             # React to output matching given patterns
66             sub react ($) {
67 0     0 0   my ($self, @p) = @_;
68 0           my %p = @p;
69 0           my $handle = $self->{Handle};
70              
71             # Options
72 0 0         my $wait = ( exists $p{WAIT} ) ? $p{WAIT} : $self->{Wait};
73 0 0         my $timeout = ( exists $p{TIMEOUT} ) ? $p{TIMEOUT} : $self->{Timeout};
74 0 0         my $eof = ( exists $p{EOF} ) ? $p{EOF} : $self->{EOF};
75 0           delete $p{WAIT};
76 0           delete $p{TIMEOUT};
77 0           delete $p{EOF};
78 0 0 0       croak "non-numeric wait value: $wait"
79             if ( defined $wait and $wait !~ /^\d+$/ );
80              
81 0           my $start = time;
82 0           my $timeleft = $wait;
83 0           my $text = '';
84 0           my $buf = '';
85 0           my $rin = '';
86 0           vec($rin, $handle->fileno, 1) = 1; # Bit vector of handles to select
87              
88 0           ReadData:
89             my $nfound = select(my $rout=$rin, undef, undef, $timeleft);
90 0 0         croak "select failed: $!" if ( $nfound < 0 );
91 0 0         if ( $nfound == 0 ) {
92             # Timeout can set a new time limit
93 0           $timeleft = $timeout->();
94 0 0 0       croak "TIMEOUT function returned non-numeric value: $timeleft"
95             if ( defined $timeleft and $timeleft !~ /^\d+$/ );
96 0 0         goto ReadData if defined $timeleft;
97 0           return;
98             }
99              
100 0           my $nread = sysread($handle, $buf, 1024);
101 0 0         croak "sysread failed: $!" if ( $nread < 0 );
102 0 0         if ( $nread == 0 ) {
103             # End of file
104 0           $eof->();
105 0           return;
106             }
107              
108 0 0         print $buf if $self->{Display};
109              
110 0           $text .= $buf; # Accumuate text for matching
111              
112             # Check all the patterns
113 0           foreach ( keys %p ) {
114 0 0         if ( $text =~ /$_/m ) {
115 0           my $f = $p{$_};
116 0           $f->($handle, $text);
117 0           return 1;
118             }
119             }
120              
121             # If there is no timeout, just go back to waiting
122 0 0         goto ReadData unless defined $timeleft;
123              
124             # Otherwise, adjust timer for the time that has passed
125 0           $timeleft = $wait - ( time - $start );
126 0 0         $timeleft = 0 if ( $timeleft < 0 ); # Must not be negative
127 0           goto ReadData;
128             }
129              
130             1;
131              
132             __END__