File Coverage

blib/lib/WARC/Record/Block.pm
Criterion Covered Total %
statement 91 91 100.0
branch 39 42 92.8
condition 2 2 100.0
subroutine 16 16 100.0
pod n/a
total 148 151 98.0


line stmt bran cond sub pod time code
1             package WARC::Record::Block; # -*- CPerl -*-
2              
3 26     26   67575 use strict;
  26         70  
  26         771  
4 26     26   138 use warnings;
  26         46  
  26         1159  
5              
6             our @ISA = qw();
7              
8 26     26   517 use WARC; *WARC::Record::Block::VERSION = \$WARC::VERSION;
  26         47  
  26         861  
9              
10 26     26   130 use Carp;
  26         86  
  26         1445  
11 26     26   192 use Fcntl qw/SEEK_SET SEEK_CUR SEEK_END/;
  26         87  
  26         1570  
12              
13             # This implementation uses an array as the underlying object.
14              
15 26     26   166 use constant { BASE => 0, LENGTH => 1, HANDLE => 2, PARENT => 3, AT_EOF => 4 };
  26         47  
  26         2356  
16 26     26   186 use constant OBJECT_INIT => undef, undef, undef, undef, 0;
  26         63  
  26         24249  
17              
18             sub _dbg_dump {
19 23     23   639 my $self = shift;
20              
21 23         65 my $out = 'record block '.$self->[BASE].' +> '.$self->[LENGTH];
22 23         78 $out .= ' @'.((tell $self->[HANDLE]) - $self->[BASE]);
23 23 100       56 $out .= ' [EOF]' if $self->[AT_EOF];
24 23         50 $out .= "\n";
25              
26 23         69 return $out;
27             }
28              
29             sub TIEHANDLE {
30 70     70   6045 my $class = shift;
31 70         88 my $parent = shift;
32              
33 70         140 my $handle = $parent->volume->open;
34              
35 70 100       1062 if (defined $parent->{compression}) {
36 1 50       4 seek $handle, $parent->offset, SEEK_SET or die "seek: $!";
37              
38 1         8 my $z_reader = $parent->{compression};
39 1 50       9 my $zhandle = new $z_reader ($handle, MultiStream => 0, Transparent => 0,
40             AutoClose => 1)
41             or die "$z_reader: ".$parent->_get_compression_error;
42              
43 1         1831 $handle = $zhandle;
44             }
45              
46 70         159 my $ob = [OBJECT_INIT];
47 70         159 @$ob[PARENT, HANDLE] = ($parent, $handle);
48             @$ob[BASE, LENGTH] =
49 70         204 ($parent->{data_offset}, $parent->field('Content-Length'));
50              
51 70         292 bless $ob, $class;
52              
53 70         169 $ob->SEEK(0, SEEK_SET);
54              
55 70         355 return $ob;
56             }
57              
58             sub READLINE {
59 159     159   232 my $self = shift;
60              
61 159 100       268 return undef if $self->[AT_EOF];
62              
63 157         1115 my $line = readline $self->[HANDLE];
64 157 100       316 unless (defined $line) { $self->[AT_EOF] = 1; return undef }
  1         3  
  1         6  
65              
66 156         279 my $excess = (tell $self->[HANDLE]) - $self->[BASE] - $self->[LENGTH];
67 156 100       245 $self->[AT_EOF] = 1 unless $excess < 0;
68 156 100       272 $line = substr $line, 0, -$excess if $excess > 0;
69              
70 156         523 return $line;
71             }
72              
73             # This sub must rely on the aliasing effect of @_.
74             sub READ {
75 23     23   956 my $self = shift;
76             # args now: 0: buffer 1: length 2: offset into buffer or undef
77 23         70 my $length = $_[1];
78 23   100     75 my $offset = $_[2] || 0;
79              
80 23 100       93 return 0 if $self->[AT_EOF];
81              
82 21         55 my $excess = (($length + tell $self->[HANDLE])
83             - $self->[BASE] - $self->[LENGTH]);
84 21 100       54 $self->[AT_EOF] = 1 unless $excess < 0;
85 21 100       40 $length -= $excess if $excess > 0;
86              
87 21         27 my $buf; my $count = read $self->[HANDLE], $buf, $length;
  21         49  
88 21 50       82 return undef unless defined $count;
89              
90 21 100       39 $_[0] = '' unless defined $_[0];
91 21 100       45 $_[0] .= "\0" x ($offset - length($_[0])) if $offset > length $_[0];
92 21         39 substr $_[0], $offset, (length($_[0]) - $offset), $buf;
93 21         66 return $count;
94             }
95              
96             sub GETC {
97 14     14   347 my $self = shift;
98              
99 14         17 my $ch;
100 14 100       25 return undef unless $self->READ($ch, 1);
101 13         41 return $ch;
102             }
103              
104 18     18   3934 sub EOF { (shift)->[AT_EOF] }
105              
106             sub SEEK {
107 81     81   118 my $self = shift;
108 81         94 my $offset = shift;
109 81         103 my $whence = shift;
110              
111 81         95 my $npos;
112 81         118 $self->[AT_EOF] = 0;
113              
114 81 100       152 if ($whence == SEEK_SET) { $npos = $offset }
  77 100       93  
    100          
115 1         3 elsif ($whence == SEEK_CUR) { $npos = $offset + $self->TELL }
116 2         4 elsif ($whence == SEEK_END) { $npos = $self->[LENGTH] + $offset }
117 1         219 else { croak "unknown WHENCE $whence in call to seek" }
118              
119 80 100       148 return 0 if $npos < 0;
120 79 100       196 if ($npos >= $self->[LENGTH]) { $self->[AT_EOF] = 1; $npos = $self->[LENGTH] }
  1         2  
  1         2  
121              
122 79         540 seek $self->[HANDLE], $self->[BASE] + $npos, SEEK_SET;
123             }
124              
125             sub TELL {
126 28     28   344 my $self = shift;
127              
128 28 100       85 return $self->[LENGTH] if $self->[AT_EOF];
129              
130 14         51 return ((tell $self->[HANDLE]) - $self->[BASE]);
131             }
132              
133             sub CLOSE {
134 15     15   22 my $self = shift;
135 15         40 @$self[BASE, LENGTH, AT_EOF] = (0, 0, 1);
136 15         164 close $self->[HANDLE];
137             }
138              
139             1;
140             __END__