5 IO::InnerFile - define a file inside another file
11 ### Read a subset of a file:
12 $inner = IO::InnerFile->new($fh, $start, $length);
20 If you have a filehandle that can seek() and tell(), then you
21 can open an IO::InnerFile on a range of the underlying file.
24 =head1 PUBLIC INTERFACE
32 # The package version, both in 1.23 style *and* usable by MakeMaker:
35 #------------------------------
37 =item new FILEHANDLE, [START, [LENGTH]]
39 I<Class method, constructor.>
40 Create a new inner-file opened on the given FILEHANDLE,
41 from bytes START to START+LENGTH. Both START and LENGTH
42 default to 0; negative values are silently coerced to zero.
44 Note that FILEHANDLE must be able to seek() and tell(), in addition
45 to whatever other methods you may desire for reading it.
50 my ($class, $fh, $start, $lg) = @_;
51 $start = 0 if (!$start or ($start < 0));
52 $lg = 0 if (!$lg or ($lg < 0));
54 ### Create the underlying "object":
62 ### Create a new filehandle tied to this object:
64 tie(*$fh, $class, $a);
65 return bless($fh, $class);
69 my ($class, $data) = @_;
70 return bless($data, $class);
75 $self->close() if (ref($self) eq 'SCALAR');
78 #------------------------------
80 =item set_length LENGTH
84 =item add_length NBYTES
87 Get/set the virtual length of the inner file.
91 sub set_length { tied(${$_[0]})->{LG} = $_[1]; }
92 sub get_length { tied(${$_[0]})->{LG}; }
93 sub add_length { tied(${$_[0]})->{LG} += $_[1]; }
95 #------------------------------
101 =item add_start NBYTES
104 Get/set the virtual start position of the inner file.
108 sub set_start { tied(${$_[0]})->{START} = $_[1]; }
109 sub get_start { tied(${$_[0]})->{START}; }
110 sub set_end { tied(${$_[0]})->{LG} = $_[1] - tied(${$_[0]})->{START}; }
111 sub get_end { tied(${$_[0]})->{LG} + tied(${$_[0]})->{START}; }
114 #------------------------------
130 =item read BUF, NBYTES
134 =item seek OFFFSET, WHENCE
141 Standard filehandle methods.
145 sub write { shift->WRITE(@_) }
146 sub print { shift->PRINT(@_) }
147 sub printf { shift->PRINTF(@_) }
148 sub flush { "0 but true"; }
150 sub getc { return GETC(tied(${$_[0]}) ); }
151 sub read { return READ( tied(${$_[0]}), @_[1,2,3] ); }
152 sub readline { return READLINE( tied(${$_[0]}) ); }
153 sub getline { return READLINE( tied(${$_[0]}) ); }
154 sub close { return CLOSE(tied(${$_[0]}) ); }
157 my ($self, $ofs, $whence) = @_;
158 $self = tied( $$self );
160 $self->{CRPOS} = $ofs if ($whence == 0);
161 $self->{CRPOS}+= $ofs if ($whence == 1);
162 $self->{CRPOS} = $self->{LG} + $ofs if ($whence == 2);
164 $self->{CRPOS} = 0 if ($self->{CRPOS} < 0);
165 $self->{CRPOS} = $self->{LG} if ($self->{CRPOS} > $self->{LG});
170 return tied(${$_[0]})->{CRPOS};
174 die "inner files can only open for reading\n";
178 die "inner files can only open for reading\n";
182 die "inner files can only open for reading\n";
187 return 0 if ($self->{CRPOS} >= $self->{LG});
192 my $old_pos = $self->{FH}->tell;
193 $self->{FH}->seek($self->{CRPOS}+$self->{START}, 0);
196 my $lg = $self->{FH}->read($data, 1);
197 $self->{CRPOS} += $lg;
200 $self->{FH}->seek($old_pos, 0);
202 $self->{LG} = $self->{CRPOS} unless ($lg);
203 return ($lg ? $data : undef);
207 my ($self, $undefined, $lg, $ofs) = @_;
210 return 0 if ($self->{CRPOS} >= $self->{LG});
211 $lg = $self->{LG} - $self->{CRPOS} if ($self->{CRPOS} + $lg > $self->{LG});
212 return 0 unless ($lg);
215 my $old_pos = $self->{FH}->tell;
216 $self->{FH}->seek($self->{CRPOS}+$self->{START}, 0);
219 $lg = $self->{FH}->read($_[1], $lg, $_[3] );
220 $self->{CRPOS} += $lg;
223 $self->{FH}->seek($old_pos, 0);
225 $self->{LG} = $self->{CRPOS} unless ($lg);
231 return undef if ($self->{CRPOS} >= $self->{LG});
234 my $old_pos = $self->{FH}->tell;
235 $self->{FH}->seek($self->{CRPOS}+$self->{START}, 0);
238 my $text = $self->{FH}->getline;
241 $self->{FH}->seek($old_pos, 0);
243 #### If we detected a new EOF ...
244 unless (defined $text) {
245 $self->{LG} = $self->{CRPOS};
249 my $lg=length($text);
251 $lg = $self->{LG} - $self->{CRPOS} if ($self->{CRPOS} + $lg > $self->{LG});
252 $self->{CRPOS} += $lg;
254 return substr($text, 0,$lg);
257 sub CLOSE { %{$_[0]}=(); }
269 $Id: InnerFile.pm,v 1.4 2005/02/10 21:21:53 dfs Exp $
274 Original version by Doru Petrescu (pdoru@kappa.ro).
276 Documentation and by Eryq (eryq@zeegee.com).
278 Currently maintained by David F. Skoll (dfs@roaringpenguin.com).