File Coverage

blib/lib/Bio/SFF/Reader/Random.pm
Criterion Covered Total %
statement 45 50 90.0
branch 4 10 40.0
condition n/a
subroutine 8 9 88.8
pod 1 1 100.0
total 58 70 82.8


line stmt bran cond sub pod time code
1             package Bio::SFF::Reader::Random;
2             {
3             $Bio::SFF::Reader::Random::VERSION = '0.007';
4             }
5              
6 1     1   1206138 use Moo;
  1         602997  
  1         8  
7              
8 1     1   2454 use Bio::SFF::Index;
  1         4  
  1         43  
9 1     1   11 use Carp qw/croak/;
  1         2  
  1         72  
10 1     1   1179 use Const::Fast;
  1         1457  
  1         8  
11 1     1   201 use Fcntl qw/SEEK_SET/;
  1         3  
  1         833  
12              
13             const my $index_header => 8;
14             const my $roche_offset => 5;
15             const my $base255 => 255;
16              
17             has _index => (
18             is => 'ro',
19             init_arg => undef,
20             builder => '_build_index',
21             lazy => 1,
22             predicate => '_has_index'
23             );
24              
25             with 'Bio::SFF::Reader';
26              
27             sub _build_index {
28 1     1   550 my $self = shift;
29 1         5 my $magic_number = $self->_index_info;
30 1 50       44 my $has_roche_index = defined $magic_number and $magic_number =~ / \A \.[sm]ft 1\.00 \z /xm;
31 1 50       8 return $has_roche_index ? $self->_read_roche_index($magic_number) : $self->_read_slow_index;
32             }
33              
34             sub _read_roche_index {
35 1     1   3 my ($self, $magic_number) = @_;
36              
37 1         6 my ($index_offset, $index_length) = ($self->header->index_offset, $self->header->index_length);
38 1         72 my $tell = $self->_fh->tell;
39 1         13 $self->_fh->seek($index_offset + $index_header, SEEK_SET);
40              
41 1         16 my $xml = $self->_read_manifest($magic_number);
42 1         13 my ($counter, $buffer, %offset_for) = (0, '');
43 1         6 while ($counter < $self->_number_of_reads) {
44 1 50       65 read $self->_fh, $buffer, 8192, length $buffer or croak "Couldn\'t read index($counter)";
45 1         11 while ($buffer =~ m/ (.+?) \xFF /gcxs) {
46 10         17 my $name = $1;
47 10         36 my @offset = unpack 'C5', substr $name, -$roche_offset, $roche_offset, '';
48 10         36 $offset_for{$name} = $offset[-1] + 255 * $offset[-2] + 255**2 * $offset[-3] + 255**3 * $offset[-4];
49 10         47 $counter++;
50             }
51 1         7 $buffer = substr $buffer, pos $buffer;
52             }
53 1         43 $self->_fh->seek($tell, SEEK_SET);
54 1         20 return Bio::SFF::Index->new(offsets => \%offset_for, manifest => $xml);
55             }
56              
57             sub _read_slow_index {
58 1     1   36 my $self = shift;
59 1         6 my $position = $self->header->header_length;
60              
61 1         48 my $tell = $self->_fh->tell;
62 1 50       14 $self->_fh->seek($position, SEEK_SET) or croak "Couldn't seek: $!";
63              
64 1         18 my %offset_for;
65 1         5 for my $counter (1 .. $self->_number_of_reads) {
66 10         334 my $offset = $self->_fh->tell;
67 10         81 $offset_for{ $self->_read_entry->name } = $offset;
68             }
69 1         26 $self->_fh->seek($tell, SEEK_SET);
70 1         43 return Bio::SFF::Index->new(offsets => \%offset_for, manifest => undef);
71             }
72              
73             sub lookup {
74 0     0 1   my ($self, $name) = @_;
75 0           my $offset = $self->_index->offset_of($name);
76 0 0         return if not defined $offset;
77 0           $self->_fh->seek($offset, SEEK_SET);
78 0           return $self->_read_entry;
79             }
80              
81             1;
82              
83             #ABSTRACT: Random-access SFF reader
84              
85             __END__