Compare commits

..

4 Commits

Author SHA1 Message Date
Mark Adler
9c3a583021 zlib 1.2.2.4 2011-09-09 23:24:52 -07:00
Mark Adler
6b8233bfe0 zlib 1.2.2.3 2011-09-09 23:24:43 -07:00
Mark Adler
0484693e17 zlib 1.2.2.2 2011-09-09 23:24:33 -07:00
Mark Adler
9811b53dd9 zlib 1.2.2.1 2011-09-09 23:24:24 -07:00
93 changed files with 16023 additions and 9509 deletions

View File

@@ -1,6 +1,92 @@
ChangeLog file for zlib ChangeLog file for zlib
Changes in 1.2.2.4 (11 July 2005)
- Add inflatePrime() function for starting inflation at bit boundary
- Avoid some Visual C warnings in deflate.c
- Avoid more silly Visual C warnings in inflate.c and inftrees.c for 64-bit
compile
- Fix some spelling errors in comments [Betts]
- Correct inflateInit2() error return documentation in zlib.h
- Added zran.c example of compressed data random access to examples
directory, shows use of inflatePrime()
- Fix cast for assignments to strm->state in inflate.c and infback.c
- Fix zlibCompileFlags() in zutil.c to use 1L for long shifts [Oberhumer]
- Move declarations of gf2 functions to right place in crc32.c [Oberhumer]
- Add cast in trees.c t avoid a warning [Oberhumer]
- Avoid some warnings in fitblk.c, gun.c, gzjoin.c in examples [Oberhumer]
- Update make_vms.com [Zinser]
- Initialize state->write in inflateReset() since copied in inflate_fast()
- Be more strict on incomplete code sets in inflate_table() and increase
ENOUGH and MAXD -- this repairs a possible security vulnerability for
invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for
discovering the vulnerability and providing test cases.
- Add ia64 support to configure for HP-UX [Smith]
- Add error return to gzread() for format or i/o error [Levin]
- Use malloc.h for OS/2 [Necasek]
Changes in 1.2.2.3 (27 May 2005)
- Replace 1U constants in inflate.c and inftrees.c for 64-bit compile
- Typecast fread() return values in gzio.c [Vollant]
- Remove trailing space in minigzip.c outmode (VC++ can't deal with it)
- Fix crc check bug in gzread() after gzungetc() [Heiner]
- Add the deflateTune() function to adjust internal compression parameters
- Add a fast gzip decompressor, gun.c, to examples (use of inflateBack)
- Remove an incorrect assertion in examples/zpipe.c
- Add C++ wrapper in infback9.h [Donais]
- Fix bug in inflateCopy() when decoding fixed codes
- Note in zlib.h how much deflateSetDictionary() actually uses
- Remove USE_DICT_HEAD in deflate.c (would mess up inflate if used)
- Add _WIN32_WCE to define WIN32 in zconf.in.h [Spencer]
- Don't include stderr.h or errno.h for _WIN32_WCE in zutil.h [Spencer]
- Add gzdirect() function to indicate transparent reads
- Update contrib/minizip [Vollant]
- Fix compilation of deflate.c when both ASMV and FASTEST [Oberhumer]
- Add casts in crc32.c to avoid warnings [Oberhumer]
- Add contrib/masmx64 [Vollant]
- Update contrib/asm586, asm686, masmx86, testzlib, vstudio [Vollant]
Changes in 1.2.2.2 (30 December 2004)
- Replace structure assignments in deflate.c and inflate.c with zmemcpy to
avoid implicit memcpy calls (portability for no-library compilation)
- Increase sprintf() buffer size in gzdopen() to allow for large numbers
- Add INFLATE_STRICT to check distances against zlib header
- Improve WinCE errno handling and comments [Chang]
- Remove comment about no gzip header processing in FAQ
- Add Z_FIXED strategy option to deflateInit2() to force fixed trees
- Add updated make_vms.com [Coghlan], update README
- Create a new "examples" directory, move gzappend.c there, add zpipe.c,
fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html.
- Add FAQ entry and comments in deflate.c on uninitialized memory access
- Add Solaris 9 make options in configure [Gilbert]
- Allow strerror() usage in gzio.c for STDC
- Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer]
- Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant]
- Use z_off_t for adler32_combine() and crc32_combine() lengths
- Make adler32() much faster for small len
- Use OS_CODE in deflate() default gzip header
Changes in 1.2.2.1 (31 October 2004)
- Allow inflateSetDictionary() call for raw inflate
- Fix inflate header crc check bug for file names and comments
- Add deflateSetHeader() and gz_header structure for custom gzip headers
- Add inflateGetheader() to retrieve gzip headers
- Add crc32_combine() and adler32_combine() functions
- Add alloc_func, free_func, in_func, out_func to Z_PREFIX list
- Use zstreamp consistently in zlib.h (inflate_back functions)
- Remove GUNZIP condition from definition of inflate_mode in inflate.h
and in contrib/inflate86/inffast.S [Truta, Anderson]
- Add support for AMD64 in contrib/inflate86/inffas86.c [Anderson]
- Update projects/README.projects and projects/visualc6 [Truta]
- Update win32/DLL_FAQ.txt [Truta]
- Avoid warning under NO_GZCOMPRESS in gzio.c; fix typo [Truta]
- Deprecate Z_ASCII; use Z_TEXT instead [Truta]
- Use a new algorithm for setting strm->data_type in trees.c [Truta]
- Do not define an exit() prototype in zutil.c unless DEBUG defined
- Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta]
- Add comment in zlib.h for Z_NO_FLUSH parameter to deflate()
- Fix Darwin build version identification [Peterson]
Changes in 1.2.2 (3 October 2004) Changes in 1.2.2 (3 October 2004)
- Update zlib.h comments on gzip in-memory processing - Update zlib.h comments on gzip in-memory processing
- Set adler to 1 in inflateReset() to support Java test suite [Walles] - Set adler to 1 in inflateReset() to support Java test suite [Walles]
@@ -449,7 +535,7 @@ Changes in 1.0.7 (20 Jan 1998)
Changes in 1.0.6 (19 Jan 1998) Changes in 1.0.6 (19 Jan 1998)
- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and - add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and
gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code)
- Fix a deflate bug occuring only with compression level 0 (thanks to - Fix a deflate bug occurring only with compression level 0 (thanks to
Andy Buckler for finding this one). Andy Buckler for finding this one).
- In minigzip, pass transparently also the first byte for .Z files. - In minigzip, pass transparently also the first byte for .Z files.
- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() - return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress()

26
FAQ
View File

@@ -148,13 +148,6 @@ The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html
format using deflateInit2(). You can also request that inflate decode format using deflateInit2(). You can also request that inflate decode
the gzip format using inflateInit2(). Read zlib.h for more details. the gzip format using inflateInit2(). Read zlib.h for more details.
Note that you cannot specify special gzip header contents (e.g. a file
name or modification date), nor will inflate tell you what was in the
gzip header. If you need to customize the header or see what's in it,
you can use the raw deflate and inflate operations and the crc32()
function and roll your own gzip encoding and decoding. Read the gzip
RFC 1952 for details of the header and trailer format.
21. Is zlib thread-safe? 21. Is zlib thread-safe?
Yes. However any library routines that zlib uses and any application- Yes. However any library routines that zlib uses and any application-
@@ -295,20 +288,29 @@ The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html
were downright silly. So now, we simply make sure that the code always were downright silly. So now, we simply make sure that the code always
works. works.
36. Will zlib read the (insert any ancient or arcane format here) compressed 36. Valgrind (or some similar memory access checker) says that deflate is
performing a conditional jump that depends on an uninitialized value.
Isn't that a bug?
No. That is intentional for performance reasons, and the output of
deflate is not affected. This only started showing up recently since
zlib 1.2.x uses malloc() by default for allocations, whereas earlier
versions used calloc(), which zeros out the allocated memory.
37. Will zlib read the (insert any ancient or arcane format here) compressed
data format? data format?
Probably not. Look in the comp.compression FAQ for pointers to various Probably not. Look in the comp.compression FAQ for pointers to various
formats and associated software. formats and associated software.
37. How can I encrypt/decrypt zip files with zlib? 38. How can I encrypt/decrypt zip files with zlib?
zlib doesn't support encryption. The original PKZIP encryption is very weak zlib doesn't support encryption. The original PKZIP encryption is very weak
and can be broken with freely available programs. To get strong encryption, and can be broken with freely available programs. To get strong encryption,
use GnuPG, http://www.gnupg.org/ , which already includes zlib compression. use GnuPG, http://www.gnupg.org/ , which already includes zlib compression.
For PKZIP compatible "encryption", look at http://www.info-zip.org/ For PKZIP compatible "encryption", look at http://www.info-zip.org/
38. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings? 39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
"gzip" is the gzip format, and "deflate" is the zlib format. They should "gzip" is the gzip format, and "deflate" is the zlib format. They should
probably have called the second one "zlib" instead to avoid confusion probably have called the second one "zlib" instead to avoid confusion
@@ -324,14 +326,14 @@ The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html
Bottom line: use the gzip format for HTTP 1.1 encoding. Bottom line: use the gzip format for HTTP 1.1 encoding.
39. Does zlib support the new "Deflate64" format introduced by PKWare? 40. Does zlib support the new "Deflate64" format introduced by PKWare?
No. PKWare has apparently decided to keep that format proprietary, since No. PKWare has apparently decided to keep that format proprietary, since
they have not documented it as they have previous compression formats. they have not documented it as they have previous compression formats.
In any case, the compression improvements are so modest compared to other In any case, the compression improvements are so modest compared to other
more modern approaches, that it's not worth the effort to implement. more modern approaches, that it's not worth the effort to implement.
40. Can you please sign these lengthy legal documents and fax them back to us 41. Can you please sign these lengthy legal documents and fax them back to us
so that we can use your software in our product? so that we can use your software in our product?
No. Go away. Shoo. No. Go away. Shoo.

View File

@@ -1,5 +1,5 @@
# Makefile for zlib # Makefile for zlib
# Copyright (C) 1995-2003 Jean-loup Gailly. # Copyright (C) 1995-2005 Jean-loup Gailly.
# For conditions of distribution and use, see copyright notice in zlib.h # For conditions of distribution and use, see copyright notice in zlib.h
# To compile and test, type: # To compile and test, type:
@@ -30,7 +30,7 @@ CPP=$(CC) -E
LIBS=libz.a LIBS=libz.a
SHAREDLIB=libz.so SHAREDLIB=libz.so
SHAREDLIBV=libz.so.1.2.2 SHAREDLIBV=libz.so.1.2.2.4
SHAREDLIBM=libz.so.1 SHAREDLIBM=libz.so.1
AR=ar rc AR=ar rc

View File

@@ -1,5 +1,5 @@
# Makefile for zlib # Makefile for zlib
# Copyright (C) 1995-2003 Jean-loup Gailly. # Copyright (C) 1995-2005 Jean-loup Gailly.
# For conditions of distribution and use, see copyright notice in zlib.h # For conditions of distribution and use, see copyright notice in zlib.h
# To compile and test, type: # To compile and test, type:
@@ -30,7 +30,7 @@ CPP=$(CC) -E
LIBS=libz.a LIBS=libz.a
SHAREDLIB=libz.so SHAREDLIB=libz.so
SHAREDLIBV=libz.so.1.2.2 SHAREDLIBV=libz.so.1.2.2.4
SHAREDLIBM=libz.so.1 SHAREDLIBM=libz.so.1
AR=ar rc AR=ar rc

9
README
View File

@@ -1,6 +1,6 @@
ZLIB DATA COMPRESSION LIBRARY ZLIB DATA COMPRESSION LIBRARY
zlib 1.2.2 is a general purpose data compression library. All the code is zlib 1.2.2.4 is a general purpose data compression library. All the code is
thread safe. The data format used by the zlib library is described by RFCs thread safe. The data format used by the zlib library is described by RFCs
(Request for Comments) 1950 to 1952 in the files (Request for Comments) 1950 to 1952 in the files
http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
@@ -16,9 +16,8 @@ minigzip.c.
To compile all files and run the test program, follow the instructions given at To compile all files and run the test program, follow the instructions given at
the top of Makefile. In short "make test; make install" should work for most the top of Makefile. In short "make test; make install" should work for most
machines. For Unix: "./configure; make test; make install" For MSDOS, use one machines. For Unix: "./configure; make test; make install". For MSDOS, use one
of the special makefiles such as Makefile.msc. For VMS, use Make_vms.com or of the special makefiles such as Makefile.msc. For VMS, use make_vms.com.
descrip.mms.
Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant
<info@winimage.com> for the Windows DLL version. The zlib home page is <info@winimage.com> for the Windows DLL version. The zlib home page is
@@ -34,7 +33,7 @@ Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
issue of Dr. Dobb's Journal; a copy of the article is available in issue of Dr. Dobb's Journal; a copy of the article is available in
http://dogma.net/markn/articles/zlibtool/zlibtool.htm http://dogma.net/markn/articles/zlibtool/zlibtool.htm
The changes made in version 1.2.2 are documented in the file ChangeLog. The changes made in version 1.2.2.4 are documented in the file ChangeLog.
Unsupported third party contributions are provided in directory "contrib". Unsupported third party contributions are provided in directory "contrib".

111
adler32.c
View File

@@ -1,5 +1,5 @@
/* adler32.c -- compute the Adler-32 checksum of a data stream /* adler32.c -- compute the Adler-32 checksum of a data stream
* Copyright (C) 1995-2003 Mark Adler * Copyright (C) 1995-2004 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@@ -12,12 +12,13 @@
#define NMAX 5552 #define NMAX 5552
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ /* 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 DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
#define DO16(buf) DO8(buf,0); DO8(buf,8); #define DO16(buf) DO8(buf,0); DO8(buf,8);
/* use NO_DIVIDE if your processor does not do division in hardware */
#ifdef NO_DIVIDE #ifdef NO_DIVIDE
# define MOD(a) \ # define MOD(a) \
do { \ do { \
@@ -39,8 +40,17 @@
if (a >= (BASE << 1)) a -= (BASE << 1); \ if (a >= (BASE << 1)) a -= (BASE << 1); \
if (a >= BASE) a -= BASE; \ if (a >= BASE) a -= BASE; \
} while (0) } while (0)
# define MOD4(a) \
do { \
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 #else
# define MOD(a) a %= BASE # define MOD(a) a %= BASE
# define MOD4(a) a %= BASE
#endif #endif
/* ========================================================================= */ /* ========================================================================= */
@@ -49,26 +59,91 @@ uLong ZEXPORT adler32(adler, buf, len)
const Bytef *buf; const Bytef *buf;
uInt len; uInt len;
{ {
unsigned long s1 = adler & 0xffff; unsigned long sum2;
unsigned long s2 = (adler >> 16) & 0xffff; unsigned n;
int k;
if (buf == Z_NULL) return 1L; /* split Adler-32 into component sums */
sum2 = (adler >> 16) & 0xffff;
adler &= 0xffff;
while (len > 0) { /* in case user likes doing a byte at a time, keep it fast */
k = len < NMAX ? (int)len : NMAX; if (len == 1) {
len -= k; adler += buf[0];
while (k >= 16) { if (adler >= BASE)
adler -= BASE;
sum2 += adler;
if (sum2 >= BASE)
sum2 -= BASE;
return adler | (sum2 << 16);
}
/* initial Adler-32 value (deferred check for len == 1 speed) */
if (buf == Z_NULL)
return 1L;
/* in case short lengths are provided, keep it somewhat fast */
if (len < 16) {
while (len--) {
adler += *buf++;
sum2 += adler;
}
if (adler >= BASE)
adler -= BASE;
MOD4(sum2); /* only added so many BASE's */
return adler | (sum2 << 16);
}
/* do length NMAX blocks -- requires just one modulo operation */
while (len >= NMAX) {
len -= NMAX;
n = NMAX / 16; /* NMAX is divisible by 16 */
do {
DO16(buf); /* 16 sums unrolled */
buf += 16;
} while (--n);
MOD(adler);
MOD(sum2);
}
/* do remaining bytes (less than NMAX, still just one modulo) */
if (len) { /* avoid modulos if none remaining */
while (len >= 16) {
len -= 16;
DO16(buf); DO16(buf);
buf += 16; buf += 16;
k -= 16;
} }
if (k != 0) do { while (len--) {
s1 += *buf++; adler += *buf++;
s2 += s1; sum2 += adler;
} while (--k);
MOD(s1);
MOD(s2);
} }
return (s2 << 16) | s1; MOD(adler);
MOD(sum2);
}
/* return recombined sums */
return adler | (sum2 << 16);
}
/* ========================================================================= */
uLong ZEXPORT adler32_combine(adler1, adler2, len2)
uLong adler1;
uLong adler2;
z_off_t len2;
{
unsigned long sum1;
unsigned long sum2;
unsigned rem;
/* the derivation of this formula is left as an exercise for the reader */
rem = (unsigned)(len2 % BASE);
sum1 = adler1 & 0xffff;
sum2 = rem * sum1;
MOD(sum2);
sum1 += (adler2 & 0xffff) + BASE - 1;
sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
if (sum1 > BASE) sum1 -= BASE;
if (sum1 > BASE) sum1 -= BASE;
if (sum2 > (BASE << 1)) sum2 -= (BASE << 1);
if (sum2 > BASE) sum2 -= BASE;
return sum1 | (sum2 << 16);
} }

View File

@@ -1,7 +1,7 @@
* ZLIB.INC - Interface to the general purpose compression library * ZLIB.INC - Interface to the general purpose compression library
* *
* ILE RPG400 version by Patrick Monnerat, DATASPHERE. * ILE RPG400 version by Patrick Monnerat, DATASPHERE.
* Version 1.2.2 * Version 1.2.2.4
* *
* *
* WARNING: * WARNING:
@@ -20,8 +20,12 @@
* Constants * Constants
************************************************************************** **************************************************************************
* *
D ZLIB_VERSION C '1.2.2' Header's version * Versioning information.
D ZLIB_VERNUM C X'1220' *
D ZLIB_VERSION C '1.2.2.4'
D ZLIB_VERNUM C X'1224'
*
* Other equates.
* *
D Z_NO_FLUSH C 0 D Z_NO_FLUSH C 0
D Z_SYNC_FLUSH C 2 D Z_SYNC_FLUSH C 2

View File

@@ -1,5 +1,5 @@
/* compress.c -- compress a memory buffer /* compress.c -- compress a memory buffer
* Copyright (C) 1995-2002 Jean-loup Gailly. * Copyright (C) 1995-2003 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */

20
configure vendored
View File

@@ -82,14 +82,21 @@ if test "$gcc" -eq 1 && ($cc -c $cflags $test.c) 2>/dev/null; then
QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4 QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4
# (alain.bonnefoy@icbt.com) # (alain.bonnefoy@icbt.com)
LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"};; LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"};;
HP-UX*) LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"} HP-UX*)
LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"}
case `(uname -m || echo unknown) 2>/dev/null` in
ia64)
shared_ext='.so'
SHAREDLIB='libz.so';;
*)
shared_ext='.sl' shared_ext='.sl'
SHAREDLIB='libz.sl';; SHAREDLIB='libz.sl';;
esac;;
Darwin*) shared_ext='.dylib' Darwin*) shared_ext='.dylib'
SHAREDLIB=libz$shared_ext SHAREDLIB=libz$shared_ext
SHAREDLIBV=libz.$VER$shared_ext SHAREDLIBV=libz.$VER$shared_ext
SHAREDLIBM=libz.$VER1$shared_ext SHAREDLIBM=libz.$VER1$shared_ext
LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBV -compatibility_version $VER2 -current_version $VER"};; LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER"};;
*) LDSHARED=${LDSHARED-"$cc -shared"};; *) LDSHARED=${LDSHARED-"$cc -shared"};;
esac esac
else else
@@ -100,8 +107,14 @@ else
CFLAGS=${CFLAGS-"-O"} CFLAGS=${CFLAGS-"-O"}
# LDSHARED=${LDSHARED-"ld -b +vnocompatwarnings"} # LDSHARED=${LDSHARED-"ld -b +vnocompatwarnings"}
LDSHARED=${LDSHARED-"ld -b"} LDSHARED=${LDSHARED-"ld -b"}
case `(uname -m || echo unknown) 2>/dev/null` in
ia64)
shared_ext='.so'
SHAREDLIB='libz.so';;
*)
shared_ext='.sl' shared_ext='.sl'
SHAREDLIB='libz.sl';; SHAREDLIB='libz.sl';;
esac;;
IRIX*) SFLAGS=${CFLAGS-"-ansi -O2 -rpath ."} IRIX*) SFLAGS=${CFLAGS-"-ansi -O2 -rpath ."}
CFLAGS=${CFLAGS-"-ansi -O2"} CFLAGS=${CFLAGS-"-ansi -O2"}
LDSHARED=${LDSHARED-"cc -shared"};; LDSHARED=${LDSHARED-"cc -shared"};;
@@ -125,6 +138,9 @@ else
SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"} SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"}
CFLAGS=${CFLAGS-"-O2"} CFLAGS=${CFLAGS-"-O2"}
LDSHARED=${LDSHARED-"ld"};; LDSHARED=${LDSHARED-"ld"};;
SunStudio\ 9*) SFLAGS=${CFLAGS-"-DUSE_MMAP -fast -xcode=pic32 -xtarget=ultra3 -xarch=v9b"}
CFLAGS=${CFLAGS-"-DUSE_MMAP -fast -xtarget=ultra3 -xarch=v9b"}
LDSHARED=${LDSHARED-"cc -xarch=v9b"};;
UNIX_System_V\ 4.2.0) UNIX_System_V\ 4.2.0)
SFLAGS=${CFLAGS-"-KPIC -O"} SFLAGS=${CFLAGS-"-KPIC -O"}
CFLAGS=${CFLAGS-"-O"} CFLAGS=${CFLAGS-"-O"}

View File

@@ -22,9 +22,6 @@ delphi/ by Cosmin Truta <cosmint@cs.ubbcluj.ro>
dotzlib/ by Henrik Ravn <henrik@ravn.com> dotzlib/ by Henrik Ravn <henrik@ravn.com>
Support for Microsoft .Net and Visual C++ .Net Support for Microsoft .Net and Visual C++ .Net
gzappend/ by Mark Adler <madler@alumni.caltech.edu>
append to a gzip file -- illustrates the use of Z_BLOCK
infback9/ by Mark Adler <madler@alumni.caltech.edu> infback9/ by Mark Adler <madler@alumni.caltech.edu>
Unsupported diffs to infback to decode the deflate64 format Unsupported diffs to infback to decode the deflate64 format
@@ -45,6 +42,10 @@ masm686/ by Dan Higdon <hdan@kinesoft.com>
and Chuck Walbourn <chuckw@kinesoft.com> and Chuck Walbourn <chuckw@kinesoft.com>
asm code for Pentium Pro/PII, using the MASM syntax asm code for Pentium Pro/PII, using the MASM syntax
masmx64/ by Gilles Vollant <info@winimage.com>
x86 64-bit (AMD64 and Intel EM64t) code for x64 assembler to
replace longest_match() and inflate_fast()
masmx86/ by Gilles Vollant <info@winimage.com> masmx86/ by Gilles Vollant <info@winimage.com>
x86 asm code to replace longest_match() and inflate_fast(), x86 asm code to replace longest_match() and inflate_fast(),
for Visual C++ and MASM for Visual C++ and MASM

View File

@@ -45,19 +45,29 @@
* program to crash horribly, without so much as a warning at * program to crash horribly, without so much as a warning at
* compile time. Sigh.) * compile time. Sigh.)
*/ */
#define dsWSize 36
#define dsWMask 44 /* All the +zlib1222add offsets are due to the addition of fields
#define dsWindow 48 * in zlib in the deflate_state structure since the asm code was first written
#define dsPrev 56 * (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
#define dsMatchLen 88 * (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
#define dsPrevMatch 92 * if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").
#define dsStrStart 100 */
#define dsMatchStart 104
#define dsLookahead 108 #define zlib1222add (8)
#define dsPrevLen 112
#define dsMaxChainLen 116 #define dsWSize (36+zlib1222add)
#define dsGoodMatch 132 #define dsWMask (44+zlib1222add)
#define dsNiceMatch 136 #define dsWindow (48+zlib1222add)
#define dsPrev (56+zlib1222add)
#define dsMatchLen (88+zlib1222add)
#define dsPrevMatch (92+zlib1222add)
#define dsStrStart (100+zlib1222add)
#define dsMatchStart (104+zlib1222add)
#define dsLookahead (108+zlib1222add)
#define dsPrevLen (112+zlib1222add)
#define dsMaxChainLen (116+zlib1222add)
#define dsGoodMatch (132+zlib1222add)
#define dsNiceMatch (136+zlib1222add)
.file "match.S" .file "match.S"

View File

@@ -38,26 +38,28 @@
#define deflatestate 56 /* the function arguments */ #define deflatestate 56 /* the function arguments */
#define curmatch 60 #define curmatch 60
/* Offsets for fields in the deflate_state structure. These numbers /* All the +zlib1222add offsets are due to the addition of fields
* are calculated from the definition of deflate_state, with the * in zlib in the deflate_state structure since the asm code was first written
* assumption that the compiler will dword-align the fields. (Thus, * (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
* changing the definition of deflate_state could easily cause this * (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
* program to crash horribly, without so much as a warning at * if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").
* compile time. Sigh.)
*/ */
#define dsWSize 36
#define dsWMask 44 #define zlib1222add (8)
#define dsWindow 48
#define dsPrev 56 #define dsWSize (36+zlib1222add)
#define dsMatchLen 88 #define dsWMask (44+zlib1222add)
#define dsPrevMatch 92 #define dsWindow (48+zlib1222add)
#define dsStrStart 100 #define dsPrev (56+zlib1222add)
#define dsMatchStart 104 #define dsMatchLen (88+zlib1222add)
#define dsLookahead 108 #define dsPrevMatch (92+zlib1222add)
#define dsPrevLen 112 #define dsStrStart (100+zlib1222add)
#define dsMaxChainLen 116 #define dsMatchStart (104+zlib1222add)
#define dsGoodMatch 132 #define dsLookahead (108+zlib1222add)
#define dsNiceMatch 136 #define dsPrevLen (112+zlib1222add)
#define dsMaxChainLen (116+zlib1222add)
#define dsGoodMatch (132+zlib1222add)
#define dsNiceMatch (136+zlib1222add)
.file "match.S" .file "match.S"

View File

@@ -344,7 +344,7 @@ begin
strm.avail_out := OutBytes; strm.avail_out := OutBytes;
DCheck(inflateInit_(strm, zlib_version, sizeof(strm))); DCheck(inflateInit_(strm, zlib_version, sizeof(strm)));
try try
while DCheck(inflate(strm, Z_FINISH)) <> Z_STREAM_END do while DCheck(inflate(strm, Z_NO_FLUSH)) <> Z_STREAM_END do
begin begin
P := OutBuf; P := OutBuf;
Inc(OutBytes, BufInc); Inc(OutBytes, BufInc);

View File

@@ -16,6 +16,10 @@
* zlib.h must be included before this header file. * zlib.h must be included before this header file.
*/ */
#ifdef __cplusplus
extern "C" {
#endif
ZEXTERN int ZEXPORT inflateBack9 OF((z_stream FAR *strm, ZEXTERN int ZEXPORT inflateBack9 OF((z_stream FAR *strm,
in_func in, void FAR *in_desc, in_func in, void FAR *in_desc,
out_func out, void FAR *out_desc)); out_func out, void FAR *out_desc));
@@ -27,3 +31,7 @@ ZEXTERN int ZEXPORT inflateBack9Init_ OF((z_stream FAR *strm,
#define inflateBack9Init(strm, window) \ #define inflateBack9Init(strm, window) \
inflateBack9Init_((strm), (window), \ inflateBack9Init_((strm), (window), \
ZLIB_VERSION, sizeof(z_stream)) ZLIB_VERSION, sizeof(z_stream))
#ifdef __cplusplus
}
#endif

View File

@@ -1,5 +1,5 @@
/* inftree9.c -- generate Huffman trees for efficient decoding /* inftree9.c -- generate Huffman trees for efficient decoding
* Copyright (C) 1995-2003 Mark Adler * Copyright (C) 1995-2005 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@@ -9,7 +9,7 @@
#define MAXBITS 15 #define MAXBITS 15
const char inflate9_copyright[] = const char inflate9_copyright[] =
" inflate9 1.2.2 Copyright 1995-2004 Mark Adler "; " inflate9 1.2.2.4 Copyright 1995-2005 Mark Adler ";
/* /*
If you use the zlib library in a product, an acknowledgment is welcome 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 in the documentation of your product. If for some reason you cannot
@@ -64,7 +64,7 @@ unsigned short FAR *work;
static const unsigned short lext[31] = { /* Length codes 257..285 extra */ static const unsigned short lext[31] = { /* Length codes 257..285 extra */
128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129,
130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132, 130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132,
133, 133, 133, 133, 144, 199, 198}; 133, 133, 133, 133, 144, 206, 69};
static const unsigned short dbase[32] = { /* Distance codes 0..31 base */ static const unsigned short dbase[32] = { /* Distance codes 0..31 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49,
65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073,

File diff suppressed because it is too large Load Diff

View File

@@ -188,17 +188,8 @@
/* /*
* typedef enum inflate_mode consts, in inflate.h * typedef enum inflate_mode consts, in inflate.h
*/ */
#ifndef NO_GUNZIP
#define GUNZIP
#endif
#ifdef GUNZIP
#define INFLATE_MODE_TYPE 11 /* state->mode flags enum-ed in inflate.h */ #define INFLATE_MODE_TYPE 11 /* state->mode flags enum-ed in inflate.h */
#define INFLATE_MODE_BAD 26 #define INFLATE_MODE_BAD 26
#else
#define INFLATE_MODE_TYPE 3
#define INFLATE_MODE_BAD 17
#endif
#if ! defined( USE_MMX ) && ! defined( NO_MMX ) #if ! defined( USE_MMX ) && ! defined( NO_MMX )

View File

@@ -12,6 +12,8 @@
; Based on match.S ; Based on match.S
; Written for zlib 1.1.2 ; Written for zlib 1.1.2
; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com> ; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
;
; Modified by Gilles Vollant (2005) for add gzhead and gzindex
.686P .686P
.MODEL FLAT .MODEL FLAT
@@ -39,6 +41,9 @@ ds_pending_buf_size dd ?
ds_pending_out dd ? ds_pending_out dd ?
ds_pending dd ? ds_pending dd ?
ds_wrap dd ? ds_wrap dd ?
; gzhead and gzindex are added in zlib 1.2.2.2 (see deflate.h)
ds_gzhead dd ?
ds_gzindex dd ?
ds_data_type db ? ds_data_type db ?
ds_method db ? ds_method db ?
db ? ; padding db ? ; padding

View File

@@ -0,0 +1,2 @@
ml64.exe /Flinffasx64 /c /Zi inffasx64.asm
ml64.exe /Flgvmat64 /c /Zi gvmat64.asm

464
contrib/masmx64/gvmat64.asm Normal file
View File

@@ -0,0 +1,464 @@
;uInt longest_match_x64(
; deflate_state *s,
; IPos cur_match); /* current match */
; gvmat64.asm -- Asm portion of the optimized longest_match for 32 bits x86
; Copyright (C) 1995-2005 Jean-loup Gailly, Brian Raiter and Gilles Vollant.
; File written by Gilles Vollant, by modifiying the longest_match
; from Jean-loup Gailly in deflate.c
; and modifying asm686 with masm, optimised assembly code from Brian Raiter,
; written 1998
; http://www.zlib.net
; http://www.winimage.com/zLibDll
; http://www.muppetlabs.com/~breadbox/software/assembly.html
;
; to compile this file, I use option
; ml64.exe /Flgvmat64 /c /Zi gvmat64.asm
; with Microsoft Macro Assembler (x64) for AMD64
;
; ml64.exe is given with Visual Studio 2005, Windows 2003 server DDK
;
; (you can get Windows 2003 server DDK with ml64 and cl for AMD64 from
; http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price)
;
; Be carrefull to adapt zlib1222add below to your version of zLib
;uInt longest_match(s, cur_match)
; deflate_state *s;
; IPos cur_match; /* current match */
.code
longest_match PROC
;LocalVarsSize equ 88
LocalVarsSize equ 72
; register used : rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12
; free register : r14,r15
; register can be saved : rsp
chainlenwmask equ rsp + 8 - LocalVarsSize ; high word: current chain len
; low word: s->wmask
;window equ rsp + xx - LocalVarsSize ; local copy of s->window ; stored in r10
;windowbestlen equ rsp + xx - LocalVarsSize ; s->window + bestlen , use r10+r11
;scanstart equ rsp + xx - LocalVarsSize ; first two bytes of string ; stored in r12w
;scanend equ rsp + xx - LocalVarsSize ; last two bytes of string use ebx
;scanalign equ rsp + xx - LocalVarsSize ; dword-misalignment of string r13
;bestlen equ rsp + xx - LocalVarsSize ; size of best match so far -> r11d
;scan equ rsp + xx - LocalVarsSize ; ptr to string wanting match -> r9
nicematch equ rsp + 16 - LocalVarsSize ; a good enough match size -> r14
save_rdi equ rsp + 24 - LocalVarsSize
save_rsi equ rsp + 32 - LocalVarsSize
save_rbx equ rsp + 40 - LocalVarsSize
save_rbp equ rsp + 48 - LocalVarsSize
save_r12 equ rsp + 56 - LocalVarsSize
save_r13 equ rsp + 64 - LocalVarsSize
;save_r14 equ rsp + 72 - LocalVarsSize
;save_r15 equ rsp + 80 - LocalVarsSize
; all the +4 offsets are due to the addition of pending_buf_size (in zlib
; in the deflate_state structure since the asm code was first written
; (if you compile with zlib 1.0.4 or older, remove the +4).
; Note : these value are good with a 8 bytes boundary pack structure
MAX_MATCH equ 258
MIN_MATCH equ 3
MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1)
;;; Offsets for fields in the deflate_state structure. These numbers
;;; are calculated from the definition of deflate_state, with the
;;; assumption that the compiler will dword-align the fields. (Thus,
;;; changing the definition of deflate_state could easily cause this
;;; program to crash horribly, without so much as a warning at
;;; compile time. Sigh.)
; all the +zlib1222add offsets are due to the addition of fields
; in zlib in the deflate_state structure since the asm code was first written
; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").
zlib1222add equ 8
dsWSize equ 56+zlib1222add+(zlib1222add/2)
dsWMask equ 64+zlib1222add+(zlib1222add/2)
dsWindow equ 72+zlib1222add
dsPrev equ 88+zlib1222add
dsMatchLen equ 128+zlib1222add
dsPrevMatch equ 132+zlib1222add
dsStrStart equ 140+zlib1222add
dsMatchStart equ 144+zlib1222add
dsLookahead equ 148+zlib1222add
dsPrevLen equ 152+zlib1222add
dsMaxChainLen equ 156+zlib1222add
dsGoodMatch equ 172+zlib1222add
dsNiceMatch equ 176+zlib1222add
; parameter 1 in r8(deflate state s), param 2 in rdx (cur match)
; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and
; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp
;
; All registers must be preserved across the call, except for
; rax, rcx, rdx, r8, r-9, r10, and r11, which are scratch.
;;; Save registers that the compiler may be using, and adjust esp to
;;; make room for our stack frame.
;;; Retrieve the function arguments. r8d will hold cur_match
;;; throughout the entire function. edx will hold the pointer to the
;;; deflate_state structure during the function's setup (before
;;; entering the main loop.
; parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match)
; this clear high 32 bits of r8, which can be garbage in both r8 and rdx
mov [save_rdi],rdi
mov [save_rsi],rsi
mov [save_rbx],rbx
mov [save_rbp],rbp
mov r8d,edx
mov [save_r12],r12
mov [save_r13],r13
; mov [save_r14],r14
; mov [save_r15],r15
;;; uInt wmask = s->w_mask;
;;; unsigned chain_length = s->max_chain_length;
;;; if (s->prev_length >= s->good_match) {
;;; chain_length >>= 2;
;;; }
mov edi, [rcx + dsPrevLen]
mov esi, [rcx + dsGoodMatch]
mov eax, [rcx + dsWMask]
mov ebx, [rcx + dsMaxChainLen]
cmp edi, esi
jl LastMatchGood
shr ebx, 2
LastMatchGood:
;;; chainlen is decremented once beforehand so that the function can
;;; use the sign flag instead of the zero flag for the exit test.
;;; It is then shifted into the high word, to make room for the wmask
;;; value, which it will always accompany.
dec ebx
shl ebx, 16
or ebx, eax
mov [chainlenwmask], ebx
;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
mov eax, [rcx + dsNiceMatch]
mov r10d, [rcx + dsLookahead]
cmp r10d, eax
cmovnl r10d, eax
mov [nicematch],r10d
LookaheadLess:
;;; register Bytef *scan = s->window + s->strstart;
mov r10, [rcx + dsWindow]
mov ebp, [rcx + dsStrStart]
lea r13, [r10 + rbp]
;;; Determine how many bytes the scan ptr is off from being
;;; dword-aligned.
mov r9,r13
neg r13
and r13,3
;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
;;; s->strstart - (IPos)MAX_DIST(s) : NIL;
mov eax, [rcx + dsWSize]
sub eax, MIN_LOOKAHEAD
xor edi,edi
sub ebp, eax
mov r11d, [rcx + dsPrevLen]
cmovng ebp,edi
;;; int best_len = s->prev_length;
;;; Store the sum of s->window + best_len in esi locally, and in esi.
lea rsi,[r10+r11]
;;; register ush scan_start = *(ushf*)scan;
;;; register ush scan_end = *(ushf*)(scan+best_len-1);
;;; Posf *prev = s->prev;
movzx r12d,word ptr [r9]
movzx ebx, word ptr [r9 + r11 - 1]
mov rdi, [rcx + dsPrev]
;;; Jump into the main loop.
mov edx, [chainlenwmask]
cmp bx,word ptr [rsi + r8 - 1]
jz LookupLoopIsZero
LookupLoop1:
and r8d, edx
movzx r8d, word ptr [rdi + r8*2]
cmp r8d, ebp
jbe LeaveNow
sub edx, 00010000h
js LeaveNow
LoopEntry1:
cmp bx,word ptr [rsi + r8 - 1]
jz LookupLoopIsZero
LookupLoop2:
and r8d, edx
movzx r8d, word ptr [rdi + r8*2]
cmp r8d, ebp
jbe LeaveNow
sub edx, 00010000h
js LeaveNow
LoopEntry2:
cmp bx,word ptr [rsi + r8 - 1]
jz LookupLoopIsZero
LookupLoop4:
and r8d, edx
movzx r8d, word ptr [rdi + r8*2]
cmp r8d, ebp
jbe LeaveNow
sub edx, 00010000h
js LeaveNow
LoopEntry4:
cmp bx,word ptr [rsi + r8 - 1]
jnz LookupLoop1
jmp LookupLoopIsZero
;;; do {
;;; match = s->window + cur_match;
;;; if (*(ushf*)(match+best_len-1) != scan_end ||
;;; *(ushf*)match != scan_start) continue;
;;; [...]
;;; } while ((cur_match = prev[cur_match & wmask]) > limit
;;; && --chain_length != 0);
;;;
;;; Here is the inner loop of the function. The function will spend the
;;; majority of its time in this loop, and majority of that time will
;;; be spent in the first ten instructions.
;;;
;;; Within this loop:
;;; ebx = scanend
;;; r8d = curmatch
;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
;;; esi = windowbestlen - i.e., (window + bestlen)
;;; edi = prev
;;; ebp = limit
LookupLoop:
and r8d, edx
movzx r8d, word ptr [rdi + r8*2]
cmp r8d, ebp
jbe LeaveNow
sub edx, 00010000h
js LeaveNow
LoopEntry:
cmp bx,word ptr [rsi + r8 - 1]
jnz LookupLoop1
LookupLoopIsZero:
cmp r12w, word ptr [r10 + r8]
jnz LookupLoop1
;;; Store the current value of chainlen.
mov [chainlenwmask], edx
;;; Point edi to the string under scrutiny, and esi to the string we
;;; are hoping to match it up with. In actuality, esi and edi are
;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is
;;; initialized to -(MAX_MATCH_8 - scanalign).
lea rsi,[r8+r10]
mov rdx, 0fffffffffffffef8h; -(MAX_MATCH_8)
lea rsi, [rsi + r13 + 0108h] ;MAX_MATCH_8]
lea rdi, [r9 + r13 + 0108h] ;MAX_MATCH_8]
prefetcht1 [rsi+rdx]
prefetcht1 [rdi+rdx]
;;; Test the strings for equality, 8 bytes at a time. At the end,
;;; adjust edx so that it is offset to the exact byte that mismatched.
;;;
;;; We already know at this point that the first three bytes of the
;;; strings match each other, and they can be safely passed over before
;;; starting the compare loop. So what this code does is skip over 0-3
;;; bytes, as much as necessary in order to dword-align the edi
;;; pointer. (esi will still be misaligned three times out of four.)
;;;
;;; It should be confessed that this loop usually does not represent
;;; much of the total running time. Replacing it with a more
;;; straightforward "rep cmpsb" would not drastically degrade
;;; performance.
;LoopCmps:
; mov eax, [rsi + rdx]
; xor eax, [rdi + rdx]
; jnz LeaveLoopCmps
; mov eax, [rsi + rdx + 4]
; xor eax, [rdi + rdx + 4]
; jnz LeaveLoopCmps4
; add rdx, 8
; jnz LoopCmps
; jmp LenMaximum
;LeaveLoopCmps4: add rdx, 4
;LeaveLoopCmps: test eax, 0000FFFFh
; jnz LenLower
; add rdx, 2
; shr eax, 16
;LenLower: sub al, 1
; adc rdx, 0
LoopCmps:
mov rax, [rsi + rdx]
xor rax, [rdi + rdx]
jnz LeaveLoopCmps
mov rax, [rsi + rdx + 8]
xor rax, [rdi + rdx + 8]
jnz LeaveLoopCmps8
mov rax, [rsi + rdx + 8+8]
xor rax, [rdi + rdx + 8+8]
jnz LeaveLoopCmps16
add rdx,8+8+8
jmp short LoopCmps
LeaveLoopCmps16: add rdx,8
LeaveLoopCmps8: add rdx,8
LeaveLoopCmps:
test eax, 0000FFFFh
jnz LenLower
test eax,0ffffffffh
jnz LenLower32
add rdx,4
shr rax,32
or ax,ax
jnz LenLower
LenLower32:
shr eax,16
add rdx,2
LenLower: sub al, 1
adc rdx, 0
;;; Calculate the length of the match. If it is longer than MAX_MATCH,
;;; then automatically accept it as the best possible match and leave.
lea rax, [rdi + rdx]
sub rax, r9
cmp eax, MAX_MATCH
jge LenMaximum
;;; If the length of the match is not longer than the best match we
;;; have so far, then forget it and return to the lookup loop.
;///////////////////////////////////
cmp eax, r11d
jg LongerMatch
lea rsi,[r10+r11]
mov rdi, [rcx + dsPrev]
mov edx, [chainlenwmask]
jmp LookupLoop
;;; s->match_start = cur_match;
;;; best_len = len;
;;; if (len >= nice_match) break;
;;; scan_end = *(ushf*)(scan+best_len-1);
LongerMatch:
mov r11d, eax
mov [rcx + dsMatchStart], r8d
cmp eax, [nicematch]
jge LeaveNow
lea rsi,[r10+rax]
movzx ebx, word ptr [r9 + rax - 1]
mov rdi, [rcx + dsPrev]
mov edx, [chainlenwmask]
jmp LookupLoop
;;; Accept the current string, with the maximum possible length.
LenMaximum:
mov r11d,MAX_MATCH
mov [rcx + dsMatchStart], r8d
;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
;;; return s->lookahead;
LeaveNow:
mov eax, [rcx + dsLookahead]
cmp r11d, eax
cmovng eax, r11d
;;; Restore the stack and return from whence we came.
mov rsi,[save_rsi]
mov rdi,[save_rdi]
mov rbx,[save_rbx]
mov rbp,[save_rbp]
mov r12,[save_r12]
mov r13,[save_r13]
; mov r14,[save_r14]
; mov r15,[save_r15]
ret 0
; please don't remove this string !
; Your can freely use gvmat32 in any free or commercial app if you don't remove the string in the binary!
db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998, converted to amd 64 by Gilles Vollant 2005",0dh,0ah,0
longest_match ENDP
match_init PROC
ret 0
match_init ENDP
END

BIN
contrib/masmx64/gvmat64.obj Normal file

Binary file not shown.

View File

@@ -0,0 +1,186 @@
/* inffas8664.c is a hand tuned assembler version of inffast.c - fast decoding
* version for AMD64 on Windows using Microsoft C compiler
*
* Copyright (C) 1995-2003 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*
* Copyright (C) 2003 Chris Anderson <christop@charm.net>
* Please use the copyright conditions above.
*
* 2005 - Adaptation to Microsoft C Compiler for AMD64 by Gilles Vollant
*
* inffas8664.c call function inffas8664fnc in inffasx64.asm
* inffasx64.asm is automatically convert from AMD64 portion of inffas86.c
*
* Dec-29-2003 -- I added AMD64 inflate asm support. This version is also
* slightly quicker on x86 systems because, instead of using rep movsb to copy
* data, it uses rep movsw, which moves data in 2-byte chunks instead of single
* bytes. I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates
* from http://fedora.linux.duke.edu/fc1_x86_64
* which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with
* 1GB ram. The 64-bit version is about 4% faster than the 32-bit version,
* when decompressing mozilla-source-1.3.tar.gz.
*
* Mar-13-2003 -- Most of this is derived from inffast.S which is derived from
* the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at
* the moment. I have successfully compiled and tested this code with gcc2.96,
* gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S
* compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX
* enabled. I will attempt to merge the MMX code into this version. Newer
* versions of this and inffast.S can be found at
* http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/
*
*/
#include <stdio.h>
#include "zutil.h"
#include "inftrees.h"
#include "inflate.h"
#include "inffast.h"
/* Mark Adler's comments from inffast.c: */
/*
Decode literal, length, and distance codes and write out the resulting
literal and match bytes until either not enough input or output is
available, an end-of-block is encountered, or a data error is encountered.
When large enough input and output buffers are supplied to inflate(), for
example, a 16K input buffer and a 64K output buffer, more than 95% of the
inflate execution time is spent in this routine.
Entry assumptions:
state->mode == LEN
strm->avail_in >= 6
strm->avail_out >= 258
start >= strm->avail_out
state->bits < 8
On return, state->mode is one of:
LEN -- ran out of enough output space or enough available input
TYPE -- reached end of block code, inflate() to interpret next block
BAD -- error in block data
Notes:
- The maximum input bits used by a length/distance pair is 15 bits for the
length code, 5 bits for the length extra, 15 bits for the distance code,
and 13 bits for the distance extra. This totals 48 bits, or six bytes.
Therefore if strm->avail_in >= 6, then there is enough input to avoid
checking for available input while decoding.
- The maximum bytes that a single length/distance pair can output is 258
bytes, which is the maximum length that can be coded. inflate_fast()
requires strm->avail_out >= 258 for each loop to avoid checking for
output space.
*/
typedef struct inffast_ar {
/* 64 32 x86 x86_64 */
/* ar offset register */
/* 0 0 */ void *esp; /* esp save */
/* 8 4 */ void *ebp; /* ebp save */
/* 16 8 */ unsigned char FAR *in; /* esi rsi local strm->next_in */
/* 24 12 */ unsigned char FAR *last; /* r9 while in < last */
/* 32 16 */ unsigned char FAR *out; /* edi rdi local strm->next_out */
/* 40 20 */ unsigned char FAR *beg; /* inflate()'s init next_out */
/* 48 24 */ unsigned char FAR *end; /* r10 while out < end */
/* 56 28 */ unsigned char FAR *window;/* size of window, wsize!=0 */
/* 64 32 */ code const FAR *lcode; /* ebp rbp local strm->lencode */
/* 72 36 */ code const FAR *dcode; /* r11 local strm->distcode */
/* 80 40 */ size_t /*unsigned long */hold; /* edx rdx local strm->hold */
/* 88 44 */ unsigned bits; /* ebx rbx local strm->bits */
/* 92 48 */ unsigned wsize; /* window size */
/* 96 52 */ unsigned write; /* window write index */
/*100 56 */ unsigned lmask; /* r12 mask for lcode */
/*104 60 */ unsigned dmask; /* r13 mask for dcode */
/*108 64 */ unsigned len; /* r14 match length */
/*112 68 */ unsigned dist; /* r15 match distance */
/*116 72 */ unsigned status; /* set when state chng*/
} type_ar;
#ifdef ASMINF
void inflate_fast(strm, start)
z_streamp strm;
unsigned start; /* inflate()'s starting value for strm->avail_out */
{
struct inflate_state FAR *state;
type_ar ar;
void inffas8664fnc(struct inffast_ar * par);
#if (defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )) || (defined(_MSC_VER) && defined(_M_AMD64))
#define PAD_AVAIL_IN 6
#define PAD_AVAIL_OUT 258
#else
#define PAD_AVAIL_IN 5
#define PAD_AVAIL_OUT 257
#endif
/* copy state to local variables */
state = (struct inflate_state FAR *)strm->state;
ar.in = strm->next_in;
ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN);
ar.out = strm->next_out;
ar.beg = ar.out - (start - strm->avail_out);
ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT);
ar.wsize = state->wsize;
ar.write = state->write;
ar.window = state->window;
ar.hold = state->hold;
ar.bits = state->bits;
ar.lcode = state->lencode;
ar.dcode = state->distcode;
ar.lmask = (1U << state->lenbits) - 1;
ar.dmask = (1U << state->distbits) - 1;
/* decode literals and length/distances until end-of-block or not enough
input data or output space */
/* align in on 1/2 hold size boundary */
while (((size_t)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) {
ar.hold += (unsigned long)*ar.in++ << ar.bits;
ar.bits += 8;
}
inffas8664fnc(&ar);
if (ar.status > 1) {
if (ar.status == 2)
strm->msg = "invalid literal/length code";
else if (ar.status == 3)
strm->msg = "invalid distance code";
else
strm->msg = "invalid distance too far back";
state->mode = BAD;
}
else if ( ar.status == 1 ) {
state->mode = TYPE;
}
/* return unused bytes (on entry, bits < 8, so in won't go too far back) */
ar.len = ar.bits >> 3;
ar.in -= ar.len;
ar.bits -= ar.len << 3;
ar.hold &= (1U << ar.bits) - 1;
/* update state and return */
strm->next_in = ar.in;
strm->next_out = ar.out;
strm->avail_in = (unsigned)(ar.in < ar.last ?
PAD_AVAIL_IN + (ar.last - ar.in) :
PAD_AVAIL_IN - (ar.in - ar.last));
strm->avail_out = (unsigned)(ar.out < ar.end ?
PAD_AVAIL_OUT + (ar.end - ar.out) :
PAD_AVAIL_OUT - (ar.out - ar.end));
state->hold = (unsigned long)ar.hold;
state->bits = ar.bits;
return;
}
#endif

View File

@@ -0,0 +1,392 @@
; inffasx64.asm is a hand tuned assembler version of inffast.c - fast decoding
; version for AMD64 on Windows using Microsoft C compiler
;
; inffasx64.asm is automatically convert from AMD64 portion of inffas86.c
; inffasx64.asm is called by inffas8664.c, which contain more info.
; to compile this file, I use option
; ml64.exe /Flinffasx64 /c /Zi inffasx64.asm
; with Microsoft Macro Assembler (x64) for AMD64
;
; ml64.exe is given with Visual Studio 2005, Windows 2003 server DDK
;
; (you can get Windows 2003 server DDK with ml64 and cl.exe for AMD64 from
; http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price)
;
.code
inffas8664fnc PROC
; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and
; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp
;
; All registers must be preserved across the call, except for
; rax, rcx, rdx, r8, r-9, r10, and r11, which are scratch.
mov [rsp-8],rsi
mov [rsp-16],rdi
mov [rsp-24],r12
mov [rsp-32],r13
mov [rsp-40],r14
mov [rsp-48],r15
mov [rsp-56],rbx
mov rax,rcx
mov [rax+8], rbp ; /* save regs rbp and rsp */
mov [rax], rsp
mov rsp, rax ; /* make rsp point to &ar */
mov rsi, [rsp+16] ; /* rsi = in */
mov rdi, [rsp+32] ; /* rdi = out */
mov r9, [rsp+24] ; /* r9 = last */
mov r10, [rsp+48] ; /* r10 = end */
mov rbp, [rsp+64] ; /* rbp = lcode */
mov r11, [rsp+72] ; /* r11 = dcode */
mov rdx, [rsp+80] ; /* rdx = hold */
mov ebx, [rsp+88] ; /* ebx = bits */
mov r12d, [rsp+100] ; /* r12d = lmask */
mov r13d, [rsp+104] ; /* r13d = dmask */
; /* r14d = len */
; /* r15d = dist */
cld
cmp r10, rdi
je L_one_time ; /* if only one decode left */
cmp r9, rsi
jne L_do_loop
L_one_time:
mov r8, r12 ; /* r8 = lmask */
cmp bl, 32
ja L_get_length_code_one_time
lodsd ; /* eax = *(uint *)in++ */
mov cl, bl ; /* cl = bits, needs it for shifting */
add bl, 32 ; /* bits += 32 */
shl rax, cl
or rdx, rax ; /* hold |= *((uint *)in)++ << bits */
jmp L_get_length_code_one_time
ALIGN 4
L_while_test:
cmp r10, rdi
jbe L_break_loop
cmp r9, rsi
jbe L_break_loop
L_do_loop:
mov r8, r12 ; /* r8 = lmask */
cmp bl, 32
ja L_get_length_code ; /* if (32 < bits) */
lodsd ; /* eax = *(uint *)in++ */
mov cl, bl ; /* cl = bits, needs it for shifting */
add bl, 32 ; /* bits += 32 */
shl rax, cl
or rdx, rax ; /* hold |= *((uint *)in)++ << bits */
L_get_length_code:
and r8, rdx ; /* r8 &= hold */
mov eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */
mov cl, ah ; /* cl = this.bits */
sub bl, ah ; /* bits -= this.bits */
shr rdx, cl ; /* hold >>= this.bits */
test al, al
jnz L_test_for_length_base ; /* if (op != 0) 45.7% */
mov r8, r12 ; /* r8 = lmask */
shr eax, 16 ; /* output this.val char */
stosb
L_get_length_code_one_time:
and r8, rdx ; /* r8 &= hold */
mov eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */
L_dolen:
mov cl, ah ; /* cl = this.bits */
sub bl, ah ; /* bits -= this.bits */
shr rdx, cl ; /* hold >>= this.bits */
test al, al
jnz L_test_for_length_base ; /* if (op != 0) 45.7% */
shr eax, 16 ; /* output this.val char */
stosb
jmp L_while_test
ALIGN 4
L_test_for_length_base:
mov r14d, eax ; /* len = this */
shr r14d, 16 ; /* len = this.val */
mov cl, al
test al, 16
jz L_test_for_second_level_length ; /* if ((op & 16) == 0) 8% */
and cl, 15 ; /* op &= 15 */
jz L_decode_distance ; /* if (!op) */
L_add_bits_to_len:
sub bl, cl
xor eax, eax
inc eax
shl eax, cl
dec eax
and eax, edx ; /* eax &= hold */
shr rdx, cl
add r14d, eax ; /* len += hold & mask[op] */
L_decode_distance:
mov r8, r13 ; /* r8 = dmask */
cmp bl, 32
ja L_get_distance_code ; /* if (32 < bits) */
lodsd ; /* eax = *(uint *)in++ */
mov cl, bl ; /* cl = bits, needs it for shifting */
add bl, 32 ; /* bits += 32 */
shl rax, cl
or rdx, rax ; /* hold |= *((uint *)in)++ << bits */
L_get_distance_code:
and r8, rdx ; /* r8 &= hold */
mov eax, [r11+r8*4] ; /* eax = dcode[hold & dmask] */
L_dodist:
mov r15d, eax ; /* dist = this */
shr r15d, 16 ; /* dist = this.val */
mov cl, ah
sub bl, ah ; /* bits -= this.bits */
shr rdx, cl ; /* hold >>= this.bits */
mov cl, al ; /* cl = this.op */
test al, 16 ; /* if ((op & 16) == 0) */
jz L_test_for_second_level_dist
and cl, 15 ; /* op &= 15 */
jz L_check_dist_one
L_add_bits_to_dist:
sub bl, cl
xor eax, eax
inc eax
shl eax, cl
dec eax ; /* (1 << op) - 1 */
and eax, edx ; /* eax &= hold */
shr rdx, cl
add r15d, eax ; /* dist += hold & ((1 << op) - 1) */
L_check_window:
mov r8, rsi ; /* save in so from can use it's reg */
mov rax, rdi
sub rax, [rsp+40] ; /* nbytes = out - beg */
cmp eax, r15d
jb L_clip_window ; /* if (dist > nbytes) 4.2% */
mov ecx, r14d ; /* ecx = len */
mov rsi, rdi
sub rsi, r15 ; /* from = out - dist */
sar ecx, 1
jnc L_copy_two ; /* if len % 2 == 0 */
rep movsw
mov al, [rsi]
mov [rdi], al
inc rdi
mov rsi, r8 ; /* move in back to %rsi, toss from */
jmp L_while_test
L_copy_two:
rep movsw
mov rsi, r8 ; /* move in back to %rsi, toss from */
jmp L_while_test
ALIGN 4
L_check_dist_one:
cmp r15d, 1 ; /* if dist 1, is a memset */
jne L_check_window
cmp [rsp+40], rdi ; /* if out == beg, outside window */
je L_check_window
mov ecx, r14d ; /* ecx = len */
mov al, [rdi-1]
mov ah, al
sar ecx, 1
jnc L_set_two
mov [rdi], al
inc rdi
L_set_two:
rep stosw
jmp L_while_test
ALIGN 4
L_test_for_second_level_length:
test al, 64
jnz L_test_for_end_of_block ; /* if ((op & 64) != 0) */
xor eax, eax
inc eax
shl eax, cl
dec eax
and eax, edx ; /* eax &= hold */
add eax, r14d ; /* eax += len */
mov eax, [rbp+rax*4] ; /* eax = lcode[val+(hold&mask[op])]*/
jmp L_dolen
ALIGN 4
L_test_for_second_level_dist:
test al, 64
jnz L_invalid_distance_code ; /* if ((op & 64) != 0) */
xor eax, eax
inc eax
shl eax, cl
dec eax
and eax, edx ; /* eax &= hold */
add eax, r15d ; /* eax += dist */
mov eax, [r11+rax*4] ; /* eax = dcode[val+(hold&mask[op])]*/
jmp L_dodist
ALIGN 4
L_clip_window:
mov ecx, eax ; /* ecx = nbytes */
mov eax, [rsp+92] ; /* eax = wsize, prepare for dist cmp */
neg ecx ; /* nbytes = -nbytes */
cmp eax, r15d
jb L_invalid_distance_too_far ; /* if (dist > wsize) */
add ecx, r15d ; /* nbytes = dist - nbytes */
cmp dword ptr [rsp+96], 0
jne L_wrap_around_window ; /* if (write != 0) */
mov rsi, [rsp+56] ; /* from = window */
sub eax, ecx ; /* eax -= nbytes */
add rsi, rax ; /* from += wsize - nbytes */
mov eax, r14d ; /* eax = len */
cmp r14d, ecx
jbe L_do_copy ; /* if (nbytes >= len) */
sub eax, ecx ; /* eax -= nbytes */
rep movsb
mov rsi, rdi
sub rsi, r15 ; /* from = &out[ -dist ] */
jmp L_do_copy
ALIGN 4
L_wrap_around_window:
mov eax, [rsp+96] ; /* eax = write */
cmp ecx, eax
jbe L_contiguous_in_window ; /* if (write >= nbytes) */
mov esi, [rsp+92] ; /* from = wsize */
add rsi, [rsp+56] ; /* from += window */
add rsi, rax ; /* from += write */
sub rsi, rcx ; /* from -= nbytes */
sub ecx, eax ; /* nbytes -= write */
mov eax, r14d ; /* eax = len */
cmp eax, ecx
jbe L_do_copy ; /* if (nbytes >= len) */
sub eax, ecx ; /* len -= nbytes */
rep movsb
mov rsi, [rsp+56] ; /* from = window */
mov ecx, [rsp+96] ; /* nbytes = write */
cmp eax, ecx
jbe L_do_copy ; /* if (nbytes >= len) */
sub eax, ecx ; /* len -= nbytes */
rep movsb
mov rsi, rdi
sub rsi, r15 ; /* from = out - dist */
jmp L_do_copy
ALIGN 4
L_contiguous_in_window:
mov rsi, [rsp+56] ; /* rsi = window */
add rsi, rax
sub rsi, rcx ; /* from += write - nbytes */
mov eax, r14d ; /* eax = len */
cmp eax, ecx
jbe L_do_copy ; /* if (nbytes >= len) */
sub eax, ecx ; /* len -= nbytes */
rep movsb
mov rsi, rdi
sub rsi, r15 ; /* from = out - dist */
jmp L_do_copy ; /* if (nbytes >= len) */
ALIGN 4
L_do_copy:
mov ecx, eax ; /* ecx = len */
rep movsb
mov rsi, r8 ; /* move in back to %esi, toss from */
jmp L_while_test
L_test_for_end_of_block:
test al, 32
jz L_invalid_literal_length_code
mov dword ptr [rsp+116], 1
jmp L_break_loop_with_status
L_invalid_literal_length_code:
mov dword ptr [rsp+116], 2
jmp L_break_loop_with_status
L_invalid_distance_code:
mov dword ptr [rsp+116], 3
jmp L_break_loop_with_status
L_invalid_distance_too_far:
mov dword ptr [rsp+116], 4
jmp L_break_loop_with_status
L_break_loop:
mov dword ptr [rsp+116], 0
L_break_loop_with_status:
; /* put in, out, bits, and hold back into ar and pop esp */
mov [rsp+16], rsi ; /* in */
mov [rsp+32], rdi ; /* out */
mov [rsp+88], ebx ; /* bits */
mov [rsp+80], rdx ; /* hold */
mov rax, [rsp] ; /* restore rbp and rsp */
mov rbp, [rsp+8]
mov rsp, rax
mov rsi,[rsp-8]
mov rdi,[rsp-16]
mov r12,[rsp-24]
mov r13,[rsp-32]
mov r14,[rsp-40]
mov r15,[rsp-48]
mov rbx,[rsp-56]
ret 0
; :
; : "m" (ar)
; : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi",
; "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
; );
inffas8664fnc ENDP
;_TEXT ENDS
END

Binary file not shown.

View File

@@ -0,0 +1,28 @@
Summary
-------
This directory contains ASM implementations of the functions
longest_match() and inflate_fast(), for 64 bits x86 (both AMD64 and Intel EM64t),
for use with Microsoft Macro Assembler (x64) for AMD64 and Microsoft C++ 64 bits.
gvmat64.asm is written by Gilles Vollant (2005), by using Brian Raiter 686/32 bits
assembly optimized version from Jean-loup Gailly original longest_match function
inffasx64.asm and inffas8664.c were written by Chris Anderson, by optimizing
original function from Mark Adler
Use instructions
----------------
Copy these files into the zlib source directory.
define ASMV and ASMINF in your project. Include inffas8664.c in your source tree,
and inffasx64.obj and gvmat64.obj as object to link.
Build instructions
------------------
run bld_64.bat with Microsoft Macro Assembler (x64) for AMD64 (ml64.exe)
ml64.exe is given with Visual Studio 2005, Windows 2003 server DDK
You can get Windows 2003 server DDK with ml64 and cl for AMD64 from
http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price)

View File

@@ -0,0 +1,2 @@
ml /coff /Zi /c /Flgvmat32.lst gvmat32.asm
ml /coff /Zi /c /Flinffas32.lst inffas32.asm

View File

@@ -1,14 +1,52 @@
;
; gvmat32.asm -- Asm portion of the optimized longest_match for 32 bits x86 ; gvmat32.asm -- Asm portion of the optimized longest_match for 32 bits x86
; Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant. ; Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.
; File written by Gilles Vollant, by modifiying the longest_match ; File written by Gilles Vollant, by modifiying the longest_match
; from Jean-loup Gailly in deflate.c ; from Jean-loup Gailly in deflate.c
; It need wmask == 0x7fff
; (assembly code is faster with a fixed wmask)
; ;
; For Visual C++ 4.2 and ML 6.11c (version in directory \MASM611C of Win95 DDK) ; http://www.zlib.net
; I compile with : "ml /coff /Zi /c gvmat32.asm" ; http://www.winimage.com/zLibDll
; http://www.muppetlabs.com/~breadbox/software/assembly.html
; ;
; For Visual C++ 4.x and higher and ML 6.x and higher
; ml.exe is in directory \MASM611C of Win95 DDK
; ml.exe is also distributed in http://www.masm32.com/masmdl.htm
; and in VC++2003 toolkit at http://msdn.microsoft.com/visualc/vctoolkit2003/
;
; this file contain two implementation of longest_match
;
; longest_match_7fff : written 1996 by Gilles Vollant optimized for
; first Pentium. Assume s->w_mask == 0x7fff
; longest_match_686 : written by Brian raiter (1998), optimized for Pentium Pro
;
; for using an seembly version of longest_match, you need define ASMV in project
; There is two way in using gvmat32.asm
;
; A) Suggested method
; if you want include both longest_match_7fff and longest_match_686
; compile the asm file running
; ml /coff /Zi /Flgvmat32.lst /c gvmat32.asm
; and include gvmat32c.c in your project
; if you have an old cpu (386,486 or first Pentium) and s->w_mask==0x7fff,
; longest_match_7fff will be used
; if you have a more modern CPU (Pentium Pro, II and higher)
; longest_match_686 will be used
; on old cpu with s->w_mask!=0x7fff, longest_match_686 will be used,
; but this is not a sitation you'll find often
;
; B) Alternative
; if you are not interresed in old cpu performance and want the smaller
; binaries possible
;
; compile the asm file running
; ml /coff /Zi /c /Flgvmat32.lst /DNOOLDPENTIUMCODE gvmat32.asm
; and do not include gvmat32c.c in your project (ou define also
; NOOLDPENTIUMCODE)
;
; note : as I known, longest_match_686 is very faster than longest_match_7fff
; on pentium Pro/II/III, faster (but less) in P4, but it seem
; longest_match_7fff can be faster (very very litte) on AMD Athlon64/K8
;
; see below : zlib1222add must be adjuster if you use a zlib version < 1.2.2.2
;uInt longest_match_7fff(s, cur_match) ;uInt longest_match_7fff(s, cur_match)
; deflate_state *s; ; deflate_state *s;
@@ -47,33 +85,48 @@
; all the +4 offsets are due to the addition of pending_buf_size (in zlib ; all the +zlib1222add offsets are due to the addition of fields
; in the deflate_state structure since the asm code was first written ; in zlib in the deflate_state structure since the asm code was first written
; (if you compile with zlib 1.0.4 or older, remove the +4). ; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").
zlib1222add equ 8
; Note : these value are good with a 8 bytes boundary pack structure ; Note : these value are good with a 8 bytes boundary pack structure
dep_chain_length equ 70h+4 dep_chain_length equ 74h+zlib1222add
dep_window equ 2ch+4 dep_window equ 30h+zlib1222add
dep_strstart equ 60h+4 dep_strstart equ 64h+zlib1222add
dep_prev_length equ 6ch+4 dep_prev_length equ 70h+zlib1222add
dep_nice_match equ 84h+4 dep_nice_match equ 88h+zlib1222add
dep_w_size equ 20h+4 dep_w_size equ 24h+zlib1222add
dep_prev equ 34h+4 dep_prev equ 38h+zlib1222add
dep_w_mask equ 28h+4 dep_w_mask equ 2ch+zlib1222add
dep_good_match equ 80h+4 dep_good_match equ 84h+zlib1222add
dep_match_start equ 64h+4 dep_match_start equ 68h+zlib1222add
dep_lookahead equ 68h+4 dep_lookahead equ 6ch+zlib1222add
_TEXT segment _TEXT segment
IFDEF NOUNDERLINE IFDEF NOUNDERLINE
IFDEF NOOLDPENTIUMCODE
public longest_match
public match_init
ELSE
public longest_match_7fff public longest_match_7fff
public cpudetect32
public longest_match_686 public longest_match_686
; public match_init ENDIF
ELSE ELSE
IFDEF NOOLDPENTIUMCODE
public _longest_match
public _match_init
ELSE
public _longest_match_7fff public _longest_match_7fff
public _cpudetect32
public _longest_match_686 public _longest_match_686
; public _match_init ENDIF
ENDIF ENDIF
MAX_MATCH equ 258 MAX_MATCH equ 258
@@ -82,17 +135,7 @@ ENDIF
IFDEF NOUNDERLINE IFNDEF NOOLDPENTIUMCODE
;match_init proc near
; ret
;match_init endp
ELSE
;_match_init proc near
; ret
;_match_init endp
ENDIF
IFDEF NOUNDERLINE IFDEF NOUNDERLINE
longest_match_7fff proc near longest_match_7fff proc near
ELSE ELSE
@@ -558,9 +601,7 @@ cpudetect32 endp
ELSE ELSE
_cpudetect32 endp _cpudetect32 endp
ENDIF ENDIF
ENDIF
MAX_MATCH equ 258 MAX_MATCH equ 258
MIN_MATCH equ 3 MIN_MATCH equ 3
@@ -597,19 +638,19 @@ curmatch equ esp + 60
;;; program to crash horribly, without so much as a warning at ;;; program to crash horribly, without so much as a warning at
;;; compile time. Sigh.) ;;; compile time. Sigh.)
dsWSize equ 36 dsWSize equ 36+zlib1222add
dsWMask equ 44 dsWMask equ 44+zlib1222add
dsWindow equ 48 dsWindow equ 48+zlib1222add
dsPrev equ 56 dsPrev equ 56+zlib1222add
dsMatchLen equ 88 dsMatchLen equ 88+zlib1222add
dsPrevMatch equ 92 dsPrevMatch equ 92+zlib1222add
dsStrStart equ 100 dsStrStart equ 100+zlib1222add
dsMatchStart equ 104 dsMatchStart equ 104+zlib1222add
dsLookahead equ 108 dsLookahead equ 108+zlib1222add
dsPrevLen equ 112 dsPrevLen equ 112+zlib1222add
dsMaxChainLen equ 116 dsMaxChainLen equ 116+zlib1222add
dsGoodMatch equ 132 dsGoodMatch equ 132+zlib1222add
dsNiceMatch equ 136 dsNiceMatch equ 136+zlib1222add
;;; match.asm -- Pentium-Pro-optimized version of longest_match() ;;; match.asm -- Pentium-Pro-optimized version of longest_match()
@@ -628,13 +669,20 @@ dsNiceMatch equ 136
;;; uInt longest_match(deflate_state *deflatestate, IPos curmatch) ;;; uInt longest_match(deflate_state *deflatestate, IPos curmatch)
;_longest_match: ;_longest_match:
IFDEF NOUNDERLINE IFDEF NOOLDPENTIUMCODE
longest_match_686 proc near IFDEF NOUNDERLINE
longest_match proc near
ELSE
_longest_match proc near
ENDIF
ELSE ELSE
_longest_match_686 proc near IFDEF NOUNDERLINE
longest_match_686 proc near
ELSE
_longest_match_686 proc near
ENDIF
ENDIF ENDIF
;;; Save registers that the compiler may be using, and adjust esp to ;;; Save registers that the compiler may be using, and adjust esp to
;;; make room for our stack frame. ;;; make room for our stack frame.
@@ -895,10 +943,29 @@ LookaheadRet:
; Your can freely use gvmat32 in any free or commercial app if you don't remove the string in the binary! ; Your can freely use gvmat32 in any free or commercial app if you don't remove the string in the binary!
db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998",0dh,0ah db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998",0dh,0ah
IFDEF NOUNDERLINE
longest_match_686 endp IFDEF NOOLDPENTIUMCODE
IFDEF NOUNDERLINE
longest_match endp
ELSE
_longest_match endp
ENDIF
IFDEF NOUNDERLINE
match_init proc near
ret
match_init endp
ELSE
_match_init proc near
ret
_match_init endp
ENDIF
ELSE ELSE
_longest_match_686 endp IFDEF NOUNDERLINE
longest_match_686 endp
ELSE
_longest_match_686 endp
ENDIF
ENDIF ENDIF
_TEXT ends _TEXT ends

View File

@@ -6,16 +6,12 @@
* longest_match execute standard C code is wmask != 0x7fff * longest_match execute standard C code is wmask != 0x7fff
* (assembly code is faster with a fixed wmask) * (assembly code is faster with a fixed wmask)
* *
* Read comment at beginning of gvmat32.asm for more information
*/ */
#if defined(ASMV) && (!defined(NOOLDPENTIUMCODE))
#include "deflate.h" #include "deflate.h"
#ifdef ASMV
#define NIL 0
#define UNALIGNED_OK
/* if your C compiler don't add underline before function name, /* if your C compiler don't add underline before function name,
define ADD_UNDERLINE_ASMFUNC */ define ADD_UNDERLINE_ASMFUNC */
#ifdef ADD_UNDERLINE_ASMFUNC #ifdef ADD_UNDERLINE_ASMFUNC
@@ -25,11 +21,6 @@
#endif #endif
void match_init()
{
}
unsigned long cpudetect32(); unsigned long cpudetect32();
uInt longest_match_c( uInt longest_match_c(
@@ -45,162 +36,27 @@ uInt longest_match_686(
deflate_state *s, deflate_state *s,
IPos cur_match); /* current match */ IPos cur_match); /* current match */
static uInt iIsPPro=2;
void match_init ()
{
iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0;
}
uInt longest_match( uInt longest_match(
deflate_state *s, deflate_state *s,
IPos cur_match) /* current match */ IPos cur_match) /* current match */
{ {
static uInt iIsPPro=2; if (iIsPPro!=0)
if ((s->w_mask == 0x7fff) && (iIsPPro==0))
return longest_match_7fff(s,cur_match);
if (iIsPPro==1)
return longest_match_686(s,cur_match); return longest_match_686(s,cur_match);
if (iIsPPro==2) if (s->w_mask != 0x7fff)
iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0; return longest_match_686(s,cur_match);
return longest_match_c(s,cur_match); /* now ((s->w_mask == 0x7fff) && (iIsPPro==0)) */
return longest_match_7fff(s,cur_match);
} }
#endif /* defined(ASMV) && (!defined(NOOLDPENTIUMCODE)) */
uInt longest_match_c(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 */

View File

@@ -1,3 +1,57 @@
;/* inffas32.asm is a hand tuned assembler version of inffast.c -- fast decoding
; *
; * inffas32.asm is derivated from inffas86.c, with translation of assembly code
; *
; * Copyright (C) 1995-2003 Mark Adler
; * For conditions of distribution and use, see copyright notice in zlib.h
; *
; * Copyright (C) 2003 Chris Anderson <christop@charm.net>
; * Please use the copyright conditions above.
; *
; * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from
; * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at
; * the moment. I have successfully compiled and tested this code with gcc2.96,
; * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S
; * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX
; * enabled. I will attempt to merge the MMX code into this version. Newer
; * versions of this and inffast.S can be found at
; * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/
; *
; * 2005 : modification by Gilles Vollant
; */
; For Visual C++ 4.x and higher and ML 6.x and higher
; ml.exe is in directory \MASM611C of Win95 DDK
; ml.exe is also distributed in http://www.masm32.com/masmdl.htm
; and in VC++2003 toolkit at http://msdn.microsoft.com/visualc/vctoolkit2003/
;
;
; compile with command line option
; ml /coff /Zi /c /Flinffas32.lst inffas32.asm
; if you define NO_GZIP (see inflate.h), compile with
; ml /coff /Zi /c /Flinffas32.lst /DNO_GUNZIP inffas32.asm
; zlib122sup is 0 fort zlib 1.2.2.1 and lower
; zlib122sup is 8 fort zlib 1.2.2.2 and more (with addition of dmax and head
; in inflate_state in inflate.h)
zlib1222sup equ 8
IFDEF GUNZIP
INFLATE_MODE_TYPE equ 11
INFLATE_MODE_BAD equ 26
ELSE
IFNDEF NO_GUNZIP
INFLATE_MODE_TYPE equ 11
INFLATE_MODE_BAD equ 26
ELSE
INFLATE_MODE_TYPE equ 3
INFLATE_MODE_BAD equ 17
ENDIF
ENDIF
; 75 "inffast.S" ; 75 "inffast.S"
;FILE "inffast.S" ;FILE "inffast.S"
@@ -84,17 +138,16 @@ dd 2147483647
dd 4294967295 dd 4294967295
mode_state equ 0 ;/* state->mode */ mode_state equ 0 ;/* state->mode */
wsize_state equ 32 ;/* state->wsize */ wsize_state equ (32+zlib1222sup) ;/* state->wsize */
write_state equ (36+4) ;/* state->write */ write_state equ (36+4+zlib1222sup) ;/* state->write */
window_state equ (40+4) ;/* state->window */ window_state equ (40+4+zlib1222sup) ;/* state->window */
hold_state equ (44+4) ;/* state->hold */ hold_state equ (44+4+zlib1222sup) ;/* state->hold */
bits_state equ (48+4) ;/* state->bits */ bits_state equ (48+4+zlib1222sup) ;/* state->bits */
lencode_state equ (64+4) ;/* state->lencode */ lencode_state equ (64+4+zlib1222sup) ;/* state->lencode */
distcode_state equ (68+4) ;/* state->distcode */ distcode_state equ (68+4+zlib1222sup) ;/* state->distcode */
lenbits_state equ (72+4) ;/* state->lenbits */ lenbits_state equ (72+4+zlib1222sup) ;/* state->lenbits */
distbits_state equ (76+4) ;/* state->distbits */ distbits_state equ (76+4+zlib1222sup) ;/* state->distbits */
;;SECTION .text ;;SECTION .text
@@ -868,7 +921,7 @@ L_invalid_distance_code:
mov ecx, invalid_distance_code_msg mov ecx, invalid_distance_code_msg
mov edx,26 mov edx,INFLATE_MODE_BAD
jmp L_update_stream_state jmp L_update_stream_state
L_test_for_end_of_block: L_test_for_end_of_block:
@@ -881,7 +934,7 @@ L_test_for_end_of_block:
jz L_invalid_literal_length_code jz L_invalid_literal_length_code
mov ecx,0 mov ecx,0
mov edx,11 mov edx,INFLATE_MODE_TYPE
jmp L_update_stream_state jmp L_update_stream_state
L_invalid_literal_length_code: L_invalid_literal_length_code:
@@ -891,7 +944,7 @@ L_invalid_literal_length_code:
mov ecx, invalid_literal_length_code_msg mov ecx, invalid_literal_length_code_msg
mov edx,26 mov edx,INFLATE_MODE_BAD
jmp L_update_stream_state jmp L_update_stream_state
L_invalid_distance_too_far: L_invalid_distance_too_far:
@@ -900,7 +953,7 @@ L_invalid_distance_too_far:
mov esi, [esp+44] mov esi, [esp+44]
mov ecx, invalid_distance_too_far_msg mov ecx, invalid_distance_too_far_msg
mov edx,26 mov edx,INFLATE_MODE_BAD
jmp L_update_stream_state jmp L_update_stream_state
L_update_stream_state: L_update_stream_state:
@@ -1026,8 +1079,5 @@ L_done:
pop edi pop edi
ret ret
_TEXT ends _TEXT ends
end end

View File

@@ -1,3 +1,7 @@
Change in 1.01e (12 feb 05)
- Fix in zipOpen2 for globalcomment (Rolf Kalbermatter)
- Fix possible memory leak in unzip.c (Zoran Stevanovic)
Change in 1.01b (20 may 04) Change in 1.01b (20 may 04)
- Integrate patch from Debian package (submited by Mark Brown) - Integrate patch from Debian package (submited by Mark Brown)
- Add tools mztools from Xavier Roche - Add tools mztools from Xavier Roche

View File

@@ -1,9 +1,9 @@
/* crypt.h -- base code for crypt/uncrypt ZIPfile /* crypt.h -- base code for crypt/uncrypt ZIPfile
Version 1.01, May 8th, 2004 Version 1.01e, February 12th, 2005
Copyright (C) 1998-2004 Gilles Vollant Copyright (C) 1998-2005 Gilles Vollant
This code is a modified version of crypting code in Infozip distribution This code is a modified version of crypting code in Infozip distribution

View File

@@ -1,9 +1,9 @@
/* ioapi.c -- IO base function header for compress/uncompress .zip /* ioapi.c -- IO base function header for compress/uncompress .zip
files using zlib + zip or unzip API files using zlib + zip or unzip API
Version 1.01, May 8th, 2004 Version 1.01e, February 12th, 2005
Copyright (C) 1998-2004 Gilles Vollant Copyright (C) 1998-2005 Gilles Vollant
*/ */
#include <stdio.h> #include <stdio.h>

View File

@@ -1,9 +1,9 @@
/* ioapi.h -- IO base function header for compress/uncompress .zip /* ioapi.h -- IO base function header for compress/uncompress .zip
files using zlib + zip or unzip API files using zlib + zip or unzip API
Version 1.01, May 8th, 2004 Version 1.01e, February 12th, 2005
Copyright (C) 1998-2004 Gilles Vollant Copyright (C) 1998-2005 Gilles Vollant
*/ */
#ifndef _ZLIBIOAPI_H #ifndef _ZLIBIOAPI_H

View File

@@ -2,9 +2,9 @@
files using zlib + zip or unzip API files using zlib + zip or unzip API
This IO API version uses the Win32 API (for Microsoft Windows) This IO API version uses the Win32 API (for Microsoft Windows)
Version 1.01, May 8th, 2004 Version 1.01e, February 12th, 2005
Copyright (C) 1998-2004 Gilles Vollant Copyright (C) 1998-2005 Gilles Vollant
*/ */
#include <stdlib.h> #include <stdlib.h>

View File

@@ -2,9 +2,9 @@
files using zlib + zip or unzip API files using zlib + zip or unzip API
This IO API version uses the Win32 API (for Microsoft Windows) This IO API version uses the Win32 API (for Microsoft Windows)
Version 1.01, May 8th, 2004 Version 1.01e, February 12th, 2005
Copyright (C) 1998-2004 Gilles Vollant Copyright (C) 1998-2005 Gilles Vollant
*/ */
#include <windows.h> #include <windows.h>

View File

@@ -1,8 +1,8 @@
/* /*
miniunz.c miniunz.c
Version 1.01b, May 30th, 2004 Version 1.01e, February 12th, 2005
Copyright (C) 1998-2004 Gilles Vollant Copyright (C) 1998-2005 Gilles Vollant
*/ */

View File

@@ -1,8 +1,8 @@
/* /*
minizip.c minizip.c
Version 1.01b, May 30th, 2004 Version 1.01e, February 12th, 2005
Copyright (C) 1998-2004 Gilles Vollant Copyright (C) 1998-2005 Gilles Vollant
*/ */
#include <stdio.h> #include <stdio.h>

View File

@@ -248,7 +248,7 @@ uLong* bytesRecovered;
if (fpOutCD != NULL) { if (fpOutCD != NULL) {
int nRead; int nRead;
char buffer[8192]; char buffer[8192];
while ( (nRead = fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) { while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) {
if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) { if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) {
err = Z_ERRNO; err = Z_ERRNO;
break; break;

View File

@@ -1,7 +1,7 @@
/* unzip.c -- IO for uncompress .zip files using zlib /* unzip.c -- IO for uncompress .zip files using zlib
Version 1.01d, September 22th, 2004 Version 1.01e, February 12th, 2005
Copyright (C) 1998-2004 Gilles Vollant Copyright (C) 1998-2005 Gilles Vollant
Read unzip.h for more info Read unzip.h for more info
*/ */
@@ -1137,7 +1137,10 @@ extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
if (err == Z_OK) if (err == Z_OK)
pfile_in_zip_read_info->stream_initialised=1; pfile_in_zip_read_info->stream_initialised=1;
else else
{
TRYFREE(pfile_in_zip_read_info);
return err; return err;
}
/* windowBits is passed < 0 to tell that there is no zlib header. /* windowBits is passed < 0 to tell that there is no zlib header.
* Note that in this case inflate *requires* an extra "dummy" byte * Note that in this case inflate *requires* an extra "dummy" byte
* after the compressed stream in order to complete decompression and * after the compressed stream in order to complete decompression and

View File

@@ -1,11 +1,13 @@
/* unzip.h -- IO for uncompress .zip files using zlib /* unzip.h -- IO for uncompress .zip files using zlib
Version 1.01, May 8th, 2004 Version 1.01e, February 12th, 2005
Copyright (C) 1998-2004 Gilles Vollant Copyright (C) 1998-2005 Gilles Vollant
This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
WinZip, InfoZip tools and compatible. WinZip, InfoZip tools and compatible.
Encryption and multi volume ZipFile (span) are not supported.
Multi volume ZipFile (span) are not supported.
Encryption compatible with pkzip 2.04g only supported
Old compressions used by old PKZip 1.x are not supported Old compressions used by old PKZip 1.x are not supported

View File

@@ -1,7 +1,10 @@
/* zip.c -- IO on .zip files using zlib /* zip.c -- IO on .zip files using zlib
Version 1.01, May 8th, 2004 Version 1.01e, February 12th, 2005
Copyright (C) 1998-2004 Gilles Vollant 27 Dec 2004 Rolf Kalbermatter
Modification to zipOpen2 to support globalComment retrieval.
Copyright (C) 1998-2005 Gilles Vollant
Read zip.h for more info Read zip.h for more info
*/ */
@@ -143,6 +146,9 @@ typedef struct
uLong begin_pos; /* position of the beginning of the zipfile */ uLong begin_pos; /* position of the beginning of the zipfile */
uLong add_position_when_writting_offset; uLong add_position_when_writting_offset;
uLong number_entry; uLong number_entry;
#ifndef NO_ADDFILEINEXISTINGZIP
char *globalcomment;
#endif
} zip_internal; } zip_internal;
@@ -532,6 +538,7 @@ extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc
/* now we add file in a zipfile */ /* now we add file in a zipfile */
# ifndef NO_ADDFILEINEXISTINGZIP # ifndef NO_ADDFILEINEXISTINGZIP
ziinit.globalcomment = NULL;
if (append == APPEND_STATUS_ADDINZIP) if (append == APPEND_STATUS_ADDINZIP)
{ {
uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
@@ -592,7 +599,7 @@ extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc
if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&offset_central_dir)!=ZIP_OK) if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&offset_central_dir)!=ZIP_OK)
err=ZIP_ERRNO; err=ZIP_ERRNO;
/* zipfile comment length */ /* zipfile global comment length */
if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&size_comment)!=ZIP_OK) if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&size_comment)!=ZIP_OK)
err=ZIP_ERRNO; err=ZIP_ERRNO;
@@ -606,9 +613,19 @@ extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc
return NULL; return NULL;
} }
if (size_comment>0)
{
ziinit.globalcomment = ALLOC(size_comment+1);
if (ziinit.globalcomment)
{
size_comment = ZREAD(ziinit.z_filefunc, ziinit.filestream,ziinit.globalcomment,size_comment);
ziinit.globalcomment[size_comment]=0;
}
}
byte_before_the_zipfile = central_pos - byte_before_the_zipfile = central_pos -
(offset_central_dir+size_central_dir); (offset_central_dir+size_central_dir);
ziinit.add_position_when_writting_offset = byte_before_the_zipfile ; ziinit.add_position_when_writting_offset = byte_before_the_zipfile;
{ {
uLong size_central_dir_to_read = size_central_dir; uLong size_central_dir_to_read = size_central_dir;
@@ -641,10 +658,18 @@ extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc
offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
err=ZIP_ERRNO; err=ZIP_ERRNO;
} }
if (globalcomment)
{
*globalcomment = ziinit.globalcomment;
}
# endif /* !NO_ADDFILEINEXISTINGZIP*/ # endif /* !NO_ADDFILEINEXISTINGZIP*/
if (err != ZIP_OK) if (err != ZIP_OK)
{ {
# ifndef NO_ADDFILEINEXISTINGZIP
TRYFREE(ziinit.globalcomment);
# endif /* !NO_ADDFILEINEXISTINGZIP*/
TRYFREE(zi); TRYFREE(zi);
return NULL; return NULL;
} }
@@ -1112,7 +1137,7 @@ extern int ZEXPORT zipClose (file, global_comment)
zip_internal* zi; zip_internal* zi;
int err = 0; int err = 0;
uLong size_centraldir = 0; uLong size_centraldir = 0;
uLong centraldir_pos_inzip ; uLong centraldir_pos_inzip;
uInt size_global_comment; uInt size_global_comment;
if (file == NULL) if (file == NULL)
return ZIP_PARAMERROR; return ZIP_PARAMERROR;
@@ -1123,12 +1148,15 @@ extern int ZEXPORT zipClose (file, global_comment)
err = zipCloseFileInZip (file); err = zipCloseFileInZip (file);
} }
#ifndef NO_ADDFILEINEXISTINGZIP
if (global_comment==NULL)
global_comment = zi->globalcomment;
#endif
if (global_comment==NULL) if (global_comment==NULL)
size_global_comment = 0; size_global_comment = 0;
else else
size_global_comment = (uInt)strlen(global_comment); size_global_comment = (uInt)strlen(global_comment);
centraldir_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream); centraldir_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream);
if (err==ZIP_OK) if (err==ZIP_OK)
{ {
@@ -1182,6 +1210,9 @@ extern int ZEXPORT zipClose (file, global_comment)
if (err == ZIP_OK) if (err == ZIP_OK)
err = ZIP_ERRNO; err = ZIP_ERRNO;
#ifndef NO_ADDFILEINEXISTINGZIP
TRYFREE(zi->globalcomment);
#endif
TRYFREE(zi); TRYFREE(zi);
return err; return err;

View File

@@ -1,11 +1,12 @@
/* zip.h -- IO for compress .zip files using zlib /* zip.h -- IO for compress .zip files using zlib
Version 1.01, May 8th, 2004 Version 1.01e, February 12th, 2005
Copyright (C) 1998-2004 Gilles Vollant Copyright (C) 1998-2005 Gilles Vollant
This unzip package allow creates .ZIP file, compatible with PKZip 2.04g This unzip package allow creates .ZIP file, compatible with PKZip 2.04g
WinZip, InfoZip tools and compatible. WinZip, InfoZip tools and compatible.
Encryption and multi volume ZipFile (span) are not supported. Multi volume ZipFile (span) are not supported.
Encryption compatible with pkzip 2.04g only supported
Old compressions used by old PKZip 1.x are not supported Old compressions used by old PKZip 1.x are not supported
For uncompress .zip file, look at unzip.h For uncompress .zip file, look at unzip.h

View File

@@ -0,0 +1,18 @@
; rdtsc64.asm
;
; unsigned _int64 myrdtsc();
;
; return the performance rdtsc value, on AMD64/Intel EM64T
;
; compile with :
; ml64.exe" /Flrdtsc64 /c /Zi rdtsc64.asm
;
.code
myrdtsc PROC
rdtsc
shl rdx,32
or rax,rdx
ret
myrdtsc ENDP
END

Binary file not shown.

View File

@@ -4,6 +4,101 @@
#include <windows.h> #include <windows.h>
#include "zlib.h" #include "zlib.h"
void MyDoMinus64(LARGE_INTEGER *R,LARGE_INTEGER A,LARGE_INTEGER B)
{
R->HighPart = A.HighPart - B.HighPart;
if (A.LowPart >= B.LowPart)
R->LowPart = A.LowPart - B.LowPart;
else
{
R->LowPart = A.LowPart - B.LowPart;
R->HighPart --;
}
}
#ifdef _AMD64_
unsigned _int64 myrdtsc();
void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64)
{
// printf("rdtsc = %I64x\n",myrdtsc());
pbeginTime64->QuadPart=myrdtsc();
}
LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf)
{
LARGE_INTEGER LIres;
unsigned _int64 res=myrdtsc()-((unsigned _int64)(beginTime64.QuadPart));
LIres.QuadPart=res;
// printf("rdtsc = %I64x\n",myrdtsc());
return LIres;
}
#else
void myGetRDTSC32(LARGE_INTEGER * pbeginTime64)
{
DWORD dwEdx,dwEax;
_asm
{
rdtsc
mov dwEax,eax
mov dwEdx,edx
}
pbeginTime64->LowPart=dwEax;
pbeginTime64->HighPart=dwEdx;
}
void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64)
{
myGetRDTSC32(pbeginTime64);
}
LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf)
{
LARGE_INTEGER LIres,endTime64;
myGetRDTSC32(&endTime64);
LIres.LowPart=LIres.HighPart=0;
MyDoMinus64(&LIres,endTime64,beginTime64);
return LIres;
}
#endif
void BeginCountPerfCounter(LARGE_INTEGER * pbeginTime64,BOOL fComputeTimeQueryPerf)
{
if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(pbeginTime64)))
{
pbeginTime64->LowPart = GetTickCount();
pbeginTime64->HighPart = 0;
}
}
DWORD GetMsecSincePerfCounter(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf)
{
LARGE_INTEGER endTime64,ticksPerSecond,ticks;
DWORDLONG ticksShifted,tickSecShifted;
DWORD dwLog=16+0;
DWORD dwRet;
if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(&endTime64)))
dwRet = (GetTickCount() - beginTime64.LowPart)*1;
else
{
MyDoMinus64(&ticks,endTime64,beginTime64);
QueryPerformanceFrequency(&ticksPerSecond);
{
ticksShifted = Int64ShrlMod32(*(DWORDLONG*)&ticks,dwLog);
tickSecShifted = Int64ShrlMod32(*(DWORDLONG*)&ticksPerSecond,dwLog);
}
dwRet = (DWORD)((((DWORD)ticksShifted)*1000)/(DWORD)(tickSecShifted));
dwRet *=1;
}
return dwRet;
}
int ReadFileMemory(const char* filename,long* plFileSize,void** pFilePtr) int ReadFileMemory(const char* filename,long* plFileSize,void** pFilePtr)
{ {
FILE* stream; FILE* stream;
@@ -43,7 +138,8 @@ int main(int argc, char *argv[])
unsigned char* CprPtr; unsigned char* CprPtr;
unsigned char* UncprPtr; unsigned char* UncprPtr;
long lSizeCpr,lSizeUncpr; long lSizeCpr,lSizeUncpr;
DWORD dwGetTick; DWORD dwGetTick,dwMsecQP;
LARGE_INTEGER li_qp,li_rdtsc,dwResRdtsc;
if (argc<=1) if (argc<=1)
{ {
@@ -71,9 +167,10 @@ int main(int argc, char *argv[])
lBufferSizeUncpr = lBufferSizeCpr; lBufferSizeUncpr = lBufferSizeCpr;
CprPtr=(unsigned char*)malloc(lBufferSizeCpr + BlockSizeCompress); CprPtr=(unsigned char*)malloc(lBufferSizeCpr + BlockSizeCompress);
UncprPtr=(unsigned char*)malloc(lBufferSizeUncpr + BlockSizeUncompress);
BeginCountPerfCounter(&li_qp,TRUE);
dwGetTick=GetTickCount(); dwGetTick=GetTickCount();
BeginCountRdtsc(&li_rdtsc);
{ {
z_stream zcpr; z_stream zcpr;
int ret=Z_OK; int ret=Z_OK;
@@ -101,11 +198,20 @@ int main(int argc, char *argv[])
lSizeCpr=zcpr.total_out; lSizeCpr=zcpr.total_out;
deflateEnd(&zcpr); deflateEnd(&zcpr);
dwGetTick=GetTickCount()-dwGetTick; dwGetTick=GetTickCount()-dwGetTick;
dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE);
dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE);
printf("total compress size = %u, in %u step\n",lSizeCpr,step); printf("total compress size = %u, in %u step\n",lSizeCpr,step);
printf("time = %u msec = %f sec\n\n",dwGetTick,dwGetTick/(double)1000.); printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.);
printf("defcpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.);
printf("defcpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart);
} }
CprPtr=(unsigned char*)realloc(CprPtr,lSizeCpr);
UncprPtr=(unsigned char*)malloc(lBufferSizeUncpr + BlockSizeUncompress);
BeginCountPerfCounter(&li_qp,TRUE);
dwGetTick=GetTickCount(); dwGetTick=GetTickCount();
BeginCountRdtsc(&li_rdtsc);
{ {
z_stream zcpr; z_stream zcpr;
int ret=Z_OK; int ret=Z_OK;
@@ -133,8 +239,12 @@ int main(int argc, char *argv[])
lSizeUncpr=zcpr.total_out; lSizeUncpr=zcpr.total_out;
inflateEnd(&zcpr); inflateEnd(&zcpr);
dwGetTick=GetTickCount()-dwGetTick; dwGetTick=GetTickCount()-dwGetTick;
dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE);
dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE);
printf("total uncompress size = %u, in %u step\n",lSizeUncpr,step); printf("total uncompress size = %u, in %u step\n",lSizeUncpr,step);
printf("time = %u msec = %f sec\n\n",dwGetTick,dwGetTick/(double)1000.); printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.);
printf("uncpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.);
printf("uncpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart);
} }
if (lSizeUncpr==lFileSize) if (lSizeUncpr==lFileSize)
@@ -145,5 +255,4 @@ int main(int argc, char *argv[])
} }
return 0; return 0;
} }

View File

@@ -0,0 +1,10 @@
To build testzLib with Visual Studio 2005:
copy to a directory file from :
- root of zLib tree
- contrib/testzlib
- contrib/masmx86
- contrib/masmx64
- contrib/vstudio/vc7
and open testzlib8.sln

View File

@@ -0,0 +1,32 @@

Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib8", "testzlib8.vcproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|Win64 (AMD64) = Debug|Win64 (AMD64)
Release|Win32 = Release|Win32
Release|Win64 (AMD64) = Release|Win64 (AMD64)
ReleaseAsm|Win32 = ReleaseAsm|Win32
ReleaseAsm|Win64 (AMD64) = ReleaseAsm|Win64 (AMD64)
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win64 (AMD64).ActiveCfg = Debug|Win64 (AMD64)
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win64 (AMD64).Build.0 = Debug|Win64 (AMD64)
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win64 (AMD64).ActiveCfg = Release|Win64 (AMD64)
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win64 (AMD64).Build.0 = Release|Win64 (AMD64)
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseAsm|Win32.ActiveCfg = ReleaseAsm|Win32
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseAsm|Win32.Build.0 = ReleaseAsm|Win32
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseAsm|Win64 (AMD64).ActiveCfg = ReleaseAsm|Win64 (AMD64)
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseAsm|Win64 (AMD64).Build.0 = ReleaseAsm|Win64 (AMD64)
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,638 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="testzlib8"
ProjectGUID="{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="Win64 (AMD64)"
/>
</Platforms>
<ToolFiles>
<DefaultToolFile
FileName="masm.tool"
/>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="x86\$(ConfigurationName)"
IntermediateDirectory="x86\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="MASM"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
AssemblerOutput="4"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="gvmat32.obj inffas32.obj"
OutputFile="$(OutDir)/testzlib.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/testzlib.pdb"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|Win64 (AMD64)"
OutputDirectory="amd64\$(ConfigurationName)"
IntermediateDirectory="amd64\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="MASM"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
AssemblerOutput="4"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
CommandLine=""
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="gvmat64.obj inffasx64.obj rdtsc64.obj"
OutputFile="$(OutDir)/testzlib.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/testzlib.pdb"
SubSystem="1"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="x86\$(ConfigurationName)"
IntermediateDirectory="x86\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="MASM"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
OmitFramePointers="TRUE"
PreprocessorDefinitions="WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
StringPooling="TRUE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="TRUE"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/testzlib.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
OptimizeForWindows98="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win64 (AMD64)"
OutputDirectory="amd64\$(ConfigurationName)"
IntermediateDirectory="amd64\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="MASM"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
OmitFramePointers="TRUE"
PreprocessorDefinitions="WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
StringPooling="TRUE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="TRUE"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="rdtsc64.obj"
OutputFile="$(OutDir)/testzlib.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
OptimizeForWindows98="1"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="ReleaseAsm|Win32"
OutputDirectory="x86\$(ConfigurationName)"
IntermediateDirectory="x86\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="MASM"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
OmitFramePointers="TRUE"
PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
StringPooling="TRUE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="TRUE"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="gvmat32.obj inffas32.obj"
OutputFile="$(OutDir)/testzlib.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
OptimizeForWindows98="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="ReleaseAsm|Win64 (AMD64)"
OutputDirectory="amd64\$(ConfigurationName)"
IntermediateDirectory="amd64\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
CommandLine=""
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="MASM"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
OmitFramePointers="TRUE"
PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
StringPooling="TRUE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="TRUE"
UsePrecompiledHeader="0"
AssemblerOutput="4"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
CommandLine=""
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="gvmat64.obj inffasx64.obj rdtsc64.obj"
OutputFile="$(OutDir)/testzlib.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
OptimizeForWindows98="1"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
>
<File
RelativePath=".\adler32.c"
>
</File>
<File
RelativePath=".\compress.c"
>
</File>
<File
RelativePath=".\crc32.c"
>
</File>
<File
RelativePath=".\deflate.c"
>
</File>
<File
RelativePath=".\gvmat32c.c"
>
<FileConfiguration
Name="Debug|Win64 (AMD64)"
ExcludedFromBuild="TRUE"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win64 (AMD64)"
ExcludedFromBuild="TRUE"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="ReleaseAsm|Win32"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="ReleaseAsm|Win64 (AMD64)"
ExcludedFromBuild="TRUE"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\infback.c"
>
</File>
<File
RelativePath=".\inffas8664.c"
>
<FileConfiguration
Name="Debug|Win32"
ExcludedFromBuild="TRUE"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="ReleaseAsm|Win32"
ExcludedFromBuild="TRUE"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\inffast.c"
>
</File>
<File
RelativePath=".\inflate.c"
>
</File>
<File
RelativePath=".\inftrees.c"
>
</File>
<File
RelativePath="testzlib.c"
>
</File>
<File
RelativePath=".\trees.c"
>
</File>
<File
RelativePath=".\uncompr.c"
>
</File>
<File
RelativePath=".\zutil.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc"
>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -1,4 +1,4 @@
Building instructions for the DLL versions of Zlib 1.21 Building instructions for the DLL versions of Zlib 1.2.x
======================================================= =======================================================
This directory contains projects that build zlib and minizip using This directory contains projects that build zlib and minizip using

Binary file not shown.

Binary file not shown.

View File

@@ -2,8 +2,8 @@
#define IDR_VERSION1 1 #define IDR_VERSION1 1
IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
FILEVERSION 1,2,2 FILEVERSION 1,2,2,4
PRODUCTVERSION 1,2,2 PRODUCTVERSION 1,2,2,4
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEFLAGS 0 FILEFLAGS 0
FILEOS VOS_DOS_WINDOWS32 FILEOS VOS_DOS_WINDOWS32
@@ -17,7 +17,7 @@ BEGIN
BEGIN BEGIN
VALUE "FileDescription", "zlib data compression library\0" VALUE "FileDescription", "zlib data compression library\0"
VALUE "FileVersion", "1.2.2\0" VALUE "FileVersion", "1.2.2.4\0"
VALUE "InternalName", "zlib\0" VALUE "InternalName", "zlib\0"
VALUE "OriginalFilename", "zlib.dll\0" VALUE "OriginalFilename", "zlib.dll\0"
VALUE "ProductName", "ZLib.DLL\0" VALUE "ProductName", "ZLib.DLL\0"

102
crc32.c
View File

@@ -1,12 +1,12 @@
/* crc32.c -- compute the CRC-32 of a data stream /* crc32.c -- compute the CRC-32 of a data stream
* Copyright (C) 1995-2003 Mark Adler * Copyright (C) 1995-2005 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * 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 * 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 * 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 * 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 * instead of four steps with four exclusive-ors. This results in about a
* of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
*/ */
/* @(#) $Id$ */ /* @(#) $Id$ */
@@ -64,6 +64,11 @@
# define TBLS 1 # define TBLS 1
#endif /* BYFOUR */ #endif /* BYFOUR */
/* Local functions for crc concatenation */
local unsigned long gf2_matrix_times OF((unsigned long *mat,
unsigned long vec));
local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
#ifdef DYNAMIC_CRC_TABLE #ifdef DYNAMIC_CRC_TABLE
local volatile int crc_table_empty = 1; local volatile int crc_table_empty = 1;
@@ -72,7 +77,6 @@ local void make_crc_table OF((void));
#ifdef MAKECRCH #ifdef MAKECRCH
local void write_table OF((FILE *, const unsigned long FAR *)); local void write_table OF((FILE *, const unsigned long FAR *));
#endif /* MAKECRCH */ #endif /* MAKECRCH */
/* /*
Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: 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. 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.
@@ -270,7 +274,7 @@ local unsigned long crc32_little(crc, buf, len)
len--; len--;
} }
buf4 = (const u4 FAR *)buf; buf4 = (const u4 FAR *)(const void FAR *)buf;
while (len >= 32) { while (len >= 32) {
DOLIT32; DOLIT32;
len -= 32; len -= 32;
@@ -310,7 +314,7 @@ local unsigned long crc32_big(crc, buf, len)
len--; len--;
} }
buf4 = (const u4 FAR *)buf; buf4 = (const u4 FAR *)(const void FAR *)buf;
buf4--; buf4--;
while (len >= 32) { while (len >= 32) {
DOBIG32; DOBIG32;
@@ -331,3 +335,89 @@ local unsigned long crc32_big(crc, buf, len)
} }
#endif /* BYFOUR */ #endif /* BYFOUR */
#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
/* ========================================================================= */
local unsigned long gf2_matrix_times(mat, vec)
unsigned long *mat;
unsigned long vec;
{
unsigned long sum;
sum = 0;
while (vec) {
if (vec & 1)
sum ^= *mat;
vec >>= 1;
mat++;
}
return sum;
}
/* ========================================================================= */
local void gf2_matrix_square(square, mat)
unsigned long *square;
unsigned long *mat;
{
int n;
for (n = 0; n < GF2_DIM; n++)
square[n] = gf2_matrix_times(mat, mat[n]);
}
/* ========================================================================= */
uLong ZEXPORT crc32_combine(crc1, crc2, len2)
uLong crc1;
uLong crc2;
z_off_t len2;
{
int n;
unsigned long row;
unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
/* degenerate case */
if (len2 == 0)
return crc1;
/* put operator for one zero bit in odd */
odd[0] = 0xedb88320L; /* CRC-32 polynomial */
row = 1;
for (n = 1; n < GF2_DIM; n++) {
odd[n] = row;
row <<= 1;
}
/* put operator for two zero bits in even */
gf2_matrix_square(even, odd);
/* put operator for four zero bits in odd */
gf2_matrix_square(odd, even);
/* apply len2 zeros to crc1 (first square will put the operator for one
zero byte, eight zero bits, in even) */
do {
/* apply zeros operator for this bit of len2 */
gf2_matrix_square(even, odd);
if (len2 & 1)
crc1 = gf2_matrix_times(even, crc1);
len2 >>= 1;
/* if no more bits set, then done */
if (len2 == 0)
break;
/* another iteration of the loop with odd and even swapped */
gf2_matrix_square(odd, even);
if (len2 & 1)
crc1 = gf2_matrix_times(odd, crc1);
len2 >>= 1;
/* if no more bits set, then done */
} while (len2 != 0);
/* return combined crc */
crc1 ^= crc2;
return crc1;
}

264
deflate.c
View File

@@ -1,5 +1,5 @@
/* deflate.c -- compress data using the deflation algorithm /* deflate.c -- compress data using the deflation algorithm
* Copyright (C) 1995-2004 Jean-loup Gailly. * Copyright (C) 1995-2005 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@@ -52,7 +52,7 @@
#include "deflate.h" #include "deflate.h"
const char deflate_copyright[] = const char deflate_copyright[] =
" deflate 1.2.2 Copyright 1995-2004 Jean-loup Gailly "; " deflate 1.2.2.4 Copyright 1995-2005 Jean-loup Gailly ";
/* /*
If you use the zlib library in a product, an acknowledgment is welcome 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 in the documentation of your product. If for some reason you cannot
@@ -264,7 +264,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
#endif #endif
if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
strategy < 0 || strategy > Z_RLE) { strategy < 0 || strategy > Z_FIXED) {
return Z_STREAM_ERROR; return Z_STREAM_ERROR;
} }
if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */
@@ -274,6 +274,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
s->strm = strm; s->strm = strm;
s->wrap = wrap; s->wrap = wrap;
s->gzhead = Z_NULL;
s->w_bits = windowBits; s->w_bits = windowBits;
s->w_size = 1 << s->w_bits; s->w_size = 1 << s->w_bits;
s->w_mask = s->w_size - 1; s->w_mask = s->w_size - 1;
@@ -333,9 +334,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
if (length < MIN_MATCH) return Z_OK; if (length < MIN_MATCH) return Z_OK;
if (length > MAX_DIST(s)) { if (length > MAX_DIST(s)) {
length = MAX_DIST(s); length = MAX_DIST(s);
#ifndef USE_DICT_HEAD
dictionary += dictLength - length; /* use the tail of the dictionary */ dictionary += dictLength - length; /* use the tail of the dictionary */
#endif
} }
zmemcpy(s->window, dictionary, length); zmemcpy(s->window, dictionary, length);
s->strstart = length; s->strstart = length;
@@ -390,6 +389,17 @@ int ZEXPORT deflateReset (strm)
return Z_OK; return Z_OK;
} }
/* ========================================================================= */
int ZEXPORT deflateSetHeader (strm, head)
z_streamp strm;
gz_headerp head;
{
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
if (strm->state->wrap != 2) return Z_STREAM_ERROR;
strm->state->gzhead = head;
return Z_OK;
}
/* ========================================================================= */ /* ========================================================================= */
int ZEXPORT deflatePrime (strm, bits, value) int ZEXPORT deflatePrime (strm, bits, value)
z_streamp strm; z_streamp strm;
@@ -420,7 +430,7 @@ int ZEXPORT deflateParams(strm, level, strategy)
#else #else
if (level == Z_DEFAULT_COMPRESSION) level = 6; if (level == Z_DEFAULT_COMPRESSION) level = 6;
#endif #endif
if (level < 0 || level > 9 || strategy < 0 || strategy > Z_RLE) { if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
return Z_STREAM_ERROR; return Z_STREAM_ERROR;
} }
func = configuration_table[s->level].func; func = configuration_table[s->level].func;
@@ -440,6 +450,25 @@ int ZEXPORT deflateParams(strm, level, strategy)
return err; return err;
} }
/* ========================================================================= */
int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain)
z_streamp strm;
int good_length;
int max_lazy;
int nice_length;
int max_chain;
{
deflate_state *s;
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
s = strm->state;
s->good_match = good_length;
s->max_lazy_match = max_lazy;
s->nice_match = nice_length;
s->max_chain_length = max_chain;
return Z_OK;
}
/* ========================================================================= /* =========================================================================
* For the default windowBits of 15 and memLevel of 8, this function returns * 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. * a close to exact, as well as small, upper bound on the compressed size.
@@ -548,9 +577,11 @@ int ZEXPORT deflate (strm, flush)
if (s->status == INIT_STATE) { if (s->status == INIT_STATE) {
#ifdef GZIP #ifdef GZIP
if (s->wrap == 2) { if (s->wrap == 2) {
strm->adler = crc32(0L, Z_NULL, 0);
put_byte(s, 31); put_byte(s, 31);
put_byte(s, 139); put_byte(s, 139);
put_byte(s, 8); put_byte(s, 8);
if (s->gzhead == NULL) {
put_byte(s, 0); put_byte(s, 0);
put_byte(s, 0); put_byte(s, 0);
put_byte(s, 0); put_byte(s, 0);
@@ -559,9 +590,34 @@ int ZEXPORT deflate (strm, flush)
put_byte(s, s->level == 9 ? 2 : put_byte(s, s->level == 9 ? 2 :
(s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
4 : 0)); 4 : 0));
put_byte(s, 255); put_byte(s, OS_CODE);
s->status = BUSY_STATE; s->status = BUSY_STATE;
strm->adler = crc32(0L, Z_NULL, 0); }
else {
put_byte(s, (s->gzhead->text ? 1 : 0) +
(s->gzhead->hcrc ? 2 : 0) +
(s->gzhead->extra == Z_NULL ? 0 : 4) +
(s->gzhead->name == Z_NULL ? 0 : 8) +
(s->gzhead->comment == Z_NULL ? 0 : 16)
);
put_byte(s, (Byte)(s->gzhead->time & 0xff));
put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff));
put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff));
put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff));
put_byte(s, s->level == 9 ? 2 :
(s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
4 : 0));
put_byte(s, s->gzhead->os & 0xff);
if (s->gzhead->extra != NULL) {
put_byte(s, s->gzhead->extra_len & 0xff);
put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
}
if (s->gzhead->hcrc)
strm->adler = crc32(strm->adler, s->pending_buf,
s->pending);
s->gzindex = 0;
s->status = EXTRA_STATE;
}
} }
else else
#endif #endif
@@ -592,6 +648,110 @@ int ZEXPORT deflate (strm, flush)
strm->adler = adler32(0L, Z_NULL, 0); strm->adler = adler32(0L, Z_NULL, 0);
} }
} }
#ifdef GZIP
if (s->status == EXTRA_STATE) {
if (s->gzhead->extra != NULL) {
uInt beg = s->pending; /* start of bytes to update crc */
while (s->gzindex < (s->gzhead->extra_len & 0xffff)) {
if (s->pending == s->pending_buf_size) {
if (s->gzhead->hcrc && s->pending > beg)
strm->adler = crc32(strm->adler, s->pending_buf + beg,
s->pending - beg);
flush_pending(strm);
beg = s->pending;
if (s->pending == s->pending_buf_size)
break;
}
put_byte(s, s->gzhead->extra[s->gzindex]);
s->gzindex++;
}
if (s->gzhead->hcrc && s->pending > beg)
strm->adler = crc32(strm->adler, s->pending_buf + beg,
s->pending - beg);
if (s->gzindex == s->gzhead->extra_len) {
s->gzindex = 0;
s->status = NAME_STATE;
}
}
else
s->status = NAME_STATE;
}
if (s->status == NAME_STATE) {
if (s->gzhead->name != NULL) {
uInt beg = s->pending; /* start of bytes to update crc */
int val;
do {
if (s->pending == s->pending_buf_size) {
if (s->gzhead->hcrc && s->pending > beg)
strm->adler = crc32(strm->adler, s->pending_buf + beg,
s->pending - beg);
flush_pending(strm);
beg = s->pending;
if (s->pending == s->pending_buf_size) {
val = 1;
break;
}
}
val = s->gzhead->name[s->gzindex++];
put_byte(s, val);
} while (val != 0);
if (s->gzhead->hcrc && s->pending > beg)
strm->adler = crc32(strm->adler, s->pending_buf + beg,
s->pending - beg);
if (val == 0) {
s->gzindex = 0;
s->status = COMMENT_STATE;
}
}
else
s->status = COMMENT_STATE;
}
if (s->status == COMMENT_STATE) {
if (s->gzhead->comment != NULL) {
uInt beg = s->pending; /* start of bytes to update crc */
int val;
do {
if (s->pending == s->pending_buf_size) {
if (s->gzhead->hcrc && s->pending > beg)
strm->adler = crc32(strm->adler, s->pending_buf + beg,
s->pending - beg);
flush_pending(strm);
beg = s->pending;
if (s->pending == s->pending_buf_size) {
val = 1;
break;
}
}
val = s->gzhead->comment[s->gzindex++];
put_byte(s, val);
} while (val != 0);
if (s->gzhead->hcrc && s->pending > beg)
strm->adler = crc32(strm->adler, s->pending_buf + beg,
s->pending - beg);
if (val == 0)
s->status = HCRC_STATE;
}
else
s->status = HCRC_STATE;
}
if (s->status == HCRC_STATE) {
if (s->gzhead->hcrc) {
if (s->pending + 2 > s->pending_buf_size)
flush_pending(strm);
if (s->pending + 2 <= s->pending_buf_size) {
put_byte(s, (Byte)(strm->adler & 0xff));
put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
strm->adler = crc32(0L, Z_NULL, 0);
s->status = BUSY_STATE;
}
}
else
s->status = BUSY_STATE;
}
#endif
/* Flush as much pending output as possible */ /* Flush as much pending output as possible */
if (s->pending != 0) { if (s->pending != 0) {
@@ -704,7 +864,12 @@ int ZEXPORT deflateEnd (strm)
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
status = strm->state->status; status = strm->state->status;
if (status != INIT_STATE && status != BUSY_STATE && if (status != INIT_STATE &&
status != EXTRA_STATE &&
status != NAME_STATE &&
status != COMMENT_STATE &&
status != HCRC_STATE &&
status != BUSY_STATE &&
status != FINISH_STATE) { status != FINISH_STATE) {
return Z_STREAM_ERROR; return Z_STREAM_ERROR;
} }
@@ -744,12 +909,12 @@ int ZEXPORT deflateCopy (dest, source)
ss = source->state; ss = source->state;
*dest = *source; zmemcpy(dest, source, sizeof(z_stream));
ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
if (ds == Z_NULL) return Z_MEM_ERROR; if (ds == Z_NULL) return Z_MEM_ERROR;
dest->state = (struct internal_state FAR *) ds; dest->state = (struct internal_state FAR *) ds;
*ds = *ss; zmemcpy(ds, ss, sizeof(deflate_state));
ds->strm = dest; ds->strm = dest;
ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
@@ -838,9 +1003,11 @@ local void lm_init (s)
s->match_length = s->prev_length = MIN_MATCH-1; s->match_length = s->prev_length = MIN_MATCH-1;
s->match_available = 0; s->match_available = 0;
s->ins_h = 0; s->ins_h = 0;
#ifndef FASTEST
#ifdef ASMV #ifdef ASMV
match_init(); /* initialize the asm code */ match_init(); /* initialize the asm code */
#endif #endif
#endif
} }
#ifndef FASTEST #ifndef FASTEST
@@ -909,7 +1076,12 @@ local uInt longest_match(s, cur_match)
match = s->window + cur_match; match = s->window + cur_match;
/* Skip to next match if the match length cannot increase /* Skip to next match if the match length cannot increase
* or if the match length is less than 2: * or if the match length is less than 2. Note that the checks below
* for insufficient lookahead only occur occasionally for performance
* reasons. Therefore uninitialized memory will be accessed, and
* conditional jumps will be made that depend on those values.
* However the length of the match is limited to the lookahead, so
* the output of deflate is not affected by the uninitialized values.
*/ */
#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) #if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
/* This code assumes sizeof(unsigned short) == 2. Do not use /* This code assumes sizeof(unsigned short) == 2. Do not use
@@ -1131,6 +1303,7 @@ local void fill_window(s)
later. (Using level 0 permanently is not an optimal usage of later. (Using level 0 permanently is not an optimal usage of
zlib, so we don't care about this pathological case.) zlib, so we don't care about this pathological case.)
*/ */
/* %%% avoid this when Z_RLE */
n = s->hash_size; n = s->hash_size;
p = &s->head[n]; p = &s->head[n];
do { do {
@@ -1309,12 +1482,12 @@ local block_state deflate_fast(s, flush)
* of the string with itself at the start of the input file). * of the string with itself at the start of the input file).
*/ */
#ifdef FASTEST #ifdef FASTEST
if ((s->strategy < Z_HUFFMAN_ONLY) || if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) ||
(s->strategy == Z_RLE && s->strstart - hash_head == 1)) { (s->strategy == Z_RLE && s->strstart - hash_head == 1)) {
s->match_length = longest_match_fast (s, hash_head); s->match_length = longest_match_fast (s, hash_head);
} }
#else #else
if (s->strategy < Z_HUFFMAN_ONLY) { if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
s->match_length = longest_match (s, hash_head); s->match_length = longest_match (s, hash_head);
} else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
s->match_length = longest_match_fast (s, hash_head); s->match_length = longest_match_fast (s, hash_head);
@@ -1418,7 +1591,7 @@ local block_state deflate_slow(s, flush)
* of window index 0 (in particular we have to avoid a match * of window index 0 (in particular we have to avoid a match
* of the string with itself at the start of the input file). * of the string with itself at the start of the input file).
*/ */
if (s->strategy < Z_HUFFMAN_ONLY) { if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
s->match_length = longest_match (s, hash_head); s->match_length = longest_match (s, hash_head);
} else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
s->match_length = longest_match_fast (s, hash_head); s->match_length = longest_match_fast (s, hash_head);
@@ -1500,3 +1673,64 @@ local block_state deflate_slow(s, flush)
return flush == Z_FINISH ? finish_done : block_done; return flush == Z_FINISH ? finish_done : block_done;
} }
#endif /* FASTEST */ #endif /* FASTEST */
#if 0
/* ===========================================================================
* For Z_RLE, simply look for runs of bytes, generate matches only of distance
* one. Do not maintain a hash table. (It will be regenerated if this run of
* deflate switches away from Z_RLE.)
*/
local block_state deflate_rle(s, flush)
deflate_state *s;
int flush;
{
int bflush; /* set if current block must be flushed */
uInt run; /* length of run */
uInt max; /* maximum length of run */
uInt prev; /* byte at distance one to match */
Bytef *scan; /* scan for end of run */
for (;;) {
/* Make sure that we always have enough lookahead, except
* at the end of the input file. We need MAX_MATCH bytes
* for the longest encodable run.
*/
if (s->lookahead < MAX_MATCH) {
fill_window(s);
if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) {
return need_more;
}
if (s->lookahead == 0) break; /* flush the current block */
}
/* See how many times the previous byte repeats */
run = 0;
if (s->strstart > 0) { /* if there is a previous byte, that is */
max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH;
scan = s->window + s->strstart - 1;
prev = *scan++;
do {
if (*scan++ != prev)
break;
} while (++run < max);
}
/* Emit match if have run of MIN_MATCH or longer, else emit literal */
if (run >= MIN_MATCH) {
check_match(s, s->strstart, s->strstart - 1, run);
_tr_tally_dist(s, 1, run - MIN_MATCH, bflush);
s->lookahead -= run;
s->strstart += run;
} 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;
}
#endif

View File

@@ -1,5 +1,5 @@
/* deflate.h -- internal compression state /* deflate.h -- internal compression state
* Copyright (C) 1995-2002 Jean-loup Gailly * Copyright (C) 1995-2004 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@@ -49,6 +49,10 @@
/* All codes must not exceed MAX_BITS bits */ /* All codes must not exceed MAX_BITS bits */
#define INIT_STATE 42 #define INIT_STATE 42
#define EXTRA_STATE 69
#define NAME_STATE 73
#define COMMENT_STATE 91
#define HCRC_STATE 103
#define BUSY_STATE 113 #define BUSY_STATE 113
#define FINISH_STATE 666 #define FINISH_STATE 666
/* Stream status */ /* Stream status */
@@ -93,8 +97,10 @@ typedef struct internal_state {
Bytef *pending_buf; /* output still pending */ Bytef *pending_buf; /* output still pending */
ulg pending_buf_size; /* size of pending_buf */ ulg pending_buf_size; /* size of pending_buf */
Bytef *pending_out; /* next pending byte to output to the stream */ Bytef *pending_out; /* next pending byte to output to the stream */
int pending; /* nb of bytes in the pending buffer */ uInt pending; /* nb of bytes in the pending buffer */
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
gz_headerp gzhead; /* gzip header information to write */
uInt gzindex; /* where in extra, name, or comment */
Byte method; /* STORED (for zip only) or DEFLATED */ Byte method; /* STORED (for zip only) or DEFLATED */
int last_flush; /* value of flush param for previous deflate call */ int last_flush; /* value of flush param for previous deflate call */

View File

@@ -1,5 +1,5 @@
/* example.c -- usage example of the zlib compression library /* example.c -- usage example of the zlib compression library
* Copyright (C) 1995-2003 Jean-loup Gailly. * Copyright (C) 1995-2004 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@@ -11,8 +11,6 @@
#ifdef STDC #ifdef STDC
# include <string.h> # include <string.h>
# include <stdlib.h> # include <stdlib.h>
#else
extern void exit OF((int));
#endif #endif
#if defined(VMS) || defined(RISCOS) #if defined(VMS) || defined(RISCOS)

42
examples/README.examples Normal file
View File

@@ -0,0 +1,42 @@
This directory contains examples of the use of zlib.
fitblk.c
compress just enough input to nearly fill a requested output size
- zlib isn't designed to do this, but fitblk does it anyway
gun.c
uncompress a gzip file
- illustrates the use of inflateBack() for high speed file-to-file
decompression using call-back functions
- is approximately twice as fast as gzip -d
- also provides Unix uncompress functionality, again twice as fast
gzappend.c
append to a gzip file
- illustrates the use of the Z_BLOCK flush parameter for inflate()
- illustrates the use of deflatePrime() to start at any bit
gzjoin.c
join gzip files without recalculating the crc or recompressing
- illustrates the use of the Z_BLOCK flush parameter for inflate()
- illustrates the use of crc32_combine()
gzlog.c
gzlog.h
efficiently maintain a message log file in gzip format
- illustrates use of raw deflate and Z_SYNC_FLUSH
- illustrates use of gzip header extra field
zlib_how.html
painfully comprehensive description of zpipe.c (see below)
- describes in excruciating detail the use of deflate() and inflate()
zpipe.c
reads and writes zlib streams from stdin to stdout
- illustrates the proper use of deflate() and inflate()
- deeply commented in zlib_how.html (see above)
zran.c
index a zlib or gzip stream and randomly access it
- illustrates the use of Z_BLOCK, inflatePrime(), and
inflateSetDictionary() to provide random access

233
examples/fitblk.c Normal file
View File

@@ -0,0 +1,233 @@
/* fitblk.c: example of fitting compressed output to a specified size
Not copyrighted -- provided to the public domain
Version 1.1 25 November 2004 Mark Adler */
/* Version history:
1.0 24 Nov 2004 First version
1.1 25 Nov 2004 Change deflateInit2() to deflateInit()
Use fixed-size, stack-allocated raw buffers
Simplify code moving compression to subroutines
Use assert() for internal errors
Add detailed description of approach
*/
/* Approach to just fitting a requested compressed size:
fitblk performs three compression passes on a portion of the input
data in order to determine how much of that input will compress to
nearly the requested output block size. The first pass generates
enough deflate blocks to produce output to fill the requested
output size plus a specfied excess amount (see the EXCESS define
below). The last deflate block may go quite a bit past that, but
is discarded. The second pass decompresses and recompresses just
the compressed data that fit in the requested plus excess sized
buffer. The deflate process is terminated after that amount of
input, which is less than the amount consumed on the first pass.
The last deflate block of the result will be of a comparable size
to the final product, so that the header for that deflate block and
the compression ratio for that block will be about the same as in
the final product. The third compression pass decompresses the
result of the second step, but only the compressed data up to the
requested size minus an amount to allow the compressed stream to
complete (see the MARGIN define below). That will result in a
final compressed stream whose length is less than or equal to the
requested size. Assuming sufficient input and a requested size
greater than a few hundred bytes, the shortfall will typically be
less than ten bytes.
If the input is short enough that the first compression completes
before filling the requested output size, then that compressed
stream is return with no recompression.
EXCESS is chosen to be just greater than the shortfall seen in a
two pass approach similar to the above. That shortfall is due to
the last deflate block compressing more efficiently with a smaller
header on the second pass. EXCESS is set to be large enough so
that there is enough uncompressed data for the second pass to fill
out the requested size, and small enough so that the final deflate
block of the second pass will be close in size to the final deflate
block of the third and final pass. MARGIN is chosen to be just
large enough to assure that the final compression has enough room
to complete in all cases.
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "zlib.h"
#define local static
/* print nastygram and leave */
local void quit(char *why)
{
fprintf(stderr, "fitblk abort: %s\n", why);
exit(1);
}
#define RAWLEN 4096 /* intermediate uncompressed buffer size */
/* compress from file to def until provided buffer is full or end of
input reached; return last deflate() return value, or Z_ERRNO if
there was read error on the file */
local int partcompress(FILE *in, z_streamp def)
{
int ret, flush;
unsigned char raw[RAWLEN];
flush = Z_NO_FLUSH;
do {
def->avail_in = fread(raw, 1, RAWLEN, in);
if (ferror(in))
return Z_ERRNO;
def->next_in = raw;
if (feof(in))
flush = Z_FINISH;
ret = deflate(def, flush);
assert(ret != Z_STREAM_ERROR);
} while (def->avail_out != 0 && flush == Z_NO_FLUSH);
return ret;
}
/* recompress from inf's input to def's output; the input for inf and
the output for def are set in those structures before calling;
return last deflate() return value, or Z_MEM_ERROR if inflate()
was not able to allocate enough memory when it needed to */
local int recompress(z_streamp inf, z_streamp def)
{
int ret, flush;
unsigned char raw[RAWLEN];
flush = Z_NO_FLUSH;
do {
/* decompress */
inf->avail_out = RAWLEN;
inf->next_out = raw;
ret = inflate(inf, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR && ret != Z_DATA_ERROR &&
ret != Z_NEED_DICT);
if (ret == Z_MEM_ERROR)
return ret;
/* compress what was decompresed until done or no room */
def->avail_in = RAWLEN - inf->avail_out;
def->next_in = raw;
if (inf->avail_out != 0)
flush = Z_FINISH;
ret = deflate(def, flush);
assert(ret != Z_STREAM_ERROR);
} while (ret != Z_STREAM_END && def->avail_out != 0);
return ret;
}
#define EXCESS 256 /* empirically determined stream overage */
#define MARGIN 8 /* amount to back off for completion */
/* compress from stdin to fixed-size block on stdout */
int main(int argc, char **argv)
{
int ret; /* return code */
unsigned size; /* requested fixed output block size */
unsigned have; /* bytes written by deflate() call */
unsigned char *blk; /* intermediate and final stream */
unsigned char *tmp; /* close to desired size stream */
z_stream def, inf; /* zlib deflate and inflate states */
/* get requested output size */
if (argc != 2)
quit("need one argument: size of output block");
ret = strtol(argv[1], argv + 1, 10);
if (argv[1][0] != 0)
quit("argument must be a number");
if (ret < 8) /* 8 is minimum zlib stream size */
quit("need positive size of 8 or greater");
size = (unsigned)ret;
/* allocate memory for buffers and compression engine */
blk = malloc(size + EXCESS);
def.zalloc = Z_NULL;
def.zfree = Z_NULL;
def.opaque = Z_NULL;
ret = deflateInit(&def, Z_DEFAULT_COMPRESSION);
if (ret != Z_OK || blk == NULL)
quit("out of memory");
/* compress from stdin until output full, or no more input */
def.avail_out = size + EXCESS;
def.next_out = blk;
ret = partcompress(stdin, &def);
if (ret == Z_ERRNO)
quit("error reading input");
/* if it all fit, then size was undersubscribed -- done! */
if (ret == Z_STREAM_END && def.avail_out >= EXCESS) {
/* write block to stdout */
have = size + EXCESS - def.avail_out;
if (fwrite(blk, 1, have, stdout) != have || ferror(stdout))
quit("error writing output");
/* clean up and print results to stderr */
ret = deflateEnd(&def);
assert(ret != Z_STREAM_ERROR);
free(blk);
fprintf(stderr,
"%u bytes unused out of %u requested (all input)\n",
size - have, size);
return 0;
}
/* it didn't all fit -- set up for recompression */
inf.zalloc = Z_NULL;
inf.zfree = Z_NULL;
inf.opaque = Z_NULL;
inf.avail_in = 0;
inf.next_in = Z_NULL;
ret = inflateInit(&inf);
tmp = malloc(size + EXCESS);
if (ret != Z_OK || tmp == NULL)
quit("out of memory");
ret = deflateReset(&def);
assert(ret != Z_STREAM_ERROR);
/* do first recompression close to the right amount */
inf.avail_in = size + EXCESS;
inf.next_in = blk;
def.avail_out = size + EXCESS;
def.next_out = tmp;
ret = recompress(&inf, &def);
if (ret == Z_MEM_ERROR)
quit("out of memory");
/* set up for next reocmpression */
ret = inflateReset(&inf);
assert(ret != Z_STREAM_ERROR);
ret = deflateReset(&def);
assert(ret != Z_STREAM_ERROR);
/* do second and final recompression (third compression) */
inf.avail_in = size - MARGIN; /* assure stream will complete */
inf.next_in = tmp;
def.avail_out = size;
def.next_out = blk;
ret = recompress(&inf, &def);
if (ret == Z_MEM_ERROR)
quit("out of memory");
assert(ret == Z_STREAM_END); /* otherwise MARGIN too small */
/* done -- write block to stdout */
have = size - def.avail_out;
if (fwrite(blk, 1, have, stdout) != have || ferror(stdout))
quit("error writing output");
/* clean up and print results to stderr */
free(tmp);
ret = inflateEnd(&inf);
assert(ret != Z_STREAM_ERROR);
ret = deflateEnd(&def);
assert(ret != Z_STREAM_ERROR);
free(blk);
fprintf(stderr,
"%u bytes unused out of %u requested (%lu input)\n",
size - have, size, def.total_in);
return 0;
}

693
examples/gun.c Normal file
View File

@@ -0,0 +1,693 @@
/* gun.c -- simple gunzip to give an example of the use of inflateBack()
* Copyright (C) 2003, 2005 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
Version 1.3 12 June 2005 Mark Adler */
/* Version history:
1.0 16 Feb 2003 First version for testing of inflateBack()
1.1 21 Feb 2005 Decompress concatenated gzip streams
Remove use of "this" variable (C++ keyword)
Fix return value for in()
Improve allocation failure checking
Add typecasting for void * structures
Add -h option for command version and usage
Add a bunch of comments
1.2 20 Mar 2005 Add Unix compress (LZW) decompression
Copy file attributes from input file to output file
1.3 12 Jun 2005 Add casts for error messages [Oberhumer]
*/
/*
gun [ -t ] [ name ... ]
decompresses the data in the named gzip files. If no arguments are given,
gun will decompress from stdin to stdout. The names must end in .gz, -gz,
.z, -z, _z, or .Z. The uncompressed data will be written to a file name
with the suffix stripped. On success, the original file is deleted. On
failure, the output file is deleted. For most failures, the command will
continue to process the remaining names on the command line. A memory
allocation failure will abort the command. If -t is specified, then the
listed files or stdin will be tested as gzip files for integrity (without
checking for a proper suffix), no output will be written, and no files
will be deleted.
Like gzip, gun allows concatenated gzip streams and will decompress them,
writing all of the uncompressed data to the output. Unlike gzip, gun allows
an empty file on input, and will produce no error writing an empty output
file.
gun will also decompress files made by Unix compress, which uses LZW
compression. These files are automatically detected by virtue of their
magic header bytes. Since the end of Unix compress stream is marked by the
end-of-file, they cannot be concantenated. If a Unix compress stream is
encountered in an input file, it is the last stream in that file.
Like gunzip and uncompress, the file attributes of the orignal compressed
file are maintained in the final uncompressed file, to the extent that the
user permissions allow it.
On my Mac OS X PowerPC G4, gun is almost twice as fast as gunzip (version
1.2.4) is on the same file, when gun is linked with zlib 1.2.2. Also the
LZW decompression provided by gun is about twice as fast as the standard
Unix uncompress command.
*/
/* external functions and related types and constants */
#include <stdio.h> /* fprintf() */
#include <stdlib.h> /* malloc(), free() */
#include <string.h> /* strerror(), strcmp(), strlen(), memcpy() */
#include <errno.h> /* errno */
#include <fcntl.h> /* open() */
#include <unistd.h> /* read(), write(), close(), chown(), unlink() */
#include <sys/types.h>
#include <sys/stat.h> /* stat(), chmod() */
#include <utime.h> /* utime() */
#include "zlib.h" /* inflateBackInit(), inflateBack(), */
/* inflateBackEnd(), crc32() */
/* function declaration */
#define local static
/* buffer constants */
#define SIZE 32768U /* input and output buffer sizes */
#define PIECE 16384 /* limits i/o chunks for 16-bit int case */
/* structure for infback() to pass to input function in() -- it maintains the
input file and a buffer of size SIZE */
struct ind {
int infile;
unsigned char *inbuf;
};
/* Load input buffer, assumed to be empty, and return bytes loaded and a
pointer to them. read() is called until the buffer is full, or until it
returns end-of-file or error. Return 0 on error. */
local unsigned in(void *in_desc, unsigned char **buf)
{
int ret;
unsigned len;
unsigned char *next;
struct ind *me = (struct ind *)in_desc;
next = me->inbuf;
*buf = next;
len = 0;
do {
ret = PIECE;
if ((unsigned)ret > SIZE - len)
ret = (int)(SIZE - len);
ret = (int)read(me->infile, next, ret);
if (ret == -1) {
len = 0;
break;
}
next += ret;
len += ret;
} while (ret != 0 && len < SIZE);
return len;
}
/* structure for infback() to pass to output function out() -- it maintains the
output file, a running CRC-32 check on the output and the total number of
bytes output, both for checking against the gzip trailer. (The length in
the gzip trailer is stored modulo 2^32, so it's ok if a long is 32 bits and
the output is greater than 4 GB.) */
struct outd {
int outfile;
int check; /* true if checking crc and total */
unsigned long crc;
unsigned long total;
};
/* Write output buffer and update the CRC-32 and total bytes written. write()
is called until all of the output is written or an error is encountered.
On success out() returns 0. For a write failure, out() returns 1. If the
output file descriptor is -1, then nothing is written.
*/
local int out(void *out_desc, unsigned char *buf, unsigned len)
{
int ret;
struct outd *me = (struct outd *)out_desc;
if (me->check) {
me->crc = crc32(me->crc, buf, len);
me->total += len;
}
if (me->outfile != -1)
do {
ret = PIECE;
if ((unsigned)ret > len)
ret = (int)len;
ret = (int)write(me->outfile, buf, ret);
if (ret == -1)
return 1;
buf += ret;
len -= ret;
} while (len != 0);
return 0;
}
/* next input byte macro for use inside lunpipe() and gunpipe() */
#define NEXT() (have ? 0 : (have = in(indp, &next)), \
last = have ? (have--, (int)(*next++)) : -1)
/* memory for gunpipe() and lunpipe() --
the first 256 entries of prefix[] and suffix[] are never used, could
have offset the index, but it's faster to waste the memory */
unsigned char inbuf[SIZE]; /* input buffer */
unsigned char outbuf[SIZE]; /* output buffer */
unsigned short prefix[65536]; /* index to LZW prefix string */
unsigned char suffix[65536]; /* one-character LZW suffix */
unsigned char match[65280 + 2]; /* buffer for reversed match or gzip
32K sliding window */
/* throw out what's left in the current bits byte buffer (this is a vestigial
aspect of the compressed data format derived from an implementation that
made use of a special VAX machine instruction!) */
#define FLUSHCODE() \
do { \
left = 0; \
rem = 0; \
if (chunk > have) { \
chunk -= have; \
have = 0; \
if (NEXT() == -1) \
break; \
chunk--; \
if (chunk > have) { \
chunk = have = 0; \
break; \
} \
} \
have -= chunk; \
next += chunk; \
chunk = 0; \
} while (0)
/* Decompress a compress (LZW) file from indp to outfile. The compress magic
header (two bytes) has already been read and verified. There are have bytes
of buffered input at next. strm is used for passing error information back
to gunpipe().
lunpipe() will return Z_OK on success, Z_BUF_ERROR for an unexpected end of
file, read error, or write error (a write error indicated by strm->next_in
not equal to Z_NULL), or Z_DATA_ERROR for invalid input.
*/
local int lunpipe(unsigned have, unsigned char *next, struct ind *indp,
int outfile, z_stream *strm)
{
int last; /* last byte read by NEXT(), or -1 if EOF */
int chunk; /* bytes left in current chunk */
int left; /* bits left in rem */
unsigned rem; /* unused bits from input */
int bits; /* current bits per code */
unsigned code; /* code, table traversal index */
unsigned mask; /* mask for current bits codes */
int max; /* maximum bits per code for this stream */
int flags; /* compress flags, then block compress flag */
unsigned end; /* last valid entry in prefix/suffix tables */
unsigned temp; /* current code */
unsigned prev; /* previous code */
unsigned final; /* last character written for previous code */
unsigned stack; /* next position for reversed string */
unsigned outcnt; /* bytes in output buffer */
struct outd outd; /* output structure */
/* set up output */
outd.outfile = outfile;
outd.check = 0;
/* process remainder of compress header -- a flags byte */
flags = NEXT();
if (last == -1)
return Z_BUF_ERROR;
if (flags & 0x60) {
strm->msg = (char *)"unknown lzw flags set";
return Z_DATA_ERROR;
}
max = flags & 0x1f;
if (max < 9 || max > 16) {
strm->msg = (char *)"lzw bits out of range";
return Z_DATA_ERROR;
}
if (max == 9) /* 9 doesn't really mean 9 */
max = 10;
flags &= 0x80; /* true if block compress */
/* clear table */
bits = 9;
mask = 0x1ff;
end = flags ? 256 : 255;
/* set up: get first 9-bit code, which is the first decompressed byte, but
don't create a table entry until the next code */
if (NEXT() == -1) /* no compressed data is ok */
return Z_OK;
final = prev = (unsigned)last; /* low 8 bits of code */
if (NEXT() == -1) /* missing a bit */
return Z_BUF_ERROR;
if (last & 1) { /* code must be < 256 */
strm->msg = (char *)"invalid lzw code";
return Z_DATA_ERROR;
}
rem = (unsigned)last >> 1; /* remaining 7 bits */
left = 7;
chunk = bits - 2; /* 7 bytes left in this chunk */
outbuf[0] = (unsigned char)final; /* write first decompressed byte */
outcnt = 1;
/* decode codes */
stack = 0;
for (;;) {
/* if the table will be full after this, increment the code size */
if (end >= mask && bits < max) {
FLUSHCODE();
bits++;
mask <<= 1;
mask++;
}
/* get a code of length bits */
if (chunk == 0) /* decrement chunk modulo bits */
chunk = bits;
code = rem; /* low bits of code */
if (NEXT() == -1) { /* EOF is end of compressed data */
/* write remaining buffered output */
if (outcnt && out(&outd, outbuf, outcnt)) {
strm->next_in = outbuf; /* signal write error */
return Z_BUF_ERROR;
}
return Z_OK;
}
code += (unsigned)last << left; /* middle (or high) bits of code */
left += 8;
chunk--;
if (bits > left) { /* need more bits */
if (NEXT() == -1) /* can't end in middle of code */
return Z_BUF_ERROR;
code += (unsigned)last << left; /* high bits of code */
left += 8;
chunk--;
}
code &= mask; /* mask to current code length */
left -= bits; /* number of unused bits */
rem = (unsigned)last >> (8 - left); /* unused bits from last byte */
/* process clear code (256) */
if (code == 256 && flags) {
FLUSHCODE();
bits = 9; /* initialize bits and mask */
mask = 0x1ff;
end = 255; /* empty table */
continue; /* get next code */
}
/* special code to reuse last match */
temp = code; /* save the current code */
if (code > end) {
/* Be picky on the allowed code here, and make sure that the code
we drop through (prev) will be a valid index so that random
input does not cause an exception. The code != end + 1 check is
empirically derived, and not checked in the original uncompress
code. If this ever causes a problem, that check could be safely
removed. Leaving this check in greatly improves gun's ability
to detect random or corrupted input after a compress header.
In any case, the prev > end check must be retained. */
if (code != end + 1 || prev > end) {
strm->msg = (char *)"invalid lzw code";
return Z_DATA_ERROR;
}
match[stack++] = (unsigned char)final;
code = prev;
}
/* walk through linked list to generate output in reverse order */
while (code >= 256) {
match[stack++] = suffix[code];
code = prefix[code];
}
match[stack++] = (unsigned char)code;
final = code;
/* link new table entry */
if (end < mask) {
end++;
prefix[end] = (unsigned short)prev;
suffix[end] = (unsigned char)final;
}
/* set previous code for next iteration */
prev = temp;
/* write output in forward order */
while (stack > SIZE - outcnt) {
while (outcnt < SIZE)
outbuf[outcnt++] = match[--stack];
if (out(&outd, outbuf, outcnt)) {
strm->next_in = outbuf; /* signal write error */
return Z_BUF_ERROR;
}
outcnt = 0;
}
do {
outbuf[outcnt++] = match[--stack];
} while (stack);
/* loop for next code with final and prev as the last match, rem and
left provide the first 0..7 bits of the next code, end is the last
valid table entry */
}
}
/* Decompress a gzip file from infile to outfile. strm is assumed to have been
successfully initialized with inflateBackInit(). The input file may consist
of a series of gzip streams, in which case all of them will be decompressed
to the output file. If outfile is -1, then the gzip stream(s) integrity is
checked and nothing is written.
The return value is a zlib error code: Z_MEM_ERROR if out of memory,
Z_DATA_ERROR if the header or the compressed data is invalid, or if the
trailer CRC-32 check or length doesn't match, Z_BUF_ERROR if the input ends
prematurely or a write error occurs, or Z_ERRNO if junk (not a another gzip
stream) follows a valid gzip stream.
*/
local int gunpipe(z_stream *strm, int infile, int outfile)
{
int ret, first, last;
unsigned have, flags, len;
unsigned char *next;
struct ind ind, *indp;
struct outd outd;
/* setup input buffer */
ind.infile = infile;
ind.inbuf = inbuf;
indp = &ind;
/* decompress concatenated gzip streams */
have = 0; /* no input data read in yet */
first = 1; /* looking for first gzip header */
strm->next_in = Z_NULL; /* so Z_BUF_ERROR means EOF */
for (;;) {
/* look for the two magic header bytes for a gzip stream */
if (NEXT() == -1) {
ret = Z_OK;
break; /* empty gzip stream is ok */
}
if (last != 31 || (NEXT() != 139 && last != 157)) {
strm->msg = (char *)"incorrect header check";
ret = first ? Z_DATA_ERROR : Z_ERRNO;
break; /* not a gzip or compress header */
}
first = 0; /* next non-header is junk */
/* process a compress (LZW) file -- can't be concatenated after this */
if (last == 157) {
ret = lunpipe(have, next, indp, outfile, strm);
break;
}
/* process remainder of gzip header */
ret = Z_BUF_ERROR;
if (NEXT() != 8) { /* only deflate method allowed */
if (last == -1) break;
strm->msg = (char *)"unknown compression method";
ret = Z_DATA_ERROR;
break;
}
flags = NEXT(); /* header flags */
NEXT(); /* discard mod time, xflgs, os */
NEXT();
NEXT();
NEXT();
NEXT();
NEXT();
if (last == -1) break;
if (flags & 0xe0) {
strm->msg = (char *)"unknown header flags set";
ret = Z_DATA_ERROR;
break;
}
if (flags & 4) { /* extra field */
len = NEXT();
len += (unsigned)(NEXT()) << 8;
if (last == -1) break;
while (len > have) {
len -= have;
have = 0;
if (NEXT() == -1) break;
len--;
}
if (last == -1) break;
have -= len;
next += len;
}
if (flags & 8) /* file name */
while (NEXT() != 0 && last != -1)
;
if (flags & 16) /* comment */
while (NEXT() != 0 && last != -1)
;
if (flags & 2) { /* header crc */
NEXT();
NEXT();
}
if (last == -1) break;
/* set up output */
outd.outfile = outfile;
outd.check = 1;
outd.crc = crc32(0L, Z_NULL, 0);
outd.total = 0;
/* decompress data to output */
strm->next_in = next;
strm->avail_in = have;
ret = inflateBack(strm, in, indp, out, &outd);
if (ret != Z_STREAM_END) break;
next = strm->next_in;
have = strm->avail_in;
strm->next_in = Z_NULL; /* so Z_BUF_ERROR means EOF */
/* check trailer */
ret = Z_BUF_ERROR;
if (NEXT() != (outd.crc & 0xff) ||
NEXT() != ((outd.crc >> 8) & 0xff) ||
NEXT() != ((outd.crc >> 16) & 0xff) ||
NEXT() != ((outd.crc >> 24) & 0xff)) {
/* crc error */
if (last != -1) {
strm->msg = (char *)"incorrect data check";
ret = Z_DATA_ERROR;
}
break;
}
if (NEXT() != (outd.total & 0xff) ||
NEXT() != ((outd.total >> 8) & 0xff) ||
NEXT() != ((outd.total >> 16) & 0xff) ||
NEXT() != ((outd.total >> 24) & 0xff)) {
/* length error */
if (last != -1) {
strm->msg = (char *)"incorrect length check";
ret = Z_DATA_ERROR;
}
break;
}
/* go back and look for another gzip stream */
}
/* clean up and return */
return ret;
}
/* Copy file attributes, from -> to, as best we can. This is best effort, so
no errors are reported. The mode bits, including suid, sgid, and the sticky
bit are copied (if allowed), the owner's user id and group id are copied
(again if allowed), and the access and modify times are copied. */
local void copymeta(char *from, char *to)
{
struct stat was;
struct utimbuf when;
/* get all of from's Unix meta data, return if not a regular file */
if (stat(from, &was) != 0 || (was.st_mode & S_IFMT) != S_IFREG)
return;
/* set to's mode bits, ignore errors */
(void)chmod(to, was.st_mode & 07777);
/* copy owner's user and group, ignore errors */
(void)chown(to, was.st_uid, was.st_gid);
/* copy access and modify times, ignore errors */
when.actime = was.st_atime;
when.modtime = was.st_mtime;
(void)utime(to, &when);
}
/* Decompress the file inname to the file outnname, of if test is true, just
decompress without writing and check the gzip trailer for integrity. If
inname is NULL or an empty string, read from stdin. If outname is NULL or
an empty string, write to stdout. strm is a pre-initialized inflateBack
structure. When appropriate, copy the file attributes from inname to
outname.
gunzip() returns 1 if there is an out-of-memory error or an unexpected
return code from gunpipe(). Otherwise it returns 0.
*/
local int gunzip(z_stream *strm, char *inname, char *outname, int test)
{
int ret;
int infile, outfile;
/* open files */
if (inname == NULL || *inname == 0) {
inname = "-";
infile = 0; /* stdin */
}
else {
infile = open(inname, O_RDONLY, 0);
if (infile == -1) {
fprintf(stderr, "gun cannot open %s\n", inname);
return 0;
}
}
if (test)
outfile = -1;
else if (outname == NULL || *outname == 0) {
outname = "-";
outfile = 1; /* stdout */
}
else {
outfile = open(outname, O_CREAT | O_TRUNC | O_WRONLY, 0666);
if (outfile == -1) {
close(infile);
fprintf(stderr, "gun cannot create %s\n", outname);
return 0;
}
}
errno = 0;
/* decompress */
ret = gunpipe(strm, infile, outfile);
if (outfile > 2) close(outfile);
if (infile > 2) close(infile);
/* interpret result */
switch (ret) {
case Z_OK:
case Z_ERRNO:
if (infile > 2 && outfile > 2) {
copymeta(inname, outname); /* copy attributes */
unlink(inname);
}
if (ret == Z_ERRNO)
fprintf(stderr, "gun warning: trailing garbage ignored in %s\n",
inname);
break;
case Z_DATA_ERROR:
if (outfile > 2) unlink(outname);
fprintf(stderr, "gun data error on %s: %s\n", inname, strm->msg);
break;
case Z_MEM_ERROR:
if (outfile > 2) unlink(outname);
fprintf(stderr, "gun out of memory error--aborting\n");
return 1;
case Z_BUF_ERROR:
if (outfile > 2) unlink(outname);
if (strm->next_in != Z_NULL) {
fprintf(stderr, "gun write error on %s: %s\n",
outname, strerror(errno));
}
else if (errno) {
fprintf(stderr, "gun read error on %s: %s\n",
inname, strerror(errno));
}
else {
fprintf(stderr, "gun unexpected end of file on %s\n",
inname);
}
break;
default:
if (outfile > 2) unlink(outname);
fprintf(stderr, "gun internal error--aborting\n");
return 1;
}
return 0;
}
/* Process the gun command line arguments. See the command syntax near the
beginning of this source file. */
int main(int argc, char **argv)
{
int ret, len, test;
char *outname;
unsigned char *window;
z_stream strm;
/* initialize inflateBack state for repeated use */
window = match; /* reuse LZW match buffer */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
ret = inflateBackInit(&strm, 15, window);
if (ret != Z_OK) {
fprintf(stderr, "gun out of memory error--aborting\n");
return 1;
}
/* decompress each file to the same name with the suffix removed */
argc--;
argv++;
test = 0;
if (argc && strcmp(*argv, "-h") == 0) {
fprintf(stderr, "gun 1.3 (12 Jun 2005)\n");
fprintf(stderr, "Copyright (c) 2005 Mark Adler\n");
fprintf(stderr, "usage: gun [-t] [file1.gz [file2.Z ...]]\n");
return 0;
}
if (argc && strcmp(*argv, "-t") == 0) {
test = 1;
argc--;
argv++;
}
if (argc)
do {
if (test)
outname = NULL;
else {
len = (int)strlen(*argv);
if (strcmp(*argv + len - 3, ".gz") == 0 ||
strcmp(*argv + len - 3, "-gz") == 0)
len -= 3;
else if (strcmp(*argv + len - 2, ".z") == 0 ||
strcmp(*argv + len - 2, "-z") == 0 ||
strcmp(*argv + len - 2, "_z") == 0 ||
strcmp(*argv + len - 2, ".Z") == 0)
len -= 2;
else {
fprintf(stderr, "gun error: no gz type on %s--skipping\n",
*argv);
continue;
}
outname = malloc(len + 1);
if (outname == NULL) {
fprintf(stderr, "gun out of memory error--aborting\n");
ret = 1;
break;
}
memcpy(outname, *argv, len);
outname[len] = 0;
}
ret = gunzip(&strm, *argv, outname, test);
if (outname != NULL) free(outname);
if (ret) break;
} while (argv++, --argc);
else
ret = gunzip(&strm, NULL, NULL, test);
/* clean up */
inflateBackEnd(&strm);
return ret;
}

448
examples/gzjoin.c Normal file
View File

@@ -0,0 +1,448 @@
/* gzjoin -- command to join gzip files into one gzip file
Copyright (C) 2004 Mark Adler, all rights reserved
version 1.0, 11 Dec 2004
This software is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Mark Adler madler@alumni.caltech.edu
*/
/*
* Change history:
*
* 1.0 11 Dec 2004 - First version
* 1.1 12 Jun 2005 - Changed ssize_t to long for portability
*/
/*
gzjoin takes one or more gzip files on the command line and writes out a
single gzip file that will uncompress to the concatenation of the
uncompressed data from the individual gzip files. gzjoin does this without
having to recompress any of the data and without having to calculate a new
crc32 for the concatenated uncompressed data. gzjoin does however have to
decompress all of the input data in order to find the bits in the compressed
data that need to be modified to concatenate the streams.
gzjoin does not do an integrity check on the input gzip files other than
checking the gzip header and decompressing the compressed data. They are
otherwise assumed to be complete and correct.
Each joint between gzip files removes at least 18 bytes of previous trailer
and subsequent header, and inserts an average of about three bytes to the
compressed data in order to connect the streams. The output gzip file
has a minimal ten-byte gzip header with no file name or modification time.
This program was written to illustrate the use of the Z_BLOCK option of
inflate() and the crc32_combine() function. gzjoin will not compile with
versions of zlib earlier than 1.2.3.
*/
#include <stdio.h> /* fputs(), fprintf(), fwrite(), putc() */
#include <stdlib.h> /* exit(), malloc(), free() */
#include <fcntl.h> /* open() */
#include <unistd.h> /* close(), read(), lseek() */
#include "zlib.h"
/* crc32(), crc32_combine(), inflateInit2(), inflate(), inflateEnd() */
#define local static
/* exit with an error (return a value to allow use in an expression) */
local int bail(char *why1, char *why2)
{
fprintf(stderr, "gzjoin error: %s%s, output incomplete\n", why1, why2);
exit(1);
return 0;
}
/* -- simple buffered file input with access to the buffer -- */
#define CHUNK 32768 /* must be a power of two and fit in unsigned */
/* bin buffered input file type */
typedef struct {
char *name; /* name of file for error messages */
int fd; /* file descriptor */
unsigned left; /* bytes remaining at next */
unsigned char *next; /* next byte to read */
unsigned char *buf; /* allocated buffer of length CHUNK */
} bin;
/* close a buffered file and free allocated memory */
local void bclose(bin *in)
{
if (in != NULL) {
if (in->fd != -1)
close(in->fd);
if (in->buf != NULL)
free(in->buf);
free(in);
}
}
/* open a buffered file for input, return a pointer to type bin, or NULL on
failure */
local bin *bopen(char *name)
{
bin *in;
in = malloc(sizeof(bin));
if (in == NULL)
return NULL;
in->buf = malloc(CHUNK);
in->fd = open(name, O_RDONLY, 0);
if (in->buf == NULL || in->fd == -1) {
bclose(in);
return NULL;
}
in->left = 0;
in->next = in->buf;
in->name = name;
return in;
}
/* load buffer from file, return -1 on read error, 0 or 1 on success, with
1 indicating that end-of-file was reached */
local int bload(bin *in)
{
long len;
if (in == NULL)
return -1;
if (in->left != 0)
return 0;
in->next = in->buf;
do {
len = (long)read(in->fd, in->buf + in->left, CHUNK - in->left);
if (len < 0)
return -1;
in->left += (unsigned)len;
} while (len != 0 && in->left < CHUNK);
return len == 0 ? 1 : 0;
}
/* get a byte from the file, bail if end of file */
#define bget(in) (in->left ? 0 : bload(in), \
in->left ? (in->left--, *(in->next)++) : \
bail("unexpected end of file on ", in->name))
/* get a four-byte little-endian unsigned integer from file */
local unsigned long bget4(bin *in)
{
unsigned long val;
val = bget(in);
val += (unsigned long)(bget(in)) << 8;
val += (unsigned long)(bget(in)) << 16;
val += (unsigned long)(bget(in)) << 24;
return val;
}
/* skip bytes in file */
local void bskip(bin *in, unsigned skip)
{
/* check pointer */
if (in == NULL)
return;
/* easy case -- skip bytes in buffer */
if (skip <= in->left) {
in->left -= skip;
in->next += skip;
return;
}
/* skip what's in buffer, discard buffer contents */
skip -= in->left;
in->left = 0;
/* seek past multiples of CHUNK bytes */
if (skip > CHUNK) {
unsigned left;
left = skip & (CHUNK - 1);
if (left == 0) {
/* exact number of chunks: seek all the way minus one byte to check
for end-of-file with a read */
lseek(in->fd, skip - 1, SEEK_CUR);
if (read(in->fd, in->buf, 1) != 1)
bail("unexpected end of file on ", in->name);
return;
}
/* skip the integral chunks, update skip with remainder */
lseek(in->fd, skip - left, SEEK_CUR);
skip = left;
}
/* read more input and skip remainder */
bload(in);
if (skip > in->left)
bail("unexpected end of file on ", in->name);
in->left -= skip;
in->next += skip;
}
/* -- end of buffered input functions -- */
/* skip the gzip header from file in */
local void gzhead(bin *in)
{
int flags;
/* verify gzip magic header and compression method */
if (bget(in) != 0x1f || bget(in) != 0x8b || bget(in) != 8)
bail(in->name, " is not a valid gzip file");
/* get and verify flags */
flags = bget(in);
if ((flags & 0xe0) != 0)
bail("unknown reserved bits set in ", in->name);
/* skip modification time, extra flags, and os */
bskip(in, 6);
/* skip extra field if present */
if (flags & 4) {
unsigned len;
len = bget(in);
len += (unsigned)(bget(in)) << 8;
bskip(in, len);
}
/* skip file name if present */
if (flags & 8)
while (bget(in) != 0)
;
/* skip comment if present */
if (flags & 16)
while (bget(in) != 0)
;
/* skip header crc if present */
if (flags & 2)
bskip(in, 2);
}
/* write a four-byte little-endian unsigned integer to out */
local void put4(unsigned long val, FILE *out)
{
putc(val & 0xff, out);
putc((val >> 8) & 0xff, out);
putc((val >> 16) & 0xff, out);
putc((val >> 24) & 0xff, out);
}
/* Load up zlib stream from buffered input, bail if end of file */
local void zpull(z_streamp strm, bin *in)
{
if (in->left == 0)
bload(in);
if (in->left == 0)
bail("unexpected end of file on ", in->name);
strm->avail_in = in->left;
strm->next_in = in->next;
}
/* Write header for gzip file to out and initialize trailer. */
local void gzinit(unsigned long *crc, unsigned long *tot, FILE *out)
{
fwrite("\x1f\x8b\x08\0\0\0\0\0\0\xff", 1, 10, out);
*crc = crc32(0L, Z_NULL, 0);
*tot = 0;
}
/* Copy the compressed data from name, zeroing the last block bit of the last
block if clr is true, and adding empty blocks as needed to get to a byte
boundary. If clr is false, then the last block becomes the last block of
the output, and the gzip trailer is written. crc and tot maintains the
crc and length (modulo 2^32) of the output for the trailer. The resulting
gzip file is written to out. gzinit() must be called before the first call
of gzcopy() to write the gzip header and to initialize crc and tot. */
local void gzcopy(char *name, int clr, unsigned long *crc, unsigned long *tot,
FILE *out)
{
int ret; /* return value from zlib functions */
int pos; /* where the "last block" bit is in byte */
int last; /* true if processing the last block */
bin *in; /* buffered input file */
unsigned char *start; /* start of compressed data in buffer */
unsigned char *junk; /* buffer for uncompressed data -- discarded */
z_off_t len; /* length of uncompressed data (support > 4 GB) */
z_stream strm; /* zlib inflate stream */
/* open gzip file and skip header */
in = bopen(name);
if (in == NULL)
bail("could not open ", name);
gzhead(in);
/* allocate buffer for uncompressed data and initialize raw inflate
stream */
junk = malloc(CHUNK);
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit2(&strm, -15);
if (junk == NULL || ret != Z_OK)
bail("out of memory", "");
/* inflate and copy compressed data, clear last-block bit if requested */
len = 0;
zpull(&strm, in);
start = strm.next_in;
last = start[0] & 1;
if (last && clr)
start[0] &= ~1;
strm.avail_out = 0;
for (;;) {
/* if input used and output done, write used input and get more */
if (strm.avail_in == 0 && strm.avail_out != 0) {
fwrite(start, 1, strm.next_in - start, out);
start = in->buf;
in->left = 0;
zpull(&strm, in);
}
/* decompress -- return early when end-of-block reached */
strm.avail_out = CHUNK;
strm.next_out = junk;
ret = inflate(&strm, Z_BLOCK);
switch (ret) {
case Z_MEM_ERROR:
bail("out of memory", "");
case Z_DATA_ERROR:
bail("invalid compressed data in ", in->name);
}
/* update length of uncompressed data */
len += CHUNK - strm.avail_out;
/* check for block boundary (only get this when block copied out) */
if (strm.data_type & 128) {
/* if that was the last block, then done */
if (last)
break;
/* number of unused bits in last byte */
pos = strm.data_type & 7;
/* find the next last-block bit */
if (pos != 0) {
/* next last-block bit is in last used byte */
pos = 0x100 >> pos;
last = strm.next_in[-1] & pos;
if (last && clr)
strm.next_in[-1] &= ~pos;
}
else {
/* next last-block bit is in next unused byte */
if (strm.avail_in == 0) {
/* don't have that byte yet -- get it */
fwrite(start, 1, strm.next_in - start, out);
start = in->buf;
in->left = 0;
zpull(&strm, in);
}
last = strm.next_in[0] & 1;
if (last && clr)
strm.next_in[0] &= ~1;
}
}
}
/* update buffer with unused input */
in->left = strm.avail_in;
in->next = strm.next_in;
/* copy used input, write empty blocks to get to byte boundary */
pos = strm.data_type & 7;
fwrite(start, 1, in->next - start - 1, out);
last = in->next[-1];
if (pos == 0 || !clr)
/* already at byte boundary, or last file: write last byte */
putc(last, out);
else {
/* append empty blocks to last byte */
last &= ((0x100 >> pos) - 1); /* assure unused bits are zero */
if (pos & 1) {
/* odd -- append an empty stored block */
putc(last, out);
if (pos == 1)
putc(0, out); /* two more bits in block header */
fwrite("\0\0\xff\xff", 1, 4, out);
}
else {
/* even -- append 1, 2, or 3 empty fixed blocks */
switch (pos) {
case 6:
putc(last | 8, out);
last = 0;
case 4:
putc(last | 0x20, out);
last = 0;
case 2:
putc(last | 0x80, out);
putc(0, out);
}
}
}
/* update crc and tot */
*crc = crc32_combine(*crc, bget4(in), len);
*tot += (unsigned long)len;
/* clean up */
inflateEnd(&strm);
free(junk);
bclose(in);
/* write trailer if this is the last gzip file */
if (!clr) {
put4(*crc, out);
put4(*tot, out);
}
}
/* join the gzip files on the command line, write result to stdout */
int main(int argc, char **argv)
{
unsigned long crc, tot; /* running crc and total uncompressed length */
/* skip command name */
argc--;
argv++;
/* show usage if no arguments */
if (argc == 0) {
fputs("gzjoin usage: gzjoin f1.gz [f2.gz [f3.gz ...]] > fjoin.gz\n",
stderr);
return 0;
}
/* join gzip files on command line and write to stdout */
gzinit(&crc, &tot, stdout);
while (argc--)
gzcopy(*argv++, argc, &crc, &tot, stdout);
/* done */
return 0;
}

413
examples/gzlog.c Normal file
View File

@@ -0,0 +1,413 @@
/*
* gzlog.c
* Copyright (C) 2004 Mark Adler
* For conditions of distribution and use, see copyright notice in gzlog.h
* version 1.0, 26 Nov 2004
*
*/
#include <string.h> /* memcmp() */
#include <stdlib.h> /* malloc(), free(), NULL */
#include <sys/types.h> /* size_t, off_t */
#include <unistd.h> /* read(), close(), sleep(), ftruncate(), */
/* lseek() */
#include <fcntl.h> /* open() */
#include <sys/file.h> /* flock() */
#include "zlib.h" /* deflateInit2(), deflate(), deflateEnd() */
#include "gzlog.h" /* interface */
#define local static
/* log object structure */
typedef struct {
int id; /* object identifier */
int fd; /* log file descriptor */
off_t extra; /* offset of extra "ap" subfield */
off_t mark_off; /* offset of marked data */
off_t last_off; /* offset of last block */
unsigned long crc; /* uncompressed crc */
unsigned long len; /* uncompressed length (modulo 2^32) */
unsigned stored; /* length of current stored block */
} gz_log;
#define GZLOGID 19334 /* gz_log object identifier */
#define LOCK_RETRY 1 /* retry lock once a second */
#define LOCK_PATIENCE 1200 /* try about twenty minutes before forcing */
/* acquire a lock on a file */
local int lock(int fd)
{
int patience;
/* try to lock every LOCK_RETRY seconds for LOCK_PATIENCE seconds */
patience = LOCK_PATIENCE;
do {
if (flock(fd, LOCK_EX + LOCK_NB) == 0)
return 0;
(void)sleep(LOCK_RETRY);
patience -= LOCK_RETRY;
} while (patience > 0);
/* we've run out of patience -- give up */
return -1;
}
/* release lock */
local void unlock(int fd)
{
(void)flock(fd, LOCK_UN);
}
/* release a log object */
local void log_clean(gz_log *log)
{
unlock(log->fd);
(void)close(log->fd);
free(log);
}
/* read an unsigned long from a byte buffer little-endian */
local unsigned long make_ulg(unsigned char *buf)
{
int n;
unsigned long val;
val = (unsigned long)(*buf++);
for (n = 8; n < 32; n += 8)
val += (unsigned long)(*buf++) << n;
return val;
}
/* read an off_t from a byte buffer little-endian */
local off_t make_off(unsigned char *buf)
{
int n;
off_t val;
val = (off_t)(*buf++);
for (n = 8; n < 64; n += 8)
val += (off_t)(*buf++) << n;
return val;
}
/* write an unsigned long little-endian to byte buffer */
local void dice_ulg(unsigned long val, unsigned char *buf)
{
int n;
for (n = 0; n < 4; n++) {
*buf++ = val & 0xff;
val >>= 8;
}
}
/* write an off_t little-endian to byte buffer */
local void dice_off(off_t val, unsigned char *buf)
{
int n;
for (n = 0; n < 8; n++) {
*buf++ = val & 0xff;
val >>= 8;
}
}
/* initial, empty gzip file for appending */
local char empty_gz[] = {
0x1f, 0x8b, /* magic gzip id */
8, /* compression method is deflate */
4, /* there is an extra field */
0, 0, 0, 0, /* no modification time provided */
0, 0xff, /* no extra flags, no OS */
20, 0, 'a', 'p', 16, 0, /* extra field with "ap" subfield */
32, 0, 0, 0, 0, 0, 0, 0, /* offset of uncompressed data */
32, 0, 0, 0, 0, 0, 0, 0, /* offset of last block */
1, 0, 0, 0xff, 0xff, /* empty stored block (last) */
0, 0, 0, 0, /* crc */
0, 0, 0, 0 /* uncompressed length */
};
/* initialize a log object with locking */
void *gzlog_open(char *path)
{
unsigned xlen;
unsigned char temp[20];
unsigned sub_len;
int good;
gz_log *log;
/* allocate log structure */
log = malloc(sizeof(gz_log));
if (log == NULL)
return NULL;
log->id = GZLOGID;
/* open file, creating it if necessary, and locking it */
log->fd = open(path, O_RDWR | O_CREAT, 0600);
if (log->fd < 0) {
free(log);
return NULL;
}
if (lock(log->fd)) {
close(log->fd);
free(log);
return NULL;
}
/* if file is empty, write new gzip stream */
if (lseek(log->fd, 0, SEEK_END) == 0) {
if (write(log->fd, empty_gz, sizeof(empty_gz)) != sizeof(empty_gz)) {
log_clean(log);
return NULL;
}
}
/* check gzip header */
(void)lseek(log->fd, 0, SEEK_SET);
if (read(log->fd, temp, 12) != 12 || temp[0] != 0x1f ||
temp[1] != 0x8b || temp[2] != 8 || (temp[3] & 4) == 0) {
log_clean(log);
return NULL;
}
/* process extra field to find "ap" sub-field */
xlen = temp[10] + (temp[11] << 8);
good = 0;
while (xlen) {
if (xlen < 4 || read(log->fd, temp, 4) != 4)
break;
sub_len = temp[2];
sub_len += temp[3] << 8;
xlen -= 4;
if (memcmp(temp, "ap", 2) == 0 && sub_len == 16) {
good = 1;
break;
}
if (xlen < sub_len)
break;
(void)lseek(log->fd, sub_len, SEEK_CUR);
xlen -= sub_len;
}
if (!good) {
log_clean(log);
return NULL;
}
/* read in "ap" sub-field */
log->extra = lseek(log->fd, 0, SEEK_CUR);
if (read(log->fd, temp, 16) != 16) {
log_clean(log);
return NULL;
}
log->mark_off = make_off(temp);
log->last_off = make_off(temp + 8);
/* get crc, length of gzip file */
(void)lseek(log->fd, log->last_off, SEEK_SET);
if (read(log->fd, temp, 13) != 13 ||
memcmp(temp, "\001\000\000\377\377", 5) != 0) {
log_clean(log);
return NULL;
}
log->crc = make_ulg(temp + 5);
log->len = make_ulg(temp + 9);
/* set up to write over empty last block */
(void)lseek(log->fd, log->last_off + 5, SEEK_SET);
log->stored = 0;
return (void *)log;
}
/* maximum amount to put in a stored block before starting a new one */
#define MAX_BLOCK 16384
/* write a block to a log object */
int gzlog_write(void *obj, char *data, size_t len)
{
size_t some;
unsigned char temp[5];
gz_log *log;
/* check object */
log = (gz_log *)obj;
if (log == NULL || log->id != GZLOGID)
return 1;
/* write stored blocks until all of the input is written */
do {
some = MAX_BLOCK - log->stored;
if (some > len)
some = len;
if (write(log->fd, data, some) != some)
return 1;
log->crc = crc32(log->crc, data, some);
log->len += some;
len -= some;
data += some;
log->stored += some;
/* if the stored block is full, end it and start another */
if (log->stored == MAX_BLOCK) {
(void)lseek(log->fd, log->last_off, SEEK_SET);
temp[0] = 0;
dice_ulg(log->stored + ((unsigned long)(~log->stored) << 16),
temp + 1);
if (write(log->fd, temp, 5) != 5)
return 1;
log->last_off = lseek(log->fd, log->stored, SEEK_CUR);
(void)lseek(log->fd, 5, SEEK_CUR);
log->stored = 0;
}
} while (len);
return 0;
}
/* recompress the remaining stored deflate data in place */
local int recomp(gz_log *log)
{
z_stream strm;
size_t len, max;
unsigned char *in;
unsigned char *out;
unsigned char temp[16];
/* allocate space and read it all in (it's around 1 MB) */
len = log->last_off - log->mark_off;
max = len + (len >> 12) + (len >> 14) + 11;
out = malloc(max);
if (out == NULL)
return 1;
in = malloc(len);
if (in == NULL) {
free(out);
return 1;
}
(void)lseek(log->fd, log->mark_off, SEEK_SET);
if (read(log->fd, in, len) != len) {
free(in);
free(out);
return 1;
}
/* recompress in memory, decoding stored data as we go */
/* note: this assumes that unsigned is four bytes or more */
/* consider not making that assumption */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
if (deflateInit2(&strm, Z_BEST_COMPRESSION, Z_DEFLATED, -15, 8,
Z_DEFAULT_STRATEGY) != Z_OK) {
free(in);
free(out);
return 1;
}
strm.next_in = in;
strm.avail_out = max;
strm.next_out = out;
while (len >= 5) {
if (strm.next_in[0] != 0)
break;
strm.avail_in = strm.next_in[1] + (strm.next_in[2] << 8);
strm.next_in += 5;
len -= 5;
if (strm.avail_in != 0) {
if (len < strm.avail_in)
break;
len -= strm.avail_in;
(void)deflate(&strm, Z_NO_FLUSH);
if (strm.avail_in != 0 || strm.avail_out == 0)
break;
}
}
(void)deflate(&strm, Z_SYNC_FLUSH);
(void)deflateEnd(&strm);
free(in);
if (len != 0 || strm.avail_out == 0) {
free(out);
return 1;
}
/* overwrite stored data with compressed data */
(void)lseek(log->fd, log->mark_off, SEEK_SET);
len = max - strm.avail_out;
if (write(log->fd, out, len) != len) {
free(out);
return 1;
}
free(out);
/* write last empty block, crc, and length */
log->mark_off = log->last_off = lseek(log->fd, 0, SEEK_CUR);
temp[0] = 1;
dice_ulg(0xffffL << 16, temp + 1);
dice_ulg(log->crc, temp + 5);
dice_ulg(log->len, temp + 9);
if (write(log->fd, temp, 13) != 13)
return 1;
/* truncate file to discard remaining stored data and old trailer */
ftruncate(log->fd, lseek(log->fd, 0, SEEK_CUR));
/* update extra field to point to new last empty block */
(void)lseek(log->fd, log->extra, SEEK_SET);
dice_off(log->mark_off, temp);
dice_off(log->last_off, temp + 8);
if (write(log->fd, temp, 16) != 16)
return 1;
return 0;
}
/* maximum accumulation of stored blocks before compressing */
#define MAX_STORED 1048576
/* close log object */
int gzlog_close(void *obj)
{
unsigned char temp[8];
gz_log *log;
/* check object */
log = (gz_log *)obj;
if (log == NULL || log->id != GZLOGID)
return 1;
/* go to start of most recent block being written */
(void)lseek(log->fd, log->last_off, SEEK_SET);
/* if some stuff was put there, update block */
if (log->stored) {
temp[0] = 0;
dice_ulg(log->stored + ((unsigned long)(~log->stored) << 16),
temp + 1);
if (write(log->fd, temp, 5) != 5)
return 1;
log->last_off = lseek(log->fd, log->stored, SEEK_CUR);
}
/* write last block (empty) */
if (write(log->fd, "\001\000\000\377\377", 5) != 5)
return 1;
/* write updated crc and uncompressed length */
dice_ulg(log->crc, temp);
dice_ulg(log->len, temp + 4);
if (write(log->fd, temp, 8) != 8)
return 1;
/* put offset of that last block in gzip extra block */
(void)lseek(log->fd, log->extra + 8, SEEK_SET);
dice_off(log->last_off, temp);
if (write(log->fd, temp, 8) != 8)
return 1;
/* if more than 1 MB stored, then time to compress it */
if (log->last_off - log->mark_off > MAX_STORED) {
if (recomp(log))
return 1;
}
/* unlock and close file */
log_clean(log);
return 0;
}

58
examples/gzlog.h Normal file
View File

@@ -0,0 +1,58 @@
/* gzlog.h
Copyright (C) 2004 Mark Adler, all rights reserved
version 1.0, 26 Nov 2004
This software is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Mark Adler madler@alumni.caltech.edu
*/
/*
The gzlog object allows writing short messages to a gzipped log file,
opening the log file locked for small bursts, and then closing it. The log
object works by appending stored data to the gzip file until 1 MB has been
accumulated. At that time, the stored data is compressed, and replaces the
uncompressed data in the file. The log file is truncated to its new size at
that time. After closing, the log file is always valid gzip file that can
decompressed to recover what was written.
A gzip header "extra" field contains two file offsets for appending. The
first points to just after the last compressed data. The second points to
the last stored block in the deflate stream, which is empty. All of the
data between those pointers is uncompressed.
*/
/* Open a gzlog object, creating the log file if it does not exist. Return
NULL on error. Note that gzlog_open() could take a long time to return if
there is difficulty in locking the file. */
void *gzlog_open(char *path);
/* Write to a gzlog object. Return non-zero on error. This function will
simply write data to the file uncompressed. Compression of the data
will not occur until gzlog_close() is called. It is expected that
gzlog_write() is used for a short message, and then gzlog_close() is
called. If a large amount of data is to be written, then the application
should write no more than 1 MB at a time with gzlog_write() before
calling gzlog_close() and then gzlog_open() again. */
int gzlog_write(void *log, char *data, size_t len);
/* Close a gzlog object. Return non-zero on error. The log file is locked
until this function is called. This function will compress stored data
at the end of the gzip file if at least 1 MB has been accumulated. Note
that the file will not be a valid gzip file until this function completes.
*/
int gzlog_close(void *log);

523
examples/zlib_how.html Normal file
View File

@@ -0,0 +1,523 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>zlib Usage Example</title>
<!-- Copyright (c) 2004 Mark Adler. -->
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#00A000">
<h2 align="center"> zlib Usage Example </h2>
We often get questions about how the <tt>deflate()</tt> and <tt>inflate()</tt> functions should be used.
Users wonder when they should provide more input, when they should use more output,
what to do with a <tt>Z_BUF_ERROR</tt>, how to make sure the process terminates properly, and
so on. So for those who have read <tt>zlib.h</tt> (a few times), and
would like further edification, below is an annotated example in C of simple routines to compress and decompress
from an input file to an output file using <tt>deflate()</tt> and <tt>inflate()</tt> respectively. The
annotations are interspersed between lines of the code. So please read between the lines.
We hope this helps explain some of the intricacies of <em>zlib</em>.
<p>
Without further adieu, here is the program <a href="zpipe.c"><tt>zpipe.c</tt></a>:
<pre><b>
/* zpipe.c: example of proper use of zlib's inflate() and deflate()
Not copyrighted -- provided to the public domain
Version 1.2 9 November 2004 Mark Adler */
/* Version history:
1.0 30 Oct 2004 First version
1.1 8 Nov 2004 Add void casting for unused return values
Use switch statement for inflate() return values
1.2 9 Nov 2004 Add assertions to document zlib guarantees
*/
</b></pre><!-- -->
We now include the header files for the required definitions. From
<tt>stdio.h</tt> we use <tt>fopen()</tt>, <tt>fread()</tt>, <tt>fwrite()</tt>,
<tt>feof()</tt>, <tt>ferror()</tt>, and <tt>fclose()</tt> for file i/o, and
<tt>fputs()</tt> for error messages. From <tt>string.h</tt> we use
<tt>strcmp()</tt> for command line argument processing.
From <tt>assert.h</tt> we use the <tt>assert()</tt> macro.
From <tt>zlib.h</tt>
we use the basic compression functions <tt>deflateInit()</tt>,
<tt>deflate()</tt>, and <tt>deflateEnd()</tt>, and the basic decompression
functions <tt>inflateInit()</tt>, <tt>inflate()</tt>, and
<tt>inflateEnd()</tt>.
<pre><b>
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;assert.h&gt;
#include "zlib.h"
</b></pre><!-- -->
<tt>CHUNK</tt> is simply the buffer size for feeding data to and pulling data
from the <em>zlib</em> routines. Larger buffer sizes would be more efficient,
especially for <tt>inflate()</tt>. If the memory is available, buffers sizes
on the order of 128K or 256K bytes should be used.
<pre><b>
#define CHUNK 16384
</b></pre><!-- -->
The <tt>def()</tt> routine compresses data from an input file to an output file. The output data
will be in the <em>zlib</em> format, which is different from the <em>gzip</em> or <em>zip</em>
formats. The <em>zlib</em> format has a very small header of only two bytes to identify it as
a <em>zlib</em> stream and to provide decoding information, and a four-byte trailer with a fast
check value to verify the integrity of the uncompressed data after decoding.
<pre><b>
/* Compress from file source to file dest until EOF on source.
def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
allocated for processing, Z_STREAM_ERROR if an invalid compression
level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
version of the library linked do not match, or Z_ERRNO if there is
an error reading or writing the files. */
int def(FILE *source, FILE *dest, int level)
{
</b></pre>
Here are the local variables for <tt>def()</tt>. <tt>ret</tt> will be used for <em>zlib</em>
return codes. <tt>flush</tt> will keep track of the current flushing state for <tt>deflate()</tt>,
which is either no flushing, or flush to completion after the end of the input file is reached.
<tt>have</tt> is the amount of data returned from <tt>deflate()</tt>. The <tt>strm</tt> structure
is used to pass information to and from the <em>zlib</em> routines, and to maintain the
<tt>deflate()</tt> state. <tt>in</tt> and <tt>out</tt> are the input and output buffers for
<tt>deflate()</tt>.
<pre><b>
int ret, flush;
unsigned have;
z_stream strm;
char in[CHUNK];
char out[CHUNK];
</b></pre><!-- -->
The first thing we do is to initialize the <em>zlib</em> state for compression using
<tt>deflateInit()</tt>. This must be done before the first use of <tt>deflate()</tt>.
The <tt>zalloc</tt>, <tt>zfree</tt>, and <tt>opaque</tt> fields in the <tt>strm</tt>
structure must be initialized before calling <tt>deflateInit()</tt>. Here they are
set to the <em>zlib</em> constant <tt>Z_NULL</tt> to request that <em>zlib</em> use
the default memory allocation routines. An application may also choose to provide
custom memory allocation routines here. <tt>deflateInit()</tt> will allocate on the
order of 256K bytes for the internal state.
(See <a href="zlib_tech.html"><em>zlib Technical Details</em></a>.)
<p>
<tt>deflateInit()</tt> is called with a pointer to the structure to be initialized and
the compression level, which is an integer in the range of -1 to 9. Lower compression
levels result in faster execution, but less compression. Higher levels result in
greater compression, but slower execution. The <em>zlib</em> constant Z_DEFAULT_COMPRESSION,
equal to -1,
provides a good compromise between compression and speed and is equivalent to level 6.
Level 0 actually does no compression at all, and in fact expands the data slightly to produce
the <em>zlib</em> format (it is not a byte-for-byte copy of the input).
More advanced applications of <em>zlib</em>
may use <tt>deflateInit2()</tt> here instead. Such an application may want to reduce how
much memory will be used, at some price in compression. Or it may need to request a
<em>gzip</em> header and trailer instead of a <em>zlib</em> header and trailer, or raw
encoding with no header or trailer at all.
<p>
We must check the return value of <tt>deflateInit()</tt> against the <em>zlib</em> constant
<tt>Z_OK</tt> to make sure that it was able to
allocate memory for the internal state, and that the provided arguments were valid.
<tt>deflateInit()</tt> will also check that the version of <em>zlib</em> that the <tt>zlib.h</tt>
file came from matches the version of <em>zlib</em> actually linked with the program. This
is especially important for environments in which <em>zlib</em> is a shared library.
<p>
Note that an application can initialize multiple, independent <em>zlib</em> streams, which can
operate in parallel. The state information maintained in the structure allows the <em>zlib</em>
routines to be reentrant.
<pre><b>
/* allocate deflate state */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
ret = deflateInit(&amp;strm, level);
if (ret != Z_OK)
return ret;
</b></pre><!-- -->
With the pleasantries out of the way, now we can get down to business. The outer <tt>do</tt>-loop
reads all of the input file and exits at the bottom of the loop once end-of-file is reached.
This loop contains the only call of <tt>deflate()</tt>. So we must make sure that all of the
input data has been processed and that all of the output data has been generated and consumed
before we fall out of the loop at the bottom.
<pre><b>
/* compress until end of file */
do {
</b></pre>
We start off by reading data from the input file. The number of bytes read is put directly
into <tt>avail_in</tt>, and a pointer to those bytes is put into <tt>next_in</tt>. We also
check to see if end-of-file on the input has been reached. If we are at the end of file, then <tt>flush</tt> is set to the
<em>zlib</em> constant <tt>Z_FINISH</tt>, which is later passed to <tt>deflate()</tt> to
indicate that this is the last chunk of input data to compress. We need to use <tt>feof()</tt>
to check for end-of-file as opposed to seeing if fewer than <tt>CHUNK</tt> bytes have been read. The
reason is that if the input file length is an exact multiple of <tt>CHUNK</tt>, we will miss
the fact that we got to the end-of-file, and not know to tell <tt>deflate()</tt> to finish
up the compressed stream. If we are not yet at the end of the input, then the <em>zlib</em>
constant <tt>Z_NO_FLUSH</tt> will be passed to <tt>deflate</tt> to indicate that we are still
in the middle of the uncompressed data.
<p>
If there is an error in reading from the input file, the process is aborted with
<tt>deflateEnd()</tt> being called to free the allocated <em>zlib</em> state before returning
the error. We wouldn't want a memory leak, now would we? <tt>deflateEnd()</tt> can be called
at any time after the state has been initialized. Once that's done, <tt>deflateInit()</tt> (or
<tt>deflateInit2()</tt>) would have to be called to start a new compression process. There is
no point here in checking the <tt>deflateEnd()</tt> return code. The deallocation can't fail.
<pre><b>
strm.avail_in = fread(in, 1, CHUNK, source);
if (ferror(source)) {
(void)deflateEnd(&amp;strm);
return Z_ERRNO;
}
flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
strm.next_in = in;
</b></pre><!-- -->
The inner <tt>do</tt>-loop passes our chunk of input data to <tt>deflate()</tt>, and then
keeps calling <tt>deflate()</tt> until it is done producing output. Once there is no more
new output, <tt>deflate()</tt> is guaranteed to have consumed all of the input, i.e.,
<tt>avail_in</tt> will be zero.
<pre><b>
/* run deflate() on input until output buffer not full, finish
compression if all of source has been read in */
do {
</b></pre>
Output space is provided to <tt>deflate()</tt> by setting <tt>avail_out</tt> to the number
of available output bytes and <tt>next_out</tt> to a pointer to that space.
<pre><b>
strm.avail_out = CHUNK;
strm.next_out = out;
</b></pre>
Now we call the compression engine itself, <tt>deflate()</tt>. It takes as many of the
<tt>avail_in</tt> bytes at <tt>next_in</tt> as it can process, and writes as many as
<tt>avail_out</tt> bytes to <tt>next_out</tt>. Those counters and pointers are then
updated past the input data consumed and the output data written. It is the amount of
output space available that may limit how much input is consumed.
Hence the inner loop to make sure that
all of the input is consumed by providing more output space each time. Since <tt>avail_in</tt>
and <tt>next_in</tt> are updated by <tt>deflate()</tt>, we don't have to mess with those
between <tt>deflate()</tt> calls until it's all used up.
<p>
The parameters to <tt>deflate()</tt> are a pointer to the <tt>strm</tt> structure containing
the input and output information and the internal compression engine state, and a parameter
indicating whether and how to flush data to the output. Normally <tt>deflate</tt> will consume
several K bytes of input data before producing any output (except for the header), in order
to accumulate statistics on the data for optimum compression. It will then put out a burst of
compressed data, and proceed to consume more input before the next burst. Eventually,
<tt>deflate()</tt>
must be told to terminate the stream, complete the compression with provided input data, and
write out the trailer check value. <tt>deflate()</tt> will continue to compress normally as long
as the flush parameter is <tt>Z_NO_FLUSH</tt>. Once the <tt>Z_FINISH</tt> parameter is provided,
<tt>deflate()</tt> will begin to complete the compressed output stream. However depending on how
much output space is provided, <tt>deflate()</tt> may have to be called several times until it
has provided the complete compressed stream, even after it has consumed all of the input. The flush
parameter must continue to be <tt>Z_FINISH</tt> for those subsequent calls.
<p>
There are other values of the flush parameter that are used in more advanced applications. You can
force <tt>deflate()</tt> to produce a burst of output that encodes all of the input data provided
so far, even if it wouldn't have otherwise, for example to control data latency on a link with
compressed data. You can also ask that <tt>deflate()</tt> do that as well as erase any history up to
that point so that what follows can be decompressed independently, for example for random access
applications. Both requests will degrade compression by an amount depending on how often such
requests are made.
<p>
<tt>deflate()</tt> has a return value that can indicate errors, yet we do not check it here. Why
not? Well, it turns out that <tt>deflate()</tt> can do no wrong here. Let's go through
<tt>deflate()</tt>'s return values and dispense with them one by one. The possible values are
<tt>Z_OK</tt>, <tt>Z_STREAM_END</tt>, <tt>Z_STREAM_ERROR</tt>, or <tt>Z_BUF_ERROR</tt>. <tt>Z_OK</tt>
is, well, ok. <tt>Z_STREAM_END</tt> is also ok and will be returned for the last call of
<tt>deflate()</tt>. This is already guaranteed by calling <tt>deflate()</tt> with <tt>Z_FINISH</tt>
until it has no more output. <tt>Z_STREAM_ERROR</tt> is only possible if the stream is not
initialized properly, but we did initialize it properly. There is no harm in checking for
<tt>Z_STREAM_ERROR</tt> here, for example to check for the possibility that some
other part of the application inadvertently clobbered the memory containing the <em>zlib</em> state.
<tt>Z_BUF_ERROR</tt> will be explained further below, but
suffice it to say that this is simply an indication that <tt>deflate()</tt> could not consume
more input or produce more output. <tt>deflate()</tt> can be called again with more output space
or more available input, which it will be in this code.
<pre><b>
ret = deflate(&amp;strm, flush); /* no bad return value */
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
</b></pre>
Now we compute how much output <tt>deflate()</tt> provided on the last call, which is the
difference between how much space was provided before the call, and how much output space
is still available after the call. Then that data, if any, is written to the output file.
We can then reuse the output buffer for the next call of <tt>deflate()</tt>. Again if there
is a file i/o error, we call <tt>deflateEnd()</tt> before returning to avoid a memory leak.
<pre><b>
have = CHUNK - strm.avail_out;
if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
(void)deflateEnd(&amp;strm);
return Z_ERRNO;
}
</b></pre>
The inner <tt>do</tt>-loop is repeated until the last <tt>deflate()</tt> call fails to fill the
provided output buffer. Then we know that <tt>deflate()</tt> has done as much as it can with
the provided input, and that all of that input has been consumed. We can then fall out of this
loop and reuse the input buffer.
<p>
The way we tell that <tt>deflate()</tt> has no more output is by seeing that it did not fill
the output buffer, leaving <tt>avail_out</tt> greater than zero. However suppose that
<tt>deflate()</tt> has no more output, but just so happened to exactly fill the output buffer!
<tt>avail_out</tt> is zero, and we can't tell that <tt>deflate()</tt> has done all it can.
As far as we know, <tt>deflate()</tt>
has more output for us. So we call it again. But now <tt>deflate()</tt> produces no output
at all, and <tt>avail_out</tt> remains unchanged as <tt>CHUNK</tt>. That <tt>deflate()</tt> call
wasn't able to do anything, either consume input or produce output, and so it returns
<tt>Z_BUF_ERROR</tt>. (See, I told you I'd cover this later.) However this is not a problem at
all. Now we finally have the desired indication that <tt>deflate()</tt> is really done,
and so we drop out of the inner loop to provide more input to <tt>deflate()</tt>.
<p>
With <tt>flush</tt> set to <tt>Z_FINISH</tt>, this final set of <tt>deflate()</tt> calls will
complete the output stream. Once that is done, subsequent calls of <tt>deflate()</tt> would return
<tt>Z_STREAM_ERROR</tt> if the flush parameter is not <tt>Z_FINISH</tt>, and do no more processing
until the state is reinitialized.
<p>
Some applications of <em>zlib</em> have two loops that call <tt>deflate()</tt>
instead of the single inner loop we have here. The first loop would call
without flushing and feed all of the data to <tt>deflate()</tt>. The second loop would call
<tt>deflate()</tt> with no more
data and the <tt>Z_FINISH</tt> parameter to complete the process. As you can see from this
example, that can be avoided by simply keeping track of the current flush state.
<pre><b>
} while (strm.avail_out == 0);
assert(strm.avail_in == 0); /* all input will be used */
</b></pre><!-- -->
Now we check to see if we have already processed all of the input file. That information was
saved in the <tt>flush</tt> variable, so we see if that was set to <tt>Z_FINISH</tt>. If so,
then we're done and we fall out of the outer loop. We're guaranteed to get <tt>Z_STREAM_END</tt>
from the last <tt>deflate()</tt> call, since we ran it until the last chunk of input was
consumed and all of the output was generated.
<pre><b>
/* done when last data in file processed */
} while (flush != Z_FINISH);
assert(ret == Z_STREAM_END); /* stream will be complete */
</b></pre><!-- -->
The process is complete, but we still need to deallocate the state to avoid a memory leak
(or rather more like a memory hemorrhage if you didn't do this). Then
finally we can return with a happy return value.
<pre><b>
/* clean up and return */
(void)deflateEnd(&amp;strm);
return Z_OK;
}
</b></pre><!-- -->
Now we do the same thing for decompression in the <tt>inf()</tt> routine. <tt>inf()</tt>
decompresses what is hopefully a valid <em>zlib</em> stream from the input file and writes the
uncompressed data to the output file. Much of the discussion above for <tt>def()</tt>
applies to <tt>inf()</tt> as well, so the discussion here will focus on the differences between
the two.
<pre><b>
/* Decompress from file source to file dest until stream ends or EOF.
inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
allocated for processing, Z_DATA_ERROR if the deflate data is
invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
the version of the library linked do not match, or Z_ERRNO if there
is an error reading or writing the files. */
int inf(FILE *source, FILE *dest)
{
</b></pre>
The local variables have the same functionality as they do for <tt>def()</tt>. The
only difference is that there is no <tt>flush</tt> variable, since <tt>inflate()</tt>
can tell from the <em>zlib</em> stream itself when the stream is complete.
<pre><b>
int ret;
unsigned have;
z_stream strm;
char in[CHUNK];
char out[CHUNK];
</b></pre><!-- -->
The initialization of the state is the same, except that there is no compression level,
of course, and two more elements of the structure are initialized. <tt>avail_in</tt>
and <tt>next_in</tt> must be initialized before calling <tt>inflateInit()</tt>. This
is because the application has the option to provide the start of the zlib stream in
order for <tt>inflateInit()</tt> to have access to information about the compression
method to aid in memory allocation. In the current implementation of <em>zlib</em>
(up through versions 1.2.x), the method-dependent memory allocations are deferred to the first call of
<tt>inflate()</tt> anyway. However those fields must be initialized since later versions
of <em>zlib</em> that provide more compression methods may take advantage of this interface.
In any case, no decompression is performed by <tt>inflateInit()</tt>, so the
<tt>avail_out</tt> and <tt>next_out</tt> fields do not need to be initialized before calling.
<p>
Here <tt>avail_in</tt> is set to zero and <tt>next_in</tt> is set to <tt>Z_NULL</tt> to
indicate that no input data is being provided.
<pre><b>
/* allocate inflate state */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit(&amp;strm);
if (ret != Z_OK)
return ret;
</b></pre><!-- -->
The outer <tt>do</tt>-loop decompresses input until <tt>inflate()</tt> indicates
that it has reached the end of the compressed data and has produced all of the uncompressed
output. This is in contrast to <tt>def()</tt> which processes all of the input file.
If end-of-file is reached before the compressed data self-terminates, then the compressed
data is incomplete and an error is returned.
<pre><b>
/* decompress until deflate stream ends or end of file */
do {
</b></pre>
We read input data and set the <tt>strm</tt> structure accordingly. If we've reached the
end of the input file, then we leave the outer loop and report an error, since the
compressed data is incomplete. Note that we may read more data than is eventually consumed
by <tt>inflate()</tt>, if the input file continues past the <em>zlib</em> stream.
For applications where <em>zlib</em> streams are embedded in other data, this routine would
need to be modified to return the unused data, or at least indicate how much of the input
data was not used, so the application would know where to pick up after the <em>zlib</em> stream.
<pre><b>
strm.avail_in = fread(in, 1, CHUNK, source);
if (ferror(source)) {
(void)inflateEnd(&amp;strm);
return Z_ERRNO;
}
if (strm.avail_in == 0)
break;
strm.next_in = in;
</b></pre><!-- -->
The inner <tt>do</tt>-loop has the same function it did in <tt>def()</tt>, which is to
keep calling <tt>inflate()</tt> until has generated all of the output it can with the
provided input.
<pre><b>
/* run inflate() on input until output buffer not full */
do {
</b></pre>
Just like in <tt>def()</tt>, the same output space is provided for each call of <tt>inflate()</tt>.
<pre><b>
strm.avail_out = CHUNK;
strm.next_out = out;
</b></pre>
Now we run the decompression engine itself. There is no need to adjust the flush parameter, since
the <em>zlib</em> format is self-terminating. The main difference here is that there are
return values that we need to pay attention to. <tt>Z_DATA_ERROR</tt>
indicates that <tt>inflate()</tt> detected an error in the <em>zlib</em> compressed data format,
which means that either the data is not a <em>zlib</em> stream to begin with, or that the data was
corrupted somewhere along the way since it was compressed. The other error to be processed is
<tt>Z_MEM_ERROR</tt>, which can occur since memory allocation is deferred until <tt>inflate()</tt>
needs it, unlike <tt>deflate()</tt>, whose memory is allocated at the start by <tt>deflateInit()</tt>.
<p>
Advanced applications may use
<tt>deflateSetDictionary()</tt> to prime <tt>deflate()</tt> with a set of likely data to improve the
first 32K or so of compression. This is noted in the <em>zlib</em> header, so <tt>inflate()</tt>
requests that that dictionary be provided before it can start to decompress. Without the dictionary,
correct decompression is not possible. For this routine, we have no idea what the dictionary is,
so the <tt>Z_NEED_DICT</tt> indication is converted to a <tt>Z_DATA_ERROR</tt>.
<p>
<tt>inflate()</tt> can also return <tt>Z_STREAM_ERROR</tt>, which should not be possible here,
but could be checked for as noted above for <tt>def()</tt>. <tt>Z_BUF_ERROR</tt> does not need to be
checked for here, for the same reasons noted for <tt>def()</tt>. <tt>Z_STREAM_END</tt> will be
checked for later.
<pre><b>
ret = inflate(&amp;strm, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
switch (ret) {
case Z_NEED_DICT:
ret = Z_DATA_ERROR; /* and fall through */
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&amp;strm);
return ret;
}
</b></pre>
The output of <tt>inflate()</tt> is handled identically to that of <tt>deflate()</tt>.
<pre><b>
have = CHUNK - strm.avail_out;
if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
(void)inflateEnd(&amp;strm);
return Z_ERRNO;
}
</b></pre>
The inner <tt>do</tt>-loop ends when <tt>inflate()</tt> has no more output as indicated
by not filling the output buffer, just as for <tt>deflate()</tt>. In this case, we cannot
assert that <tt>strm.avail_in</tt> will be zero, since the deflate stream may end before the file
does.
<pre><b>
} while (strm.avail_out == 0);
</b></pre><!-- -->
The outer <tt>do</tt>-loop ends when <tt>inflate()</tt> reports that it has reached the
end of the input <em>zlib</em> stream, has completed the decompression and integrity
check, and has provided all of the output. This is indicated by the <tt>inflate()</tt>
return value <tt>Z_STREAM_END</tt>. The inner loop is guaranteed to leave <tt>ret</tt>
equal to <tt>Z_STREAM_END</tt> if the last chunk of the input file read contained the end
of the <em>zlib</em> stream. So if the return value is not <tt>Z_STREAM_END</tt>, the
loop continues to read more input.
<pre><b>
/* done when inflate() says it's done */
} while (ret != Z_STREAM_END);
</b></pre><!-- -->
At this point, decompression successfully completed, or we broke out of the loop due to no
more data being available from the input file. If the last <tt>inflate()</tt> return value
is not <tt>Z_STREAM_END</tt>, then the <em>zlib</em> stream was incomplete and a data error
is returned. Otherwise, we return with a happy return value. Of course, <tt>inflateEnd()</tt>
is called first to avoid a memory leak.
<pre><b>
/* clean up and return */
(void)inflateEnd(&amp;strm);
return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
}
</b></pre><!-- -->
That ends the routines that directly use <em>zlib</em>. The following routines make this
a command-line program by running data through the above routines from <tt>stdin</tt> to
<tt>stdout</tt>, and handling any errors reported by <tt>def()</tt> or <tt>inf()</tt>.
<p>
<tt>zerr()</tt> is used to interpret the possible error codes from <tt>def()</tt>
and <tt>inf()</tt>, as detailed in their comments above, and print out an error message.
Note that these are only a subset of the possible return values from <tt>deflate()</tt>
and <tt>inflate()</tt>.
<pre><b>
/* report a zlib or i/o error */
void zerr(int ret)
{
fputs("zpipe: ", stderr);
switch (ret) {
case Z_ERRNO:
if (ferror(stdin))
fputs("error reading stdin\n", stderr);
if (ferror(stdout))
fputs("error writing stdout\n", stderr);
break;
case Z_STREAM_ERROR:
fputs("invalid compression level\n", stderr);
break;
case Z_DATA_ERROR:
fputs("invalid or incomplete deflate data\n", stderr);
break;
case Z_MEM_ERROR:
fputs("out of memory\n", stderr);
break;
case Z_VERSION_ERROR:
fputs("zlib version mismatch!\n", stderr);
}
}
</b></pre><!-- -->
Here is the <tt>main()</tt> routine used to test <tt>def()</tt> and <tt>inf()</tt>. The
<tt>zpipe</tt> command is simply a compression pipe from <tt>stdin</tt> to <tt>stdout</tt>, if
no arguments are given, or it is a decompression pipe if <tt>zpipe -d</tt> is used. If any other
arguments are provided, no compression or decompression is performed. Instead a usage
message is displayed. Examples are <tt>zpipe < foo.txt > foo.txt.z</tt> to compress, and
<tt>zpipe -d < foo.txt.z > foo.txt</tt> to decompress.
<pre><b>
/* compress or decompress from stdin to stdout */
int main(int argc, char **argv)
{
int ret;
/* do compression if no arguments */
if (argc == 1) {
ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION);
if (ret != Z_OK)
zerr(ret);
return ret;
}
/* do decompression if -d specified */
else if (argc == 2 &amp;&amp; strcmp(argv[1], "-d") == 0) {
ret = inf(stdin, stdout);
if (ret != Z_OK)
zerr(ret);
return ret;
}
/* otherwise, report usage */
else {
fputs("zpipe usage: zpipe [-d] &lt; source &gt; dest\n", stderr);
return 1;
}
}
</b></pre>
<hr>
<i>Copyright (c) 2004 by Mark Adler<br>Last modified 13 November 2004</i>
</body>
</html>

191
examples/zpipe.c Normal file
View File

@@ -0,0 +1,191 @@
/* zpipe.c: example of proper use of zlib's inflate() and deflate()
Not copyrighted -- provided to the public domain
Version 1.2 9 November 2004 Mark Adler */
/* Version history:
1.0 30 Oct 2004 First version
1.1 8 Nov 2004 Add void casting for unused return values
Use switch statement for inflate() return values
1.2 9 Nov 2004 Add assertions to document zlib guarantees
1.3 6 Apr 2005 Remove incorrect assertion in inf()
*/
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "zlib.h"
#define CHUNK 16384
/* Compress from file source to file dest until EOF on source.
def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
allocated for processing, Z_STREAM_ERROR if an invalid compression
level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
version of the library linked do not match, or Z_ERRNO if there is
an error reading or writing the files. */
int def(FILE *source, FILE *dest, int level)
{
int ret, flush;
unsigned have;
z_stream strm;
char in[CHUNK];
char out[CHUNK];
/* allocate deflate state */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
ret = deflateInit(&strm, level);
if (ret != Z_OK)
return ret;
/* compress until end of file */
do {
strm.avail_in = fread(in, 1, CHUNK, source);
if (ferror(source)) {
(void)deflateEnd(&strm);
return Z_ERRNO;
}
flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
strm.next_in = in;
/* run deflate() on input until output buffer not full, finish
compression if all of source has been read in */
do {
strm.avail_out = CHUNK;
strm.next_out = out;
ret = deflate(&strm, flush); /* no bad return value */
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
have = CHUNK - strm.avail_out;
if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
(void)deflateEnd(&strm);
return Z_ERRNO;
}
} while (strm.avail_out == 0);
assert(strm.avail_in == 0); /* all input will be used */
/* done when last data in file processed */
} while (flush != Z_FINISH);
assert(ret == Z_STREAM_END); /* stream will be complete */
/* clean up and return */
(void)deflateEnd(&strm);
return Z_OK;
}
/* Decompress from file source to file dest until stream ends or EOF.
inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
allocated for processing, Z_DATA_ERROR if the deflate data is
invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
the version of the library linked do not match, or Z_ERRNO if there
is an error reading or writing the files. */
int inf(FILE *source, FILE *dest)
{
int ret;
unsigned have;
z_stream strm;
char in[CHUNK];
char out[CHUNK];
/* allocate inflate state */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit(&strm);
if (ret != Z_OK)
return ret;
/* decompress until deflate stream ends or end of file */
do {
strm.avail_in = fread(in, 1, CHUNK, source);
if (ferror(source)) {
(void)inflateEnd(&strm);
return Z_ERRNO;
}
if (strm.avail_in == 0)
break;
strm.next_in = in;
/* run inflate() on input until output buffer not full */
do {
strm.avail_out = CHUNK;
strm.next_out = out;
ret = inflate(&strm, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
switch (ret) {
case Z_NEED_DICT:
ret = Z_DATA_ERROR; /* and fall through */
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&strm);
return ret;
}
have = CHUNK - strm.avail_out;
if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
(void)inflateEnd(&strm);
return Z_ERRNO;
}
} while (strm.avail_out == 0);
/* done when inflate() says it's done */
} while (ret != Z_STREAM_END);
/* clean up and return */
(void)inflateEnd(&strm);
return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
}
/* report a zlib or i/o error */
void zerr(int ret)
{
fputs("zpipe: ", stderr);
switch (ret) {
case Z_ERRNO:
if (ferror(stdin))
fputs("error reading stdin\n", stderr);
if (ferror(stdout))
fputs("error writing stdout\n", stderr);
break;
case Z_STREAM_ERROR:
fputs("invalid compression level\n", stderr);
break;
case Z_DATA_ERROR:
fputs("invalid or incomplete deflate data\n", stderr);
break;
case Z_MEM_ERROR:
fputs("out of memory\n", stderr);
break;
case Z_VERSION_ERROR:
fputs("zlib version mismatch!\n", stderr);
}
}
/* compress or decompress from stdin to stdout */
int main(int argc, char **argv)
{
int ret;
/* do compression if no arguments */
if (argc == 1) {
ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION);
if (ret != Z_OK)
zerr(ret);
return ret;
}
/* do decompression if -d specified */
else if (argc == 2 && strcmp(argv[1], "-d") == 0) {
ret = inf(stdin, stdout);
if (ret != Z_OK)
zerr(ret);
return ret;
}
/* otherwise, report usage */
else {
fputs("zpipe usage: zpipe [-d] < source > dest\n", stderr);
return 1;
}
}

404
examples/zran.c Normal file
View File

@@ -0,0 +1,404 @@
/* zran.c -- example of zlib/gzip stream indexing and random access
* Copyright (C) 2005 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
Version 1.0 29 May 2005 Mark Adler */
/* Illustrate the use of Z_BLOCK, inflatePrime(), and inflateSetDictionary()
for random access of a compressed file. A file containing a zlib or gzip
stream is provided on the command line. The compressed stream is decoded in
its entirety, and an index built with access points about every SPAN bytes
in the uncompressed output. The compressed file is left open, and can then
be read randomly, having to decompress on the average SPAN/2 uncompressed
bytes before getting to the desired block of data.
An access point can be created at the start of any deflate block, by saving
the starting file offset and bit of that block, and the 32K bytes of
uncompressed data that precede that block. Also the uncompressed offset of
that block is saved to provide a referece for locating a desired starting
point in the uncompressed stream. build_index() works by decompressing the
input zlib or gzip stream a block at a time, and at the end of each block
deciding if enough uncompressed data has gone by to justify the creation of
a new access point. If so, that point is saved in a data structure that
grows as needed to accommodate the points.
To use the index, an offset in the uncompressed data is provided, for which
the latest accees point at or preceding that offset is located in the index.
The input file is positioned to the specified location in the index, and if
necessary the first few bits of the compressed data is read from the file.
inflate is initialized with those bits and the 32K of uncompressed data, and
the decompression then proceeds until the desired offset in the file is
reached. Then the decompression continues to read the desired uncompressed
data from the file.
Another approach would be to generate the index on demand. In that case,
requests for random access reads from the compressed data would try to use
the index, but if a read far enough past the end of the index is required,
then further index entries would be generated and added.
There is some fair bit of overhead to starting inflation for the random
access, mainly copying the 32K byte dictionary. So if small pieces of the
file are being accessed, it would make sense to implement a cache to hold
some lookahead and avoid many calls to extract() for small lengths.
Another way to build an index would be to use inflateCopy(). That would
not be constrained to have access points at block boundaries, but requires
more memory per access point, and also cannot be saved to file due to the
use of pointers in the state. The approach here allows for storage of the
index in a file.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "zlib.h"
#define local static
#define SPAN 1048576L /* desired distance between access points */
#define WINSIZE 32768U /* sliding window size */
#define CHUNK 16384 /* file input buffer size */
/* access point entry */
struct point {
off_t out; /* corresponding offset in uncompressed data */
off_t in; /* offset in input file of first full byte */
int bits; /* number of bits (1-7) from byte at in - 1, or 0 */
unsigned char window[WINSIZE]; /* preceding 32K of uncompressed data */
};
/* access point list */
struct access {
int have; /* number of list entries filled in */
int size; /* number of list entries allocated */
struct point *list; /* allocated list */
};
/* Deallocate an index built by build_index() */
local void free_index(struct access *index)
{
if (index != NULL) {
free(index->list);
free(index);
}
}
/* Add an entry to the access point list. If out of memory, deallocate the
existing list and return NULL. */
local struct access *addpoint(struct access *index, int bits,
off_t in, off_t out, unsigned left, unsigned char *window)
{
struct point *next;
/* if list is empty, create it (start with eight points) */
if (index == NULL) {
index = malloc(sizeof(struct access));
if (index == NULL) return NULL;
index->list = malloc(sizeof(struct point) << 3);
if (index->list == NULL) {
free(index);
return NULL;
}
index->size = 8;
index->have = 0;
}
/* if list is full, make it bigger */
else if (index->have == index->size) {
index->size <<= 1;
next = realloc(index->list, sizeof(struct point) * index->size);
if (next == NULL) {
free_index(index);
return NULL;
}
index->list = next;
}
/* fill in entry and increment how many we have */
next = index->list + index->have;
next->bits = bits;
next->in = in;
next->out = out;
if (left)
memcpy(next->window, window + WINSIZE - left, left);
if (left < WINSIZE)
memcpy(next->window + left, window, WINSIZE - left);
index->have++;
/* return list, possibly reallocated */
return index;
}
/* Make one entire pass through the compressed stream and build an index, with
access points about every span bytes of uncompressed output -- span is
chosen to balance the speed of random access against the memory requirements
of the list, about 32K bytes per access point. Note that data after the end
of the first zlib or gzip stream in the file is ignored. build_index()
returns the number of access points on success (>= 1), Z_MEM_ERROR for out
of memory, Z_DATA_ERROR for an error in the input file, or Z_ERRNO for a
file read error. On success, *built points to the resulting index. */
local int build_index(FILE *in, off_t span, struct access **built)
{
int ret;
off_t totin, totout; /* our own total counters to avoid 4GB limit */
off_t last; /* totout value of last access point */
struct access *index; /* access points being generated */
z_stream strm;
unsigned char input[CHUNK];
unsigned char window[WINSIZE];
/* initialize inflate */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit2(&strm, 47); /* automatic zlib or gzip decoding */
if (ret != Z_OK)
return ret;
/* inflate the input, maintain a sliding window, and build an index -- this
also validates the integrity of the compressed data using the check
information at the end of the gzip or zlib stream */
totin = totout = last = 0;
index = NULL; /* will be allocated by first addpoint() */
strm.avail_out = 0;
do {
/* get some compressed data from input file */
strm.avail_in = fread(input, 1, CHUNK, in);
if (ferror(in)) {
ret = Z_ERRNO;
goto build_index_error;
}
if (strm.avail_in == 0) {
ret = Z_DATA_ERROR;
goto build_index_error;
}
strm.next_in = input;
/* process all of that, or until end of stream */
do {
/* reset sliding window if necessary */
if (strm.avail_out == 0) {
strm.avail_out = WINSIZE;
strm.next_out = window;
}
/* inflate until out of input, output, or at end of block --
update the total input and output counters */
totin += strm.avail_in;
totout += strm.avail_out;
ret = inflate(&strm, Z_BLOCK); /* return at end of block */
totin -= strm.avail_in;
totout -= strm.avail_out;
if (ret == Z_NEED_DICT)
ret = Z_DATA_ERROR;
if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR)
goto build_index_error;
if (ret == Z_STREAM_END)
break;
/* if at end of block, consider adding an index entry (note that if
data_type indicates an end-of-block, then all of the
uncompressed data from that block has been delivered, and none
of the compressed data after that block has been consumed,
except for up to seven bits) -- the totout == 0 provides an
entry point after the zlib or gzip header, and assures that the
index always has at least one access point; we avoid creating an
access point after the last block by checking bit 6 of data_type
*/
if ((strm.data_type & 128) && !(strm.data_type & 64) &&
(totout == 0 || totout - last > span)) {
index = addpoint(index, strm.data_type & 7, totin,
totout, strm.avail_out, window);
if (index == NULL) {
ret = Z_MEM_ERROR;
goto build_index_error;
}
last = totout;
}
} while (strm.avail_in != 0);
} while (ret != Z_STREAM_END);
/* clean up and return index (release unused entries in list) */
(void)inflateEnd(&strm);
index = realloc(index, sizeof(struct point) * index->have);
index->size = index->have;
*built = index;
return index->size;
/* return error */
build_index_error:
(void)inflateEnd(&strm);
if (index != NULL)
free_index(index);
return ret;
}
/* Use the index to read len bytes from offset into buf, return bytes read or
negative for error (Z_DATA_ERROR or Z_MEM_ERROR). If data is requested past
the end of the uncompressed data, then extract() will return a value less
than len, indicating how much as actually read into buf. This function
should not return a data error unless the file was modified since the index
was generated. extract() may also return Z_ERRNO if there is an error on
reading or seeking the input file. */
local int extract(FILE *in, struct access *index, off_t offset,
unsigned char *buf, int len)
{
int ret, skip;
z_stream strm;
struct point *here;
unsigned char input[CHUNK];
unsigned char discard[WINSIZE];
/* proceed only if something reasonable to do */
if (len < 0)
return 0;
/* find where in stream to start */
here = index->list;
ret = index->have;
while (--ret && here[1].out <= offset)
here++;
/* initialize file and inflate state to start there */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit2(&strm, -15); /* raw inflate */
if (ret != Z_OK)
return ret;
ret = fseeko(in, here->in - (here->bits ? 1 : 0), SEEK_SET);
if (ret == -1)
goto extract_ret;
if (here->bits) {
ret = getc(in);
if (ret == -1) {
ret = ferror(in) ? Z_ERRNO : Z_DATA_ERROR;
goto extract_ret;
}
(void)inflatePrime(&strm, here->bits, ret >> (8 - here->bits));
}
(void)inflateSetDictionary(&strm, here->window, WINSIZE);
/* skip uncompressed bytes until offset reached, then satisfy request */
offset -= here->out;
strm.avail_in = 0;
skip = 1; /* while skipping to offset */
do {
/* define where to put uncompressed data, and how much */
if (offset == 0 && skip) { /* at offset now */
strm.avail_out = len;
strm.next_out = buf;
skip = 0; /* only do this once */
}
if (offset > WINSIZE) { /* skip WINSIZE bytes */
strm.avail_out = WINSIZE;
strm.next_out = discard;
offset -= WINSIZE;
}
else if (offset != 0) { /* last skip */
strm.avail_out = (unsigned)offset;
strm.next_out = discard;
offset = 0;
}
/* uncompress until avail_out filled, or end of stream */
do {
if (strm.avail_in == 0) {
strm.avail_in = fread(input, 1, CHUNK, in);
if (ferror(in)) {
ret = Z_ERRNO;
goto extract_ret;
}
if (strm.avail_in == 0) {
ret = Z_DATA_ERROR;
goto extract_ret;
}
strm.next_in = input;
}
ret = inflate(&strm, Z_NO_FLUSH); /* normal inflate */
if (ret == Z_NEED_DICT)
ret = Z_DATA_ERROR;
if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR)
goto extract_ret;
if (ret == Z_STREAM_END)
break;
} while (strm.avail_out != 0);
/* if reach end of stream, then don't keep trying to get more */
if (ret == Z_STREAM_END)
break;
/* do until offset reached and requested data read, or stream ends */
} while (skip);
/* compute number of uncompressed bytes read after offset */
ret = skip ? 0 : len - strm.avail_out;
/* clean up and return bytes read or error */
extract_ret:
(void)inflateEnd(&strm);
return ret;
}
/* Demonstrate the use of build_index() and extract() by processing the file
provided on the command line, and the extracting 16K from about 2/3rds of
the way through the uncompressed output, and writing that to stdout. */
int main(int argc, char **argv)
{
int len;
off_t offset;
FILE *in;
struct access *index;
unsigned char buf[CHUNK];
/* open input file */
if (argc != 2) {
fprintf(stderr, "usage: zran file.gz\n");
return 1;
}
in = fopen(argv[1], "rb");
if (in == NULL) {
fprintf(stderr, "zran: could not open %s for reading\n", argv[1]);
return 1;
}
/* build index */
len = build_index(in, SPAN, &index);
if (len < 0) {
fclose(in);
switch (len) {
case Z_MEM_ERROR:
fprintf(stderr, "zran: out of memory\n");
break;
case Z_DATA_ERROR:
fprintf(stderr, "zran: compressed data error in %s\n", argv[1]);
break;
case Z_ERRNO:
fprintf(stderr, "zran: read error on %s\n", argv[1]);
break;
default:
fprintf(stderr, "zran: error %d while building index\n", len);
}
return 1;
}
fprintf(stderr, "zran: built index with %d access points\n", len);
/* use index by reading some bytes from an arbitrary offset */
offset = (index->list[index->have - 1].out << 1) / 3;
len = extract(in, index, offset, buf, CHUNK);
if (len < 0)
fprintf(stderr, "zran: extraction failed: %s error\n",
len == Z_MEM_ERROR ? "out of memory" : "input corrupted");
else {
fwrite(buf, 1, len, stdout);
fprintf(stderr, "zran: extracted %d bytes at %llu\n", len, offset);
}
/* clean up and exit */
free_index(index);
fclose(in);
return 0;
}

51
gzio.c
View File

@@ -1,5 +1,5 @@
/* gzio.c -- IO on .gz files /* gzio.c -- IO on .gz files
* Copyright (C) 1995-2003 Jean-loup Gailly. * Copyright (C) 1995-2005 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
* *
* Compile this file with -DNO_GZCOMPRESS to avoid the compression code. * Compile this file with -DNO_GZCOMPRESS to avoid the compression code.
@@ -11,7 +11,7 @@
#include "zutil.h" #include "zutil.h"
#ifdef NO_DEFLATE /* for compatiblity with old definition */ #ifdef NO_DEFLATE /* for compatibility with old definition */
# define NO_GZCOMPRESS # define NO_GZCOMPRESS
#endif #endif
@@ -220,7 +220,7 @@ gzFile ZEXPORT gzdopen (fd, mode)
int fd; int fd;
const char *mode; const char *mode;
{ {
char name[20]; char name[46]; /* allow for up to 128-bit integers */
if (fd < 0) return (gzFile)Z_NULL; if (fd < 0) return (gzFile)Z_NULL;
sprintf(name, "<fd:%d>", fd); /* for debugging */ sprintf(name, "<fd:%d>", fd); /* for debugging */
@@ -264,7 +264,7 @@ local int get_byte(s)
if (s->z_eof) return EOF; if (s->z_eof) return EOF;
if (s->stream.avail_in == 0) { if (s->stream.avail_in == 0) {
errno = 0; errno = 0;
s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
if (s->stream.avail_in == 0) { if (s->stream.avail_in == 0) {
s->z_eof = 1; s->z_eof = 1;
if (ferror(s->file)) s->z_err = Z_ERRNO; if (ferror(s->file)) s->z_err = Z_ERRNO;
@@ -300,7 +300,7 @@ local void check_header(s)
if (len < 2) { if (len < 2) {
if (len) s->inbuf[0] = s->stream.next_in[0]; if (len) s->inbuf[0] = s->stream.next_in[0];
errno = 0; errno = 0;
len = fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO;
s->stream.avail_in += len; s->stream.avail_in += len;
s->stream.next_in = s->inbuf; s->stream.next_in = s->inbuf;
@@ -415,6 +415,7 @@ int ZEXPORT gzread (file, buf, len)
s->stream.avail_out--; s->stream.avail_out--;
s->back = EOF; s->back = EOF;
s->out++; s->out++;
start++;
if (s->last) { if (s->last) {
s->z_err = Z_STREAM_END; s->z_err = Z_STREAM_END;
return 1; return 1;
@@ -436,8 +437,8 @@ int ZEXPORT gzread (file, buf, len)
s->stream.avail_in -= n; s->stream.avail_in -= n;
} }
if (s->stream.avail_out > 0) { if (s->stream.avail_out > 0) {
s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out, s->stream.avail_out -=
s->file); (uInt)fread(next_out, 1, s->stream.avail_out, s->file);
} }
len -= s->stream.avail_out; len -= s->stream.avail_out;
s->in += len; s->in += len;
@@ -448,17 +449,13 @@ int ZEXPORT gzread (file, buf, len)
if (s->stream.avail_in == 0 && !s->z_eof) { if (s->stream.avail_in == 0 && !s->z_eof) {
errno = 0; errno = 0;
s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
if (s->stream.avail_in == 0) { if (s->stream.avail_in == 0) {
s->z_eof = 1; s->z_eof = 1;
if (ferror(s->file)) { if (ferror(s->file)) {
s->z_err = Z_ERRNO; s->z_err = Z_ERRNO;
break; break;
} }
if (feof(s->file)) { /* avoid error for empty file */
s->z_err = Z_STREAM_END;
break;
}
} }
s->stream.next_in = s->inbuf; s->stream.next_in = s->inbuf;
} }
@@ -492,6 +489,9 @@ int ZEXPORT gzread (file, buf, len)
} }
s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
if (len == s->stream.avail_out &&
(s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO))
return -1;
return (int)(len - s->stream.avail_out); return (int)(len - s->stream.avail_out);
} }
@@ -902,6 +902,18 @@ int ZEXPORT gzeof (file)
return s->z_err == Z_STREAM_END; return s->z_err == Z_STREAM_END;
} }
/* ===========================================================================
Returns 1 if reading and doing so transparently, otherwise zero.
*/
int ZEXPORT gzdirect (file)
gzFile file;
{
gz_stream *s = (gz_stream*)file;
if (s == NULL || s->mode != 'r') return 0;
return s->transparent;
}
/* =========================================================================== /* ===========================================================================
Outputs a long in LSB order to the given file Outputs a long in LSB order to the given file
*/ */
@@ -941,7 +953,6 @@ local uLong getLong (s)
int ZEXPORT gzclose (file) int ZEXPORT gzclose (file)
gzFile file; gzFile file;
{ {
int err;
gz_stream *s = (gz_stream*)file; gz_stream *s = (gz_stream*)file;
if (s == NULL) return Z_STREAM_ERROR; if (s == NULL) return Z_STREAM_ERROR;
@@ -950,8 +961,8 @@ int ZEXPORT gzclose (file)
#ifdef NO_GZCOMPRESS #ifdef NO_GZCOMPRESS
return Z_STREAM_ERROR; return Z_STREAM_ERROR;
#else #else
err = do_flush (file, Z_FINISH); if (do_flush (file, Z_FINISH) != Z_OK)
if (err != Z_OK) return destroy((gz_stream*)file); return destroy((gz_stream*)file);
putLong (s->file, s->crc); putLong (s->file, s->crc);
putLong (s->file, (uLong)(s->in & 0xffffffff)); putLong (s->file, (uLong)(s->in & 0xffffffff));
@@ -960,10 +971,16 @@ int ZEXPORT gzclose (file)
return destroy((gz_stream*)file); return destroy((gz_stream*)file);
} }
#ifdef STDC
# define zstrerror(errnum) strerror(errnum)
#else
# define zstrerror(errnum) ""
#endif
/* =========================================================================== /* ===========================================================================
Returns the error message for the last error which occured on the Returns the error message for the last error which occurred on the
given compressed file. errnum is set to zlib error number. If an given compressed file. errnum is set to zlib error number. If an
error occured in the file system and not in the compression library, error occurred in the file system and not in the compression library,
errnum is set to Z_ERRNO and the application may consult errno errnum is set to Z_ERRNO and the application may consult errno
to get the exact error code. to get the exact error code.
*/ */

View File

@@ -1,5 +1,5 @@
/* infback.c -- inflate using a call-back interface /* infback.c -- inflate using a call-back interface
* Copyright (C) 1995-2003 Mark Adler * Copyright (C) 1995-2005 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@@ -26,7 +26,7 @@ local void fixedtables OF((struct inflate_state FAR *state));
window and output buffer that is 2**windowBits bytes. window and output buffer that is 2**windowBits bytes.
*/ */
int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
z_stream FAR *strm; z_streamp strm;
int windowBits; int windowBits;
unsigned char FAR *window; unsigned char FAR *window;
const char *version; const char *version;
@@ -50,7 +50,8 @@ int stream_size;
sizeof(struct inflate_state)); sizeof(struct inflate_state));
if (state == Z_NULL) return Z_MEM_ERROR; if (state == Z_NULL) return Z_MEM_ERROR;
Tracev((stderr, "inflate: allocated\n")); Tracev((stderr, "inflate: allocated\n"));
strm->state = (voidpf)state; strm->state = (struct internal_state FAR *)state;
state->dmax = 32768U;
state->wbits = windowBits; state->wbits = windowBits;
state->wsize = 1U << windowBits; state->wsize = 1U << windowBits;
state->window = window; state->window = window;
@@ -238,7 +239,7 @@ struct inflate_state FAR *state;
are not correct, i.e. strm is Z_NULL or the state was not initialized. 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) int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
z_stream FAR *strm; z_streamp strm;
in_func in; in_func in;
void FAR *in_desc; void FAR *in_desc;
out_func out; out_func out;
@@ -611,7 +612,7 @@ void FAR *out_desc;
} }
int ZEXPORT inflateBackEnd(strm) int ZEXPORT inflateBackEnd(strm)
z_stream FAR *strm; z_streamp strm;
{ {
if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
return Z_STREAM_ERROR; return Z_STREAM_ERROR;

View File

@@ -74,6 +74,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
unsigned char FAR *out; /* local strm->next_out */ unsigned char FAR *out; /* local strm->next_out */
unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
unsigned char FAR *end; /* while out < end, enough space available */ unsigned char FAR *end; /* while out < end, enough space available */
#ifdef INFLATE_STRICT
unsigned dmax; /* maximum distance from zlib header */
#endif
unsigned wsize; /* window size or zero if not using window */ unsigned wsize; /* window size or zero if not using window */
unsigned whave; /* valid bytes in the window */ unsigned whave; /* valid bytes in the window */
unsigned write; /* window write index */ unsigned write; /* window write index */
@@ -98,6 +101,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
out = strm->next_out - OFF; out = strm->next_out - OFF;
beg = out - (start - strm->avail_out); beg = out - (start - strm->avail_out);
end = out + (strm->avail_out - 257); end = out + (strm->avail_out - 257);
#ifdef INFLATE_STRICT
dmax = state->dmax;
#endif
wsize = state->wsize; wsize = state->wsize;
whave = state->whave; whave = state->whave;
write = state->write; write = state->write;
@@ -167,6 +173,13 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
} }
} }
dist += (unsigned)hold & ((1U << op) - 1); dist += (unsigned)hold & ((1U << op) - 1);
#ifdef INFLATE_STRICT
if (dist > dmax) {
strm->msg = (char *)"invalid distance too far back";
state->mode = BAD;
break;
}
#endif
hold >>= op; hold >>= op;
bits -= op; bits -= op;
Tracevv((stderr, "inflate: distance %u\n", dist)); Tracevv((stderr, "inflate: distance %u\n", dist));

118
inflate.c
View File

@@ -1,5 +1,5 @@
/* inflate.c -- zlib decompression /* inflate.c -- zlib decompression
* Copyright (C) 1995-2003 Mark Adler * Copyright (C) 1995-2005 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@@ -113,8 +113,11 @@ z_streamp strm;
state->mode = HEAD; state->mode = HEAD;
state->last = 0; state->last = 0;
state->havedict = 0; state->havedict = 0;
state->dmax = 32768U;
state->head = Z_NULL;
state->wsize = 0; state->wsize = 0;
state->whave = 0; state->whave = 0;
state->write = 0;
state->hold = 0; state->hold = 0;
state->bits = 0; state->bits = 0;
state->lencode = state->distcode = state->next = state->codes; state->lencode = state->distcode = state->next = state->codes;
@@ -122,6 +125,22 @@ z_streamp strm;
return Z_OK; return Z_OK;
} }
int ZEXPORT inflatePrime(strm, bits, value)
z_streamp strm;
int bits;
int value;
{
struct inflate_state FAR *state;
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state;
if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
value &= (1L << bits) - 1;
state->hold += value << state->bits;
state->bits += bits;
return Z_OK;
}
int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
z_streamp strm; z_streamp strm;
int windowBits; int windowBits;
@@ -144,7 +163,7 @@ int stream_size;
ZALLOC(strm, 1, sizeof(struct inflate_state)); ZALLOC(strm, 1, sizeof(struct inflate_state));
if (state == Z_NULL) return Z_MEM_ERROR; if (state == Z_NULL) return Z_MEM_ERROR;
Tracev((stderr, "inflate: allocated\n")); Tracev((stderr, "inflate: allocated\n"));
strm->state = (voidpf)state; strm->state = (struct internal_state FAR *)state;
if (windowBits < 0) { if (windowBits < 0) {
state->wrap = 0; state->wrap = 0;
windowBits = -windowBits; windowBits = -windowBits;
@@ -582,6 +601,8 @@ int flush;
break; break;
} }
state->flags = 0; /* expect zlib header */ state->flags = 0; /* expect zlib header */
if (state->head != Z_NULL)
state->head->done = -1;
if (!(state->wrap & 1) || /* check if zlib header allowed */ if (!(state->wrap & 1) || /* check if zlib header allowed */
#else #else
if ( if (
@@ -597,11 +618,13 @@ int flush;
break; break;
} }
DROPBITS(4); DROPBITS(4);
if (BITS(4) + 8 > state->wbits) { len = BITS(4) + 8;
if (len > state->wbits) {
strm->msg = (char *)"invalid window size"; strm->msg = (char *)"invalid window size";
state->mode = BAD; state->mode = BAD;
break; break;
} }
state->dmax = 1U << len;
Tracev((stderr, "inflate: zlib header ok\n")); Tracev((stderr, "inflate: zlib header ok\n"));
strm->adler = state->check = adler32(0L, Z_NULL, 0); strm->adler = state->check = adler32(0L, Z_NULL, 0);
state->mode = hold & 0x200 ? DICTID : TYPE; state->mode = hold & 0x200 ? DICTID : TYPE;
@@ -621,16 +644,24 @@ int flush;
state->mode = BAD; state->mode = BAD;
break; break;
} }
if (state->head != Z_NULL)
state->head->text = (int)((hold >> 8) & 1);
if (state->flags & 0x0200) CRC2(state->check, hold); if (state->flags & 0x0200) CRC2(state->check, hold);
INITBITS(); INITBITS();
state->mode = TIME; state->mode = TIME;
case TIME: case TIME:
NEEDBITS(32); NEEDBITS(32);
if (state->head != Z_NULL)
state->head->time = hold;
if (state->flags & 0x0200) CRC4(state->check, hold); if (state->flags & 0x0200) CRC4(state->check, hold);
INITBITS(); INITBITS();
state->mode = OS; state->mode = OS;
case OS: case OS:
NEEDBITS(16); NEEDBITS(16);
if (state->head != Z_NULL) {
state->head->xflags = (int)(hold & 0xff);
state->head->os = (int)(hold >> 8);
}
if (state->flags & 0x0200) CRC2(state->check, hold); if (state->flags & 0x0200) CRC2(state->check, hold);
INITBITS(); INITBITS();
state->mode = EXLEN; state->mode = EXLEN;
@@ -638,15 +669,26 @@ int flush;
if (state->flags & 0x0400) { if (state->flags & 0x0400) {
NEEDBITS(16); NEEDBITS(16);
state->length = (unsigned)(hold); state->length = (unsigned)(hold);
if (state->head != Z_NULL)
state->head->extra_len = (unsigned)hold;
if (state->flags & 0x0200) CRC2(state->check, hold); if (state->flags & 0x0200) CRC2(state->check, hold);
INITBITS(); INITBITS();
} }
else if (state->head != Z_NULL)
state->head->extra = Z_NULL;
state->mode = EXTRA; state->mode = EXTRA;
case EXTRA: case EXTRA:
if (state->flags & 0x0400) { if (state->flags & 0x0400) {
copy = state->length; copy = state->length;
if (copy > have) copy = have; if (copy > have) copy = have;
if (copy) { if (copy) {
if (state->head != Z_NULL &&
state->head->extra != Z_NULL) {
len = state->head->extra_len - state->length;
zmemcpy(state->head->extra + len, next,
len + copy > state->head->extra_max ?
state->head->extra_max - len : copy);
}
if (state->flags & 0x0200) if (state->flags & 0x0200)
state->check = crc32(state->check, next, copy); state->check = crc32(state->check, next, copy);
have -= copy; have -= copy;
@@ -655,6 +697,7 @@ int flush;
} }
if (state->length) goto inf_leave; if (state->length) goto inf_leave;
} }
state->length = 0;
state->mode = NAME; state->mode = NAME;
case NAME: case NAME:
if (state->flags & 0x0800) { if (state->flags & 0x0800) {
@@ -662,13 +705,20 @@ int flush;
copy = 0; copy = 0;
do { do {
len = (unsigned)(next[copy++]); len = (unsigned)(next[copy++]);
if (state->head != Z_NULL &&
state->head->name != Z_NULL &&
state->length < state->head->name_max)
state->head->name[state->length++] = len;
} while (len && copy < have); } while (len && copy < have);
if (state->flags & 0x02000) if (state->flags & 0x0200)
state->check = crc32(state->check, next, copy); state->check = crc32(state->check, next, copy);
have -= copy; have -= copy;
next += copy; next += copy;
if (len) goto inf_leave; if (len) goto inf_leave;
} }
else if (state->head != Z_NULL)
state->head->name = Z_NULL;
state->length = 0;
state->mode = COMMENT; state->mode = COMMENT;
case COMMENT: case COMMENT:
if (state->flags & 0x1000) { if (state->flags & 0x1000) {
@@ -676,13 +726,19 @@ int flush;
copy = 0; copy = 0;
do { do {
len = (unsigned)(next[copy++]); len = (unsigned)(next[copy++]);
if (state->head != Z_NULL &&
state->head->comment != Z_NULL &&
state->length < state->head->comm_max)
state->head->comment[state->length++] = len;
} while (len && copy < have); } while (len && copy < have);
if (state->flags & 0x02000) if (state->flags & 0x0200)
state->check = crc32(state->check, next, copy); state->check = crc32(state->check, next, copy);
have -= copy; have -= copy;
next += copy; next += copy;
if (len) goto inf_leave; if (len) goto inf_leave;
} }
else if (state->head != Z_NULL)
state->head->comment = Z_NULL;
state->mode = HCRC; state->mode = HCRC;
case HCRC: case HCRC:
if (state->flags & 0x0200) { if (state->flags & 0x0200) {
@@ -694,6 +750,10 @@ int flush;
} }
INITBITS(); INITBITS();
} }
if (state->head != Z_NULL) {
state->head->hcrc = (int)((state->flags >> 9) & 1);
state->head->done = 1;
}
strm->adler = state->check = crc32(0L, Z_NULL, 0); strm->adler = state->check = crc32(0L, Z_NULL, 0);
state->mode = TYPE; state->mode = TYPE;
break; break;
@@ -969,6 +1029,13 @@ int flush;
state->offset += BITS(state->extra); state->offset += BITS(state->extra);
DROPBITS(state->extra); DROPBITS(state->extra);
} }
#ifdef INFLATE_STRICT
if (state->offset > state->dmax) {
strm->msg = (char *)"invalid distance too far back";
state->mode = BAD;
break;
}
#endif
if (state->offset > state->whave + out - left) { if (state->offset > state->whave + out - left) {
strm->msg = (char *)"invalid distance too far back"; strm->msg = (char *)"invalid distance too far back";
state->mode = BAD; state->mode = BAD;
@@ -1110,12 +1177,16 @@ uInt dictLength;
/* check state */ /* check state */
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state; state = (struct inflate_state FAR *)strm->state;
if (state->mode != DICT) return Z_STREAM_ERROR; if (state->wrap != 0 && state->mode != DICT)
return Z_STREAM_ERROR;
/* check for correct dictionary id */ /* check for correct dictionary id */
if (state->mode == DICT) {
id = adler32(0L, Z_NULL, 0); id = adler32(0L, Z_NULL, 0);
id = adler32(id, dictionary, dictLength); id = adler32(id, dictionary, dictLength);
if (id != state->check) return Z_DATA_ERROR; if (id != state->check)
return Z_DATA_ERROR;
}
/* copy dictionary to window */ /* copy dictionary to window */
if (updatewindow(strm, strm->avail_out)) { if (updatewindow(strm, strm->avail_out)) {
@@ -1137,6 +1208,23 @@ uInt dictLength;
return Z_OK; return Z_OK;
} }
int ZEXPORT inflateGetHeader(strm, head)
z_streamp strm;
gz_headerp head;
{
struct inflate_state FAR *state;
/* check state */
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state;
if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
/* save header structure */
state->head = head;
head->done = 0;
return Z_OK;
}
/* /*
Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found
or when out of input. When called, *have is the number of pattern bytes or when out of input. When called, *have is the number of pattern bytes
@@ -1239,6 +1327,7 @@ z_streamp source;
struct inflate_state FAR *state; struct inflate_state FAR *state;
struct inflate_state FAR *copy; struct inflate_state FAR *copy;
unsigned char FAR *window; unsigned char FAR *window;
unsigned wsize;
/* check input */ /* check input */
if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL ||
@@ -1261,14 +1350,19 @@ z_streamp source;
} }
/* copy state */ /* copy state */
*dest = *source; zmemcpy(dest, source, sizeof(z_stream));
*copy = *state; zmemcpy(copy, state, sizeof(struct inflate_state));
if (state->lencode >= state->codes &&
state->lencode <= state->codes + ENOUGH - 1) {
copy->lencode = copy->codes + (state->lencode - state->codes); copy->lencode = copy->codes + (state->lencode - state->codes);
copy->distcode = copy->codes + (state->distcode - state->codes); copy->distcode = copy->codes + (state->distcode - state->codes);
}
copy->next = copy->codes + (state->next - state->codes); copy->next = copy->codes + (state->next - state->codes);
if (window != Z_NULL) if (window != Z_NULL) {
zmemcpy(window, state->window, 1U << state->wbits); wsize = 1U << state->wbits;
zmemcpy(window, state->window, wsize);
}
copy->window = window; copy->window = window;
dest->state = (voidpf)copy; dest->state = (struct internal_state FAR *)copy;
return Z_OK; return Z_OK;
} }

View File

@@ -1,5 +1,5 @@
/* inflate.h -- internal inflate state definition /* inflate.h -- internal inflate state definition
* Copyright (C) 1995-2003 Mark Adler * Copyright (C) 1995-2004 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@@ -19,7 +19,6 @@
/* Possible inflate modes between inflate() calls */ /* Possible inflate modes between inflate() calls */
typedef enum { typedef enum {
HEAD, /* i: waiting for magic header */ HEAD, /* i: waiting for magic header */
#ifdef GUNZIP
FLAGS, /* i: waiting for method and flags (gzip) */ FLAGS, /* i: waiting for method and flags (gzip) */
TIME, /* i: waiting for modification time (gzip) */ TIME, /* i: waiting for modification time (gzip) */
OS, /* i: waiting for extra flags and operating system (gzip) */ OS, /* i: waiting for extra flags and operating system (gzip) */
@@ -28,7 +27,6 @@ typedef enum {
NAME, /* i: waiting for end of file name (gzip) */ NAME, /* i: waiting for end of file name (gzip) */
COMMENT, /* i: waiting for end of comment (gzip) */ COMMENT, /* i: waiting for end of comment (gzip) */
HCRC, /* i: waiting for header crc (gzip) */ HCRC, /* i: waiting for header crc (gzip) */
#endif
DICTID, /* i: waiting for dictionary check value */ DICTID, /* i: waiting for dictionary check value */
DICT, /* waiting for inflateSetDictionary() call */ DICT, /* waiting for inflateSetDictionary() call */
TYPE, /* i: waiting for type bits, including last-flag bit */ TYPE, /* i: waiting for type bits, including last-flag bit */
@@ -45,9 +43,7 @@ typedef enum {
MATCH, /* o: waiting for output space to copy string */ MATCH, /* o: waiting for output space to copy string */
LIT, /* o: waiting for output space to write literal */ LIT, /* o: waiting for output space to write literal */
CHECK, /* i: waiting for 32-bit check value */ CHECK, /* i: waiting for 32-bit check value */
#ifdef GUNZIP
LENGTH, /* i: waiting for 32-bit length (gzip) */ LENGTH, /* i: waiting for 32-bit length (gzip) */
#endif
DONE, /* finished check, done -- remain here until reset */ DONE, /* finished check, done -- remain here until reset */
BAD, /* got a data error -- remain here until reset */ BAD, /* got a data error -- remain here until reset */
MEM, /* got an inflate() memory error -- remain here until reset */ MEM, /* got an inflate() memory error -- remain here until reset */
@@ -84,8 +80,10 @@ struct inflate_state {
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
int havedict; /* true if dictionary provided */ int havedict; /* true if dictionary provided */
int flags; /* gzip header method and flags (0 if zlib) */ int flags; /* gzip header method and flags (0 if zlib) */
unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
unsigned long check; /* protected copy of check value */ unsigned long check; /* protected copy of check value */
unsigned long total; /* protected copy of output count */ unsigned long total; /* protected copy of output count */
gz_headerp head; /* where to save gzip header information */
/* sliding window */ /* sliding window */
unsigned wbits; /* log base 2 of requested window size */ unsigned wbits; /* log base 2 of requested window size */
unsigned wsize; /* window size or zero if not using window */ unsigned wsize; /* window size or zero if not using window */

View File

@@ -1,5 +1,5 @@
/* inftrees.c -- generate Huffman trees for efficient decoding /* inftrees.c -- generate Huffman trees for efficient decoding
* Copyright (C) 1995-2004 Mark Adler * Copyright (C) 1995-2005 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@@ -9,7 +9,7 @@
#define MAXBITS 15 #define MAXBITS 15
const char inflate_copyright[] = const char inflate_copyright[] =
" inflate 1.2.2 Copyright 1995-2004 Mark Adler "; " inflate 1.2.2.4 Copyright 1995-2005 Mark Adler ";
/* /*
If you use the zlib library in a product, an acknowledgment is welcome 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 in the documentation of your product. If for some reason you cannot
@@ -62,7 +62,7 @@ unsigned short FAR *work;
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
static const unsigned short lext[31] = { /* Length codes 257..285 extra */ static const unsigned short lext[31] = { /* Length codes 257..285 extra */
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 199, 198}; 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 206, 69};
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
@@ -134,7 +134,7 @@ unsigned short FAR *work;
left -= count[len]; left -= count[len];
if (left < 0) return -1; /* over-subscribed */ if (left < 0) return -1; /* over-subscribed */
} }
if (left > 0 && (type == CODES || (codes - count[0] != 1))) if (left > 0 && (type == CODES || max != 1))
return -1; /* incomplete set */ return -1; /* incomplete set */
/* generate offsets into symbol table for each length for sorting */ /* generate offsets into symbol table for each length for sorting */
@@ -232,6 +232,7 @@ unsigned short FAR *work;
/* replicate for those indices with low len bits equal to huff */ /* replicate for those indices with low len bits equal to huff */
incr = 1U << (len - drop); incr = 1U << (len - drop);
fill = 1U << curr; fill = 1U << curr;
min = fill; /* save offset to next table */
do { do {
fill -= incr; fill -= incr;
next[(huff >> drop) + fill] = this; next[(huff >> drop) + fill] = this;
@@ -262,7 +263,7 @@ unsigned short FAR *work;
drop = root; drop = root;
/* increment past last table */ /* increment past last table */
next += 1U << curr; next += min; /* here min is 1 << curr */
/* determine length of next table */ /* determine length of next table */
curr = len - drop; curr = len - drop;

View File

@@ -1,5 +1,5 @@
/* inftrees.h -- header to use inftrees.c /* inftrees.h -- header to use inftrees.c
* Copyright (C) 1995-2003 Mark Adler * Copyright (C) 1995-2005 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@@ -36,12 +36,12 @@ typedef struct {
*/ */
/* Maximum size of dynamic tree. The maximum found in a long but non- /* Maximum size of dynamic tree. The maximum found in a long but non-
exhaustive search was 1004 code structures (850 for length/literals exhaustive search was 1444 code structures (852 for length/literals
and 154 for distances, the latter actually the result of an and 592 for distances, the latter actually the result of an
exhaustive search). The true maximum is not known, but the value exhaustive search). The true maximum is not known, but the value
below is more than safe. */ below is more than safe. */
#define ENOUGH 1440 #define ENOUGH 2048
#define MAXD 154 #define MAXD 592
/* Type of code to build for inftable() */ /* Type of code to build for inftable() */
typedef enum { typedef enum {

461
make_vms.com Normal file
View File

@@ -0,0 +1,461 @@
$! make libz under VMS written by
$! Martin P.J. Zinser
$! <zinser@zinser.no-ip.info or zinser@sysdev.deutsche-boerse.com>
$!
$ on error then goto err_exit
$!
$!
$! Just some general constants...
$!
$ true = 1
$ false = 0
$ tmpnam = "temp_" + f$getjpi("","pid")
$ SAY = "WRITE SYS$OUTPUT"
$!
$! Setup variables holding "config" information
$!
$ Make = ""
$ name = "Zlib"
$ version = "?.?.?"
$ v_string = "ZLIB_VERSION"
$ v_file = "zlib.h"
$ ccopt = ""
$ lopts = ""
$ linkonly = false
$ optfile = name + ".opt"
$ its_decc = false
$ its_vaxc = false
$ its_gnuc = false
$ axp = f$getsyi("HW_MODEL").ge.1024
$ s_case = false
$! Check for MMK/MMS
$!
$ If F$Search ("Sys$System:MMS.EXE") .nes. "" Then Make = "MMS"
$ If F$Type (MMK) .eqs. "STRING" Then Make = "MMK"
$!
$!
$ gosub find_version
$!
$ gosub check_opts
$!
$! Look for the compiler used
$!
$ gosub check_compiler
$ if its_decc
$ then
$ ccopt = "/prefix=all" + ccopt
$ if f$trnlnm("SYS") .eqs. ""
$ then
$ if axp
$ then
$ define sys sys$library:
$ else
$ ccopt = "/decc" + ccopt
$ define sys decc$library_include:
$ endif
$ endif
$ endif
$ if its_vaxc .or. its_gnuc
$ then
$ if f$trnlnm("SYS").eqs."" then define sys sys$library:
$ endif
$!
$! Build the thing plain or with mms
$!
$ write sys$output "Compiling Zlib sources ..."
$ if make.eqs.""
$ then
$ dele example.obj;*,minigzip.obj;*
$ CALL MAKE adler32.OBJ "CC ''CCOPT' adler32" -
adler32.c zlib.h zconf.h
$ CALL MAKE compress.OBJ "CC ''CCOPT' compress" -
compress.c zlib.h zconf.h
$ CALL MAKE crc32.OBJ "CC ''CCOPT' crc32" -
crc32.c zlib.h zconf.h
$ CALL MAKE deflate.OBJ "CC ''CCOPT' deflate" -
deflate.c deflate.h zutil.h zlib.h zconf.h
$ CALL MAKE gzio.OBJ "CC ''CCOPT' gzio" -
gzio.c zutil.h zlib.h zconf.h
$ CALL MAKE infback.OBJ "CC ''CCOPT' infback" -
infback.c zutil.h inftrees.h inflate.h inffast.h inffixed.h
$ CALL MAKE inffast.OBJ "CC ''CCOPT' inffast" -
inffast.c zutil.h zlib.h zconf.h inffast.h
$ CALL MAKE inflate.OBJ "CC ''CCOPT' inflate" -
inflate.c zutil.h zlib.h zconf.h infblock.h
$ CALL MAKE inftrees.OBJ "CC ''CCOPT' inftrees" -
inftrees.c zutil.h zlib.h zconf.h inftrees.h
$ CALL MAKE trees.OBJ "CC ''CCOPT' trees" -
trees.c deflate.h zutil.h zlib.h zconf.h
$ CALL MAKE uncompr.OBJ "CC ''CCOPT' uncompr" -
uncompr.c zlib.h zconf.h
$ CALL MAKE zutil.OBJ "CC ''CCOPT' zutil" -
zutil.c zutil.h zlib.h zconf.h
$ write sys$output "Building Zlib ..."
$ CALL MAKE libz.OLB "lib/crea libz.olb *.obj" *.OBJ
$ write sys$output "Building example..."
$ CALL MAKE example.OBJ "CC ''CCOPT' example" -
example.c zlib.h zconf.h
$ call make example.exe "LINK example,libz.olb/lib" example.obj libz.olb
$ if f$search("x11vms:xvmsutils.olb") .nes. ""
$ then
$ write sys$output "Building minigzip..."
$ CALL MAKE minigzip.OBJ "CC ''CCOPT' minigzip" -
minigzip.c zlib.h zconf.h
$ call make minigzip.exe -
"LINK minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib" -
minigzip.obj libz.olb
$ endif
$ else
$ gosub crea_mms
$ SAY "Make ''name' ''version' with ''Make' "
$ 'make'
$ endif
$!
$! Alpha gets a shareable image
$!
$ If axp
$ Then
$ gosub crea_olist
$ write sys$output "Creating libzshr.exe"
$ call anal_obj_axp modules.opt _link.opt
$ if s_case
$ then
$ open/append optf modules.opt
$ write optf "case_sensitive=YES"
$ close optf
$ endif
$ LINK_'lopts'/SHARE=libzshr.exe modules.opt/opt,_link.opt/opt
$ endif
$ write sys$output "Zlib build completed"
$ exit
$CC_ERR:
$ write sys$output "C compiler required to build ''name'"
$ goto err_exit
$ERR_EXIT:
$ set message/facil/ident/sever/text
$ write sys$output "Exiting..."
$ exit 2
$!
$!
$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES
$ V = 'F$Verify(0)
$! P1 = What we are trying to make
$! P2 = Command to make it
$! P3 - P8 What it depends on
$
$ If F$Search(P1) .Eqs. "" Then Goto Makeit
$ Time = F$CvTime(F$File(P1,"RDT"))
$arg=3
$Loop:
$ Argument = P'arg
$ If Argument .Eqs. "" Then Goto Exit
$ El=0
$Loop2:
$ File = F$Element(El," ",Argument)
$ If File .Eqs. " " Then Goto Endl
$ AFile = ""
$Loop3:
$ OFile = AFile
$ AFile = F$Search(File)
$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl
$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit
$ Goto Loop3
$NextEL:
$ El = El + 1
$ Goto Loop2
$EndL:
$ arg=arg+1
$ If arg .Le. 8 Then Goto Loop
$ Goto Exit
$
$Makeit:
$ VV=F$VERIFY(0)
$ write sys$output P2
$ 'P2
$ VV='F$Verify(VV)
$Exit:
$ If V Then Set Verify
$ENDSUBROUTINE
$!------------------------------------------------------------------------------
$!
$! Check command line options and set symbols accordingly
$!
$ CHECK_OPTS:
$ i = 1
$ OPT_LOOP:
$ if i .lt. 9
$ then
$ cparm = f$edit(p'i',"upcase")
$ if cparm .eqs. "DEBUG"
$ then
$ ccopt = ccopt + "/noopt/deb"
$ lopts = lopts + "/deb"
$ endif
$ if f$locate("CCOPT=",cparm) .lt. f$length(cparm)
$ then
$ start = f$locate("=",cparm) + 1
$ len = f$length(cparm) - start
$ ccopt = ccopt + f$extract(start,len,cparm)
$ if f$locate("AS_IS",f$edit(ccopt,"UPCASE")) .lt. f$length(ccopt) -
then s_case = true
$ endif
$ if cparm .eqs. "LINK" then linkonly = true
$ if f$locate("LOPTS=",cparm) .lt. f$length(cparm)
$ then
$ start = f$locate("=",cparm) + 1
$ len = f$length(cparm) - start
$ lopts = lopts + f$extract(start,len,cparm)
$ endif
$ if f$locate("CC=",cparm) .lt. f$length(cparm)
$ then
$ start = f$locate("=",cparm) + 1
$ len = f$length(cparm) - start
$ cc_com = f$extract(start,len,cparm)
if (cc_com .nes. "DECC") .and. -
(cc_com .nes. "VAXC") .and. -
(cc_com .nes. "GNUC")
$ then
$ write sys$output "Unsupported compiler choice ''cc_com' ignored"
$ write sys$output "Use DECC, VAXC, or GNUC instead"
$ else
$ if cc_com .eqs. "DECC" then its_decc = true
$ if cc_com .eqs. "VAXC" then its_vaxc = true
$ if cc_com .eqs. "GNUC" then its_gnuc = true
$ endif
$ endif
$ if f$locate("MAKE=",cparm) .lt. f$length(cparm)
$ then
$ start = f$locate("=",cparm) + 1
$ len = f$length(cparm) - start
$ mmks = f$extract(start,len,cparm)
$ if (mmks .eqs. "MMK") .or. (mmks .eqs. "MMS")
$ then
$ make = mmks
$ else
$ write sys$output "Unsupported make choice ''mmks' ignored"
$ write sys$output "Use MMK or MMS instead"
$ endif
$ endif
$ i = i + 1
$ goto opt_loop
$ endif
$ return
$!------------------------------------------------------------------------------
$!
$! Look for the compiler used
$!
$CHECK_COMPILER:
$ if (.not. (its_decc .or. its_vaxc .or. its_gnuc))
$ then
$ its_decc = (f$search("SYS$SYSTEM:DECC$COMPILER.EXE") .nes. "")
$ its_vaxc = .not. its_decc .and. (F$Search("SYS$System:VAXC.Exe") .nes. "")
$ its_gnuc = .not. (its_decc .or. its_vaxc) .and. (f$trnlnm("gnu_cc") .nes. "")
$ endif
$!
$! Exit if no compiler available
$!
$ if (.not. (its_decc .or. its_vaxc .or. its_gnuc))
$ then goto CC_ERR
$ else
$ if its_decc then write sys$output "CC compiler check ... Compaq C"
$ if its_vaxc then write sys$output "CC compiler check ... VAX C"
$ if its_gnuc then write sys$output "CC compiler check ... GNU C"
$ endif
$ return
$!------------------------------------------------------------------------------
$!
$! If MMS/MMK are available dump out the descrip.mms if required
$!
$CREA_MMS:
$ write sys$output "Creating descrip.mms..."
$ create descrip.mms
$ open/append out descrip.mms
$ copy sys$input: out
$ deck
# descrip.mms: MMS description file for building zlib on VMS
# written by Martin P.J. Zinser
# <zinser@zinser.no-ip.info or zinser@sysdev.deutsche-boerse.com>
OBJS = adler32.obj, compress.obj, crc32.obj, gzio.obj, uncompr.obj, infback.obj\
deflate.obj, trees.obj, zutil.obj, inflate.obj, \
inftrees.obj, inffast.obj
$ eod
$ write out "CFLAGS=", ccopt
$ write out "LOPTS=", lopts
$ copy sys$input: out
$ deck
all : example.exe minigzip.exe libz.olb
@ write sys$output " Example applications available"
libz.olb : libz.olb($(OBJS))
@ write sys$output " libz available"
example.exe : example.obj libz.olb
link $(LOPTS) example,libz.olb/lib
minigzip.exe : minigzip.obj libz.olb
link $(LOPTS) minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib
clean :
delete *.obj;*,libz.olb;*,*.opt;*,*.exe;*
# Other dependencies.
adler32.obj : adler32.c zutil.h zlib.h zconf.h
compress.obj : compress.c zlib.h zconf.h
crc32.obj : crc32.c zutil.h zlib.h zconf.h
deflate.obj : deflate.c deflate.h zutil.h zlib.h zconf.h
example.obj : example.c zlib.h zconf.h
gzio.obj : gzio.c zutil.h zlib.h zconf.h
inffast.obj : inffast.c zutil.h zlib.h zconf.h inftrees.h inffast.h
inflate.obj : inflate.c zutil.h zlib.h zconf.h
inftrees.obj : inftrees.c zutil.h zlib.h zconf.h inftrees.h
minigzip.obj : minigzip.c zlib.h zconf.h
trees.obj : trees.c deflate.h zutil.h zlib.h zconf.h
uncompr.obj : uncompr.c zlib.h zconf.h
zutil.obj : zutil.c zutil.h zlib.h zconf.h
infback.obj : infback.c zutil.h inftrees.h inflate.h inffast.h inffixed.h
$ eod
$ close out
$ return
$!------------------------------------------------------------------------------
$!
$! Read list of core library sources from makefile.in and create options
$! needed to build shareable image
$!
$CREA_OLIST:
$ open/read min makefile.in
$ open/write mod modules.opt
$ src_check = "OBJS ="
$MRLOOP:
$ read/end=mrdone min rec
$ if (f$extract(0,6,rec) .nes. src_check) then goto mrloop
$ rec = rec - src_check
$ gosub extra_filnam
$ if (f$element(1,"\",rec) .eqs. "\") then goto mrdone
$MRSLOOP:
$ read/end=mrdone min rec
$ gosub extra_filnam
$ if (f$element(1,"\",rec) .nes. "\") then goto mrsloop
$MRDONE:
$ close min
$ close mod
$ return
$!------------------------------------------------------------------------------
$!
$! Take record extracted in crea_olist and split it into single filenames
$!
$EXTRA_FILNAM:
$ myrec = f$edit(rec - "\", "trim,compress")
$ i = 0
$FELOOP:
$ srcfil = f$element(i," ", myrec)
$ if (srcfil .nes. " ")
$ then
$ write mod f$parse(srcfil,,,"NAME"), ".obj"
$ i = i + 1
$ goto feloop
$ endif
$ return
$!------------------------------------------------------------------------------
$!
$! Find current Zlib version number
$!
$FIND_VERSION:
$ open/read h_in 'v_file'
$hloop:
$ read/end=hdone h_in rec
$ rec = f$edit(rec,"TRIM")
$ if (f$extract(0,1,rec) .nes. "#") then goto hloop
$ rec = f$edit(rec - "#", "TRIM")
$ if f$element(0," ",rec) .nes. "define" then goto hloop
$ if f$element(1," ",rec) .eqs. v_string
$ then
$ version = 'f$element(2," ",rec)'
$ goto hdone
$ endif
$ goto hloop
$hdone:
$ close h_in
$ return
$!------------------------------------------------------------------------------
$!
$! Analyze Object files for OpenVMS AXP to extract Procedure and Data
$! information to build a symbol vector for a shareable image
$! All the "brains" of this logic was suggested by Hartmut Becker
$! (Hartmut.Becker@compaq.com). All the bugs were introduced by me
$! (zinser@decus.de), so if you do have problem reports please do not
$! bother Hartmut/HP, but get in touch with me
$!
$ ANAL_OBJ_AXP: Subroutine
$ V = 'F$Verify(0)
$ SAY := "WRITE_ SYS$OUTPUT"
$
$ IF F$SEARCH("''P1'") .EQS. ""
$ THEN
$ SAY "ANAL_OBJ_AXP-E-NOSUCHFILE: Error, inputfile ''p1' not available"
$ goto exit_aa
$ ENDIF
$ IF "''P2'" .EQS. ""
$ THEN
$ SAY "ANAL_OBJ_AXP: Error, no output file provided"
$ goto exit_aa
$ ENDIF
$
$ open/read in 'p1
$ create a.tmp
$ open/append atmp a.tmp
$ loop:
$ read/end=end_loop in line
$ f= f$search(line)
$ if f .eqs. ""
$ then
$ write sys$output "ANAL_OBJ_AXP-w-nosuchfile, ''line'"
$ goto loop
$ endif
$ define/user sys$output nl:
$ define/user sys$error nl:
$ anal/obj/gsd 'f /out=x.tmp
$ open/read xtmp x.tmp
$ XLOOP:
$ read/end=end_xloop xtmp xline
$ xline = f$edit(xline,"compress")
$ write atmp xline
$ goto xloop
$ END_XLOOP:
$ close xtmp
$ goto loop
$ end_loop:
$ close in
$ close atmp
$ if f$search("a.tmp") .eqs. "" -
then $ exit
$ ! all global definitions
$ search a.tmp "symbol:","EGSY$V_DEF 1","EGSY$V_NORM 1"/out=b.tmp
$ ! all procedures
$ search b.tmp "EGSY$V_NORM 1"/wind=(0,1) /out=c.tmp
$ search c.tmp "symbol:"/out=d.tmp
$ define/user sys$output nl:
$ edito/edt/command=sys$input d.tmp
sub/symbol: "/symbol_vector=(/whole
sub/"/=PROCEDURE)/whole
exit
$ ! all data
$ search b.tmp "EGSY$V_DEF 1"/wind=(0,1) /out=e.tmp
$ search e.tmp "symbol:"/out=f.tmp
$ define/user sys$output nl:
$ edito/edt/command=sys$input f.tmp
sub/symbol: "/symbol_vector=(/whole
sub/"/=DATA)/whole
exit
$ sort/nodupl d.tmp,f.tmp 'p2'
$ delete a.tmp;*,b.tmp;*,c.tmp;*,d.tmp;*,e.tmp;*,f.tmp;*
$ if f$search("x.tmp") .nes. "" -
then $ delete x.tmp;*
$!
$ EXIT_AA:
$ if V then set verify
$ endsubroutine
$!------------------------------------------------------------------------------

View File

@@ -1,5 +1,5 @@
/* minigzip.c -- simulate gzip using the zlib compression library /* minigzip.c -- simulate gzip using the zlib compression library
* Copyright (C) 1995-2002 Jean-loup Gailly. * Copyright (C) 1995-2005 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@@ -21,8 +21,6 @@
#ifdef STDC #ifdef STDC
# include <string.h> # include <string.h>
# include <stdlib.h> # include <stdlib.h>
#else
extern void exit OF((int));
#endif #endif
#ifdef USE_MMAP #ifdef USE_MMAP
@@ -297,6 +295,8 @@ int main(argc, argv)
break; break;
argc--, argv++; argc--, argv++;
} }
if (outmode[3] == ' ')
outmode[3] = 0;
if (argc == 0) { if (argc == 0) {
SET_BINARY_MODE(stdin); SET_BINARY_MODE(stdin);
SET_BINARY_MODE(stdout); SET_BINARY_MODE(stdout);

View File

@@ -1,115 +0,0 @@
$! make libz under VMS
$! written by Martin P.J. Zinser <m.zinser@gsi.de>
$!
$! Look for the compiler used
$!
$ ccopt = ""
$ if f$getsyi("HW_MODEL").ge.1024
$ then
$ ccopt = "/prefix=all"+ccopt
$ comp = "__decc__=1"
$ if f$trnlnm("SYS").eqs."" then define sys sys$library:
$ else
$ if f$search("SYS$SYSTEM:DECC$COMPILER.EXE").eqs.""
$ then
$ comp = "__vaxc__=1"
$ if f$trnlnm("SYS").eqs."" then define sys sys$library:
$ else
$ if f$trnlnm("SYS").eqs."" then define sys decc$library_include:
$ ccopt = "/decc/prefix=all"+ccopt
$ comp = "__decc__=1"
$ endif
$ endif
$!
$! Build the thing plain or with mms
$!
$ write sys$output "Compiling Zlib sources ..."
$ if f$search("SYS$SYSTEM:MMS.EXE").eqs.""
$ then
$ dele example.obj;*,minigzip.obj;*
$ CALL MAKE adler32.OBJ "CC ''CCOPT' adler32" -
adler32.c zlib.h zconf.h
$ CALL MAKE compress.OBJ "CC ''CCOPT' compress" -
compress.c zlib.h zconf.h
$ CALL MAKE crc32.OBJ "CC ''CCOPT' crc32" -
crc32.c zlib.h zconf.h
$ CALL MAKE deflate.OBJ "CC ''CCOPT' deflate" -
deflate.c deflate.h zutil.h zlib.h zconf.h
$ CALL MAKE gzio.OBJ "CC ''CCOPT' gzio" -
gzio.c zutil.h zlib.h zconf.h
$ CALL MAKE infblock.OBJ "CC ''CCOPT' infblock" -
infblock.c zutil.h zlib.h zconf.h infblock.h
$ CALL MAKE infcodes.OBJ "CC ''CCOPT' infcodes" -
infcodes.c zutil.h zlib.h zconf.h inftrees.h
$ CALL MAKE inffast.OBJ "CC ''CCOPT' inffast" -
inffast.c zutil.h zlib.h zconf.h inffast.h
$ CALL MAKE inflate.OBJ "CC ''CCOPT' inflate" -
inflate.c zutil.h zlib.h zconf.h infblock.h
$ CALL MAKE inftrees.OBJ "CC ''CCOPT' inftrees" -
inftrees.c zutil.h zlib.h zconf.h inftrees.h
$ CALL MAKE infutil.OBJ "CC ''CCOPT' infutil" -
infutil.c zutil.h zlib.h zconf.h inftrees.h infutil.h
$ CALL MAKE trees.OBJ "CC ''CCOPT' trees" -
trees.c deflate.h zutil.h zlib.h zconf.h
$ CALL MAKE uncompr.OBJ "CC ''CCOPT' uncompr" -
uncompr.c zlib.h zconf.h
$ CALL MAKE zutil.OBJ "CC ''CCOPT' zutil" -
zutil.c zutil.h zlib.h zconf.h
$ write sys$output "Building Zlib ..."
$ CALL MAKE libz.OLB "lib/crea libz.olb *.obj" *.OBJ
$ write sys$output "Building example..."
$ CALL MAKE example.OBJ "CC ''CCOPT' example" -
example.c zlib.h zconf.h
$ call make example.exe "LINK example,libz.olb/lib" example.obj libz.olb
$ write sys$output "Building minigzip..."
$ CALL MAKE minigzip.OBJ "CC ''CCOPT' minigzip" -
minigzip.c zlib.h zconf.h
$ call make minigzip.exe -
"LINK minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib" -
minigzip.obj libz.olb
$ else
$ mms/macro=('comp')
$ endif
$ write sys$output "Zlib build completed"
$ exit
$!
$!
$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES
$ V = 'F$Verify(0)
$! P1 = What we are trying to make
$! P2 = Command to make it
$! P3 - P8 What it depends on
$
$ If F$Search(P1) .Eqs. "" Then Goto Makeit
$ Time = F$CvTime(F$File(P1,"RDT"))
$arg=3
$Loop:
$ Argument = P'arg
$ If Argument .Eqs. "" Then Goto Exit
$ El=0
$Loop2:
$ File = F$Element(El," ",Argument)
$ If File .Eqs. " " Then Goto Endl
$ AFile = ""
$Loop3:
$ OFile = AFile
$ AFile = F$Search(File)
$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl
$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit
$ Goto Loop3
$NextEL:
$ El = El + 1
$ Goto Loop2
$EndL:
$ arg=arg+1
$ If arg .Le. 8 Then Goto Loop
$ Goto Exit
$
$Makeit:
$ VV=F$VERIFY(0)
$ write sys$output P2
$ 'P2
$ VV='F$Verify(VV)
$Exit:
$ If V Then Set Verify
$ENDSUBROUTINE

View File

@@ -10,18 +10,21 @@ please consider submitting the project to the contrib directory.
Requirements Requirements
============ ============
- The project must build zlib using exclusively the source files from - The project must build zlib using the source files from the official
the official zlib distribution. zlib source distribution, exclusively.
- If there are "official" makefiles in the zlib distribution, the builds - If the project produces redistributable builds (e.g. shared objects
given by the makefiles must be compatible with the builds given by the or DLL files), these builds must be compatible to those produced by
project. These builds are called "official" builds. makefiles, if such makefiles exist in the zlib distribution.
In particular, if the project produces a DLL build for the Win32
platform, this build must comply to the officially-ammended Win32 DLL
Application Binary Interface (ABI), described in win32/DLL_FAQ.txt.
- It is possible to add non-official pieces of code to the project, - The project may provide additional build targets, which depend on
if the resulting build remains compatible with an official build. 3rd-party (unofficially-supported) software, present in the contrib
For example, it is possible to add an "ASM build" target besides directory. For example, it is possible to provide an "ASM build",
the regular target, by including ASM source files from the contrib besides the officially-supported build, and have ASM source files
directory. among its dependencies.
- If there are significant differences between the project files created - If there are significant differences between the project files created
by different versions of an IDE (e.g. Visual C++ 6.0 vs. 7.0), the name by different versions of an IDE (e.g. Visual C++ 6.0 vs. 7.0), the name

View File

@@ -5,23 +5,6 @@ Copyright (C) 2004 Cosmin Truta.
For conditions of distribution and use, see copyright notice in zlib.h. For conditions of distribution and use, see copyright notice in zlib.h.
To use:
1) On the main menu, select "File | Open Workspace".
Open "zlib.dsw".
2) Select "Build | Set Active Configuration".
Choose the configuration you wish to build.
3) Select "Build | Clean".
4) Select "Build | Build ... (F7)". Ignore warning messages about
not being able to find certain include files (e.g. alloc.h).
5) If you built one of the sample programs (example or minigzip),
select "Build | Execute ... (Ctrl+F5)".
This project builds the zlib binaries as follows: This project builds the zlib binaries as follows:
* Win32_DLL_Release\zlib1.dll DLL build * Win32_DLL_Release\zlib1.dll DLL build
@@ -36,3 +19,55 @@ This project builds the zlib binaries as follows:
For more information regarding the DLL builds, please see the DLL FAQ For more information regarding the DLL builds, please see the DLL FAQ
in ..\..\win32\DLL_FAQ.txt. in ..\..\win32\DLL_FAQ.txt.
To build and test:
1) On the main menu, select "File | Open Workspace".
Open "zlib.dsw".
2) Select "Build | Set Active Configuration".
Choose the configuration you wish to build.
3) Select "Build | Clean".
4) Select "Build | Build ... (F7)". Ignore warning messages about
not being able to find certain include files (e.g. alloc.h).
5) If you built one of the sample programs (example or minigzip),
select "Build | Execute ... (Ctrl+F5)".
To use:
1) Select "Project | Settings (Alt+F7)".
Make note of the configuration names used in your project.
Usually, these names are "Win32 Release" and "Win32 Debug".
2) In the Workspace window, select the "FileView" tab.
Right-click on the root item "Workspace '...'".
Select "Insert Project into Workspace".
Switch on the checkbox "Dependency of:", and select the name
of your project. Open "zlib.dsp".
3) Select "Build | Configurations".
For each configuration of your project:
3.1) Choose the zlib configuration you wish to use.
3.2) Click on "Add".
3.3) Set the new zlib configuration name to the name used by
the configuration from the current iteration.
4) Select "Build | Set Active Configuration".
Choose the configuration you wish to build.
5) Select "Build | Build ... (F7)".
6) If you built an executable program, select
"Build | Execute ... (Ctrl+F5)".
Note:
To build the ASM-enabled code, you need Microsoft Assembler
(ML.EXE). You can get it by downloading and installing the
latest Processor Pack for Visual C++ 6.0.

View File

@@ -47,7 +47,7 @@ RSC=rc.exe
# PROP Intermediate_Dir "Win32_DLL_Release" # PROP Intermediate_Dir "Win32_DLL_Release"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c # ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
# SUBTRACT BASE CPP /YX # SUBTRACT BASE CPP /YX
# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c # ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
# SUBTRACT CPP /YX # SUBTRACT CPP /YX
@@ -58,7 +58,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 zlib1.lib /nologo /subsystem:console /machine:I386 /libpath:"Win32_DLL_Release" # ADD LINK32 /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "example - Win32 DLL Debug" !ELSEIF "$(CFG)" == "example - Win32 DLL Debug"
@@ -73,7 +73,7 @@ LINK32=link.exe
# PROP Intermediate_Dir "Win32_DLL_Debug" # PROP Intermediate_Dir "Win32_DLL_Debug"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c # ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
# SUBTRACT BASE CPP /YX # SUBTRACT BASE CPP /YX
# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
# SUBTRACT CPP /YX # SUBTRACT CPP /YX
@@ -84,7 +84,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 zlib1d.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"Win32_DLL_Debug" # ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ELSEIF "$(CFG)" == "example - Win32 DLL ASM Release" !ELSEIF "$(CFG)" == "example - Win32 DLL ASM Release"
@@ -99,7 +99,7 @@ LINK32=link.exe
# PROP Intermediate_Dir "Win32_DLL_ASM_Release" # PROP Intermediate_Dir "Win32_DLL_ASM_Release"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c # ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
# SUBTRACT BASE CPP /YX # SUBTRACT BASE CPP /YX
# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c # ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
# SUBTRACT CPP /YX # SUBTRACT CPP /YX
@@ -110,7 +110,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 zlib1.lib /nologo /subsystem:console /machine:I386 /libpath:"Win32_DLL_ASM_Release" # ADD LINK32 /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "example - Win32 DLL ASM Debug" !ELSEIF "$(CFG)" == "example - Win32 DLL ASM Debug"
@@ -125,7 +125,7 @@ LINK32=link.exe
# PROP Intermediate_Dir "Win32_DLL_ASM_Debug" # PROP Intermediate_Dir "Win32_DLL_ASM_Debug"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c # ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
# SUBTRACT BASE CPP /YX # SUBTRACT BASE CPP /YX
# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
# SUBTRACT CPP /YX # SUBTRACT CPP /YX
@@ -136,7 +136,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 zlib1d.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"Win32_DLL_ASM_Debug" # ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ELSEIF "$(CFG)" == "example - Win32 LIB Release" !ELSEIF "$(CFG)" == "example - Win32 LIB Release"
@@ -151,7 +151,7 @@ LINK32=link.exe
# PROP Intermediate_Dir "Win32_LIB_Release" # PROP Intermediate_Dir "Win32_LIB_Release"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c # ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
# SUBTRACT BASE CPP /YX # SUBTRACT BASE CPP /YX
# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c # ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
# SUBTRACT CPP /YX # SUBTRACT CPP /YX
@@ -162,7 +162,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 zlib.lib /nologo /subsystem:console /machine:I386 /libpath:"Win32_LIB_Release" # ADD LINK32 /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "example - Win32 LIB Debug" !ELSEIF "$(CFG)" == "example - Win32 LIB Debug"
@@ -177,7 +177,7 @@ LINK32=link.exe
# PROP Intermediate_Dir "Win32_LIB_Debug" # PROP Intermediate_Dir "Win32_LIB_Debug"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c # ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
# SUBTRACT BASE CPP /YX # SUBTRACT BASE CPP /YX
# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
# SUBTRACT CPP /YX # SUBTRACT CPP /YX
@@ -188,7 +188,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 zlibd.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"Win32_LIB_Debug" # ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ELSEIF "$(CFG)" == "example - Win32 LIB ASM Release" !ELSEIF "$(CFG)" == "example - Win32 LIB ASM Release"
@@ -203,7 +203,7 @@ LINK32=link.exe
# PROP Intermediate_Dir "Win32_LIB_ASM_Release" # PROP Intermediate_Dir "Win32_LIB_ASM_Release"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c # ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
# SUBTRACT BASE CPP /YX # SUBTRACT BASE CPP /YX
# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c # ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
# SUBTRACT CPP /YX # SUBTRACT CPP /YX
@@ -214,7 +214,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 zlib.lib /nologo /subsystem:console /machine:I386 /libpath:"Win32_LIB_ASM_Release" # ADD LINK32 /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "example - Win32 LIB ASM Debug" !ELSEIF "$(CFG)" == "example - Win32 LIB ASM Debug"
@@ -229,7 +229,7 @@ LINK32=link.exe
# PROP Intermediate_Dir "Win32_LIB_ASM_Debug" # PROP Intermediate_Dir "Win32_LIB_ASM_Debug"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c # ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
# SUBTRACT BASE CPP /YX # SUBTRACT BASE CPP /YX
# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
# SUBTRACT CPP /YX # SUBTRACT CPP /YX
@@ -240,7 +240,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 zlibd.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"Win32_LIB_ASM_Debug" # ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF !ENDIF

View File

@@ -47,7 +47,7 @@ RSC=rc.exe
# PROP Intermediate_Dir "Win32_DLL_Release" # PROP Intermediate_Dir "Win32_DLL_Release"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c # ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
# SUBTRACT BASE CPP /YX # SUBTRACT BASE CPP /YX
# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c # ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
# SUBTRACT CPP /YX # SUBTRACT CPP /YX
@@ -58,7 +58,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 zlib1.lib /nologo /subsystem:console /machine:I386 /libpath:"Win32_DLL_Release" # ADD LINK32 /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "minigzip - Win32 DLL Debug" !ELSEIF "$(CFG)" == "minigzip - Win32 DLL Debug"
@@ -73,7 +73,7 @@ LINK32=link.exe
# PROP Intermediate_Dir "Win32_DLL_Debug" # PROP Intermediate_Dir "Win32_DLL_Debug"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c # ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
# SUBTRACT BASE CPP /YX # SUBTRACT BASE CPP /YX
# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
# SUBTRACT CPP /YX # SUBTRACT CPP /YX
@@ -84,7 +84,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 zlib1d.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"Win32_DLL_Debug" # ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ELSEIF "$(CFG)" == "minigzip - Win32 DLL ASM Release" !ELSEIF "$(CFG)" == "minigzip - Win32 DLL ASM Release"
@@ -99,7 +99,7 @@ LINK32=link.exe
# PROP Intermediate_Dir "Win32_DLL_ASM_Release" # PROP Intermediate_Dir "Win32_DLL_ASM_Release"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c # ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
# SUBTRACT BASE CPP /YX # SUBTRACT BASE CPP /YX
# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c # ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
# SUBTRACT CPP /YX # SUBTRACT CPP /YX
@@ -110,7 +110,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 zlib1.lib /nologo /subsystem:console /machine:I386 /libpath:"Win32_DLL_ASM_Release" # ADD LINK32 /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "minigzip - Win32 DLL ASM Debug" !ELSEIF "$(CFG)" == "minigzip - Win32 DLL ASM Debug"
@@ -125,7 +125,7 @@ LINK32=link.exe
# PROP Intermediate_Dir "Win32_DLL_ASM_Debug" # PROP Intermediate_Dir "Win32_DLL_ASM_Debug"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c # ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
# SUBTRACT BASE CPP /YX # SUBTRACT BASE CPP /YX
# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
# SUBTRACT CPP /YX # SUBTRACT CPP /YX
@@ -136,7 +136,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 zlib1d.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"Win32_DLL_ASM_Debug" # ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ELSEIF "$(CFG)" == "minigzip - Win32 LIB Release" !ELSEIF "$(CFG)" == "minigzip - Win32 LIB Release"
@@ -151,7 +151,7 @@ LINK32=link.exe
# PROP Intermediate_Dir "Win32_LIB_Release" # PROP Intermediate_Dir "Win32_LIB_Release"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c # ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
# SUBTRACT BASE CPP /YX # SUBTRACT BASE CPP /YX
# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c # ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
# SUBTRACT CPP /YX # SUBTRACT CPP /YX
@@ -162,7 +162,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 zlib.lib /nologo /subsystem:console /machine:I386 /libpath:"Win32_LIB_Release" # ADD LINK32 /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "minigzip - Win32 LIB Debug" !ELSEIF "$(CFG)" == "minigzip - Win32 LIB Debug"
@@ -177,7 +177,7 @@ LINK32=link.exe
# PROP Intermediate_Dir "Win32_LIB_Debug" # PROP Intermediate_Dir "Win32_LIB_Debug"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c # ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
# SUBTRACT BASE CPP /YX # SUBTRACT BASE CPP /YX
# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
# SUBTRACT CPP /YX # SUBTRACT CPP /YX
@@ -188,7 +188,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 zlibd.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"Win32_LIB_Debug" # ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ELSEIF "$(CFG)" == "minigzip - Win32 LIB ASM Release" !ELSEIF "$(CFG)" == "minigzip - Win32 LIB ASM Release"
@@ -203,7 +203,7 @@ LINK32=link.exe
# PROP Intermediate_Dir "Win32_LIB_ASM_Release" # PROP Intermediate_Dir "Win32_LIB_ASM_Release"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c # ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
# SUBTRACT BASE CPP /YX # SUBTRACT BASE CPP /YX
# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c # ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
# SUBTRACT CPP /YX # SUBTRACT CPP /YX
@@ -214,7 +214,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 zlib.lib /nologo /subsystem:console /machine:I386 /libpath:"Win32_LIB_ASM_Release" # ADD LINK32 /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "minigzip - Win32 LIB ASM Debug" !ELSEIF "$(CFG)" == "minigzip - Win32 LIB ASM Debug"
@@ -229,7 +229,7 @@ LINK32=link.exe
# PROP Intermediate_Dir "Win32_LIB_ASM_Debug" # PROP Intermediate_Dir "Win32_LIB_ASM_Debug"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c # ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
# SUBTRACT BASE CPP /YX # SUBTRACT BASE CPP /YX
# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
# SUBTRACT CPP /YX # SUBTRACT CPP /YX
@@ -240,7 +240,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 zlibd.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"Win32_LIB_ASM_Debug" # ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF !ENDIF

View File

@@ -435,7 +435,7 @@ InputPath=..\..\contrib\masmx86\gvmat32.asm
InputName=gvmat32 InputName=gvmat32
"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" "$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
ml /nologo /c /Cx /coff /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)" ml.exe /nologo /c /coff /Cx /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
# End Custom Build # End Custom Build
@@ -447,7 +447,7 @@ InputPath=..\..\contrib\masmx86\gvmat32.asm
InputName=gvmat32 InputName=gvmat32
"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" "$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
ml /nologo /c /Cx /coff /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)" ml.exe /nologo /c /coff /Cx /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
# End Custom Build # End Custom Build
@@ -467,7 +467,7 @@ InputPath=..\..\contrib\masmx86\gvmat32.asm
InputName=gvmat32 InputName=gvmat32
"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" "$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
ml /nologo /c /Cx /coff /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)" ml.exe /nologo /c /coff /Cx /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
# End Custom Build # End Custom Build
@@ -479,7 +479,7 @@ InputPath=..\..\contrib\masmx86\gvmat32.asm
InputName=gvmat32 InputName=gvmat32
"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" "$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
ml /nologo /c /Cx /coff /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)" ml.exe /nologo /c /coff /Cx /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
# End Custom Build # End Custom Build
@@ -549,7 +549,7 @@ InputPath=..\..\contrib\masmx86\inffas32.asm
InputName=inffas32 InputName=inffas32
"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" "$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
ml /nologo /c /Cx /coff /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)" ml.exe /nologo /c /coff /Cx /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
# End Custom Build # End Custom Build
@@ -561,7 +561,7 @@ InputPath=..\..\contrib\masmx86\inffas32.asm
InputName=inffas32 InputName=inffas32
"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" "$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
ml /nologo /c /Cx /coff /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)" ml.exe /nologo /c /coff /Cx /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
# End Custom Build # End Custom Build
@@ -581,7 +581,7 @@ InputPath=..\..\contrib\masmx86\inffas32.asm
InputName=inffas32 InputName=inffas32
"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" "$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
ml /nologo /c /Cx /coff /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)" ml.exe /nologo /c /coff /Cx /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
# End Custom Build # End Custom Build
@@ -593,7 +593,7 @@ InputPath=..\..\contrib\masmx86\inffas32.asm
InputName=inffas32 InputName=inffas32
"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" "$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
ml /nologo /c /Cx /coff /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)" ml.exe /nologo /c /coff /Cx /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
# End Custom Build # End Custom Build

View File

@@ -25,10 +25,10 @@
<QPG:Files> <QPG:Files>
<QPG:Add file="../zconf.h" install="/opt/include/" user="root:sys" permission="644"/> <QPG:Add file="../zconf.h" install="/opt/include/" user="root:sys" permission="644"/>
<QPG:Add file="../zlib.h" install="/opt/include/" user="root:sys" permission="644"/> <QPG:Add file="../zlib.h" install="/opt/include/" user="root:sys" permission="644"/>
<QPG:Add file="../libz.so.1.2.2" install="/opt/lib/" user="root:bin" permission="644"/> <QPG:Add file="../libz.so.1.2.2.4" install="/opt/lib/" user="root:bin" permission="644"/>
<QPG:Add file="libz.so" install="/opt/lib/" component="dev" filetype="symlink" linkto="libz.so.1.2.2"/> <QPG:Add file="libz.so" install="/opt/lib/" component="dev" filetype="symlink" linkto="libz.so.1.2.2.4"/>
<QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.2.2"/> <QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.2.2.4"/>
<QPG:Add file="../libz.so.1.2.2" install="/opt/lib/" component="slib"/> <QPG:Add file="../libz.so.1.2.2.4" install="/opt/lib/" component="slib"/>
</QPG:Files> </QPG:Files>
<QPG:PackageFilter> <QPG:PackageFilter>
@@ -63,7 +63,7 @@
</QPM:ProductDescription> </QPM:ProductDescription>
<QPM:ReleaseDescription> <QPM:ReleaseDescription>
<QPM:ReleaseVersion>1.2.2</QPM:ReleaseVersion> <QPM:ReleaseVersion>1.2.2.4</QPM:ReleaseVersion>
<QPM:ReleaseUrgency>Medium</QPM:ReleaseUrgency> <QPM:ReleaseUrgency>Medium</QPM:ReleaseUrgency>
<QPM:ReleaseStability>Stable</QPM:ReleaseStability> <QPM:ReleaseStability>Stable</QPM:ReleaseStability>
<QPM:ReleaseNoteMinor></QPM:ReleaseNoteMinor> <QPM:ReleaseNoteMinor></QPM:ReleaseNoteMinor>

36
trees.c
View File

@@ -1,5 +1,5 @@
/* trees.c -- output deflated data using Huffman coding /* trees.c -- output deflated data using Huffman coding
* Copyright (C) 1995-2003 Jean-loup Gailly * Copyright (C) 1995-2005 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@@ -555,7 +555,7 @@ local void gen_bitlen(s, desc)
while (n != 0) { while (n != 0) {
m = s->heap[--h]; m = s->heap[--h];
if (m > max_code) continue; if (m > max_code) continue;
if (tree[m].Len != (unsigned) bits) { if ((unsigned) tree[m].Len != (unsigned) bits) {
Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
s->opt_len += ((long)bits - (long)tree[m].Len) s->opt_len += ((long)bits - (long)tree[m].Len)
*(long)tree[m].Freq; *(long)tree[m].Freq;
@@ -930,8 +930,9 @@ void _tr_flush_block(s, buf, stored_len, eof)
/* Build the Huffman trees unless a stored block is forced */ /* Build the Huffman trees unless a stored block is forced */
if (s->level > 0) { if (s->level > 0) {
/* Check if the file is ascii or binary */ /* Check if the file is binary or text */
if (s->strm->data_type == Z_UNKNOWN) set_data_type(s); if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN)
set_data_type(s);
/* Construct the literal and distance trees */ /* Construct the literal and distance trees */
build_tree(s, (tree_desc *)(&(s->l_desc))); build_tree(s, (tree_desc *)(&(s->l_desc)));
@@ -982,7 +983,7 @@ void _tr_flush_block(s, buf, stored_len, eof)
#ifdef FORCE_STATIC #ifdef FORCE_STATIC
} else if (static_lenb >= 0) { /* force static trees */ } else if (static_lenb >= 0) { /* force static trees */
#else #else
} else if (static_lenb == opt_lenb) { } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
#endif #endif
send_bits(s, (STATIC_TREES<<1)+eof, 3); send_bits(s, (STATIC_TREES<<1)+eof, 3);
compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
@@ -1117,21 +1118,24 @@ local void compress_block(s, ltree, dtree)
} }
/* =========================================================================== /* ===========================================================================
* Set the data type to ASCII or BINARY, using a crude approximation: * Set the data type to BINARY or TEXT, using a crude approximation:
* binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. * set it to Z_TEXT if all symbols are either printable characters (33 to 255)
* IN assertion: the fields freq of dyn_ltree are set and the total of all * or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise.
* frequencies does not exceed 64K (to fit in an int on 16 bit machines). * IN assertion: the fields Freq of dyn_ltree are set.
*/ */
local void set_data_type(s) local void set_data_type(s)
deflate_state *s; deflate_state *s;
{ {
int n = 0; int n;
unsigned ascii_freq = 0;
unsigned bin_freq = 0; for (n = 0; n < 9; n++)
while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; if (s->dyn_ltree[n].Freq != 0)
while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; break;
while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; if (n == 9)
s->strm->data_type = bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII; for (n = 14; n < 32; n++)
if (s->dyn_ltree[n].Freq != 0)
break;
s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY;
} }
/* =========================================================================== /* ===========================================================================

View File

@@ -175,7 +175,7 @@ in the zlib distribution, or at the following location:
zlib in other programming languages. Some of them, like Ada zlib in other programming languages. Some of them, like Ada
(GNAT) and Fortran (GNU G77), have C bindings implemented (GNAT) and Fortran (GNU G77), have C bindings implemented
initially on Unix, and relying on the C calling convention. initially on Unix, and relying on the C calling convention.
On the other hand, the pre- .Net versions of Microsoft Visual On the other hand, the pre- .NET versions of Microsoft Visual
Basic require STDCALL, while Borland Delphi prefers, although Basic require STDCALL, while Borland Delphi prefers, although
it does not require, FASTCALL. it does not require, FASTCALL.
@@ -203,10 +203,10 @@ in the zlib distribution, or at the following location:
zlib distribution. zlib distribution.
8. I need to use zlib in my Microsoft .Net project. What can I 8. I need to use zlib in my Microsoft .NET project. What can I
do? do?
- Henrik Ravn has contributed a .Net wrapper around zlib. Look - Henrik Ravn has contributed a .NET wrapper around zlib. Look
into contrib/dotzlib/, inside the zlib distribution. into contrib/dotzlib/, inside the zlib distribution.
@@ -225,8 +225,8 @@ in the zlib distribution, or at the following location:
depend on it should also be linked to MSVCRT.DLL. depend on it should also be linked to MSVCRT.DLL.
10. Why are you saying that ZLIB1.DLL and my application must be 10. Why are you saying that ZLIB1.DLL and my application should
linked to the same C run-time (CRT) library? I linked my be linked to the same C run-time (CRT) library? I linked my
application and my DLLs to different C libraries (e.g. my application and my DLLs to different C libraries (e.g. my
application to a static library, and my DLLs to MSVCRT.DLL), application to a static library, and my DLLs to MSVCRT.DLL),
and everything works fine. and everything works fine.
@@ -277,12 +277,6 @@ in the zlib distribution, or at the following location:
even run on it. Furthermore, no serious user should run even run on it. Furthermore, no serious user should run
Windows 95 without a proper update installed. Windows 95 without a proper update installed.
There is also the fact that the mainstream C compilers for
Windows are Microsoft Visual C++ 6.0, and gcc/MinGW. Both
are producing executables that link to MSVCRT.DLL by default,
without offering other dynamic CRTs as alternatives easy to
select by users.
12. Why are you not linking ZLIB1.DLL to 12. Why are you not linking ZLIB1.DLL to
<<my favorite C run-time library>> ? <<my favorite C run-time library>> ?
@@ -295,27 +289,60 @@ in the zlib distribution, or at the following location:
to a static C library, you may as well consider linking zlib to a static C library, you may as well consider linking zlib
in statically, too. in statically, too.
* Linking ZLIB1.DLL to CRTDLL.DLL looks very appealing, * Linking ZLIB1.DLL to CRTDLL.DLL looks appealing, because
because CRTDLL.DLL is present on every Win32 installation. CRTDLL.DLL is present on every Win32 installation.
Unfortunately, it has a series of problems: it raises Unfortunately, it has a series of problems: it does not
difficulties when using it with C++ code, it does not work work properly with Microsoft's C++ libraries, it does not
with 64-bit file offsets, (and so on...), and Microsoft provide support for 64-bit file offsets, (and so on...),
discontinued its support a long time ago. and Microsoft discontinued its support a long time ago.
* Linking ZLIB1.DLL to MSVCR70.DLL, supplied with the * Linking ZLIB1.DLL to MSVCR70.DLL or MSVCR71.DLL, supplied
Microsoft .NET platform and Visual C++ 7.0 or newer, is not with the Microsoft .NET platform, and Visual C++ 7.0/7.1,
a good option. Although it is available for free download raises problems related to the status of ZLIB1.DLL as a
and distribution, its presence is scarce on today's Win32 system component. According to the Microsoft Knowledge Base
installations. If it will ever become more popular than article KB326922 "INFO: Redistribution of the Shared C
MSVCRT.DLL and will be pre-installed on the future Win32 Runtime Component in Visual C++ .NET", MSVCR70.DLL and
systems, we will probably think again about it. MSVCR71.DLL are not supposed to function as system DLLs,
because they may clash with MSVCRT.DLL. Instead, the
application's installer is supposed to put these DLLs
(if needed) in the application's private directory.
If ZLIB1.DLL depends on a non-system runtime, it cannot
function as a redistributable system component.
* Linking ZLIB1.DLL to NTDLL.DLL is not possible. * Linking ZLIB1.DLL to non-Microsoft runtimes, such as
NTDLL.DLL exports only a part of the C library, and only on Borland's, or Cygwin's, raises problems related to the
Windows NT systems. reliable presence of these runtimes on Win32 systems.
It's easier to let the DLL build of zlib up to the people
who distribute these runtimes, and who may proceed as
explained in the answer to Question 14.
13. I need to link my own DLL build to a CRT different than 13. If ZLIB1.DLL cannot be linked to MSVCR70.DLL or MSVCR71.DLL,
how can I build/use ZLIB1.DLL in Microsoft Visual C++ 7.0
(Visual Studio .NET) or newer?
- Due to the problems explained in the Microsoft Knowledge Base
article KB326922 (see the previous answer), the C runtime that
comes with the VC7 environment is no longer considered a
system component. That is, it should not be assumed that this
runtime exists, or may be installed in a system directory.
Since ZLIB1.DLL is supposed to be a system component, it may
not depend on a non-system component.
In order to link ZLIB1.DLL and your application to MSVCRT.DLL
in VC7, you need the library of Visual C++ 6.0 or older. If
you don't have this library at hand, it's probably best not to
use ZLIB1.DLL.
We are hoping that, in the future, Microsoft will provide a
way to build applications linked to a proper system runtime,
from the Visual C++ environment. Until then, you have a
couple of alternatives, such as linking zlib in statically.
If your application requires dynamic linking, you may proceed
as explained in the answer to Question 14.
14. I need to link my own DLL build to a CRT different than
MSVCRT.DLL. What can I do? MSVCRT.DLL. What can I do?
- Feel free to rebuild the DLL from the zlib sources, and link - Feel free to rebuild the DLL from the zlib sources, and link
@@ -331,7 +358,7 @@ in the zlib distribution, or at the following location:
CYGWIN1.DLL, and it is distributed under the name CYGZ.DLL. CYGWIN1.DLL, and it is distributed under the name CYGZ.DLL.
14. May I include additional pieces of code that I find useful, 15. May I include additional pieces of code that I find useful,
link them in ZLIB1.DLL, and export them? link them in ZLIB1.DLL, and export them?
- No. A legitimate build of ZLIB1.DLL must not include code - No. A legitimate build of ZLIB1.DLL must not include code
@@ -344,7 +371,7 @@ in the zlib distribution, or at the following location:
is a redistributable file, named VCLxx.DLL. is a redistributable file, named VCLxx.DLL.
15. May I remove some functionality out of ZLIB1.DLL, by enabling 16. May I remove some functionality out of ZLIB1.DLL, by enabling
macros like NO_GZCOMPRESS or NO_GZIP at compile time? macros like NO_GZCOMPRESS or NO_GZIP at compile time?
- No. A legitimate build of ZLIB1.DLL must provide the complete - No. A legitimate build of ZLIB1.DLL must provide the complete
@@ -353,7 +380,7 @@ in the zlib distribution, or at the following location:
different file name, as suggested in the previous answer. different file name, as suggested in the previous answer.
16. I made my own ZLIB1.DLL build. Can I test it for compliance? 17. I made my own ZLIB1.DLL build. Can I test it for compliance?
- We prefer that you download the official DLL from the zlib - We prefer that you download the official DLL from the zlib
web site. If you need something peculiar from this DLL, you web site. If you need something peculiar from this DLL, you

View File

@@ -5,8 +5,8 @@ VS_VERSION_INFO VERSIONINFO
#else #else
VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
#endif #endif
FILEVERSION 1,2,2 FILEVERSION 1,2,2,4
PRODUCTVERSION 1,2,2 PRODUCTVERSION 1,2,2,4
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 1 FILEFLAGS 1
@@ -23,12 +23,12 @@ BEGIN
//language ID = U.S. English, char set = Windows, Multilingual //language ID = U.S. English, char set = Windows, Multilingual
BEGIN BEGIN
VALUE "FileDescription", "zlib data compression library\0" VALUE "FileDescription", "zlib data compression library\0"
VALUE "FileVersion", "1.2.2\0" VALUE "FileVersion", "1.2.2.4\0"
VALUE "InternalName", "zlib1.dll\0" VALUE "InternalName", "zlib1.dll\0"
VALUE "LegalCopyright", "(C) 1995-2004 Jean-loup Gailly & Mark Adler\0" VALUE "LegalCopyright", "(C) 1995-2004 Jean-loup Gailly & Mark Adler\0"
VALUE "OriginalFilename", "zlib1.dll\0" VALUE "OriginalFilename", "zlib1.dll\0"
VALUE "ProductName", "zlib\0" VALUE "ProductName", "zlib\0"
VALUE "ProductVersion", "1.2.2\0" VALUE "ProductVersion", "1.2.2.4\0"
VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
END END
END END

10
zconf.h
View File

@@ -1,5 +1,5 @@
/* zconf.h -- configuration of the zlib compression library /* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995-2004 Jean-loup Gailly. * Copyright (C) 1995-2005 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@@ -43,6 +43,10 @@
# define get_crc_table z_get_crc_table # define get_crc_table z_get_crc_table
# define zError z_zError # define zError z_zError
# define alloc_func z_alloc_func
# define free_func z_free_func
# define in_func z_in_func
# define out_func z_out_func
# define Byte z_Byte # define Byte z_Byte
# define uInt z_uInt # define uInt z_uInt
# define uLong z_uLong # define uLong z_uLong
@@ -64,8 +68,10 @@
#if defined(_WINDOWS) && !defined(WINDOWS) #if defined(_WINDOWS) && !defined(WINDOWS)
# define WINDOWS # define WINDOWS
#endif #endif
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) #if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
# ifndef WIN32
# define WIN32 # define WIN32
# endif
#endif #endif
#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) #if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) # if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)

View File

@@ -1,5 +1,5 @@
/* zconf.h -- configuration of the zlib compression library /* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995-2004 Jean-loup Gailly. * Copyright (C) 1995-2005 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@@ -43,6 +43,10 @@
# define get_crc_table z_get_crc_table # define get_crc_table z_get_crc_table
# define zError z_zError # define zError z_zError
# define alloc_func z_alloc_func
# define free_func z_free_func
# define in_func z_in_func
# define out_func z_out_func
# define Byte z_Byte # define Byte z_Byte
# define uInt z_uInt # define uInt z_uInt
# define uLong z_uLong # define uLong z_uLong
@@ -64,8 +68,10 @@
#if defined(_WINDOWS) && !defined(WINDOWS) #if defined(_WINDOWS) && !defined(WINDOWS)
# define WINDOWS # define WINDOWS
#endif #endif
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) #if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
# ifndef WIN32
# define WIN32 # define WIN32
# endif
#endif #endif
#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) #if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) # if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)

6
zlib.3
View File

@@ -1,4 +1,4 @@
.TH ZLIB 3 "3 October 2004" .TH ZLIB 3 "11 July 2005"
.SH NAME .SH NAME
zlib \- compression/decompression library zlib \- compression/decompression library
.SH SYNOPSIS .SH SYNOPSIS
@@ -133,8 +133,8 @@ before asking for help.
Send questions and/or comments to zlib@gzip.org, Send questions and/or comments to zlib@gzip.org,
or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). or (for the Windows DLL version) to Gilles Vollant (info@winimage.com).
.SH AUTHORS .SH AUTHORS
Version 1.2.2 Version 1.2.2.4
Copyright (C) 1995-2004 Jean-loup Gailly (jloup@gzip.org) Copyright (C) 1995-2005 Jean-loup Gailly (jloup@gzip.org)
and Mark Adler (madler@alumni.caltech.edu). and Mark Adler (madler@alumni.caltech.edu).
.LP .LP
This software is provided "as-is," This software is provided "as-is,"

229
zlib.h
View File

@@ -1,7 +1,7 @@
/* zlib.h -- interface of the 'zlib' general purpose compression library /* zlib.h -- interface of the 'zlib' general purpose compression library
version 1.2.2, October 3rd, 2004 version 1.2.2.4, July 11th, 2005
Copyright (C) 1995-2004 Jean-loup Gailly and Mark Adler Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
@@ -37,8 +37,8 @@
extern "C" { extern "C" {
#endif #endif
#define ZLIB_VERSION "1.2.2" #define ZLIB_VERSION "1.2.2.4"
#define ZLIB_VERNUM 0x1220 #define ZLIB_VERNUM 0x1224
/* /*
The 'zlib' compression library provides in-memory compression and The 'zlib' compression library provides in-memory compression and
@@ -95,13 +95,36 @@ typedef struct z_stream_s {
free_func zfree; /* used to free the internal state */ free_func zfree; /* used to free the internal state */
voidpf opaque; /* private data object passed to zalloc and zfree */ voidpf opaque; /* private data object passed to zalloc and zfree */
int data_type; /* best guess about the data type: ascii or binary */ int data_type; /* best guess about the data type: binary or text */
uLong adler; /* adler32 value of the uncompressed data */ uLong adler; /* adler32 value of the uncompressed data */
uLong reserved; /* reserved for future use */ uLong reserved; /* reserved for future use */
} z_stream; } z_stream;
typedef z_stream FAR *z_streamp; typedef z_stream FAR *z_streamp;
/*
gzip header information passed to and from zlib routines. See RFC 1952
for more details on the meanings of these fields.
*/
typedef struct gz_header_s {
int text; /* true if compressed data believed to be text */
uLong time; /* modification time */
int xflags; /* extra flags (not used when writing a gzip file) */
int os; /* operating system */
Bytef *extra; /* pointer to extra field or Z_NULL if none */
uInt extra_len; /* extra field length (valid if extra != Z_NULL) */
uInt extra_max; /* space at extra (only when reading header) */
Bytef *name; /* pointer to zero-terminated file name or Z_NULL */
uInt name_max; /* space at name (only when reading header) */
Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */
uInt comm_max; /* space at comment (only when reading header) */
int hcrc; /* true if there was or will be a header crc */
int done; /* true when done reading gzip header (not used
when writing a gzip file) */
} gz_header;
typedef gz_header FAR *gz_headerp;
/* /*
The application must update next_in and avail_in when avail_in has The application must update next_in and avail_in when avail_in has
dropped to zero. It must update next_out and avail_out when avail_out dropped to zero. It must update next_out and avail_out when avail_out
@@ -166,11 +189,13 @@ typedef z_stream FAR *z_streamp;
#define Z_FILTERED 1 #define Z_FILTERED 1
#define Z_HUFFMAN_ONLY 2 #define Z_HUFFMAN_ONLY 2
#define Z_RLE 3 #define Z_RLE 3
#define Z_FIXED 4
#define Z_DEFAULT_STRATEGY 0 #define Z_DEFAULT_STRATEGY 0
/* compression strategy; see deflateInit2() below for details */ /* compression strategy; see deflateInit2() below for details */
#define Z_BINARY 0 #define Z_BINARY 0
#define Z_ASCII 1 #define Z_TEXT 1
#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */
#define Z_UNKNOWN 2 #define Z_UNKNOWN 2
/* Possible values of the data_type field (though see inflate()) */ /* Possible values of the data_type field (though see inflate()) */
@@ -244,6 +269,10 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
and with zero avail_out, it must be called again after making room in the and with zero avail_out, it must be called again after making room in the
output buffer because there might be more output pending. output buffer because there might be more output pending.
Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
decide how much data to accumualte before producing output, in order to
maximize compression.
If the parameter flush is set to Z_SYNC_FLUSH, all pending output is If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
flushed to the output buffer and the output is aligned on a byte boundary, so flushed to the output buffer and the output is aligned on a byte boundary, so
that the decompressor can get all input data available so far. (In particular that the decompressor can get all input data available so far. (In particular
@@ -255,7 +284,7 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
Z_SYNC_FLUSH, and the compression state is reset so that decompression can Z_SYNC_FLUSH, and the compression state is reset so that decompression can
restart from this point if previous compressed data has been damaged or if restart from this point if previous compressed data has been damaged or if
random access is desired. Using Z_FULL_FLUSH too often can seriously degrade random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
the compression. compression.
If deflate returns with avail_out == 0, this function must be called again If deflate returns with avail_out == 0, this function must be called again
with the same value of the flush parameter and more output space (updated with the same value of the flush parameter and more output space (updated
@@ -280,8 +309,8 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
deflate() sets strm->adler to the adler32 checksum of all input read deflate() sets strm->adler to the adler32 checksum of all input read
so far (that is, total_in bytes). so far (that is, total_in bytes).
deflate() may update data_type if it can make a good guess about deflate() may update strm->data_type if it can make a good guess about
the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered
binary. This field is only for information purposes and does not affect binary. This field is only for information purposes and does not affect
the compression algorithm in any manner. the compression algorithm in any manner.
@@ -363,11 +392,11 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH,
Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much
output as possible to the output buffer. Z_BLOCK requests that inflate() stop output as possible to the output buffer. Z_BLOCK requests that inflate() stop
if and when it get to the next deflate block boundary. When decoding the zlib if and when it gets to the next deflate block boundary. When decoding the
or gzip format, this will cause inflate() to return immediately after the zlib or gzip format, this will cause inflate() to return immediately after
header and before the first block. When doing a raw inflate, inflate() will the header and before the first block. When doing a raw inflate, inflate()
go ahead and process the first block, and will return when it gets to the end will go ahead and process the first block, and will return when it gets to
of that block, or when it runs out of data. the end of that block, or when it runs out of data.
The Z_BLOCK option assists in appending to or combining deflate streams. The Z_BLOCK option assists in appending to or combining deflate streams.
Also to assist in this, on return inflate() will set strm->data_type to the Also to assist in this, on return inflate() will set strm->data_type to the
@@ -496,7 +525,9 @@ ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as
Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy
parameter only affects the compression ratio but not the correctness of the parameter only affects the compression ratio but not the correctness of the
compressed output even if it is not set appropriately. compressed output even if it is not set appropriately. Z_FIXED prevents the
use of dynamic Huffman codes, allowing for a simpler decoder for special
applications.
deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
@@ -525,7 +556,9 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
deflateInit or deflateInit2, a part of the dictionary may in effect be deflateInit or deflateInit2, a part of the dictionary may in effect be
discarded, for example if the dictionary is larger than the window size in discarded, for example if the dictionary is larger than the window size in
deflate or deflate2. Thus the strings most likely to be useful should be deflate or deflate2. Thus the strings most likely to be useful should be
put at the end of the dictionary, not at the front. put at the end of the dictionary, not at the front. In addition, the
current implementation of deflate will use at most the window size minus
262 bytes of the provided dictionary.
Upon return of this function, strm->adler is set to the adler32 value Upon return of this function, strm->adler is set to the adler32 value
of the dictionary; the decompressor may later use this value to determine of the dictionary; the decompressor may later use this value to determine
@@ -591,6 +624,23 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
if strm->avail_out was zero. if strm->avail_out was zero.
*/ */
ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
int good_length,
int max_lazy,
int nice_length,
int max_chain));
/*
Fine tune deflate's internal compression parameters. This should only be
used by someone who understands the algorithm used by zlib's deflate for
searching for the best matching string, and even then only by the most
fanatic optimizer trying to squeeze out the last compressed bit for their
specific input data. Read the deflate.c source code for the meaning of the
max_lazy, good_length, nice_length, and max_chain parameters.
deflateTune() can be called after deflateInit() or deflateInit2(), and
returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
*/
ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
uLong sourceLen)); uLong sourceLen));
/* /*
@@ -616,6 +666,30 @@ ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
stream state was inconsistent. stream state was inconsistent.
*/ */
ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
gz_headerp head));
/*
deflateSetHeader() provides gzip header information for when a gzip
stream is requested by deflateInit2(). deflateSetHeader() may be called
after deflateInit2() or deflateReset() and before the first call of
deflate(). The text, time, os, extra field, name, and comment information
in the provided gz_header structure are written to the gzip header (xflag is
ignored -- the extra flags are set according to the compression level). The
caller must assure that, if not Z_NULL, name and comment are terminated with
a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
available there. If hcrc is true, a gzip header crc is included. Note that
the current versions of the command-line version of gzip (up through version
1.3.x) do not support header crc's, and will report that it is a "multi-part
gzip file" and give up.
If deflateSetHeader is not used, the default gzip header has text false,
the time set to zero, and os set to 255, with no extra, name, or comment
fields. The gzip header is returned to the default state by deflateReset().
deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
stream state was inconsistent.
*/
/* /*
ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
int windowBits)); int windowBits));
@@ -648,15 +722,15 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
windowBits can also be greater than 15 for optional gzip decoding. Add windowBits can also be greater than 15 for optional gzip decoding. Add
32 to windowBits to enable zlib and gzip decoding with automatic header 32 to windowBits to enable zlib and gzip decoding with automatic header
detection, or add 16 to decode only the gzip format (the zlib format will detection, or add 16 to decode only the gzip format (the zlib format will
return a Z_DATA_ERROR. If a gzip stream is being decoded, strm->adler is return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is
a crc32 instead of an adler32. a crc32 instead of an adler32.
inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg
memLevel). msg is set to null if there is no error message. inflateInit2 is set to null if there is no error message. inflateInit2 does not perform
does not perform any decompression apart from reading the zlib header if any decompression apart from reading the zlib header if present: this will
present: this will be done by inflate(). (So next_in and avail_in may be be done by inflate(). (So next_in and avail_in may be modified, but next_out
modified, but next_out and avail_out are unchanged.) and avail_out are unchanged.)
*/ */
ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
@@ -664,11 +738,14 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
uInt dictLength)); uInt dictLength));
/* /*
Initializes the decompression dictionary from the given uncompressed byte Initializes the decompression dictionary from the given uncompressed byte
sequence. This function must be called immediately after a call of inflate sequence. This function must be called immediately after a call of inflate,
if this call returned Z_NEED_DICT. The dictionary chosen by the compressor if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
can be determined from the adler32 value returned by this call of can be determined from the adler32 value returned by that call of inflate.
inflate. The compressor and decompressor must use exactly the same The compressor and decompressor must use exactly the same dictionary (see
dictionary (see deflateSetDictionary). deflateSetDictionary). For raw inflate, this function can be called
immediately after inflateInit2() or inflateReset() and before any call of
inflate() to set the dictionary. The application must insure that the
dictionary that was used for compression is provided.
inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
parameter is invalid (such as NULL dictionary) or the stream state is parameter is invalid (such as NULL dictionary) or the stream state is
@@ -719,8 +796,64 @@ ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
stream state was inconsistent (such as zalloc or state being NULL). stream state was inconsistent (such as zalloc or state being NULL).
*/ */
ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
int bits,
int value));
/* /*
ZEXTERN int ZEXPORT inflateBackInit OF((z_stream FAR *strm, int windowBits, This function inserts bits in the inflate input stream. The intent is
that this function is used to start inflating at a bit position in the
middle of a byte. The provided bits will be used before any bytes are used
from next_in. This function should only be used with raw inflate, and
should be used before the first inflate() call after inflateInit2() or
inflateReset(). bits must be less than or equal to 16, and that many of the
least significant bits of value will be inserted in the input.
inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
stream state was inconsistent.
*/
ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
gz_headerp head));
/*
inflateGetHeader() requests that gzip header information be stored in the
provided gz_header structure. inflateGetHeader() may be called after
inflateInit2() or inflateReset(), and before the first call of inflate().
As inflate() processes the gzip stream, head->done is zero until the header
is completed, at which time head->done is set to one. If a zlib stream is
being decoded, then head->done is set to -1 to indicate that there will be
no gzip header information forthcoming. Note that Z_BLOCK can be used to
force inflate() to return immediately after header processing is complete
and before any actual data is decompressed.
The text, time, xflags, and os fields are filled in with the gzip header
contents. hcrc is set to true if there is a header CRC. (The header CRC
was valid if done is set to one.) If extra is not Z_NULL, then extra_max
contains the maximum number of bytes to write to extra. Once done is true,
extra_len contains the actual extra field length, and extra contains the
extra field, or that field truncated if extra_max is less than extra_len.
If name is not Z_NULL, then up to name_max characters are written there,
terminated with a zero unless the length is greater than name_max. If
comment is not Z_NULL, then up to comm_max characters are written there,
terminated with a zero unless the length is greater than comm_max. When
any of extra, name, or comment are not Z_NULL and the respective field is
not present in the header, then that field is set to Z_NULL to signal its
absence. This allows the use of deflateSetHeader() with the returned
structure to duplicate the header. However if those fields are set to
allocated memory, then the application will need to save those pointers
elsewhere so that they can be eventually freed.
If inflateGetHeader is not used, then the header information is simply
discarded. The header is always checked for validity, including the header
CRC if present. inflateReset() will reset the process to discard the header
information. The application would need to call inflateGetHeader() again to
retrieve the header from the next gzip stream.
inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
stream state was inconsistent.
*/
/*
ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
unsigned char FAR *window)); unsigned char FAR *window));
Initialize the internal stream state for decompression using inflateBack() Initialize the internal stream state for decompression using inflateBack()
@@ -744,7 +877,7 @@ ZEXTERN int ZEXPORT inflateBackInit OF((z_stream FAR *strm, int windowBits,
typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
ZEXTERN int ZEXPORT inflateBack OF((z_stream FAR *strm, ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
in_func in, void FAR *in_desc, in_func in, void FAR *in_desc,
out_func out, void FAR *out_desc)); out_func out, void FAR *out_desc));
/* /*
@@ -813,7 +946,7 @@ ZEXTERN int ZEXPORT inflateBack OF((z_stream FAR *strm,
that inflateBack() cannot return Z_OK. that inflateBack() cannot return Z_OK.
*/ */
ZEXTERN int ZEXPORT inflateBackEnd OF((z_stream FAR *strm)); ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
/* /*
All memory allocated by inflateBackInit() is freed. All memory allocated by inflateBackInit() is freed.
@@ -1087,6 +1220,12 @@ ZEXTERN int ZEXPORT gzeof OF((gzFile file));
input stream, otherwise zero. input stream, otherwise zero.
*/ */
ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
/*
Returns 1 if file is being read directly without decompression, otherwise
zero.
*/
ZEXTERN int ZEXPORT gzclose OF((gzFile file)); ZEXTERN int ZEXPORT gzclose OF((gzFile file));
/* /*
Flushes all pending output if necessary, closes the compressed file Flushes all pending output if necessary, closes the compressed file
@@ -1119,7 +1258,6 @@ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
*/ */
ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
/* /*
Update a running Adler-32 checksum with the bytes buf[0..len-1] and Update a running Adler-32 checksum with the bytes buf[0..len-1] and
return the updated checksum. If buf is NULL, this function returns return the updated checksum. If buf is NULL, this function returns
@@ -1135,12 +1273,21 @@ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
if (adler != original_adler) error(); if (adler != original_adler) error();
*/ */
ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
z_off_t len2));
/*
Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of
seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.
*/
ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
/* /*
Update a running crc with the bytes buf[0..len-1] and return the updated Update a running CRC-32 with the bytes buf[0..len-1] and return the
crc. If buf is NULL, this function returns the required initial value updated CRC-32. If buf is NULL, this function returns the required initial
for the crc. Pre- and post-conditioning (one's complement) is performed value for the for the crc. Pre- and post-conditioning (one's complement) is
within this function so it shouldn't be done by the application. performed within this function so it shouldn't be done by the application.
Usage example: Usage example:
uLong crc = crc32(0L, Z_NULL, 0); uLong crc = crc32(0L, Z_NULL, 0);
@@ -1151,6 +1298,16 @@ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
if (crc != original_crc) error(); if (crc != original_crc) error();
*/ */
ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
/*
Combine two CRC-32 check values into one. For two sequences of bytes,
seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
len2.
*/
/* various hacks, don't look :) */ /* various hacks, don't look :) */
@@ -1167,7 +1324,7 @@ ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
int stream_size)); int stream_size));
ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
const char *version, int stream_size)); const char *version, int stream_size));
ZEXTERN int ZEXPORT inflateBackInit_ OF((z_stream FAR *strm, int windowBits, ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
unsigned char FAR *window, unsigned char FAR *window,
const char *version, const char *version,
int stream_size)); int stream_size));

33
zutil.c
View File

@@ -1,5 +1,5 @@
/* zutil.c -- target dependent utility functions for the compression library /* zutil.c -- target dependent utility functions for the compression library
* Copyright (C) 1995-2003 Jean-loup Gailly. * Copyright (C) 1995-2005 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@@ -11,10 +11,6 @@
struct internal_state {int dummy;}; /* for buggy compilers */ struct internal_state {int dummy;}; /* for buggy compilers */
#endif #endif
#ifndef STDC
extern void exit OF((int));
#endif
const char * const z_errmsg[10] = { const char * const z_errmsg[10] = {
"need dictionary", /* Z_NEED_DICT 2 */ "need dictionary", /* Z_NEED_DICT 2 */
"stream end", /* Z_STREAM_END 1 */ "stream end", /* Z_STREAM_END 1 */
@@ -78,38 +74,38 @@ uLong ZEXPORT zlibCompileFlags()
flags += 1 << 13; flags += 1 << 13;
#endif #endif
#ifdef NO_GZCOMPRESS #ifdef NO_GZCOMPRESS
flags += 1 << 16; flags += 1L << 16;
#endif #endif
#ifdef NO_GZIP #ifdef NO_GZIP
flags += 1 << 17; flags += 1L << 17;
#endif #endif
#ifdef PKZIP_BUG_WORKAROUND #ifdef PKZIP_BUG_WORKAROUND
flags += 1 << 20; flags += 1L << 20;
#endif #endif
#ifdef FASTEST #ifdef FASTEST
flags += 1 << 21; flags += 1L << 21;
#endif #endif
#ifdef STDC #ifdef STDC
# ifdef NO_vsnprintf # ifdef NO_vsnprintf
flags += 1 << 25; flags += 1L << 25;
# ifdef HAS_vsprintf_void # ifdef HAS_vsprintf_void
flags += 1 << 26; flags += 1L << 26;
# endif # endif
# else # else
# ifdef HAS_vsnprintf_void # ifdef HAS_vsnprintf_void
flags += 1 << 26; flags += 1L << 26;
# endif # endif
# endif # endif
#else #else
flags += 1 << 24; flags += 1L << 24;
# ifdef NO_snprintf # ifdef NO_snprintf
flags += 1 << 25; flags += 1L << 25;
# ifdef HAS_sprintf_void # ifdef HAS_sprintf_void
flags += 1 << 26; flags += 1L << 26;
# endif # endif
# else # else
# ifdef HAS_snprintf_void # ifdef HAS_snprintf_void
flags += 1 << 26; flags += 1L << 26;
# endif # endif
# endif # endif
#endif #endif
@@ -141,7 +137,10 @@ const char * ZEXPORT zError(err)
} }
#if defined(_WIN32_WCE) #if defined(_WIN32_WCE)
/* does not exist on WCE */ /* The Microsoft C Run-Time Library for Windows CE doesn't have
* errno. We define it as a global variable to simplify porting.
* Its value is always 0 and should not be used.
*/
int errno = 0; int errno = 0;
#endif #endif

26
zutil.h
View File

@@ -1,5 +1,5 @@
/* zutil.h -- internal interface and configuration of the compression library /* zutil.h -- internal interface and configuration of the compression library
* Copyright (C) 1995-2003 Jean-loup Gailly. * Copyright (C) 1995-2005 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@@ -17,14 +17,26 @@
#include "zlib.h" #include "zlib.h"
#ifdef STDC #ifdef STDC
# ifndef _WIN32_WCE
# include <stddef.h> # include <stddef.h>
# endif
# include <string.h> # include <string.h>
# include <stdlib.h> # include <stdlib.h>
#endif #endif
#ifdef NO_ERRNO_H #ifdef NO_ERRNO_H
# ifdef _WIN32_WCE
/* The Microsoft C Run-Time Library for Windows CE doesn't have
* errno. We define it as a global variable to simplify porting.
* Its value is always 0 and should not be used. We rename it to
* avoid conflict with other libraries that use the same workaround.
*/
# define errno z_errno
# endif
extern int errno; extern int errno;
#else #else
# ifndef _WIN32_WCE
# include <errno.h> # include <errno.h>
# endif
#endif #endif
#ifndef local #ifndef local
@@ -105,6 +117,9 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
#ifdef OS2 #ifdef OS2
# define OS_CODE 0x06 # define OS_CODE 0x06
# ifdef M_I86
#include <malloc.h>
# endif
#endif #endif
#if defined(MACOS) || defined(TARGET_OS_MAC) #if defined(MACOS) || defined(TARGET_OS_MAC)
@@ -193,15 +208,6 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
# define NO_vsnprintf # define NO_vsnprintf
#endif #endif
#ifdef HAVE_STRERROR
# ifndef VMS
extern char *strerror OF((int));
# endif
# define zstrerror(errnum) strerror(errnum)
#else
# define zstrerror(errnum) ""
#endif
#if defined(pyr) #if defined(pyr)
# define NO_MEMCPY # define NO_MEMCPY
#endif #endif