home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / perl5 / IO / Uncompress / Base.pm < prev    next >
Encoding:
Perl POD Document  |  2008-09-03  |  34.0 KB  |  1,457 lines

  1.  
  2. package IO::Uncompress::Base ;
  3.  
  4. use strict ;
  5. use warnings;
  6. use bytes;
  7.  
  8. our (@ISA, $VERSION, @EXPORT_OK, %EXPORT_TAGS);
  9. @ISA    = qw(Exporter IO::File);
  10.  
  11.  
  12. $VERSION = '2.015';
  13.  
  14. use constant G_EOF => 0 ;
  15. use constant G_ERR => -1 ;
  16.  
  17. use IO::Compress::Base::Common 2.015 ;
  18. #use Parse::Parameters ;
  19.  
  20. use IO::File ;
  21. use Symbol;
  22. use Scalar::Util qw(readonly);
  23. use List::Util qw(min);
  24. use Carp ;
  25.  
  26. %EXPORT_TAGS = ( );
  27. push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
  28. #Exporter::export_ok_tags('all') ;
  29.  
  30.  
  31.  
  32. sub smartRead
  33. {
  34.     my $self = $_[0];
  35.     my $out = $_[1];
  36.     my $size = $_[2];
  37.     $$out = "" ;
  38.  
  39.     my $offset = 0 ;
  40.  
  41.  
  42.     if (defined *$self->{InputLength}) {
  43.         return 0
  44.             if *$self->{InputLengthRemaining} <= 0 ;
  45.         $size = min($size, *$self->{InputLengthRemaining});
  46.     }
  47.  
  48.     if ( length *$self->{Prime} ) {
  49.         #$$out = substr(*$self->{Prime}, 0, $size, '') ;
  50.         $$out = substr(*$self->{Prime}, 0, $size) ;
  51.         substr(*$self->{Prime}, 0, $size) =  '' ;
  52.         if (length $$out == $size) {
  53.             *$self->{InputLengthRemaining} -= length $$out
  54.                 if defined *$self->{InputLength};
  55.  
  56.             return length $$out ;
  57.         }
  58.         $offset = length $$out ;
  59.     }
  60.  
  61.     my $get_size = $size - $offset ;
  62.  
  63.     if (defined *$self->{FH}) {
  64.         if ($offset) {
  65.             # Not using this 
  66.             #
  67.             #  *$self->{FH}->read($$out, $get_size, $offset);
  68.             #
  69.             # because the filehandle may not support the offset parameter
  70.             # An example is Net::FTP
  71.             my $tmp = '';
  72.             *$self->{FH}->read($tmp, $get_size) > 0 &&
  73.                 (substr($$out, $offset) = $tmp);
  74.         }
  75.         else
  76.           { *$self->{FH}->read($$out, $get_size) }
  77.     }
  78.     elsif (defined *$self->{InputEvent}) {
  79.         my $got = 1 ;
  80.         while (length $$out < $size) {
  81.             last 
  82.                 if ($got = *$self->{InputEvent}->($$out, $get_size)) <= 0;
  83.         }
  84.  
  85.         if (length $$out > $size ) {
  86.             #*$self->{Prime} = substr($$out, $size, length($$out), '');
  87.             *$self->{Prime} = substr($$out, $size, length($$out));
  88.             substr($$out, $size, length($$out)) =  '';
  89.         }
  90.  
  91.        *$self->{EventEof} = 1 if $got <= 0 ;
  92.     }
  93.     else {
  94.        no warnings 'uninitialized';
  95.        my $buf = *$self->{Buffer} ;
  96.        $$buf = '' unless defined $$buf ;
  97.        #$$out = '' unless defined $$out ;
  98.        substr($$out, $offset) = substr($$buf, *$self->{BufferOffset}, $get_size);
  99.        if (*$self->{ConsumeInput})
  100.          { substr($$buf, 0, $get_size) = '' }
  101.        else  
  102.          { *$self->{BufferOffset} += length($$out) - $offset }
  103.     }
  104.  
  105.     *$self->{InputLengthRemaining} -= length($$out) #- $offset 
  106.         if defined *$self->{InputLength};
  107.         
  108.     $self->saveStatus(length $$out < 0 ? STATUS_ERROR : STATUS_OK) ;
  109.  
  110.     return length $$out;
  111. }
  112.  
  113. sub pushBack
  114. {
  115.     my $self = shift ;
  116.  
  117.     return if ! defined $_[0] || length $_[0] == 0 ;
  118.  
  119.     if (defined *$self->{FH} || defined *$self->{InputEvent} ) {
  120.         *$self->{Prime} = $_[0] . *$self->{Prime} ;
  121.         *$self->{InputLengthRemaining} += length($_[0]);
  122.     }
  123.     else {
  124.         my $len = length $_[0];
  125.  
  126.         if($len > *$self->{BufferOffset}) {
  127.             *$self->{Prime} = substr($_[0], 0, $len - *$self->{BufferOffset}) . *$self->{Prime} ;
  128.             *$self->{InputLengthRemaining} = *$self->{InputLength};
  129.             *$self->{BufferOffset} = 0
  130.         }
  131.         else {
  132.             *$self->{InputLengthRemaining} += length($_[0]);
  133.             *$self->{BufferOffset} -= length($_[0]) ;
  134.         }
  135.     }
  136. }
  137.  
  138. sub smartSeek
  139. {
  140.     my $self   = shift ;
  141.     my $offset = shift ;
  142.     my $truncate = shift;
  143.     #print "smartSeek to $offset\n";
  144.  
  145.     # TODO -- need to take prime into account
  146.     if (defined *$self->{FH})
  147.       { *$self->{FH}->seek($offset, SEEK_SET) }
  148.     else {
  149.         *$self->{BufferOffset} = $offset ;
  150.         substr(${ *$self->{Buffer} }, *$self->{BufferOffset}) = ''
  151.             if $truncate;
  152.         return 1;
  153.     }
  154. }
  155.  
  156. sub smartWrite
  157. {
  158.     my $self   = shift ;
  159.     my $out_data = shift ;
  160.  
  161.     if (defined *$self->{FH}) {
  162.         # flush needed for 5.8.0 
  163.         defined *$self->{FH}->write($out_data, length $out_data) &&
  164.         defined *$self->{FH}->flush() ;
  165.     }
  166.     else {
  167.        my $buf = *$self->{Buffer} ;
  168.        substr($$buf, *$self->{BufferOffset}, length $out_data) = $out_data ;
  169.        *$self->{BufferOffset} += length($out_data) ;
  170.        return 1;
  171.     }
  172. }
  173.  
  174. sub smartReadExact
  175. {
  176.     return $_[0]->smartRead($_[1], $_[2]) == $_[2];
  177. }
  178.  
  179. sub smartEof
  180. {
  181.     my ($self) = $_[0];
  182.     local $.; 
  183.  
  184.     return 0 if length *$self->{Prime} || *$self->{PushMode};
  185.  
  186.     if (defined *$self->{FH})
  187.     {
  188.         # Could use
  189.         #
  190.         #  *$self->{FH}->eof() 
  191.         #
  192.         # here, but this can cause trouble if
  193.         # the filehandle is itself a tied handle, but it uses sysread.
  194.         # Then we get into mixing buffered & non-buffered IO, which will cause trouble
  195.  
  196.         my $info = $self->getErrInfo();
  197.         
  198.         my $buffer = '';
  199.         my $status = $self->smartRead(\$buffer, 1);
  200.         $self->pushBack($buffer) if length $buffer;
  201.         $self->setErrInfo($info);
  202.         
  203.         return $status == 0 ;
  204.     }
  205.     elsif (defined *$self->{InputEvent})
  206.      { *$self->{EventEof} }
  207.     else 
  208.      { *$self->{BufferOffset} >= length(${ *$self->{Buffer} }) }
  209. }
  210.  
  211. sub clearError
  212. {
  213.     my $self   = shift ;
  214.  
  215.     *$self->{ErrorNo}  =  0 ;
  216.     ${ *$self->{Error} } = '' ;
  217. }
  218.  
  219. sub getErrInfo
  220. {
  221.     my $self   = shift ;
  222.  
  223.     return [ *$self->{ErrorNo}, ${ *$self->{Error} } ] ;
  224. }
  225.  
  226. sub setErrInfo
  227. {
  228.     my $self   = shift ;
  229.     my $ref    = shift;
  230.  
  231.     *$self->{ErrorNo}  =  $ref->[0] ;
  232.     ${ *$self->{Error} } = $ref->[1] ;
  233. }
  234.  
  235. sub saveStatus
  236. {
  237.     my $self   = shift ;
  238.     my $errno = shift() + 0 ;
  239.     #return $errno unless $errno || ! defined *$self->{ErrorNo};
  240.     #return $errno unless $errno ;
  241.  
  242.     *$self->{ErrorNo}  = $errno;
  243.     ${ *$self->{Error} } = '' ;
  244.  
  245.     return *$self->{ErrorNo} ;
  246. }
  247.  
  248.  
  249. sub saveErrorString
  250. {
  251.     my $self   = shift ;
  252.     my $retval = shift ;
  253.  
  254.     #return $retval if ${ *$self->{Error} };
  255.  
  256.     ${ *$self->{Error} } = shift ;
  257.     *$self->{ErrorNo} = shift() + 0 if @_ ;
  258.  
  259.     #warn "saveErrorString: " . ${ *$self->{Error} } . " " . *$self->{Error} . "\n" ;
  260.     return $retval;
  261. }
  262.  
  263. sub croakError
  264. {
  265.     my $self   = shift ;
  266.     $self->saveErrorString(0, $_[0]);
  267.     croak $_[0];
  268. }
  269.  
  270.  
  271. sub closeError
  272. {
  273.     my $self = shift ;
  274.     my $retval = shift ;
  275.  
  276.     my $errno = *$self->{ErrorNo};
  277.     my $error = ${ *$self->{Error} };
  278.  
  279.     $self->close();
  280.  
  281.     *$self->{ErrorNo} = $errno ;
  282.     ${ *$self->{Error} } = $error ;
  283.  
  284.     return $retval;
  285. }
  286.  
  287. sub error
  288. {
  289.     my $self   = shift ;
  290.     return ${ *$self->{Error} } ;
  291. }
  292.  
  293. sub errorNo
  294. {
  295.     my $self   = shift ;
  296.     return *$self->{ErrorNo};
  297. }
  298.  
  299. sub HeaderError
  300. {
  301.     my ($self) = shift;
  302.     return $self->saveErrorString(undef, "Header Error: $_[0]", STATUS_ERROR);
  303. }
  304.  
  305. sub TrailerError
  306. {
  307.     my ($self) = shift;
  308.     return $self->saveErrorString(G_ERR, "Trailer Error: $_[0]", STATUS_ERROR);
  309. }
  310.  
  311. sub TruncatedHeader
  312. {
  313.     my ($self) = shift;
  314.     return $self->HeaderError("Truncated in $_[0] Section");
  315. }
  316.  
  317. sub TruncatedTrailer
  318. {
  319.     my ($self) = shift;
  320.     return $self->TrailerError("Truncated in $_[0] Section");
  321. }
  322.  
  323. sub postCheckParams
  324. {
  325.     return 1;
  326. }
  327.  
  328. sub checkParams
  329. {
  330.     my $self = shift ;
  331.     my $class = shift ;
  332.  
  333.     my $got = shift || IO::Compress::Base::Parameters::new();
  334.     
  335.     my $Valid = {
  336.                     'BlockSize'     => [1, 1, Parse_unsigned, 16 * 1024],
  337.                     'AutoClose'     => [1, 1, Parse_boolean,  0],
  338.                     'Strict'        => [1, 1, Parse_boolean,  0],
  339.                     'Append'        => [1, 1, Parse_boolean,  0],
  340.                     'Prime'         => [1, 1, Parse_any,      undef],
  341.                     'MultiStream'   => [1, 1, Parse_boolean,  0],
  342.                     'Transparent'   => [1, 1, Parse_any,      1],
  343.                     'Scan'          => [1, 1, Parse_boolean,  0],
  344.                     'InputLength'   => [1, 1, Parse_unsigned, undef],
  345.                     'BinModeOut'    => [1, 1, Parse_boolean,  0],
  346.                     #'Encode'        => [1, 1, Parse_any,       undef],
  347.  
  348.                    #'ConsumeInput'  => [1, 1, Parse_boolean,  0],
  349.  
  350.                     $self->getExtraParams(),
  351.  
  352.                     #'Todo - Revert to ordinary file on end Z_STREAM_END'=> 0,
  353.                     # ContinueAfterEof
  354.                 } ;
  355.  
  356.     $Valid->{TrailingData} = [1, 1, Parse_writable_scalar, undef]
  357.         if  *$self->{OneShot} ;
  358.         
  359.     $got->parse($Valid, @_ ) 
  360.         or $self->croakError("${class}: $got->{Error}")  ;
  361.  
  362.     $self->postCheckParams($got) 
  363.         or $self->croakError("${class}: " . $self->error())  ;
  364.  
  365.     return $got;
  366. }
  367.  
  368. sub _create
  369. {
  370.     my $obj = shift;
  371.     my $got = shift;
  372.     my $append_mode = shift ;
  373.  
  374.     my $class = ref $obj;
  375.     $obj->croakError("$class: Missing Input parameter")
  376.         if ! @_ && ! $got ;
  377.  
  378.     my $inValue = shift ;
  379.  
  380.     *$obj->{OneShot}           = 0 ;
  381.  
  382.     if (! $got)
  383.     {
  384.         $got = $obj->checkParams($class, undef, @_)
  385.             or return undef ;
  386.     }
  387.  
  388.     my $inType  = whatIsInput($inValue, 1);
  389.  
  390.     $obj->ckInputParam($class, $inValue, 1) 
  391.         or return undef ;
  392.  
  393.     *$obj->{InNew} = 1;
  394.  
  395.     $obj->ckParams($got)
  396.         or $obj->croakError("${class}: " . *$obj->{Error});
  397.  
  398.     if ($inType eq 'buffer' || $inType eq 'code') {
  399.         *$obj->{Buffer} = $inValue ;        
  400.         *$obj->{InputEvent} = $inValue 
  401.            if $inType eq 'code' ;
  402.     }
  403.     else {
  404.         if ($inType eq 'handle') {
  405.             *$obj->{FH} = $inValue ;
  406.             *$obj->{Handle} = 1 ;
  407.  
  408.             # Need to rewind for Scan
  409.             *$obj->{FH}->seek(0, SEEK_SET) 
  410.                 if $got->value('Scan');
  411.         }  
  412.         else {    
  413.             my $mode = '<';
  414.             $mode = '+<' if $got->value('Scan');
  415.             *$obj->{StdIO} = ($inValue eq '-');
  416.             *$obj->{FH} = new IO::File "$mode $inValue"
  417.                 or return $obj->saveErrorString(undef, "cannot open file '$inValue': $!", $!) ;
  418.         }
  419.         
  420.         *$obj->{LineNo} = $. = 0;
  421.         setBinModeInput(*$obj->{FH}) ;
  422.  
  423.         my $buff = "" ;
  424.         *$obj->{Buffer} = \$buff ;
  425.     }
  426.  
  427.     if ($got->parsed('Encode')) { 
  428.         my $want_encoding = $got->value('Encode');
  429.         *$obj->{Encoding} = getEncoding($obj, $class, $want_encoding);
  430.     }
  431.  
  432.  
  433.     *$obj->{InputLength}       = $got->parsed('InputLength') 
  434.                                     ? $got->value('InputLength')
  435.                                     : undef ;
  436.     *$obj->{InputLengthRemaining} = $got->value('InputLength');
  437.     *$obj->{BufferOffset}      = 0 ;
  438.     *$obj->{AutoClose}         = $got->value('AutoClose');
  439.     *$obj->{Strict}            = $got->value('Strict');
  440.     *$obj->{BlockSize}         = $got->value('BlockSize');
  441.     *$obj->{Append}            = $got->value('Append');
  442.     *$obj->{AppendOutput}      = $append_mode || $got->value('Append');
  443.     *$obj->{ConsumeInput}      = $got->value('ConsumeInput');
  444.     *$obj->{Transparent}       = $got->value('Transparent');
  445.     *$obj->{MultiStream}       = $got->value('MultiStream');
  446.  
  447.     # TODO - move these two into RawDeflate
  448.     *$obj->{Scan}              = $got->value('Scan');
  449.     *$obj->{ParseExtra}        = $got->value('ParseExtra') 
  450.                                   || $got->value('Strict')  ;
  451.     *$obj->{Type}              = '';
  452.     *$obj->{Prime}             = $got->value('Prime') || '' ;
  453.     *$obj->{Pending}           = '';
  454.     *$obj->{Plain}             = 0;
  455.     *$obj->{PlainBytesRead}    = 0;
  456.     *$obj->{InflatedBytesRead} = 0;
  457.     *$obj->{UnCompSize}        = new U64;
  458.     *$obj->{CompSize}          = new U64;
  459.     *$obj->{TotalInflatedBytesRead} = 0;
  460.     *$obj->{NewStream}         = 0 ;
  461.     *$obj->{EventEof}          = 0 ;
  462.     *$obj->{ClassName}         = $class ;
  463.     *$obj->{Params}            = $got ;
  464.  
  465.     if (*$obj->{ConsumeInput}) {
  466.         *$obj->{InNew} = 0;
  467.         *$obj->{Closed} = 0;
  468.         return $obj
  469.     }
  470.  
  471.     my $status = $obj->mkUncomp($got);
  472.  
  473.     return undef
  474.         unless defined $status;
  475.  
  476.     if ( !  $status) {
  477.         return undef 
  478.             unless *$obj->{Transparent};
  479.  
  480.         $obj->clearError();
  481.         *$obj->{Type} = 'plain';
  482.         *$obj->{Plain} = 1;
  483.         #$status = $obj->mkIdentityUncomp($class, $got);
  484.         $obj->pushBack(*$obj->{HeaderPending})  ;
  485.     }
  486.  
  487.     push @{ *$obj->{InfoList} }, *$obj->{Info} ;
  488.  
  489.     $obj->saveStatus(STATUS_OK) ;
  490.     *$obj->{InNew} = 0;
  491.     *$obj->{Closed} = 0;
  492.  
  493.     return $obj;
  494. }
  495.  
  496. sub ckInputParam
  497. {
  498.     my $self = shift ;
  499.     my $from = shift ;
  500.     my $inType = whatIsInput($_[0], $_[1]);
  501.  
  502.     $self->croakError("$from: input parameter not a filename, filehandle, array ref or scalar ref")
  503.         if ! $inType ;
  504.  
  505.     if ($inType  eq 'filename' )
  506.     {
  507.         $self->croakError("$from: input filename is undef or null string")
  508.             if ! defined $_[0] || $_[0] eq ''  ;
  509.  
  510.         if ($_[0] ne '-' && ! -e $_[0] )
  511.         {
  512.             return $self->saveErrorString(undef, 
  513.                             "input file '$_[0]' does not exist", STATUS_ERROR);
  514.         }
  515.     }
  516.  
  517.     return 1;
  518. }
  519.  
  520.  
  521. sub _inf
  522. {
  523.     my $obj = shift ;
  524.  
  525.     my $class = (caller)[0] ;
  526.     my $name = (caller(1))[3] ;
  527.  
  528.     $obj->croakError("$name: expected at least 1 parameters\n")
  529.         unless @_ >= 1 ;
  530.  
  531.     my $input = shift ;
  532.     my $haveOut = @_ ;
  533.     my $output = shift ;
  534.  
  535.  
  536.     my $x = new IO::Compress::Base::Validator($class, *$obj->{Error}, $name, $input, $output)
  537.         or return undef ;
  538.     
  539.     push @_, $output if $haveOut && $x->{Hash};
  540.  
  541.     *$obj->{OneShot} = 1 ;
  542.     
  543.     my $got = $obj->checkParams($name, undef, @_)
  544.         or return undef ;
  545.  
  546.     if ($got->parsed('TrailingData'))
  547.     {
  548.         *$obj->{TrailingData} = $got->value('TrailingData');
  549.     }
  550.  
  551.     *$obj->{MultiStream} = $got->value('MultiStream');
  552.     $got->value('MultiStream', 0);
  553.  
  554.     $x->{Got} = $got ;
  555.  
  556. #    if ($x->{Hash})
  557. #    {
  558. #        while (my($k, $v) = each %$input)
  559. #        {
  560. #            $v = \$input->{$k} 
  561. #                unless defined $v ;
  562. #
  563. #            $obj->_singleTarget($x, $k, $v, @_)
  564. #                or return undef ;
  565. #        }
  566. #
  567. #        return keys %$input ;
  568. #    }
  569.     
  570.     if ($x->{GlobMap})
  571.     {
  572.         $x->{oneInput} = 1 ;
  573.         foreach my $pair (@{ $x->{Pairs} })
  574.         {
  575.             my ($from, $to) = @$pair ;
  576.             $obj->_singleTarget($x, $from, $to, @_)
  577.                 or return undef ;
  578.         }
  579.  
  580.         return scalar @{ $x->{Pairs} } ;
  581.     }
  582.  
  583.     if (! $x->{oneOutput} )
  584.     {
  585.         my $inFile = ($x->{inType} eq 'filenames' 
  586.                         || $x->{inType} eq 'filename');
  587.  
  588.         $x->{inType} = $inFile ? 'filename' : 'buffer';
  589.         
  590.         foreach my $in ($x->{oneInput} ? $input : @$input)
  591.         {
  592.             my $out ;
  593.             $x->{oneInput} = 1 ;
  594.  
  595.             $obj->_singleTarget($x, $in, $output, @_)
  596.                 or return undef ;
  597.         }
  598.  
  599.         return 1 ;
  600.     }
  601.  
  602.     # finally the 1 to 1 and n to 1
  603.     return $obj->_singleTarget($x, $input, $output, @_);
  604.  
  605.     croak "should not be here" ;
  606. }
  607.  
  608. sub retErr
  609. {
  610.     my $x = shift ;
  611.     my $string = shift ;
  612.  
  613.     ${ $x->{Error} } = $string ;
  614.  
  615.     return undef ;
  616. }
  617.  
  618. sub _singleTarget
  619. {
  620.     my $self      = shift ;
  621.     my $x         = shift ;
  622.     my $input     = shift;
  623.     my $output    = shift;
  624.     
  625.     my $buff = '';
  626.     $x->{buff} = \$buff ;
  627.  
  628.     my $fh ;
  629.     if ($x->{outType} eq 'filename') {
  630.         my $mode = '>' ;
  631.         $mode = '>>'
  632.             if $x->{Got}->value('Append') ;
  633.         $x->{fh} = new IO::File "$mode $output" 
  634.             or return retErr($x, "cannot open file '$output': $!") ;
  635.         binmode $x->{fh} if $x->{Got}->valueOrDefault('BinModeOut');
  636.  
  637.     }
  638.  
  639.     elsif ($x->{outType} eq 'handle') {
  640.         $x->{fh} = $output;
  641.         binmode $x->{fh} if $x->{Got}->valueOrDefault('BinModeOut');
  642.         if ($x->{Got}->value('Append')) {
  643.                 seek($x->{fh}, 0, SEEK_END)
  644.                     or return retErr($x, "Cannot seek to end of output filehandle: $!") ;
  645.             }
  646.     }
  647.  
  648.     
  649.     elsif ($x->{outType} eq 'buffer' )
  650.     {
  651.         $$output = '' 
  652.             unless $x->{Got}->value('Append');
  653.         $x->{buff} = $output ;
  654.     }
  655.  
  656.     if ($x->{oneInput})
  657.     {
  658.         defined $self->_rd2($x, $input, $output)
  659.             or return undef; 
  660.     }
  661.     else
  662.     {
  663.         for my $element ( ($x->{inType} eq 'hash') ? keys %$input : @$input)
  664.         {
  665.             defined $self->_rd2($x, $element, $output) 
  666.                 or return undef ;
  667.         }
  668.     }
  669.  
  670.  
  671.     if ( ($x->{outType} eq 'filename' && $output ne '-') || 
  672.          ($x->{outType} eq 'handle' && $x->{Got}->value('AutoClose'))) {
  673.         $x->{fh}->close() 
  674.             or return retErr($x, $!); 
  675.         delete $x->{fh};
  676.     }
  677.  
  678.     return 1 ;
  679. }
  680.  
  681. sub _rd2
  682. {
  683.     my $self      = shift ;
  684.     my $x         = shift ;
  685.     my $input     = shift;
  686.     my $output    = shift;
  687.         
  688.     my $z = createSelfTiedObject($x->{Class}, *$self->{Error});
  689.     
  690.     $z->_create($x->{Got}, 1, $input, @_)
  691.         or return undef ;
  692.  
  693.     my $status ;
  694.     my $fh = $x->{fh};
  695.     
  696.     while (1) {
  697.  
  698.         while (($status = $z->read($x->{buff})) > 0) {
  699.             if ($fh) {
  700.                 print $fh ${ $x->{buff} }
  701.                     or return $z->saveErrorString(undef, "Error writing to output file: $!", $!);
  702.                 ${ $x->{buff} } = '' ;
  703.             }
  704.         }
  705.  
  706.         if (! $x->{oneOutput} ) {
  707.             my $ot = $x->{outType} ;
  708.  
  709.             if ($ot eq 'array') 
  710.               { push @$output, $x->{buff} }
  711.             elsif ($ot eq 'hash') 
  712.               { $output->{$input} = $x->{buff} }
  713.  
  714.             my $buff = '';
  715.             $x->{buff} = \$buff;
  716.         }
  717.  
  718.         last 
  719.             unless *$self->{MultiStream};
  720.  
  721.         $status = $z->nextStream();
  722.  
  723.         last 
  724.             unless $status == 1 ;
  725.     }
  726.  
  727.     return $z->closeError(undef)
  728.         if $status < 0 ;
  729.  
  730.     ${ *$self->{TrailingData} } = $z->trailingData()
  731.         if defined *$self->{TrailingData} ;
  732.  
  733.     $z->close() 
  734.         or return undef ;
  735.  
  736.     return 1 ;
  737. }
  738.  
  739. sub TIEHANDLE
  740. {
  741.     return $_[0] if ref($_[0]);
  742.     die "OOPS\n" ;
  743.  
  744. }
  745.   
  746. sub UNTIE
  747. {
  748.     my $self = shift ;
  749. }
  750.  
  751.  
  752. sub getHeaderInfo
  753. {
  754.     my $self = shift ;
  755.     wantarray ? @{ *$self->{InfoList} } : *$self->{Info};
  756. }
  757.  
  758. sub readBlock
  759. {
  760.     my $self = shift ;
  761.     my $buff = shift ;
  762.     my $size = shift ;
  763.  
  764.     if (defined *$self->{CompressedInputLength}) {
  765.         if (*$self->{CompressedInputLengthRemaining} == 0) {
  766.             delete *$self->{CompressedInputLength};
  767.             *$self->{CompressedInputLengthDone} = 1;
  768.             return STATUS_OK ;
  769.         }
  770.         $size = min($size, *$self->{CompressedInputLengthRemaining} );
  771.         *$self->{CompressedInputLengthRemaining} -= $size ;
  772.     }
  773.     
  774.     my $status = $self->smartRead($buff, $size) ;
  775.     return $self->saveErrorString(STATUS_ERROR, "Error Reading Data")
  776.         if $status < 0  ;
  777.  
  778.     if ($status == 0 ) {
  779.         *$self->{Closed} = 1 ;
  780.         *$self->{EndStream} = 1 ;
  781.         return $self->saveErrorString(STATUS_ERROR, "unexpected end of file", STATUS_ERROR);
  782.     }
  783.  
  784.     return STATUS_OK;
  785. }
  786.  
  787. sub postBlockChk
  788. {
  789.     return STATUS_OK;
  790. }
  791.  
  792. sub _raw_read
  793. {
  794.     # return codes
  795.     # >0 - ok, number of bytes read
  796.     # =0 - ok, eof
  797.     # <0 - not ok
  798.     
  799.     my $self = shift ;
  800.  
  801.     return G_EOF if *$self->{Closed} ;
  802.     #return G_EOF if !length *$self->{Pending} && *$self->{EndStream} ;
  803.     return G_EOF if *$self->{EndStream} ;
  804.  
  805.     my $buffer = shift ;
  806.     my $scan_mode = shift ;
  807.  
  808.     if (*$self->{Plain}) {
  809.         my $tmp_buff ;
  810.         my $len = $self->smartRead(\$tmp_buff, *$self->{BlockSize}) ;
  811.         
  812.         return $self->saveErrorString(G_ERR, "Error reading data: $!", $!) 
  813.                 if $len < 0 ;
  814.  
  815.         if ($len == 0 ) {
  816.             *$self->{EndStream} = 1 ;
  817.         }
  818.         else {
  819.             *$self->{PlainBytesRead} += $len ;
  820.             $$buffer .= $tmp_buff;
  821.         }
  822.  
  823.         return $len ;
  824.     }
  825.  
  826.     if (*$self->{NewStream}) {
  827.  
  828.         $self->gotoNextStream() > 0
  829.             or return G_ERR;
  830.  
  831.         # For the headers that actually uncompressed data, put the
  832.         # uncompressed data into the output buffer.
  833.         $$buffer .=  *$self->{Pending} ;
  834.         my $len = length  *$self->{Pending} ;
  835.         *$self->{Pending} = '';
  836.         return $len; 
  837.     }
  838.  
  839.     my $temp_buf = '';
  840.     my $outSize = 0;
  841.     my $status = $self->readBlock(\$temp_buf, *$self->{BlockSize}, $outSize) ;
  842.     return G_ERR
  843.         if $status == STATUS_ERROR  ;
  844.  
  845.     my $buf_len = 0;
  846.     if ($status == STATUS_OK) {
  847.         my $beforeC_len = length $temp_buf;
  848.         my $before_len = defined $$buffer ? length $$buffer : 0 ;
  849.         $status = *$self->{Uncomp}->uncompr(\$temp_buf, $buffer,
  850.                                     defined *$self->{CompressedInputLengthDone} ||
  851.                                                 $self->smartEof(), $outSize);
  852.  
  853.         return $self->saveErrorString(G_ERR, *$self->{Uncomp}{Error}, *$self->{Uncomp}{ErrorNo})
  854.             if $self->saveStatus($status) == STATUS_ERROR;
  855.  
  856.         $self->postBlockChk($buffer, $before_len) == STATUS_OK
  857.             or return G_ERR;
  858.  
  859.         $buf_len = defined $$buffer ? length($$buffer) - $before_len : 0;
  860.     
  861.         *$self->{CompSize}->add($beforeC_len - length $temp_buf) ;
  862.  
  863.         *$self->{InflatedBytesRead} += $buf_len ;
  864.         *$self->{TotalInflatedBytesRead} += $buf_len ;
  865.         *$self->{UnCompSize}->add($buf_len) ;
  866.  
  867.         $self->filterUncompressed($buffer);
  868.  
  869.         if (*$self->{Encoding}) {
  870.             $$buffer = *$self->{Encoding}->decode($$buffer);
  871.         }
  872.     }
  873.  
  874.     if ($status == STATUS_ENDSTREAM) {
  875.  
  876.         *$self->{EndStream} = 1 ;
  877.         $self->pushBack($temp_buf)  ;
  878.         $temp_buf = '';
  879.  
  880.         my $trailer;
  881.         my $trailer_size = *$self->{Info}{TrailerLength} ;
  882.         my $got = 0;
  883.         if (*$self->{Info}{TrailerLength})
  884.         {
  885.             $got = $self->smartRead(\$trailer, $trailer_size) ;
  886.         }
  887.  
  888.         if ($got == $trailer_size) {
  889.             $self->chkTrailer($trailer) == STATUS_OK
  890.                 or return G_ERR;
  891.         }
  892.         else {
  893.             return $self->TrailerError("trailer truncated. Expected " . 
  894.                                       "$trailer_size bytes, got $got")
  895.                 if *$self->{Strict};
  896.             $self->pushBack($trailer)  ;
  897.         }
  898.  
  899.         # TODO - if want to file file pointer, do it here
  900.  
  901.         if (! $self->smartEof()) {
  902.             *$self->{NewStream} = 1 ;
  903.  
  904.             if (*$self->{MultiStream}) {
  905.                 *$self->{EndStream} = 0 ;
  906.                 return $buf_len ;
  907.             }
  908.         }
  909.  
  910.     }
  911.     
  912.  
  913.     # return the number of uncompressed bytes read
  914.     return $buf_len ;
  915. }
  916.  
  917. sub reset
  918. {
  919.     my $self = shift ;
  920.  
  921.     return *$self->{Uncomp}->reset();
  922. }
  923.  
  924. sub filterUncompressed
  925. {
  926. }
  927.  
  928. #sub isEndStream
  929. #{
  930. #    my $self = shift ;
  931. #    return *$self->{NewStream} ||
  932. #           *$self->{EndStream} ;
  933. #}
  934.  
  935. sub nextStream
  936. {
  937.     my $self = shift ;
  938.  
  939.     my $status = $self->gotoNextStream();
  940.     $status == 1
  941.         or return $status ;
  942.  
  943.     *$self->{TotalInflatedBytesRead} = 0 ;
  944.     *$self->{LineNo} = $. = 0;
  945.  
  946.     return 1;
  947. }
  948.  
  949. sub gotoNextStream
  950. {
  951.     my $self = shift ;
  952.  
  953.     if (! *$self->{NewStream}) {
  954.         my $status = 1;
  955.         my $buffer ;
  956.  
  957.         # TODO - make this more efficient if know the offset for the end of
  958.         # the stream and seekable
  959.         $status = $self->read($buffer) 
  960.             while $status > 0 ;
  961.  
  962.         return $status
  963.             if $status < 0;
  964.     }
  965.  
  966.     *$self->{NewStream} = 0 ;
  967.     *$self->{EndStream} = 0 ;
  968.     $self->reset();
  969.     *$self->{UnCompSize}->reset();
  970.     *$self->{CompSize}->reset();
  971.  
  972.     my $magic = $self->ckMagic();
  973.     #*$self->{EndStream} = 0 ;
  974.  
  975.     if ( ! defined $magic) {
  976.         if (! *$self->{Transparent} )
  977.         {
  978.             *$self->{EndStream} = 1 ;
  979.             return 0;
  980.         }
  981.  
  982.         $self->clearError();
  983.         *$self->{Type} = 'plain';
  984.         *$self->{Plain} = 1;
  985.         $self->pushBack(*$self->{HeaderPending})  ;
  986.     }
  987.     else
  988.     {
  989.         *$self->{Info} = $self->readHeader($magic);
  990.  
  991.         if ( ! defined *$self->{Info} ) {
  992.             *$self->{EndStream} = 1 ;
  993.             return -1;
  994.         }
  995.     }
  996.  
  997.     push @{ *$self->{InfoList} }, *$self->{Info} ;
  998.  
  999.     return 1; 
  1000. }
  1001.  
  1002. sub streamCount
  1003. {
  1004.     my $self = shift ;
  1005.     return 1 if ! defined *$self->{InfoList};
  1006.     return scalar @{ *$self->{InfoList} }  ;
  1007. }
  1008.  
  1009. sub read
  1010. {
  1011.     # return codes
  1012.     # >0 - ok, number of bytes read
  1013.     # =0 - ok, eof
  1014.     # <0 - not ok
  1015.     
  1016.     my $self = shift ;
  1017.  
  1018.     return G_EOF if *$self->{Closed} ;
  1019.  
  1020.     my $buffer ;
  1021.  
  1022.     if (ref $_[0] ) {
  1023.         $self->croakError(*$self->{ClassName} . "::read: buffer parameter is read-only")
  1024.             if readonly(${ $_[0] });
  1025.  
  1026.         $self->croakError(*$self->{ClassName} . "::read: not a scalar reference $_[0]" )
  1027.             unless ref $_[0] eq 'SCALAR' ;
  1028.         $buffer = $_[0] ;
  1029.     }
  1030.     else {
  1031.         $self->croakError(*$self->{ClassName} . "::read: buffer parameter is read-only")
  1032.             if readonly($_[0]);
  1033.  
  1034.         $buffer = \$_[0] ;
  1035.     }
  1036.  
  1037.     my $length = $_[1] ;
  1038.     my $offset = $_[2] || 0;
  1039.  
  1040.     if (! *$self->{AppendOutput}) {
  1041.         if (! $offset) {    
  1042.             $$buffer = '' ;
  1043.         }
  1044.         else {
  1045.             if ($offset > length($$buffer)) {
  1046.                 $$buffer .= "\x00" x ($offset - length($$buffer));
  1047.             }
  1048.             else {
  1049.                 substr($$buffer, $offset) = '';
  1050.             }
  1051.         }
  1052.     }
  1053.  
  1054.     return G_EOF if !length *$self->{Pending} && *$self->{EndStream} ;
  1055.  
  1056.     # the core read will return 0 if asked for 0 bytes
  1057.     return 0 if defined $length && $length == 0 ;
  1058.  
  1059.     $length = $length || 0;
  1060.  
  1061.     $self->croakError(*$self->{ClassName} . "::read: length parameter is negative")
  1062.         if $length < 0 ;
  1063.  
  1064.     # Short-circuit if this is a simple read, with no length
  1065.     # or offset specified.
  1066.     unless ( $length || $offset) {
  1067.         if (length *$self->{Pending}) {
  1068.             $$buffer .= *$self->{Pending} ;
  1069.             my $len = length *$self->{Pending};
  1070.             *$self->{Pending} = '' ;
  1071.             return $len ;
  1072.         }
  1073.         else {
  1074.             my $len = 0;
  1075.             $len = $self->_raw_read($buffer) 
  1076.                 while ! *$self->{EndStream} && $len == 0 ;
  1077.             return $len ;
  1078.         }
  1079.     }
  1080.  
  1081.     # Need to jump through more hoops - either length or offset 
  1082.     # or both are specified.
  1083.     my $out_buffer = *$self->{Pending} ;
  1084.  
  1085.  
  1086.     while (! *$self->{EndStream} && length($out_buffer) < $length)
  1087.     {
  1088.         my $buf_len = $self->_raw_read(\$out_buffer);
  1089.         return $buf_len 
  1090.             if $buf_len < 0 ;
  1091.     }
  1092.  
  1093.     $length = length $out_buffer 
  1094.         if length($out_buffer) < $length ;
  1095.  
  1096.     return 0 
  1097.         if $length == 0 ;
  1098.  
  1099.     $$buffer = '' 
  1100.         if ! defined $$buffer;
  1101.  
  1102.     $offset = length $$buffer
  1103.         if *$self->{AppendOutput} ;
  1104.  
  1105.     *$self->{Pending} = $out_buffer;
  1106.     $out_buffer = \*$self->{Pending} ;
  1107.  
  1108.     #substr($$buffer, $offset) = substr($$out_buffer, 0, $length, '') ;
  1109.     substr($$buffer, $offset) = substr($$out_buffer, 0, $length) ;
  1110.     substr($$out_buffer, 0, $length) =  '' ;
  1111.  
  1112.     return $length ;
  1113. }
  1114.  
  1115. sub _getline
  1116. {
  1117.     my $self = shift ;
  1118.  
  1119.     # Slurp Mode
  1120.     if ( ! defined $/ ) {
  1121.         my $data ;
  1122.         1 while $self->read($data) > 0 ;
  1123.         return \$data ;
  1124.     }
  1125.  
  1126.     # Record Mode
  1127.     if ( ref $/ eq 'SCALAR' && ${$/} =~ /^\d+$/ && ${$/} > 0) {
  1128.         my $reclen = ${$/} ;
  1129.         my $data ;
  1130.         $self->read($data, $reclen) ;
  1131.         return \$data ;
  1132.     }
  1133.  
  1134.     # Paragraph Mode
  1135.     if ( ! length $/ ) {
  1136.         my $paragraph ;    
  1137.         while ($self->read($paragraph) > 0 ) {
  1138.             if ($paragraph =~ s/^(.*?\n\n+)//s) {
  1139.                 *$self->{Pending}  = $paragraph ;
  1140.                 my $par = $1 ;
  1141.                 return \$par ;
  1142.             }
  1143.         }
  1144.         return \$paragraph;
  1145.     }
  1146.  
  1147.     # $/ isn't empty, or a reference, so it's Line Mode.
  1148.     {
  1149.         my $line ;    
  1150.         my $offset;
  1151.         my $p = \*$self->{Pending}  ;
  1152.  
  1153.         if (length(*$self->{Pending}) && 
  1154.                     ($offset = index(*$self->{Pending}, $/)) >=0) {
  1155.             my $l = substr(*$self->{Pending}, 0, $offset + length $/ );
  1156.             substr(*$self->{Pending}, 0, $offset + length $/) = '';    
  1157.             return \$l;
  1158.         }
  1159.  
  1160.         while ($self->read($line) > 0 ) {
  1161.             my $offset = index($line, $/);
  1162.             if ($offset >= 0) {
  1163.                 my $l = substr($line, 0, $offset + length $/ );
  1164.                 substr($line, 0, $offset + length $/) = '';    
  1165.                 $$p = $line;
  1166.                 return \$l;
  1167.             }
  1168.         }
  1169.  
  1170.         return \$line;
  1171.     }
  1172. }
  1173.  
  1174. sub getline
  1175. {
  1176.     my $self = shift;
  1177.     my $current_append = *$self->{AppendOutput} ;
  1178.     *$self->{AppendOutput} = 1;
  1179.     my $lineref = $self->_getline();
  1180.     $. = ++ *$self->{LineNo} if defined $$lineref ;
  1181.     *$self->{AppendOutput} = $current_append;
  1182.     return $$lineref ;
  1183. }
  1184.  
  1185. sub getlines
  1186. {
  1187.     my $self = shift;
  1188.     $self->croakError(*$self->{ClassName} . 
  1189.             "::getlines: called in scalar context\n") unless wantarray;
  1190.     my($line, @lines);
  1191.     push(@lines, $line) 
  1192.         while defined($line = $self->getline);
  1193.     return @lines;
  1194. }
  1195.  
  1196. sub READLINE
  1197. {
  1198.     goto &getlines if wantarray;
  1199.     goto &getline;
  1200. }
  1201.  
  1202. sub getc
  1203. {
  1204.     my $self = shift;
  1205.     my $buf;
  1206.     return $buf if $self->read($buf, 1);
  1207.     return undef;
  1208. }
  1209.  
  1210. sub ungetc
  1211. {
  1212.     my $self = shift;
  1213.     *$self->{Pending} = ""  unless defined *$self->{Pending} ;    
  1214.     *$self->{Pending} = $_[0] . *$self->{Pending} ;    
  1215. }
  1216.  
  1217.  
  1218. sub trailingData
  1219. {
  1220.     my $self = shift ;
  1221.  
  1222.     if (defined *$self->{FH} || defined *$self->{InputEvent} ) {
  1223.         return *$self->{Prime} ;
  1224.     }
  1225.     else {
  1226.         my $buf = *$self->{Buffer} ;
  1227.         my $offset = *$self->{BufferOffset} ;
  1228.         return substr($$buf, $offset) ;
  1229.     }
  1230. }
  1231.  
  1232.  
  1233. sub eof
  1234. {
  1235.     my $self = shift ;
  1236.  
  1237.     return (*$self->{Closed} ||
  1238.               (!length *$self->{Pending} 
  1239.                 && ( $self->smartEof() || *$self->{EndStream}))) ;
  1240. }
  1241.  
  1242. sub tell
  1243. {
  1244.     my $self = shift ;
  1245.  
  1246.     my $in ;
  1247.     if (*$self->{Plain}) {
  1248.         $in = *$self->{PlainBytesRead} ;
  1249.     }
  1250.     else {
  1251.         $in = *$self->{TotalInflatedBytesRead} ;
  1252.     }
  1253.  
  1254.     my $pending = length *$self->{Pending} ;
  1255.  
  1256.     return 0 if $pending > $in ;
  1257.     return $in - $pending ;
  1258. }
  1259.  
  1260. sub close
  1261. {
  1262.     # todo - what to do if close is called before the end of the gzip file
  1263.     #        do we remember any trailing data?
  1264.     my $self = shift ;
  1265.  
  1266.     return 1 if *$self->{Closed} ;
  1267.  
  1268.     untie *$self 
  1269.         if $] >= 5.008 ;
  1270.  
  1271.     my $status = 1 ;
  1272.  
  1273.     if (defined *$self->{FH}) {
  1274.         if ((! *$self->{Handle} || *$self->{AutoClose}) && ! *$self->{StdIO}) {
  1275.         #if ( *$self->{AutoClose}) {
  1276.             local $.; 
  1277.             $! = 0 ;
  1278.             $status = *$self->{FH}->close();
  1279.             return $self->saveErrorString(0, $!, $!)
  1280.                 if !*$self->{InNew} && $self->saveStatus($!) != 0 ;
  1281.         }
  1282.         delete *$self->{FH} ;
  1283.         $! = 0 ;
  1284.     }
  1285.     *$self->{Closed} = 1 ;
  1286.  
  1287.     return 1;
  1288. }
  1289.  
  1290. sub DESTROY
  1291. {
  1292.     my $self = shift ;
  1293.     local ($., $@, $!, $^E, $?);
  1294.  
  1295.     $self->close() ;
  1296. }
  1297.  
  1298. sub seek
  1299. {
  1300.     my $self     = shift ;
  1301.     my $position = shift;
  1302.     my $whence   = shift ;
  1303.  
  1304.     my $here = $self->tell() ;
  1305.     my $target = 0 ;
  1306.  
  1307.  
  1308.     if ($whence == SEEK_SET) {
  1309.         $target = $position ;
  1310.     }
  1311.     elsif ($whence == SEEK_CUR) {
  1312.         $target = $here + $position ;
  1313.     }
  1314.     elsif ($whence == SEEK_END) {
  1315.         $target = $position ;
  1316.         $self->croakError(*$self->{ClassName} . "::seek: SEEK_END not allowed") ;
  1317.     }
  1318.     else {
  1319.         $self->croakError(*$self->{ClassName} ."::seek: unknown value, $whence, for whence parameter");
  1320.     }
  1321.  
  1322.     # short circuit if seeking to current offset
  1323.     return 1 if $target == $here ;    
  1324.  
  1325.     # Outlaw any attempt to seek backwards
  1326.     $self->croakError( *$self->{ClassName} ."::seek: cannot seek backwards")
  1327.         if $target < $here ;
  1328.  
  1329.     # Walk the file to the new offset
  1330.     my $offset = $target - $here ;
  1331.  
  1332.     my $got;
  1333.     while (($got = $self->read(my $buffer, min($offset, *$self->{BlockSize})) ) > 0)
  1334.     {
  1335.         $offset -= $got;
  1336.         last if $offset == 0 ;
  1337.     }
  1338.  
  1339.     return $offset == 0 ? 1 : 0 ;
  1340. }
  1341.  
  1342. sub fileno
  1343. {
  1344.     my $self = shift ;
  1345.     return defined *$self->{FH} 
  1346.            ? fileno *$self->{FH} 
  1347.            : undef ;
  1348. }
  1349.  
  1350. sub binmode
  1351. {
  1352.     1;
  1353. #    my $self     = shift ;
  1354. #    return defined *$self->{FH} 
  1355. #            ? binmode *$self->{FH} 
  1356. #            : 1 ;
  1357. }
  1358.  
  1359. sub opened
  1360. {
  1361.     my $self     = shift ;
  1362.     return ! *$self->{Closed} ;
  1363. }
  1364.  
  1365. sub autoflush
  1366. {
  1367.     my $self     = shift ;
  1368.     return defined *$self->{FH} 
  1369.             ? *$self->{FH}->autoflush(@_) 
  1370.             : undef ;
  1371. }
  1372.  
  1373. sub input_line_number
  1374. {
  1375.     my $self = shift ;
  1376.     my $last = *$self->{LineNo};
  1377.     $. = *$self->{LineNo} = $_[1] if @_ ;
  1378.     return $last;
  1379. }
  1380.  
  1381.  
  1382. *BINMODE  = \&binmode;
  1383. *SEEK     = \&seek; 
  1384. *READ     = \&read;
  1385. *sysread  = \&read;
  1386. *TELL     = \&tell;
  1387. *EOF      = \&eof;
  1388.  
  1389. *FILENO   = \&fileno;
  1390. *CLOSE    = \&close;
  1391.  
  1392. sub _notAvailable
  1393. {
  1394.     my $name = shift ;
  1395.     #return sub { croak "$name Not Available" ; } ;
  1396.     return sub { croak "$name Not Available: File opened only for intput" ; } ;
  1397. }
  1398.  
  1399.  
  1400. *print    = _notAvailable('print');
  1401. *PRINT    = _notAvailable('print');
  1402. *printf   = _notAvailable('printf');
  1403. *PRINTF   = _notAvailable('printf');
  1404. *write    = _notAvailable('write');
  1405. *WRITE    = _notAvailable('write');
  1406.  
  1407. #*sysread  = \&read;
  1408. #*syswrite = \&_notAvailable;
  1409.  
  1410.  
  1411.  
  1412. package IO::Uncompress::Base ;
  1413.  
  1414.  
  1415. 1 ;
  1416. __END__
  1417.  
  1418. =head1 NAME
  1419.  
  1420. IO::Uncompress::Base - Base Class for IO::Uncompress modules 
  1421.  
  1422. =head1 SYNOPSIS
  1423.  
  1424.     use IO::Uncompress::Base ;
  1425.  
  1426. =head1 DESCRIPTION
  1427.  
  1428. This module is not intended for direct use in application code. Its sole
  1429. purpose if to to be sub-classed by IO::Unompress modules.
  1430.  
  1431. =head1 SEE ALSO
  1432.  
  1433. 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::Lzop>, L<IO::Uncompress::UnLzop>, L<IO::Compress::Lzf>, L<IO::Uncompress::UnLzf>, L<IO::Uncompress::AnyInflate>, L<IO::Uncompress::AnyUncompress>
  1434.  
  1435. L<Compress::Zlib::FAQ|Compress::Zlib::FAQ>
  1436.  
  1437. L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>,
  1438. L<Archive::Tar|Archive::Tar>,
  1439. L<IO::Zlib|IO::Zlib>
  1440.  
  1441. =head1 AUTHOR
  1442.  
  1443. This module was written by Paul Marquess, F<pmqs@cpan.org>. 
  1444.  
  1445. =head1 MODIFICATION HISTORY
  1446.  
  1447. See the Changes file.
  1448.  
  1449. =head1 COPYRIGHT AND LICENSE
  1450.  
  1451. Copyright (c) 2005-2008 Paul Marquess. All rights reserved.
  1452.  
  1453. This program is free software; you can redistribute it and/or
  1454. modify it under the same terms as Perl itself.
  1455.  
  1456.  
  1457.