File Coverage

blib/lib/File/LinearRaid.pm
Criterion Covered Total %
statement 112 123 91.0
branch 34 48 70.8
condition 6 7 85.7
subroutine 17 20 85.0
pod 3 3 100.0
total 172 201 85.5


line stmt bran cond sub pod time code
1             package File::LinearRaid;
2              
3 1     1   734 use strict;
  1         1  
  1         36  
4 1     1   4 use warnings;
  1         2  
  1         36  
5 1     1   18 use Symbol;
  1         2  
  1         71  
6 1     1   5 use Carp;
  1         1  
  1         56  
7 1     1   5 use vars '$VERSION';
  1         2  
  1         1283  
8              
9             $VERSION = '0.12';
10              
11             sub new {
12 3     3 1 9373 my $pkg = shift;
13            
14 3         19 my $sym = gensym;
15 3         56 tie *$sym, $pkg, @_;
16              
17 3         12 return bless $sym, $pkg;
18             }
19              
20             sub size {
21 2     2 1 6 tied( *{+shift} )->{length};
  2         19  
22             }
23              
24             sub append {
25 1     1 1 2 my $self = tied( *{+shift} );
  1         3  
26            
27 1         6 while (my ($file, $size) = splice @_, 0, 2) {
28 1 50       46 open my $fh, $self->{mode}, $file
29             or croak "File::LinearRaid: couldn't open $file: $!\n";
30              
31 1         2 push @{ $self->{handles} }, $fh;
  1         2  
32 1         2 push @{ $self->{files} }, $file;
  1         3  
33 1         1 push @{ $self->{sizes} }, $size;
  1         2  
34            
35 1         4 $self->{length} += $size;
36             }
37              
38 1         3 return 1;
39             }
40              
41             sub TIEHANDLE {
42 3     3   7 my $pkg = shift;
43 3         5 my $mode = shift;
44            
45 3         4 my @files;
46             my @sizes;
47 0         0 my @handles;
48 3         7 my $length = 0;
49            
50 3         18 while (my ($file, $size) = splice @_, 0, 2) {
51 7 50       311 open my $fh, $mode, $file
52             or croak "File::LinearRaid: couldn't open $file: $!\n";
53            
54 7         13 push @handles, $fh;
55 7         11 push @files, $file;
56 7         9 push @sizes, $size;
57 7         29 $length += $size;
58             }
59            
60             bless {
61 3         26 pos => 0,
62             files => \@files,
63             sizes => \@sizes,
64             handles => \@handles,
65             length => $length,
66             mode => $mode
67             }, $pkg;
68             }
69              
70             sub READ {
71 20     20   60 my ($self, undef, $length, $offset) = @_;
72            
73 20   100     55 $offset ||= 0;
74            
75 20 100       30 if ($self->EOF) {
76 5         8 substr($_[1], $offset) = "";
77 5         19 return 0;
78             }
79            
80 15         25 my $pos = $self->{pos};
81              
82 15         15 my $f = 0;
83 15         36 while ($pos >= $self->{sizes}[$f]) {
84 11         13 $pos -= $self->{sizes}[$f];
85 11         96 $f++;
86             }
87            
88 15         17 my $b;
89            
90 15 100       34 my $this_read = ($pos + $length > $self->{sizes}[$f])
91             ? $self->{sizes}[$f] - $pos
92             : $length;
93            
94 15 100       40 if (tell $self->{handles}[$f] != $pos) {
95 9 50       67 seek $self->{handles}[$f], $pos, 0
96             or croak "File::LinearRaid: couldn't seek $self->{files}[$f]: $!";
97             }
98            
99 15         154 $b = read $self->{handles}[$f], $_[1], $this_read, $offset;
100              
101 15 50       32 defined $b
102             or croak "File::LinearRaid: error reading from $self->{files}[$f]: $!";
103              
104 15         19 $self->{pos} += $this_read;
105            
106 15 100       25 if ( $b < $this_read ) {
107             # pad out rest of chunk with nulls
108 2         9 substr($_[1], $offset + $b) = "\x0" x ($this_read - $b);
109             }
110              
111 15 100       23 if ($this_read == $length) {
112 6         16 return $length;
113             } else {
114 9         32 return $this_read + $self->READ($_[1], $length - $this_read, $offset + $this_read);
115             }
116             }
117              
118             sub READLINE {
119 6     6   901 my $self = shift;
120 6         10 my $oldpos = $self->{pos};
121              
122 6 100       8 return undef if $self->EOF;
123            
124 5         7 my $buf = "";
125            
126 5 100       13 if (not defined $/) {
    50          
127 2         5 $self->READ($buf, $self->{length} - $oldpos);
128             } elsif (ref $/) {
129 0         0 $self->READ($buf, ${$/});
  0         0  
130             } else {
131            
132 3   66     15 while (index($buf, $/) == -1 and not $self->EOF) {
133 3         10 $self->READ($buf, 1024, length $buf);
134             }
135            
136 3 50       9 if (index($buf, $/) != -1) {
137 3         5 substr($buf, index($buf, $/) + length($/)) = "";
138 3         7 $self->{pos} = $oldpos + length $buf;
139             }
140             }
141            
142 5         14 return $buf;
143            
144             }
145              
146             sub GETC {
147 0     0   0 my $c;
148 0         0 $_[0]->READ($c, 1);
149 0         0 return $c;
150             }
151              
152              
153              
154             sub WRITE {
155 3     3   5 my ($self, undef, $length, $offset) = @_;
156            
157 3   100     10 $offset ||= 0;
158            
159 3 50       5 if ($self->EOF) {
160 0         0 return 0;
161             }
162            
163 3         8 my $pos = $self->{pos};
164              
165 3         3 my $f = 0;
166 3         8 while ($pos >= $self->{sizes}[$f]) {
167 1         2 $pos -= $self->{sizes}[$f];
168 1         3 $f++;
169             }
170            
171 3 100       8 my $this_write = ($pos + $length > $self->{sizes}[$f])
172             ? $self->{sizes}[$f] - $pos
173             : $length;
174            
175 3 100       9 if (tell $self->{handles}[$f] != $pos) {
176 2 50       57 seek $self->{handles}[$f], $pos, 0
177             or croak "File::LinearRaid: couldn't seek $self->{files}[$f]: $!";
178             }
179            
180 3 50       2 print { $self->{handles}[$f] } substr($_[1], $offset, $this_write)
  3         17  
181             or return 0;
182              
183 3         6 $self->{pos} += $this_write;
184              
185 3 100       5 if ($this_write == $length) {
186 2         7 return 1;
187             } else {
188 1         6 return $self->WRITE($_[1], $length - $this_write, $offset + $this_write);
189             }
190             }
191              
192             sub PRINT {
193 2     2   11 my $self = shift;
194 2 50       6 my $buf = join +(defined $, ? $, : "") => @_;
195 2         6 $self->WRITE($buf, length($buf), 0);
196             }
197              
198             sub PRINTF {
199 0     0   0 my $self = shift;
200 0         0 my $fmt = shift;
201 0         0 $self->PRINT( sprintf $fmt, @_ );
202             }
203              
204              
205              
206             sub SEEK {
207 12     12   2079 my ($self, $offset, $whence) = @_;
208            
209 12         22 my $pos = $self->{pos};
210            
211 12 50       28 $whence == 0 and $pos = $offset;
212 12 50       24 $whence == 1 and $pos += $offset;
213 12 50       25 $whence == 2 and $pos = $self->{size} + $offset;
214              
215 12 50       21 return 0 if $pos < 0;
216 12         16 $self->{pos} = $pos;
217 12         38 return 1;
218             }
219              
220             sub TELL {
221 14     14   5185 $_[0]->{pos};
222             }
223              
224             sub EOF {
225 33     33   36 my $self = shift;
226 33         108 return $self->{pos} == $self->{length};
227             }
228              
229             sub CLOSE {
230 1     1   307 close $_ for @{ $_[0]->{handles} };
  1         20  
231 1         99 $_[0] = undef;
232             }
233              
234             sub OPEN {
235 0     0     croak "File::LinearRaid::OPEN Unimplemented";
236             }
237             1;
238              
239             __END__