File Coverage

blib/lib/PerlIO/via/Skip.pm
Criterion Covered Total %
statement 47 59 79.6
branch 19 36 52.7
condition 4 11 36.3
subroutine 8 8 100.0
pod 0 4 0.0
total 78 118 66.1


line stmt bran cond sub pod time code
1             package PerlIO::via::Skip;
2              
3             #use 5.008004;
4 24     24   714815 use strict;
  24         62  
  24         1157  
5 24     24   131 use warnings;
  24         50  
  24         3573  
6             #use Data::Dumper;
7              
8             require Exporter;
9              
10             our $VERSION = '0.06';
11             use constant DEFAULTS => ( start => undef ,
12             end => undef ,
13             maxlines => undef ,
14             skippatterns => undef ,
15             skipblanklines => 0 ,
16             skipcomments => 0 ,
17             after => 0 ,
18             nread_ => 0 ,
19             nwrite_ => 0 ,
20             n_ => 0 ,
21             bipolar => sub {
22 13         21 my $obj = shift;
23 13 100       45 ($_[0]..$_[1]) ? ++$obj->{n_} : ($obj->{n_}=0);
24 13 100 50     88 ($obj->{n_} > ($obj->{after}||0)) ? return 1 :0;
25 24     24   152 }, );
  24         54  
  24         41589  
26              
27              
28             sub PUSHED {
29 27     27 0 79258 my ($class, $mode, $fh) = @_ ;
30 27 100       206 ($mode =~ /^[rwa]$/) or return -1 ;
31 19         4674 my $obj = (defined $ENV{ viaSKIP})
32 25 100       198 ? bless { DEFAULTS, %{$ENV{ viaSKIP}} }
33             : bless { DEFAULTS } ;
34             # init stuff
35 6         16 reset;
36 6         36 $obj->{qr_} = [compile_patterns( $obj->{skippatterns} ) ];
37 6 50       29 $obj->{skipblanklines} and ($obj->{qr_} = [ qr/^\s*$/, @{$obj->{qr_}}]);
  0         0  
38 6 50       20 $obj->{skipcomments} and ($obj->{qr_} = [ qr/^\s*#/, @{$obj->{qr_}}]);
  0         0  
39 6         20 ($obj->{bipolar})->( $obj, 0, 1 );
40 6 50       171 (defined $obj->{start}) ? ($obj->{start} = qr/\s*$obj->{start}\s*/)
41             : ($obj->{start} = qr/^/ );
42             (defined $obj->{ end }) ? ($obj->{ end } = qr/\s*$obj->{ end }\s*/)
43 6 50       152 : ($obj->{ end } = qr/^.\A/ );
44 6         77 $obj;
45             }
46              
47             sub compile_patterns {
48 6     6 0 12 my $pats = shift;
49 6 50       29 return unless $pats;
50 0 0       0 return qr/$pats/ unless ref $pats;
51 0         0 map {qr/$_/} @$pats;
  0         0  
52             }
53              
54              
55              
56             sub FILL {
57 1     1 0 14 my ($obj, $fh) = @_ ;
58              
59             # stop output if maxlines will be exceeded
60 1 50 33     6 (defined $obj->{maxlines}) &&
61             ($obj->{nread_} >= $obj->{maxlines}) && return;
62 1         2 local $_ = <$fh>;
63 1 50       4 return undef unless (defined $_);
64 1         4 my ($s, $e) = ( $obj->{start} , $obj->{end} );
65 1   33     3 until ( pattern_check( $obj , $_ ) &&
66             ($obj->{bipolar})->( $obj, scalar (?$s?), scalar (/$e/) )
67             ){
68 0         0 $_ = <$fh>;
69 0         0 $. = $obj->{nread_};
70 0 0       0 return undef unless (defined $_);
71             }
72             # update stats
73 1         4 $. = ++ $obj->{nread_};
74 1         30 $_;
75             }
76              
77              
78             sub pattern_check {
79             # return FALSE if line should be ignored
80 7     7 0 10 my ($obj, $line) = @_ ;
81 7 50       9 return 1 unless @{$obj->{qr_}};
  7         68  
82 0         0 for (@{$obj->{qr_}} ) {
  0         0  
83 0 0       0 return 0 if $line =~ $_ ;
84             }
85 0         0 1;
86             }
87              
88              
89             sub WRITE {
90 6     6   37 my ($obj, $buf, $fh) = @_ ;
91 6         7 local $_ = $buf;
92              
93 6 50 33     19 return 0 if (defined $obj->{maxlines}) &&
94             ($obj->{nwrite_} >= $obj->{maxlines});
95 6 50       15 return 0 unless pattern_check( $obj , $_ );
96 6         27 my $s = ?$obj->{start}? ;
97 6         19 my $e = /$obj->{end}/ ;
98             #print qq (write: "$_"\n);
99 6 50       14 return 0 unless ($obj->{bipolar})->( $obj , $s , $e );
100 6         22 printf $fh "%s", $buf;
101 6         10 ++ $obj->{nwrite_};
102 6         26 length ;
103             }
104              
105             1;
106             __END__
107             # Below is stub documentation for your module. You'd better edit it!
108              
109             =head1 NAME
110              
111             PerlIO::via::Skip - PerlIO layer for skipping lines
112              
113             =head1 SYNOPSIS
114              
115             use PerlIO::via::Skip;
116              
117             $ENV{ viaSKIP} = { start=>'Fiat', end=>'Reno' };
118             open my $i ,'<:via(Skip)', 'cars' or die $!;
119              
120              
121             $ENV{ viaSKIP} = { start => 'Fiat' ,
122             end => undef ,
123             maxlines => 10 ,
124             after => 0 ,
125             skippatterns => [qw( a e )] ,
126             skipcomments => 1 ,
127             skipblanklines => 1 , }
128             open my $i ,'<:via(Skip)', 'cars' or die $!;
129              
130              
131             =head1 DESCRIPTION
132              
133             This module implements a PerlIO layer that discards lines from
134             IO streams. By default, all lines are accepted and passed-through
135             as if no filters are present. Input filters discard input lines,
136             and output filters discard output lines; therefore, input lines
137             (that meet user's criteria) are excluded from input, and in a similar
138             manner when specified, output lines are omitted from output.
139              
140             The code is re-entrant. Multiple filters can be
141             stacked together without interfering with one another.
142             These filters were designed for read, write, and append handles
143             ( 'r', 'w', 'a'), but will refuse installation
144             for read-write mode.
145              
146             =head1 CONFIGURATION
147              
148             In order to stay re-entrant, configuration is done by setting the
149             global variable $ENV{viaSKIP} . While other PerlIO modules are
150             usually configured via class variables through import(), I choose
151             to sacrifice pretty syntax for data integrity. During the call to
152             open(), or during binmode(), the filter reads its configuration
153             from the $ENV{viaSKIP} variable; since this is a dynamic value, you
154             probably want to change it before the open(), or binmode() if other
155             filters should read a different configurations.
156              
157             The env variable 'viaSKIP' takes the form of a hash reference.
158             For example: $ENV{ viaSKIP } = { maxlines=> 10, start=>'apple' };
159              
160             Where 'maxlines', and 'start' are configuration parameters. Here are
161             all the parameters that allow you to alter the characteristics of
162             the filter:
163              
164             maxlines limit the maximum number of input (or output) lines
165             skippatterns skip lines containing one of these patterns
166             skipblanklines skip whitespace lines
167             skipcomments skip lines with (leading) comments
168             start Start a bipolar vibrator. Skip leading lines
169             until a certain pattern
170             end End a bipolar vibrator. Skip remaining lines
171             after a certain pattern.
172             after Used with a bipolar vibrator. Skip more leading lines,
173             after you find the start pattern.
174              
175              
176             =head2 EXPORT
177              
178             None by default.
179              
180              
181             =head1 SEE ALSO
182              
183             Consult the documentation of the range operator,
184             when in scalar context for a description on how
185             the bipolar vibrator operates. Note, however,
186             that in this implementation the bipolar is designed
187             for only full one cycle. (Will need to change
188             the range operator from a a m?? regex to a m// regex
189             if you need infinite cycles.)
190              
191              
192             =head1 AUTHOR
193              
194             Ioannis Tambouras E<lt>ioannis@cpan.org>
195              
196             =head1 COPYRIGHT AND LICENSE
197              
198             Copyright (C) 2005 by Ioannis Tambouras
199              
200             This library is free software; you can redistribute it and/or modify
201             it under the same terms as Perl itself, either Perl version 5.8.4 or,
202             at your option, any later version of Perl 5 you may have available.
203              
204              
205             =cut