Cleaing up for production release
[archive-zip.git] / lib / Archive / Zip / MemberRead.pm
blobc274ea7a3908c5531e2990c0a43de48afcd0b0f1
1 package Archive::Zip::MemberRead;
3 =head1 NAME
5 Archive::Zip::MemberRead - A wrapper that lets you read Zip archive members as if they were files.
7 =cut
9 =head1 SYNOPSIS
11 use Archive::Zip;
12 use Archive::Zip::MemberRead;
13 $zip = Archive::Zip->new("file.zip");
14 $fh = Archive::Zip::MemberRead->new($zip, "subdir/abc.txt");
15 while (defined($line = $fh->getline()))
17 print $fh->input_line_number . "#: $line\n";
20 $read = $fh->read($buffer, 32*1024);
21 print "Read $read bytes as :$buffer:\n";
23 =head1 DESCRIPTION
25 The Archive::Zip::MemberRead module lets you read Zip archive member data
26 just like you read data from files.
28 =head1 METHODS
30 =over 4
32 =cut
34 use strict;
36 use Archive::Zip qw( :ERROR_CODES :CONSTANTS );
38 use vars qw{$VERSION};
40 my $nl;
42 BEGIN {
43 $VERSION = '1.28';
44 $VERSION = eval $VERSION;
45 # Requirement for newline conversion. Should check for e.g., DOS and OS/2 as well, but am too lazy.
46 $nl = $^O eq 'MSWin32' ? "\r\n" : "\n";
49 =item Archive::Zip::Member::readFileHandle()
51 You can get a C<Archive::Zip::MemberRead> from an archive member by
52 calling C<readFileHandle()>:
54 my $member = $zip->memberNamed('abc/def.c');
55 my $fh = $member->readFileHandle();
56 while (defined($line = $fh->getline()))
58 # ...
60 $fh->close();
62 =cut
64 sub Archive::Zip::Member::readFileHandle {
65 return Archive::Zip::MemberRead->new( shift() );
68 =item Archive::Zip::MemberRead->new($zip, $fileName)
70 =item Archive::Zip::MemberRead->new($zip, $member)
72 =item Archive::Zip::MemberRead->new($member)
74 Construct a new Archive::Zip::MemberRead on the specified member.
76 my $fh = Archive::Zip::MemberRead->new($zip, 'fred.c')
78 =cut
80 sub new {
81 my ( $class, $zip, $file ) = @_;
82 my ( $self, $member );
84 if ( $zip && $file ) # zip and filename, or zip and member
86 $member = ref($file) ? $file : $zip->memberNamed($file);
88 elsif ( $zip && !$file && ref($zip) ) # just member
90 $member = $zip;
92 else {
93 die(
94 'Archive::Zip::MemberRead::new needs a zip and filename, zip and member, or member'
98 $self = {};
99 bless( $self, $class );
100 $self->set_member($member);
101 return $self;
104 sub set_member {
105 my ( $self, $member ) = @_;
107 $self->{member} = $member;
108 $self->set_compression(COMPRESSION_STORED);
109 $self->rewind();
112 sub set_compression {
113 my ( $self, $compression ) = @_;
114 $self->{member}->desiredCompressionMethod($compression) if $self->{member};
117 =item setLineEnd(expr)
119 Set the line end character to use. This is set to \n by default
120 except on Windows systems where it is set to \r\n. You will
121 only need to set this on systems which are not Windows or Unix
122 based and require a line end diffrent from \n.
123 This is a class method so call as C<Archive::Zip::MemberRead>->C<setLineEnd($nl)>
125 =cut
127 sub setLineEnd {
128 shift;
129 $nl = shift;
132 =item rewind()
134 Rewinds an C<Archive::Zip::MemberRead> so that you can read from it again
135 starting at the beginning.
137 =cut
139 sub rewind {
140 my $self = shift;
142 $self->_reset_vars();
143 $self->{member}->rewindData() if $self->{member};
146 sub _reset_vars {
147 my $self = shift;
149 $self->{line_no} = 0;
150 $self->{at_end} = 0;
152 delete $self->{buffer};
155 =item input_record_separator(expr)
157 If the argumnet is given, input_record_separator for this
158 instance is set to it. The current setting (which may be
159 the global $/) is always returned.
161 =cut
163 sub input_record_separator {
164 my $self = shift;
165 if (@_) {
166 $self->{sep} = shift;
167 $self->{sep_re} = _sep_as_re($self->{sep}); # Cache the RE as an optimization
169 return exists $self->{sep} ? $self->{sep} : $/;
172 # Return the input_record_separator in use as an RE fragment
173 # Note that if we have a per-instance input_record_separator
174 # we can just return the already converted value. Otherwise,
175 # the conversion must be done on $/ every time since we cannot
176 # know whether it has changed or not.
177 sub _sep_re {
178 my $self = shift;
179 # Important to phrase this way: sep's value may be undef.
180 return exists $self->{sep} ? $self->{sep_re} : _sep_as_re($/);
183 # Convert the input record separator into an RE and return it.
184 sub _sep_as_re {
185 my $sep = shift;
186 if (defined $sep) {
187 if ($sep eq '') {
188 return "(?:$nl){2,}";
189 } else {
190 $sep =~ s/\n/$nl/og;
191 return quotemeta $sep;
193 } else {
194 return undef;
198 =item input_line_number()
200 Returns the current line number, but only if you're using C<getline()>.
201 Using C<read()> will not update the line number.
203 =cut
205 sub input_line_number {
206 my $self = shift;
207 return $self->{line_no};
210 =item close()
212 Closes the given file handle.
214 =cut
216 sub close {
217 my $self = shift;
219 $self->_reset_vars();
220 $self->{member}->endRead();
223 =item buffer_size([ $size ])
225 Gets or sets the buffer size used for reads.
226 Default is the chunk size used by Archive::Zip.
228 =cut
230 sub buffer_size {
231 my ( $self, $size ) = @_;
233 if ( !$size ) {
234 return $self->{chunkSize} || Archive::Zip::chunkSize();
236 else {
237 $self->{chunkSize} = $size;
241 =item getline()
243 Returns the next line from the currently open member.
244 Makes sense only for text files.
245 A read error is considered fatal enough to die.
246 Returns undef on eof. All subsequent calls would return undef,
247 unless a rewind() is called.
248 Note: The line returned has the input_record_separator (default: newline) removed.
250 =cut
252 sub getline {
253 my $self = shift;
254 my $size = $self->buffer_size();
255 my $sep = $self->_sep_re();
257 for (;;) {
258 if ( $sep
259 && defined($self->{buffer})
260 && $self->{buffer} =~ s/^(.*?)$sep//s
262 $self->{line_no}++;
263 return $1;
264 } elsif ($self->{at_end}) {
265 $self->{line_no}++ if $self->{buffer};
266 return delete $self->{buffer};
268 my ($temp,$status) = $self->{member}->readChunk($size);
269 if ($status != AZ_OK && $status != AZ_STREAM_END) {
270 die "ERROR: Error reading chunk from archive - $status";
272 $self->{at_end} = $status == AZ_STREAM_END;
273 $self->{buffer} .= $$temp;
277 =item read($buffer, $num_bytes_to_read)
279 Simulates a normal C<read()> system call.
280 Returns the no. of bytes read. C<undef> on error, 0 on eof, I<e.g.>:
282 $fh = Archive::Zip::MemberRead->new($zip, "sreeji/secrets.bin");
283 while (1)
285 $read = $fh->read($buffer, 1024);
286 die "FATAL ERROR reading my secrets !\n" if (!defined($read));
287 last if (!$read);
288 # Do processing.
289 ....
292 =cut
295 # All these $_ are required to emulate read().
297 sub read {
298 my $self = $_[0];
299 my $size = $_[2];
300 my ( $temp, $status, $ret );
302 ( $temp, $status ) = $self->{member}->readChunk($size);
303 if ( $status != AZ_OK && $status != AZ_STREAM_END ) {
304 $_[1] = undef;
305 $ret = undef;
307 else {
308 $_[1] = $$temp;
309 $ret = length($$temp);
311 return $ret;
316 =back
318 =head1 AUTHOR
320 Sreeji K. Das, <sreeji_k@yahoo.com>
321 See L<Archive::Zip> by Ned Konz without which this module does not make
322 any sense!
324 Minor mods by Ned Konz.
326 =head1 COPYRIGHT
328 Copyright 2002 Sreeji K. Das.
330 This program is free software; you can redistribute it and/or modify it under
331 the same terms as Perl itself.
333 =cut