File Coverage

blib/lib/IO/Uncompress/Base.pm
Criterion Covered Total %
statement 649 685 94.7
branch 291 360 80.8
condition 82 107 76.6
subroutine 71 73 97.2
pod 8 47 17.0
total 1101 1272 86.5


line stmt bran cond sub pod time code
1              
2             package IO::Uncompress::Base ;
3              
4 100     100   1039 use strict ;
  100         220  
  100         5340  
5 100     100   523 use warnings;
  100         193  
  100         4910  
6 100     100   567 use bytes;
  100         189  
  100         625  
7              
8             our (@ISA, $VERSION, @EXPORT_OK, %EXPORT_TAGS);
9             @ISA = qw(IO::File Exporter);
10              
11              
12             $VERSION = '2.219';
13              
14 100     100   10274 use constant G_EOF => 0 ;
  100         270  
  100         8537  
15 100     100   628 use constant G_ERR => -1 ;
  100         388  
  100         6970  
16              
17 100     100   634 use IO::Compress::Base::Common 2.219 ;
  100         2515  
  100         18940  
18              
19 100     100   24385 use IO::File ;
  100         230871  
  100         15898  
20 100     100   864 use Symbol;
  100         199  
  100         6654  
21 100     100   646 use Scalar::Util ();
  100         207  
  100         2545  
22 100     100   542 use List::Util ();
  100         186  
  100         2303  
23 100     100   554 use Carp ;
  100         310  
  100         49665  
24              
25             %EXPORT_TAGS = ( );
26             $EXPORT_TAGS{all} = [ defined $EXPORT_TAGS{all} ? @{ $EXPORT_TAGS{all} } : (), @EXPORT_OK ] ;
27              
28             sub smartRead
29             {
30 44642     44642 0 69703 my $self = $_[0];
31 44642         62705 my $out = $_[1];
32 44642         66648 my $size = $_[2];
33 44642         84745 $$out = "" ;
34              
35 44642         73916 my $offset = 0 ;
36 44642         61925 my $status = 1;
37              
38              
39 44642 100       104181 if (defined *$self->{InputLength}) {
40             return 0
41 441 100       1187 if *$self->{InputLengthRemaining} <= 0 ;
42 268         866 $size = List::Util::min($size, *$self->{InputLengthRemaining});
43             }
44              
45 44469 100       98176 if ( length *$self->{Prime} ) {
46 14182         30990 $$out = substr(*$self->{Prime}, 0, $size) ;
47 14182         26197 substr(*$self->{Prime}, 0, $size) = '' ;
48 14182 100       26633 if (length $$out == $size) {
49             *$self->{InputLengthRemaining} -= length $$out
50 11882 100       25347 if defined *$self->{InputLength};
51              
52 11882         31270 return length $$out ;
53             }
54 2300         4117 $offset = length $$out ;
55             }
56              
57 32587         62202 my $get_size = $size - $offset ;
58              
59 32587 100       79802 if (defined *$self->{FH}) {
    50          
60 16001 100       29490 if ($offset) {
61             # Not using this
62             #
63             # *$self->{FH}->read($$out, $get_size, $offset);
64             #
65             # because the filehandle may not support the offset parameter
66             # An example is Net::FTP
67 2300         3938 my $tmp = '';
68 2300         9711 $status = *$self->{FH}->read($tmp, $get_size) ;
69 2300 100 66     34788 substr($$out, $offset) = $tmp
70             if defined $status && $status > 0 ;
71             }
72             else
73 13701         52602 { $status = *$self->{FH}->read($$out, $get_size) }
74             }
75             elsif (defined *$self->{InputEvent}) {
76 0         0 my $got = 1 ;
77 0         0 while (length $$out < $size) {
78             last
79 0 0       0 if ($got = *$self->{InputEvent}->($$out, $get_size)) <= 0;
80             }
81              
82 0 0       0 if (length $$out > $size ) {
83 0         0 *$self->{Prime} = substr($$out, $size, length($$out));
84 0         0 substr($$out, $size, length($$out)) = '';
85             }
86              
87 0 0       0 *$self->{EventEof} = 1 if $got <= 0 ;
88             }
89             else {
90 100     100   817 no warnings 'uninitialized';
  100         205  
  100         268418  
91 16586         30977 my $buf = *$self->{Buffer} ;
92 16586 50       32491 $$buf = '' unless defined $$buf ;
93 16586         49140 substr($$out, $offset) = substr($$buf, *$self->{BufferOffset}, $get_size);
94 16586 50       32523 if (*$self->{ConsumeInput})
95 0         0 { substr($$buf, 0, $get_size) = '' }
96             else
97 16586         32696 { *$self->{BufferOffset} += length($$out) - $offset }
98             }
99              
100             *$self->{InputLengthRemaining} -= length($$out) #- $offset
101 32587 100       239697 if defined *$self->{InputLength};
102              
103 32587 50       65011 if (! defined $status) {
104 0         0 $self->saveStatus($!) ;
105 0         0 return STATUS_ERROR;
106             }
107              
108 32587 50       115949 $self->saveStatus(length $$out < 0 ? STATUS_ERROR : STATUS_OK) ;
109              
110 32587         83899 return length $$out;
111             }
112              
113             sub pushBack
114             {
115 11619     11619 0 20286 my $self = shift ;
116              
117 11619 100 66     54422 return if ! defined $_[0] || length $_[0] == 0 ;
118              
119 8341 100 66     31965 if (defined *$self->{FH} || defined *$self->{InputEvent} ) {
120 4530         13745 *$self->{Prime} = $_[0] . *$self->{Prime} ;
121 4530         11493 *$self->{InputLengthRemaining} += length($_[0]);
122             }
123             else {
124 3811         6823 my $len = length $_[0];
125              
126 3811 50       8920 if($len > *$self->{BufferOffset}) {
127 0         0 *$self->{Prime} = substr($_[0], 0, $len - *$self->{BufferOffset}) . *$self->{Prime} ;
128 0         0 *$self->{InputLengthRemaining} = *$self->{InputLength};
129 0         0 *$self->{BufferOffset} = 0
130             }
131             else {
132 3811         10245 *$self->{InputLengthRemaining} += length($_[0]);
133 3811         8887 *$self->{BufferOffset} -= length($_[0]) ;
134             }
135             }
136             }
137              
138             sub smartSeek
139             {
140 120     120 0 177 my $self = shift ;
141 120         168 my $offset = shift ;
142 120         180 my $truncate = shift;
143 120   50     363 my $position = shift || SEEK_SET;
144              
145             # TODO -- need to take prime into account
146 120         257 *$self->{Prime} = '';
147 120 100       320 if (defined *$self->{FH})
148 72         291 { *$self->{FH}->seek($offset, $position) }
149             else {
150 48 50       133 if ($position == SEEK_END) {
    50          
151 0         0 *$self->{BufferOffset} = length(${ *$self->{Buffer} }) + $offset ;
  0         0  
152             }
153             elsif ($position == SEEK_CUR) {
154 0         0 *$self->{BufferOffset} += $offset ;
155             }
156             else {
157 48         82 *$self->{BufferOffset} = $offset ;
158             }
159              
160 48 50       99 substr(${ *$self->{Buffer} }, *$self->{BufferOffset}) = ''
  0         0  
161             if $truncate;
162 48         258 return 1;
163             }
164             }
165              
166             sub smartTell
167             {
168 0     0 0 0 my $self = shift ;
169              
170 0 0       0 if (defined *$self->{FH})
171 0         0 { return *$self->{FH}->tell() }
172             else
173 0         0 { return *$self->{BufferOffset} }
174             }
175              
176             sub smartWrite
177             {
178 60     60 0 535 my $self = shift ;
179 60         115 my $out_data = shift ;
180              
181 60 100       157 if (defined *$self->{FH}) {
182             # flush needed for 5.8.0
183             defined *$self->{FH}->write($out_data, length $out_data) &&
184 36 50       152 defined *$self->{FH}->flush() ;
185             }
186             else {
187 24         47 my $buf = *$self->{Buffer} ;
188 24         77 substr($$buf, *$self->{BufferOffset}, length $out_data) = $out_data ;
189 24         51 *$self->{BufferOffset} += length($out_data) ;
190 24         91 return 1;
191             }
192             }
193              
194             sub smartReadExact
195             {
196 23604     23604 0 58945 return $_[0]->smartRead($_[1], $_[2]) == $_[2];
197             }
198              
199             sub smartEof
200             {
201 14961     14961 0 33003 my ($self) = $_[0];
202 14961         57809 local $.;
203              
204 14961 100 66     73797 return 0 if length *$self->{Prime} || *$self->{PushMode};
205              
206 13483 100       41411 if (defined *$self->{FH})
    50          
207             {
208             # Could use
209             #
210             # *$self->{FH}->eof()
211             #
212             # here, but this can cause trouble if
213             # the filehandle is itself a tied handle, but it uses sysread.
214             # Then we get into mixing buffered & non-buffered IO,
215             # which will cause trouble
216              
217 7375         22827 my $info = $self->getErrInfo();
218              
219 7375         12820 my $buffer = '';
220 7375         17796 my $status = $self->smartRead(\$buffer, 1);
221 7375 100       17052 $self->pushBack($buffer) if length $buffer;
222 7375         24751 $self->setErrInfo($info);
223              
224 7375         56870 return $status == 0 ;
225             }
226             elsif (defined *$self->{InputEvent})
227 0         0 { *$self->{EventEof} }
228             else
229 6108         10705 { *$self->{BufferOffset} >= length(${ *$self->{Buffer} }) }
  6108         38150  
230             }
231              
232             sub clearError
233             {
234 273     273 0 541 my $self = shift ;
235              
236 273         610 *$self->{ErrorNo} = 0 ;
237 273         486 ${ *$self->{Error} } = '' ;
  273         693  
238             }
239              
240             sub getErrInfo
241             {
242 7375     7375 0 12076 my $self = shift ;
243              
244 7375         13966 return [ *$self->{ErrorNo}, ${ *$self->{Error} } ] ;
  7375         24723  
245             }
246              
247             sub setErrInfo
248             {
249 7375     7375 0 10773 my $self = shift ;
250 7375         10951 my $ref = shift;
251              
252 7375         15691 *$self->{ErrorNo} = $ref->[0] ;
253 7375         15217 ${ *$self->{Error} } = $ref->[1] ;
  7375         15963  
254             }
255              
256             sub saveStatus
257             {
258 43857     43857 0 66797 my $self = shift ;
259 43857         74313 my $errno = shift() + 0 ;
260              
261 43857         80920 *$self->{ErrorNo} = $errno;
262 43857         78618 ${ *$self->{Error} } = '' ;
  43857         103036  
263              
264 43857         94121 return *$self->{ErrorNo} ;
265             }
266              
267              
268             sub saveErrorString
269             {
270 3415     3415 0 6993 my $self = shift ;
271 3415         5908 my $retval = shift ;
272              
273 3415         5366 ${ *$self->{Error} } = shift ;
  3415         7557  
274 3415 100       9648 *$self->{ErrorNo} = @_ ? shift() + 0 : STATUS_ERROR ;
275              
276 3415         12931 return $retval;
277             }
278              
279             sub croakError
280             {
281 95     95 0 281 my $self = shift ;
282 95         559 $self->saveErrorString(0, $_[0]);
283 95         23001 croak $_[0];
284             }
285              
286              
287             sub closeError
288             {
289 18     18 0 37 my $self = shift ;
290 18         35 my $retval = shift ;
291              
292 18         44 my $errno = *$self->{ErrorNo};
293 18         30 my $error = ${ *$self->{Error} };
  18         67  
294              
295 18         117 $self->close();
296              
297 18         39 *$self->{ErrorNo} = $errno ;
298 18         42 ${ *$self->{Error} } = $error ;
  18         40  
299              
300 18         196 return $retval;
301             }
302              
303             sub error
304             {
305 2109     2109 1 297956 my $self = shift ;
306 2109         3711 return ${ *$self->{Error} } ;
  2109         10007  
307             }
308              
309             sub errorNo
310             {
311 210     210 0 368 my $self = shift ;
312 210         1000 return *$self->{ErrorNo};
313             }
314              
315             sub HeaderError
316             {
317 2058     2058 0 4940 my ($self) = shift;
318 2058         10888 return $self->saveErrorString(undef, "Header Error: $_[0]", STATUS_ERROR);
319             }
320              
321             sub TrailerError
322             {
323 18     18 0 45 my ($self) = shift;
324 18         5523 return $self->saveErrorString(G_ERR, "Trailer Error: $_[0]", STATUS_ERROR);
325             }
326              
327             sub TruncatedHeader
328             {
329 16     16 0 22 my ($self) = shift;
330 16         39 return $self->HeaderError("Truncated in $_[0] Section");
331             }
332              
333             sub TruncatedTrailer
334             {
335 0     0 0 0 my ($self) = shift;
336 0         0 return $self->TrailerError("Truncated in $_[0] Section");
337             }
338              
339             sub postCheckParams
340             {
341 3520     3520 0 10452 return 1;
342             }
343              
344             sub checkParams
345             {
346 3552     3552 0 7150 my $self = shift ;
347 3552         6448 my $class = shift ;
348              
349 3552   33     20925 my $got = shift || IO::Compress::Base::Parameters::new();
350              
351 3552         38544 my $Valid = {
352             'blocksize' => [IO::Compress::Base::Common::Parse_unsigned, 16 * 1024],
353             'autoclose' => [IO::Compress::Base::Common::Parse_boolean, 0],
354             'strict' => [IO::Compress::Base::Common::Parse_boolean, 0],
355             'append' => [IO::Compress::Base::Common::Parse_boolean, 0],
356             'prime' => [IO::Compress::Base::Common::Parse_any, undef],
357             'multistream' => [IO::Compress::Base::Common::Parse_boolean, 0],
358             'transparent' => [IO::Compress::Base::Common::Parse_any, 1],
359             'scan' => [IO::Compress::Base::Common::Parse_boolean, 0],
360             'inputlength' => [IO::Compress::Base::Common::Parse_unsigned, undef],
361             'binmodeout' => [IO::Compress::Base::Common::Parse_boolean, 0],
362             #'decode' => [IO::Compress::Base::Common::Parse_any, undef],
363              
364             #'consumeinput' => [IO::Compress::Base::Common::Parse_boolean, 0],
365              
366             $self->getExtraParams(),
367              
368             #'Todo - Revert to ordinary file on end Z_STREAM_END'=> 0,
369             # ContinueAfterEof
370             } ;
371              
372             $Valid->{trailingdata} = [IO::Compress::Base::Common::Parse_writable_scalar, undef]
373 3552 100       16349 if *$self->{OneShot} ;
374              
375 3552 100       16818 $got->parse($Valid, @_ )
376             or $self->croakError("${class}: " . $got->getError()) ;
377              
378 3520 50       14529 $self->postCheckParams($got)
379             or $self->croakError("${class}: " . $self->error()) ;
380              
381 3520         50720 return $got;
382             }
383              
384             sub _create
385             {
386 3667     3667   7626 my $obj = shift;
387 3667         6536 my $got = shift;
388 3667         6435 my $append_mode = shift ;
389              
390 3667         11958 my $class = ref $obj;
391 3667 50 66     12351 $obj->croakError("$class: Missing Input parameter")
392             if ! @_ && ! $got ;
393              
394 3662         6982 my $inValue = shift ;
395              
396 3662         12107 *$obj->{OneShot} = 0 ;
397              
398 3662 100       12484 if (! $got)
399             {
400 2984 50       11630 $got = $obj->checkParams($class, undef, @_)
401             or return undef ;
402             }
403              
404 3650         13273 my $inType = whatIsInput($inValue, 1);
405              
406 3650 50       14392 $obj->ckInputParam($class, $inValue, 1)
407             or return undef ;
408              
409 3645         11155 *$obj->{InNew} = 1;
410              
411             $obj->ckParams($got)
412 3645 50       33523 or $obj->croakError("${class}: " . *$obj->{Error});
413              
414 3645 100 66     20297 if ($inType eq 'buffer' || $inType eq 'code') {
415 1450         5516 *$obj->{Buffer} = $inValue ;
416 1450 50       4333 *$obj->{InputEvent} = $inValue
417             if $inType eq 'code' ;
418             }
419             else {
420 2195 100       6264 if ($inType eq 'handle') {
421 471         1872 *$obj->{FH} = $inValue ;
422 471         1549 *$obj->{Handle} = 1 ;
423              
424             # Need to rewind for Scan
425 471 100       2013 *$obj->{FH}->seek(0, SEEK_SET)
426             if $got->getValue('scan');
427             }
428             else {
429 100     100   3508 no warnings ;
  100         294  
  100         678202  
430 1724         6620 my $mode = '<';
431 1724 100       5650 $mode = '+<' if $got->getValue('scan');
432 1724         7391 *$obj->{StdIO} = ($inValue eq '-');
433 1724 100       14091 *$obj->{FH} = IO::File->new( "$mode $inValue" )
434             or return $obj->saveErrorString(undef, "cannot open file '$inValue': $!", $!) ;
435             }
436              
437 2190         197628 *$obj->{LineNo} = $. = 0;
438 2190         11708 setBinModeInput(*$obj->{FH}) ;
439              
440 2190         4655 my $buff = "" ;
441 2190         7093 *$obj->{Buffer} = \$buff ;
442             }
443              
444             # if ($got->getValue('decode')) {
445             # my $want_encoding = $got->getValue('decode');
446             # *$obj->{Encoding} = IO::Compress::Base::Common::getEncoding($obj, $class, $want_encoding);
447             # }
448             # else {
449             # *$obj->{Encoding} = undef;
450             # }
451              
452 3640 100       12532 *$obj->{InputLength} = $got->parsed('inputlength')
453             ? $got->getValue('inputlength')
454             : undef ;
455 3640         10069 *$obj->{InputLengthRemaining} = $got->getValue('inputlength');
456 3640         34332 *$obj->{BufferOffset} = 0 ;
457 3640         9767 *$obj->{AutoClose} = $got->getValue('autoclose');
458 3640         9626 *$obj->{Strict} = $got->getValue('strict');
459 3640         11545 *$obj->{BlockSize} = $got->getValue('blocksize');
460 3640         9573 *$obj->{Append} = $got->getValue('append');
461 3640   100     14941 *$obj->{AppendOutput} = $append_mode || $got->getValue('append');
462 3640         10143 *$obj->{ConsumeInput} = $got->getValue('consumeinput');
463 3640         9488 *$obj->{Transparent} = $got->getValue('transparent');
464 3640         9278 *$obj->{MultiStream} = $got->getValue('multistream');
465              
466             # TODO - move these two into RawDeflate
467 3640         9148 *$obj->{Scan} = $got->getValue('scan');
468 3640   100     9086 *$obj->{ParseExtra} = $got->getValue('parseextra')
469             || $got->getValue('strict') ;
470 3640         11604 *$obj->{Type} = '';
471 3640   50     9146 *$obj->{Prime} = $got->getValue('prime') || '' ;
472 3640         13213 *$obj->{Pending} = '';
473 3640         9127 *$obj->{Plain} = 0;
474 3640         8857 *$obj->{PlainBytesRead} = 0;
475 3640         8560 *$obj->{InflatedBytesRead} = 0;
476 3640         27228 *$obj->{UnCompSize} = U64->new;
477 3640         10622 *$obj->{CompSize} = U64->new;
478 3640         8200 *$obj->{TotalInflatedBytesRead} = 0;
479 3640         9399 *$obj->{NewStream} = 0 ;
480 3640         13517 *$obj->{EventEof} = 0 ;
481 3640         13600 *$obj->{ClassName} = $class ;
482 3640         9121 *$obj->{Params} = $got ;
483              
484 3640 50       11013 if (*$obj->{ConsumeInput}) {
485 0         0 *$obj->{InNew} = 0;
486 0         0 *$obj->{Closed} = 0;
487 0         0 return $obj
488             }
489              
490 3640         16272 my $status = $obj->mkUncomp($got);
491              
492             return undef
493 3639 100       18169 unless defined $status;
494              
495 3612         9337 *$obj->{InNew} = 0;
496 3612         7801 *$obj->{Closed} = 0;
497              
498             return $obj
499 3612 50       10433 if *$obj->{Pause} ;
500              
501 3612 100       8275 if ($status) {
502             # Need to try uncompressing to catch the case
503             # where the compressed file uncompresses to an
504             # empty string - so eof is set immediately.
505              
506 3311         6712 my $out_buffer = '';
507              
508 3311         14271 $status = $obj->read(\$out_buffer);
509              
510 3311 100       9262 if ($status < 0) {
511 6         47 *$obj->{ReadStatus} = [ $status, $obj->error(), $obj->errorNo() ];
512             }
513              
514 3311 100       15011 $obj->ungetc($out_buffer)
515             if length $out_buffer;
516             }
517             else {
518             return undef
519 301 100       1118 unless *$obj->{Transparent};
520              
521 270         2160 $obj->clearError();
522 270         684 *$obj->{Type} = 'plain';
523 270         559 *$obj->{Plain} = 1;
524 270         905 $obj->pushBack(*$obj->{HeaderPending}) ;
525             }
526              
527 3581         6495 push @{ *$obj->{InfoList} }, *$obj->{Info} ;
  3581         16263  
528              
529 3581         11530 $obj->saveStatus(STATUS_OK) ;
530 3581         8222 *$obj->{InNew} = 0;
531 3581         7643 *$obj->{Closed} = 0;
532              
533 3581         22339 return $obj;
534             }
535              
536             sub ckInputParam
537             {
538 3650     3650 0 10839 my $self = shift ;
539 3650         6862 my $from = shift ;
540 3650         11007 my $inType = whatIsInput($_[0], $_[1]);
541              
542 3650 100       13506 $self->croakError("$from: input parameter not a filename, filehandle, array ref or scalar ref")
543             if ! $inType ;
544              
545             # if ($inType eq 'filename' )
546             # {
547             # return $self->saveErrorString(1, "$from: input filename is undef or null string", STATUS_ERROR)
548             # if ! defined $_[0] || $_[0] eq '' ;
549             #
550             # if ($_[0] ne '-' && ! -e $_[0] )
551             # {
552             # return $self->saveErrorString(1,
553             # "input file '$_[0]' does not exist", STATUS_ERROR);
554             # }
555             # }
556              
557 3645         11580 return 1;
558             }
559              
560              
561             sub _inf
562             {
563 728     728   1517 my $obj = shift ;
564              
565 728         2910 my $class = (caller)[0] ;
566 728         4599 my $name = (caller(1))[3] ;
567              
568 728 100       2932 $obj->croakError("$name: expected at least 1 parameters\n")
569             unless @_ >= 1 ;
570              
571 718         1490 my $input = shift ;
572 718         1451 my $haveOut = @_ ;
573 718         1406 my $output = shift ;
574              
575              
576 718 100       19758 my $x = IO::Compress::Base::Validator->new($class, *$obj->{Error}, $name, $input, $output)
577             or return undef ;
578              
579 568 50 33     3285 push @_, $output if $haveOut && $x->{Hash};
580              
581 568         1896 *$obj->{OneShot} = 1 ;
582              
583 568 50       2880 my $got = $obj->checkParams($name, undef, @_)
584             or return undef ;
585              
586 548 100       2736 if ($got->parsed('trailingdata'))
587             {
588             # my $value = $got->valueRef('TrailingData');
589             # warn "TD $value ";
590             # #$value = $$value;
591             ## warn "TD $value $$value ";
592             #
593             # return retErr($obj, "Parameter 'TrailingData' not writable")
594             # if readonly $$value ;
595             #
596             # if (ref $$value)
597             # {
598             # return retErr($obj,"Parameter 'TrailingData' not a scalar reference")
599             # if ref $$value ne 'SCALAR' ;
600             #
601             # *$obj->{TrailingData} = $$value ;
602             # }
603             # else
604             # {
605             # return retErr($obj,"Parameter 'TrailingData' not a scalar")
606             # if ref $value ne 'SCALAR' ;
607             #
608             # *$obj->{TrailingData} = $value ;
609             # }
610              
611 10         35 *$obj->{TrailingData} = $got->getValue('trailingdata');
612             }
613              
614 548         1915 *$obj->{MultiStream} = $got->getValue('multistream');
615 548         2349 $got->setValue('multistream', 0);
616              
617 548         1797 $x->{Got} = $got ;
618              
619             # if ($x->{Hash})
620             # {
621             # while (my($k, $v) = each %$input)
622             # {
623             # $v = \$input->{$k}
624             # unless defined $v ;
625             #
626             # $obj->_singleTarget($x, $k, $v, @_)
627             # or return undef ;
628             # }
629             #
630             # return keys %$input ;
631             # }
632              
633 548 100       1835 if ($x->{GlobMap})
634             {
635 10         35 $x->{oneInput} = 1 ;
636 10         25 foreach my $pair (@{ $x->{Pairs} })
  10         33  
637             {
638 30         96 my ($from, $to) = @$pair ;
639 30 50       137 $obj->_singleTarget($x, $from, $to, @_)
640             or return undef ;
641             }
642              
643 10         31 return scalar @{ $x->{Pairs} } ;
  10         291  
644             }
645              
646 538 100       1786 if (! $x->{oneOutput} )
647             {
648             my $inFile = ($x->{inType} eq 'filenames'
649 40   66     247 || $x->{inType} eq 'filename');
650              
651 40 100       383 $x->{inType} = $inFile ? 'filename' : 'buffer';
652              
653 40 100       168 foreach my $in ($x->{oneInput} ? $input : @$input)
654             {
655 70         126 my $out ;
656 70         172 $x->{oneInput} = 1 ;
657              
658 70 50       277 $obj->_singleTarget($x, $in, $output, @_)
659             or return undef ;
660             }
661              
662 40         714 return 1 ;
663             }
664              
665             # finally the 1 to 1 and n to 1
666 498         2354 return $obj->_singleTarget($x, $input, $output, @_);
667              
668 0         0 croak "should not be here" ;
669             }
670              
671             sub retErr
672             {
673 10     10 0 1069 my $x = shift ;
674 10         212 my $string = shift ;
675              
676 10         26 ${ $x->{Error} } = $string ;
  10         33  
677              
678 10         167 return undef ;
679             }
680              
681             sub _singleTarget
682             {
683 598     598   1145 my $self = shift ;
684 598         6418 my $x = shift ;
685 598         1175 my $input = shift;
686 598         2632 my $output = shift;
687              
688 598         4316 my $buff = '';
689 598         1890 $x->{buff} = \$buff ;
690              
691 598         1265 my $fh ;
692 598 100       3589 if ($x->{outType} eq 'filename') {
    100          
    100          
693 130         294 my $mode = '>' ;
694             $mode = '>>'
695 130 100       503 if $x->{Got}->getValue('append') ;
696 130 100       1684 $x->{fh} = IO::File->new( "$mode $output" )
697             or return retErr($x, "cannot open file '$output': $!") ;
698 120         26442 binmode $x->{fh} ;
699              
700             }
701              
702             elsif ($x->{outType} eq 'handle') {
703 85         275 $x->{fh} = $output;
704 85         391 binmode $x->{fh} ;
705 85 100       314 if ($x->{Got}->getValue('append')) {
706 30 50       434 seek($x->{fh}, 0, SEEK_END)
707             or return retErr($x, "Cannot seek to end of output filehandle: $!") ;
708             }
709             }
710              
711              
712             elsif ($x->{outType} eq 'buffer' )
713             {
714             $$output = ''
715 313 100       1107 unless $x->{Got}->getValue('append');
716 313         841 $x->{buff} = $output ;
717             }
718              
719 588 100       1738 if ($x->{oneInput})
720             {
721 528 100       2282 defined $self->_rd2($x, $input, $output)
722             or return undef;
723             }
724             else
725             {
726 60 50       306 for my $element ( ($x->{inType} eq 'hash') ? keys %$input : @$input)
727             {
728 150 50       663 defined $self->_rd2($x, $element, $output)
729             or return undef ;
730             }
731             }
732              
733              
734 556 100 66     13860 if ( ($x->{outType} eq 'filename' && $output ne '-') ||
      100        
      100        
735             ($x->{outType} eq 'handle' && $x->{Got}->getValue('autoclose'))) {
736             $x->{fh}->close()
737 190 50       959 or return retErr($x, $!);
738 190         21452 delete $x->{fh};
739             }
740              
741 556         11297 return 1 ;
742             }
743              
744             sub _rd2
745             {
746 678     678   1317 my $self = shift ;
747 678         1296 my $x = shift ;
748 678         1239 my $input = shift;
749 678         1337 my $output = shift;
750              
751 678         3008 my $z = IO::Compress::Base::Common::createSelfTiedObject($x->{Class}, *$self->{Error});
752              
753 678 100       2960 $z->_create($x->{Got}, 1, $input, @_)
754             or return undef ;
755              
756 664         1267 my $status ;
757 664         4739 my $fh = $x->{fh};
758              
759 664         1081 while (1) {
760              
761 682         2052 while (($status = $z->read($x->{buff})) > 0) {
762 728 100       5698 if ($fh) {
763 265         2236 local $\;
764 265 50       562 print $fh ${ $x->{buff} }
  265         1587  
765             or return $z->saveErrorString(undef, "Error writing to output file: $!", $!);
766 265         558 ${ $x->{buff} } = '' ;
  265         1120  
767             }
768             }
769              
770 682 100       2092 if (! $x->{oneOutput} ) {
771 100         257 my $ot = $x->{outType} ;
772              
773 100 100       326 if ($ot eq 'array')
    50          
774 70         5082 { push @$output, $x->{buff} }
775             elsif ($ot eq 'hash')
776 0         0 { $output->{$input} = $x->{buff} }
777              
778 100         487 my $buff = '';
779 100         241 $x->{buff} = \$buff;
780             }
781              
782 682 100 100     4308 last if $status < 0 || $z->smartEof();
783              
784             last
785 56 100       228 unless *$self->{MultiStream};
786              
787 18         146 $status = $z->nextStream();
788              
789             last
790 18 50       70 unless $status == 1 ;
791             }
792              
793 664 100       1900 return $z->closeError(undef)
794             if $status < 0 ;
795              
796 10         32 ${ *$self->{TrailingData} } = $z->trailingData()
797 646 100       2113 if defined *$self->{TrailingData} ;
798              
799 646 50       2788 $z->close()
800             or return undef ;
801              
802 646         2634 return 1 ;
803             }
804              
805             sub TIEHANDLE
806             {
807 4395 50   4395   25888 return $_[0] if ref($_[0]);
808 0         0 die "OOPS\n" ;
809              
810             }
811              
812             sub UNTIE
813             {
814 3600     3600   11995 my $self = shift ;
815             }
816              
817              
818             sub getHeaderInfo
819             {
820 239     239 0 8381 my $self = shift ;
821 239 100       943 wantarray ? @{ *$self->{InfoList} } : *$self->{Info};
  90         603  
822             }
823              
824             sub readBlock
825             {
826 4847     4847 0 8089 my $self = shift ;
827 4847         7452 my $buff = shift ;
828 4847         7721 my $size = shift ;
829              
830 4847 100       13465 if (defined *$self->{CompressedInputLength}) {
831 103 100       344 if (*$self->{CompressedInputLengthRemaining} == 0) {
832 22         89 delete *$self->{CompressedInputLength};
833 22         93 *$self->{CompressedInputLengthDone} = 1;
834 22         55 return STATUS_OK ;
835             }
836 81         349 $size = List::Util::min($size, *$self->{CompressedInputLengthRemaining} );
837 81         174 *$self->{CompressedInputLengthRemaining} -= $size ;
838             }
839              
840 4825         13569 my $status = $self->smartRead($buff, $size) ;
841 4825 50       12258 return $self->saveErrorString(STATUS_ERROR, "Error Reading Data: $!", $!)
842             if $status == STATUS_ERROR ;
843              
844 4825 100       10919 if ($status == 0 ) {
845 12         33 *$self->{Closed} = 1 ;
846 12         27 *$self->{EndStream} = 1 ;
847 12         55 return $self->saveErrorString(STATUS_ERROR, "unexpected end of file", STATUS_ERROR);
848             }
849              
850 4813         9293 return STATUS_OK;
851             }
852              
853             sub postBlockChk
854             {
855 4831     4831 0 12188 return STATUS_OK;
856             }
857              
858             sub _raw_read
859             {
860             # return codes
861             # >0 - ok, number of bytes read
862             # =0 - ok, eof
863             # <0 - not ok
864              
865 6564     6564   11053 my $self = shift ;
866              
867 6564 50       21680 return G_EOF if *$self->{Closed} ;
868 6564 50       15664 return G_EOF if *$self->{EndStream} ;
869              
870 6564         10690 my $buffer = shift ;
871 6564         11254 my $scan_mode = shift ;
872              
873 6564 100       21551 if (*$self->{Plain}) {
874 541         906 my $tmp_buff ;
875 541         2191 my $len = $self->smartRead(\$tmp_buff, *$self->{BlockSize}) ;
876              
877 541 50       1452 return $self->saveErrorString(G_ERR, "Error reading data: $!", $!)
878             if $len == STATUS_ERROR ;
879              
880 541 100       2024 if ($len == 0 ) {
881 260         677 *$self->{EndStream} = 1 ;
882             }
883             else {
884 281         600 *$self->{PlainBytesRead} += $len ;
885 281         1763 $$buffer .= $tmp_buff;
886             }
887              
888 541         1645 return $len ;
889             }
890              
891 6023 100       15050 if (*$self->{NewStream}) {
892              
893 1176 50       4895 $self->gotoNextStream() > 0
894             or return G_ERR;
895              
896             # For the headers that actually uncompressed data, put the
897             # uncompressed data into the output buffer.
898 1176         3529 $$buffer .= *$self->{Pending} ;
899 1176         2754 my $len = length *$self->{Pending} ;
900 1176         2255 *$self->{Pending} = '';
901 1176         5089 return $len;
902             }
903              
904 4847         9645 my $temp_buf = '';
905 4847         7824 my $outSize = 0;
906 4847         25368 my $status = $self->readBlock(\$temp_buf, *$self->{BlockSize}, $outSize) ;
907              
908 4847 100       12477 return G_ERR
909             if $status == STATUS_ERROR ;
910              
911 4835         7943 my $buf_len = 0;
912 4835 50       13848 if ($status == STATUS_OK) {
913 4835         8009 my $beforeC_len = length $temp_buf;
914 4835 50       12519 my $before_len = defined $$buffer ? length $$buffer : 0 ;
915             $status = *$self->{Uncomp}->uncompr(\$temp_buf, $buffer,
916             defined *$self->{CompressedInputLengthDone} ||
917 4835   100     23968 $self->smartEof(), $outSize);
918              
919             # Remember the input buffer if it wasn't consumed completely
920 4835 50       41636 $self->pushBack($temp_buf) if *$self->{Uncomp}{ConsumesInput};
921              
922             return $self->saveErrorString(G_ERR, *$self->{Uncomp}{Error}, *$self->{Uncomp}{ErrorNo})
923 4835 100       11618 if $self->saveStatus($status) == STATUS_ERROR;
924              
925 4831 50       13230 $self->postBlockChk($buffer, $before_len) == STATUS_OK
926             or return G_ERR;
927              
928 4831 50       12686 $buf_len = defined $$buffer ? length($$buffer) - $before_len : 0;
929              
930 4831         26627 *$self->{CompSize}->add($beforeC_len - length $temp_buf) ;
931              
932 4831         9655 *$self->{InflatedBytesRead} += $buf_len ;
933 4831         9207 *$self->{TotalInflatedBytesRead} += $buf_len ;
934 4831         18859 *$self->{UnCompSize}->add($buf_len) ;
935              
936 4831         14770 $self->filterUncompressed($buffer, $before_len);
937              
938             # if (*$self->{Encoding}) {
939             # use Encode ;
940             # *$self->{PendingDecode} .= substr($$buffer, $before_len) ;
941             # my $got = *$self->{Encoding}->decode(*$self->{PendingDecode}, Encode::FB_QUIET) ;
942             # substr($$buffer, $before_len) = $got;
943             # }
944             }
945              
946 4831 100       13387 if ($status == STATUS_ENDSTREAM) {
947              
948 3986         11118 *$self->{EndStream} = 1 ;
949              
950 3986         6330 my $trailer;
951 3986         8435 my $trailer_size = *$self->{Info}{TrailerLength} ;
952 3986         6532 my $got = 0;
953 3986 100       10208 if (*$self->{Info}{TrailerLength})
954             {
955 2836         7443 $got = $self->smartRead(\$trailer, $trailer_size) ;
956             }
957              
958 3986 100       8973 if ($got == $trailer_size) {
959 3942 100       13708 $self->chkTrailer($trailer) == STATUS_OK
960             or return G_ERR;
961             }
962             else {
963             return $self->TrailerError("trailer truncated. Expected " .
964             "$trailer_size bytes, got $got")
965 44 100       212 if *$self->{Strict};
966 32         97 $self->pushBack($trailer) ;
967             }
968              
969             # TODO - if want file pointer, do it here
970              
971 3968 100       12106 if (! $self->smartEof()) {
972 1378         4707 *$self->{NewStream} = 1 ;
973              
974 1378 100       4955 if (*$self->{MultiStream}) {
975 942         2447 *$self->{EndStream} = 0 ;
976 942         5029 return $buf_len ;
977             }
978             }
979              
980             }
981              
982              
983             # return the number of uncompressed bytes read
984 3871         15554 return $buf_len ;
985             }
986              
987             sub reset
988             {
989 1773     1773 0 2765 my $self = shift ;
990              
991 1773         7339 return *$self->{Uncomp}->reset();
992             }
993              
994             sub filterUncompressed
995       3609 0   {
996             }
997              
998             #sub isEndStream
999             #{
1000             # my $self = shift ;
1001             # return *$self->{NewStream} ||
1002             # *$self->{EndStream} ;
1003             #}
1004              
1005             sub nextStream
1006             {
1007 598     598 0 58212 my $self = shift ;
1008              
1009             # An uncompressed file cannot have a next stream, so
1010             # return immediately.
1011             return 0
1012 598 100       2331 if *$self->{Plain} ;
1013              
1014 597         1911 my $status = $self->gotoNextStream();
1015 597 100       2253 $status == 1
1016             or return $status ;
1017              
1018             *$self->{Pending} = ''
1019 406 50 66     6373 if $self !~ /IO::Uncompress::RawInflate/ && ! *$self->{MultiStream};
1020              
1021 406         994 *$self->{TotalInflatedBytesRead} = 0 ;
1022 406         1445 *$self->{LineNo} = $. = 0;
1023              
1024 406         2159 return 1;
1025             }
1026              
1027             sub gotoNextStream
1028             {
1029 1773     1773 0 6993 my $self = shift ;
1030              
1031 1773 100       4762 if (! *$self->{NewStream}) {
1032 271         522 my $status = 1;
1033 271         475 my $buffer ;
1034              
1035             # TODO - make this more efficient if know the offset for the end of
1036             # the stream and seekable
1037 271         1264 $status = $self->read($buffer)
1038             while $status > 0 ;
1039              
1040 271 50       895 return $status
1041             if $status < 0;
1042             }
1043              
1044 1773         4952 *$self->{NewStream} = 0 ;
1045 1773         3386 *$self->{EndStream} = 0 ;
1046 1773         4582 *$self->{CompressedInputLengthDone} = undef ;
1047 1773         4206 *$self->{CompressedInputLength} = undef ;
1048 1773         5631 $self->reset();
1049 1773         12506 *$self->{UnCompSize}->reset();
1050 1773         5338 *$self->{CompSize}->reset();
1051              
1052 1773         5726 my $magic = $self->ckMagic();
1053              
1054 1773 100       4638 if ( ! defined $magic) {
1055 194 100 100     983 if (! *$self->{Transparent} || $self->eof())
1056             {
1057 191         473 *$self->{EndStream} = 1 ;
1058 191         490 return 0;
1059             }
1060              
1061             # Not EOF, so Transparent mode kicks in now for trailing data
1062             # Reset member name in case anyone calls getHeaderInfo()->{Name}
1063 3         17 *$self->{Info} = { Name => undef, Type => 'plain' };
1064              
1065 3         15 $self->clearError();
1066 3         8 *$self->{Type} = 'plain';
1067 3         7 *$self->{Plain} = 1;
1068 3         12 $self->pushBack(*$self->{HeaderPending}) ;
1069             }
1070             else
1071             {
1072 1579         4374 *$self->{Info} = $self->readHeader($magic);
1073              
1074 1579 50       6289 if ( ! defined *$self->{Info} ) {
1075 0         0 *$self->{EndStream} = 1 ;
1076 0         0 return -1;
1077             }
1078             }
1079              
1080 1582         2594 push @{ *$self->{InfoList} }, *$self->{Info} ;
  1582         4336  
1081              
1082 1582         6117 return 1;
1083             }
1084              
1085             sub streamCount
1086             {
1087 1260     1260 0 2679 my $self = shift ;
1088 1260 50       4671 return 1 if ! defined *$self->{InfoList};
1089 1260         2360 return scalar @{ *$self->{InfoList} } ;
  1260         7980  
1090             }
1091              
1092             sub read
1093             {
1094             # return codes
1095             # >0 - ok, number of bytes read
1096             # =0 - ok, eof
1097             # <0 - not ok
1098              
1099 332826     332826 0 1318738 my $self = shift ;
1100              
1101 332826 100       732218 if (defined *$self->{ReadStatus} ) {
1102 6         17 my $status = *$self->{ReadStatus}[0];
1103 6         10 $self->saveErrorString( @{ *$self->{ReadStatus} } );
  6         25  
1104 6         20 delete *$self->{ReadStatus} ;
1105 6         192 return $status ;
1106             }
1107              
1108 332820 100       695451 return G_EOF if *$self->{Closed} ;
1109              
1110 332810         468354 my $buffer ;
1111              
1112 332810 100       598499 if (ref $_[0] ) {
1113             $self->croakError(*$self->{ClassName} . "::read: buffer parameter is read-only")
1114 4715 50       6961 if Scalar::Util::readonly(${ $_[0] });
  4715         20830  
1115              
1116 4715 50       15144 $self->croakError(*$self->{ClassName} . "::read: not a scalar reference $_[0]" )
1117             unless ref $_[0] eq 'SCALAR' ;
1118 4715         8454 $buffer = $_[0] ;
1119             }
1120             else {
1121 328095 100       793103 $self->croakError(*$self->{ClassName} . "::read: buffer parameter is read-only")
1122             if Scalar::Util::readonly($_[0]);
1123              
1124 328090         503481 $buffer = \$_[0] ;
1125             }
1126              
1127 332805         530395 my $length = $_[1] ;
1128 332805   100     911276 my $offset = $_[2] || 0;
1129              
1130 332805 100       745912 if (! *$self->{AppendOutput}) {
    100          
1131 161660 100       270684 if (! $offset) {
1132              
1133 161625         256747 $$buffer = '' ;
1134             }
1135             else {
1136 35 100       122 if ($offset > length($$buffer)) {
1137 10         47 $$buffer .= "\x00" x ($offset - length($$buffer));
1138             }
1139             else {
1140 25         67 substr($$buffer, $offset) = '';
1141             }
1142             }
1143             }
1144             elsif (! defined $$buffer) {
1145 2253         5167 $$buffer = '' ;
1146             }
1147              
1148 332805 100 100     718827 return G_EOF if !length *$self->{Pending} && *$self->{EndStream} ;
1149              
1150             # the core read will return 0 if asked for 0 bytes
1151 329523 100 100     1015856 return 0 if defined $length && $length == 0 ;
1152              
1153 329503   100     643937 $length = $length || 0;
1154              
1155 329503 100       611431 $self->croakError(*$self->{ClassName} . "::read: length parameter is negative")
1156             if $length < 0 ;
1157              
1158             # Short-circuit if this is a simple read, with no length
1159             # or offset specified.
1160 329498 100 66     719655 unless ( $length || $offset) {
1161 7075 100       18519 if (length *$self->{Pending}) {
1162 3454         9736 $$buffer .= *$self->{Pending} ;
1163 3454         6927 my $len = length *$self->{Pending};
1164 3454         6948 *$self->{Pending} = '' ;
1165 3454         15780 return $len ;
1166             }
1167             else {
1168 3621         6508 my $len = 0;
1169             $len = $self->_raw_read($buffer)
1170 3621   100     30445 while ! *$self->{EndStream} && $len == 0 ;
1171 3621         11977 return $len ;
1172             }
1173             }
1174              
1175             # Need to jump through more hoops - either length or offset
1176             # or both are specified.
1177 322423         712458 my $out_buffer = *$self->{Pending} ;
1178 322423         527320 *$self->{Pending} = '';
1179              
1180              
1181 322423   100     1005795 while (! *$self->{EndStream} && length($out_buffer) < $length)
1182             {
1183 2494         6775 my $buf_len = $self->_raw_read(\$out_buffer);
1184 2494 50       12700 return $buf_len
1185             if $buf_len < 0 ;
1186             }
1187              
1188 322423 100       610535 $length = length $out_buffer
1189             if length($out_buffer) < $length ;
1190              
1191 322423 100       600156 return 0
1192             if $length == 0 ;
1193              
1194 322313 50       609163 $$buffer = ''
1195             if ! defined $$buffer;
1196              
1197             $offset = length $$buffer
1198 322313 100       666225 if *$self->{AppendOutput} ;
1199              
1200 322313         572021 *$self->{Pending} = $out_buffer;
1201 322313         567073 $out_buffer = \*$self->{Pending} ;
1202              
1203 322313         628829 substr($$buffer, $offset) = substr($$out_buffer, 0, $length) ;
1204 322313         514064 substr($$out_buffer, 0, $length) = '' ;
1205              
1206 322313         782523 return $length ;
1207             }
1208              
1209             sub _getline
1210             {
1211 1525     1525   2400 my $self = shift ;
1212 1525         2364 my $status = 0 ;
1213              
1214             # Slurp Mode
1215 1525 100       3845 if ( ! defined $/ ) {
1216 55         124 my $data ;
1217 55         166 1 while ($status = $self->read($data)) > 0 ;
1218 55         197 return ($status, \$data);
1219             }
1220              
1221             # Record Mode
1222 1470 50 66     6988 if ( ref $/ eq 'SCALAR' && ${$/} =~ /^\d+$/ && ${$/} > 0) {
  85   66     549  
  85         262  
1223 85         118 my $reclen = ${$/} ;
  85         197  
1224 85         117 my $data ;
1225 85         168 $status = $self->read($data, $reclen) ;
1226 85         270 return ($status, \$data);
1227             }
1228              
1229             # Paragraph Mode
1230 1385 100       3376 if ( ! length $/ ) {
1231 60         105 my $paragraph ;
1232 60         195 while (($status = $self->read($paragraph)) > 0 ) {
1233 50 50       455 if ($paragraph =~ s/^(.*?\n\n+)//s) {
1234 50         119 *$self->{Pending} = $paragraph ;
1235 50         147 my $par = $1 ;
1236 50         182 return (1, \$par);
1237             }
1238             }
1239 10         40 return ($status, \$paragraph);
1240             }
1241              
1242             # $/ isn't empty, or a reference, so it's Line Mode.
1243             {
1244 1325         1996 my $line ;
  1325         2081  
1245 1325         2540 my $p = \*$self->{Pending} ;
1246 1325         3208 while (($status = $self->read($line)) > 0 ) {
1247 1320         3695 my $offset = index($line, $/);
1248 1320 100       3224 if ($offset >= 0) {
1249 1287         3531 my $l = substr($line, 0, $offset + length $/ );
1250 1287         2846 substr($line, 0, $offset + length $/) = '';
1251 1287         1996 $$p = $line;
1252 1287         6137 return (1, \$l);
1253             }
1254             }
1255              
1256 38         146 return ($status, \$line);
1257             }
1258             }
1259              
1260             sub getline
1261             {
1262 2086     2086 1 135176 my $self = shift;
1263              
1264 2086 50       6109 if (defined *$self->{ReadStatus} ) {
1265 0         0 $self->saveErrorString( @{ *$self->{ReadStatus} } );
  0         0  
1266 0         0 delete *$self->{ReadStatus} ;
1267 0         0 return undef;
1268             }
1269              
1270             return undef
1271 2086 100 100     10944 if *$self->{Closed} || (!length *$self->{Pending} && *$self->{EndStream}) ;
      66        
1272              
1273 1525         2908 my $current_append = *$self->{AppendOutput} ;
1274 1525         2877 *$self->{AppendOutput} = 1;
1275              
1276 1525         3542 my ($status, $lineref) = $self->_getline();
1277 1525         3005 *$self->{AppendOutput} = $current_append;
1278              
1279             return undef
1280 1525 100 66     5888 if $status < 0 || length $$lineref == 0 ;
1281              
1282 1497         3601 $. = ++ *$self->{LineNo} ;
1283              
1284 1497         5259 return $$lineref ;
1285             }
1286              
1287             sub getlines
1288             {
1289 110     110 1 342 my $self = shift;
1290             $self->croakError(*$self->{ClassName} .
1291 110 50       348 "::getlines: called in scalar context\n") unless wantarray;
1292 110         265 my($line, @lines);
1293 110         399 push(@lines, $line)
1294             while defined($line = $self->getline);
1295 110         580 return @lines;
1296             }
1297              
1298             sub READLINE
1299             {
1300 193 100   193   2460 goto &getlines if wantarray;
1301 163         624 goto &getline;
1302             }
1303              
1304             sub getc
1305             {
1306 105     105 0 11727 my $self = shift;
1307 105         183 my $buf;
1308 105 100       321 return $buf if $self->read($buf, 1);
1309 45         148 return undef;
1310             }
1311              
1312             sub ungetc
1313             {
1314 2941     2941 1 17940 my $self = shift;
1315 2941 50       9332 *$self->{Pending} = "" unless defined *$self->{Pending} ;
1316 2941         12798 *$self->{Pending} = $_[0] . *$self->{Pending} ;
1317             }
1318              
1319              
1320             sub trailingData
1321             {
1322 34     34 0 14449 my $self = shift ;
1323              
1324 34 100 66     242 if (defined *$self->{FH} || defined *$self->{InputEvent} ) {
1325 24         177 return *$self->{Prime} ;
1326             }
1327             else {
1328 10         41 my $buf = *$self->{Buffer} ;
1329 10         32 my $offset = *$self->{BufferOffset} ;
1330 10         56 return substr($$buf, $offset) ;
1331             }
1332             }
1333              
1334              
1335             sub eof
1336             {
1337 2724     2724 0 42138 my $self = shift ;
1338              
1339             return (*$self->{Closed} ||
1340             (!length *$self->{Pending}
1341 2724   66     22644 && ( $self->smartEof() || *$self->{EndStream}))) ;
1342             }
1343              
1344             sub tell
1345             {
1346 1133     1133 1 19292 my $self = shift ;
1347              
1348 1133         2075 my $in ;
1349 1133 100       4034 if (*$self->{Plain}) {
1350 250         639 $in = *$self->{PlainBytesRead} ;
1351             }
1352             else {
1353 883         2011 $in = *$self->{TotalInflatedBytesRead} ;
1354             }
1355              
1356 1133         2479 my $pending = length *$self->{Pending} ;
1357              
1358 1133 100       3525 return 0 if $pending > $in ;
1359 1097         4797 return $in - $pending ;
1360             }
1361              
1362             sub close
1363             {
1364             # todo - what to do if close is called before the end of the gzip file
1365             # do we remember any trailing data?
1366 6344     6344 0 34294 my $self = shift ;
1367              
1368 6344 100       50253 return 1 if *$self->{Closed} ;
1369              
1370 3600 50       22557 untie *$self
1371             if $] >= 5.008 ;
1372              
1373 3600         8148 my $status = 1 ;
1374              
1375 3600 100       11770 if (defined *$self->{FH}) {
1376 2149 100 100     16644 if ((! *$self->{Handle} || *$self->{AutoClose}) && ! *$self->{StdIO}) {
      66        
1377 1959         5923 local $.;
1378 1959         4641 $! = 0 ;
1379 1959         9004 $status = *$self->{FH}->close();
1380             return $self->saveErrorString(0, $!, $!)
1381 1959 50 33     65754 if !*$self->{InNew} && $self->saveStatus($!) != 0 ;
1382             }
1383 2149         10211 delete *$self->{FH} ;
1384 2149         4829 $! = 0 ;
1385             }
1386 3600         7763 *$self->{Closed} = 1 ;
1387              
1388 3600         45527 return 1;
1389             }
1390              
1391             sub DESTROY
1392             {
1393 4395     4395   566684 my $self = shift ;
1394 4395         35632 local ($., $@, $!, $^E, $?);
1395              
1396 4395         14434 $self->close() ;
1397             }
1398              
1399             sub seek
1400             {
1401 106     106 1 14584 my $self = shift ;
1402 106         219 my $position = shift;
1403 106         171 my $whence = shift ;
1404              
1405 106         360 my $here = $self->tell() ;
1406 106         220 my $target = 0 ;
1407              
1408              
1409 106 100       374 if ($whence == SEEK_SET) {
    100          
    100          
1410 21         49 $target = $position ;
1411             }
1412             elsif ($whence == SEEK_CUR) {
1413 63         130 $target = $here + $position ;
1414             }
1415             elsif ($whence == SEEK_END) {
1416 11         32 $target = $position ;
1417 11         102 $self->croakError(*$self->{ClassName} . "::seek: SEEK_END not allowed") ;
1418             }
1419             else {
1420 11         171 $self->croakError(*$self->{ClassName} ."::seek: unknown value, $whence, for whence parameter");
1421             }
1422              
1423             # short circuit if seeking to current offset
1424 84 100       287 if ($target == $here) {
1425             # On ordinary filehandles, seeking to the current
1426             # position also clears the EOF condition, so we
1427             # emulate this behavior locally while simultaneously
1428             # cascading it to the underlying filehandle
1429 26 100       117 if (*$self->{Plain}) {
1430 10         39 *$self->{EndStream} = 0;
1431 10 100       92 seek(*$self->{FH},0,1) if *$self->{FH};
1432             }
1433 26         135 return 1;
1434             }
1435              
1436             # Outlaw any attempt to seek backwards
1437 58 100       210 $self->croakError( *$self->{ClassName} ."::seek: cannot seek backwards")
1438             if $target < $here ;
1439              
1440             # Walk the file to the new offset
1441 47         95 my $offset = $target - $here ;
1442              
1443 47         84 my $got;
1444 47         322 while (($got = $self->read(my $buffer, List::Util::min($offset, *$self->{BlockSize})) ) > 0)
1445             {
1446 47         92 $offset -= $got;
1447 47 50       168 last if $offset == 0 ;
1448             }
1449              
1450 47         327 $here = $self->tell() ;
1451 47 50       313 return $offset == 0 ? 1 : 0 ;
1452             }
1453              
1454             sub fileno
1455             {
1456 35     35 0 1736 my $self = shift ;
1457             return defined *$self->{FH}
1458             ? fileno *$self->{FH}
1459 35 100       308 : undef ;
1460             }
1461              
1462             sub binmode
1463             {
1464 5     5 1 27 1;
1465             # my $self = shift ;
1466             # return defined *$self->{FH}
1467             # ? binmode *$self->{FH}
1468             # : 1 ;
1469             }
1470              
1471             sub opened
1472             {
1473 10     10 1 29 my $self = shift ;
1474 10         56 return ! *$self->{Closed} ;
1475             }
1476              
1477             sub autoflush
1478             {
1479 10     10 0 27 my $self = shift ;
1480             return defined *$self->{FH}
1481 10 50       70 ? *$self->{FH}->autoflush(@_)
1482             : undef ;
1483             }
1484              
1485             sub input_line_number
1486             {
1487 80     80 0 27005 my $self = shift ;
1488 80         217 my $last = *$self->{LineNo};
1489 80 50       288 $. = *$self->{LineNo} = $_[1] if @_ ;
1490 80         617 return $last;
1491             }
1492              
1493             sub _notAvailable
1494             {
1495 600     600   1103 my $name = shift ;
1496 600     25   2414 return sub { croak "$name Not Available: File opened only for intput" ; } ;
  25         12210  
1497             }
1498              
1499             {
1500 100     100   1454 no warnings 'once';
  100         240  
  100         33162  
1501              
1502             *BINMODE = \&binmode;
1503             *SEEK = \&seek;
1504             *READ = \&read;
1505             *sysread = \&read;
1506             *TELL = \&tell;
1507             *EOF = \&eof;
1508              
1509             *FILENO = \&fileno;
1510             *CLOSE = \&close;
1511              
1512             *print = _notAvailable('print');
1513             *PRINT = _notAvailable('print');
1514             *printf = _notAvailable('printf');
1515             *PRINTF = _notAvailable('printf');
1516             *write = _notAvailable('write');
1517             *WRITE = _notAvailable('write');
1518              
1519             #*sysread = \&read;
1520             #*syswrite = \&_notAvailable;
1521             }
1522              
1523              
1524              
1525             package IO::Uncompress::Base ;
1526              
1527              
1528             1 ;
1529             __END__
1530              
1531             =head1 NAME
1532              
1533             IO::Uncompress::Base - Base Class for IO::Uncompress modules
1534              
1535             =head1 SYNOPSIS
1536              
1537             use IO::Uncompress::Base ;
1538              
1539             =head1 DESCRIPTION
1540              
1541             This module is not intended for direct use in application code. Its sole
1542             purpose is to be sub-classed by IO::Uncompress modules.
1543              
1544             =head1 SUPPORT
1545              
1546             General feedback/questions/bug reports should be sent to
1547             L<https://github.com/pmqs/IO-Compress/issues> (preferred) or
1548             L<https://rt.cpan.org/Public/Dist/Display.html?Name=IO-Compress>.
1549              
1550             =head1 SEE ALSO
1551              
1552             L<Compress::Zlib>, L<IO::Compress::Gzip>, L<IO::Uncompress::Gunzip>, L<IO::Compress::Deflate>, L<IO::Uncompress::Inflate>, L<IO::Compress::RawDeflate>, L<IO::Uncompress::RawInflate>, L<IO::Compress::Bzip2>, L<IO::Uncompress::Bunzip2>, L<IO::Compress::Lzma>, L<IO::Uncompress::UnLzma>, L<IO::Compress::Xz>, L<IO::Uncompress::UnXz>, L<IO::Compress::Lzip>, L<IO::Uncompress::UnLzip>, L<IO::Compress::Lzop>, L<IO::Uncompress::UnLzop>, L<IO::Compress::Lzf>, L<IO::Uncompress::UnLzf>, L<IO::Compress::Zstd>, L<IO::Uncompress::UnZstd>, L<IO::Uncompress::AnyInflate>, L<IO::Uncompress::AnyUncompress>
1553              
1554             L<IO::Compress::FAQ|IO::Compress::FAQ>
1555              
1556             L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>,
1557             L<Archive::Tar|Archive::Tar>,
1558             L<IO::Zlib|IO::Zlib>
1559              
1560             =head1 AUTHOR
1561              
1562             This module was written by Paul Marquess, C<pmqs@cpan.org>.
1563              
1564             =head1 MODIFICATION HISTORY
1565              
1566             See the Changes file.
1567              
1568             =head1 COPYRIGHT AND LICENSE
1569              
1570             Copyright (c) 2005-2026 Paul Marquess. All rights reserved.
1571              
1572             This program is free software; you can redistribute it and/or
1573             modify it under the same terms as Perl itself.