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   68819 use strict;
  26         81  
  26         887  
4 26     26   149 use warnings;
  26         52  
  26         1097  
5              
6             our @ISA = qw();
7              
8 26     26   532 use WARC; *WARC::Record::Block::VERSION = \$WARC::VERSION;
  26         46  
  26         793  
9              
10 26     26   140 use Carp;
  26         60  
  26         1663  
11 26     26   186 use Fcntl qw/SEEK_SET SEEK_CUR SEEK_END/;
  26         44  
  26         1697  
12              
13             # This implementation uses an array as the underlying object.
14              
15 26     26   181 use constant { BASE => 0, LENGTH => 1, HANDLE => 2, PARENT => 3, AT_EOF => 4 };
  26         48  
  26         2614  
16 26     26   176 use constant OBJECT_INIT => undef, undef, undef, undef, 0;
  26         53  
  26         24973  
17              
18             sub _dbg_dump {
19 23     23   641 my $self = shift;
20              
21 23         59 my $out = 'record block '.$self->[BASE].' +> '.$self->[LENGTH];
22 23         87 $out .= ' @'.((tell $self->[HANDLE]) - $self->[BASE]);
23 23 100       58 $out .= ' [EOF]' if $self->[AT_EOF];
24 23         31 $out .= "\n";
25              
26 23         68 return $out;
27             }
28              
29             sub TIEHANDLE {
30 139     139   6391 my $class = shift;
31 139         208 my $parent = shift;
32              
33 139         315 my $handle = $parent->volume->open;
34              
35 139 100       1458 if (defined $parent->{compression}) {
36 1 50       4 seek $handle, $parent->offset, SEEK_SET or die "seek: $!";
37              
38 1         7 my $z_reader = $parent->{compression};
39 1 50       7 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         1999 $handle = $zhandle;
44             }
45              
46 139         365 my $ob = [OBJECT_INIT];
47 139         369 @$ob[PARENT, HANDLE] = ($parent, $handle);
48             @$ob[BASE, LENGTH] =
49 139         448 ($parent->{data_offset}, $parent->field('Content-Length'));
50              
51 139         571 bless $ob, $class;
52              
53 139         388 $ob->SEEK(0, SEEK_SET);
54              
55 139         772 return $ob;
56             }
57              
58             sub READLINE {
59 228     228   391 my $self = shift;
60              
61 228 100       472 return undef if $self->[AT_EOF];
62              
63 226         3106 my $line = readline $self->[HANDLE];
64 226 100       623 unless (defined $line) { $self->[AT_EOF] = 1; return undef }
  1         2  
  1         6  
65              
66 225         549 my $excess = (tell $self->[HANDLE]) - $self->[BASE] - $self->[LENGTH];
67 225 100       475 $self->[AT_EOF] = 1 unless $excess < 0;
68 225 100       580 $line = substr $line, 0, -$excess if $excess > 0;
69              
70 225         1083 return $line;
71             }
72              
73             # This sub must rely on the aliasing effect of @_.
74             sub READ {
75 23     23   1010 my $self = shift;
76             # args now: 0: buffer 1: length 2: offset into buffer or undef
77 23         34 my $length = $_[1];
78 23   100     79 my $offset = $_[2] || 0;
79              
80 23 100       51 return 0 if $self->[AT_EOF];
81              
82 21         54 my $excess = (($length + tell $self->[HANDLE])
83             - $self->[BASE] - $self->[LENGTH]);
84 21 100       51 $self->[AT_EOF] = 1 unless $excess < 0;
85 21 100       41 $length -= $excess if $excess > 0;
86              
87 21         24 my $buf; my $count = read $self->[HANDLE], $buf, $length;
  21         45  
88 21 50       78 return undef unless defined $count;
89              
90 21 100       46 $_[0] = '' unless defined $_[0];
91 21 100       44 $_[0] .= "\0" x ($offset - length($_[0])) if $offset > length $_[0];
92 21         70 substr $_[0], $offset, (length($_[0]) - $offset), $buf;
93 21         73 return $count;
94             }
95              
96             sub GETC {
97 14     14   721 my $self = shift;
98              
99 14         20 my $ch;
100 14 100       25 return undef unless $self->READ($ch, 1);
101 13         39 return $ch;
102             }
103              
104 18     18   4033 sub EOF { (shift)->[AT_EOF] }
105              
106             sub SEEK {
107 150     150   236 my $self = shift;
108 150         208 my $offset = shift;
109 150         196 my $whence = shift;
110              
111 150         205 my $npos;
112 150         251 $self->[AT_EOF] = 0;
113              
114 150 100       299 if ($whence == SEEK_SET) { $npos = $offset }
  146 100       209  
    100          
115 1         3 elsif ($whence == SEEK_CUR) { $npos = $offset + $self->TELL }
116 2         5 elsif ($whence == SEEK_END) { $npos = $self->[LENGTH] + $offset }
117 1         229 else { croak "unknown WHENCE $whence in call to seek" }
118              
119 149 100       301 return 0 if $npos < 0;
120 148 100       418 if ($npos >= $self->[LENGTH]) { $self->[AT_EOF] = 1; $npos = $self->[LENGTH] }
  1         2  
  1         2  
121              
122 148         1345 seek $self->[HANDLE], $self->[BASE] + $npos, SEEK_SET;
123             }
124              
125             sub TELL {
126 28     28   350 my $self = shift;
127              
128 28 100       95 return $self->[LENGTH] if $self->[AT_EOF];
129              
130 14         54 return ((tell $self->[HANDLE]) - $self->[BASE]);
131             }
132              
133             sub CLOSE {
134 48     48   84 my $self = shift;
135 48         123 @$self[BASE, LENGTH, AT_EOF] = (0, 0, 1);
136 48         672 close $self->[HANDLE];
137             }
138              
139             1;
140             __END__