File Coverage

blib/lib/Bio/Gonzales/Util/Role/FileIO.pm
Criterion Covered Total %
statement 44 44 100.0
branch 8 10 80.0
condition 1 6 16.6
subroutine 12 12 100.0
pod 1 2 50.0
total 66 74 89.1


line stmt bran cond sub pod time code
1             package Bio::Gonzales::Util::Role::FileIO;
2              
3 9     9   4877 use warnings;
  9         24  
  9         348  
4 9     9   54 use strict;
  9         20  
  9         218  
5              
6 9     9   4969 use Mouse::Role;
  9         11842  
  9         45  
7 9     9   3221 use Data::Dumper;
  9         21  
  9         493  
8 9     9   998 use Bio::Gonzales::Util::File qw/open_on_demand/;
  9         20  
  9         555  
9 9     9   63 use Carp;
  9         19  
  9         440  
10 9     9   66 use IO::Handle;
  9         19  
  9         424  
11 9     9   78 use IO::Zlib;
  9         41  
  9         75  
12              
13             our $VERSION = '0.083'; # VERSION
14              
15             has fh => ( is => 'rw' );
16             has mode => ( is => 'rw', default => '<' );
17             has _fhi => ( is => 'rw', lazy_build => 1 );
18             has _cached_records => ( is => 'rw', default => sub { [] } );
19             has record_separator => ( is => 'rw', default => $/ );
20             has record_filter => ( is => 'rw' );
21             has _fh_was_open => ( is => 'rw', default => 1 );
22              
23             requires 'BUILDARGS';
24              
25             # file handle iterator
26             sub _build__fhi {
27 12     12   35 my ($self) = @_;
28              
29 12         40 my $fh = $self->fh;
30              
31 12         48 my $rs = $self->record_separator;
32 12         102 my $filter = $self->record_filter;
33              
34             return sub {
35             # make use of cached records if we have
36 58         178 return shift @{ $self->_cached_records }
37 12362 100   12362   17270 if ( @{ $self->_cached_records } > 0 );
  12362         28748  
38              
39 12304         32352 local $/ = $rs;
40              
41 12304         17368 while (1) {
42 12304         24326 my $l = <$fh>;
43 12304 100       20381 if ( defined($l) ) {
44             # handle DOS format
45             #$l =~ s/\r\n$/\n/;
46             # this is 2x as fast
47 12286 50       24920 substr( $l, -2, 1, '' ) if ( substr( $l, -2, 1 ) eq "\r" );
48 12286         17474 chomp $l;
49             } else {
50 18         133 return;
51             }
52              
53 12286 50 0     49977 return $l
      33        
54             if ( !$filter || ( $filter && $filter->($l) ) );
55             }
56 12         117 };
57             }
58              
59             around BUILDARGS => sub {
60             my $orig = shift;
61             my $class = shift;
62              
63             if ( @_ == 1 && !ref $_[0] ) {
64             return $class->$orig( file => $_[0] );
65             } else {
66             return $class->$orig(@_);
67             }
68             };
69              
70       9 0   sub BUILD { }
71              
72             before BUILD => sub {
73             my ( $self, $args ) = @_;
74              
75             confess "use either file, fh or file_or_fh" . Dumper $args
76             if ( $self->fh && $args->{file} );
77             $args->{file} //= $args->{file_or_fh} if($args->{file_or_fh});
78             # open file
79             if ( $args->{file} ) {
80             my ( $fh, $was_open ) = open_on_demand( $args->{file}, $self->mode );
81             $self->fh($fh);
82             $self->_fh_was_open($was_open);
83             } else {
84             confess "You did not supply a file handle for fh: " . ref $self->fh
85             unless ( Bio::Gonzales::Util::File::is_fh( $self->fh ) );
86             }
87             };
88              
89             sub close {
90 7     7 1 35 my ($self) = @_;
91              
92 7         23 my $fh = $self->fh;
93 7 100       54 $fh->close unless ( $self->_fh_was_open );
94              
95 7         334 return;
96             }
97              
98             1;
99              
100             __END__
101              
102             =head1 NAME
103              
104             BaMo::Role::FileIO - File input & ouput interface for parser classes
105              
106             =head1 SYNOPSIS
107              
108             use Mouse;
109              
110             with 'BaMo::Role::FileIO';
111              
112             sub parse {
113             my ($self) = @_;
114             $fhi = $self->_fhi;
115              
116             while(my $line = $fhi->()) {
117             #parse a bit
118             if($line =~ /break/) {
119             # oh no, we parsed too much...
120             push @{$self->_cached_records}, $line;
121             #but we can reverse it
122             }
123             }
124             }
125              
126             =head1 DESCRIPTION
127              
128             Enhances the class that uses this role with a file handle iterator that is
129             capable of caching records (lines in most cases), in case you read too much.
130              
131             =head1 METHODS
132              
133             =over 4
134              
135             =item B<< $self->fh() >>
136              
137             Get or set the filehandle.
138              
139             =item B<< $self->_cached_records() >>
140              
141             You can push lines on @{$self->_cached_records} (they need to be chomped
142             already). The file handle iterator will use them first if you call it. The
143             file handle will not be touched until all cached lines are shifted.
144              
145             =item B<< $class->new(file => 'filename.xyz', mode => '<') >>
146              
147             Opens the file in the specified mode. Sets the C<fh> and C<_fhi> attribute (indirectly).
148              
149             =item B<< $self->_fhi() >>
150              
151             Get the file handle iterator.
152              
153             =item B<< $class->new(fh => $fh) >>
154              
155             =item B<< $self->close() >>
156              
157             Close the filehandle.
158              
159             =back
160              
161             =head1 SEE ALSO
162              
163             =head1 AUTHOR
164              
165             jw bargsten, C<< <joachim.bargsten at wur.nl> >>
166              
167             =cut