This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Drom Compress::Zlib 1.34 in ext/
authorRafael Garcia-Suarez <rgarciasuarez@gmail.com>
Fri, 10 Jun 2005 12:05:38 +0000 (12:05 +0000)
committerRafael Garcia-Suarez <rgarciasuarez@gmail.com>
Fri, 10 Jun 2005 12:05:38 +0000 (12:05 +0000)
p4raw-id: //depot/perl@24786

45 files changed:
MANIFEST
ext/Compress/Zlib/ANNOUNCE [new file with mode: 0644]
ext/Compress/Zlib/Changes [new file with mode: 0644]
ext/Compress/Zlib/MANIFEST [new file with mode: 0644]
ext/Compress/Zlib/Makefile.PL [new file with mode: 0755]
ext/Compress/Zlib/README [new file with mode: 0644]
ext/Compress/Zlib/Zlib.pm [new file with mode: 0644]
ext/Compress/Zlib/Zlib.xs [new file with mode: 0644]
ext/Compress/Zlib/config.in [new file with mode: 0755]
ext/Compress/Zlib/examples/filtdef [new file with mode: 0755]
ext/Compress/Zlib/examples/filtinf [new file with mode: 0755]
ext/Compress/Zlib/examples/gzcat [new file with mode: 0755]
ext/Compress/Zlib/examples/gzgrep [new file with mode: 0755]
ext/Compress/Zlib/examples/gzstream [new file with mode: 0755]
ext/Compress/Zlib/fallback.h [new file with mode: 0644]
ext/Compress/Zlib/fallback.xs [new file with mode: 0644]
ext/Compress/Zlib/t/01version.t [new file with mode: 0644]
ext/Compress/Zlib/t/02zlib.t [new file with mode: 0644]
ext/Compress/Zlib/t/03examples.t [new file with mode: 0644]
ext/Compress/Zlib/t/04encoding.t [new file with mode: 0644]
ext/Compress/Zlib/t/05gzsetp.t [new file with mode: 0644]
ext/Compress/Zlib/t/06gzdopen.t [new file with mode: 0644]
ext/Compress/Zlib/typemap [new file with mode: 0644]
ext/Compress/Zlib/zlib-src-1.2.2/adler32.c [new file with mode: 0644]
ext/Compress/Zlib/zlib-src-1.2.2/compress.c [new file with mode: 0644]
ext/Compress/Zlib/zlib-src-1.2.2/crc32.c [new file with mode: 0644]
ext/Compress/Zlib/zlib-src-1.2.2/crc32.h [new file with mode: 0644]
ext/Compress/Zlib/zlib-src-1.2.2/deflate.c [new file with mode: 0644]
ext/Compress/Zlib/zlib-src-1.2.2/deflate.h [new file with mode: 0644]
ext/Compress/Zlib/zlib-src-1.2.2/gzio.c [new file with mode: 0644]
ext/Compress/Zlib/zlib-src-1.2.2/infback.c [new file with mode: 0644]
ext/Compress/Zlib/zlib-src-1.2.2/inffast.c [new file with mode: 0644]
ext/Compress/Zlib/zlib-src-1.2.2/inffast.h [new file with mode: 0644]
ext/Compress/Zlib/zlib-src-1.2.2/inffixed.h [new file with mode: 0644]
ext/Compress/Zlib/zlib-src-1.2.2/inflate.c [new file with mode: 0644]
ext/Compress/Zlib/zlib-src-1.2.2/inflate.h [new file with mode: 0644]
ext/Compress/Zlib/zlib-src-1.2.2/inftrees.c [new file with mode: 0644]
ext/Compress/Zlib/zlib-src-1.2.2/inftrees.h [new file with mode: 0644]
ext/Compress/Zlib/zlib-src-1.2.2/trees.c [new file with mode: 0644]
ext/Compress/Zlib/zlib-src-1.2.2/trees.h [new file with mode: 0644]
ext/Compress/Zlib/zlib-src-1.2.2/uncompr.c [new file with mode: 0644]
ext/Compress/Zlib/zlib-src-1.2.2/zconf.h [new file with mode: 0644]
ext/Compress/Zlib/zlib-src-1.2.2/zlib.h [new file with mode: 0644]
ext/Compress/Zlib/zlib-src-1.2.2/zutil.c [new file with mode: 0644]
ext/Compress/Zlib/zlib-src-1.2.2/zutil.h [new file with mode: 0644]

index 2e5af00..fd78a2a 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -149,6 +149,50 @@ ext/Cwd/ppport.h           portability header for Cwd
 ext/Cwd/t/cwd.t                        See if Cwd works
 ext/Cwd/t/taint.t              See if Cwd works with taint
 ext/Cwd/t/win32.t              See if Cwd works on Win32
+ext/Compress/Zlib/ANNOUNCE     Compress::Zlib
+ext/Compress/Zlib/MANIFEST     Compress::Zlib
+ext/Compress/Zlib/Makefile.PL  Compress::Zlib
+ext/Compress/Zlib/README       Compress::Zlib
+ext/Compress/Zlib/Changes      Compress::Zlib
+ext/Compress/Zlib/Zlib.pm      Compress::Zlib
+ext/Compress/Zlib/Zlib.xs      Compress::Zlib
+ext/Compress/Zlib/config.in    Compress::Zlib
+ext/Compress/Zlib/examples/filtdef     Compress::Zlib
+ext/Compress/Zlib/examples/filtinf     Compress::Zlib
+ext/Compress/Zlib/examples/gzcat       Compress::Zlib
+ext/Compress/Zlib/examples/gzgrep      Compress::Zlib
+ext/Compress/Zlib/examples/gzstream    Compress::Zlib
+ext/Compress/Zlib/fallback.h           Compress::Zlib
+ext/Compress/Zlib/fallback.xs          Compress::Zlib
+ext/Compress/Zlib/t/01version.t                Compress::Zlib
+ext/Compress/Zlib/t/02zlib.t           Compress::Zlib
+ext/Compress/Zlib/t/03examples.t       Compress::Zlib
+ext/Compress/Zlib/t/04encoding.t       Compress::Zlib
+ext/Compress/Zlib/t/05gzsetp.t         Compress::Zlib
+ext/Compress/Zlib/t/06gzdopen.t                Compress::Zlib
+ext/Compress/Zlib/typemap              Compress::Zlib
+ext/Compress/Zlib/zlib-src-1.2.2/adler32.c     Compress::Zlib
+ext/Compress/Zlib/zlib-src-1.2.2/compress.c    Compress::Zlib
+ext/Compress/Zlib/zlib-src-1.2.2/crc32.c       Compress::Zlib
+ext/Compress/Zlib/zlib-src-1.2.2/crc32.h       Compress::Zlib
+ext/Compress/Zlib/zlib-src-1.2.2/deflate.c     Compress::Zlib
+ext/Compress/Zlib/zlib-src-1.2.2/deflate.h     Compress::Zlib
+ext/Compress/Zlib/zlib-src-1.2.2/gzio.c                Compress::Zlib
+ext/Compress/Zlib/zlib-src-1.2.2/infback.c     Compress::Zlib
+ext/Compress/Zlib/zlib-src-1.2.2/inffast.c     Compress::Zlib
+ext/Compress/Zlib/zlib-src-1.2.2/inffast.h     Compress::Zlib
+ext/Compress/Zlib/zlib-src-1.2.2/inffixed.h    Compress::Zlib
+ext/Compress/Zlib/zlib-src-1.2.2/inflate.c     Compress::Zlib
+ext/Compress/Zlib/zlib-src-1.2.2/inflate.h     Compress::Zlib
+ext/Compress/Zlib/zlib-src-1.2.2/inftrees.c    Compress::Zlib
+ext/Compress/Zlib/zlib-src-1.2.2/inftrees.h    Compress::Zlib
+ext/Compress/Zlib/zlib-src-1.2.2/trees.c       Compress::Zlib
+ext/Compress/Zlib/zlib-src-1.2.2/trees.h       Compress::Zlib
+ext/Compress/Zlib/zlib-src-1.2.2/uncompr.c     Compress::Zlib
+ext/Compress/Zlib/zlib-src-1.2.2/zconf.h       Compress::Zlib
+ext/Compress/Zlib/zlib-src-1.2.2/zlib.h                Compress::Zlib
+ext/Compress/Zlib/zlib-src-1.2.2/zutil.c       Compress::Zlib
+ext/Compress/Zlib/zlib-src-1.2.2/zutil.h       Compress::Zlib
 ext/Data/Dumper/Changes                Data pretty printer, changelog
 ext/Data/Dumper/Dumper.pm      Data pretty printer, module
 ext/Data/Dumper/Dumper.xs      Data pretty printer, externals
diff --git a/ext/Compress/Zlib/ANNOUNCE b/ext/Compress/Zlib/ANNOUNCE
new file mode 100644 (file)
index 0000000..5bb34cd
--- /dev/null
@@ -0,0 +1,51 @@
+                          Compress::Zlib - 1.00
+
+Announcing release 1.00 of Compress::Zlib (formerly known as Zip
+in the module list).
+
+What is Compress::Zlib?
+=======================
+
+Compress::Zlib is a Perl external module which provides an interface to
+the info-zip zlib compression library. zlib is a general purpose
+compression library.
+
+Some of the features provided by Compress::Zlib include:
+
+   * in-memory compression and decompression
+   * read and write gzip (.gz) files directly.
+
+By way of an example here is a small script which reads gzipped files
+and writes the unzipped output to standard output.
+
+
+    use Compress::Zlib ;
+
+    die "Usage: gzcat file...\n"
+        unless @ARGV ;
+    
+    foreach $file (@ARGV) {
+        $gz = gzopen($file, "rb") 
+             or die "Cannot open $file: $gzerrno\n" ;
+    
+        print $buffer while $gz->gzread($buffer) > 0 ;
+    
+        die "Error reading from $file: $gzerrno\n" if $gzerrno ;
+        
+        $gz->gzclose() ;
+    }
+    
+
+Availability
+============
+
+The latest copy of Compress::ZLib is available on CPAN
+
+    http://www.cpan.org/modules/by-module/Archive/Archive-Zip-*.tar.gz
+
+and zlib is available at
+
+    http://www.gzip.org/zlib/
+
+
+Paul Marquess
diff --git a/ext/Compress/Zlib/Changes b/ext/Compress/Zlib/Changes
new file mode 100644 (file)
index 0000000..617cc1b
--- /dev/null
@@ -0,0 +1,329 @@
+CHANGES
+-------
+
+  1.34 - 30 January 2005
+
+      * Fixed typo in the README
+
+      * Fixed examples.t on Win32 where paths have embedded whitespace.
+
+      * Fix for Cygwin and core integration from Jos I. Boumans
+
+      * Upgrade zlib source to 1.2.2
+
+  1.33 - 14 January 2004
+
+      * Reworked Makefile.PL to avoid creating a private copy of zlib. 
+        This both simplifies the build, plus it makes life easier for VMS.
+
+      * Patches for Makefile.PL to get it to work on VMS supplied by
+        Craig A. Berry.
+
+      * memGunzip has very slow on FreeBSD. Turns out to be down to
+        the way realloc works on FreeBSD. Changed both inflate & deflate
+        to use exponentially increasing buffer sizes when they need to
+        realloc. Thanks to Peter Jeremy for the lowdown on FreeBSD
+        memory allocation.
+
+  1.32 - 26 November 2003
+
+      * Steve Hay reported a problem on rt.cpan.org with Windows and
+        MSCV++ 6.0 where the source from the zlib directory was getting
+        installed with the rest of the module.
+        https://rt.cpan.org/Ticket/Display.html?id=1741
+
+        This has been fixed by renaming the "zlib" directory to "zlib-src"
+        thus avoiding a conflict with the name of this Perl module.
+
+      * Fixed a bug in the inflate method where the input buffer is an
+        lvalue (via substr). Problem & solution reported by Salvador Fandiqo.
+
+      * Tightened up the logic in Makefile.PL when BUILD_ZLIB is
+        True. Issue spotted by Ralf S. Engelschall.
+
+  1.31 - 29 October 2003
+
+      * Reinstated the creation of .bak files - $^I seems to need a
+        backup file on Windows. For OpenVMS, the extenstion _bak is used.
+
+  1.30 - 28 October 2003
+
+      * Bundled a sub-set of the zlib source with the module and changed
+        the default make behaviour to build with the included zlib source.
+        The previous behaviour of using a pre-built zlib library is
+        still available for those that want it.
+
+      * Added prototypes to the subs in Zlib.pm that didn't already have
+        them. Patch from Ed Avis.
+
+      * No .bak files are created by Makefile.PL any more - this keep
+        distclean much happier. Patch suggested by Ed Avis.
+        This also fixes a similar problem reported by Dr. Martin Zinser
+        on OpenVMS.
+
+      * Documentation for some of the gz functions updated.
+
+      * Format strings modified in DispStream to keep OpenVMS happy. 
+        Problem reported by Dr. Martin Zinser.
+
+
+  1.22 - 17 June 2003
+
+      * Makefile.PL now displays a warning about not installing
+        Compress::Zlib via the CPAN shell.
+
+      * Fix to allow intermingling of gzread & gzreadline - patch
+        supplied by Doug Perham.
+
+      * memGunzip will silently now work if the gzip trailer is
+        missing. Some HTTP Origin Servers seem to leave it out.
+
+  1.21 - 28 April 2003
+
+      * Tests 148 & 150 from t/02zlib.t were failing on redhat 9. 
+
+      * Added a few words about the problems with Mac OS X to the README file. 
+
+  1.20 - 4 April 2003
+
+      * Fixed bug in gzopen where $gzerrno wasn't being set correctly.
+        The symptom was $gzerrno was set to Z_MEM_ERROR although the file 
+       was opened ok. If gzopen failed, $gzerrno was being set correctly.
+       This problem wasn't spotted before because the typical test
+       to determine whether gzopen passed or failed was to check its
+       return value. 
+
+  1.19 - 31 October 2002
+
+      * fixed a problem with t/02zlib.t that was failing with redhat 8.
+
+  1.18 - 24 October 2002
+
+      * fixed a Win32 problem in t/02zlib.t by changing sysread to read.
+
+      * zlib 1.0.5 & older doesn't have gzsetparams & gzeof. Added a new
+        variable to config.in to flag an old version of zlib. Split
+        out the tests for gzsetparams into t/05gzsetp.t
+
+  1.17 - 22 October 2002
+
+      * Moved the test to check the versions of libz & zlib.h into a separate
+        file and added troubleshooting notes to README.
+
+      * In gzopen, only attempt to call "tell" for normal files.
+
+      * Broke changes out of README into Changes file.
+
+      * Replaced internal use of Z_PARTIAL_FLUSH symbol with Z_SYNC_FLUSH. 
+        zlib.h says  /* will be removed, use Z_SYNC_FLUSH instead */  
+
+      * Added support for zlib functions inflateSync and deflateParams.
+
+      * Added support for zlib functions gzeof and gzsetparams.
+
+      * Added support for access to adler, total_in & total_out
+
+      * The compress function can now take an optional parameter that
+        allows the compression level to be specified. This mirrors the
+        compress2 function available in zlib.
+
+      * memGzip doesn't work properly with perl 5.8.0 when it is given
+        UTF-8 data. Bug spotted by Andreas J. Koenig.
+
+      * Added note about Linux zlib-devel RPM to README.
+
+      * Fixed recursive build problem on win32 machines.
+
+      * Fixed problem with the test harness on Mac OS X.
+        Thanks to Carl Johan Berglund for reporting the problem and
+        helping track it down.
+
+
+  1.16 - 13 December 2001
+
+      * Fixed bug in Makefile.PL that stopped "perl Makefile.PL PREFIX=..."
+        working.
+
+  1.15 - 4th December 2001
+
+      * Changes a few types to get the module to build on 64-bit Solaris
+
+      * Changed the up/downgrade logic to default to the older constructs, and
+        to only call a downgrade if specifically requested. Some older versions
+        of Perl were having problems with the in-place edit.
+
+      * added the new XS constant code.
+
+  1.14 - 27th August 2001
+
+      * Memory overwrite bug fixed in "inflate". Kudos to Rob Simons for
+        reporting the bug and to Anton Berezin for fixing it for me.
+
+  1.13 - 31st June 2001
+
+      * Make sure config.in is consistant when released.
+
+  1.12 - 28th April 2001
+
+      * Modified Makefile.PL to only enable the warnings pragma if
+        using perl 5.6.1 or better.
+
+  1.11 - 17th February 2001
+
+      * Added logic in Makefile.PL to toggle between using $^W and
+        the warnings pragma in the module.
+
+      * The module, the examples & the test harness are now all strict
+        & warnings clean.
+
+  1.10 - 5th February 2001
+
+      * fixed a bug in memGunzip. Used Z_ERR instead of Z_DATA_ERROR.
+
+  1.09 - 15th January 2001
+
+      * Silenced a few compiler warnings.
+
+      * Updated zlib home site in README & Zlib.pm to www.info-zip.org
+
+      * Minor typo in Zlib.pm - a link used AUTHORS instead of AUTHOR
+        -- spotted by Frank Martini.
+
+      * Mention Archive::Zip
+
+      * added memGunzip. This is largely based on code provided by Jim Leonard.
+
+      * $deflate->flush can now take an optional parameter. Valid
+        values are Z_NO_FLUSH, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, Z_FULL_FLUSH
+        and Z_FINISH. The default is Z_FINISH.
+
+  1.08 - 6 Jan 2000
+
+      * uncompress was clobbering its input parameter. Now it doesn't.
+        This bug was spotted by Deven T. Corzine.
+      * If a variable that only ever contained a number was given
+        to compress or deflate, it would not be compressed properly. Now
+        it will be coerced to a string and then compressed. This bug
+        was spotted by Deven T. Corzine.
+
+  1.07 - 27 Nov 1999
+
+      * ANSI-ified the static functions in Zlib.xs
+
+      * Added the ability to build zlib along with the module.
+        This feature is 90% based on a Makefile provided by Gurusamy
+        Sarathy.
+
+  1.06 - 20 Sep 1999
+
+      * Fixed a nasty problem where inflate could truncate the data
+        returned. Thanks to Douglas Thomson <dougt@mugc.cc.monash.edu.au>
+        for both spotting the problem and fixing the bug.
+
+      * Added a note about the undocumented features in zlib that are
+        required when accessing zip files.
+
+      * gzclose will now get called automatically when the gzip object is
+        destroyed.
+
+  1.05 - 3 June 1999
+
+      * Previous release used newSVpvn, which doesn't exist in 5.004_04
+        or earlier. Changed to use newSVpv instead.
+
+      * The module needs Perl 5.004 or better, so updated the version
+        checking in Zlib.pm and Makefile.PL
+
+  1.04 - 27 May 1999
+
+      * Bug 19990527.001: compress(undef) core dumps -- Fixed. 
+
+  1.03 - 17 Mar 1999
+
+      * Updated to use the new PL_ symbols. 
+        Means the module can be built with Perl 5.005_5*
+
+  1.02 - 31 Jan 1999
+
+      * The return codes for gzread, gzreadline and gzwrite were
+        documented incorrectly as returning a status code.
+
+      * The test harness was missing a "gzclose". This caused problem
+        showed up on an amiga. Thanks to Erik van Roode for reporting
+        this one.
+
+      * Patched zlib.t for OS/2. Thanks to Ilya Zakharevich for the patch.
+
+  1.01 - 23 Nov 1997
+
+      * A number of fixes to the test suite and the example scripts to
+       allow them to work under win32. All courtesy of Gurusamy
+       Sarathy.
+
+  1.00 - 14 Nov 1997
+
+      * Fixed crc32 & adler32. They were very broken. 
+
+      * The following functions can now take a scalar reference in
+       place of a scalar for their buffer parameters:
+
+           compress
+           uncompress
+           deflate
+           inflate
+           crc32
+           adler32
+       This should mean applications that make use of the module don't
+       have to copy large buffers around.
+
+      * Normally the inflate method consumes I<all> of the input buffer
+       before returning. The exception to this is when inflate detects
+       the end of the stream (Z_STREAM_END). In this case the input
+       buffer need not be completely consumed. To allow processing of
+       file formats that embed a deflation stream (e.g. zip, gzip),
+       the inflate method now sets the buffer parameter to be what
+       remains after inflation.
+
+       When the return status is Z_STREAM_END, it will be what remains
+       of the buffer (if any) after deflation. When the status is Z_OK
+       it will be an empty string.
+
+       This change means that the buffer parameter must be a lvalue.
+      * Fixed crc32 and adler32. They were both very broken.
+
+      * Added the Compress::Zlib::memGzip function.
+
+  0.5 - Confirmed that no changes were necessary for zlib 1.0.3, or 1.0.4.
+
+       The optional parameters for deflateInit and inflateInit can now
+       be specified as an associative array in addition to a reference
+       to an associative array. They can also accept the -Name
+       syntax.
+
+       gzopen can now optionally take a reference to an open
+       filehandle in place of a filename. In this case it will call
+       gzdopen.
+
+       Added gzstream example script.
+  0.4 - Upgrade to support zlib 0.99 
+
+       Added dictionary interface.
+
+       Fixed bug in gzreadline - previously it would keep returning
+       the same buffer. This bug was reported by Helmut Jarausch
+
+       Removed dependency to zutil.h and so dropped support for 
+       
+           DEF_MEM_LEVEL (use MAX_MEM_LEVEL instead)
+           DEF_WBITS     (use MAX_WBITS instead)
+
+  0.3 - Added prototype specification.
+
+  0.2 - Fixed a minor allocation problem in Zlib.xs
+
+  0.1 - first alpha release. 2nd October 1995
diff --git a/ext/Compress/Zlib/MANIFEST b/ext/Compress/Zlib/MANIFEST
new file mode 100644 (file)
index 0000000..e7d7271
--- /dev/null
@@ -0,0 +1,45 @@
+ANNOUNCE
+MANIFEST
+Makefile.PL
+README
+Changes
+Zlib.pm
+Zlib.xs
+config.in
+examples/filtdef
+examples/filtinf
+examples/gzcat
+examples/gzgrep
+examples/gzstream
+fallback.h
+fallback.xs
+t/01version.t
+t/02zlib.t
+t/03examples.t
+t/04encoding.t
+t/05gzsetp.t
+t/06gzdopen.t
+typemap
+zlib-src-1.2.2/adler32.c
+zlib-src-1.2.2/compress.c
+zlib-src-1.2.2/crc32.c
+zlib-src-1.2.2/crc32.h
+zlib-src-1.2.2/deflate.c
+zlib-src-1.2.2/deflate.h
+zlib-src-1.2.2/gzio.c
+zlib-src-1.2.2/infback.c
+zlib-src-1.2.2/inffast.c
+zlib-src-1.2.2/inffast.h
+zlib-src-1.2.2/inffixed.h
+zlib-src-1.2.2/inflate.c
+zlib-src-1.2.2/inflate.h
+zlib-src-1.2.2/inftrees.c
+zlib-src-1.2.2/inftrees.h
+zlib-src-1.2.2/trees.c
+zlib-src-1.2.2/trees.h
+zlib-src-1.2.2/uncompr.c
+zlib-src-1.2.2/zconf.h
+zlib-src-1.2.2/zlib.h
+zlib-src-1.2.2/zutil.c
+zlib-src-1.2.2/zutil.h
+META.yml                                 Module meta-data (added by MakeMaker)
diff --git a/ext/Compress/Zlib/Makefile.PL b/ext/Compress/Zlib/Makefile.PL
new file mode 100755 (executable)
index 0000000..2ffe575
--- /dev/null
@@ -0,0 +1,433 @@
+#! perl -w
+
+use strict ;
+require 5.004 ;
+
+use ExtUtils::MakeMaker 5.16 ;
+use Config ;
+use File::Copy ;
+
+BEGIN
+{
+    eval { require File::Spec::Functions ; File::Spec::Functions->import() } ;
+    if ($@)
+    {
+        *catfile = sub { return "$_[0]/$_[1]" }
+    }
+}
+
+require VMS::Filespec if $^O eq 'VMS';
+
+my $ZLIB_LIB ;
+my $ZLIB_INCLUDE ;
+my $BUILD_ZLIB = 0 ;
+my $OLD_ZLIB = '' ;
+my $WALL = '';
+#$WALL = ' -Wall ';
+
+# don't ask if MM_USE_DEFAULT is set -- enables perl core building on cygwin
+if ($^O =~ /cygwin/i and not $ENV{PERL_MM_USE_DEFAULT})
+{
+    print <<EOM ;
+
+I see you are running Cygwin.
+
+Please note that this module cannot be installed on Cygwin using the
+CPAN shell. The CPAN Shell uses Compress::Zlib internally and it is not
+possible to delete an active DLL.
+
+If you are running the CPAN shell, please exit it and install this module
+by hand by running 'make install' under the directory
+
+    ~/.cpan/build/Compress-Zlib-VERSION
+
+EOM
+
+    print "Do you want to continue? [Y/N]: " ;
+    my $answer = <STDIN> ;
+
+    if ($answer =~ /^yes|y/i)
+    {
+       print "continuing...\n" 
+    }
+    else
+    {
+       print "exiting...\n" ;
+       exit 1 ;
+    }
+
+
+}
+
+ParseCONFIG() ;
+
+my @files = ('Zlib.pm', glob("t/*.t"), grep(!/\.bak$/,  glob("examples/*"))) ;
+UpDowngrade(@files);
+
+WriteMakefile( 
+       NAME            => 'Compress::Zlib',
+       VERSION_FROM    => 'Zlib.pm',
+       INC             => "-I$ZLIB_INCLUDE" ,
+       DEFINE          => "$OLD_ZLIB $WALL" ,
+       XS              => { 'Zlib.xs'    => 'Zlib.c' },
+       'depend'        => { 'Makefile'   => 'config.in' },
+       'clean'         => { FILES        => '*.c constants.h constants.xs' },
+       'dist'          => { COMPRESS     => 'gzip', 
+                            SUFFIX       => 'gz',
+                            DIST_DEFAULT => 'MyDoubleCheck Downgrade tardist',
+                           },
+       ($BUILD_ZLIB
+          ? zlib_files($ZLIB_LIB)
+         : (LIBS       => [ "-L$ZLIB_LIB -lz " ])
+       ),  
+       ($] >= 5.005
+           ? (ABSTRACT_FROM    => 'Zlib.pm',
+              AUTHOR  => 'Paul Marquess <pmqs@cpan.org>')
+           : ()
+       ),
+    ) ;
+
+my @names = qw(
+
+       DEF_WBITS
+        MAX_MEM_LEVEL
+       MAX_WBITS
+       OS_CODE
+
+       Z_ASCII
+       Z_BEST_COMPRESSION
+       Z_BEST_SPEED
+       Z_BINARY
+       Z_BUF_ERROR
+       Z_DATA_ERROR
+       Z_DEFAULT_COMPRESSION
+       Z_DEFAULT_STRATEGY
+        Z_DEFLATED
+       Z_ERRNO
+       Z_FILTERED
+       Z_FINISH
+       Z_FULL_FLUSH
+       Z_HUFFMAN_ONLY
+       Z_MEM_ERROR
+       Z_NEED_DICT
+       Z_NO_COMPRESSION
+       Z_NO_FLUSH
+       Z_NULL
+       Z_OK
+       Z_PARTIAL_FLUSH
+       Z_STREAM_END
+       Z_STREAM_ERROR
+       Z_SYNC_FLUSH
+       Z_UNKNOWN
+       Z_VERSION_ERROR
+       );
+
+if (eval {require ExtUtils::Constant; 1}) {
+    # Check the constants above all appear in @EXPORT in Zlib.pm
+    my %names = map { $_, 1} @names, 'ZLIB_VERSION';
+    open F, "<Zlib.pm" or die "Cannot open Zlib.pm: $!\n";
+    while (<F>)
+    {
+        last if /^\s*\@EXPORT\s+=\s+qw\(/ ;
+    }
+
+    while (<F>)
+    {
+        last if /^\s*\)/ ;
+        /(\S+)/ ;
+        delete $names{$1} if defined $1 ;
+    }
+    close F ;
+
+    if ( keys %names )
+    {
+        my $missing = join ("\n\t", sort keys %names) ;
+        die "The following names are missing from \@EXPORT in Zlib.pm\n" .
+            "\t$missing\n" ;
+    }
+    
+    push @names, {name => 'ZLIB_VERSION', type => 'PV' };
+
+    ExtUtils::Constant::WriteConstants(
+                                     NAME => 'Zlib',
+                                     NAMES => \@names,
+                                     C_FILE  => 'constants.h',
+                                     XS_FILE  => 'constants.xs',
+                                                                       
+                                    );
+} 
+else {
+    copy ('fallback.h', 'constants.h')
+      or die "Can't copy fallback.h to constants.h: $!";
+    copy ('fallback.xs', 'constants.xs')
+      or die "Can't copy fallback.xs to constants.xs: $!";
+}
+
+sub MY::postamble 
+{
+    my $postamble = <<'EOM';
+
+Downgrade:
+       @echo Downgrading.
+       perl Makefile.PL -downgrade
+
+MyDoubleCheck: 
+       @echo Checking config.in is setup for a release
+       @(grep '^LIB *= *./zlib' config.in &&                   \
+         grep '^INCLUDE *= *./zlib' config.in &&               \
+         grep '^OLD_ZLIB *= *False' config.in &&               \
+         grep '^BUILD_ZLIB *= *True' config.in) >/dev/null ||  \
+       (echo config.in needs fixing ; exit 1)
+       @echo config.in is ok
+
+MyTrebleCheck:
+       @echo Checking for $$^W in files: '. "@files" . '
+       @perl -ne \'                                            \
+           exit 1 if /^\s*local\s*\(\s*\$$\^W\s*\)/;           \
+         \' ' . " @files || " . '                              \
+       (echo found unexpected $$^W ; exit 1)
+       @echo All is ok.
+
+Zlib.xs:       typemap
+       @$(TOUCH) Zlib.xs
+
+EOM
+
+    return $postamble;
+
+}
+
+sub ParseCONFIG
+{
+    my ($k, $v) ;
+    my @badkey = () ;
+    my %Info = () ;
+    my @Options = qw( INCLUDE LIB BUILD_ZLIB OLD_ZLIB ) ;
+    my %ValidOption = map {$_, 1} @Options ;
+    my %Parsed = %ValidOption ;
+    my $CONFIG = 'config.in' ;
+
+    print "Parsing $CONFIG...\n" ;
+
+    open(F, "<$CONFIG") or die "Cannot open file $CONFIG: $!\n" ;
+    while (<F>) {
+       s/^\s*|\s*$//g ;
+       next if /^\s*$/ or /^\s*#/ ;
+       s/\s*#\s*$// ;
+
+       ($k, $v) = split(/\s+=\s+/, $_, 2) ;
+       $k = uc $k ;
+       if ($ValidOption{$k}) {
+           delete $Parsed{$k} ;
+           $Info{$k} = $v ;
+       }
+       else {
+           push(@badkey, $k) ;
+       }
+    }
+    close F ;
+
+    print "Unknown keys in $CONFIG ignored [@badkey]\n"
+       if @badkey ;
+
+    # check parsed values
+    my @missing = () ;
+    die "The following keys are missing from $CONFIG  [@missing]\n" 
+        if @missing = keys %Parsed ;
+
+    $ZLIB_INCLUDE = $ENV{'ZLIB_INCLUDE'} || $Info{'INCLUDE'} ;
+    $ZLIB_LIB = $ENV{'ZLIB_LIB'} || $Info{'LIB'} ;
+
+    if ($^O eq 'VMS') {
+        $ZLIB_INCLUDE = VMS::Filespec::vmspath($ZLIB_INCLUDE);
+        $ZLIB_LIB = VMS::Filespec::vmspath($ZLIB_LIB);
+    }
+
+    my $y = $ENV{'OLD_ZLIB'} || $Info{'OLD_ZLIB'} ;
+    $OLD_ZLIB = '-DOLD_ZLIB' if $y and $y =~ /^yes|on|true|1$/i;
+
+    my $x = $ENV{'BUILD_ZLIB'} || $Info{'BUILD_ZLIB'} ;
+
+    if ($x and $x =~ /^yes|on|true|1$/i ) {
+
+        $BUILD_ZLIB = 1 ;
+
+       # ZLIB_LIB & ZLIB_INCLUDE must point to the same place when 
+       # BUILD_ZLIB is specified.
+       die "INCLUDE & LIB must be the same when BUILD_ZLIB is True\n"
+           if $ZLIB_LIB ne $ZLIB_INCLUDE ;
+
+       # Check the zlib source directory exists
+       die "LIB/INCLUDE directory '$ZLIB_LIB' does not exits\n"
+          unless -d $ZLIB_LIB ;
+
+       # check for a well known file
+       die "LIB/INCLUDE directory, '$ZLIB_LIB', doesn't seem to have the zlib source files\n"
+          unless -e catfile($ZLIB_LIB, 'zlib.h') ;
+
+
+       # check Makefile.zlib has been copied to ZLIB_LIB
+    #copy 'Makefile.zlib', catfile($ZLIB_LIB, 'Makefile.PL') ||
+    #die "Could not copy Makefile.zlib to " . catfile($ZLIB_LIB, 'Makefile.PL') . ": $!\n" ;
+       #print "Created a Makefile.PL for zlib\n" ;
+       
+       # write the Makefile
+       print "Building Zlib enabled\n" ;
+    }
+
+    print <<EOM if 0 ;
+    INCLUDE    [$ZLIB_INCLUDE]
+    LIB                [$ZLIB_LIB]
+
+EOM
+
+    print "Looks Good.\n" ;
+
+}
+
+sub UpDowngrade
+{
+    my @files = @_ ;
+
+    # our      is stable from 5.6.0 onward
+    # warnings is stable from 5.6.1 onward
+
+    # Note: this code assumes that each statement it modifies is not
+    #       split across multiple lines.
+
+
+    my $warn_sub = '';
+    my $our_sub = '' ;
+
+    my $opt = shift @ARGV || '' ;
+    my $upgrade = ($opt =~ /^-upgrade/i);
+    my $downgrade = ($opt =~ /^-downgrade/i);
+    push @ARGV, $opt unless $downgrade || $upgrade;
+
+    if ($downgrade) {
+        # From: use|no warnings "blah"
+        # To:   local ($^W) = 1; # use|no warnings "blah"
+        $warn_sub = sub {
+           s/^(\s*)(no\s+warnings)/${1}local (\$^W) = 0; #$2/ ;
+           s/^(\s*)(use\s+warnings)/${1}local (\$^W) = 1; #$2/ ;
+          };
+    }
+    elsif ($] >= 5.006001 || $upgrade) {
+        # From: local ($^W) = 1; # use|no warnings "blah"
+        # To:   use|no warnings "blah"
+        $warn_sub = sub {
+           s/^(\s*)local\s*\(\$\^W\)\s*=\s*\d+\s*;\s*#\s*((no|use)\s+warnings.*)/$1$2/ ;
+          };
+    }
+
+    if ($downgrade) {
+        $our_sub = sub {
+           if ( /^(\s*)our\s+\(\s*([^)]+\s*)\)/ ) {
+                my $indent = $1;
+                my $vars = join ' ', split /\s*,\s*/, $2;
+                $_ = "${indent}use vars qw($vars);\n";
+            }
+          };
+    }
+    elsif ($] >= 5.006000 || $upgrade) {
+        $our_sub = sub {
+           if ( /^(\s*)use\s+vars\s+qw\((.*?)\)/ ) {
+                my $indent = $1;
+                my $vars = join ', ', split ' ', $2;
+                $_ = "${indent}our ($vars);\n";
+            }
+          };
+    }
+
+    if (! $our_sub && ! $warn_sub) {
+        warn "Up/Downgrade not needed.\n";
+       if ($upgrade || $downgrade)
+          { exit 0 }
+        else
+          { return }
+    }
+
+    foreach (@files)
+      { doUpDown($our_sub, $warn_sub, $_) }
+
+    warn "Up/Downgrade complete.\n" ;
+    exit 0 if $upgrade || $downgrade;
+
+}
+
+
+sub doUpDown
+{
+    my $our_sub = shift;
+    my $warn_sub = shift;
+
+    local ($^I) = ($^O eq 'VMS') ? "_bak" : ".bak";
+    local (@ARGV) = shift;
+
+    while (<>)
+    {
+       print, last if /^__(END|DATA)__/ ;
+
+       &{ $our_sub }() if $our_sub ;
+       &{ $warn_sub }() if $warn_sub ;
+       print ;
+    }
+
+    return if eof ;
+
+    while (<>)
+      { print }
+}
+
+
+sub zlib_files
+{
+    my $dir = shift ;
+
+    my @h_files = ();
+    my @c_files = ();
+    
+    if (-f catfile($dir, "infback.c")) {
+        # zlib 1.2.0 or greater
+        #
+        @h_files = qw(crc32.h    inffast.h inflate.h  trees.h    zconf.in.h 
+                 zutil.h    deflate.h inffixed.h inftrees.h zconf.h  
+                 zlib.h 
+                );
+        @c_files = qw(adler32  crc32   infback  inflate  uncompr
+                 compress deflate gzio     inffast  inftrees  
+                 trees    zutil 
+                );
+    }
+    else {
+        # zlib 1.1.x
+    
+        @h_files = qw(deflate.h  infcodes.h inftrees.h zconf.h zutil.h
+                 infblock.h inffast.h  infutil.h  zlib.h
+                );
+        @c_files = qw(adler32  compress crc32    gzio    uncompr
+                 deflate  trees    zutil    inflate infblock
+                 inftrees infcodes infutil  inffast
+                );
+    }
+    
+    @h_files = map { catfile($dir, $_)  } @h_files ;
+    my @o_files = map { "$_\$(OBJ_EXT)" } 'Zlib', @c_files;
+    @c_files = map { "$_.c" } 'Zlib', @c_files ;
+
+    foreach my $file (@c_files)
+      { copy(catfile($dir, $file), '.') }
+    
+    return (
+        #'H'         =>  [ @h_files ],
+       'C'         =>  [ @c_files ] ,
+        #'OBJECT'    => qq[ @o_files ],
+        'OBJECT'    => q[ $(O_FILES) ],
+        
+
+           ) ;
+}
+
+
+# end of file Makefile.PL
+
diff --git a/ext/Compress/Zlib/README b/ext/Compress/Zlib/README
new file mode 100644 (file)
index 0000000..8b899bf
--- /dev/null
@@ -0,0 +1,406 @@
+                                 Compress::Zlib
+
+                                  Version 1.34
+
+                                 30 January 2005
+
+             Copyright (c) 1995-2005 Paul Marquess. All rights reserved.
+            This program is free software; you can redistribute it and/or
+                modify it under the same terms as Perl itself.
+
+         The directory zlib-src contains a subset of the source files copied 
+          directly from zlib version 1.2.2.  These files are Copyright(C) 
+                   1995-2004 Jean-loup Gailly and Mark Adler.
+                 Full source for the zlib library is available at 
+                             http://www.zlib.org
+
+
+DESCRIPTION
+-----------
+
+This module provides a Perl interface to most of the zlib compression
+library.  For more details see the pod documentation embedded in the
+file Zlib.pm.
+
+If you have downloaded this module in the expectation of manipulating the
+contents of .zip files, you will need to fetch and build the Archive::Zip
+module below once you have installed this one.
+
+    http://www.cpan.org/modules/by-module/Archive/Archive-Zip-*.tar.gz
+
+
+PREREQUISITES
+-------------
+
+Before you can build Compress::Zlib you need to have the following
+installed on your system:
+
+    * A C compiler
+
+    * Perl 5.004 or better. 
+
+By default, Compress::Zlib will build its own private copy of the zlib
+library. If you want to use a different version of zlib, follow the
+instructions in the section called "Controlling the version of zlib used
+by Compress::Zlib" later in this document.
+
+
+BUILDING THE MODULE
+-------------------
+
+Assuming you have met all the prerequisites, the module can now be built
+using this sequence of commands:
+
+    perl Makefile.PL
+    make
+    make test
+
+
+
+INSTALLATION
+------------
+
+To install Compress::Zlib, run the command below:
+
+    make install
+
+UPDATES
+-------
+The most recent version of Compress::Zlib is always available at
+    http://www.cpan.org/modules/by-module/Compress/
+
+
+
+Controlling the version of zlib used by Compress::Zlib
+-----------------------------------------------------
+
+Compress::Zlib interfaces to the zlib compression library. There are
+three options available to control which version/instance of the zlib
+library is used:
+
+    1. Build a private copy of the zlib library using the zlib library
+       source that is included with this module.
+       This is the default and recommended option.
+
+    2. Build a private copy of the zlib library using a standard zlib
+       source distribution.
+
+    3. Use a pre-buiild zlib library.
+
+Note that if you intend to use either Option 2 or 3, you need to have
+zlib version 1.0.6 or better. Although this module can build with old
+versions of zlib, it is strongly recommended that you use the most recent
+version of zlib available.
+
+
+The contents of the file config.in are used to control which of the
+three options is actually used. This file is used during the
+
+    perl Makefile.PL 
+
+step of the build, so remember to make any required changes to config.in
+before building this module.
+
+
+
+  Option 1
+  --------
+  
+  For option 1, edit the file config.in and set the variables in it
+  as follows:
+  
+      BUILD_ZLIB = True
+      INCLUDE    = ./zlib-src
+      LIB        = ./zlib-src
+      OLD_ZLIB   = False
+  
+  
+  Option 2
+  --------
+  
+  For option 2, fetch a copy of the zlib source distribution from
+  http://www.zlib.org and unpack it into the Compress::Zlib source
+  directory. Assuming you have fetched zlib 1.1.4, it will create a
+  directory called zlib-1.1.4. 
+  
+  Now set the variables in the file config.in as follows (if the version
+  you have fetched isn't 1.1.4, change the INCLUDE and LIB variables
+  appropriately):
+  
+      BUILD_ZLIB = True
+      INCLUDE    = ./zlib-1.1.4
+      LIB        = ./zlib-1.1.4
+      OLD_ZLIB   = False
+  
+  
+  Option 3
+  --------
+  
+  For option 3, you need to find out where zlib is stored on your system.
+  There are two parts to this.
+
+  First, find the directory where the zlib library is stored (some common
+  names for the library are libz.a and libz.so). Set the LIB variable in
+  the config.in file to that directory.
+  
+  Secondly, find the directory where the file zlib.h is stored. Now set
+  the INCLUDE variable in the config.in file to that directory.
+  
+  Next set BUILD_ZLIB to False
+  
+  Finally, if you are running zlib 1.0.5 or older, set the OLD_ZLIB
+  variable to True. Otherwise set it to False.
+
+  As an example, if the zlib library on your system is in /usr/local/lib,
+  zlib.h is in /usr/local/include and zlib is more older than version
+  1.0.5, the variables in config.in should be set as follows:
+
+      BUILD_ZLIB = False
+      INCLUDE    = /usr/local/include
+      LIB        = /usr/local/lib
+      OLD_ZLIB   = True
+  
+
+
+
+TROUBLESHOOTING
+---------------
+
+Undefined Symbol gzsetparams
+----------------------------
+
+If you get the error shown below when you run the Compress::Zlib test
+harness it probably means you are running a copy of zlib that is version
+1.0.5 or older.
+
+t/01version.........Can't load 'blib/arch/auto/Compress/Zlib/Zlib.so' for 
+                    module Compress::Zlib: blib/arch/auto/Compress/Zlib/Zlib.so:
+                    undefined symbol: gzsetparams at ...
+
+There are two ways to fix this problem:
+
+    1. Upgrade to the latest version of zlib.
+
+    2. Edit config.in and set the OLD_ZLIB variable to True.
+
+
+
+Test Harness 01version fails
+----------------------------
+If the 01version test harness fails, and the problem isn't covered by
+the scenario above, it probably means that you have two versions of zlib
+installed on your system.
+
+Run the command below to see if this is indeed the case
+
+    make test TEST_VERBOSE=1 TEST_FILES=t/01version.t 
+
+Try removing the one you don't want to use and rebuild.   
+
+
+
+
+Solaris build fails with "language optional software package not installed"
+---------------------------------------------------------------------------
+
+If you are trying to build this module under Solaris and you get an
+error message like this
+
+    /usr/ucb/cc: language optional software package not installed
+
+it means that Perl cannot find the C compiler on your system. The cryptic
+message is just Sun's way of telling you that you haven't bought their
+C compiler.
+
+When you build a Perl module that needs a C compiler, the Perl build
+system tries to use the same C compiler that was used to build perl
+itself. In this case your Perl binary was built with a C compiler that
+lived in /usr/ucb.
+
+To continue with building this module, you need to get a C compiler,
+or tell Perl where your C compiler is, if you already have one.
+
+Assuming you have now got a C compiler, what you do next will be dependant
+on what C compiler you have installed. If you have just installed Sun's
+C compiler, you shouldn't have to do anything. Just try rebuilding
+this module.
+
+If you have installed another C compiler, say gcc, you have to tell perl
+how to use it instead of /usr/ucb/cc.
+
+This set of options seems to work if you want to use gcc. Your mileage
+may vary.
+
+    perl Makefile.PL CC=gcc CCCDLFLAGS=-fPIC OPTIMIZE=" "
+    make test
+
+If that doesn't work for you, it's time to make changes to the Makefile
+by hand. Good luck!
+
+
+
+
+Solaris build fails with "gcc: unrecognized option `-KPIC'"
+-----------------------------------------------------------
+
+You are running Solaris and you get an error like this when you try to
+build this Perl module
+
+    gcc: unrecognized option `-KPIC'
+
+This symptom usually means that you are using a Perl binary that has been
+built with the Sun C compiler, but you are using gcc to build this module.
+
+When Perl builds modules that need a C compiler, it will attempt to use
+the same C compiler and command line options that was used to build perl
+itself. In this case "-KPIC" is a valid option for the Sun C compiler,
+but not for gcc. The equivalent option for gcc is "-fPIC".
+
+The solution is either:
+
+    1. Build both Perl and this module with the same C compiler, either
+       by using the Sun C compiler for both or gcc for both.
+
+    2. Try generating the Makefile for this module like this perl
+
+           perl Makefile.PL CC=gcc CCCDLFLAGS=-fPIC OPTIMIZE=" " LD=gcc
+           make test
+
+       This second option seems to work when mixing a Perl binary built
+       with the Sun C compiler and this module built with gcc. Your
+       mileage may vary.
+
+
+
+HP-UX Notes
+-----------
+
+I've had a report that when building Compress::Zlib under HP-UX that it
+is necessary to have first built the zlib library with the -fpic option.
+
+
+
+Linux Notes
+-----------
+
+Although most Linux distributions already come with zlib, some people
+report getting this error when they try to build this module:
+
+$ make
+cp Zlib.pm blib/lib/Compress/Zlib.pm
+AutoSplitting blib/lib/Compress/Zlib.pm (blib/lib/auto/Compress/Zlib)
+/usr/bin/perl -I/usr/lib/perl5/5.6.1/i386-linux -I/usr/lib/perl5/5.6.1 /usr/lib/perl5/5.6.1/ExtUtils/xsubpp  -typemap /usr/lib/perl5/5.6.1/ExtUtils/typemap -typemap typemap Zlib.xs > Zlib.xsc && mv Zlib.xsc Zlib.c
+gcc -c -I/usr/local/include -fno-strict-aliasing -I/usr/local/include -O2 -march=i386 -mcpu=i686   -DVERSION=\"1.16\" -DXS_VERSION=\"1.16\" -fPIC -I/usr/lib/perl5/5.6.1/i386-linux/CORE  Zlib.c
+Zlib.xs:25:19: zlib.h: No such file or directory
+make: *** [Zlib.o] Error 1
+
+This usually means that you have not installed the development RPM
+for zlib. Check for an RPM that start with "zlib-devel" in your Linux
+distribution.
+
+
+
+
+Win32 Notes
+-----------
+
+If you are running Activestate Perl (from http://www.activestate.com),
+it ships with a pre-compiled version of Compress::Zlib. To check if a
+newer version of Compress::Zlib is available run this from the command
+prompt
+
+    C:\> ppm verify -upgrade Compress-Zlib
+
+
+If you are not running Activestate Perl and you don't have access
+to a C compiler, you will not be able to build and install this module.
+
+
+
+
+Win32 & Cygwin Notes
+--------------------
+
+It is not possible to install Compress::Zlib using the CPAN shell.
+This is because the Compress::Zlib DLL is itself used by the CPAN shell
+and it is impossible to remove a DLL while it is already loaded under
+Windows.
+
+The workaround is to install Compress::Zlib manually using the
+instructions given at the start of this file.
+
+
+
+Mac OX X Notes
+--------------
+
+Some versions of Mac OS X are failing a number of the tests in the
+06gzdopen.t test harness.
+
+The functionality being exercised in these tests is checking that it is
+possible to call gzopen with an existing Perl filenhandle instead of a
+filename. For some reason it does not seem possible to extract a
+numeric file descriptor (using fileno) from a FILE* and then make use
+of it.
+
+If you happen to now how to fix for this, I would like to hear from you.
+
+In the meantime, a workaround that has been reported to me is to use fink,
+available at http://fink.sourceforge.net
+
+
+
+FEEDBACK
+--------
+
+How to report a problem with Compress::Zlib.
+
+To help me help you, I need all of the following information:
+
+ 1. The *complete* output from running this
+        perl -V
+    Do not edit the output in any way.
+    Note, I want you to run "perl -V" and NOT "perl -v".
+    If your perl does not understand the "-V" option it is too
+    old. This module needs Perl version 5.004 or better.     
+
+ 2. The version of Compress::Zlib you have. 
+    If you have successfully installed Compress::Zlib, this one-liner
+    will tell you:
+
+       perl -MCompress::Zlib -e 'print qq[ver $Compress::Zlib::VERSION\n]'
+
+    If you are running windows use this
+
+       perl -MCompress::Zlib -e "print qq[ver $Compress::Zlib::VERSION\n]"
+
+    If you haven't installed Compress::Zlib then search Compress::Zlib.pm
+    for a line like this:
+
+      $VERSION = "1.05" ;
+
+ 3. The version of zlib you have installed.
+    If you have successfully installed Compress::Zlib, this one-liner
+    will tell you:
+
+      perl -MCompress::Zlib -e "print q[zlib ver ]. Compress::Zlib::ZLIB_VERSION.qq[\n]" 
+
+
+    If not, look at the beginning of the file zlib.h. 
+
+ 4. If you are having problems building Compress::Zlib, send me a
+    complete log of what happened. Start by unpacking the Compress:Zlib
+    module into a fresh directory and keep a log of all the steps
+
+        [edit config.in, if necessary]
+        perl Makefile.PL
+        make
+        make test TEST_VERBOSE=1          
+
+
+Paul Marquess <pmqs@cpan.org>
diff --git a/ext/Compress/Zlib/Zlib.pm b/ext/Compress/Zlib/Zlib.pm
new file mode 100644 (file)
index 0000000..18bcd07
--- /dev/null
@@ -0,0 +1,1182 @@
+# File   : Zlib.pm
+# Author  : Paul Marquess
+# Created : 30 January 2005
+# Version : 1.34
+#
+#     Copyright (c) 1995-2005 Paul Marquess. All rights reserved.
+#     This program is free software; you can redistribute it and/or
+#     modify it under the same terms as Perl itself.
+#
+
+package Compress::Zlib;
+
+require 5.004 ;
+require Exporter;
+require DynaLoader;
+use AutoLoader;
+use Carp ;
+use IO::Handle ;
+
+use strict ;
+local ($^W) = 1; #use warnings ;
+use vars qw($VERSION @ISA @EXPORT $AUTOLOAD);
+use vars qw($deflateDefault $deflateParamsDefault $inflateDefault);
+
+$VERSION = "1.34" ;
+
+@ISA = qw(Exporter DynaLoader);
+# Items to export into callers namespace by default. Note: do not export
+# names by default without a very good reason. Use EXPORT_OK instead.
+# Do not simply export all your public functions/methods/constants.
+@EXPORT = qw(
+       deflateInit 
+       inflateInit
+
+       compress 
+       uncompress
+
+       gzip gunzip
+
+       gzopen 
+       $gzerrno
+
+       adler32 
+       crc32
+
+       ZLIB_VERSION
+
+       DEF_WBITS
+       OS_CODE
+
+        MAX_MEM_LEVEL
+       MAX_WBITS
+
+       Z_ASCII
+       Z_BEST_COMPRESSION
+       Z_BEST_SPEED
+       Z_BINARY
+       Z_BUF_ERROR
+       Z_DATA_ERROR
+       Z_DEFAULT_COMPRESSION
+       Z_DEFAULT_STRATEGY
+        Z_DEFLATED
+       Z_ERRNO
+       Z_FILTERED
+       Z_FINISH
+       Z_FULL_FLUSH
+       Z_HUFFMAN_ONLY
+       Z_MEM_ERROR
+       Z_NEED_DICT
+       Z_NO_COMPRESSION
+       Z_NO_FLUSH
+       Z_NULL
+       Z_OK
+       Z_PARTIAL_FLUSH
+       Z_STREAM_END
+       Z_STREAM_ERROR
+       Z_SYNC_FLUSH
+       Z_UNKNOWN
+       Z_VERSION_ERROR
+);
+
+
+
+sub AUTOLOAD {
+    my($constname);
+    ($constname = $AUTOLOAD) =~ s/.*:://;
+    my ($error, $val) = constant($constname);
+    Carp::croak $error if $error;
+    no strict 'refs';
+    *{$AUTOLOAD} = sub { $val };
+    goto &{$AUTOLOAD};
+}
+
+bootstrap Compress::Zlib $VERSION ;
+
+# Preloaded methods go here.
+
+sub isaFilehandle($)
+{
+    my $fh = shift ;
+
+    return ((UNIVERSAL::isa($fh,'GLOB') or UNIVERSAL::isa(\$fh,'GLOB')) 
+               and defined fileno($fh)  )
+
+}
+
+sub isaFilename($)
+{
+    my $name = shift ;
+
+    return (! ref $name and UNIVERSAL::isa(\$name, 'SCALAR')) ;
+}
+
+sub gzopen($$)
+{
+    my ($file, $mode) = @_ ;
+    if (isaFilehandle $file) {
+       IO::Handle::flush($file) ;
+       my $offset = tell($file) ;
+        gzdopen_(fileno($file), $mode, $offset) ;
+    }
+    elsif (isaFilename $file) {
+       gzopen_($file, $mode) 
+    }
+    else {
+       croak "gzopen: file parameter is not a filehandle or filename"
+    }
+}
+
+sub ParseParameters($@)
+{
+    my ($default, @rest) = @_ ;
+    my (%got) = %$default ;
+    my (@Bad) ;
+    my ($key, $value) ;
+    my $sub = (caller(1))[3] ;
+    my %options = () ;
+
+    # allow the options to be passed as a hash reference or
+    # as the complete hash.
+    if (@rest == 1) {
+
+        croak "$sub: parameter is not a reference to a hash"
+            if ref $rest[0] ne "HASH" ;
+
+        %options = %{ $rest[0] } ;
+    }
+    elsif (@rest >= 2) {
+        my $count = @rest;
+        croak "$sub: Expected even number of parameters, got $count"
+            if @rest % 2 != 0 ;
+        %options = @rest ;
+    }
+
+    while (($key, $value) = each %options)
+    {
+       $key =~ s/^-// ;
+
+        if (exists $default->{$key})
+          { $got{$key} = $value }
+        else
+         { push (@Bad, $key) }
+    }
+    
+    if (@Bad) {
+        my ($bad) = join(", ", @Bad) ;
+        croak "unknown key value(s) @Bad" ;
+    }
+
+    return \%got ;
+}
+
+$deflateDefault = {
+       'Level'      => Z_DEFAULT_COMPRESSION(),
+       'Method'     => Z_DEFLATED(),
+       'WindowBits' => MAX_WBITS(),
+       'MemLevel'   => MAX_MEM_LEVEL(),
+       'Strategy'   => Z_DEFAULT_STRATEGY(),
+       'Bufsize'    => 4096,
+       'Dictionary' => "",
+       } ;
+
+$deflateParamsDefault = {
+       'Level'      => undef,
+       'Strategy'   => undef,
+       'Bufsize'    => undef,
+       } ;
+
+$inflateDefault = {
+       'WindowBits' => MAX_WBITS(),
+       'Bufsize'    => 4096,
+       'Dictionary' => "",
+       } ;
+
+
+sub deflateInit(@)
+{
+    my ($got) = ParseParameters($deflateDefault, @_) ;
+    local ($^W) = 0; #no warnings;
+    croak "deflateInit: Bufsize must be >= 1, you specified $got->{Bufsize}"
+        unless $got->{Bufsize} >= 1;
+    _deflateInit($got->{Level}, $got->{Method}, $got->{WindowBits}, 
+               $got->{MemLevel}, $got->{Strategy}, $got->{Bufsize},
+               $got->{Dictionary}) ;
+               
+}
+
+sub inflateInit(@)
+{
+    my ($got) = ParseParameters($inflateDefault, @_) ;
+    local ($^W) = 0; #no warnings;
+    croak "inflateInit: Bufsize must be >= 1, you specified $got->{Bufsize}"
+        unless $got->{Bufsize} >= 1;
+    _inflateInit($got->{WindowBits}, $got->{Bufsize}, $got->{Dictionary});
+}
+
+sub Compress::Zlib::deflateStream::deflateParams
+{
+    my $self = shift ;
+    my ($got) = ParseParameters($deflateParamsDefault, @_) ;
+    croak "deflateParams needs Level and/or Strategy"
+        unless defined $got->{Level} || defined $got->{Strategy};
+    local ($^W) = 0; #no warnings;
+    croak "deflateParams: Bufsize must be >= 1, you specified $got->{Bufsize}"
+        unless  !defined $got->{Bufsize} || $got->{Bufsize} >= 1;
+
+    my $flags = 0;
+    if (defined $got->{Level}) 
+      { $flags |= 1 }
+    else 
+      { $got->{Level} = 0 }
+
+    if (defined $got->{Strategy}) 
+      { $flags |= 2 }
+    else 
+      { $got->{Strategy} = 0 }
+
+    $got->{Bufsize} = 0 
+        if !defined $got->{Bufsize};
+
+    $self->_deflateParams($flags, $got->{Level}, $got->{Strategy}, 
+                          $got->{Bufsize});
+               
+}
+
+sub compress($;$)
+{
+    my ($x, $output, $out, $err, $in) ;
+
+    if (ref $_[0] ) {
+        $in = $_[0] ;
+       croak "not a scalar reference" unless ref $in eq 'SCALAR' ;
+    }
+    else {
+        $in = \$_[0] ;
+    }
+
+    my $level = (@_ == 2 ? $_[1] : Z_DEFAULT_COMPRESSION() );
+
+
+    if ( (($x, $err) = deflateInit(Level => $level))[1] == Z_OK()) {
+
+        ($output, $err) = $x->deflate($in) ;
+       return undef unless $err == Z_OK() ;
+
+       ($out, $err) = $x->flush() ;
+       return undef unless $err == Z_OK() ;
+    
+        return ($output . $out) ;
+
+    }
+
+    return undef ;
+}
+
+
+sub uncompress($)
+{
+    my ($x, $output, $err, $in) ;
+
+    if (ref $_[0] ) {
+        $in = $_[0] ;
+       croak "not a scalar reference" unless ref $in eq 'SCALAR' ;
+    }
+    else {
+        $in = \$_[0] ;
+    }
+
+    if ( (($x, $err) = inflateInit())[1] == Z_OK())  {
+        ($output, $err) = $x->__unc_inflate($in) ;
+        return undef unless $err == Z_STREAM_END() ;
+       return $output ;
+    }
+    return undef ;
+}
+
+
+# Constants
+use constant MAGIC1    => 0x1f ;
+use constant MAGIC2    => 0x8b ;
+use constant OSCODE    => 3 ;
+
+use constant FTEXT     => 1 ;
+use constant FHCRC     => 2 ;
+use constant FEXTRA    => 4 ;
+use constant FNAME     => 8 ;
+use constant FCOMMENT  => 16 ;
+use constant NULL      => pack("C", 0) ;
+use constant RESERVED  => 0xE0 ;
+
+use constant MIN_HDR_SIZE => 10 ; # minimum gzip header size
+sub memGzip($)
+{
+  my $x = deflateInit(
+                      -Level         => Z_BEST_COMPRESSION(),
+                      -WindowBits     =>  - MAX_WBITS(),
+                     )
+      or return undef ;
+  # write a minimal gzip header
+  my(@m);
+  push @m, pack("C" . MIN_HDR_SIZE, 
+                MAGIC1, MAGIC2, Z_DEFLATED(), 0,0,0,0,0,0, OSCODE) ;
+  # if the deflation buffer isn't a reference, make it one
+  my $string = (ref $_[0] ? $_[0] : \$_[0]) ;
+
+  my ($output, $status) = $x->deflate($string) ;
+  push @m, $output ;
+  $status == Z_OK()
+      or return undef ;
+  ($output, $status) = $x->flush() ;
+  push @m, $output ;
+  $status == Z_OK()
+      or return undef ;
+  push @m, pack("V V", crc32($string), $x->total_in());
+  return join "", @m;
+}
+
+sub _removeGzipHeader($)
+{
+    my $string = shift ;
+
+    return Z_DATA_ERROR() 
+        if length($$string) < MIN_HDR_SIZE ;
+
+    my ($magic1, $magic2, $method, $flags, $time, $xflags, $oscode) = 
+        unpack ('CCCCVCC', $$string);
+
+    return Z_DATA_ERROR()
+        unless $magic1 == MAGIC1 and $magic2 == MAGIC2 and
+           $method == Z_DEFLATED() and !($flags & RESERVED()) ;
+    substr($$string, 0, MIN_HDR_SIZE) = '' ;
+
+    # skip extra field
+    if ($flags & FEXTRA)
+    {
+        return Z_DATA_ERROR()
+            if length($$string) < 2 ;
+
+        my ($extra_len) = unpack ('v', $$string);
+        $extra_len += 2;
+        return Z_DATA_ERROR()
+            if length($$string) < $extra_len ;
+
+        substr($$string, 0, $extra_len) = '';
+    }
+
+    # skip orig name
+    if ($flags & FNAME)
+    {
+        my $name_end = index ($$string, NULL);
+        return Z_DATA_ERROR()
+           if $name_end == -1 ;
+        substr($$string, 0, $name_end + 1) =  '';
+    }
+
+    # skip comment
+    if ($flags & FCOMMENT)
+    {
+        my $comment_end = index ($$string, NULL);
+        return Z_DATA_ERROR()
+            if $comment_end == -1 ;
+        substr($$string, 0, $comment_end + 1) = '';
+    }
+
+    # skip header crc
+    if ($flags & FHCRC)
+    {
+        return Z_DATA_ERROR()
+            if length ($$string) < 2 ;
+        substr($$string, 0, 2) = '';
+    }
+    
+    return Z_OK();
+}
+
+
+sub memGunzip($)
+{
+    # if the buffer isn't a reference, make it one
+    my $string = (ref $_[0] ? $_[0] : \$_[0]);
+    _removeGzipHeader($string) == Z_OK() 
+        or return undef;
+     
+    my $bufsize = length $$string > 4096 ? length $$string : 4096 ;
+    my $x = inflateInit( -WindowBits => - MAX_WBITS(),
+                         -Bufsize => $bufsize) 
+              or return undef;
+    my ($output, $status) = $x->inflate($string);
+    return undef 
+        unless $status == Z_STREAM_END();
+
+    if (length $$string >= 8)
+    {
+        my ($crc, $len) = unpack ("VV", substr($$string, 0, 8));
+        substr($$string, 0, 8) = '';
+        return undef 
+            unless $len == length($output) and
+                   $crc == crc32($output);
+    }
+    else
+    {
+        $$string = '';
+    }
+
+    return $output;   
+}
+
+# Autoload methods go after __END__, and are processed by the autosplit program.
+
+1;
+__END__
+
+=cut
+
+=head1 NAME
+
+Compress::Zlib - Interface to zlib compression library
+
+=head1 SYNOPSIS
+
+    use Compress::Zlib ;
+
+    ($d, $status) = deflateInit( [OPT] ) ;
+    ($out, $status) = $d->deflate($buffer) ;
+    $status = $d->deflateParams([OPT]) ;
+    ($out, $status) = $d->flush() ;
+    $d->dict_adler() ;
+    $d->total_in() ;
+    $d->total_out() ;
+    $d->msg() ;
+
+    ($i, $status) = inflateInit( [OPT] ) ;
+    ($out, $status) = $i->inflate($buffer) ;
+    $status = $i->inflateSync($buffer) ;
+    $i->dict_adler() ;
+    $i->total_in() ;
+    $i->total_out() ;
+    $i->msg() ;
+
+    $dest = compress($source, [$level]) ;
+    $dest = uncompress($source) ;
+
+    $gz = gzopen($filename or filehandle, $mode) ;
+    $bytesread = $gz->gzread($buffer [,$size]) ;
+    $bytesread = $gz->gzreadline($line) ;
+    $byteswritten = $gz->gzwrite($buffer) ;
+    $status = $gz->gzflush($flush) ;
+    $status = $gz->gzclose() ;
+    $status = $gz->gzeof() ;
+    $status = $gz->gzsetparams($level, $strategy) ;
+    $errstring = $gz->gzerror() ; 
+    $gzerrno
+
+    $dest = Compress::Zlib::memGzip($buffer) ;
+    $dest = Compress::Zlib::memGunzip($buffer) ;
+
+    $crc = adler32($buffer [,$crc]) ;
+    $crc = crc32($buffer [,$crc]) ;
+
+    ZLIB_VERSION
+
+=head1 DESCRIPTION
+
+The I<Compress::Zlib> module provides a Perl interface to the I<zlib>
+compression library (see L</AUTHOR> for details about where to get
+I<zlib>). Most of the functionality provided by I<zlib> is available
+in I<Compress::Zlib>.
+
+The module can be split into two general areas of functionality, namely
+in-memory compression/decompression and read/write access to I<gzip>
+files. Each of these areas will be discussed separately below.
+
+=head1 DEFLATE 
+
+The interface I<Compress::Zlib> provides to the in-memory I<deflate>
+(and I<inflate>) functions has been modified to fit into a Perl model.
+
+The main difference is that for both inflation and deflation, the Perl
+interface will I<always> consume the complete input buffer before
+returning. Also the output buffer returned will be automatically grown
+to fit the amount of output available.
+
+Here is a definition of the interface available:
+
+
+=head2 B<($d, $status) = deflateInit( [OPT] )>
+
+Initialises a deflation stream. 
+
+It combines the features of the I<zlib> functions B<deflateInit>,
+B<deflateInit2> and B<deflateSetDictionary>.
+
+If successful, it will return the initialised deflation stream, B<$d>
+and B<$status> of C<Z_OK> in a list context. In scalar context it
+returns the deflation stream, B<$d>, only.
+
+If not successful, the returned deflation stream (B<$d>) will be
+I<undef> and B<$status> will hold the exact I<zlib> error code.
+
+The function optionally takes a number of named options specified as
+C<-Name=E<gt>value> pairs. This allows individual options to be
+tailored without having to specify them all in the parameter list.
+
+For backward compatibility, it is also possible to pass the parameters
+as a reference to a hash containing the name=>value pairs.
+
+The function takes one optional parameter, a reference to a hash.  The
+contents of the hash allow the deflation interface to be tailored.
+
+Here is a list of the valid options:
+
+=over 5
+
+=item B<-Level>
+
+Defines the compression level. Valid values are 0 through 9,
+C<Z_NO_COMPRESSION>, C<Z_BEST_SPEED>, C<Z_BEST_COMPRESSION>, and
+C<Z_DEFAULT_COMPRESSION>.
+
+The default is C<-Level =E<gt>Z_DEFAULT_COMPRESSION>.
+
+=item B<-Method>
+
+Defines the compression method. The only valid value at present (and
+the default) is C<-Method =E<gt>Z_DEFLATED>.
+
+=item B<-WindowBits>
+
+For a definition of the meaning and valid values for B<WindowBits>
+refer to the I<zlib> documentation for I<deflateInit2>.
+
+Defaults to C<-WindowBits =E<gt>MAX_WBITS>.
+
+=item B<-MemLevel>
+
+For a definition of the meaning and valid values for B<MemLevel>
+refer to the I<zlib> documentation for I<deflateInit2>.
+
+Defaults to C<-MemLevel =E<gt>MAX_MEM_LEVEL>.
+
+=item B<-Strategy>
+
+Defines the strategy used to tune the compression. The valid values are
+C<Z_DEFAULT_STRATEGY>, C<Z_FILTERED> and C<Z_HUFFMAN_ONLY>. 
+
+The default is C<-Strategy =E<gt>Z_DEFAULT_STRATEGY>.
+
+=item B<-Dictionary>
+
+When a dictionary is specified I<Compress::Zlib> will automatically
+call B<deflateSetDictionary> directly after calling B<deflateInit>. The
+Adler32 value for the dictionary can be obtained by calling the method 
+C<$d->dict_adler()>.
+
+The default is no dictionary.
+
+=item B<-Bufsize>
+
+Sets the initial size for the deflation buffer. If the buffer has to be
+reallocated to increase the size, it will grow in increments of
+B<Bufsize>.
+
+The default is 4096.
+
+=back
+
+Here is an example of using the B<deflateInit> optional parameter list
+to override the default buffer size and compression level. All other
+options will take their default values.
+
+    deflateInit( -Bufsize => 300, 
+                 -Level => Z_BEST_SPEED  ) ;
+
+
+=head2 B<($out, $status) = $d-E<gt>deflate($buffer)>
+
+
+Deflates the contents of B<$buffer>. The buffer can either be a scalar
+or a scalar reference.  When finished, B<$buffer> will be
+completely processed (assuming there were no errors). If the deflation
+was successful it returns the deflated output, B<$out>, and a status
+value, B<$status>, of C<Z_OK>.
+
+On error, B<$out> will be I<undef> and B<$status> will contain the
+I<zlib> error code.
+
+In a scalar context B<deflate> will return B<$out> only.
+
+As with the I<deflate> function in I<zlib>, it is not necessarily the
+case that any output will be produced by this method. So don't rely on
+the fact that B<$out> is empty for an error test.
+
+
+=head2 B<($out, $status) = $d-E<gt>flush([flush_type])>
+
+Typically used to finish the deflation. Any pending output will be
+returned via B<$out>.
+B<$status> will have a value C<Z_OK> if successful.
+
+In a scalar context B<flush> will return B<$out> only.
+
+Note that flushing can seriously degrade the compression ratio, so it
+should only be used to terminate a decompression (using C<Z_FINISH>) or
+when you want to create a I<full flush point> (using C<Z_FULL_FLUSH>).
+
+By default the C<flush_type> used is C<Z_FINISH>. Other valid values
+for C<flush_type> are C<Z_NO_FLUSH>, C<Z_PARTIAL_FLUSH>, C<Z_SYNC_FLUSH>
+and C<Z_FULL_FLUSH>. It is strongly recommended that you only set the
+C<flush_type> parameter if you fully understand the implications of
+what it does. See the C<zlib> documentation for details.
+
+=head2 B<$status = $d-E<gt>deflateParams([OPT])>
+
+Change settings for the deflate stream C<$d>.
+
+The list of the valid options is shown below. Options not specified
+will remain unchanged.
+
+=over 5
+
+=item B<-Level>
+
+Defines the compression level. Valid values are 0 through 9,
+C<Z_NO_COMPRESSION>, C<Z_BEST_SPEED>, C<Z_BEST_COMPRESSION>, and
+C<Z_DEFAULT_COMPRESSION>.
+
+=item B<-Strategy>
+
+Defines the strategy used to tune the compression. The valid values are
+C<Z_DEFAULT_STRATEGY>, C<Z_FILTERED> and C<Z_HUFFMAN_ONLY>. 
+
+=back
+
+=head2 B<$d-E<gt>dict_adler()>
+
+Returns the adler32 value for the dictionary.
+
+=head2 B<$d-E<gt>msg()>
+
+Returns the last error message generated by zlib.
+
+=head2 B<$d-E<gt>total_in()>
+
+Returns the total number of bytes uncompressed bytes input to deflate.
+
+=head2 B<$d-E<gt>total_out()>
+
+Returns the total number of compressed bytes output from deflate.
+
+=head2 Example
+
+
+Here is a trivial example of using B<deflate>. It simply reads standard
+input, deflates it and writes it to standard output.
+
+    use strict ;
+    use warnings ;
+
+    use Compress::Zlib ;
+
+    binmode STDIN;
+    binmode STDOUT;
+    my $x = deflateInit()
+       or die "Cannot create a deflation stream\n" ;
+
+    my ($output, $status) ;
+    while (<>)
+    {
+        ($output, $status) = $x->deflate($_) ;
+    
+        $status == Z_OK
+            or die "deflation failed\n" ;
+    
+        print $output ;
+    }
+    
+    ($output, $status) = $x->flush() ;
+    
+    $status == Z_OK
+        or die "deflation failed\n" ;
+    
+    print $output ;
+
+=head1 INFLATE
+
+Here is a definition of the interface:
+
+
+=head2 B<($i, $status) = inflateInit()>
+
+Initialises an inflation stream. 
+
+In a list context it returns the inflation stream, B<$i>, and the
+I<zlib> status code (B<$status>). In a scalar context it returns the
+inflation stream only.
+
+If successful, B<$i> will hold the inflation stream and B<$status> will
+be C<Z_OK>.
+
+If not successful, B<$i> will be I<undef> and B<$status> will hold the
+I<zlib> error code.
+
+The function optionally takes a number of named options specified as
+C<-Name=E<gt>value> pairs. This allows individual options to be
+tailored without having to specify them all in the parameter list.
+For backward compatibility, it is also possible to pass the parameters
+as a reference to a hash containing the name=>value pairs.
+The function takes one optional parameter, a reference to a hash.  The
+contents of the hash allow the deflation interface to be tailored.
+Here is a list of the valid options:
+
+=over 5
+
+=item B<-WindowBits>
+
+For a definition of the meaning and valid values for B<WindowBits>
+refer to the I<zlib> documentation for I<inflateInit2>.
+
+Defaults to C<-WindowBits =E<gt>MAX_WBITS>.
+
+=item B<-Bufsize>
+
+Sets the initial size for the inflation buffer. If the buffer has to be
+reallocated to increase the size, it will grow in increments of
+B<Bufsize>. 
+
+Default is 4096.
+
+=item B<-Dictionary>
+
+The default is no dictionary.
+
+=back
+
+Here is an example of using the B<inflateInit> optional parameter to
+override the default buffer size.
+
+    inflateInit( -Bufsize => 300 ) ;
+
+=head2 B<($out, $status) = $i-E<gt>inflate($buffer)>
+
+Inflates the complete contents of B<$buffer>. The buffer can either be
+a scalar or a scalar reference.
+
+Returns C<Z_OK> if successful and C<Z_STREAM_END> if the end of the
+compressed data has been successfully reached. 
+If not successful, B<$out> will be I<undef> and B<$status> will hold
+the I<zlib> error code.
+
+The C<$buffer> parameter is modified by C<inflate>. On completion it
+will contain what remains of the input buffer after inflation. This
+means that C<$buffer> will be an empty string when the return status is
+C<Z_OK>. When the return status is C<Z_STREAM_END> the C<$buffer>
+parameter will contains what (if anything) was stored in the input
+buffer after the deflated data stream.
+
+This feature is useful when processing a file format that encapsulates
+a  compressed data stream (e.g. gzip, zip).
+
+=head2 B<$status = $i-E<gt>inflateSync($buffer)>
+
+Scans C<$buffer> until it reaches either a I<full flush point> or the
+end of the buffer.
+
+If a I<full flush point> is found, C<Z_OK> is returned and C<$buffer>
+will be have all data up to the flush point removed. This can then be
+passed to the C<deflate> method.
+
+Any other return code means that a flush point was not found. If more
+data is available, C<inflateSync> can be called repeatedly with more
+compressed data until the flush point is found.
+
+
+=head2 B<$i-E<gt>dict_adler()>
+
+Returns the adler32 value for the dictionary.
+
+=head2 B<$i-E<gt>msg()>
+
+Returns the last error message generated by zlib.
+
+=head2 B<$i-E<gt>total_in()>
+
+Returns the total number of bytes compressed bytes input to inflate.
+
+=head2 B<$i-E<gt>total_out()>
+
+Returns the total number of uncompressed bytes output from inflate.
+
+=head2 Example
+
+Here is an example of using B<inflate>.
+
+    use strict ;
+    use warnings ;
+    
+    use Compress::Zlib ;
+    
+    my $x = inflateInit()
+       or die "Cannot create a inflation stream\n" ;
+    
+    my $input = '' ;
+    binmode STDIN;
+    binmode STDOUT;
+    
+    my ($output, $status) ;
+    while (read(STDIN, $input, 4096))
+    {
+        ($output, $status) = $x->inflate(\$input) ;
+    
+        print $output 
+            if $status == Z_OK or $status == Z_STREAM_END ;
+    
+        last if $status != Z_OK ;
+    }
+    
+    die "inflation failed\n"
+        unless $status == Z_STREAM_END ;
+
+=head1 COMPRESS/UNCOMPRESS
+
+Two high-level functions are provided by I<zlib> to perform in-memory
+compression. They are B<compress> and B<uncompress>. Two Perl subs are
+provided which provide similar functionality.
+
+=over 5
+
+=item B<$dest = compress($source [, $level] ) ;>
+
+Compresses B<$source>. If successful it returns the
+compressed data. Otherwise it returns I<undef>.
+
+The source buffer can either be a scalar or a scalar reference.
+
+The B<$level> paramter defines the compression level. Valid values are
+0 through 9, C<Z_NO_COMPRESSION>, C<Z_BEST_SPEED>,
+C<Z_BEST_COMPRESSION>, and C<Z_DEFAULT_COMPRESSION>.
+If B<$level> is not specified C<Z_DEFAULT_COMPRESSION> will be used.
+
+
+=item B<$dest = uncompress($source) ;>
+
+Uncompresses B<$source>. If successful it returns the uncompressed
+data. Otherwise it returns I<undef>.
+
+The source buffer can either be a scalar or a scalar reference.
+
+=back
+
+=head1 GZIP INTERFACE
+
+A number of functions are supplied in I<zlib> for reading and writing
+I<gzip> files. This module provides an interface to most of them. In
+general the interface provided by this module operates identically to
+the functions provided by I<zlib>. Any differences are explained
+below.
+
+=over 5
+
+=item B<$gz = gzopen(filename or filehandle, mode)>
+
+This function operates identically to the I<zlib> equivalent except
+that it returns an object which is used to access the other I<gzip>
+methods.
+
+As with the I<zlib> equivalent, the B<mode> parameter is used to
+specify both whether the file is opened for reading or writing and to
+optionally specify a a compression level. Refer to the I<zlib>
+documentation for the exact format of the B<mode> parameter.
+
+If a reference to an open filehandle is passed in place of the
+filename, gzdopen will be called behind the scenes. The third example
+at the end of this section, I<gzstream>, uses this feature.
+
+=item B<$bytesread = $gz-E<gt>gzread($buffer [, $size]) ;>
+
+Reads B<$size> bytes from the compressed file into B<$buffer>. If
+B<$size> is not specified, it will default to 4096. If the scalar
+B<$buffer> is not large enough, it will be extended automatically.
+
+Returns the number of bytes actually read. On EOF it returns 0 and in
+the case of an error, -1.
+
+=item B<$bytesread = $gz-E<gt>gzreadline($line) ;>
+
+Reads the next line from the compressed file into B<$line>. 
+
+Returns the number of bytes actually read. On EOF it returns 0 and in
+the case of an error, -1.
+
+It is legal to intermix calls to B<gzread> and B<gzreadline>.
+
+At this time B<gzreadline> ignores the variable C<$/>
+(C<$INPUT_RECORD_SEPARATOR> or C<$RS> when C<English> is in use). The
+end of a line is denoted by the C character C<'\n'>.
+
+=item B<$byteswritten = $gz-E<gt>gzwrite($buffer) ;>
+
+Writes the contents of B<$buffer> to the compressed file. Returns the
+number of bytes actually written, or 0 on error.
+
+=item B<$status = $gz-E<gt>gzflush($flush) ;>
+
+Flushes all pending output to the compressed file.
+Works identically to the I<zlib> function it interfaces to. Note that
+the use of B<gzflush> can degrade compression.
+
+Returns C<Z_OK> if B<$flush> is C<Z_FINISH> and all output could be
+flushed. Otherwise the zlib error code is returned.
+
+Refer to the I<zlib> documentation for the valid values of B<$flush>.
+
+=item B<$status = $gz-E<gt>gzeof() ;>
+
+Returns 1 if the end of file has been detected while reading the input
+file, otherwise returns 0.
+
+=item B<$gz-E<gt>gzclose>
+
+Closes the compressed file. Any pending data is flushed to the file
+before it is closed.
+
+=item B<$gz-E<gt>gzsetparams($level, $strategy>
+
+Change settings for the deflate stream C<$gz>.
+
+The list of the valid options is shown below. Options not specified
+will remain unchanged.
+
+Note: This method is only available if you are running zlib 1.0.6 or better.
+
+=over 5
+
+=item B<$level>
+
+Defines the compression level. Valid values are 0 through 9,
+C<Z_NO_COMPRESSION>, C<Z_BEST_SPEED>, C<Z_BEST_COMPRESSION>, and
+C<Z_DEFAULT_COMPRESSION>.
+
+=item B<$strategy>
+
+Defines the strategy used to tune the compression. The valid values are
+C<Z_DEFAULT_STRATEGY>, C<Z_FILTERED> and C<Z_HUFFMAN_ONLY>. 
+
+=back
+
+=item B<$gz-E<gt>gzerror>
+
+Returns the I<zlib> error message or number for the last operation
+associated with B<$gz>. The return value will be the I<zlib> error
+number when used in a numeric context and the I<zlib> error message
+when used in a string context. The I<zlib> error number constants,
+shown below, are available for use.
+
+    Z_OK
+    Z_STREAM_END
+    Z_ERRNO
+    Z_STREAM_ERROR
+    Z_DATA_ERROR
+    Z_MEM_ERROR
+    Z_BUF_ERROR
+
+=item B<$gzerrno>
+
+The B<$gzerrno> scalar holds the error code associated with the most
+recent I<gzip> routine. Note that unlike B<gzerror()>, the error is
+I<not> associated with a particular file.
+
+As with B<gzerror()> it returns an error number in numeric context and
+an error message in string context. Unlike B<gzerror()> though, the
+error message will correspond to the I<zlib> message when the error is
+associated with I<zlib> itself, or the UNIX error message when it is
+not (i.e. I<zlib> returned C<Z_ERRORNO>).
+
+As there is an overlap between the error numbers used by I<zlib> and
+UNIX, B<$gzerrno> should only be used to check for the presence of
+I<an> error in numeric context. Use B<gzerror()> to check for specific
+I<zlib> errors. The I<gzcat> example below shows how the variable can
+be used safely.
+
+=back
+
+
+=head2 Examples
+
+Here is an example script which uses the interface. It implements a
+I<gzcat> function.
+
+    use strict ;
+    use warnings ;
+    
+    use Compress::Zlib ;
+    
+    die "Usage: gzcat file...\n"
+        unless @ARGV ;
+    
+    my $file ;
+    
+    foreach $file (@ARGV) {
+        my $buffer ;
+    
+        my $gz = gzopen($file, "rb") 
+             or die "Cannot open $file: $gzerrno\n" ;
+    
+        print $buffer while $gz->gzread($buffer) > 0 ;
+    
+        die "Error reading from $file: $gzerrno" . ($gzerrno+0) . "\n" 
+            if $gzerrno != Z_STREAM_END ;
+        
+        $gz->gzclose() ;
+    }
+
+Below is a script which makes use of B<gzreadline>. It implements a
+very simple I<grep> like script.
+
+    use strict ;
+    use warnings ;
+    
+    use Compress::Zlib ;
+    
+    die "Usage: gzgrep pattern file...\n"
+        unless @ARGV >= 2;
+    
+    my $pattern = shift ;
+    
+    my $file ;
+    
+    foreach $file (@ARGV) {
+        my $gz = gzopen($file, "rb") 
+             or die "Cannot open $file: $gzerrno\n" ;
+    
+        while ($gz->gzreadline($_) > 0) {
+            print if /$pattern/ ;
+        }
+    
+        die "Error reading from $file: $gzerrno\n" 
+            if $gzerrno != Z_STREAM_END ;
+        
+        $gz->gzclose() ;
+    }
+
+This script, I<gzstream>, does the opposite of the I<gzcat> script
+above. It reads from standard input and writes a gzip file to standard
+output.
+
+    use strict ;
+    use warnings ;
+    
+    use Compress::Zlib ;
+    
+    binmode STDOUT;    # gzopen only sets it on the fd
+    
+    my $gz = gzopen(\*STDOUT, "wb")
+         or die "Cannot open stdout: $gzerrno\n" ;
+    
+    while (<>) {
+        $gz->gzwrite($_) 
+       or die "error writing: $gzerrno\n" ;
+    }
+
+    $gz->gzclose ;
+
+=head2 Compress::Zlib::memGzip
+
+This function is used to create an in-memory gzip file. 
+It creates a minimal gzip header.
+
+    $dest = Compress::Zlib::memGzip($buffer) ;
+
+If successful, it returns the in-memory gzip file, otherwise it returns
+undef.
+
+The buffer parameter can either be a scalar or a scalar reference.
+
+=head2 Compress::Zlib::memGunzip
+
+This function is used to uncompress an in-memory gzip file.
+
+    $dest = Compress::Zlib::memGunzip($buffer) ;
+
+If successful, it returns the uncompressed gzip file, otherwise it
+returns undef.
+
+The buffer parameter can either be a scalar or a scalar reference. The
+contents of the buffer parameter are destroyed after calling this
+function.
+
+=head1 CHECKSUM FUNCTIONS
+
+Two functions are provided by I<zlib> to calculate a checksum. For the
+Perl interface, the order of the two parameters in both functions has
+been reversed. This allows both running checksums and one off
+calculations to be done.
+
+    $crc = adler32($buffer [,$crc]) ;
+    $crc = crc32($buffer [,$crc]) ;
+
+The buffer parameters can either be a scalar or a scalar reference.
+
+If the $crc parameters is C<undef>, the crc value will be reset.
+
+=head1 ACCESSING ZIP FILES
+
+Although it is possible to use this module to access .zip files, there
+is a module on CPAN that will do all the hard work for you. Check out
+
+    http://www.cpan.org/modules/by-module/Archive/Archive-Zip-*.tar.gz    
+
+Assuming you don't want to use this module to access zip files there
+are a number of undocumented features in the zlib library you need to
+be aware of.
+
+=over 5
+
+=item 1.
+
+When calling B<inflateInit> or B<deflateInit> the B<WindowBits> parameter
+must be set to C<-MAX_WBITS>. This disables the creation of the zlib
+header.
+
+=item 2.
+
+The zlib function B<inflate>, and so the B<inflate> method supplied in
+this module, assume that there is at least one trailing byte after the
+compressed data stream. Normally this isn't a problem because both
+the gzip and zip file formats will guarantee that there is data directly
+after the compressed data stream.
+
+=back
+
+=head1 CONSTANTS
+
+All the I<zlib> constants are automatically imported when you make use
+of I<Compress::Zlib>.
+
+=head1 AUTHOR
+
+The I<Compress::Zlib> module was written by Paul Marquess,
+F<pmqs@cpan.org>. The latest copy of the module can be
+found on CPAN in F<modules/by-module/Compress/Compress-Zlib-x.x.tar.gz>.
+
+The primary site for the I<zlib> compression library is
+F<http://www.zlib.org>.
+
+=head1 MODIFICATION HISTORY
+
+See the Changes file.
diff --git a/ext/Compress/Zlib/Zlib.xs b/ext/Compress/Zlib/Zlib.xs
new file mode 100644 (file)
index 0000000..2421f2c
--- /dev/null
@@ -0,0 +1,1066 @@
+/* Filename: Zlib.xs
+ * Author  : Paul Marquess, <pmqs@cpan.org>
+ * Created : 30 January 2005
+ * Version : 1.34
+ *
+ *   Copyright (c) 1995-2005 Paul Marquess. All rights reserved.
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the same terms as Perl itself.
+ *
+ */
+
+/* Part of this code is based on the file gzio.c */
+
+/* gzio.c -- IO on .gz files
+ * Copyright (C) 1995 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+
+
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+
+#include <zlib.h> 
+
+#ifndef PERL_VERSION
+#include "patchlevel.h"
+#define PERL_REVISION  5
+#define PERL_VERSION   PATCHLEVEL
+#define PERL_SUBVERSION        SUBVERSION
+#endif
+
+#if PERL_REVISION == 5 && (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION <= 75 ))
+
+#    define PL_sv_undef                sv_undef
+#    define PL_na              na
+#    define PL_curcop          curcop
+#    define PL_compiling       compiling
+
+#endif
+
+#ifndef newSVuv
+#    define newSVuv    newSViv
+#endif
+
+typedef struct di_stream {
+    z_stream stream;
+    uLong    bufsize; 
+    uLong    bufinc; 
+    SV *     dictionary ;
+    uLong    dict_adler ;
+    bool     deflateParams_out_valid ;
+    Bytef    deflateParams_out_byte;
+    int      Level;
+    int      Method;
+    int      WindowBits;
+    int      MemLevel;
+    int      Strategy;
+} di_stream;
+
+typedef di_stream * deflateStream ;
+typedef di_stream * Compress__Zlib__deflateStream ;
+typedef di_stream * inflateStream ;
+typedef di_stream * Compress__Zlib__inflateStream ;
+
+/* typedef gzFile Compress__Zlib__gzFile ; */
+typedef struct gzType {
+    gzFile gz ;
+    SV *   buffer ;
+    uLong   offset ;
+    bool   closed ;
+}  gzType ;
+
+typedef gzType* Compress__Zlib__gzFile ; 
+
+
+
+#define GZERRNO        "Compress::Zlib::gzerrno"
+
+#define ZMALLOC(to, typ) ((to = (typ *)safemalloc(sizeof(typ))), \
+                                Zero(to,1,typ))
+
+#define adlerInitial adler32(0L, Z_NULL, 0)
+#define crcInitial crc32(0L, Z_NULL, 0)
+
+#if 1
+static char *my_z_errmsg[] = {
+    "need dictionary",     /* Z_NEED_DICT     2 */
+    "stream end",          /* Z_STREAM_END    1 */
+    "",                    /* Z_OK            0 */
+    "file error",          /* Z_ERRNO        (-1) */
+    "stream error",        /* Z_STREAM_ERROR (-2) */
+    "data error",          /* Z_DATA_ERROR   (-3) */
+    "insufficient memory", /* Z_MEM_ERROR    (-4) */
+    "buffer error",        /* Z_BUF_ERROR    (-5) */
+    "incompatible version",/* Z_VERSION_ERROR(-6) */
+    ""};
+#endif
+
+
+static int trace = 0 ;
+
+static void
+#ifdef CAN_PROTOTYPE
+SetGzErrorNo(int error_no)
+#else
+SetGzErrorNo(error_no)
+int error_no ;
+#endif
+{
+    char * errstr ;
+    SV * gzerror_sv = perl_get_sv(GZERRNO, FALSE) ;
+  
+    if (error_no == Z_ERRNO) {
+        error_no = errno ;
+        errstr = Strerror(errno) ;
+    }
+    else
+        /* errstr = gzerror(fil, &error_no) ; */
+        errstr = (char*) my_z_errmsg[2 - error_no]; 
+
+    if (SvIV(gzerror_sv) != error_no) {
+        sv_setiv(gzerror_sv, error_no) ;
+        sv_setpv(gzerror_sv, errstr) ;
+        SvIOK_on(gzerror_sv) ;
+    }
+
+}
+
+static void
+#ifdef CAN_PROTOTYPE
+SetGzError(gzFile file)
+#else
+SetGzError(file)
+gzFile file ;
+#endif
+{
+    int error_no ;
+
+    (void)gzerror(file, &error_no) ;
+    SetGzErrorNo(error_no) ;
+}
+
+static void
+#ifdef CAN_PROTOTYPE
+DispHex(void * ptr, int length)
+#else
+DispHex(ptr, length)
+    void * ptr;
+    int length;
+#endif
+{
+    char * p = (char*)ptr;
+    int i;
+    for (i = 0; i < length; ++i) {
+        printf(" %02x", 0xFF & *(p+i));
+    }
+}
+
+
+static void
+#ifdef CAN_PROTOTYPE
+DispStream(di_stream * s, char * message)
+#else
+DispStream(s, message)
+    di_stream * s;
+    char * message;
+#endif
+{
+
+#if 0
+    if (! trace)
+        return ;
+#endif
+
+    printf("DispStream 0x%p - %s \n", s, message) ;
+
+    if (!s)  {
+       printf("    stream pointer is NULL\n");
+    }
+    else     {
+       printf("    stream           0x%p\n", &(s->stream));
+       printf("           zalloc    0x%p\n", s->stream.zalloc);
+       printf("           zfree     0x%p\n", s->stream.zfree);
+       printf("           opaque    0x%p\n", s->stream.opaque);
+       if (s->stream.msg)
+           printf("           msg       %s\n", s->stream.msg);
+       else
+           printf("           msg       \n");
+       printf("           next_in   0x%p", s->stream.next_in);
+       if (s->stream.next_in) {
+           printf(" =>");
+            DispHex(s->stream.next_in, 4);
+       }
+        printf("\n");
+
+       printf("           next_out  0x%p", s->stream.next_out);
+       if (s->stream.next_out){
+           printf(" =>");
+            DispHex(s->stream.next_out, 4);
+       }
+        printf("\n");
+
+       printf("           avail_in  %ld\n", s->stream.avail_in);
+       printf("           avail_out %ld\n", s->stream.avail_out);
+       printf("           total_in  %ld\n", s->stream.total_in);
+       printf("           total_out %ld\n", s->stream.total_out);
+       printf("           adler     0x%lx\n", s->stream.adler);
+       printf("           reserved  0x%lx\n", s->stream.reserved);
+       printf("    bufsize          %ld\n", s->bufsize);
+       printf("    dictionary       0x%p\n", s->dictionary);
+       printf("    dict_adler       0x%ld\n", s->dict_adler);
+       printf("\n");
+
+    }
+}
+
+
+static di_stream *
+#ifdef CAN_PROTOTYPE
+InitStream(uLong bufsize)
+#else
+InitStream(bufsize)
+    uLong bufsize ;
+#endif
+{
+    di_stream *s ;
+
+    ZMALLOC(s, di_stream) ;
+
+    if (s)  {
+        s->bufsize = bufsize ;
+        s->bufinc  = bufsize ;
+    }
+
+    return s ;
+    
+}
+
+#define SIZE 4096
+
+static int
+#ifdef CAN_PROTOTYPE
+gzreadline(Compress__Zlib__gzFile file, SV * output)
+#else
+gzreadline(file, output)
+  Compress__Zlib__gzFile file ;
+  SV * output ;
+#endif
+{
+
+    SV * store = file->buffer ;
+    char *nl = "\n"; 
+    char *p;
+    char *out_ptr = SvPVX(store) ;
+    int n;
+
+    while (1) {
+
+       /* anything left from last time */
+       if ((n = SvCUR(store))) {
+
+           out_ptr = SvPVX(store) + file->offset ;
+           if ((p = ninstr(out_ptr, out_ptr + n - 1, nl, nl))) {
+            /* if (rschar != 0777 && */
+                /* p = ninstr(out_ptr, out_ptr + n - 1, rs, rs+rslen-1)) { */
+
+               sv_catpvn(output, out_ptr, p - out_ptr + 1);
+
+               file->offset += (p - out_ptr + 1) ;
+               n = n - (p - out_ptr + 1);
+               SvCUR_set(store, n) ;
+               return SvCUR(output);
+            }
+           else /* no EOL, so append the complete buffer */
+               sv_catpvn(output, out_ptr, n);
+           
+       }
+
+
+       SvCUR_set(store, 0) ;
+       file->offset = 0 ;
+        out_ptr = SvPVX(store) ;
+
+       n = gzread(file->gz, out_ptr, SIZE) ;
+
+       if (n <= 0) 
+           /* Either EOF or an error */
+           /* so return what we have so far else signal eof */
+           return (SvCUR(output)>0) ? SvCUR(output) : n ;
+
+       SvCUR_set(store, n) ;
+    }
+}
+
+static SV* 
+#ifdef CAN_PROTOTYPE
+deRef(SV * sv, char * string)
+#else
+deRef(sv, string)
+SV * sv ;
+char * string;
+#endif
+{
+    if (SvROK(sv)) {
+       sv = SvRV(sv) ;
+       switch(SvTYPE(sv)) {
+            case SVt_PVAV:
+            case SVt_PVHV:
+            case SVt_PVCV:
+                croak("%s: buffer parameter is not a SCALAR reference", string);
+       }
+       if (SvROK(sv))
+           croak("%s: buffer parameter is a reference to a reference", string) ;
+    }
+
+    if (!SvOK(sv)) { 
+        sv = newSVpv("", 0);
+    }  
+    return sv ;
+}
+
+#include "constants.h"
+
+MODULE = Compress::Zlib                PACKAGE = Compress::Zlib        PREFIX = Zip_
+
+REQUIRE:       1.924
+PROTOTYPES:    DISABLE
+
+INCLUDE: constants.xs
+
+BOOT:
+    /* Check this version of zlib is == 1 */
+    if (zlibVersion()[0] != '1')
+       croak("Compress::Zlib needs zlib version 1.x\n") ;
+       
+    {
+        /* Create the $gzerror scalar */
+        SV * gzerror_sv = perl_get_sv(GZERRNO, GV_ADDMULTI) ;
+        sv_setiv(gzerror_sv, 0) ;
+        sv_setpv(gzerror_sv, "") ;
+        SvIOK_on(gzerror_sv) ;
+    }
+
+
+#define Zip_zlib_version()     (char*)zlib_version
+char*
+Zip_zlib_version()
+
+
+void
+DispStream(s, message=NULL)
+       Compress::Zlib::inflateStream   s
+       char *  message
+
+Compress::Zlib::gzFile
+gzopen_(path, mode)
+       char *  path
+       char *  mode
+       CODE:
+       gzFile  gz ;
+       gz = gzopen(path, mode) ;
+       if (gz) {
+           ZMALLOC(RETVAL, gzType) ;
+           RETVAL->buffer = newSV(SIZE) ;
+           SvPOK_only(RETVAL->buffer) ;
+           SvCUR_set(RETVAL->buffer, 0) ; 
+           RETVAL->offset = 0 ;
+           RETVAL->gz = gz ;
+           RETVAL->closed = FALSE ;
+           SetGzErrorNo(0) ;
+       }
+       else {
+           RETVAL = NULL ;
+           SetGzErrorNo(errno ? Z_ERRNO : Z_MEM_ERROR) ;
+       }
+       OUTPUT:
+         RETVAL
+
+
+Compress::Zlib::gzFile
+gzdopen_(fh, mode, offset)
+        int     fh
+        char *  mode
+        long    offset
+       CODE:
+        gzFile  gz ;
+        if (offset != -1)
+            lseek(fh, offset, 0) ; 
+        gz = gzdopen(fh, mode) ;
+        if (gz) {
+           ZMALLOC(RETVAL, gzType) ;
+            RETVAL->buffer = newSV(SIZE) ;
+            SvPOK_only(RETVAL->buffer) ;
+            SvCUR_set(RETVAL->buffer, 0) ;
+            RETVAL->offset = 0 ;
+            RETVAL->gz = gz ;
+           RETVAL->closed = FALSE ;
+           SetGzErrorNo(0) ;
+        }
+        else {
+            RETVAL = NULL ;
+           SetGzErrorNo(errno ? Z_ERRNO : Z_MEM_ERROR) ;
+       }
+        OUTPUT:
+          RETVAL
+
+
+MODULE = Compress::Zlib        PACKAGE = Compress::Zlib::gzFile PREFIX = Zip_
+
+#define Zip_gzread(file, buf, len) gzread(file->gz, bufp, len)
+
+int
+Zip_gzread(file, buf, len=4096)
+       Compress::Zlib::gzFile  file
+       unsigned        len
+       SV *            buf
+       voidp           bufp = NO_INIT
+       uLong           bufsize = 0 ;
+       int             RETVAL = 0 ;
+       CODE:
+       if (SvREADONLY(buf) && PL_curcop != &PL_compiling)
+            croak("gzread: buffer parameter is read-only");
+        if (!SvUPGRADE(buf, SVt_PV))
+            croak("cannot use buf argument as lvalue");
+        SvPOK_only(buf);
+        SvCUR_set(buf, 0);
+       /* any left over from gzreadline ? */
+       if ((bufsize = SvCUR(file->buffer)) > 0) {
+           uLong movesize ;
+       
+           if (bufsize < len) {
+               movesize = bufsize ;
+               len -= movesize ;
+           }
+           else {
+               movesize = len ;
+               len = 0 ;
+           }
+           RETVAL = movesize ;
+
+                   sv_catpvn(buf, SvPVX(file->buffer) + file->offset, movesize);
+
+           file->offset += movesize ;
+           SvCUR_set(file->buffer, bufsize - movesize) ;
+       }
+
+       if (len) {
+           bufp = (Byte*)SvGROW(buf, bufsize+len+1);
+           RETVAL = gzread(file->gz, ((Bytef*)bufp)+bufsize, len) ;
+           SetGzError(file->gz) ; 
+            if (RETVAL >= 0) {
+               RETVAL += bufsize ;
+                SvCUR_set(buf, RETVAL) ;
+                *SvEND(buf) = '\0';
+            }
+       }
+       OUTPUT:
+          RETVAL
+          buf
+
+int
+gzreadline(file, buf)
+       Compress::Zlib::gzFile  file
+       SV *            buf
+       int             RETVAL = 0;
+       CODE:
+       if (SvREADONLY(buf) && PL_curcop != &PL_compiling) 
+            croak("gzreadline: buffer parameter is read-only"); 
+        if (!SvUPGRADE(buf, SVt_PV))
+            croak("cannot use buf argument as lvalue");
+        SvPOK_only(buf);
+       /* sv_setpvn(buf, "", SIZE) ; */
+        SvGROW(buf, SIZE) ;
+        SvCUR_set(buf, 0);
+       RETVAL = gzreadline(file, buf) ;
+       SetGzError(file->gz) ; 
+       OUTPUT:
+         RETVAL
+         buf
+       CLEANUP:
+        if (RETVAL >= 0) {
+            /* SvCUR(buf) = RETVAL; */
+            /* Don't need to explicitly terminate with '\0', because
+               sv_catpvn aready has */
+        }
+
+#define Zip_gzwrite(file, buf) gzwrite(file->gz, buf, (unsigned)len)
+int
+Zip_gzwrite(file, buf)
+       Compress::Zlib::gzFile  file
+       STRLEN          len = NO_INIT
+       voidp           buf = (voidp)SvPV(ST(1), len) ;
+       CLEANUP:
+         SetGzError(file->gz) ;
+
+#define Zip_gzflush(file, flush) gzflush(file->gz, flush) 
+int
+Zip_gzflush(file, flush)
+       Compress::Zlib::gzFile  file
+       int             flush
+       CLEANUP:
+         SetGzError(file->gz) ;
+
+#define Zip_gzclose(file) gzclose(file->gz)
+int
+Zip_gzclose(file)
+       Compress::Zlib::gzFile          file
+       CLEANUP:
+         file->closed = TRUE ;
+         SetGzErrorNo(RETVAL) ;
+
+
+#define Zip_gzeof(file) gzeof(file->gz)
+int
+Zip_gzeof(file)
+       Compress::Zlib::gzFile          file
+       CODE:
+#ifdef OLD_ZLIB
+       croak("gzeof needs zlib 1.0.6 or better") ;
+#else
+       RETVAL = gzeof(file->gz);
+#endif
+       OUTPUT:
+           RETVAL
+
+
+#define Zip_gzsetparams(file,l,s) gzsetparams(file->gz,l,s)
+int
+Zip_gzsetparams(file, level, strategy)
+       Compress::Zlib::gzFile          file
+       int             level
+       int             strategy
+       CODE:
+#ifdef OLD_ZLIB
+       croak("gzsetparams needs zlib 1.0.6 or better") ;
+#else
+       RETVAL = gzsetparams(file->gz, level, strategy);
+#endif
+       OUTPUT:
+           RETVAL
+
+void
+DESTROY(file)
+       Compress::Zlib::gzFile          file
+       CODE:
+           if (! file->closed)
+               Zip_gzclose(file) ;
+           SvREFCNT_dec(file->buffer) ;
+           safefree((char*)file) ;
+
+#define Zip_gzerror(file) (char*)gzerror(file->gz, &errnum)
+
+char *
+Zip_gzerror(file)
+       Compress::Zlib::gzFile  file
+       int             errnum = NO_INIT
+       CLEANUP:
+           sv_setiv(ST(0), errnum) ;
+            SvPOK_on(ST(0)) ;
+
+
+
+MODULE = Compress::Zlib        PACKAGE = Compress::Zlib        PREFIX = Zip_
+
+
+#define Zip_adler32(buf, adler) adler32(adler, buf, (uInt)len)
+
+uLong
+Zip_adler32(buf, adler=adlerInitial)
+        uLong    adler = NO_INIT
+        STRLEN   len = NO_INIT
+        Bytef *  buf = NO_INIT
+       SV *     sv = ST(0) ;
+       INIT:
+       /* If the buffer is a reference, dereference it */
+       sv = deRef(sv, "adler32") ;
+       buf = (Byte*)SvPV(sv, len) ;
+
+       if (items < 2)
+         adler = adlerInitial;
+       else if (SvOK(ST(1)))
+         adler = SvUV(ST(1)) ;
+       else
+         adler = adlerInitial;
+#define Zip_crc32(buf, crc) crc32(crc, buf, (uInt)len)
+
+uLong
+Zip_crc32(buf, crc=crcInitial)
+        uLong    crc = NO_INIT
+        STRLEN   len = NO_INIT
+        Bytef *  buf = NO_INIT
+       SV *     sv = ST(0) ;
+       INIT:
+       /* If the buffer is a reference, dereference it */
+       sv = deRef(sv, "crc32") ;
+       buf = (Byte*)SvPV(sv, len) ;
+
+       if (items < 2)
+         crc = crcInitial;
+       else if (SvOK(ST(1)))
+         crc = SvUV(ST(1)) ;
+       else
+         crc = crcInitial;
+
+MODULE = Compress::Zlib PACKAGE = Compress::Zlib
+
+void
+_deflateInit(level, method, windowBits, memLevel, strategy, bufsize, dictionary)
+    int        level
+    int method
+    int windowBits
+    int memLevel
+    int strategy
+    uLong bufsize
+    SV * dictionary
+  PPCODE:
+
+    int err ;
+    deflateStream s ;
+
+    if (trace)
+        warn("in _deflateInit(level=%d, method=%d, windowBits=%d, memLevel=%d, strategy=%d, bufsize=%d\n",
+       level, method, windowBits, memLevel, strategy, bufsize) ;
+    if ((s = InitStream(bufsize)) ) {
+
+        s->Level      = level;
+        s->Method     = method;
+        s->WindowBits = windowBits;
+        s->MemLevel   = memLevel;
+        s->Strategy   = strategy;
+
+        err = deflateInit2(&(s->stream), level, 
+                          method, windowBits, memLevel, strategy);
+
+       /* Check if a dictionary has been specified */
+       if (err == Z_OK && SvCUR(dictionary)) {
+           err = deflateSetDictionary(&(s->stream), (const Bytef*) SvPVX(dictionary), 
+                                       SvCUR(dictionary)) ;
+           s->dict_adler = s->stream.adler ;
+       }
+
+        if (err != Z_OK) {
+            Safefree(s) ;
+            s = NULL ;
+       }
+        
+    }
+    else
+        err = Z_MEM_ERROR ;
+
+    XPUSHs(sv_setref_pv(sv_newmortal(), 
+       "Compress::Zlib::deflateStream", (void*)s));
+    if (GIMME == G_ARRAY) 
+        XPUSHs(sv_2mortal(newSViv(err))) ;
+
+void
+_inflateInit(windowBits, bufsize, dictionary)
+    int windowBits
+    uLong bufsize
+    SV * dictionary
+  PPCODE:
+    int err = Z_OK ;
+    inflateStream s ;
+    if (trace)
+        warn("in _inflateInit(windowBits=%d, bufsize=%d, dictionary=%d\n",
+                windowBits, bufsize, SvCUR(dictionary)) ;
+    if ((s = InitStream(bufsize)) ) {
+
+        s->WindowBits = windowBits;
+
+        err = inflateInit2(&(s->stream), windowBits);
+        if (err != Z_OK) {
+            Safefree(s) ;
+            s = NULL ;
+       }
+       else if (SvCUR(dictionary)) {
+            /* Dictionary specified - take a copy for use in inflate */
+           s->dictionary = newSVsv(dictionary) ;
+       }
+    }
+    else
+       err = Z_MEM_ERROR ;
+
+    XPUSHs(sv_setref_pv(sv_newmortal(), 
+                   "Compress::Zlib::inflateStream", (void*)s));
+    if (GIMME == G_ARRAY) 
+        XPUSHs(sv_2mortal(newSViv(err))) ;
+
+
+MODULE = Compress::Zlib PACKAGE = Compress::Zlib::deflateStream
+
+void
+DispStream(s, message=NULL)
+       Compress::Zlib::deflateStream   s
+       char *  message
+
+void 
+deflate (s, buf)
+    Compress::Zlib::deflateStream      s
+    SV *       buf
+    uLong      outsize = NO_INIT 
+    SV *       output = NO_INIT
+    int                err = 0;
+  PPCODE:
+  
+    /* If the buffer is a reference, dereference it */
+    buf = deRef(buf, "deflate") ;
+    /* initialise the input buffer */
+    s->stream.next_in = (Bytef*)SvPV(buf, *(STRLEN*)&s->stream.avail_in) ;
+    /* s->stream.next_in = (Bytef*)SvPVX(buf); */
+    s->stream.avail_in = SvCUR(buf) ;
+
+    /* and the output buffer */
+    /* output = sv_2mortal(newSVpv("", s->bufinc)) ; */
+    output = sv_2mortal(newSV(s->bufinc)) ;
+    SvPOK_only(output) ;
+    SvCUR_set(output, 0) ; 
+    outsize = s->bufinc ;
+    s->stream.next_out = (Bytef*) SvPVX(output) ;
+    s->stream.avail_out = outsize;
+
+    /* Check for saved output from deflateParams */
+    if (s->deflateParams_out_valid) {
+       *(s->stream.next_out) = s->deflateParams_out_byte;
+       ++ s->stream.next_out;
+       -- s->stream.avail_out ;
+       s->deflateParams_out_valid = FALSE;
+    }
+
+    while (s->stream.avail_in != 0) {
+
+        if (s->stream.avail_out == 0) {
+            s->bufinc *= 2 ;
+            SvGROW(output, outsize + s->bufinc) ;
+            s->stream.next_out = (Bytef*) SvPVX(output) + outsize ;
+            outsize += s->bufinc ;
+            s->stream.avail_out = s->bufinc ;
+        }
+        err = deflate(&(s->stream), Z_NO_FLUSH);
+        if (err != Z_OK) 
+            break;
+    }
+
+    if (err == Z_OK) {
+        SvPOK_only(output);
+        SvCUR_set(output, outsize - s->stream.avail_out) ;
+    }
+    else
+        output = &PL_sv_undef ;
+    XPUSHs(output) ;
+    if (GIMME == G_ARRAY) 
+        XPUSHs(sv_2mortal(newSViv(err))) ;
+  
+
+
+void
+flush(s, f=Z_FINISH)
+    Compress::Zlib::deflateStream      s
+    int        f
+    uLong      outsize = NO_INIT
+    SV * output = NO_INIT
+    int err = Z_OK ;
+  PPCODE:
+  
+    s->stream.avail_in = 0; /* should be zero already anyway */
+  
+    /* output = sv_2mortal(newSVpv("", s->bufinc)) ; */
+    output = sv_2mortal(newSV(s->bufinc)) ;
+    SvPOK_only(output) ;
+    SvCUR_set(output, 0) ; 
+    outsize = s->bufinc ;
+    s->stream.next_out = (Bytef*) SvPVX(output) ;
+    s->stream.avail_out = outsize;
+      
+    /* Check for saved output from deflateParams */
+    if (s->deflateParams_out_valid) {
+       *(s->stream.next_out) = s->deflateParams_out_byte;
+       ++ s->stream.next_out;
+       -- s->stream.avail_out ;
+       s->deflateParams_out_valid = FALSE;
+    }
+
+    for (;;) {
+        if (s->stream.avail_out == 0) {
+           /* consumed all the available output, so extend it */
+            s->bufinc *= 2 ;
+           SvGROW(output, outsize + s->bufinc) ;
+            s->stream.next_out = (Bytef*)SvPVX(output) + outsize ;
+           outsize += s->bufinc ;
+            s->stream.avail_out = s->bufinc ;
+        }
+        err = deflate(&(s->stream), f);
+    
+        /* deflate has finished flushing only when it hasn't used up
+         * all the available space in the output buffer: 
+         */
+        if (s->stream.avail_out != 0 || err != Z_OK )
+            break;
+    }
+  
+    err =  (err == Z_STREAM_END ? Z_OK : err) ;
+  
+    if (err == Z_OK) {
+        SvPOK_only(output);
+        SvCUR_set(output, outsize - s->stream.avail_out) ;
+    }
+    else
+        output = &PL_sv_undef ;
+    XPUSHs(output) ;
+    if (GIMME == G_ARRAY) 
+        XPUSHs(sv_2mortal(newSViv(err))) ;
+
+int
+_deflateParams(s, flags, level, strategy, bufsize)
+       Compress::Zlib::deflateStream   s
+       int     flags
+       int     level
+       int     strategy
+       uLong   bufsize
+    CODE:
+       if (flags & 1)
+           s->Level = level ;
+       if (flags & 2)
+           s->Strategy = strategy ;
+        if (bufsize) {
+            s->bufsize = bufsize; 
+            s->bufinc  = bufsize; 
+       }
+        s->stream.avail_in = 0; 
+        s->stream.next_out = &(s->deflateParams_out_byte) ;
+        s->stream.avail_out = 1;
+       RETVAL = deflateParams(&(s->stream), s->Level, s->Strategy);
+       s->deflateParams_out_valid = 
+               (RETVAL == Z_OK && s->stream.avail_out == 0) ;
+    OUTPUT:
+       RETVAL
+
+
+int
+get_Level(s)
+        Compress::Zlib::deflateStream   s
+    CODE:
+       RETVAL = s->Level ;
+    OUTPUT:
+       RETVAL
+
+int
+get_Strategy(s)
+        Compress::Zlib::deflateStream   s
+    CODE:
+       RETVAL = s->Strategy ;
+    OUTPUT:
+       RETVAL
+
+void
+DESTROY(s)
+    Compress::Zlib::deflateStream      s
+  CODE:
+    deflateEnd(&s->stream) ;
+    if (s->dictionary)
+       SvREFCNT_dec(s->dictionary) ;
+    Safefree(s) ;
+
+
+uLong
+dict_adler(s)
+        Compress::Zlib::deflateStream   s
+    CODE:
+       RETVAL = s->dict_adler ;
+    OUTPUT:
+       RETVAL
+
+uLong
+total_in(s)
+        Compress::Zlib::deflateStream   s
+    CODE:
+       RETVAL = s->stream.total_in ;
+    OUTPUT:
+       RETVAL
+
+uLong
+total_out(s)
+        Compress::Zlib::deflateStream   s
+    CODE:
+       RETVAL = s->stream.total_out ;
+    OUTPUT:
+       RETVAL
+
+char*
+msg(s)
+        Compress::Zlib::deflateStream   s
+    CODE:
+        RETVAL = s->stream.msg;
+    OUTPUT:
+       RETVAL
+
+
+MODULE = Compress::Zlib PACKAGE = Compress::Zlib::inflateStream
+
+void
+DispStream(s, message=NULL)
+       Compress::Zlib::inflateStream   s
+       char *  message
+
+void 
+inflate (s, buf)
+    Compress::Zlib::inflateStream      s
+    SV *       buf
+    uLong      outsize = NO_INIT 
+    SV *       output = NO_INIT
+    int                err = Z_OK ;
+  ALIAS:
+    __unc_inflate = 1
+  PPCODE:
+  
+    /* If the buffer is a reference, dereference it */
+    buf = deRef(buf, "inflate") ;
+    
+    /* initialise the input buffer */
+    s->stream.next_in = (Bytef*)SvPVX(buf) ;
+    s->stream.avail_in = SvCUR(buf) ;
+       
+    /* and the output buffer */
+    output = sv_2mortal(newSV(s->bufinc+1)) ;
+    SvPOK_only(output) ;
+    SvCUR_set(output, 0) ; 
+    outsize = s->bufinc ;
+    s->stream.next_out = (Bytef*) SvPVX(output)  ;
+    s->stream.avail_out = outsize;
+
+    while (1) {
+
+        if (s->stream.avail_out == 0) {
+            s->bufinc *= 2 ;
+            SvGROW(output, outsize + s->bufinc+1) ;
+            s->stream.next_out = (Bytef*) SvPVX(output) + outsize ;
+            outsize += s->bufinc ;
+            s->stream.avail_out = s->bufinc ;
+        }
+
+        err = inflate(&(s->stream), Z_SYNC_FLUSH);
+       if (err == Z_BUF_ERROR) {
+           if (s->stream.avail_out == 0)
+               continue ;
+           if (s->stream.avail_in == 0) {
+               err = Z_OK ;
+               break ;
+           }
+       }
+
+       if (err == Z_NEED_DICT && s->dictionary) {
+           s->dict_adler = s->stream.adler ;
+            err = inflateSetDictionary(&(s->stream), 
+                                       (const Bytef*)SvPVX(s->dictionary),
+                                       SvCUR(s->dictionary));
+       }
+       
+        if (err != Z_OK) 
+            break;
+    }
+
+    if (err == Z_OK || err == Z_STREAM_END || err == Z_DATA_ERROR) {
+       unsigned in ;
+       
+        SvPOK_only(output);
+        SvCUR_set(output, outsize - s->stream.avail_out) ;
+        *SvEND(output) = '\0';
+       
+       /* fix the input buffer */
+       if (ix == 0) {
+           in = s->stream.avail_in ;
+           SvCUR_set(buf, in) ;
+           if (in)
+               Move(s->stream.next_in, SvPVX(buf), in, char) ; 
+            *SvEND(buf) = '\0';
+            SvSETMAGIC(buf);
+       }
+    }
+    else
+        output = &PL_sv_undef ;
+    XPUSHs(output) ;
+    if (GIMME == G_ARRAY) 
+        XPUSHs(sv_2mortal(newSViv(err))) ;
+
+int 
+inflateSync (s, buf)
+    Compress::Zlib::inflateStream      s
+    SV *       buf
+  CODE:
+  
+    /* If the buffer is a reference, dereference it */
+    buf = deRef(buf, "inflateSync") ;
+    
+    /* initialise the input buffer */
+    s->stream.next_in = (Bytef*)SvPVX(buf) ;
+    s->stream.avail_in = SvCUR(buf) ;
+       
+    /* inflateSync doesn't create any output */
+    s->stream.next_out = (Bytef*) NULL;
+    s->stream.avail_out = 0;
+
+    RETVAL = inflateSync(&(s->stream));
+    {
+       /* fix the input buffer */
+       unsigned in = s->stream.avail_in ;
+       
+       SvCUR_set(buf, in) ;
+       if (in)
+           Move(s->stream.next_in, SvPVX(buf), in, char) ;     
+        *SvEND(buf) = '\0';
+        SvSETMAGIC(buf);
+    }
+    OUTPUT:
+       RETVAL
+
+void
+DESTROY(s)
+    Compress::Zlib::inflateStream      s
+  CODE:
+    inflateEnd(&s->stream) ;
+    if (s->dictionary)
+       SvREFCNT_dec(s->dictionary) ;
+    Safefree(s) ;
+
+
+uLong
+dict_adler(s)
+        Compress::Zlib::inflateStream   s
+    CODE:
+       RETVAL = s->dict_adler ;
+    OUTPUT:
+       RETVAL
+
+uLong
+total_in(s)
+        Compress::Zlib::inflateStream   s
+    CODE:
+       RETVAL = s->stream.total_in ;
+    OUTPUT:
+       RETVAL
+
+uLong
+total_out(s)
+        Compress::Zlib::inflateStream   s
+    CODE:
+       RETVAL = s->stream.total_out ;
+    OUTPUT:
+       RETVAL
+
+char*
+msg(s)
+       Compress::Zlib::inflateStream   s
+    CODE:
+        RETVAL = s->stream.msg;
+    OUTPUT:
+       RETVAL
+
+
diff --git a/ext/Compress/Zlib/config.in b/ext/Compress/Zlib/config.in
new file mode 100755 (executable)
index 0000000..88c1061
--- /dev/null
@@ -0,0 +1,21 @@
+# Filename:    config.in
+#
+# written by Paul Marquess <pmqs@cpan.org>
+# last modified 30th January 2005
+# version 1.34
+# 
+# 
+# This file is used to control which zlib library will be used by
+# Compress::Zlib
+# 
+# See to the section "Controlling the version of zlib used by
+# Compress::Zlib" in the README file for details of how to use this file.
+
+BUILD_ZLIB = True
+INCLUDE    = ./zlib-src-1.2.2
+LIB        = ./zlib-src-1.2.2
+OLD_ZLIB   = False
+
+
+
+# end of file config.in
diff --git a/ext/Compress/Zlib/examples/filtdef b/ext/Compress/Zlib/examples/filtdef
new file mode 100755 (executable)
index 0000000..5cbc882
--- /dev/null
@@ -0,0 +1,29 @@
+#!/usr/local/bin/perl
+
+use strict ;
+local ($^W) = 1; #use warnings ;
+
+use Compress::Zlib ;
+
+binmode STDIN;
+binmode STDOUT;
+my $x = deflateInit()
+   or die "Cannot create a deflation stream\n" ;
+
+my ($output, $status) ;
+while (<>)
+{
+    ($output, $status) = $x->deflate($_) ;
+
+    $status == Z_OK
+        or die "deflation failed\n" ;
+
+    print $output ;
+}
+
+($output, $status) = $x->flush() ;
+
+$status == Z_OK
+    or die "deflation failed\n" ;
+
+print $output ;
diff --git a/ext/Compress/Zlib/examples/filtinf b/ext/Compress/Zlib/examples/filtinf
new file mode 100755 (executable)
index 0000000..f65ed8c
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/local/bin/perl
+
+use strict ;
+local ($^W) = 1; #use warnings ;
+
+use Compress::Zlib ;
+
+my $x = inflateInit()
+   or die "Cannot create a inflation stream\n" ;
+
+my $input = '' ;
+binmode STDIN;
+binmode STDOUT;
+
+my ($output, $status) ;
+while (read(STDIN, $input, 4096))
+{
+    ($output, $status) = $x->inflate(\$input) ;
+
+    print $output 
+        if $status == Z_OK or $status == Z_STREAM_END ;
+
+    last if $status != Z_OK ;
+}
+
+die "inflation failed\n"
+    unless $status == Z_STREAM_END ;
+
diff --git a/ext/Compress/Zlib/examples/gzcat b/ext/Compress/Zlib/examples/gzcat
new file mode 100755 (executable)
index 0000000..6c595b8
--- /dev/null
@@ -0,0 +1,30 @@
+#!/usr/local/bin/perl
+
+use strict ;
+local ($^W) = 1; #use warnings ;
+
+use Compress::Zlib ;
+
+#die "Usage: gzcat file...\n"
+#    unless @ARGV ;
+
+my $filename ;
+
+@ARGV = '-' unless @ARGV ;
+
+foreach my $filename (@ARGV) {
+    my $buffer ;
+
+    my $file = $filename ;
+    $file = \*STDIN if $file eq '-' ;
+
+    my $gz = gzopen($file, "rb") 
+         or die "Cannot open $file: $gzerrno\n" ;
+
+    print $buffer while $gz->gzread($buffer) > 0 ;
+
+    die "Error reading from $filename: $gzerrno" . ($gzerrno+0) . "\n" 
+        if $gzerrno != Z_STREAM_END ;
+    
+    $gz->gzclose() ;
+}
diff --git a/ext/Compress/Zlib/examples/gzgrep b/ext/Compress/Zlib/examples/gzgrep
new file mode 100755 (executable)
index 0000000..26f8939
--- /dev/null
@@ -0,0 +1,27 @@
+#!/usr/local/bin/perl
+
+use strict ;
+local ($^W) = 1; #use warnings ;
+
+use Compress::Zlib ;
+
+die "Usage: gzgrep pattern file...\n"
+    unless @ARGV >= 2;
+
+my $pattern = shift ;
+
+my $file ;
+
+foreach $file (@ARGV) {
+    my $gz = gzopen($file, "rb") 
+         or die "Cannot open $file: $gzerrno\n" ;
+
+    while ($gz->gzreadline($_) > 0) {
+        print if /$pattern/ ;
+    }
+
+    die "Error reading from $file: $gzerrno\n" 
+        if $gzerrno != Z_STREAM_END ;
+    
+    $gz->gzclose() ;
+}
diff --git a/ext/Compress/Zlib/examples/gzstream b/ext/Compress/Zlib/examples/gzstream
new file mode 100755 (executable)
index 0000000..22d3d27
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/local/bin/perl
+
+use strict ;
+local ($^W) = 1; #use warnings ;
+
+use Compress::Zlib ;
+
+binmode STDOUT;        # gzopen only sets it on the fd
+
+my $gz = gzopen(\*STDOUT, "wb")
+         or die "Cannot open stdout: $gzerrno\n" ;
+
+while (<>) {
+    $gz->gzwrite($_) 
+       or die "error writing: $gzerrno\n" ;
+}
+
+$gz->gzclose ;
diff --git a/ext/Compress/Zlib/fallback.h b/ext/Compress/Zlib/fallback.h
new file mode 100644 (file)
index 0000000..2aef05e
--- /dev/null
@@ -0,0 +1,497 @@
+#define PERL_constant_NOTFOUND 1
+#define PERL_constant_NOTDEF   2
+#define PERL_constant_ISIV     3
+#define PERL_constant_ISNO     4
+#define PERL_constant_ISNV     5
+#define PERL_constant_ISPV     6
+#define PERL_constant_ISPVN    7
+#define PERL_constant_ISSV     8
+#define PERL_constant_ISUNDEF  9
+#define PERL_constant_ISUV     10
+#define PERL_constant_ISYES    11
+
+#ifndef NVTYPE
+typedef double NV; /* 5.6 and later define NVTYPE, and typedef NV to it.  */
+#endif
+#ifndef aTHX_
+#define aTHX_ /* 5.6 or later define this for threading support.  */
+#endif
+#ifndef pTHX_
+#define pTHX_ /* 5.6 or later define this for threading support.  */
+#endif
+
+static int
+constant_7 (pTHX_ const char *name, IV *iv_return) {
+  /* When generated this function returned values for the list of names given
+     here.  However, subsequent manual editing may have added or removed some.
+     OS_CODE Z_ASCII Z_ERRNO */
+  /* Offset 5 gives the best switch position.  */
+  switch (name[5]) {
+  case 'D':
+    if (memEQ(name, "OS_CODE", 7)) {
+    /*                    ^       */
+#ifdef OS_CODE
+      *iv_return = OS_CODE;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'I':
+    if (memEQ(name, "Z_ASCII", 7)) {
+    /*                    ^       */
+#ifdef Z_ASCII
+      *iv_return = Z_ASCII;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'N':
+    if (memEQ(name, "Z_ERRNO", 7)) {
+    /*                    ^       */
+#ifdef Z_ERRNO
+      *iv_return = Z_ERRNO;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  }
+  return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_9 (pTHX_ const char *name, IV *iv_return) {
+  /* When generated this function returned values for the list of names given
+     here.  However, subsequent manual editing may have added or removed some.
+     DEF_WBITS MAX_WBITS Z_UNKNOWN */
+  /* Offset 2 gives the best switch position.  */
+  switch (name[2]) {
+  case 'F':
+    if (memEQ(name, "DEF_WBITS", 9)) {
+    /*                 ^            */
+#ifdef DEF_WBITS
+      *iv_return = DEF_WBITS;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'U':
+    if (memEQ(name, "Z_UNKNOWN", 9)) {
+    /*                 ^            */
+#ifdef Z_UNKNOWN
+      *iv_return = Z_UNKNOWN;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'X':
+    if (memEQ(name, "MAX_WBITS", 9)) {
+    /*                 ^            */
+#ifdef MAX_WBITS
+      *iv_return = MAX_WBITS;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  }
+  return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_10 (pTHX_ const char *name, IV *iv_return) {
+  /* When generated this function returned values for the list of names given
+     here.  However, subsequent manual editing may have added or removed some.
+     Z_DEFLATED Z_FILTERED Z_NO_FLUSH */
+  /* Offset 7 gives the best switch position.  */
+  switch (name[7]) {
+  case 'R':
+    if (memEQ(name, "Z_FILTERED", 10)) {
+    /*                      ^         */
+#ifdef Z_FILTERED
+      *iv_return = Z_FILTERED;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'T':
+    if (memEQ(name, "Z_DEFLATED", 10)) {
+    /*                      ^         */
+#ifdef Z_DEFLATED
+      *iv_return = Z_DEFLATED;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'U':
+    if (memEQ(name, "Z_NO_FLUSH", 10)) {
+    /*                      ^         */
+#ifdef Z_NO_FLUSH
+      *iv_return = Z_NO_FLUSH;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  }
+  return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_11 (pTHX_ const char *name, IV *iv_return) {
+  /* When generated this function returned values for the list of names given
+     here.  However, subsequent manual editing may have added or removed some.
+     Z_BUF_ERROR Z_MEM_ERROR Z_NEED_DICT */
+  /* Offset 4 gives the best switch position.  */
+  switch (name[4]) {
+  case 'E':
+    if (memEQ(name, "Z_NEED_DICT", 11)) {
+    /*                   ^             */
+#ifdef Z_NEED_DICT
+      *iv_return = Z_NEED_DICT;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'F':
+    if (memEQ(name, "Z_BUF_ERROR", 11)) {
+    /*                   ^             */
+#ifdef Z_BUF_ERROR
+      *iv_return = Z_BUF_ERROR;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'M':
+    if (memEQ(name, "Z_MEM_ERROR", 11)) {
+    /*                   ^             */
+#ifdef Z_MEM_ERROR
+      *iv_return = Z_MEM_ERROR;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  }
+  return PERL_constant_NOTFOUND;
+}
+
+static int
+constant_12 (pTHX_ const char *name, IV *iv_return, const char **pv_return) {
+  /* When generated this function returned values for the list of names given
+     here.  However, subsequent manual editing may have added or removed some.
+     ZLIB_VERSION Z_BEST_SPEED Z_DATA_ERROR Z_FULL_FLUSH Z_STREAM_END
+     Z_SYNC_FLUSH */
+  /* Offset 4 gives the best switch position.  */
+  switch (name[4]) {
+  case 'L':
+    if (memEQ(name, "Z_FULL_FLUSH", 12)) {
+    /*                   ^              */
+#ifdef Z_FULL_FLUSH
+      *iv_return = Z_FULL_FLUSH;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'N':
+    if (memEQ(name, "Z_SYNC_FLUSH", 12)) {
+    /*                   ^              */
+#ifdef Z_SYNC_FLUSH
+      *iv_return = Z_SYNC_FLUSH;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'R':
+    if (memEQ(name, "Z_STREAM_END", 12)) {
+    /*                   ^              */
+#ifdef Z_STREAM_END
+      *iv_return = Z_STREAM_END;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'S':
+    if (memEQ(name, "Z_BEST_SPEED", 12)) {
+    /*                   ^              */
+#ifdef Z_BEST_SPEED
+      *iv_return = Z_BEST_SPEED;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'T':
+    if (memEQ(name, "Z_DATA_ERROR", 12)) {
+    /*                   ^              */
+#ifdef Z_DATA_ERROR
+      *iv_return = Z_DATA_ERROR;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case '_':
+    if (memEQ(name, "ZLIB_VERSION", 12)) {
+    /*                   ^              */
+#ifdef ZLIB_VERSION
+      *pv_return = ZLIB_VERSION;
+      return PERL_constant_ISPV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  }
+  return PERL_constant_NOTFOUND;
+}
+
+static int
+constant (pTHX_ const char *name, STRLEN len, IV *iv_return, const char **pv_return) {
+  /* Initially switch on the length of the name.  */
+  /* When generated this function returned values for the list of names given
+     in this section of perl code.  Rather than manually editing these functions
+     to add or remove constants, which would result in this comment and section
+     of code becoming inaccurate, we recommend that you edit this section of
+     code, and use it to regenerate a new set of constant functions which you
+     then use to replace the originals.
+
+     Regenerate these constant functions by feeding this entire source file to
+     perl -x
+
+#!/home/paul/perl/install/redhat6.1/bleed/bin/perl5.7.2 -w
+use ExtUtils::Constant qw (constant_types C_constant XS_constant);
+
+my $types = {map {($_, 1)} qw(IV PV)};
+my @names = (qw(DEF_WBITS MAX_MEM_LEVEL MAX_WBITS OS_CODE Z_ASCII
+              Z_BEST_COMPRESSION Z_BEST_SPEED Z_BINARY Z_BUF_ERROR
+              Z_DATA_ERROR Z_DEFAULT_COMPRESSION Z_DEFAULT_STRATEGY Z_DEFLATED
+              Z_ERRNO Z_FILTERED Z_FINISH Z_FULL_FLUSH Z_HUFFMAN_ONLY
+              Z_MEM_ERROR Z_NEED_DICT Z_NO_COMPRESSION Z_NO_FLUSH Z_NULL Z_OK
+              Z_PARTIAL_FLUSH Z_STREAM_END Z_STREAM_ERROR Z_SYNC_FLUSH
+              Z_UNKNOWN Z_VERSION_ERROR),
+            {name=>"ZLIB_VERSION", type=>"PV"});
+
+print constant_types(); # macro defs
+foreach (C_constant ("Zlib", 'constant', 'IV', $types, undef, 3, @names) ) {
+    print $_, "\n"; # C constant subs
+}
+print "#### XS Section:\n";
+print XS_constant ("Zlib", $types);
+__END__
+   */
+
+  switch (len) {
+  case 4:
+    if (memEQ(name, "Z_OK", 4)) {
+#ifdef Z_OK
+      *iv_return = Z_OK;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 6:
+    if (memEQ(name, "Z_NULL", 6)) {
+#ifdef Z_NULL
+      *iv_return = Z_NULL;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 7:
+    return constant_7 (aTHX_ name, iv_return);
+    break;
+  case 8:
+    /* Names all of length 8.  */
+    /* Z_BINARY Z_FINISH */
+    /* Offset 6 gives the best switch position.  */
+    switch (name[6]) {
+    case 'R':
+      if (memEQ(name, "Z_BINARY", 8)) {
+      /*                     ^       */
+#ifdef Z_BINARY
+        *iv_return = Z_BINARY;
+        return PERL_constant_ISIV;
+#else
+        return PERL_constant_NOTDEF;
+#endif
+      }
+      break;
+    case 'S':
+      if (memEQ(name, "Z_FINISH", 8)) {
+      /*                     ^       */
+#ifdef Z_FINISH
+        *iv_return = Z_FINISH;
+        return PERL_constant_ISIV;
+#else
+        return PERL_constant_NOTDEF;
+#endif
+      }
+      break;
+    }
+    break;
+  case 9:
+    return constant_9 (aTHX_ name, iv_return);
+    break;
+  case 10:
+    return constant_10 (aTHX_ name, iv_return);
+    break;
+  case 11:
+    return constant_11 (aTHX_ name, iv_return);
+    break;
+  case 12:
+    return constant_12 (aTHX_ name, iv_return, pv_return);
+    break;
+  case 13:
+    if (memEQ(name, "MAX_MEM_LEVEL", 13)) {
+#ifdef MAX_MEM_LEVEL
+      *iv_return = MAX_MEM_LEVEL;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 14:
+    /* Names all of length 14.  */
+    /* Z_HUFFMAN_ONLY Z_STREAM_ERROR */
+    /* Offset 3 gives the best switch position.  */
+    switch (name[3]) {
+    case 'T':
+      if (memEQ(name, "Z_STREAM_ERROR", 14)) {
+      /*                  ^                 */
+#ifdef Z_STREAM_ERROR
+        *iv_return = Z_STREAM_ERROR;
+        return PERL_constant_ISIV;
+#else
+        return PERL_constant_NOTDEF;
+#endif
+      }
+      break;
+    case 'U':
+      if (memEQ(name, "Z_HUFFMAN_ONLY", 14)) {
+      /*                  ^                 */
+#ifdef Z_HUFFMAN_ONLY
+        *iv_return = Z_HUFFMAN_ONLY;
+        return PERL_constant_ISIV;
+#else
+        return PERL_constant_NOTDEF;
+#endif
+      }
+      break;
+    }
+    break;
+  case 15:
+    /* Names all of length 15.  */
+    /* Z_PARTIAL_FLUSH Z_VERSION_ERROR */
+    /* Offset 5 gives the best switch position.  */
+    switch (name[5]) {
+    case 'S':
+      if (memEQ(name, "Z_VERSION_ERROR", 15)) {
+      /*                    ^                */
+#ifdef Z_VERSION_ERROR
+        *iv_return = Z_VERSION_ERROR;
+        return PERL_constant_ISIV;
+#else
+        return PERL_constant_NOTDEF;
+#endif
+      }
+      break;
+    case 'T':
+      if (memEQ(name, "Z_PARTIAL_FLUSH", 15)) {
+      /*                    ^                */
+#ifdef Z_PARTIAL_FLUSH
+        *iv_return = Z_PARTIAL_FLUSH;
+        return PERL_constant_ISIV;
+#else
+        return PERL_constant_NOTDEF;
+#endif
+      }
+      break;
+    }
+    break;
+  case 16:
+    if (memEQ(name, "Z_NO_COMPRESSION", 16)) {
+#ifdef Z_NO_COMPRESSION
+      *iv_return = Z_NO_COMPRESSION;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 18:
+    /* Names all of length 18.  */
+    /* Z_BEST_COMPRESSION Z_DEFAULT_STRATEGY */
+    /* Offset 14 gives the best switch position.  */
+    switch (name[14]) {
+    case 'S':
+      if (memEQ(name, "Z_BEST_COMPRESSION", 18)) {
+      /*                             ^          */
+#ifdef Z_BEST_COMPRESSION
+        *iv_return = Z_BEST_COMPRESSION;
+        return PERL_constant_ISIV;
+#else
+        return PERL_constant_NOTDEF;
+#endif
+      }
+      break;
+    case 'T':
+      if (memEQ(name, "Z_DEFAULT_STRATEGY", 18)) {
+      /*                             ^          */
+#ifdef Z_DEFAULT_STRATEGY
+        *iv_return = Z_DEFAULT_STRATEGY;
+        return PERL_constant_ISIV;
+#else
+        return PERL_constant_NOTDEF;
+#endif
+      }
+      break;
+    }
+    break;
+  case 21:
+    if (memEQ(name, "Z_DEFAULT_COMPRESSION", 21)) {
+#ifdef Z_DEFAULT_COMPRESSION
+      *iv_return = Z_DEFAULT_COMPRESSION;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  }
+  return PERL_constant_NOTFOUND;
+}
+
diff --git a/ext/Compress/Zlib/fallback.xs b/ext/Compress/Zlib/fallback.xs
new file mode 100644 (file)
index 0000000..02a6ef4
--- /dev/null
@@ -0,0 +1,87 @@
+void
+constant(sv)
+    PREINIT:
+#ifdef dXSTARG
+       dXSTARG; /* Faster if we have it.  */
+#else
+       dTARGET;
+#endif
+       STRLEN          len;
+        int            type;
+       IV              iv;
+       /* NV           nv;     Uncomment this if you need to return NVs */
+       const char      *pv;
+    INPUT:
+       SV *            sv;
+        const char *   s = SvPV(sv, len);
+    PPCODE:
+        /* Change this to constant(aTHX_ s, len, &iv, &nv);
+           if you need to return both NVs and IVs */
+       type = constant(aTHX_ s, len, &iv, &pv);
+      /* Return 1 or 2 items. First is error message, or undef if no error.
+           Second, if present, is found value */
+        switch (type) {
+        case PERL_constant_NOTFOUND:
+          sv = sv_2mortal(newSVpvf("%s is not a valid Zlib macro", s));
+          PUSHs(sv);
+          break;
+        case PERL_constant_NOTDEF:
+          sv = sv_2mortal(newSVpvf(
+           "Your vendor has not defined Zlib macro %s, used", s));
+          PUSHs(sv);
+          break;
+        case PERL_constant_ISIV:
+          EXTEND(SP, 1);
+          PUSHs(&PL_sv_undef);
+          PUSHi(iv);
+          break;
+       /* Uncomment this if you need to return NOs
+        case PERL_constant_ISNO:
+          EXTEND(SP, 1);
+          PUSHs(&PL_sv_undef);
+          PUSHs(&PL_sv_no);
+          break; */
+       /* Uncomment this if you need to return NVs
+        case PERL_constant_ISNV:
+          EXTEND(SP, 1);
+          PUSHs(&PL_sv_undef);
+          PUSHn(nv);
+          break; */
+        case PERL_constant_ISPV:
+          EXTEND(SP, 1);
+          PUSHs(&PL_sv_undef);
+          PUSHp(pv, strlen(pv));
+          break;
+       /* Uncomment this if you need to return PVNs
+        case PERL_constant_ISPVN:
+          EXTEND(SP, 1);
+          PUSHs(&PL_sv_undef);
+          PUSHp(pv, iv);
+          break; */
+       /* Uncomment this if you need to return SVs
+        case PERL_constant_ISSV:
+          EXTEND(SP, 1);
+          PUSHs(&PL_sv_undef);
+          PUSHs(sv);
+          break; */
+       /* Uncomment this if you need to return UNDEFs
+        case PERL_constant_ISUNDEF:
+          break; */
+       /* Uncomment this if you need to return UVs
+        case PERL_constant_ISUV:
+          EXTEND(SP, 1);
+          PUSHs(&PL_sv_undef);
+          PUSHu((UV)iv);
+          break; */
+       /* Uncomment this if you need to return YESs
+        case PERL_constant_ISYES:
+          EXTEND(SP, 1);
+          PUSHs(&PL_sv_undef);
+          PUSHs(&PL_sv_yes);
+          break; */
+        default:
+          sv = sv_2mortal(newSVpvf(
+           "Unexpected return type %d while processing Zlib macro %s, used",
+               type, s));
+          PUSHs(sv);
+        }
diff --git a/ext/Compress/Zlib/t/01version.t b/ext/Compress/Zlib/t/01version.t
new file mode 100644 (file)
index 0000000..1a0030a
--- /dev/null
@@ -0,0 +1,34 @@
+
+use strict ;
+local ($^W) = 1; #use warnings ;
+
+use Compress::Zlib ;
+
+sub ok
+{
+    my ($no, $ok) = @_ ;
+
+    #++ $total ;
+    #++ $totalBad unless $ok ;
+
+    print "ok $no\n" if $ok ;
+    print "not ok $no\n" unless $ok ;
+    return $ok;
+}
+
+print "1..1\n" ;
+
+# Check zlib_version and ZLIB_VERSION are the same.
+my $zlib_h = ZLIB_VERSION ;
+my $libz   = Compress::Zlib::zlib_version;
+ok(1, $zlib_h eq $libz) ||
+print <<EOM;
+# The version of zlib.h does not match the version of libz
+# 
+# You have zlib.h version $zlib_h
+#      and libz   version $libz
+# 
+# You probably have two versions of zlib installed on your system.
+# Try removing the one you don't want to use and rebuild.
+EOM
+
diff --git a/ext/Compress/Zlib/t/02zlib.t b/ext/Compress/Zlib/t/02zlib.t
new file mode 100644 (file)
index 0000000..995bb52
--- /dev/null
@@ -0,0 +1,921 @@
+
+
+use strict ;
+local ($^W) = 1; #use warnings ;
+
+use Compress::Zlib ;
+
+sub ok
+{
+    my ($no, $ok) = @_ ;
+
+    #++ $total ;
+    #++ $totalBad unless $ok ;
+
+    print "ok $no\n" if $ok ;
+    print "not ok $no\n" unless $ok ;
+}
+
+sub readFile
+{
+    my ($filename) = @_ ;
+    my ($string) = '' ;
+    open (F, "<$filename")
+        or die "Cannot open $filename: $!\n" ;
+    binmode(F);
+    while (<F>)
+      { $string .= $_ }
+    close F ;
+    $string ;
+}     
+
+my $hello = <<EOM ;
+hello world
+this is a test
+EOM
+
+my $len   = length $hello ;
+
+
+print "1..239\n" ;
+
+# Check zlib_version and ZLIB_VERSION are the same.
+ok(1, Compress::Zlib::zlib_version eq ZLIB_VERSION) ;
+
+# gzip tests
+#===========
+
+my $name = "test.gz" ;
+my ($x, $uncomp) ;
+
+ok(2, my $fil = gzopen($name, "wb")) ;
+
+ok(3, $gzerrno == 0);
+
+ok(4, $fil->gzwrite($hello) == $len) ;
+
+ok(5, ! $fil->gzclose ) ;
+
+ok(6, $fil = gzopen($name, "rb") ) ;
+
+ok(7, $gzerrno == 0);
+
+ok(8, ($x = $fil->gzread($uncomp)) == $len) ;
+
+ok(9, ! $fil->gzclose ) ;
+
+unlink $name ;
+
+ok(10, $hello eq $uncomp) ;
+
+# check that a number can be gzipped
+my $number = 7603 ;
+my $num_len = 4 ;
+
+ok(11, $fil = gzopen($name, "wb")) ;
+
+ok(12, $gzerrno == 0);
+
+ok(13, $fil->gzwrite($number) == $num_len) ;
+
+ok(14, $gzerrno == 0);
+
+ok(15, ! $fil->gzclose ) ;
+
+ok(16, $gzerrno == 0);
+
+ok(17, $fil = gzopen($name, "rb") ) ;
+
+ok(18, ($x = $fil->gzread($uncomp)) == $num_len) ;
+
+ok(19, $gzerrno == 0 || $gzerrno == Z_STREAM_END);
+
+ok(20, ! $fil->gzclose ) ;
+
+ok(21, $gzerrno == 0);
+
+unlink $name ;
+
+ok(22, $number == $uncomp) ;
+ok(23, $number eq $uncomp) ;
+
+
+# now a bigger gzip test
+
+my $text = 'text' ;
+my $file = "$text.gz" ;
+
+ok(24, my $f = gzopen($file, "wb")) ;
+
+# generate a long random string
+my $contents = '' ;
+foreach (1 .. 5000)
+  { $contents .= chr int rand 256 }
+
+$len = length $contents ;
+
+ok(25, $f->gzwrite($contents) == $len ) ;
+
+ok(26, ! $f->gzclose );
+
+ok(27, $f = gzopen($file, "rb")) ;
+my $uncompressed ;
+ok(28, $f->gzread($uncompressed, $len) == $len) ;
+
+ok(29, $contents eq $uncompressed) ;
+
+ok(30, ! $f->gzclose ) ;
+
+unlink($file) ;
+
+# gzip - readline tests
+# ======================
+
+# first create a small gzipped text file
+$name = "test.gz" ;
+my @text = (<<EOM, <<EOM, <<EOM, <<EOM) ;
+this is line 1
+EOM
+the second line
+EOM
+the line after the previous line
+EOM
+the final line
+EOM
+
+$text = join("", @text) ;
+
+ok(31, $fil = gzopen($name, "wb")) ;
+ok(32, $fil->gzwrite($text) == length $text) ;
+ok(33, ! $fil->gzclose ) ;
+
+# now try to read it back in
+ok(34, $fil = gzopen($name, "rb")) ;
+my $aok = 1 ; 
+my $remember = '';
+my $line = '';
+my $lines = 0 ;
+while ($fil->gzreadline($line) > 0) {
+    ($aok = 0), last
+       if $line ne $text[$lines] ;
+    $remember .= $line ;
+    ++ $lines ;
+}
+ok(35, $aok) ;
+ok(36, $remember eq $text) ;
+ok(37, $lines == @text) ;
+ok(38, ! $fil->gzclose ) ;
+unlink($name) ;
+
+# a text file with a very long line (bigger than the internal buffer)
+my $line1 = ("abcdefghijklmnopq" x 2000) . "\n" ;
+my $line2 = "second line\n" ;
+$text = $line1 . $line2 ;
+ok(39, $fil = gzopen($name, "wb")) ;
+ok(40, $fil->gzwrite($text) == length $text) ;
+ok(41, ! $fil->gzclose ) ;
+
+# now try to read it back in
+ok(42, $fil = gzopen($name, "rb")) ;
+my $i = 0 ;
+my @got = ();
+while ($fil->gzreadline($line) > 0) {
+    $got[$i] = $line ;    
+    ++ $i ;
+}
+ok(43, $i == 2) ;
+ok(44, $got[0] eq $line1 ) ;
+ok(45, $got[1] eq $line2) ;
+
+ok(46, ! $fil->gzclose ) ;
+
+unlink $name ;
+
+# a text file which is not termined by an EOL
+
+$line1 = "hello hello, I'm back again\n" ;
+$line2 = "there is no end in sight" ;
+
+$text = $line1 . $line2 ;
+ok(47, $fil = gzopen($name, "wb")) ;
+ok(48, $fil->gzwrite($text) == length $text) ;
+ok(49, ! $fil->gzclose ) ;
+
+# now try to read it back in
+ok(50, $fil = gzopen($name, "rb")) ;
+@got = () ; $i = 0 ;
+while ($fil->gzreadline($line) > 0) {
+    $got[$i] = $line ;    
+    ++ $i ;
+}
+ok(51, $i == 2) ;
+ok(52, $got[0] eq $line1 ) ;
+ok(53, $got[1] eq $line2) ;
+
+ok(54, ! $fil->gzclose ) ;
+
+unlink $name ;
+
+
+# mix gzread and gzreadline <
+
+# case 1: read a line, then a block. The block is
+#         smaller than the internal block used by
+#        gzreadline
+$line1 = "hello hello, I'm back again\n" ;
+$line2 = "abc" x 200 ; 
+my $line3 = "def" x 200 ;
+
+$text = $line1 . $line2 . $line3 ;
+ok(55, $fil = gzopen($name, "wb")) ;
+ok(56, $fil->gzwrite($text) == length $text) ;
+ok(57, ! $fil->gzclose ) ;
+
+# now try to read it back in
+ok(58, $fil = gzopen($name, "rb")) ;
+ok(59, $fil->gzreadline($line) > 0) ;
+ok(60, $line eq $line1) ;
+ok(61, $fil->gzread($line, length $line2) > 0) ;
+ok(62, $line eq $line2) ;
+ok(63, $fil->gzread($line, length $line3) > 0) ;
+ok(64, $line eq $line3) ;
+ok(65, ! $fil->gzclose ) ;
+unlink $name ;
+
+# change $/ <<TODO
+
+
+
+# compress/uncompress tests
+# =========================
+
+$hello = "hello mum" ;
+my $keep_hello = $hello ;
+
+my $compr = compress($hello) ;
+ok(66, $compr ne "") ;
+
+my $keep_compr = $compr ;
+
+my $uncompr = uncompress ($compr) ;
+
+ok(67, $hello eq $uncompr) ;
+
+ok(68, $hello eq $keep_hello) ;
+ok(69, $compr eq $keep_compr) ;
+
+# compress a number
+$hello = 7890 ;
+$keep_hello = $hello ;
+
+$compr = compress($hello) ;
+ok(70, $compr ne "") ;
+
+$keep_compr = $compr ;
+
+$uncompr = uncompress ($compr) ;
+
+ok(71, $hello eq $uncompr) ;
+
+ok(72, $hello eq $keep_hello) ;
+ok(73, $compr eq $keep_compr) ;
+
+# bigger compress
+
+$compr = compress ($contents) ;
+ok(74, $compr ne "") ;
+
+$uncompr = uncompress ($compr) ;
+
+ok(75, $contents eq $uncompr) ;
+
+# buffer reference
+
+$compr = compress(\$hello) ;
+ok(76, $compr ne "") ;
+
+
+$uncompr = uncompress (\$compr) ;
+ok(77, $hello eq $uncompr) ;
+
+# bad level
+$compr = compress($hello, 1000) ;
+ok(78, ! defined $compr);
+
+# change level
+$compr = compress($hello, Z_BEST_COMPRESSION) ;
+ok(79, defined $compr);
+$uncompr = uncompress (\$compr) ;
+ok(80, $hello eq $uncompr) ;
+
+# deflate/inflate - small buffer
+# ==============================
+
+$hello = "I am a HAL 9000 computer" ;
+my @hello = split('', $hello) ;
+my ($err, $X, $status);
+ok(81,  ($x, $err) = deflateInit( {-Bufsize => 1} ) ) ;
+ok(82, $x) ;
+ok(83, $err == Z_OK) ;
+my $Answer = '';
+foreach (@hello)
+{
+    ($X, $status) = $x->deflate($_) ;
+    last unless $status == Z_OK ;
+
+    $Answer .= $X ;
+}
+ok(84, $status == Z_OK) ;
+
+ok(85,    (($X, $status) = $x->flush())[1] == Z_OK ) ;
+$Answer .= $X ;
+my @Answer = split('', $Answer) ;
+my $k;
+ok(86, ($k, $err) = inflateInit( {-Bufsize => 1}) ) ;
+ok(87, $k) ;
+ok(88, $err == Z_OK) ;
+my $GOT = '';
+my $Z;
+foreach (@Answer)
+{
+    ($Z, $status) = $k->inflate($_) ;
+    $GOT .= $Z ;
+    last if $status == Z_STREAM_END or $status != Z_OK ;
+}
+ok(89, $status == Z_STREAM_END) ;
+ok(90, $GOT eq $hello ) ;
+
+
+# deflate/inflate - small buffer with a number
+# ==============================
+
+$hello = 6529 ;
+ok(91,  ($x, $err) = deflateInit( {-Bufsize => 1} ) ) ;
+ok(92, $x) ;
+ok(93, $err == Z_OK) ;
+$Answer = '';
+{
+    ($X, $status) = $x->deflate($hello) ;
+
+    $Answer .= $X ;
+}
+ok(94, $status == Z_OK) ;
+
+ok(95,    (($X, $status) = $x->flush())[1] == Z_OK ) ;
+$Answer .= $X ;
+@Answer = split('', $Answer) ;
+ok(96, ($k, $err) = inflateInit( {-Bufsize => 1}) ) ;
+ok(97, $k) ;
+ok(98, $err == Z_OK) ;
+$GOT = '';
+foreach (@Answer)
+{
+    ($Z, $status) = $k->inflate($_) ;
+    $GOT .= $Z ;
+    last if $status == Z_STREAM_END or $status != Z_OK ;
+}
+ok(99, $status == Z_STREAM_END) ;
+ok(100, $GOT eq $hello ) ;
+
+
+# deflate/inflate - larger buffer
+# ==============================
+
+
+ok(101, $x = deflateInit() ) ;
+ok(102, (($X, $status) = $x->deflate($contents))[1] == Z_OK) ;
+
+my $Y = $X ;
+ok(103, (($X, $status) = $x->flush() )[1] == Z_OK ) ;
+$Y .= $X ;
+ok(104, $k = inflateInit() ) ;
+($Z, $status) = $k->inflate($Y) ;
+ok(105, $status == Z_STREAM_END) ;
+ok(106, $contents eq $Z ) ;
+
+# deflate/inflate - preset dictionary
+# ===================================
+
+my $dictionary = "hello" ;
+ok(107, $x = deflateInit({-Level => Z_BEST_COMPRESSION,
+                        -Dictionary => $dictionary})) ;
+my $dictID = $x->dict_adler() ;
+
+($X, $status) = $x->deflate($hello) ;
+ok(108, $status == Z_OK) ;
+($Y, $status) = $x->flush() ;
+ok(109, $status == Z_OK) ;
+$X .= $Y ;
+$x = 0 ;
+ok(110, $k = inflateInit(-Dictionary => $dictionary) ) ;
+($Z, $status) = $k->inflate($X);
+ok(111, $status == Z_STREAM_END) ;
+ok(112, $k->dict_adler() == $dictID);
+ok(113, $hello eq $Z ) ;
+
+##ok(76, $k->inflateSetDictionary($dictionary) == Z_OK);
+# 
+#$Z='';
+#while (1) {
+#    ($Z, $status) = $k->inflate($X) ;
+#    last if $status == Z_STREAM_END or $status != Z_OK ;
+#print "status=[$status] hello=[$hello] Z=[$Z]\n";
+#}
+#ok(77, $status == Z_STREAM_END) ;
+#ok(78, $hello eq $Z ) ;
+#print "status=[$status] hello=[$hello] Z=[$Z]\n";
+#
+#
+## all done.
+#
+#
+#
+
+
+# inflate - check remaining buffer after Z_STREAM_END
+# ===================================================
+{
+    ok(114, $x = deflateInit(-Level => Z_BEST_COMPRESSION )) ;
+    ($X, $status) = $x->deflate($hello) ;
+    ok(115, $status == Z_OK) ;
+    ($Y, $status) = $x->flush() ;
+    ok(116, $status == Z_OK) ;
+    $X .= $Y ;
+    $x = 0 ;
+    ok(117, $k = inflateInit() ) ;
+    my $first = substr($X, 0, 2) ;
+    my $last  = substr($X, 2) ;
+    ($Z, $status) = $k->inflate($first);
+    ok(118, $status == Z_OK) ;
+    ok(119, $first eq "") ;
+
+    $last .= "appendage" ;
+    my ($T, $status) = $k->inflate($last);
+    ok(120, $status == Z_STREAM_END) ;
+    ok(121, $hello eq $Z . $T ) ;
+    ok(122, $last eq "appendage") ;
+
+}
+
+# memGzip & memGunzip
+{
+    my $name = "test.gz" ;
+    my $buffer = <<EOM;
+some sample 
+text
+
+EOM
+
+    my $len = length $buffer ;
+    my ($x, $uncomp) ;
+
+
+    # create an in-memory gzip file
+    my $dest = Compress::Zlib::memGzip($buffer) ;
+    ok(123, length $dest) ;
+
+    # write it to disk
+    ok(124, open(FH, ">$name")) ;
+    binmode(FH);
+    print FH $dest ;
+    close FH ;
+
+    # uncompress with gzopen
+    ok(125, my $fil = gzopen($name, "rb") ) ;
+    ok(126, ($x = $fil->gzread($uncomp)) == $len) ;
+    ok(127, ! $fil->gzclose ) ;
+
+    ok(128, $uncomp eq $buffer) ;
+    unlink $name ;
+
+    # now check that memGunzip can deal with it.
+    my $ungzip = Compress::Zlib::memGunzip($dest) ;
+    ok(129, defined $ungzip) ;
+    ok(130, $buffer eq $ungzip) ;
+    # now do the same but use a reference 
+
+    $dest = Compress::Zlib::memGzip(\$buffer) ; 
+    ok(131, length $dest) ;
+
+    # write it to disk
+    ok(132, open(FH, ">$name")) ;
+    binmode(FH);
+    print FH $dest ;
+    close FH ;
+
+    # uncompress with gzopen
+    ok(133, $fil = gzopen($name, "rb") ) ;
+    ok(134, ($x = $fil->gzread($uncomp)) == $len) ;
+    ok(135, ! $fil->gzclose ) ;
+
+    ok(136, $uncomp eq $buffer) ;
+    # now check that memGunzip can deal with it.
+    my $keep = $dest;
+    $ungzip = Compress::Zlib::memGunzip(\$dest) ;
+    ok(137, defined $ungzip) ;
+    ok(138, $buffer eq $ungzip) ;
+
+    # check memGunzip can cope with missing gzip trailer
+    my $minimal = substr($keep, 0, -1) ;
+    $ungzip = Compress::Zlib::memGunzip(\$minimal) ;
+    ok(139, defined $ungzip) ;
+    ok(140, $buffer eq $ungzip) ;
+
+    $minimal = substr($keep, 0, -2) ;
+    $ungzip = Compress::Zlib::memGunzip(\$minimal) ;
+    ok(141, defined $ungzip) ;
+    ok(142, $buffer eq $ungzip) ;
+
+    $minimal = substr($keep, 0, -3) ;
+    $ungzip = Compress::Zlib::memGunzip(\$minimal) ;
+    ok(143, defined $ungzip) ;
+    ok(144, $buffer eq $ungzip) ;
+
+    $minimal = substr($keep, 0, -4) ;
+    $ungzip = Compress::Zlib::memGunzip(\$minimal) ;
+    ok(145, defined $ungzip) ;
+    ok(146, $buffer eq $ungzip) ;
+
+    $minimal = substr($keep, 0, -5) ;
+    $ungzip = Compress::Zlib::memGunzip(\$minimal) ;
+    ok(147, defined $ungzip) ;
+    ok(148, $buffer eq $ungzip) ;
+
+    $minimal = substr($keep, 0, -6) ;
+    $ungzip = Compress::Zlib::memGunzip(\$minimal) ;
+    ok(149, defined $ungzip) ;
+    ok(150, $buffer eq $ungzip) ;
+
+    $minimal = substr($keep, 0, -7) ;
+    $ungzip = Compress::Zlib::memGunzip(\$minimal) ;
+    ok(151, defined $ungzip) ;
+    ok(152, $buffer eq $ungzip) ;
+
+    $minimal = substr($keep, 0, -8) ;
+    $ungzip = Compress::Zlib::memGunzip(\$minimal) ;
+    ok(153, defined $ungzip) ;
+    ok(154, $buffer eq $ungzip) ;
+
+    $minimal = substr($keep, 0, -9) ;
+    $ungzip = Compress::Zlib::memGunzip(\$minimal) ;
+    ok(155, ! defined $ungzip) ;
+
+    unlink $name ;
+
+    # check corrupt header -- too short
+    $dest = "x" ;
+    my $result = Compress::Zlib::memGunzip($dest) ;
+    ok(156, !defined $result) ;
+
+    # check corrupt header -- full of junk
+    $dest = "x" x 200 ;
+    $result = Compress::Zlib::memGunzip($dest) ;
+    ok(157, !defined $result) ;
+}
+
+# memGunzip with a gzopen created file
+{
+    my $name = "test.gz" ;
+    my $buffer = <<EOM;
+some sample 
+text
+
+EOM
+
+    ok(158, $fil = gzopen($name, "wb")) ;
+
+    ok(159, $fil->gzwrite($buffer) == length $buffer) ;
+
+    ok(160, ! $fil->gzclose ) ;
+
+    my $compr = readFile($name);
+    ok(161, length $compr) ;
+    my $unc = Compress::Zlib::memGunzip($compr) ;
+    ok(162, defined $unc) ;
+    ok(163, $buffer eq $unc) ;
+    unlink $name ;
+}
+
+{
+
+    # Check - MAX_WBITS
+    # =================
+    
+    $hello = "Test test test test test";
+    @hello = split('', $hello) ;
+     
+    ok(164,  ($x, $err) = deflateInit( -Bufsize => 1, -WindowBits => -MAX_WBITS() ) ) ;
+    ok(165, $x) ;
+    ok(166, $err == Z_OK) ;
+     
+    $Answer = '';
+    foreach (@hello)
+    {
+        ($X, $status) = $x->deflate($_) ;
+        last unless $status == Z_OK ;
+    
+        $Answer .= $X ;
+    }
+     
+    ok(167, $status == Z_OK) ;
+    
+    ok(168,    (($X, $status) = $x->flush())[1] == Z_OK ) ;
+    $Answer .= $X ;
+     
+     
+    @Answer = split('', $Answer) ;
+    # Undocumented corner -- extra byte needed to get inflate to return 
+    # Z_STREAM_END when done.  
+    push @Answer, " " ; 
+     
+    ok(169, ($k, $err) = inflateInit(-Bufsize => 1, -WindowBits => -MAX_WBITS()) ) ;
+    ok(170, $k) ;
+    ok(171, $err == Z_OK) ;
+     
+    $GOT = '';
+    foreach (@Answer)
+    {
+        ($Z, $status) = $k->inflate($_) ;
+        $GOT .= $Z ;
+        last if $status == Z_STREAM_END or $status != Z_OK ;
+     
+    }
+     
+    ok(172, $status == Z_STREAM_END) ;
+    ok(173, $GOT eq $hello ) ;
+    
+}
+
+{
+    # inflateSync
+
+    # create a deflate stream with flush points
+
+    my $hello = "I am a HAL 9000 computer" x 2001 ;
+    my $goodbye = "Will I dream?" x 2010;
+    my ($err, $answer, $X, $status, $Answer);
+     
+    ok(174, ($x, $err) = deflateInit() ) ;
+    ok(175, $x) ;
+    ok(176, $err == Z_OK) ;
+     
+    ($Answer, $status) = $x->deflate($hello) ;
+    ok(177, $status == Z_OK) ;
+    
+    # create a flush point
+    ok(178, (($X, $status) = $x->flush(Z_FULL_FLUSH))[1] == Z_OK ) ;
+    $Answer .= $X ;
+     
+    ($X, $status) = $x->deflate($goodbye) ;
+    ok(179, $status == Z_OK) ;
+    $Answer .= $X ;
+    
+    ok(180, (($X, $status) = $x->flush())[1] == Z_OK ) ;
+    $Answer .= $X ;
+     
+    my ($first, @Answer) = split('', $Answer) ;
+     
+    my $k;
+    ok(181, ($k, $err) = inflateInit()) ;
+    ok(182, $k) ;
+    ok(183, $err == Z_OK) ;
+     
+    ($Z, $status) = $k->inflate($first) ;
+    ok(184, $status == Z_OK) ;
+
+    # skip to the first flush point.
+    while (@Answer)
+    {
+        my $byte = shift @Answer;
+        $status = $k->inflateSync($byte) ;
+        last unless $status == Z_DATA_ERROR;
+     
+    }
+
+    ok(185, $status == Z_OK);
+     
+    my $GOT = '';
+    my $Z = '';
+    foreach (@Answer)
+    {
+        my $Z = '';
+        ($Z, $status) = $k->inflate($_) ;
+        $GOT .= $Z if defined $Z ;
+        # print "x $status\n";
+        last if $status == Z_STREAM_END or $status != Z_OK ;
+     
+    }
+     
+    # zlib 1.0.9 returns Z_STREAM_END here, all others return Z_DATA_ERROR
+    ok(186, $status == Z_DATA_ERROR || $status == Z_STREAM_END) ;
+    ok(187, $GOT eq $goodbye ) ;
+
+
+    # Check inflateSync leaves good data in buffer
+    $Answer =~ /^(.)(.*)$/ ;
+    my ($initial, $rest) = ($1, $2);
+
+    
+    ok(188, ($k, $err) = inflateInit()) ;
+    ok(189, $k) ;
+    ok(190, $err == Z_OK) ;
+     
+    ($Z, $status) = $k->inflate($initial) ;
+    ok(191, $status == Z_OK) ;
+
+    $status = $k->inflateSync($rest) ;
+    ok(192, $status == Z_OK);
+     
+    ($GOT, $status) = $k->inflate($rest) ;
+     
+    ok(193, $status == Z_DATA_ERROR) ;
+    ok(194, $Z . $GOT eq $goodbye ) ;
+}
+
+{
+    # deflateParams
+
+    my $hello = "I am a HAL 9000 computer" x 2001 ;
+    my $goodbye = "Will I dream?" x 2010;
+    my ($input, $err, $answer, $X, $status, $Answer);
+     
+    ok(195, ($x, $err) = deflateInit(-Level    => Z_BEST_COMPRESSION,
+                                     -Strategy => Z_DEFAULT_STRATEGY) ) ;
+    ok(196, $x) ;
+    ok(197, $err == Z_OK) ;
+
+    ok(198, $x->get_Level()    == Z_BEST_COMPRESSION);
+    ok(199, $x->get_Strategy() == Z_DEFAULT_STRATEGY);
+     
+    ($Answer, $status) = $x->deflate($hello) ;
+    ok(200, $status == Z_OK) ;
+    $input .= $hello;
+    
+    # error cases
+    eval { $x->deflateParams() };
+    ok(201, $@ =~ m#^deflateParams needs Level and/or Strategy#);
+
+    eval { $x->deflateParams(-Joe => 3) };
+    ok(202, $@ =~ /^unknown key value\(s\) Joe at/);
+
+    ok(203, $x->get_Level()    == Z_BEST_COMPRESSION);
+    ok(204, $x->get_Strategy() == Z_DEFAULT_STRATEGY);
+     
+    # change both Level & Strategy
+    $status = $x->deflateParams(-Level => Z_BEST_SPEED, -Strategy => Z_HUFFMAN_ONLY) ;
+    ok(205, $status == Z_OK) ;
+    
+    ok(206, $x->get_Level()    == Z_BEST_SPEED);
+    ok(207, $x->get_Strategy() == Z_HUFFMAN_ONLY);
+     
+    ($X, $status) = $x->deflate($goodbye) ;
+    ok(208, $status == Z_OK) ;
+    $Answer .= $X ;
+    $input .= $goodbye;
+    
+    # change only Level 
+    $status = $x->deflateParams(-Level => Z_NO_COMPRESSION) ;
+    ok(209, $status == Z_OK) ;
+    
+    ok(210, $x->get_Level()    == Z_NO_COMPRESSION);
+    ok(211, $x->get_Strategy() == Z_HUFFMAN_ONLY);
+     
+    ($X, $status) = $x->deflate($goodbye) ;
+    ok(212, $status == Z_OK) ;
+    $Answer .= $X ;
+    $input .= $goodbye;
+    
+    # change only Strategy
+    $status = $x->deflateParams(-Strategy => Z_FILTERED) ;
+    ok(213, $status == Z_OK) ;
+    
+    ok(214, $x->get_Level()    == Z_NO_COMPRESSION);
+    ok(215, $x->get_Strategy() == Z_FILTERED);
+     
+    ($X, $status) = $x->deflate($goodbye) ;
+    ok(216, $status == Z_OK) ;
+    $Answer .= $X ;
+    $input .= $goodbye;
+    
+    ok(217, (($X, $status) = $x->flush())[1] == Z_OK ) ;
+    $Answer .= $X ;
+     
+    my ($first, @Answer) = split('', $Answer) ;
+     
+    my $k;
+    ok(218, ($k, $err) = inflateInit()) ;
+    ok(219, $k) ;
+    ok(220, $err == Z_OK) ;
+     
+    ($Z, $status) = $k->inflate($Answer) ;
+
+    ok(221, $status == Z_STREAM_END) ;
+    ok(222, $Z  eq $input ) ;
+}
+
+{
+    # error cases
+
+    eval { deflateInit(-Level) };
+    ok(223, $@ =~ /^Compress::Zlib::deflateInit: parameter is not a reference to a hash at/);
+
+    eval { inflateInit(-Level) };
+    ok(224, $@ =~ /^Compress::Zlib::inflateInit: parameter is not a reference to a hash at/);
+
+    eval { deflateInit(-Joe => 1) };
+    ok(225, $@ =~ /^unknown key value\(s\) Joe at/);
+
+    eval { inflateInit(-Joe => 1) };
+    ok(226, $@ =~ /^unknown key value\(s\) Joe at/);
+
+    eval { deflateInit(-Bufsize => 0) };
+    ok(227, $@ =~ /^.*?: Bufsize must be >= 1, you specified 0 at/);
+
+    eval { inflateInit(-Bufsize => 0) };
+    ok(228, $@ =~ /^.*?: Bufsize must be >= 1, you specified 0 at/);
+
+    eval { deflateInit(-Bufsize => -1) };
+    ok(229, $@ =~ /^.*?: Bufsize must be >= 1, you specified -1 at/);
+
+    eval { inflateInit(-Bufsize => -1) };
+    ok(230, $@ =~ /^.*?: Bufsize must be >= 1, you specified -1 at/);
+
+    eval { deflateInit(-Bufsize => "xxx") };
+    ok(231, $@ =~ /^.*?: Bufsize must be >= 1, you specified xxx at/);
+
+    eval { inflateInit(-Bufsize => "xxx") };
+    ok(232, $@ =~ /^.*?: Bufsize must be >= 1, you specified xxx at/);
+
+}
+
+{
+    # test inflate with a substr
+
+    ok(233, my $x = deflateInit() ) ;
+     
+    ok(234, (my ($X, $status) = $x->deflate($contents))[1] == Z_OK) ;
+    
+    my $Y = $X ;
+
+     
+     
+    ok(235, (($X, $status) = $x->flush() )[1] == Z_OK ) ;
+    $Y .= $X ;
+     
+    my $append = "Appended" ;
+    $Y .= $append ;
+     
+    ok(236, $k = inflateInit() ) ;
+     
+    ($Z, $status) = $k->inflate(substr($Y, 0, -1)) ;
+     
+    ok(237, $status == Z_STREAM_END) ;
+    #print "status $status Y [$Y]\n" ;
+    ok(238, $contents eq $Z ) ;
+    ok(239, $Y eq $append);
+    
+}
diff --git a/ext/Compress/Zlib/t/03examples.t b/ext/Compress/Zlib/t/03examples.t
new file mode 100644 (file)
index 0000000..b32ef4f
--- /dev/null
@@ -0,0 +1,174 @@
+
+use strict ;
+local ($^W) = 1; #use warnings ;
+
+sub ok
+{
+    my ($no, $ok) = @_ ;
+
+    #++ $total ;
+    #++ $totalBad unless $ok ;
+
+    print "ok $no\n" if $ok ;
+    print "not ok $no\n" unless $ok ;
+    printf "# Failed test at line %d\n", (caller)[2] unless $ok ;
+}
+
+sub writeFile
+{
+    my($filename, @strings) = @_ ;
+    open (F, ">$filename") 
+        or die "Cannot open $filename: $!\n" ;
+    binmode(F);
+    foreach (@strings)
+      { print F }
+    close F ;
+}
+
+sub readFile
+{
+    my ($filename) = @_ ;
+    my ($string) = '' ;
+    open (F, "<$filename") 
+        or die "Cannot open $filename: $!\n" ;
+    binmode(F);
+    while (<F>)
+      { $string .= $_ }
+    close F ;
+    $string ;
+}
+
+my $Inc = '' ;
+if ($^O eq 'VMS') {
+  $Inc = '-"I[.blib.lib]" -"I[.blib.arch]"';
+}
+elsif ($^O eq 'MSWin32') {
+  foreach (@INC)
+   { $Inc .= qq["-I$_" ]}
+} 
+else {
+  foreach (@INC)
+   { $Inc .= "-I$_ " }
+} 
+
+my $Perl = '' ;
+$Perl = ($ENV{'FULLPERL'} or $^X or 'perl') ;
+$Perl = qq["$Perl"] if $^O eq 'MSWin32' ;
+$Perl = "$Perl -w" ;
+my $examples = $ENV{PERL_CORE} ? "../ext/Compress/Zlib/examples" : "./examples";
+
+my $hello1 = <<EOM ;
+hello
+this is 
+a test
+message
+x ttttt
+xuuuuuu
+the end
+EOM
+
+my @hello1 = grep(s/$/\n/, split(/\n/, $hello1)) ;
+
+my $hello2 = <<EOM;
+
+Howdy
+this is the
+second
+file
+x ppppp
+xuuuuuu
+really the end
+EOM
+
+my @hello2 = grep(s/$/\n/, split(/\n/, $hello2)) ;
+
+print "1..13\n" ;
+
+
+
+# gzcat
+# #####
+
+my $file1 = "hello1.gz" ;
+my $file2 = "hello2.gz" ;
+unlink $file1, $file2 ;
+
+my $hello1_uue = <<'EOM';
+M'XL("(W#+3$" VAE;&QO,0#+2,W)R><JR<@L5@ BKD2%DM3B$J[<U.+BQ/14
+;K@J%$A#@JB@% Z"Z5(74O!0N &D:".,V    
+EOM
+
+my $hello2_uue = <<'EOM';
+M'XL("*[#+3$" VAE;&QO,@#C\L@O3ZGD*LG(+%8 HI*,5*[BU.3\O!2NM,R<
+A5*X*A0(0X*HH!0.NHM3$G)Q*D#*%5* : #) E6<^    
+EOM
+
+# Write a test .gz file
+{
+    #local $^W = 0 ;
+    writeFile($file1, unpack("u", $hello1_uue)) ;
+    writeFile($file2, unpack("u", $hello2_uue)) ;
+}
+
+$a = `$Perl $Inc ${examples}/gzcat $file1 $file2 2>&1` ;
+
+ok(1, $? == 0) ;
+ok(2, $a eq $hello1 . $hello2) ;
+#print "? = $? [$a]\n";
+
+
+# gzgrep
+# ######
+
+$a = ($^O eq 'MSWin32' || $^O eq 'VMS'
+     ? `$Perl $Inc ${examples}/gzgrep "^x" $file1 $file2 2>&1`
+     : `$Perl $Inc ${examples}/gzgrep '^x' $file1 $file2 2>&1`) ;
+ok(3, $? == 0) ;
+
+ok(4, $a eq join('', grep(/^x/, @hello1, @hello2))) ;
+#print "? = $? [$a]\n";
+
+
+unlink $file1, $file2 ;
+
+
+# filtdef/filtinf
+# ##############
+
+
+my $stderr = "err.out" ;
+unlink $stderr ;
+writeFile($file1, $hello1) ;
+writeFile($file2, $hello2) ;
+
+# there's no way to set binmode on backticks in Win32 so we won't use $a later
+$a = `$Perl $Inc ${examples}/filtdef $file1 $file2 2>$stderr` ;
+ok(5, $? == 0) ;
+ok(6, -s $stderr == 0) ;
+
+unlink $stderr;
+$a = `$Perl $Inc ${examples}/filtdef $file1 $file2 | $Perl $Inc ${examples}/filtinf 2>$stderr`;
+ok(7, $? == 0) ;
+ok(8, -s $stderr == 0) ;
+ok(9, $a eq $hello1 . $hello2) ;
+
+# gzstream
+# ########
+
+{
+    writeFile($file1, $hello1) ;
+    $a = `$Perl $Inc ${examples}/gzstream <$file1 >$file2 2>$stderr` ;
+    ok(10, $? == 0) ;
+    ok(11, -s $stderr == 0) ;
+
+    my $b = `$Perl $Inc ${examples}/gzcat $file2 2>&1` ;
+    ok(12, $? == 0) ;
+    ok(13, $b eq $hello1 ) ;
+}
+
+
+unlink $file1, $file2, $stderr ;
diff --git a/ext/Compress/Zlib/t/04encoding.t b/ext/Compress/Zlib/t/04encoding.t
new file mode 100644 (file)
index 0000000..6e4ed74
--- /dev/null
@@ -0,0 +1,120 @@
+
+use strict ;
+local ($^W) = 1; #use warnings ;
+
+BEGIN 
+{
+
+    eval { require Encode; Encode->import(); };
+    
+    if ($@) {
+        print "1..0 #  Skip: Encode is not available\n";
+        #exit 0;
+        $::bomb_out = 1;
+    }
+}
+
+exit 0 if $::bomb_out ;
+
+use Compress::Zlib ;
+#use Encode;
+
+sub ok
+{
+    my ($no, $ok) = @_ ;
+
+    #++ $total ;
+    #++ $totalBad unless $ok ;
+
+    print "ok $no\n" if $ok ;
+    print "not ok $no\n" unless $ok ;
+}
+
+sub readFile
+{
+    my ($filename) = @_ ;
+    my ($string) = '' ;
+    open (F, "<$filename")
+        or die "Cannot open $filename: $!\n" ;
+    binmode(F);
+    while (<F>)
+      { $string .= $_ }
+    close F ;
+    $string ;
+}     
+
+print "1..15\n" ;
+
+# Check zlib_version and ZLIB_VERSION are the same.
+ok(1, Compress::Zlib::zlib_version eq ZLIB_VERSION) ;
+
+
+{
+    # length of this string is 2 characters
+    my $s = "\x{df}\x{100}"; 
+
+    my $cs = Compress::Zlib::memGzip($s); 
+
+    # length stored at end of gzip file should be 4
+    my ($crc, $len) = unpack ("VV", substr($cs, -8, 8));
+    
+    ok(2, $len == 4);
+}
+
+{
+    # length of this string is 2 characters
+    my $s = "\x{df}\x{100}"; 
+
+    my $cs = Compress::Zlib::memGzip(Encode::encode_utf8($s));
+
+    # length stored at end of gzip file should be 4
+    my ($crc, $len) = unpack ("VV", substr($cs, -8, 8));
+    
+    ok(3, $len == 4);
+}
+
+{
+    my $s = "\x{df}\x{100}";                                   
+    my $s_copy = $s ;
+
+    my $cs = compress($s);                      
+    my $ces = compress(Encode::encode_utf8($s_copy));
+
+    ok(4, $cs eq $ces);
+
+    my $un = uncompress($cs);
+    ok(5, $un ne $s);
+    $un = uncompress($ces);
+    ok(6, $un ne $s);
+    $un = Encode::decode_utf8(uncompress($cs));
+    ok(7, $un eq $s);
+
+}
+
+{
+    my $name = "test.gz" ;
+    my $s = "\x{df}\x{100}";                                   
+    my $byte_len = length( Encode::encode_utf8($s) );
+    my ($uncomp) ;
+
+    ok(8, my $fil = gzopen($name, "wb")) ;
+
+    ok(9, $fil->gzwrite($s) == $byte_len) ;
+
+    ok(10, ! $fil->gzclose ) ;
+
+    ok(11, $fil = gzopen($name, "rb") ) ;
+
+    ok(12, $fil->gzread($uncomp) == $byte_len) ;
+    ok(13, length($uncomp) == $byte_len);
+
+    ok(14, ! $fil->gzclose ) ;
+
+    unlink $name ;
+
+    ok(15, $s eq Encode::decode_utf8($uncomp)) ;
+
+}
diff --git a/ext/Compress/Zlib/t/05gzsetp.t b/ext/Compress/Zlib/t/05gzsetp.t
new file mode 100644 (file)
index 0000000..97762e1
--- /dev/null
@@ -0,0 +1,84 @@
+
+
+use strict ;
+local ($^W) = 1; #use warnings ;
+
+use Compress::Zlib ;
+
+BEGIN
+{
+    my $ver = Compress::Zlib::zlib_version();
+    print "ver $ver\n";
+    if (defined $ver && $ver =~ /^(\d+)\.(\d+)\.(\d+)/ )
+    {
+        my $sum = $1 * 1000000 + $2 * 1000 + $3 ;
+     
+        if ($sum < 1_000_006) {
+            print "1..0 #  Skip: gzsetparams needs zlib 1.0.6 or better. You have $ver\n";
+            exit 0;
+        }
+    }
+    else
+    {
+        print "1..0 #  Skip: gzsetparams needs zlib 1.0.6 or better.\n";
+        exit 0;
+    }
+}
+sub ok
+{
+    my ($no, $ok) = @_ ;
+
+    #++ $total ;
+    #++ $totalBad unless $ok ;
+
+    print "ok $no\n" if $ok ;
+    print "not ok $no\n" unless $ok ;
+}
+
+print "1..11\n" ;
+
+# Check zlib_version and ZLIB_VERSION are the same.
+ok(1, Compress::Zlib::zlib_version eq ZLIB_VERSION) ;
+
+
+{
+    # gzsetparams
+
+    my $hello = "I am a HAL 9000 computer" x 2001 ;
+    my $len_hello = length $hello ;
+    my $goodbye = "Will I dream?" x 2010;
+    my $len_goodbye = length $goodbye;
+
+    my ($input, $err, $answer, $X, $status, $Answer);
+     
+    my $name = "test.gz" ;
+    unlink $name ;
+    ok(2, my $x = gzopen($name, "wb")) ;
+
+    ok(3, $x->gzwrite($hello) == $len_hello) ;
+    $input .= $hello;
+    
+    # error cases
+    eval { $x->gzsetparams() };
+    ok(4, $@ =~ /^Usage: Compress::Zlib::gzFile::gzsetparams\(file, level, strategy\) at/);
+
+    # change both Level & Strategy
+    $status = $x->gzsetparams(Z_BEST_SPEED, Z_HUFFMAN_ONLY) ;
+    ok(5, $status == Z_OK) ;
+    
+    ok(6, $x->gzwrite($goodbye) == $len_goodbye) ;
+    $input .= $goodbye;
+    
+    ok(7, ! $x->gzclose ) ;
+
+    ok(8, my $k = gzopen($name, "rb")) ;
+     
+    my $len = length $input ;
+    my $uncompressed;
+    ok(9, $k->gzread($uncompressed, $len) == $len) ;
+
+    ok(10, $uncompressed  eq $input ) ;
+    ok(11, ! $k->gzclose ) ;
+}
diff --git a/ext/Compress/Zlib/t/06gzdopen.t b/ext/Compress/Zlib/t/06gzdopen.t
new file mode 100644 (file)
index 0000000..919302a
--- /dev/null
@@ -0,0 +1,132 @@
+
+
+use strict ;
+local ($^W) = 1; #use warnings ;
+
+use Compress::Zlib ;
+
+sub ok
+{
+    my ($no, $ok) = @_ ;
+
+    #++ $total ;
+    #++ $totalBad unless $ok ;
+
+    print "ok $no\n" if $ok ;
+    print "not ok $no\n" unless $ok ;
+}
+
+sub readFile
+{
+    my ($filename) = @_ ;
+    my ($string) = '' ;
+    open (F, "<$filename")
+        or die "Cannot open $filename: $!\n" ;
+    binmode(F);
+    while (<F>)
+      { $string .= $_ }
+    close F ;
+    $string ;
+}     
+
+my $hello = <<EOM ;
+hello world
+this is a test
+EOM
+
+my $len   = length $hello ;
+
+
+print "1..23\n" ;
+
+# Check zlib_version and ZLIB_VERSION are the same.
+ok(1, Compress::Zlib::zlib_version eq ZLIB_VERSION) ;
+
+
+# gzip - filehandle tests
+# ========================
+
+{
+  use IO::File ;
+  my $filename = "fh.gz" ;
+  my $hello = "hello, hello, I'm back again" ;
+  my $len = length $hello ;
+
+  my $f = new IO::File ">$filename" ;
+  binmode $f ; # for OS/2
+
+  ok(2, $f) ;
+
+  my $line_one =  "first line\n" ;
+  print $f $line_one;
+  
+  ok(3, my $fil = gzopen($f, "wb")) ;
+  ok(4, $fil->gzwrite($hello) == $len) ;
+  ok(5, ! $fil->gzclose ) ;
+
+  ok(6, my $g = new IO::File "<$filename") ;
+  binmode $g ; # for OS/2
+  my $first ;
+  my $ret = read($g, $first, length($line_one));
+  ok(7, $ret == length($line_one));
+
+  ok(8, $first eq $line_one) ;
+
+  ok(9, $fil = gzopen($g, "rb") ) ;
+  my $uncomp;
+  ok(10, (my $x = $fil->gzread($uncomp)) == $len) ;
+  ok(11, ! $fil->gzclose ) ;
+  unlink $filename ;
+  ok(12, $hello eq $uncomp) ;
+
+}
+
+{
+  my $filename = "fh.gz" ;
+  my $hello = "hello, hello, I'm back again" ;
+  my $len = length $hello ;
+  my $uncomp;
+  local (*FH1) ;
+  local (*FH2) ;
+  ok(13, open FH1, ">$filename") ;
+  binmode FH1; # for OS/2
+  my $line_one =  "first line\n" ;
+  print FH1 $line_one;
+  ok(14, my $fil = gzopen(\*FH1, "wb")) ;
+  ok(15, $fil->gzwrite($hello) == $len) ;
+  ok(16, ! $fil->gzclose ) ;
+  ok(17, my $g = open FH2, "<$filename") ;
+  binmode FH2; # for OS/2
+  my $first ;
+  my $ret = read(FH2, $first, length($line_one));
+  ok(18, $ret == length($line_one));
+  ok(19, $first eq $line_one) ;
+  ok(20, $fil = gzopen(*FH2, "rb") ) ;
+  ok(21, (my $x = $fil->gzread($uncomp)) == $len) ;
+  ok(22, ! $fil->gzclose ) ;
+  unlink $filename ;
+  ok(23, $hello eq $uncomp) ;
+}
+
diff --git a/ext/Compress/Zlib/typemap b/ext/Compress/Zlib/typemap
new file mode 100644 (file)
index 0000000..09f0d0f
--- /dev/null
@@ -0,0 +1,17 @@
+Compress::Zlib::gzFile         T_PTROBJ
+Compress::Zlib::deflateStream  T_PTROBJ
+Compress::Zlib::inflateStream  T_PTROBJ
+Bytef *                                T_PV
+uInt                           T_UV
+#uLongf                                T_IV
+const char *                   T_PV
+uLong                          T_UV
+
+#############################################################################
+INPUT
+T_UV
+       $var = (unsigned long)SvUV($arg)
+#############################################################################
+OUTPUT
+T_UV
+       sv_setuv($arg, (IV)$var);
diff --git a/ext/Compress/Zlib/zlib-src-1.2.2/adler32.c b/ext/Compress/Zlib/zlib-src-1.2.2/adler32.c
new file mode 100644 (file)
index 0000000..624a169
--- /dev/null
@@ -0,0 +1,74 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-2003 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+#define BASE 65521UL    /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
+#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf)   DO8(buf,0); DO8(buf,8);
+
+#ifdef NO_DIVIDE
+#  define MOD(a) \
+    do { \
+        if (a >= (BASE << 16)) a -= (BASE << 16); \
+        if (a >= (BASE << 15)) a -= (BASE << 15); \
+        if (a >= (BASE << 14)) a -= (BASE << 14); \
+        if (a >= (BASE << 13)) a -= (BASE << 13); \
+        if (a >= (BASE << 12)) a -= (BASE << 12); \
+        if (a >= (BASE << 11)) a -= (BASE << 11); \
+        if (a >= (BASE << 10)) a -= (BASE << 10); \
+        if (a >= (BASE << 9)) a -= (BASE << 9); \
+        if (a >= (BASE << 8)) a -= (BASE << 8); \
+        if (a >= (BASE << 7)) a -= (BASE << 7); \
+        if (a >= (BASE << 6)) a -= (BASE << 6); \
+        if (a >= (BASE << 5)) a -= (BASE << 5); \
+        if (a >= (BASE << 4)) a -= (BASE << 4); \
+        if (a >= (BASE << 3)) a -= (BASE << 3); \
+        if (a >= (BASE << 2)) a -= (BASE << 2); \
+        if (a >= (BASE << 1)) a -= (BASE << 1); \
+        if (a >= BASE) a -= BASE; \
+    } while (0)
+#else
+#  define MOD(a) a %= BASE
+#endif
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(adler, buf, len)
+    uLong adler;
+    const Bytef *buf;
+    uInt len;
+{
+    unsigned long s1 = adler & 0xffff;
+    unsigned long s2 = (adler >> 16) & 0xffff;
+    int k;
+
+    if (buf == Z_NULL) return 1L;
+
+    while (len > 0) {
+        k = len < NMAX ? (int)len : NMAX;
+        len -= k;
+        while (k >= 16) {
+            DO16(buf);
+            buf += 16;
+            k -= 16;
+        }
+        if (k != 0) do {
+            s1 += *buf++;
+            s2 += s1;
+        } while (--k);
+        MOD(s1);
+        MOD(s2);
+    }
+    return (s2 << 16) | s1;
+}
diff --git a/ext/Compress/Zlib/zlib-src-1.2.2/compress.c b/ext/Compress/Zlib/zlib-src-1.2.2/compress.c
new file mode 100644 (file)
index 0000000..24ef029
--- /dev/null
@@ -0,0 +1,79 @@
+/* compress.c -- compress a memory buffer
+ * Copyright (C) 1995-2002 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+/* ===========================================================================
+     Compresses the source buffer into the destination buffer. The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer. Upon entry, destLen is the total size of the
+   destination buffer, which must be at least 0.1% larger than sourceLen plus
+   12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
+    Bytef *dest;
+    uLongf *destLen;
+    const Bytef *source;
+    uLong sourceLen;
+    int level;
+{
+    z_stream stream;
+    int err;
+
+    stream.next_in = (Bytef*)source;
+    stream.avail_in = (uInt)sourceLen;
+#ifdef MAXSEG_64K
+    /* Check for source > 64K on 16-bit machine: */
+    if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+#endif
+    stream.next_out = dest;
+    stream.avail_out = (uInt)*destLen;
+    if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+    stream.zalloc = (alloc_func)0;
+    stream.zfree = (free_func)0;
+    stream.opaque = (voidpf)0;
+
+    err = deflateInit(&stream, level);
+    if (err != Z_OK) return err;
+
+    err = deflate(&stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        deflateEnd(&stream);
+        return err == Z_OK ? Z_BUF_ERROR : err;
+    }
+    *destLen = stream.total_out;
+
+    err = deflateEnd(&stream);
+    return err;
+}
+
+/* ===========================================================================
+ */
+int ZEXPORT compress (dest, destLen, source, sourceLen)
+    Bytef *dest;
+    uLongf *destLen;
+    const Bytef *source;
+    uLong sourceLen;
+{
+    return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
+}
+
+/* ===========================================================================
+     If the default memLevel or windowBits for deflateInit() is changed, then
+   this function needs to be updated.
+ */
+uLong ZEXPORT compressBound (sourceLen)
+    uLong sourceLen;
+{
+    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11;
+}
diff --git a/ext/Compress/Zlib/zlib-src-1.2.2/crc32.c b/ext/Compress/Zlib/zlib-src-1.2.2/crc32.c
new file mode 100644 (file)
index 0000000..b39c7e1
--- /dev/null
@@ -0,0 +1,333 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-2003 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
+ * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
+ * tables for updating the shift register in one step with three exclusive-ors
+ * instead of four steps with four exclusive-ors.  This results about a factor
+ * of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
+ */
+
+/* @(#) $Id$ */
+
+/*
+  Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
+  protection on the static variables used to control the first-use generation
+  of the crc tables.  Therefore, if you #define DYNAMIC_CRC_TABLE, you should
+  first call get_crc_table() to initialize the tables before allowing more than
+  one thread to use crc32().
+ */
+
+#ifdef MAKECRCH
+#  include <stdio.h>
+#  ifndef DYNAMIC_CRC_TABLE
+#    define DYNAMIC_CRC_TABLE
+#  endif /* !DYNAMIC_CRC_TABLE */
+#endif /* MAKECRCH */
+
+#include "zutil.h"      /* for STDC and FAR definitions */
+
+#define local static
+
+/* Find a four-byte integer type for crc32_little() and crc32_big(). */
+#ifndef NOBYFOUR
+#  ifdef STDC           /* need ANSI C limits.h to determine sizes */
+#    include <limits.h>
+#    define BYFOUR
+#    if (UINT_MAX == 0xffffffffUL)
+       typedef unsigned int u4;
+#    else
+#      if (ULONG_MAX == 0xffffffffUL)
+         typedef unsigned long u4;
+#      else
+#        if (USHRT_MAX == 0xffffffffUL)
+           typedef unsigned short u4;
+#        else
+#          undef BYFOUR     /* can't find a four-byte integer type! */
+#        endif
+#      endif
+#    endif
+#  endif /* STDC */
+#endif /* !NOBYFOUR */
+
+/* Definitions for doing the crc four data bytes at a time. */
+#ifdef BYFOUR
+#  define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
+                (((w)&0xff00)<<8)+(((w)&0xff)<<24))
+   local unsigned long crc32_little OF((unsigned long,
+                        const unsigned char FAR *, unsigned));
+   local unsigned long crc32_big OF((unsigned long,
+                        const unsigned char FAR *, unsigned));
+#  define TBLS 8
+#else
+#  define TBLS 1
+#endif /* BYFOUR */
+
+#ifdef DYNAMIC_CRC_TABLE
+
+local volatile int crc_table_empty = 1;
+local unsigned long FAR crc_table[TBLS][256];
+local void make_crc_table OF((void));
+#ifdef MAKECRCH
+   local void write_table OF((FILE *, const unsigned long FAR *));
+#endif /* MAKECRCH */
+
+/*
+  Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
+  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+  Polynomials over GF(2) are represented in binary, one bit per coefficient,
+  with the lowest powers in the most significant bit.  Then adding polynomials
+  is just exclusive-or, and multiplying a polynomial by x is a right shift by
+  one.  If we call the above polynomial p, and represent a byte as the
+  polynomial q, also with the lowest power in the most significant bit (so the
+  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+  where a mod b means the remainder after dividing a by b.
+
+  This calculation is done using the shift-register method of multiplying and
+  taking the remainder.  The register is initialized to zero, and for each
+  incoming bit, x^32 is added mod p to the register if the bit is a one (where
+  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
+  x (which is shifting right by one and adding x^32 mod p if the bit shifted
+  out is a one).  We start with the highest power (least significant bit) of
+  q and repeat for all eight bits of q.
+
+  The first table is simply the CRC of all possible eight bit values.  This is
+  all the information needed to generate CRCs on data a byte at a time for all
+  combinations of CRC register values and incoming bytes.  The remaining tables
+  allow for word-at-a-time CRC calculation for both big-endian and little-
+  endian machines, where a word is four bytes.
+*/
+local void make_crc_table()
+{
+    unsigned long c;
+    int n, k;
+    unsigned long poly;                 /* polynomial exclusive-or pattern */
+    /* terms of polynomial defining this crc (except x^32): */
+    static volatile int first = 1;      /* flag to limit concurrent making */
+    static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+    /* See if another task is already doing this (not thread-safe, but better
+       than nothing -- significantly reduces duration of vulnerability in
+       case the advice about DYNAMIC_CRC_TABLE is ignored) */
+    if (first) {
+        first = 0;
+
+        /* make exclusive-or pattern from polynomial (0xedb88320UL) */
+        poly = 0UL;
+        for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
+            poly |= 1UL << (31 - p[n]);
+
+        /* generate a crc for every 8-bit value */
+        for (n = 0; n < 256; n++) {
+            c = (unsigned long)n;
+            for (k = 0; k < 8; k++)
+                c = c & 1 ? poly ^ (c >> 1) : c >> 1;
+            crc_table[0][n] = c;
+        }
+
+#ifdef BYFOUR
+        /* generate crc for each value followed by one, two, and three zeros,
+           and then the byte reversal of those as well as the first table */
+        for (n = 0; n < 256; n++) {
+            c = crc_table[0][n];
+            crc_table[4][n] = REV(c);
+            for (k = 1; k < 4; k++) {
+                c = crc_table[0][c & 0xff] ^ (c >> 8);
+                crc_table[k][n] = c;
+                crc_table[k + 4][n] = REV(c);
+            }
+        }
+#endif /* BYFOUR */
+
+        crc_table_empty = 0;
+    }
+    else {      /* not first */
+        /* wait for the other guy to finish (not efficient, but rare) */
+        while (crc_table_empty)
+            ;
+    }
+
+#ifdef MAKECRCH
+    /* write out CRC tables to crc32.h */
+    {
+        FILE *out;
+
+        out = fopen("crc32.h", "w");
+        if (out == NULL) return;
+        fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
+        fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
+        fprintf(out, "local const unsigned long FAR ");
+        fprintf(out, "crc_table[TBLS][256] =\n{\n  {\n");
+        write_table(out, crc_table[0]);
+#  ifdef BYFOUR
+        fprintf(out, "#ifdef BYFOUR\n");
+        for (k = 1; k < 8; k++) {
+            fprintf(out, "  },\n  {\n");
+            write_table(out, crc_table[k]);
+        }
+        fprintf(out, "#endif\n");
+#  endif /* BYFOUR */
+        fprintf(out, "  }\n};\n");
+        fclose(out);
+    }
+#endif /* MAKECRCH */
+}
+
+#ifdef MAKECRCH
+local void write_table(out, table)
+    FILE *out;
+    const unsigned long FAR *table;
+{
+    int n;
+
+    for (n = 0; n < 256; n++)
+        fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : "    ", table[n],
+                n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
+}
+#endif /* MAKECRCH */
+
+#else /* !DYNAMIC_CRC_TABLE */
+/* ========================================================================
+ * Tables of CRC-32s of all single-byte values, made by make_crc_table().
+ */
+#include "crc32.h"
+#endif /* DYNAMIC_CRC_TABLE */
+
+/* =========================================================================
+ * This function can be used by asm versions of crc32()
+ */
+const unsigned long FAR * ZEXPORT get_crc_table()
+{
+#ifdef DYNAMIC_CRC_TABLE
+    if (crc_table_empty)
+        make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+    return (const unsigned long FAR *)crc_table;
+}
+
+/* ========================================================================= */
+#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
+#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
+
+/* ========================================================================= */
+unsigned long ZEXPORT crc32(crc, buf, len)
+    unsigned long crc;
+    const unsigned char FAR *buf;
+    unsigned len;
+{
+    if (buf == Z_NULL) return 0UL;
+
+#ifdef DYNAMIC_CRC_TABLE
+    if (crc_table_empty)
+        make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+
+#ifdef BYFOUR
+    if (sizeof(void *) == sizeof(ptrdiff_t)) {
+        u4 endian;
+
+        endian = 1;
+        if (*((unsigned char *)(&endian)))
+            return crc32_little(crc, buf, len);
+        else
+            return crc32_big(crc, buf, len);
+    }
+#endif /* BYFOUR */
+    crc = crc ^ 0xffffffffUL;
+    while (len >= 8) {
+        DO8;
+        len -= 8;
+    }
+    if (len) do {
+        DO1;
+    } while (--len);
+    return crc ^ 0xffffffffUL;
+}
+
+#ifdef BYFOUR
+
+/* ========================================================================= */
+#define DOLIT4 c ^= *buf4++; \
+        c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
+            crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
+#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
+
+/* ========================================================================= */
+local unsigned long crc32_little(crc, buf, len)
+    unsigned long crc;
+    const unsigned char FAR *buf;
+    unsigned len;
+{
+    register u4 c;
+    register const u4 FAR *buf4;
+
+    c = (u4)crc;
+    c = ~c;
+    while (len && ((ptrdiff_t)buf & 3)) {
+        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+        len--;
+    }
+
+    buf4 = (const u4 FAR *)buf;
+    while (len >= 32) {
+        DOLIT32;
+        len -= 32;
+    }
+    while (len >= 4) {
+        DOLIT4;
+        len -= 4;
+    }
+    buf = (const unsigned char FAR *)buf4;
+
+    if (len) do {
+        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+    } while (--len);
+    c = ~c;
+    return (unsigned long)c;
+}
+
+/* ========================================================================= */
+#define DOBIG4 c ^= *++buf4; \
+        c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
+            crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
+#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
+
+/* ========================================================================= */
+local unsigned long crc32_big(crc, buf, len)
+    unsigned long crc;
+    const unsigned char FAR *buf;
+    unsigned len;
+{
+    register u4 c;
+    register const u4 FAR *buf4;
+
+    c = REV((u4)crc);
+    c = ~c;
+    while (len && ((ptrdiff_t)buf & 3)) {
+        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+        len--;
+    }
+
+    buf4 = (const u4 FAR *)buf;
+    buf4--;
+    while (len >= 32) {
+        DOBIG32;
+        len -= 32;
+    }
+    while (len >= 4) {
+        DOBIG4;
+        len -= 4;
+    }
+    buf4++;
+    buf = (const unsigned char FAR *)buf4;
+
+    if (len) do {
+        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+    } while (--len);
+    c = ~c;
+    return (unsigned long)(REV(c));
+}
+
+#endif /* BYFOUR */
diff --git a/ext/Compress/Zlib/zlib-src-1.2.2/crc32.h b/ext/Compress/Zlib/zlib-src-1.2.2/crc32.h
new file mode 100644 (file)
index 0000000..8053b61
--- /dev/null
@@ -0,0 +1,441 @@
+/* crc32.h -- tables for rapid CRC calculation
+ * Generated automatically by crc32.c
+ */
+
+local const unsigned long FAR crc_table[TBLS][256] =
+{
+  {
+    0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
+    0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
+    0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
+    0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
+    0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
+    0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
+    0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
+    0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
+    0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
+    0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
+    0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
+    0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
+    0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
+    0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
+    0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
+    0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
+    0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
+    0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
+    0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
+    0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
+    0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
+    0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
+    0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
+    0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
+    0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
+    0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
+    0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
+    0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
+    0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
+    0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
+    0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
+    0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
+    0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
+    0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
+    0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
+    0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
+    0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
+    0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
+    0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
+    0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
+    0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
+    0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
+    0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
+    0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
+    0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
+    0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
+    0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
+    0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
+    0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
+    0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
+    0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
+    0x2d02ef8dUL
+#ifdef BYFOUR
+  },
+  {
+    0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
+    0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
+    0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
+    0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
+    0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
+    0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
+    0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
+    0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
+    0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
+    0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
+    0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
+    0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
+    0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
+    0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
+    0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
+    0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
+    0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
+    0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
+    0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
+    0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
+    0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
+    0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
+    0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
+    0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
+    0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
+    0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
+    0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
+    0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
+    0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
+    0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
+    0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
+    0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
+    0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
+    0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
+    0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
+    0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
+    0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
+    0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
+    0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
+    0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
+    0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
+    0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
+    0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
+    0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
+    0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
+    0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
+    0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
+    0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
+    0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
+    0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
+    0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
+    0x9324fd72UL
+  },
+  {
+    0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
+    0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
+    0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
+    0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
+    0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
+    0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
+    0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
+    0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
+    0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
+    0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
+    0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
+    0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
+    0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
+    0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
+    0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
+    0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
+    0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
+    0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
+    0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
+    0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
+    0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
+    0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
+    0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
+    0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
+    0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
+    0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
+    0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
+    0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
+    0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
+    0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
+    0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
+    0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
+    0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
+    0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
+    0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
+    0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
+    0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
+    0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
+    0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
+    0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
+    0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
+    0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
+    0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
+    0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
+    0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
+    0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
+    0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
+    0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
+    0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
+    0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
+    0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
+    0xbe9834edUL
+  },
+  {
+    0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
+    0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
+    0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
+    0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
+    0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
+    0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
+    0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
+    0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
+    0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
+    0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
+    0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
+    0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
+    0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
+    0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
+    0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
+    0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
+    0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
+    0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
+    0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
+    0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
+    0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
+    0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
+    0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
+    0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
+    0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
+    0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
+    0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
+    0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
+    0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
+    0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
+    0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
+    0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
+    0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
+    0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
+    0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
+    0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
+    0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
+    0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
+    0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
+    0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
+    0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
+    0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
+    0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
+    0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
+    0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
+    0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
+    0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
+    0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
+    0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
+    0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
+    0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
+    0xde0506f1UL
+  },
+  {
+    0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
+    0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
+    0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
+    0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
+    0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
+    0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
+    0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
+    0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
+    0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
+    0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
+    0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
+    0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
+    0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
+    0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
+    0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
+    0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
+    0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
+    0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
+    0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
+    0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
+    0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
+    0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
+    0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
+    0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
+    0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
+    0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
+    0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
+    0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
+    0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
+    0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
+    0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
+    0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
+    0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
+    0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
+    0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
+    0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
+    0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
+    0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
+    0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
+    0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
+    0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
+    0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
+    0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
+    0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
+    0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
+    0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
+    0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
+    0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
+    0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
+    0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
+    0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
+    0x8def022dUL
+  },
+  {
+    0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
+    0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
+    0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
+    0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
+    0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
+    0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
+    0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
+    0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
+    0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
+    0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
+    0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
+    0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
+    0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
+    0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
+    0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
+    0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
+    0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
+    0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
+    0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
+    0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
+    0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
+    0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
+    0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
+    0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
+    0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
+    0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
+    0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
+    0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
+    0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
+    0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
+    0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
+    0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
+    0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
+    0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
+    0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
+    0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
+    0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
+    0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
+    0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
+    0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
+    0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
+    0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
+    0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
+    0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
+    0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
+    0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
+    0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
+    0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
+    0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
+    0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
+    0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
+    0x72fd2493UL
+  },
+  {
+    0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
+    0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
+    0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
+    0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
+    0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
+    0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
+    0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
+    0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
+    0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
+    0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
+    0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
+    0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
+    0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
+    0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
+    0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
+    0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
+    0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
+    0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
+    0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
+    0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
+    0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
+    0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
+    0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
+    0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
+    0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
+    0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
+    0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
+    0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
+    0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
+    0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
+    0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
+    0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
+    0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
+    0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
+    0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
+    0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
+    0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
+    0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
+    0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
+    0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
+    0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
+    0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
+    0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
+    0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
+    0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
+    0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
+    0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
+    0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
+    0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
+    0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
+    0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
+    0xed3498beUL
+  },
+  {
+    0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
+    0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
+    0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
+    0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
+    0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
+    0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
+    0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
+    0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
+    0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
+    0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
+    0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
+    0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
+    0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
+    0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
+    0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
+    0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
+    0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
+    0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
+    0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
+    0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
+    0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
+    0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
+    0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
+    0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
+    0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
+    0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
+    0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
+    0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
+    0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
+    0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
+    0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
+    0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
+    0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
+    0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
+    0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
+    0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
+    0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
+    0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
+    0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
+    0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
+    0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
+    0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
+    0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
+    0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
+    0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
+    0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
+    0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
+    0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
+    0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
+    0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
+    0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
+    0xf10605deUL
+#endif
+  }
+};
diff --git a/ext/Compress/Zlib/zlib-src-1.2.2/deflate.c b/ext/Compress/Zlib/zlib-src-1.2.2/deflate.c
new file mode 100644 (file)
index 0000000..0fc53bc
--- /dev/null
@@ -0,0 +1,1502 @@
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1995-2004 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ *  ALGORITHM
+ *
+ *      The "deflation" process depends on being able to identify portions
+ *      of the input text which are identical to earlier input (within a
+ *      sliding window trailing behind the input currently being processed).
+ *
+ *      The most straightforward technique turns out to be the fastest for
+ *      most input files: try all possible matches and select the longest.
+ *      The key feature of this algorithm is that insertions into the string
+ *      dictionary are very simple and thus fast, and deletions are avoided
+ *      completely. Insertions are performed at each input character, whereas
+ *      string matches are performed only when the previous match ends. So it
+ *      is preferable to spend more time in matches to allow very fast string
+ *      insertions and avoid deletions. The matching algorithm for small
+ *      strings is inspired from that of Rabin & Karp. A brute force approach
+ *      is used to find longer strings when a small match has been found.
+ *      A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ *      (by Leonid Broukhis).
+ *         A previous version of this file used a more sophisticated algorithm
+ *      (by Fiala and Greene) which is guaranteed to run in linear amortized
+ *      time, but has a larger average cost, uses more memory and is patented.
+ *      However the F&G algorithm may be faster for some highly redundant
+ *      files if the parameter max_chain_length (described below) is too large.
+ *
+ *  ACKNOWLEDGEMENTS
+ *
+ *      The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ *      I found it in 'freeze' written by Leonid Broukhis.
+ *      Thanks to many people for bug reports and testing.
+ *
+ *  REFERENCES
+ *
+ *      Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
+ *      Available in http://www.ietf.org/rfc/rfc1951.txt
+ *
+ *      A description of the Rabin and Karp algorithm is given in the book
+ *         "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ *      Fiala,E.R., and Greene,D.H.
+ *         Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ */
+
+/* @(#) $Id$ */
+
+#include "deflate.h"
+
+const char deflate_copyright[] =
+   " deflate 1.2.2 Copyright 1995-2004 Jean-loup Gailly ";
+/*
+  If you use the zlib library in a product, an acknowledgment is welcome
+  in the documentation of your product. If for some reason you cannot
+  include such an acknowledgment, I would appreciate that you keep this
+  copyright string in the executable of your product.
+ */
+
+/* ===========================================================================
+ *  Function prototypes.
+ */
+typedef enum {
+    need_more,      /* block not completed, need more input or more output */
+    block_done,     /* block flush performed */
+    finish_started, /* finish started, need only more output at next deflate */
+    finish_done     /* finish done, accept no more input or output */
+} block_state;
+
+typedef block_state (*compress_func) OF((deflate_state *s, int flush));
+/* Compression function. Returns the block state after the call. */
+
+local void fill_window    OF((deflate_state *s));
+local block_state deflate_stored OF((deflate_state *s, int flush));
+local block_state deflate_fast   OF((deflate_state *s, int flush));
+#ifndef FASTEST
+local block_state deflate_slow   OF((deflate_state *s, int flush));
+#endif
+local void lm_init        OF((deflate_state *s));
+local void putShortMSB    OF((deflate_state *s, uInt b));
+local void flush_pending  OF((z_streamp strm));
+local int read_buf        OF((z_streamp strm, Bytef *buf, unsigned size));
+#ifndef FASTEST
+#ifdef ASMV
+      void match_init OF((void)); /* asm code initialization */
+      uInt longest_match  OF((deflate_state *s, IPos cur_match));
+#else
+local uInt longest_match  OF((deflate_state *s, IPos cur_match));
+#endif
+#endif
+local uInt longest_match_fast OF((deflate_state *s, IPos cur_match));
+
+#ifdef DEBUG
+local  void check_match OF((deflate_state *s, IPos start, IPos match,
+                            int length));
+#endif
+
+/* ===========================================================================
+ * Local data
+ */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#ifndef TOO_FAR
+#  define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+typedef struct config_s {
+   ush good_length; /* reduce lazy search above this match length */
+   ush max_lazy;    /* do not perform lazy search above this match length */
+   ush nice_length; /* quit search above this match length */
+   ush max_chain;
+   compress_func func;
+} config;
+
+#ifdef FASTEST
+local const config configuration_table[2] = {
+/*      good lazy nice chain */
+/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
+/* 1 */ {4,    4,  8,    4, deflate_fast}}; /* max speed, no lazy matches */
+#else
+local const config configuration_table[10] = {
+/*      good lazy nice chain */
+/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
+/* 1 */ {4,    4,  8,    4, deflate_fast}, /* max speed, no lazy matches */
+/* 2 */ {4,    5, 16,    8, deflate_fast},
+/* 3 */ {4,    6, 32,   32, deflate_fast},
+
+/* 4 */ {4,    4, 16,   16, deflate_slow},  /* lazy matches */
+/* 5 */ {8,   16, 32,   32, deflate_slow},
+/* 6 */ {8,   16, 128, 128, deflate_slow},
+/* 7 */ {8,   32, 128, 256, deflate_slow},
+/* 8 */ {32, 128, 258, 1024, deflate_slow},
+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */
+#endif
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+#ifndef NO_DUMMY_DECL
+struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
+#endif
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN  assertion: all calls to to UPDATE_HASH are made with consecutive
+ *    input characters, so that a running hash key can be computed from the
+ *    previous key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
+
+
+/* ===========================================================================
+ * Insert string str in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * If this file is compiled with -DFASTEST, the compression level is forced
+ * to 1, and no hash chains are maintained.
+ * IN  assertion: all calls to to INSERT_STRING are made with consecutive
+ *    input characters and the first MIN_MATCH bytes of str are valid
+ *    (except for the last MIN_MATCH-1 bytes of the input file).
+ */
+#ifdef FASTEST
+#define INSERT_STRING(s, str, match_head) \
+   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+    match_head = s->head[s->ins_h], \
+    s->head[s->ins_h] = (Pos)(str))
+#else
+#define INSERT_STRING(s, str, match_head) \
+   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+    match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \
+    s->head[s->ins_h] = (Pos)(str))
+#endif
+
+/* ===========================================================================
+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+ * prev[] will be initialized on the fly.
+ */
+#define CLEAR_HASH(s) \
+    s->head[s->hash_size-1] = NIL; \
+    zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
+
+/* ========================================================================= */
+int ZEXPORT deflateInit_(strm, level, version, stream_size)
+    z_streamp strm;
+    int level;
+    const char *version;
+    int stream_size;
+{
+    return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
+                         Z_DEFAULT_STRATEGY, version, stream_size);
+    /* To do: ignore strm->next_in if we use it as window */
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
+                  version, stream_size)
+    z_streamp strm;
+    int  level;
+    int  method;
+    int  windowBits;
+    int  memLevel;
+    int  strategy;
+    const char *version;
+    int stream_size;
+{
+    deflate_state *s;
+    int wrap = 1;
+    static const char my_version[] = ZLIB_VERSION;
+
+    ushf *overlay;
+    /* We overlay pending_buf and d_buf+l_buf. This works since the average
+     * output size for (length,distance) codes is <= 24 bits.
+     */
+
+    if (version == Z_NULL || version[0] != my_version[0] ||
+        stream_size != sizeof(z_stream)) {
+        return Z_VERSION_ERROR;
+    }
+    if (strm == Z_NULL) return Z_STREAM_ERROR;
+
+    strm->msg = Z_NULL;
+    if (strm->zalloc == (alloc_func)0) {
+        strm->zalloc = zcalloc;
+        strm->opaque = (voidpf)0;
+    }
+    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+
+#ifdef FASTEST
+    if (level != 0) level = 1;
+#else
+    if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+
+    if (windowBits < 0) { /* suppress zlib wrapper */
+        wrap = 0;
+        windowBits = -windowBits;
+    }
+#ifdef GZIP
+    else if (windowBits > 15) {
+        wrap = 2;       /* write gzip wrapper instead */
+        windowBits -= 16;
+    }
+#endif
+    if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
+        windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
+        strategy < 0 || strategy > Z_RLE) {
+        return Z_STREAM_ERROR;
+    }
+    if (windowBits == 8) windowBits = 9;  /* until 256-byte window bug fixed */
+    s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
+    if (s == Z_NULL) return Z_MEM_ERROR;
+    strm->state = (struct internal_state FAR *)s;
+    s->strm = strm;
+
+    s->wrap = wrap;
+    s->w_bits = windowBits;
+    s->w_size = 1 << s->w_bits;
+    s->w_mask = s->w_size - 1;
+
+    s->hash_bits = memLevel + 7;
+    s->hash_size = 1 << s->hash_bits;
+    s->hash_mask = s->hash_size - 1;
+    s->hash_shift =  ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
+
+    s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
+    s->prev   = (Posf *)  ZALLOC(strm, s->w_size, sizeof(Pos));
+    s->head   = (Posf *)  ZALLOC(strm, s->hash_size, sizeof(Pos));
+
+    s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+    overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
+    s->pending_buf = (uchf *) overlay;
+    s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
+
+    if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
+        s->pending_buf == Z_NULL) {
+        s->status = FINISH_STATE;
+        strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
+        deflateEnd (strm);
+        return Z_MEM_ERROR;
+    }
+    s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
+    s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
+
+    s->level = level;
+    s->strategy = strategy;
+    s->method = (Byte)method;
+
+    return deflateReset(strm);
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
+    z_streamp strm;
+    const Bytef *dictionary;
+    uInt  dictLength;
+{
+    deflate_state *s;
+    uInt length = dictLength;
+    uInt n;
+    IPos hash_head = 0;
+
+    if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
+        strm->state->wrap == 2 ||
+        (strm->state->wrap == 1 && strm->state->status != INIT_STATE))
+        return Z_STREAM_ERROR;
+
+    s = strm->state;
+    if (s->wrap)
+        strm->adler = adler32(strm->adler, dictionary, dictLength);
+
+    if (length < MIN_MATCH) return Z_OK;
+    if (length > MAX_DIST(s)) {
+        length = MAX_DIST(s);
+#ifndef USE_DICT_HEAD
+        dictionary += dictLength - length; /* use the tail of the dictionary */
+#endif
+    }
+    zmemcpy(s->window, dictionary, length);
+    s->strstart = length;
+    s->block_start = (long)length;
+
+    /* Insert all strings in the hash table (except for the last two bytes).
+     * s->lookahead stays null, so s->ins_h will be recomputed at the next
+     * call of fill_window.
+     */
+    s->ins_h = s->window[0];
+    UPDATE_HASH(s, s->ins_h, s->window[1]);
+    for (n = 0; n <= length - MIN_MATCH; n++) {
+        INSERT_STRING(s, n, hash_head);
+    }
+    if (hash_head) hash_head = 0;  /* to make compiler happy */
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateReset (strm)
+    z_streamp strm;
+{
+    deflate_state *s;
+
+    if (strm == Z_NULL || strm->state == Z_NULL ||
+        strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) {
+        return Z_STREAM_ERROR;
+    }
+
+    strm->total_in = strm->total_out = 0;
+    strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
+    strm->data_type = Z_UNKNOWN;
+
+    s = (deflate_state *)strm->state;
+    s->pending = 0;
+    s->pending_out = s->pending_buf;
+
+    if (s->wrap < 0) {
+        s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */
+    }
+    s->status = s->wrap ? INIT_STATE : BUSY_STATE;
+    strm->adler =
+#ifdef GZIP
+        s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
+#endif
+        adler32(0L, Z_NULL, 0);
+    s->last_flush = Z_NO_FLUSH;
+
+    _tr_init(s);
+    lm_init(s);
+
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflatePrime (strm, bits, value)
+    z_streamp strm;
+    int bits;
+    int value;
+{
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    strm->state->bi_valid = bits;
+    strm->state->bi_buf = (ush)(value & ((1 << bits) - 1));
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateParams(strm, level, strategy)
+    z_streamp strm;
+    int level;
+    int strategy;
+{
+    deflate_state *s;
+    compress_func func;
+    int err = Z_OK;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    s = strm->state;
+
+#ifdef FASTEST
+    if (level != 0) level = 1;
+#else
+    if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+    if (level < 0 || level > 9 || strategy < 0 || strategy > Z_RLE) {
+        return Z_STREAM_ERROR;
+    }
+    func = configuration_table[s->level].func;
+
+    if (func != configuration_table[level].func && strm->total_in != 0) {
+        /* Flush the last buffer: */
+        err = deflate(strm, Z_PARTIAL_FLUSH);
+    }
+    if (s->level != level) {
+        s->level = level;
+        s->max_lazy_match   = configuration_table[level].max_lazy;
+        s->good_match       = configuration_table[level].good_length;
+        s->nice_match       = configuration_table[level].nice_length;
+        s->max_chain_length = configuration_table[level].max_chain;
+    }
+    s->strategy = strategy;
+    return err;
+}
+
+/* =========================================================================
+ * For the default windowBits of 15 and memLevel of 8, this function returns
+ * a close to exact, as well as small, upper bound on the compressed size.
+ * They are coded as constants here for a reason--if the #define's are
+ * changed, then this function needs to be changed as well.  The return
+ * value for 15 and 8 only works for those exact settings.
+ *
+ * For any setting other than those defaults for windowBits and memLevel,
+ * the value returned is a conservative worst case for the maximum expansion
+ * resulting from using fixed blocks instead of stored blocks, which deflate
+ * can emit on compressed data for some combinations of the parameters.
+ *
+ * This function could be more sophisticated to provide closer upper bounds
+ * for every combination of windowBits and memLevel, as well as wrap.
+ * But even the conservative upper bound of about 14% expansion does not
+ * seem onerous for output buffer allocation.
+ */
+uLong ZEXPORT deflateBound(strm, sourceLen)
+    z_streamp strm;
+    uLong sourceLen;
+{
+    deflate_state *s;
+    uLong destLen;
+
+    /* conservative upper bound */
+    destLen = sourceLen +
+              ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11;
+
+    /* if can't get parameters, return conservative bound */
+    if (strm == Z_NULL || strm->state == Z_NULL)
+        return destLen;
+
+    /* if not default parameters, return conservative bound */
+    s = strm->state;
+    if (s->w_bits != 15 || s->hash_bits != 8 + 7)
+        return destLen;
+
+    /* default settings: return tight bound for that case */
+    return compressBound(sourceLen);
+}
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+local void putShortMSB (s, b)
+    deflate_state *s;
+    uInt b;
+{
+    put_byte(s, (Byte)(b >> 8));
+    put_byte(s, (Byte)(b & 0xff));
+}
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output goes
+ * through this function so some applications may wish to modify it
+ * to avoid allocating a large strm->next_out buffer and copying into it.
+ * (See also read_buf()).
+ */
+local void flush_pending(strm)
+    z_streamp strm;
+{
+    unsigned len = strm->state->pending;
+
+    if (len > strm->avail_out) len = strm->avail_out;
+    if (len == 0) return;
+
+    zmemcpy(strm->next_out, strm->state->pending_out, len);
+    strm->next_out  += len;
+    strm->state->pending_out  += len;
+    strm->total_out += len;
+    strm->avail_out  -= len;
+    strm->state->pending -= len;
+    if (strm->state->pending == 0) {
+        strm->state->pending_out = strm->state->pending_buf;
+    }
+}
+
+/* ========================================================================= */
+int ZEXPORT deflate (strm, flush)
+    z_streamp strm;
+    int flush;
+{
+    int old_flush; /* value of flush param for previous deflate call */
+    deflate_state *s;
+
+    if (strm == Z_NULL || strm->state == Z_NULL ||
+        flush > Z_FINISH || flush < 0) {
+        return Z_STREAM_ERROR;
+    }
+    s = strm->state;
+
+    if (strm->next_out == Z_NULL ||
+        (strm->next_in == Z_NULL && strm->avail_in != 0) ||
+        (s->status == FINISH_STATE && flush != Z_FINISH)) {
+        ERR_RETURN(strm, Z_STREAM_ERROR);
+    }
+    if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
+
+    s->strm = strm; /* just in case */
+    old_flush = s->last_flush;
+    s->last_flush = flush;
+
+    /* Write the header */
+    if (s->status == INIT_STATE) {
+#ifdef GZIP
+        if (s->wrap == 2) {
+            put_byte(s, 31);
+            put_byte(s, 139);
+            put_byte(s, 8);
+            put_byte(s, 0);
+            put_byte(s, 0);
+            put_byte(s, 0);
+            put_byte(s, 0);
+            put_byte(s, 0);
+            put_byte(s, s->level == 9 ? 2 :
+                        (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+                         4 : 0));
+            put_byte(s, 255);
+            s->status = BUSY_STATE;
+            strm->adler = crc32(0L, Z_NULL, 0);
+        }
+        else
+#endif
+        {
+            uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
+            uInt level_flags;
+
+            if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)
+                level_flags = 0;
+            else if (s->level < 6)
+                level_flags = 1;
+            else if (s->level == 6)
+                level_flags = 2;
+            else
+                level_flags = 3;
+            header |= (level_flags << 6);
+            if (s->strstart != 0) header |= PRESET_DICT;
+            header += 31 - (header % 31);
+
+            s->status = BUSY_STATE;
+            putShortMSB(s, header);
+
+            /* Save the adler32 of the preset dictionary: */
+            if (s->strstart != 0) {
+                putShortMSB(s, (uInt)(strm->adler >> 16));
+                putShortMSB(s, (uInt)(strm->adler & 0xffff));
+            }
+            strm->adler = adler32(0L, Z_NULL, 0);
+        }
+    }
+
+    /* Flush as much pending output as possible */
+    if (s->pending != 0) {
+        flush_pending(strm);
+        if (strm->avail_out == 0) {
+            /* Since avail_out is 0, deflate will be called again with
+             * more output space, but possibly with both pending and
+             * avail_in equal to zero. There won't be anything to do,
+             * but this is not an error situation so make sure we
+             * return OK instead of BUF_ERROR at next call of deflate:
+             */
+            s->last_flush = -1;
+            return Z_OK;
+        }
+
+    /* Make sure there is something to do and avoid duplicate consecutive
+     * flushes. For repeated and useless calls with Z_FINISH, we keep
+     * returning Z_STREAM_END instead of Z_BUF_ERROR.
+     */
+    } else if (strm->avail_in == 0 && flush <= old_flush &&
+               flush != Z_FINISH) {
+        ERR_RETURN(strm, Z_BUF_ERROR);
+    }
+
+    /* User must not provide more input after the first FINISH: */
+    if (s->status == FINISH_STATE && strm->avail_in != 0) {
+        ERR_RETURN(strm, Z_BUF_ERROR);
+    }
+
+    /* Start a new block or continue the current one.
+     */
+    if (strm->avail_in != 0 || s->lookahead != 0 ||
+        (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
+        block_state bstate;
+
+        bstate = (*(configuration_table[s->level].func))(s, flush);
+
+        if (bstate == finish_started || bstate == finish_done) {
+            s->status = FINISH_STATE;
+        }
+        if (bstate == need_more || bstate == finish_started) {
+            if (strm->avail_out == 0) {
+                s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+            }
+            return Z_OK;
+            /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+             * of deflate should use the same flush parameter to make sure
+             * that the flush is complete. So we don't have to output an
+             * empty block here, this will be done at next call. This also
+             * ensures that for a very small output buffer, we emit at most
+             * one empty block.
+             */
+        }
+        if (bstate == block_done) {
+            if (flush == Z_PARTIAL_FLUSH) {
+                _tr_align(s);
+            } else { /* FULL_FLUSH or SYNC_FLUSH */
+                _tr_stored_block(s, (char*)0, 0L, 0);
+                /* For a full flush, this empty block will be recognized
+                 * as a special marker by inflate_sync().
+                 */
+                if (flush == Z_FULL_FLUSH) {
+                    CLEAR_HASH(s);             /* forget history */
+                }
+            }
+            flush_pending(strm);
+            if (strm->avail_out == 0) {
+              s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+              return Z_OK;
+            }
+        }
+    }
+    Assert(strm->avail_out > 0, "bug2");
+
+    if (flush != Z_FINISH) return Z_OK;
+    if (s->wrap <= 0) return Z_STREAM_END;
+
+    /* Write the trailer */
+#ifdef GZIP
+    if (s->wrap == 2) {
+        put_byte(s, (Byte)(strm->adler & 0xff));
+        put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+        put_byte(s, (Byte)((strm->adler >> 16) & 0xff));
+        put_byte(s, (Byte)((strm->adler >> 24) & 0xff));
+        put_byte(s, (Byte)(strm->total_in & 0xff));
+        put_byte(s, (Byte)((strm->total_in >> 8) & 0xff));
+        put_byte(s, (Byte)((strm->total_in >> 16) & 0xff));
+        put_byte(s, (Byte)((strm->total_in >> 24) & 0xff));
+    }
+    else
+#endif
+    {
+        putShortMSB(s, (uInt)(strm->adler >> 16));
+        putShortMSB(s, (uInt)(strm->adler & 0xffff));
+    }
+    flush_pending(strm);
+    /* If avail_out is zero, the application will call deflate again
+     * to flush the rest.
+     */
+    if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */
+    return s->pending != 0 ? Z_OK : Z_STREAM_END;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateEnd (strm)
+    z_streamp strm;
+{
+    int status;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+
+    status = strm->state->status;
+    if (status != INIT_STATE && status != BUSY_STATE &&
+        status != FINISH_STATE) {
+      return Z_STREAM_ERROR;
+    }
+
+    /* Deallocate in reverse order of allocations: */
+    TRY_FREE(strm, strm->state->pending_buf);
+    TRY_FREE(strm, strm->state->head);
+    TRY_FREE(strm, strm->state->prev);
+    TRY_FREE(strm, strm->state->window);
+
+    ZFREE(strm, strm->state);
+    strm->state = Z_NULL;
+
+    return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+}
+
+/* =========================================================================
+ * Copy the source state to the destination state.
+ * To simplify the source, this is not supported for 16-bit MSDOS (which
+ * doesn't have enough memory anyway to duplicate compression states).
+ */
+int ZEXPORT deflateCopy (dest, source)
+    z_streamp dest;
+    z_streamp source;
+{
+#ifdef MAXSEG_64K
+    return Z_STREAM_ERROR;
+#else
+    deflate_state *ds;
+    deflate_state *ss;
+    ushf *overlay;
+
+
+    if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) {
+        return Z_STREAM_ERROR;
+    }
+
+    ss = source->state;
+
+    *dest = *source;
+
+    ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
+    if (ds == Z_NULL) return Z_MEM_ERROR;
+    dest->state = (struct internal_state FAR *) ds;
+    *ds = *ss;
+    ds->strm = dest;
+
+    ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
+    ds->prev   = (Posf *)  ZALLOC(dest, ds->w_size, sizeof(Pos));
+    ds->head   = (Posf *)  ZALLOC(dest, ds->hash_size, sizeof(Pos));
+    overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
+    ds->pending_buf = (uchf *) overlay;
+
+    if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
+        ds->pending_buf == Z_NULL) {
+        deflateEnd (dest);
+        return Z_MEM_ERROR;
+    }
+    /* following zmemcpy do not work for 16-bit MSDOS */
+    zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
+    zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
+    zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
+    zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
+
+    ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
+    ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
+    ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
+
+    ds->l_desc.dyn_tree = ds->dyn_ltree;
+    ds->d_desc.dyn_tree = ds->dyn_dtree;
+    ds->bl_desc.dyn_tree = ds->bl_tree;
+
+    return Z_OK;
+#endif /* MAXSEG_64K */
+}
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read.  All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->next_in buffer and copying from it.
+ * (See also flush_pending()).
+ */
+local int read_buf(strm, buf, size)
+    z_streamp strm;
+    Bytef *buf;
+    unsigned size;
+{
+    unsigned len = strm->avail_in;
+
+    if (len > size) len = size;
+    if (len == 0) return 0;
+
+    strm->avail_in  -= len;
+
+    if (strm->state->wrap == 1) {
+        strm->adler = adler32(strm->adler, strm->next_in, len);
+    }
+#ifdef GZIP
+    else if (strm->state->wrap == 2) {
+        strm->adler = crc32(strm->adler, strm->next_in, len);
+    }
+#endif
+    zmemcpy(buf, strm->next_in, len);
+    strm->next_in  += len;
+    strm->total_in += len;
+
+    return (int)len;
+}
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+local void lm_init (s)
+    deflate_state *s;
+{
+    s->window_size = (ulg)2L*s->w_size;
+
+    CLEAR_HASH(s);
+
+    /* Set the default configuration parameters:
+     */
+    s->max_lazy_match   = configuration_table[s->level].max_lazy;
+    s->good_match       = configuration_table[s->level].good_length;
+    s->nice_match       = configuration_table[s->level].nice_length;
+    s->max_chain_length = configuration_table[s->level].max_chain;
+
+    s->strstart = 0;
+    s->block_start = 0L;
+    s->lookahead = 0;
+    s->match_length = s->prev_length = MIN_MATCH-1;
+    s->match_available = 0;
+    s->ins_h = 0;
+#ifdef ASMV
+    match_init(); /* initialize the asm code */
+#endif
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+#ifndef ASMV
+/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
+ * match.S. The code will be functionally equivalent.
+ */
+local uInt longest_match(s, cur_match)
+    deflate_state *s;
+    IPos cur_match;                             /* current match */
+{
+    unsigned chain_length = s->max_chain_length;/* max hash chain length */
+    register Bytef *scan = s->window + s->strstart; /* current string */
+    register Bytef *match;                       /* matched string */
+    register int len;                           /* length of current match */
+    int best_len = s->prev_length;              /* best match length so far */
+    int nice_match = s->nice_match;             /* stop if match long enough */
+    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+        s->strstart - (IPos)MAX_DIST(s) : NIL;
+    /* Stop when cur_match becomes <= limit. To simplify the code,
+     * we prevent matches with the string of window index 0.
+     */
+    Posf *prev = s->prev;
+    uInt wmask = s->w_mask;
+
+#ifdef UNALIGNED_OK
+    /* Compare two bytes at a time. Note: this is not always beneficial.
+     * Try with and without -DUNALIGNED_OK to check.
+     */
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
+    register ush scan_start = *(ushf*)scan;
+    register ush scan_end   = *(ushf*)(scan+best_len-1);
+#else
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+    register Byte scan_end1  = scan[best_len-1];
+    register Byte scan_end   = scan[best_len];
+#endif
+
+    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+     * It is easy to get rid of this optimization if necessary.
+     */
+    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+    /* Do not waste too much time if we already have a good match: */
+    if (s->prev_length >= s->good_match) {
+        chain_length >>= 2;
+    }
+    /* Do not look for matches beyond the end of the input. This is necessary
+     * to make deflate deterministic.
+     */
+    if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+
+    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+    do {
+        Assert(cur_match < s->strstart, "no future");
+        match = s->window + cur_match;
+
+        /* Skip to next match if the match length cannot increase
+         * or if the match length is less than 2:
+         */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+        /* This code assumes sizeof(unsigned short) == 2. Do not use
+         * UNALIGNED_OK if your compiler uses a different size.
+         */
+        if (*(ushf*)(match+best_len-1) != scan_end ||
+            *(ushf*)match != scan_start) continue;
+
+        /* It is not necessary to compare scan[2] and match[2] since they are
+         * always equal when the other bytes match, given that the hash keys
+         * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+         * strstart+3, +5, ... up to strstart+257. We check for insufficient
+         * lookahead only every 4th comparison; the 128th check will be made
+         * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
+         * necessary to put more guard bytes at the end of the window, or
+         * to check more often for insufficient lookahead.
+         */
+        Assert(scan[2] == match[2], "scan[2]?");
+        scan++, match++;
+        do {
+        } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 scan < strend);
+        /* The funny "do {}" generates better code on most compilers */
+
+        /* Here, scan <= window+strstart+257 */
+        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+        if (*scan == *match) scan++;
+
+        len = (MAX_MATCH - 1) - (int)(strend-scan);
+        scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+        if (match[best_len]   != scan_end  ||
+            match[best_len-1] != scan_end1 ||
+            *match            != *scan     ||
+            *++match          != scan[1])      continue;
+
+        /* The check at best_len-1 can be removed because it will be made
+         * again later. (This heuristic is not always a win.)
+         * It is not necessary to compare scan[2] and match[2] since they
+         * are always equal when the other bytes match, given that
+         * the hash keys are equal and that HASH_BITS >= 8.
+         */
+        scan += 2, match++;
+        Assert(*scan == *match, "match[2]?");
+
+        /* We check for insufficient lookahead only every 8th comparison;
+         * the 256th check will be made at strstart+258.
+         */
+        do {
+        } while (*++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 scan < strend);
+
+        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+        len = MAX_MATCH - (int)(strend - scan);
+        scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+        if (len > best_len) {
+            s->match_start = cur_match;
+            best_len = len;
+            if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+            scan_end = *(ushf*)(scan+best_len-1);
+#else
+            scan_end1  = scan[best_len-1];
+            scan_end   = scan[best_len];
+#endif
+        }
+    } while ((cur_match = prev[cur_match & wmask]) > limit
+             && --chain_length != 0);
+
+    if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
+    return s->lookahead;
+}
+#endif /* ASMV */
+#endif /* FASTEST */
+
+/* ---------------------------------------------------------------------------
+ * Optimized version for level == 1 or strategy == Z_RLE only
+ */
+local uInt longest_match_fast(s, cur_match)
+    deflate_state *s;
+    IPos cur_match;                             /* current match */
+{
+    register Bytef *scan = s->window + s->strstart; /* current string */
+    register Bytef *match;                       /* matched string */
+    register int len;                           /* length of current match */
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+
+    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+     * It is easy to get rid of this optimization if necessary.
+     */
+    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+    Assert(cur_match < s->strstart, "no future");
+
+    match = s->window + cur_match;
+
+    /* Return failure if the match length is less than 2:
+     */
+    if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
+
+    /* The check at best_len-1 can be removed because it will be made
+     * again later. (This heuristic is not always a win.)
+     * It is not necessary to compare scan[2] and match[2] since they
+     * are always equal when the other bytes match, given that
+     * the hash keys are equal and that HASH_BITS >= 8.
+     */
+    scan += 2, match += 2;
+    Assert(*scan == *match, "match[2]?");
+
+    /* We check for insufficient lookahead only every 8th comparison;
+     * the 256th check will be made at strstart+258.
+     */
+    do {
+    } while (*++scan == *++match && *++scan == *++match &&
+             *++scan == *++match && *++scan == *++match &&
+             *++scan == *++match && *++scan == *++match &&
+             *++scan == *++match && *++scan == *++match &&
+             scan < strend);
+
+    Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+    len = MAX_MATCH - (int)(strend - scan);
+
+    if (len < MIN_MATCH) return MIN_MATCH - 1;
+
+    s->match_start = cur_match;
+    return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
+}
+
+#ifdef DEBUG
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(s, start, match, length)
+    deflate_state *s;
+    IPos start, match;
+    int length;
+{
+    /* check that the match is indeed a match */
+    if (zmemcmp(s->window + match,
+                s->window + start, length) != EQUAL) {
+        fprintf(stderr, " start %u, match %u, length %d\n",
+                start, match, length);
+        do {
+            fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
+        } while (--length != 0);
+        z_error("invalid match");
+    }
+    if (z_verbose > 1) {
+        fprintf(stderr,"\\[%d,%d]", start-match, length);
+        do { putc(s->window[start++], stderr); } while (--length != 0);
+    }
+}
+#else
+#  define check_match(s, start, match, length)
+#endif /* DEBUG */
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ *    At least one byte has been read, or avail_in == 0; reads are
+ *    performed for at least two bytes (required for the zip translate_eol
+ *    option -- not supported here).
+ */
+local void fill_window(s)
+    deflate_state *s;
+{
+    register unsigned n, m;
+    register Posf *p;
+    unsigned more;    /* Amount of free space at the end of the window. */
+    uInt wsize = s->w_size;
+
+    do {
+        more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
+
+        /* Deal with !@#$% 64K limit: */
+        if (sizeof(int) <= 2) {
+            if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+                more = wsize;
+
+            } else if (more == (unsigned)(-1)) {
+                /* Very unlikely, but possible on 16 bit machine if
+                 * strstart == 0 && lookahead == 1 (input done a byte at time)
+                 */
+                more--;
+            }
+        }
+
+        /* If the window is almost full and there is insufficient lookahead,
+         * move the upper half to the lower one to make room in the upper half.
+         */
+        if (s->strstart >= wsize+MAX_DIST(s)) {
+
+            zmemcpy(s->window, s->window+wsize, (unsigned)wsize);
+            s->match_start -= wsize;
+            s->strstart    -= wsize; /* we now have strstart >= MAX_DIST */
+            s->block_start -= (long) wsize;
+
+            /* Slide the hash table (could be avoided with 32 bit values
+               at the expense of memory usage). We slide even when level == 0
+               to keep the hash table consistent if we switch back to level > 0
+               later. (Using level 0 permanently is not an optimal usage of
+               zlib, so we don't care about this pathological case.)
+             */
+            n = s->hash_size;
+            p = &s->head[n];
+            do {
+                m = *--p;
+                *p = (Pos)(m >= wsize ? m-wsize : NIL);
+            } while (--n);
+
+            n = wsize;
+#ifndef FASTEST
+            p = &s->prev[n];
+            do {
+                m = *--p;
+                *p = (Pos)(m >= wsize ? m-wsize : NIL);
+                /* If n is not on any hash chain, prev[n] is garbage but
+                 * its value will never be used.
+                 */
+            } while (--n);
+#endif
+            more += wsize;
+        }
+        if (s->strm->avail_in == 0) return;
+
+        /* If there was no sliding:
+         *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+         *    more == window_size - lookahead - strstart
+         * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+         * => more >= window_size - 2*WSIZE + 2
+         * In the BIG_MEM or MMAP case (not yet supported),
+         *   window_size == input_size + MIN_LOOKAHEAD  &&
+         *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+         * Otherwise, window_size == 2*WSIZE so more >= 2.
+         * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+         */
+        Assert(more >= 2, "more < 2");
+
+        n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
+        s->lookahead += n;
+
+        /* Initialize the hash value now that we have some input: */
+        if (s->lookahead >= MIN_MATCH) {
+            s->ins_h = s->window[s->strstart];
+            UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+            Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+        }
+        /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+         * but this is not important since only literal bytes will be emitted.
+         */
+
+    } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK_ONLY(s, eof) { \
+   _tr_flush_block(s, (s->block_start >= 0L ? \
+                   (charf *)&s->window[(unsigned)s->block_start] : \
+                   (charf *)Z_NULL), \
+                (ulg)((long)s->strstart - s->block_start), \
+                (eof)); \
+   s->block_start = s->strstart; \
+   flush_pending(s->strm); \
+   Tracev((stderr,"[FLUSH]")); \
+}
+
+/* Same but force premature exit if necessary. */
+#define FLUSH_BLOCK(s, eof) { \
+   FLUSH_BLOCK_ONLY(s, eof); \
+   if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \
+}
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ * This function does not insert new strings in the dictionary since
+ * uncompressible data is probably not useful. This function is used
+ * only for the level=0 compression option.
+ * NOTE: this function should be optimized to avoid extra copying from
+ * window to pending_buf.
+ */
+local block_state deflate_stored(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
+     * to pending_buf_size, and each stored block has a 5 byte header:
+     */
+    ulg max_block_size = 0xffff;
+    ulg max_start;
+
+    if (max_block_size > s->pending_buf_size - 5) {
+        max_block_size = s->pending_buf_size - 5;
+    }
+
+    /* Copy as much as possible from input to output: */
+    for (;;) {
+        /* Fill the window as much as possible: */
+        if (s->lookahead <= 1) {
+
+            Assert(s->strstart < s->w_size+MAX_DIST(s) ||
+                   s->block_start >= (long)s->w_size, "slide too late");
+
+            fill_window(s);
+            if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
+
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+        Assert(s->block_start >= 0L, "block gone");
+
+        s->strstart += s->lookahead;
+        s->lookahead = 0;
+
+        /* Emit a stored block if pending_buf will be full: */
+        max_start = s->block_start + max_block_size;
+        if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
+            /* strstart == 0 is possible when wraparound on 16-bit machine */
+            s->lookahead = (uInt)(s->strstart - max_start);
+            s->strstart = (uInt)max_start;
+            FLUSH_BLOCK(s, 0);
+        }
+        /* Flush if we may have to slide, otherwise block_start may become
+         * negative and the data will be gone:
+         */
+        if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
+            FLUSH_BLOCK(s, 0);
+        }
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local block_state deflate_fast(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    IPos hash_head = NIL; /* head of the hash chain */
+    int bflush;           /* set if current block must be flushed */
+
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the next match, plus MIN_MATCH bytes to insert the
+         * string following the next match.
+         */
+        if (s->lookahead < MIN_LOOKAHEAD) {
+            fill_window(s);
+            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+                return need_more;
+            }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* Insert the string window[strstart .. strstart+2] in the
+         * dictionary, and set hash_head to the head of the hash chain:
+         */
+        if (s->lookahead >= MIN_MATCH) {
+            INSERT_STRING(s, s->strstart, hash_head);
+        }
+
+        /* Find the longest match, discarding those <= prev_length.
+         * At this point we have always match_length < MIN_MATCH
+         */
+        if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
+            /* To simplify the code, we prevent matches with the string
+             * of window index 0 (in particular we have to avoid a match
+             * of the string with itself at the start of the input file).
+             */
+#ifdef FASTEST
+            if ((s->strategy < Z_HUFFMAN_ONLY) ||
+                (s->strategy == Z_RLE && s->strstart - hash_head == 1)) {
+                s->match_length = longest_match_fast (s, hash_head);
+            }
+#else
+            if (s->strategy < Z_HUFFMAN_ONLY) {
+                s->match_length = longest_match (s, hash_head);
+            } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
+                s->match_length = longest_match_fast (s, hash_head);
+            }
+#endif
+            /* longest_match() or longest_match_fast() sets match_start */
+        }
+        if (s->match_length >= MIN_MATCH) {
+            check_match(s, s->strstart, s->match_start, s->match_length);
+
+            _tr_tally_dist(s, s->strstart - s->match_start,
+                           s->match_length - MIN_MATCH, bflush);
+
+            s->lookahead -= s->match_length;
+
+            /* Insert new strings in the hash table only if the match length
+             * is not too large. This saves time but degrades compression.
+             */
+#ifndef FASTEST
+            if (s->match_length <= s->max_insert_length &&
+                s->lookahead >= MIN_MATCH) {
+                s->match_length--; /* string at strstart already in table */
+                do {
+                    s->strstart++;
+                    INSERT_STRING(s, s->strstart, hash_head);
+                    /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+                     * always MIN_MATCH bytes ahead.
+                     */
+                } while (--s->match_length != 0);
+                s->strstart++;
+            } else
+#endif
+            {
+                s->strstart += s->match_length;
+                s->match_length = 0;
+                s->ins_h = s->window[s->strstart];
+                UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+                Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+                /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+                 * matter since it will be recomputed at next deflate call.
+                 */
+            }
+        } else {
+            /* No match, output a literal byte */
+            Tracevv((stderr,"%c", s->window[s->strstart]));
+            _tr_tally_lit (s, s->window[s->strstart], bflush);
+            s->lookahead--;
+            s->strstart++;
+        }
+        if (bflush) FLUSH_BLOCK(s, 0);
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+local block_state deflate_slow(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    IPos hash_head = NIL;    /* head of hash chain */
+    int bflush;              /* set if current block must be flushed */
+
+    /* Process the input block. */
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the next match, plus MIN_MATCH bytes to insert the
+         * string following the next match.
+         */
+        if (s->lookahead < MIN_LOOKAHEAD) {
+            fill_window(s);
+            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+                return need_more;
+            }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* Insert the string window[strstart .. strstart+2] in the
+         * dictionary, and set hash_head to the head of the hash chain:
+         */
+        if (s->lookahead >= MIN_MATCH) {
+            INSERT_STRING(s, s->strstart, hash_head);
+        }
+
+        /* Find the longest match, discarding those <= prev_length.
+         */
+        s->prev_length = s->match_length, s->prev_match = s->match_start;
+        s->match_length = MIN_MATCH-1;
+
+        if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
+            s->strstart - hash_head <= MAX_DIST(s)) {
+            /* To simplify the code, we prevent matches with the string
+             * of window index 0 (in particular we have to avoid a match
+             * of the string with itself at the start of the input file).
+             */
+            if (s->strategy < Z_HUFFMAN_ONLY) {
+                s->match_length = longest_match (s, hash_head);
+            } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
+                s->match_length = longest_match_fast (s, hash_head);
+            }
+            /* longest_match() or longest_match_fast() sets match_start */
+
+            if (s->match_length <= 5 && (s->strategy == Z_FILTERED
+#if TOO_FAR <= 32767
+                || (s->match_length == MIN_MATCH &&
+                    s->strstart - s->match_start > TOO_FAR)
+#endif
+                )) {
+
+                /* If prev_match is also MIN_MATCH, match_start is garbage
+                 * but we will ignore the current match anyway.
+                 */
+                s->match_length = MIN_MATCH-1;
+            }
+        }
+        /* If there was a match at the previous step and the current
+         * match is not better, output the previous match:
+         */
+        if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
+            uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
+            /* Do not insert strings in hash table beyond this. */
+
+            check_match(s, s->strstart-1, s->prev_match, s->prev_length);
+
+            _tr_tally_dist(s, s->strstart -1 - s->prev_match,
+                           s->prev_length - MIN_MATCH, bflush);
+
+            /* Insert in hash table all strings up to the end of the match.
+             * strstart-1 and strstart are already inserted. If there is not
+             * enough lookahead, the last two strings are not inserted in
+             * the hash table.
+             */
+            s->lookahead -= s->prev_length-1;
+            s->prev_length -= 2;
+            do {
+                if (++s->strstart <= max_insert) {
+                    INSERT_STRING(s, s->strstart, hash_head);
+                }
+            } while (--s->prev_length != 0);
+            s->match_available = 0;
+            s->match_length = MIN_MATCH-1;
+            s->strstart++;
+
+            if (bflush) FLUSH_BLOCK(s, 0);
+
+        } else if (s->match_available) {
+            /* If there was no match at the previous position, output a
+             * single literal. If there was a match but the current match
+             * is longer, truncate the previous match to a single literal.
+             */
+            Tracevv((stderr,"%c", s->window[s->strstart-1]));
+            _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+            if (bflush) {
+                FLUSH_BLOCK_ONLY(s, 0);
+            }
+            s->strstart++;
+            s->lookahead--;
+            if (s->strm->avail_out == 0) return need_more;
+        } else {
+            /* There is no previous match to compare with, wait for
+             * the next step to decide.
+             */
+            s->match_available = 1;
+            s->strstart++;
+            s->lookahead--;
+        }
+    }
+    Assert (flush != Z_NO_FLUSH, "no flush?");
+    if (s->match_available) {
+        Tracevv((stderr,"%c", s->window[s->strstart-1]));
+        _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+        s->match_available = 0;
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+#endif /* FASTEST */
diff --git a/ext/Compress/Zlib/zlib-src-1.2.2/deflate.h b/ext/Compress/Zlib/zlib-src-1.2.2/deflate.h
new file mode 100644 (file)
index 0000000..410681d
--- /dev/null
@@ -0,0 +1,325 @@
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995-2002 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef DEFLATE_H
+#define DEFLATE_H
+
+#include "zutil.h"
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+   trailer creation by deflate().  NO_GZIP would be used to avoid linking in
+   the crc code when it is not needed.  For shared libraries, gzip encoding
+   should be left enabled. */
+#ifndef NO_GZIP
+#  define GZIP
+#endif
+
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS  256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES   30
+/* number of distance codes */
+
+#define BL_CODES  19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define INIT_STATE    42
+#define BUSY_STATE   113
+#define FINISH_STATE 666
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+    union {
+        ush  freq;       /* frequency count */
+        ush  code;       /* bit string */
+    } fc;
+    union {
+        ush  dad;        /* father node in Huffman tree */
+        ush  len;        /* length of bit string */
+    } dl;
+} FAR ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad  dl.dad
+#define Len  dl.len
+
+typedef struct static_tree_desc_s  static_tree_desc;
+
+typedef struct tree_desc_s {
+    ct_data *dyn_tree;           /* the dynamic tree */
+    int     max_code;            /* largest code with non zero frequency */
+    static_tree_desc *stat_desc; /* the corresponding static tree */
+} FAR tree_desc;
+
+typedef ush Pos;
+typedef Pos FAR Posf;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct internal_state {
+    z_streamp strm;      /* pointer back to this zlib stream */
+    int   status;        /* as the name implies */
+    Bytef *pending_buf;  /* output still pending */
+    ulg   pending_buf_size; /* size of pending_buf */
+    Bytef *pending_out;  /* next pending byte to output to the stream */
+    int   pending;       /* nb of bytes in the pending buffer */
+    int   wrap;          /* bit 0 true for zlib, bit 1 true for gzip */
+    Byte  method;        /* STORED (for zip only) or DEFLATED */
+    int   last_flush;    /* value of flush param for previous deflate call */
+
+                /* used by deflate.c: */
+
+    uInt  w_size;        /* LZ77 window size (32K by default) */
+    uInt  w_bits;        /* log2(w_size)  (8..16) */
+    uInt  w_mask;        /* w_size - 1 */
+
+    Bytef *window;
+    /* Sliding window. Input bytes are read into the second half of the window,
+     * and move to the first half later to keep a dictionary of at least wSize
+     * bytes. With this organization, matches are limited to a distance of
+     * wSize-MAX_MATCH bytes, but this ensures that IO is always
+     * performed with a length multiple of the block size. Also, it limits
+     * the window size to 64K, which is quite useful on MSDOS.
+     * To do: use the user input buffer as sliding window.
+     */
+
+    ulg window_size;
+    /* Actual size of window: 2*wSize, except when the user input buffer
+     * is directly used as sliding window.
+     */
+
+    Posf *prev;
+    /* Link to older string with same hash index. To limit the size of this
+     * array to 64K, this link is maintained only for the last 32K strings.
+     * An index in this array is thus a window index modulo 32K.
+     */
+
+    Posf *head; /* Heads of the hash chains or NIL. */
+
+    uInt  ins_h;          /* hash index of string to be inserted */
+    uInt  hash_size;      /* number of elements in hash table */
+    uInt  hash_bits;      /* log2(hash_size) */
+    uInt  hash_mask;      /* hash_size-1 */
+
+    uInt  hash_shift;
+    /* Number of bits by which ins_h must be shifted at each input
+     * step. It must be such that after MIN_MATCH steps, the oldest
+     * byte no longer takes part in the hash key, that is:
+     *   hash_shift * MIN_MATCH >= hash_bits
+     */
+
+    long block_start;
+    /* Window position at the beginning of the current output block. Gets
+     * negative when the window is moved backwards.
+     */
+
+    uInt match_length;           /* length of best match */
+    IPos prev_match;             /* previous match */
+    int match_available;         /* set if previous match exists */
+    uInt strstart;               /* start of string to insert */
+    uInt match_start;            /* start of matching string */
+    uInt lookahead;              /* number of valid bytes ahead in window */
+
+    uInt prev_length;
+    /* Length of the best match at previous step. Matches not greater than this
+     * are discarded. This is used in the lazy match evaluation.
+     */
+
+    uInt max_chain_length;
+    /* To speed up deflation, hash chains are never searched beyond this
+     * length.  A higher limit improves compression ratio but degrades the
+     * speed.
+     */
+
+    uInt max_lazy_match;
+    /* Attempt to find a better match only when the current match is strictly
+     * smaller than this value. This mechanism is used only for compression
+     * levels >= 4.
+     */
+#   define max_insert_length  max_lazy_match
+    /* Insert new strings in the hash table only if the match length is not
+     * greater than this length. This saves time but degrades compression.
+     * max_insert_length is used only for compression levels <= 3.
+     */
+
+    int level;    /* compression level (1..9) */
+    int strategy; /* favor or force Huffman coding*/
+
+    uInt good_match;
+    /* Use a faster search when the previous match is longer than this */
+
+    int nice_match; /* Stop searching when current match exceeds this */
+
+                /* used by trees.c: */
+    /* Didn't use ct_data typedef below to supress compiler warning */
+    struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */
+    struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+    struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */
+
+    struct tree_desc_s l_desc;               /* desc. for literal tree */
+    struct tree_desc_s d_desc;               /* desc. for distance tree */
+    struct tree_desc_s bl_desc;              /* desc. for bit length tree */
+
+    ush bl_count[MAX_BITS+1];
+    /* number of codes at each bit length for an optimal tree */
+
+    int heap[2*L_CODES+1];      /* heap used to build the Huffman trees */
+    int heap_len;               /* number of elements in the heap */
+    int heap_max;               /* element of largest frequency */
+    /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+     * The same heap array is used to build all trees.
+     */
+
+    uch depth[2*L_CODES+1];
+    /* Depth of each subtree used as tie breaker for trees of equal frequency
+     */
+
+    uchf *l_buf;          /* buffer for literals or lengths */
+
+    uInt  lit_bufsize;
+    /* Size of match buffer for literals/lengths.  There are 4 reasons for
+     * limiting lit_bufsize to 64K:
+     *   - frequencies can be kept in 16 bit counters
+     *   - if compression is not successful for the first block, all input
+     *     data is still in the window so we can still emit a stored block even
+     *     when input comes from standard input.  (This can also be done for
+     *     all blocks if lit_bufsize is not greater than 32K.)
+     *   - if compression is not successful for a file smaller than 64K, we can
+     *     even emit a stored file instead of a stored block (saving 5 bytes).
+     *     This is applicable only for zip (not gzip or zlib).
+     *   - creating new Huffman trees less frequently may not provide fast
+     *     adaptation to changes in the input data statistics. (Take for
+     *     example a binary file with poorly compressible code followed by
+     *     a highly compressible string table.) Smaller buffer sizes give
+     *     fast adaptation but have of course the overhead of transmitting
+     *     trees more frequently.
+     *   - I can't count above 4
+     */
+
+    uInt last_lit;      /* running index in l_buf */
+
+    ushf *d_buf;
+    /* Buffer for distances. To simplify the code, d_buf and l_buf have
+     * the same number of elements. To use different lengths, an extra flag
+     * array would be necessary.
+     */
+
+    ulg opt_len;        /* bit length of current block with optimal trees */
+    ulg static_len;     /* bit length of current block with static trees */
+    uInt matches;       /* number of string matches in current block */
+    int last_eob_len;   /* bit length of EOB code for last block */
+
+#ifdef DEBUG
+    ulg compressed_len; /* total bit length of compressed file mod 2^32 */
+    ulg bits_sent;      /* bit length of compressed data sent mod 2^32 */
+#endif
+
+    ush bi_buf;
+    /* Output buffer. bits are inserted starting at the bottom (least
+     * significant bits).
+     */
+    int bi_valid;
+    /* Number of valid bits in bi_buf.  All bits above the last valid bit
+     * are always zero.
+     */
+
+} FAR deflate_state;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s)  ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+        /* in trees.c */
+void _tr_init         OF((deflate_state *s));
+int  _tr_tally        OF((deflate_state *s, unsigned dist, unsigned lc));
+void _tr_flush_block  OF((deflate_state *s, charf *buf, ulg stored_len,
+                          int eof));
+void _tr_align        OF((deflate_state *s));
+void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
+                          int eof));
+
+#define d_code(dist) \
+   ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. _dist_code[256] and _dist_code[257] are never
+ * used.
+ */
+
+#ifndef DEBUG
+/* Inline versions of _tr_tally for speed: */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+  extern uch _length_code[];
+  extern uch _dist_code[];
+#else
+  extern const uch _length_code[];
+  extern const uch _dist_code[];
+#endif
+
+# define _tr_tally_lit(s, c, flush) \
+  { uch cc = (c); \
+    s->d_buf[s->last_lit] = 0; \
+    s->l_buf[s->last_lit++] = cc; \
+    s->dyn_ltree[cc].Freq++; \
+    flush = (s->last_lit == s->lit_bufsize-1); \
+   }
+# define _tr_tally_dist(s, distance, length, flush) \
+  { uch len = (length); \
+    ush dist = (distance); \
+    s->d_buf[s->last_lit] = dist; \
+    s->l_buf[s->last_lit++] = len; \
+    dist--; \
+    s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+    s->dyn_dtree[d_code(dist)].Freq++; \
+    flush = (s->last_lit == s->lit_bufsize-1); \
+  }
+#else
+# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
+# define _tr_tally_dist(s, distance, length, flush) \
+              flush = _tr_tally(s, distance, length)
+#endif
+
+#endif /* DEFLATE_H */
diff --git a/ext/Compress/Zlib/zlib-src-1.2.2/gzio.c b/ext/Compress/Zlib/zlib-src-1.2.2/gzio.c
new file mode 100644 (file)
index 0000000..5e71b0a
--- /dev/null
@@ -0,0 +1,1009 @@
+/* gzio.c -- IO on .gz files
+ * Copyright (C) 1995-2003 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Compile this file with -DNO_GZCOMPRESS to avoid the compression code.
+ */
+
+/* @(#) $Id$ */
+
+#include <stdio.h>
+
+#include "zutil.h"
+
+#ifdef NO_DEFLATE       /* for compatiblity with old definition */
+#  define NO_GZCOMPRESS
+#endif
+
+#ifndef NO_DUMMY_DECL
+struct internal_state {int dummy;}; /* for buggy compilers */
+#endif
+
+#ifndef Z_BUFSIZE
+#  ifdef MAXSEG_64K
+#    define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */
+#  else
+#    define Z_BUFSIZE 16384
+#  endif
+#endif
+#ifndef Z_PRINTF_BUFSIZE
+#  define Z_PRINTF_BUFSIZE 4096
+#endif
+
+#ifdef __MVS__
+#  pragma map (fdopen , "\174\174FDOPEN")
+   FILE *fdopen(int, const char *);
+#endif
+
+#ifndef STDC
+extern voidp  malloc OF((uInt size));
+extern void   free   OF((voidpf ptr));
+#endif
+
+#define ALLOC(size) malloc(size)
+#define TRYFREE(p) {if (p) free(p);}
+
+static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
+
+/* gzip flag byte */
+#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
+#define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
+#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
+#define COMMENT      0x10 /* bit 4 set: file comment present */
+#define RESERVED     0xE0 /* bits 5..7: reserved */
+
+typedef struct gz_stream {
+    z_stream stream;
+    int      z_err;   /* error code for last stream operation */
+    int      z_eof;   /* set if end of input file */
+    FILE     *file;   /* .gz file */
+    Byte     *inbuf;  /* input buffer */
+    Byte     *outbuf; /* output buffer */
+    uLong    crc;     /* crc32 of uncompressed data */
+    char     *msg;    /* error message */
+    char     *path;   /* path name for debugging only */
+    int      transparent; /* 1 if input file is not a .gz file */
+    char     mode;    /* 'w' or 'r' */
+    z_off_t  start;   /* start of compressed data in file (header skipped) */
+    z_off_t  in;      /* bytes into deflate or inflate */
+    z_off_t  out;     /* bytes out of deflate or inflate */
+    int      back;    /* one character push-back */
+    int      last;    /* true if push-back is last character */
+} gz_stream;
+
+
+local gzFile gz_open      OF((const char *path, const char *mode, int  fd));
+local int do_flush        OF((gzFile file, int flush));
+local int    get_byte     OF((gz_stream *s));
+local void   check_header OF((gz_stream *s));
+local int    destroy      OF((gz_stream *s));
+local void   putLong      OF((FILE *file, uLong x));
+local uLong  getLong      OF((gz_stream *s));
+
+/* ===========================================================================
+     Opens a gzip (.gz) file for reading or writing. The mode parameter
+   is as in fopen ("rb" or "wb"). The file is given either by file descriptor
+   or path name (if fd == -1).
+     gz_open returns NULL if the file could not be opened or if there was
+   insufficient memory to allocate the (de)compression state; errno
+   can be checked to distinguish the two cases (if errno is zero, the
+   zlib error is Z_MEM_ERROR).
+*/
+local gzFile gz_open (path, mode, fd)
+    const char *path;
+    const char *mode;
+    int  fd;
+{
+    int err;
+    int level = Z_DEFAULT_COMPRESSION; /* compression level */
+    int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
+    char *p = (char*)mode;
+    gz_stream *s;
+    char fmode[80]; /* copy of mode, without the compression level */
+    char *m = fmode;
+
+    if (!path || !mode) return Z_NULL;
+
+    s = (gz_stream *)ALLOC(sizeof(gz_stream));
+    if (!s) return Z_NULL;
+
+    s->stream.zalloc = (alloc_func)0;
+    s->stream.zfree = (free_func)0;
+    s->stream.opaque = (voidpf)0;
+    s->stream.next_in = s->inbuf = Z_NULL;
+    s->stream.next_out = s->outbuf = Z_NULL;
+    s->stream.avail_in = s->stream.avail_out = 0;
+    s->file = NULL;
+    s->z_err = Z_OK;
+    s->z_eof = 0;
+    s->in = 0;
+    s->out = 0;
+    s->back = EOF;
+    s->crc = crc32(0L, Z_NULL, 0);
+    s->msg = NULL;
+    s->transparent = 0;
+
+    s->path = (char*)ALLOC(strlen(path)+1);
+    if (s->path == NULL) {
+        return destroy(s), (gzFile)Z_NULL;
+    }
+    strcpy(s->path, path); /* do this early for debugging */
+
+    s->mode = '\0';
+    do {
+        if (*p == 'r') s->mode = 'r';
+        if (*p == 'w' || *p == 'a') s->mode = 'w';
+        if (*p >= '0' && *p <= '9') {
+            level = *p - '0';
+        } else if (*p == 'f') {
+          strategy = Z_FILTERED;
+        } else if (*p == 'h') {
+          strategy = Z_HUFFMAN_ONLY;
+        } else if (*p == 'R') {
+          strategy = Z_RLE;
+        } else {
+            *m++ = *p; /* copy the mode */
+        }
+    } while (*p++ && m != fmode + sizeof(fmode));
+    if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
+
+    if (s->mode == 'w') {
+#ifdef NO_GZCOMPRESS
+        err = Z_STREAM_ERROR;
+#else
+        err = deflateInit2(&(s->stream), level,
+                           Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy);
+        /* windowBits is passed < 0 to suppress zlib header */
+
+        s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
+#endif
+        if (err != Z_OK || s->outbuf == Z_NULL) {
+            return destroy(s), (gzFile)Z_NULL;
+        }
+    } else {
+        s->stream.next_in  = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
+
+        err = inflateInit2(&(s->stream), -MAX_WBITS);
+        /* windowBits is passed < 0 to tell that there is no zlib header.
+         * Note that in this case inflate *requires* an extra "dummy" byte
+         * after the compressed stream in order to complete decompression and
+         * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
+         * present after the compressed stream.
+         */
+        if (err != Z_OK || s->inbuf == Z_NULL) {
+            return destroy(s), (gzFile)Z_NULL;
+        }
+    }
+    s->stream.avail_out = Z_BUFSIZE;
+
+    errno = 0;
+    s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode);
+
+    if (s->file == NULL) {
+        return destroy(s), (gzFile)Z_NULL;
+    }
+    if (s->mode == 'w') {
+        /* Write a very simple .gz header:
+         */
+        fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
+             Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
+        s->start = 10L;
+        /* We use 10L instead of ftell(s->file) to because ftell causes an
+         * fflush on some systems. This version of the library doesn't use
+         * start anyway in write mode, so this initialization is not
+         * necessary.
+         */
+    } else {
+        check_header(s); /* skip the .gz header */
+        s->start = ftell(s->file) - s->stream.avail_in;
+    }
+
+    return (gzFile)s;
+}
+
+/* ===========================================================================
+     Opens a gzip (.gz) file for reading or writing.
+*/
+gzFile ZEXPORT gzopen (path, mode)
+    const char *path;
+    const char *mode;
+{
+    return gz_open (path, mode, -1);
+}
+
+/* ===========================================================================
+     Associate a gzFile with the file descriptor fd. fd is not dup'ed here
+   to mimic the behavio(u)r of fdopen.
+*/
+gzFile ZEXPORT gzdopen (fd, mode)
+    int fd;
+    const char *mode;
+{
+    char name[20];
+
+    if (fd < 0) return (gzFile)Z_NULL;
+    sprintf(name, "<fd:%d>", fd); /* for debugging */
+
+    return gz_open (name, mode, fd);
+}
+
+/* ===========================================================================
+ * Update the compression level and strategy
+ */
+int ZEXPORT gzsetparams (file, level, strategy)
+    gzFile file;
+    int level;
+    int strategy;
+{
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
+
+    /* Make room to allow flushing */
+    if (s->stream.avail_out == 0) {
+
+        s->stream.next_out = s->outbuf;
+        if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
+            s->z_err = Z_ERRNO;
+        }
+        s->stream.avail_out = Z_BUFSIZE;
+    }
+
+    return deflateParams (&(s->stream), level, strategy);
+}
+
+/* ===========================================================================
+     Read a byte from a gz_stream; update next_in and avail_in. Return EOF
+   for end of file.
+   IN assertion: the stream s has been sucessfully opened for reading.
+*/
+local int get_byte(s)
+    gz_stream *s;
+{
+    if (s->z_eof) return EOF;
+    if (s->stream.avail_in == 0) {
+        errno = 0;
+        s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
+        if (s->stream.avail_in == 0) {
+            s->z_eof = 1;
+            if (ferror(s->file)) s->z_err = Z_ERRNO;
+            return EOF;
+        }
+        s->stream.next_in = s->inbuf;
+    }
+    s->stream.avail_in--;
+    return *(s->stream.next_in)++;
+}
+
+/* ===========================================================================
+      Check the gzip header of a gz_stream opened for reading. Set the stream
+    mode to transparent if the gzip magic header is not present; set s->err
+    to Z_DATA_ERROR if the magic header is present but the rest of the header
+    is incorrect.
+    IN assertion: the stream s has already been created sucessfully;
+       s->stream.avail_in is zero for the first time, but may be non-zero
+       for concatenated .gz files.
+*/
+local void check_header(s)
+    gz_stream *s;
+{
+    int method; /* method byte */
+    int flags;  /* flags byte */
+    uInt len;
+    int c;
+
+    /* Assure two bytes in the buffer so we can peek ahead -- handle case
+       where first byte of header is at the end of the buffer after the last
+       gzip segment */
+    len = s->stream.avail_in;
+    if (len < 2) {
+        if (len) s->inbuf[0] = s->stream.next_in[0];
+        errno = 0;
+        len = fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
+        if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO;
+        s->stream.avail_in += len;
+        s->stream.next_in = s->inbuf;
+        if (s->stream.avail_in < 2) {
+            s->transparent = s->stream.avail_in;
+            return;
+        }
+    }
+
+    /* Peek ahead to check the gzip magic header */
+    if (s->stream.next_in[0] != gz_magic[0] ||
+        s->stream.next_in[1] != gz_magic[1]) {
+        s->transparent = 1;
+        return;
+    }
+    s->stream.avail_in -= 2;
+    s->stream.next_in += 2;
+
+    /* Check the rest of the gzip header */
+    method = get_byte(s);
+    flags = get_byte(s);
+    if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
+        s->z_err = Z_DATA_ERROR;
+        return;
+    }
+
+    /* Discard time, xflags and OS code: */
+    for (len = 0; len < 6; len++) (void)get_byte(s);
+
+    if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
+        len  =  (uInt)get_byte(s);
+        len += ((uInt)get_byte(s))<<8;
+        /* len is garbage if EOF but the loop below will quit anyway */
+        while (len-- != 0 && get_byte(s) != EOF) ;
+    }
+    if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
+        while ((c = get_byte(s)) != 0 && c != EOF) ;
+    }
+    if ((flags & COMMENT) != 0) {   /* skip the .gz file comment */
+        while ((c = get_byte(s)) != 0 && c != EOF) ;
+    }
+    if ((flags & HEAD_CRC) != 0) {  /* skip the header crc */
+        for (len = 0; len < 2; len++) (void)get_byte(s);
+    }
+    s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
+}
+
+ /* ===========================================================================
+ * Cleanup then free the given gz_stream. Return a zlib error code.
+   Try freeing in the reverse order of allocations.
+ */
+local int destroy (s)
+    gz_stream *s;
+{
+    int err = Z_OK;
+
+    if (!s) return Z_STREAM_ERROR;
+
+    TRYFREE(s->msg);
+
+    if (s->stream.state != NULL) {
+        if (s->mode == 'w') {
+#ifdef NO_GZCOMPRESS
+            err = Z_STREAM_ERROR;
+#else
+            err = deflateEnd(&(s->stream));
+#endif
+        } else if (s->mode == 'r') {
+            err = inflateEnd(&(s->stream));
+        }
+    }
+    if (s->file != NULL && fclose(s->file)) {
+#ifdef ESPIPE
+        if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */
+#endif
+            err = Z_ERRNO;
+    }
+    if (s->z_err < 0) err = s->z_err;
+
+    TRYFREE(s->inbuf);
+    TRYFREE(s->outbuf);
+    TRYFREE(s->path);
+    TRYFREE(s);
+    return err;
+}
+
+/* ===========================================================================
+     Reads the given number of uncompressed bytes from the compressed file.
+   gzread returns the number of bytes actually read (0 for end of file).
+*/
+int ZEXPORT gzread (file, buf, len)
+    gzFile file;
+    voidp buf;
+    unsigned len;
+{
+    gz_stream *s = (gz_stream*)file;
+    Bytef *start = (Bytef*)buf; /* starting point for crc computation */
+    Byte  *next_out; /* == stream.next_out but not forced far (for MSDOS) */
+
+    if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
+
+    if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
+    if (s->z_err == Z_STREAM_END) return 0;  /* EOF */
+
+    next_out = (Byte*)buf;
+    s->stream.next_out = (Bytef*)buf;
+    s->stream.avail_out = len;
+
+    if (s->stream.avail_out && s->back != EOF) {
+        *next_out++ = s->back;
+        s->stream.next_out++;
+        s->stream.avail_out--;
+        s->back = EOF;
+        s->out++;
+        if (s->last) {
+            s->z_err = Z_STREAM_END;
+            return 1;
+        }
+    }
+
+    while (s->stream.avail_out != 0) {
+
+        if (s->transparent) {
+            /* Copy first the lookahead bytes: */
+            uInt n = s->stream.avail_in;
+            if (n > s->stream.avail_out) n = s->stream.avail_out;
+            if (n > 0) {
+                zmemcpy(s->stream.next_out, s->stream.next_in, n);
+                next_out += n;
+                s->stream.next_out = next_out;
+                s->stream.next_in   += n;
+                s->stream.avail_out -= n;
+                s->stream.avail_in  -= n;
+            }
+            if (s->stream.avail_out > 0) {
+                s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out,
+                                             s->file);
+            }
+            len -= s->stream.avail_out;
+            s->in  += len;
+            s->out += len;
+            if (len == 0) s->z_eof = 1;
+            return (int)len;
+        }
+        if (s->stream.avail_in == 0 && !s->z_eof) {
+
+            errno = 0;
+            s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
+            if (s->stream.avail_in == 0) {
+                s->z_eof = 1;
+                if (ferror(s->file)) {
+                    s->z_err = Z_ERRNO;
+                    break;
+                }
+                if (feof(s->file)) {        /* avoid error for empty file */
+                    s->z_err = Z_STREAM_END;
+                    break;
+                }
+            }
+            s->stream.next_in = s->inbuf;
+        }
+        s->in += s->stream.avail_in;
+        s->out += s->stream.avail_out;
+        s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
+        s->in -= s->stream.avail_in;
+        s->out -= s->stream.avail_out;
+
+        if (s->z_err == Z_STREAM_END) {
+            /* Check CRC and original size */
+            s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
+            start = s->stream.next_out;
+
+            if (getLong(s) != s->crc) {
+                s->z_err = Z_DATA_ERROR;
+            } else {
+                (void)getLong(s);
+                /* The uncompressed length returned by above getlong() may be
+                 * different from s->out in case of concatenated .gz files.
+                 * Check for such files:
+                 */
+                check_header(s);
+                if (s->z_err == Z_OK) {
+                    inflateReset(&(s->stream));
+                    s->crc = crc32(0L, Z_NULL, 0);
+                }
+            }
+        }
+        if (s->z_err != Z_OK || s->z_eof) break;
+    }
+    s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
+
+    return (int)(len - s->stream.avail_out);
+}
+
+
+/* ===========================================================================
+      Reads one byte from the compressed file. gzgetc returns this byte
+   or -1 in case of end of file or error.
+*/
+int ZEXPORT gzgetc(file)
+    gzFile file;
+{
+    unsigned char c;
+
+    return gzread(file, &c, 1) == 1 ? c : -1;
+}
+
+
+/* ===========================================================================
+      Push one byte back onto the stream.
+*/
+int ZEXPORT gzungetc(c, file)
+    int c;
+    gzFile file;
+{
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF;
+    s->back = c;
+    s->out--;
+    s->last = (s->z_err == Z_STREAM_END);
+    if (s->last) s->z_err = Z_OK;
+    s->z_eof = 0;
+    return c;
+}
+
+
+/* ===========================================================================
+      Reads bytes from the compressed file until len-1 characters are
+   read, or a newline character is read and transferred to buf, or an
+   end-of-file condition is encountered.  The string is then terminated
+   with a null character.
+      gzgets returns buf, or Z_NULL in case of error.
+
+      The current implementation is not optimized at all.
+*/
+char * ZEXPORT gzgets(file, buf, len)
+    gzFile file;
+    char *buf;
+    int len;
+{
+    char *b = buf;
+    if (buf == Z_NULL || len <= 0) return Z_NULL;
+
+    while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ;
+    *buf = '\0';
+    return b == buf && len > 0 ? Z_NULL : b;
+}
+
+
+#ifndef NO_GZCOMPRESS
+/* ===========================================================================
+     Writes the given number of uncompressed bytes into the compressed file.
+   gzwrite returns the number of bytes actually written (0 in case of error).
+*/
+int ZEXPORT gzwrite (file, buf, len)
+    gzFile file;
+    voidpc buf;
+    unsigned len;
+{
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
+
+    s->stream.next_in = (Bytef*)buf;
+    s->stream.avail_in = len;
+
+    while (s->stream.avail_in != 0) {
+
+        if (s->stream.avail_out == 0) {
+
+            s->stream.next_out = s->outbuf;
+            if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
+                s->z_err = Z_ERRNO;
+                break;
+            }
+            s->stream.avail_out = Z_BUFSIZE;
+        }
+        s->in += s->stream.avail_in;
+        s->out += s->stream.avail_out;
+        s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
+        s->in -= s->stream.avail_in;
+        s->out -= s->stream.avail_out;
+        if (s->z_err != Z_OK) break;
+    }
+    s->crc = crc32(s->crc, (const Bytef *)buf, len);
+
+    return (int)(len - s->stream.avail_in);
+}
+
+
+/* ===========================================================================
+     Converts, formats, and writes the args to the compressed file under
+   control of the format string, as in fprintf. gzprintf returns the number of
+   uncompressed bytes actually written (0 in case of error).
+*/
+#ifdef STDC
+#include <stdarg.h>
+
+int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...)
+{
+    char buf[Z_PRINTF_BUFSIZE];
+    va_list va;
+    int len;
+
+    buf[sizeof(buf) - 1] = 0;
+    va_start(va, format);
+#ifdef NO_vsnprintf
+#  ifdef HAS_vsprintf_void
+    (void)vsprintf(buf, format, va);
+    va_end(va);
+    for (len = 0; len < sizeof(buf); len++)
+        if (buf[len] == 0) break;
+#  else
+    len = vsprintf(buf, format, va);
+    va_end(va);
+#  endif
+#else
+#  ifdef HAS_vsnprintf_void
+    (void)vsnprintf(buf, sizeof(buf), format, va);
+    va_end(va);
+    len = strlen(buf);
+#  else
+    len = vsnprintf(buf, sizeof(buf), format, va);
+    va_end(va);
+#  endif
+#endif
+    if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0)
+        return 0;
+    return gzwrite(file, buf, (unsigned)len);
+}
+#else /* not ANSI C */
+
+int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
+                       a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
+    gzFile file;
+    const char *format;
+    int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
+        a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
+{
+    char buf[Z_PRINTF_BUFSIZE];
+    int len;
+
+    buf[sizeof(buf) - 1] = 0;
+#ifdef NO_snprintf
+#  ifdef HAS_sprintf_void
+    sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
+            a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+    for (len = 0; len < sizeof(buf); len++)
+        if (buf[len] == 0) break;
+#  else
+    len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
+                a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+#  endif
+#else
+#  ifdef HAS_snprintf_void
+    snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
+             a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+    len = strlen(buf);
+#  else
+    len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
+                 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+#  endif
+#endif
+    if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0)
+        return 0;
+    return gzwrite(file, buf, len);
+}
+#endif
+
+/* ===========================================================================
+      Writes c, converted to an unsigned char, into the compressed file.
+   gzputc returns the value that was written, or -1 in case of error.
+*/
+int ZEXPORT gzputc(file, c)
+    gzFile file;
+    int c;
+{
+    unsigned char cc = (unsigned char) c; /* required for big endian systems */
+
+    return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1;
+}
+
+
+/* ===========================================================================
+      Writes the given null-terminated string to the compressed file, excluding
+   the terminating null character.
+      gzputs returns the number of characters written, or -1 in case of error.
+*/
+int ZEXPORT gzputs(file, s)
+    gzFile file;
+    const char *s;
+{
+    return gzwrite(file, (char*)s, (unsigned)strlen(s));
+}
+
+
+/* ===========================================================================
+     Flushes all pending output into the compressed file. The parameter
+   flush is as in the deflate() function.
+*/
+local int do_flush (file, flush)
+    gzFile file;
+    int flush;
+{
+    uInt len;
+    int done = 0;
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
+
+    s->stream.avail_in = 0; /* should be zero already anyway */
+
+    for (;;) {
+        len = Z_BUFSIZE - s->stream.avail_out;
+
+        if (len != 0) {
+            if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
+                s->z_err = Z_ERRNO;
+                return Z_ERRNO;
+            }
+            s->stream.next_out = s->outbuf;
+            s->stream.avail_out = Z_BUFSIZE;
+        }
+        if (done) break;
+        s->out += s->stream.avail_out;
+        s->z_err = deflate(&(s->stream), flush);
+        s->out -= s->stream.avail_out;
+
+        /* Ignore the second of two consecutive flushes: */
+        if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
+
+        /* deflate has finished flushing only when it hasn't used up
+         * all the available space in the output buffer:
+         */
+        done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
+
+        if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
+    }
+    return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
+}
+
+int ZEXPORT gzflush (file, flush)
+     gzFile file;
+     int flush;
+{
+    gz_stream *s = (gz_stream*)file;
+    int err = do_flush (file, flush);
+
+    if (err) return err;
+    fflush(s->file);
+    return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
+}
+#endif /* NO_GZCOMPRESS */
+
+/* ===========================================================================
+      Sets the starting position for the next gzread or gzwrite on the given
+   compressed file. The offset represents a number of bytes in the
+      gzseek returns the resulting offset location as measured in bytes from
+   the beginning of the uncompressed stream, or -1 in case of error.
+      SEEK_END is not implemented, returns error.
+      In this version of the library, gzseek can be extremely slow.
+*/
+z_off_t ZEXPORT gzseek (file, offset, whence)
+    gzFile file;
+    z_off_t offset;
+    int whence;
+{
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL || whence == SEEK_END ||
+        s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) {
+        return -1L;
+    }
+
+    if (s->mode == 'w') {
+#ifdef NO_GZCOMPRESS
+        return -1L;
+#else
+        if (whence == SEEK_SET) {
+            offset -= s->in;
+        }
+        if (offset < 0) return -1L;
+
+        /* At this point, offset is the number of zero bytes to write. */
+        if (s->inbuf == Z_NULL) {
+            s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */
+            if (s->inbuf == Z_NULL) return -1L;
+            zmemzero(s->inbuf, Z_BUFSIZE);
+        }
+        while (offset > 0)  {
+            uInt size = Z_BUFSIZE;
+            if (offset < Z_BUFSIZE) size = (uInt)offset;
+
+            size = gzwrite(file, s->inbuf, size);
+            if (size == 0) return -1L;
+
+            offset -= size;
+        }
+        return s->in;
+#endif
+    }
+    /* Rest of function is for reading only */
+
+    /* compute absolute position */
+    if (whence == SEEK_CUR) {
+        offset += s->out;
+    }
+    if (offset < 0) return -1L;
+
+    if (s->transparent) {
+        /* map to fseek */
+        s->back = EOF;
+        s->stream.avail_in = 0;
+        s->stream.next_in = s->inbuf;
+        if (fseek(s->file, offset, SEEK_SET) < 0) return -1L;
+
+        s->in = s->out = offset;
+        return offset;
+    }
+
+    /* For a negative seek, rewind and use positive seek */
+    if (offset >= s->out) {
+        offset -= s->out;
+    } else if (gzrewind(file) < 0) {
+        return -1L;
+    }
+    /* offset is now the number of bytes to skip. */
+
+    if (offset != 0 && s->outbuf == Z_NULL) {
+        s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
+        if (s->outbuf == Z_NULL) return -1L;
+    }
+    if (offset && s->back != EOF) {
+        s->back = EOF;
+        s->out++;
+        offset--;
+        if (s->last) s->z_err = Z_STREAM_END;
+    }
+    while (offset > 0)  {
+        int size = Z_BUFSIZE;
+        if (offset < Z_BUFSIZE) size = (int)offset;
+
+        size = gzread(file, s->outbuf, (uInt)size);
+        if (size <= 0) return -1L;
+        offset -= size;
+    }
+    return s->out;
+}
+
+/* ===========================================================================
+     Rewinds input file.
+*/
+int ZEXPORT gzrewind (file)
+    gzFile file;
+{
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL || s->mode != 'r') return -1;
+
+    s->z_err = Z_OK;
+    s->z_eof = 0;
+    s->back = EOF;
+    s->stream.avail_in = 0;
+    s->stream.next_in = s->inbuf;
+    s->crc = crc32(0L, Z_NULL, 0);
+    if (!s->transparent) (void)inflateReset(&s->stream);
+    s->in = 0;
+    s->out = 0;
+    return fseek(s->file, s->start, SEEK_SET);
+}
+
+/* ===========================================================================
+     Returns the starting position for the next gzread or gzwrite on the
+   given compressed file. This position represents a number of bytes in the
+   uncompressed data stream.
+*/
+z_off_t ZEXPORT gztell (file)
+    gzFile file;
+{
+    return gzseek(file, 0L, SEEK_CUR);
+}
+
+/* ===========================================================================
+     Returns 1 when EOF has previously been detected reading the given
+   input stream, otherwise zero.
+*/
+int ZEXPORT gzeof (file)
+    gzFile file;
+{
+    gz_stream *s = (gz_stream*)file;
+
+    /* With concatenated compressed files that can have embedded
+     * crc trailers, z_eof is no longer the only/best indicator of EOF
+     * on a gz_stream. Handle end-of-stream error explicitly here.
+     */
+    if (s == NULL || s->mode != 'r') return 0;
+    if (s->z_eof) return 1;
+    return s->z_err == Z_STREAM_END;
+}
+
+/* ===========================================================================
+   Outputs a long in LSB order to the given file
+*/
+local void putLong (file, x)
+    FILE *file;
+    uLong x;
+{
+    int n;
+    for (n = 0; n < 4; n++) {
+        fputc((int)(x & 0xff), file);
+        x >>= 8;
+    }
+}
+
+/* ===========================================================================
+   Reads a long in LSB order from the given gz_stream. Sets z_err in case
+   of error.
+*/
+local uLong getLong (s)
+    gz_stream *s;
+{
+    uLong x = (uLong)get_byte(s);
+    int c;
+
+    x += ((uLong)get_byte(s))<<8;
+    x += ((uLong)get_byte(s))<<16;
+    c = get_byte(s);
+    if (c == EOF) s->z_err = Z_DATA_ERROR;
+    x += ((uLong)c)<<24;
+    return x;
+}
+
+/* ===========================================================================
+     Flushes all pending output if necessary, closes the compressed file
+   and deallocates all the (de)compression state.
+*/
+int ZEXPORT gzclose (file)
+    gzFile file;
+{
+    int err;
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL) return Z_STREAM_ERROR;
+
+    if (s->mode == 'w') {
+#ifdef NO_GZCOMPRESS
+        return Z_STREAM_ERROR;
+#else
+        err = do_flush (file, Z_FINISH);
+        if (err != Z_OK) return destroy((gz_stream*)file);
+
+        putLong (s->file, s->crc);
+        putLong (s->file, (uLong)(s->in & 0xffffffff));
+#endif
+    }
+    return destroy((gz_stream*)file);
+}
+
+/* ===========================================================================
+     Returns the error message for the last error which occured on the
+   given compressed file. errnum is set to zlib error number. If an
+   error occured in the file system and not in the compression library,
+   errnum is set to Z_ERRNO and the application may consult errno
+   to get the exact error code.
+*/
+const char * ZEXPORT gzerror (file, errnum)
+    gzFile file;
+    int *errnum;
+{
+    char *m;
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL) {
+        *errnum = Z_STREAM_ERROR;
+        return (const char*)ERR_MSG(Z_STREAM_ERROR);
+    }
+    *errnum = s->z_err;
+    if (*errnum == Z_OK) return (const char*)"";
+
+    m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
+
+    if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err);
+
+    TRYFREE(s->msg);
+    s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
+    if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR);
+    strcpy(s->msg, s->path);
+    strcat(s->msg, ": ");
+    strcat(s->msg, m);
+    return (const char*)s->msg;
+}
+
+/* ===========================================================================
+     Clear the error and end-of-file flags, and do the same for the real file.
+*/
+void ZEXPORT gzclearerr (file)
+    gzFile file;
+{
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL) return;
+    if (s->z_err != Z_STREAM_END) s->z_err = Z_OK;
+    s->z_eof = 0;
+    clearerr(s->file);
+}
diff --git a/ext/Compress/Zlib/zlib-src-1.2.2/infback.c b/ext/Compress/Zlib/zlib-src-1.2.2/infback.c
new file mode 100644 (file)
index 0000000..262f97c
--- /dev/null
@@ -0,0 +1,622 @@
+/* infback.c -- inflate using a call-back interface
+ * Copyright (C) 1995-2003 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+   This code is largely copied from inflate.c.  Normally either infback.o or
+   inflate.o would be linked into an application--not both.  The interface
+   with inffast.c is retained so that optimized assembler-coded versions of
+   inflate_fast() can be used with either inflate.c or infback.c.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+/* function prototypes */
+local void fixedtables OF((struct inflate_state FAR *state));
+
+/*
+   strm provides memory allocation functions in zalloc and zfree, or
+   Z_NULL to use the library memory allocation functions.
+
+   windowBits is in the range 8..15, and window is a user-supplied
+   window and output buffer that is 2**windowBits bytes.
+ */
+int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
+z_stream FAR *strm;
+int windowBits;
+unsigned char FAR *window;
+const char *version;
+int stream_size;
+{
+    struct inflate_state FAR *state;
+
+    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+        stream_size != (int)(sizeof(z_stream)))
+        return Z_VERSION_ERROR;
+    if (strm == Z_NULL || window == Z_NULL ||
+        windowBits < 8 || windowBits > 15)
+        return Z_STREAM_ERROR;
+    strm->msg = Z_NULL;                 /* in case we return an error */
+    if (strm->zalloc == (alloc_func)0) {
+        strm->zalloc = zcalloc;
+        strm->opaque = (voidpf)0;
+    }
+    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+    state = (struct inflate_state FAR *)ZALLOC(strm, 1,
+                                               sizeof(struct inflate_state));
+    if (state == Z_NULL) return Z_MEM_ERROR;
+    Tracev((stderr, "inflate: allocated\n"));
+    strm->state = (voidpf)state;
+    state->wbits = windowBits;
+    state->wsize = 1U << windowBits;
+    state->window = window;
+    state->write = 0;
+    state->whave = 0;
+    return Z_OK;
+}
+
+/*
+   Return state with length and distance decoding tables and index sizes set to
+   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
+   If BUILDFIXED is defined, then instead this routine builds the tables the
+   first time it's called, and returns those tables the first time and
+   thereafter.  This reduces the size of the code by about 2K bytes, in
+   exchange for a little execution time.  However, BUILDFIXED should not be
+   used for threaded applications, since the rewriting of the tables and virgin
+   may not be thread-safe.
+ */
+local void fixedtables(state)
+struct inflate_state FAR *state;
+{
+#ifdef BUILDFIXED
+    static int virgin = 1;
+    static code *lenfix, *distfix;
+    static code fixed[544];
+
+    /* build fixed huffman tables if first call (may not be thread safe) */
+    if (virgin) {
+        unsigned sym, bits;
+        static code *next;
+
+        /* literal/length table */
+        sym = 0;
+        while (sym < 144) state->lens[sym++] = 8;
+        while (sym < 256) state->lens[sym++] = 9;
+        while (sym < 280) state->lens[sym++] = 7;
+        while (sym < 288) state->lens[sym++] = 8;
+        next = fixed;
+        lenfix = next;
+        bits = 9;
+        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+        /* distance table */
+        sym = 0;
+        while (sym < 32) state->lens[sym++] = 5;
+        distfix = next;
+        bits = 5;
+        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+        /* do this just once */
+        virgin = 0;
+    }
+#else /* !BUILDFIXED */
+#   include "inffixed.h"
+#endif /* BUILDFIXED */
+    state->lencode = lenfix;
+    state->lenbits = 9;
+    state->distcode = distfix;
+    state->distbits = 5;
+}
+
+/* Macros for inflateBack(): */
+
+/* Load returned state from inflate_fast() */
+#define LOAD() \
+    do { \
+        put = strm->next_out; \
+        left = strm->avail_out; \
+        next = strm->next_in; \
+        have = strm->avail_in; \
+        hold = state->hold; \
+        bits = state->bits; \
+    } while (0)
+
+/* Set state from registers for inflate_fast() */
+#define RESTORE() \
+    do { \
+        strm->next_out = put; \
+        strm->avail_out = left; \
+        strm->next_in = next; \
+        strm->avail_in = have; \
+        state->hold = hold; \
+        state->bits = bits; \
+    } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+    do { \
+        hold = 0; \
+        bits = 0; \
+    } while (0)
+
+/* Assure that some input is available.  If input is requested, but denied,
+   then return a Z_BUF_ERROR from inflateBack(). */
+#define PULL() \
+    do { \
+        if (have == 0) { \
+            have = in(in_desc, &next); \
+            if (have == 0) { \
+                next = Z_NULL; \
+                ret = Z_BUF_ERROR; \
+                goto inf_leave; \
+            } \
+        } \
+    } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflateBack()
+   with an error if there is no input available. */
+#define PULLBYTE() \
+    do { \
+        PULL(); \
+        have--; \
+        hold += (unsigned long)(*next++) << bits; \
+        bits += 8; \
+    } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator.  If there is
+   not enough available input to do that, then return from inflateBack() with
+   an error. */
+#define NEEDBITS(n) \
+    do { \
+        while (bits < (unsigned)(n)) \
+            PULLBYTE(); \
+    } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+    ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+    do { \
+        hold >>= (n); \
+        bits -= (unsigned)(n); \
+    } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+    do { \
+        hold >>= bits & 7; \
+        bits -= bits & 7; \
+    } while (0)
+
+/* Assure that some output space is available, by writing out the window
+   if it's full.  If the write fails, return from inflateBack() with a
+   Z_BUF_ERROR. */
+#define ROOM() \
+    do { \
+        if (left == 0) { \
+            put = state->window; \
+            left = state->wsize; \
+            state->whave = left; \
+            if (out(out_desc, put, left)) { \
+                ret = Z_BUF_ERROR; \
+                goto inf_leave; \
+            } \
+        } \
+    } while (0)
+
+/*
+   strm provides the memory allocation functions and window buffer on input,
+   and provides information on the unused input on return.  For Z_DATA_ERROR
+   returns, strm will also provide an error message.
+
+   in() and out() are the call-back input and output functions.  When
+   inflateBack() needs more input, it calls in().  When inflateBack() has
+   filled the window with output, or when it completes with data in the
+   window, it calls out() to write out the data.  The application must not
+   change the provided input until in() is called again or inflateBack()
+   returns.  The application must not change the window/output buffer until
+   inflateBack() returns.
+
+   in() and out() are called with a descriptor parameter provided in the
+   inflateBack() call.  This parameter can be a structure that provides the
+   information required to do the read or write, as well as accumulated
+   information on the input and output such as totals and check values.
+
+   in() should return zero on failure.  out() should return non-zero on
+   failure.  If either in() or out() fails, than inflateBack() returns a
+   Z_BUF_ERROR.  strm->next_in can be checked for Z_NULL to see whether it
+   was in() or out() that caused in the error.  Otherwise,  inflateBack()
+   returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
+   error, or Z_MEM_ERROR if it could not allocate memory for the state.
+   inflateBack() can also return Z_STREAM_ERROR if the input parameters
+   are not correct, i.e. strm is Z_NULL or the state was not initialized.
+ */
+int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
+z_stream FAR *strm;
+in_func in;
+void FAR *in_desc;
+out_func out;
+void FAR *out_desc;
+{
+    struct inflate_state FAR *state;
+    unsigned char FAR *next;    /* next input */
+    unsigned char FAR *put;     /* next output */
+    unsigned have, left;        /* available input and output */
+    unsigned long hold;         /* bit buffer */
+    unsigned bits;              /* bits in bit buffer */
+    unsigned copy;              /* number of stored or match bytes to copy */
+    unsigned char FAR *from;    /* where to copy match bytes from */
+    code this;                  /* current decoding table entry */
+    code last;                  /* parent table entry */
+    unsigned len;               /* length to copy for repeats, bits to drop */
+    int ret;                    /* return code */
+    static const unsigned short order[19] = /* permutation of code lengths */
+        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+    /* Check that the strm exists and that the state was initialized */
+    if (strm == Z_NULL || strm->state == Z_NULL)
+        return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* Reset the state */
+    strm->msg = Z_NULL;
+    state->mode = TYPE;
+    state->last = 0;
+    state->whave = 0;
+    next = strm->next_in;
+    have = next != Z_NULL ? strm->avail_in : 0;
+    hold = 0;
+    bits = 0;
+    put = state->window;
+    left = state->wsize;
+
+    /* Inflate until end of block marked as last */
+    for (;;)
+        switch (state->mode) {
+        case TYPE:
+            /* determine and dispatch block type */
+            if (state->last) {
+                BYTEBITS();
+                state->mode = DONE;
+                break;
+            }
+            NEEDBITS(3);
+            state->last = BITS(1);
+            DROPBITS(1);
+            switch (BITS(2)) {
+            case 0:                             /* stored block */
+                Tracev((stderr, "inflate:     stored block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = STORED;
+                break;
+            case 1:                             /* fixed block */
+                fixedtables(state);
+                Tracev((stderr, "inflate:     fixed codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = LEN;              /* decode codes */
+                break;
+            case 2:                             /* dynamic block */
+                Tracev((stderr, "inflate:     dynamic codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = TABLE;
+                break;
+            case 3:
+                strm->msg = (char *)"invalid block type";
+                state->mode = BAD;
+            }
+            DROPBITS(2);
+            break;
+
+        case STORED:
+            /* get and verify stored block length */
+            BYTEBITS();                         /* go to byte boundary */
+            NEEDBITS(32);
+            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+                strm->msg = (char *)"invalid stored block lengths";
+                state->mode = BAD;
+                break;
+            }
+            state->length = (unsigned)hold & 0xffff;
+            Tracev((stderr, "inflate:       stored length %u\n",
+                    state->length));
+            INITBITS();
+
+            /* copy stored block from input to output */
+            while (state->length != 0) {
+                copy = state->length;
+                PULL();
+                ROOM();
+                if (copy > have) copy = have;
+                if (copy > left) copy = left;
+                zmemcpy(put, next, copy);
+                have -= copy;
+                next += copy;
+                left -= copy;
+                put += copy;
+                state->length -= copy;
+            }
+            Tracev((stderr, "inflate:       stored end\n"));
+            state->mode = TYPE;
+            break;
+
+        case TABLE:
+            /* get dynamic table entries descriptor */
+            NEEDBITS(14);
+            state->nlen = BITS(5) + 257;
+            DROPBITS(5);
+            state->ndist = BITS(5) + 1;
+            DROPBITS(5);
+            state->ncode = BITS(4) + 4;
+            DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+            if (state->nlen > 286 || state->ndist > 30) {
+                strm->msg = (char *)"too many length or distance symbols";
+                state->mode = BAD;
+                break;
+            }
+#endif
+            Tracev((stderr, "inflate:       table sizes ok\n"));
+
+            /* get code length code lengths (not a typo) */
+            state->have = 0;
+            while (state->have < state->ncode) {
+                NEEDBITS(3);
+                state->lens[order[state->have++]] = (unsigned short)BITS(3);
+                DROPBITS(3);
+            }
+            while (state->have < 19)
+                state->lens[order[state->have++]] = 0;
+            state->next = state->codes;
+            state->lencode = (code const FAR *)(state->next);
+            state->lenbits = 7;
+            ret = inflate_table(CODES, state->lens, 19, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid code lengths set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       code lengths ok\n"));
+
+            /* get length and distance code code lengths */
+            state->have = 0;
+            while (state->have < state->nlen + state->ndist) {
+                for (;;) {
+                    this = state->lencode[BITS(state->lenbits)];
+                    if ((unsigned)(this.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                if (this.val < 16) {
+                    NEEDBITS(this.bits);
+                    DROPBITS(this.bits);
+                    state->lens[state->have++] = this.val;
+                }
+                else {
+                    if (this.val == 16) {
+                        NEEDBITS(this.bits + 2);
+                        DROPBITS(this.bits);
+                        if (state->have == 0) {
+                            strm->msg = (char *)"invalid bit length repeat";
+                            state->mode = BAD;
+                            break;
+                        }
+                        len = (unsigned)(state->lens[state->have - 1]);
+                        copy = 3 + BITS(2);
+                        DROPBITS(2);
+                    }
+                    else if (this.val == 17) {
+                        NEEDBITS(this.bits + 3);
+                        DROPBITS(this.bits);
+                        len = 0;
+                        copy = 3 + BITS(3);
+                        DROPBITS(3);
+                    }
+                    else {
+                        NEEDBITS(this.bits + 7);
+                        DROPBITS(this.bits);
+                        len = 0;
+                        copy = 11 + BITS(7);
+                        DROPBITS(7);
+                    }
+                    if (state->have + copy > state->nlen + state->ndist) {
+                        strm->msg = (char *)"invalid bit length repeat";
+                        state->mode = BAD;
+                        break;
+                    }
+                    while (copy--)
+                        state->lens[state->have++] = (unsigned short)len;
+                }
+            }
+
+            /* handle error breaks in while */
+            if (state->mode == BAD) break;
+
+            /* build code tables */
+            state->next = state->codes;
+            state->lencode = (code const FAR *)(state->next);
+            state->lenbits = 9;
+            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid literal/lengths set";
+                state->mode = BAD;
+                break;
+            }
+            state->distcode = (code const FAR *)(state->next);
+            state->distbits = 6;
+            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+                            &(state->next), &(state->distbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid distances set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       codes ok\n"));
+            state->mode = LEN;
+
+        case LEN:
+            /* use inflate_fast() if we have enough input and output */
+            if (have >= 6 && left >= 258) {
+                RESTORE();
+                if (state->whave < state->wsize)
+                    state->whave = state->wsize - left;
+                inflate_fast(strm, state->wsize);
+                LOAD();
+                break;
+            }
+
+            /* get a literal, length, or end-of-block code */
+            for (;;) {
+                this = state->lencode[BITS(state->lenbits)];
+                if ((unsigned)(this.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if (this.op && (this.op & 0xf0) == 0) {
+                last = this;
+                for (;;) {
+                    this = state->lencode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + this.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+            }
+            DROPBITS(this.bits);
+            state->length = (unsigned)this.val;
+
+            /* process literal */
+            if (this.op == 0) {
+                Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+                        "inflate:         literal '%c'\n" :
+                        "inflate:         literal 0x%02x\n", this.val));
+                ROOM();
+                *put++ = (unsigned char)(state->length);
+                left--;
+                state->mode = LEN;
+                break;
+            }
+
+            /* process end of block */
+            if (this.op & 32) {
+                Tracevv((stderr, "inflate:         end of block\n"));
+                state->mode = TYPE;
+                break;
+            }
+
+            /* invalid code */
+            if (this.op & 64) {
+                strm->msg = (char *)"invalid literal/length code";
+                state->mode = BAD;
+                break;
+            }
+
+            /* length code -- get extra bits, if any */
+            state->extra = (unsigned)(this.op) & 15;
+            if (state->extra != 0) {
+                NEEDBITS(state->extra);
+                state->length += BITS(state->extra);
+                DROPBITS(state->extra);
+            }
+            Tracevv((stderr, "inflate:         length %u\n", state->length));
+
+            /* get distance code */
+            for (;;) {
+                this = state->distcode[BITS(state->distbits)];
+                if ((unsigned)(this.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if ((this.op & 0xf0) == 0) {
+                last = this;
+                for (;;) {
+                    this = state->distcode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + this.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+            }
+            DROPBITS(this.bits);
+            if (this.op & 64) {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
+                break;
+            }
+            state->offset = (unsigned)this.val;
+
+            /* get distance extra bits, if any */
+            state->extra = (unsigned)(this.op) & 15;
+            if (state->extra != 0) {
+                NEEDBITS(state->extra);
+                state->offset += BITS(state->extra);
+                DROPBITS(state->extra);
+            }
+            if (state->offset > state->wsize - (state->whave < state->wsize ?
+                                                left : 0)) {
+                strm->msg = (char *)"invalid distance too far back";
+                state->mode = BAD;
+                break;
+            }
+            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
+
+            /* copy match from window to output */
+            do {
+                ROOM();
+                copy = state->wsize - state->offset;
+                if (copy < left) {
+                    from = put + copy;
+                    copy = left - copy;
+                }
+                else {
+       &