Compare commits

..

1 Commits

Author SHA1 Message Date
Mark Adler
6b8233bfe0 zlib 1.2.2.3 2011-09-09 23:24:43 -07:00
63 changed files with 11616 additions and 8906 deletions

View File

@@ -1,6 +1,27 @@
ChangeLog file for zlib ChangeLog file for zlib
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) Changes in 1.2.2.2 (30 December 2004)
- Replace structure assignments in deflate.c and inflate.c with zmemcpy to - Replace structure assignments in deflate.c and inflate.c with zmemcpy to
avoid implicit memcpy calls (portability for no-library compilation) avoid implicit memcpy calls (portability for no-library compilation)

View File

@@ -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.2 SHAREDLIBV=libz.so.1.2.2.3
SHAREDLIBM=libz.so.1 SHAREDLIBM=libz.so.1
AR=ar rc AR=ar rc

View File

@@ -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.2 SHAREDLIBV=libz.so.1.2.2.3
SHAREDLIBM=libz.so.1 SHAREDLIBM=libz.so.1
AR=ar rc AR=ar rc

4
README
View File

@@ -1,6 +1,6 @@
ZLIB DATA COMPRESSION LIBRARY ZLIB DATA COMPRESSION LIBRARY
zlib 1.2.2.2 is a general purpose data compression library. All the code is zlib 1.2.2.3 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)
@@ -33,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.2 are documented in the file ChangeLog. The changes made in version 1.2.2.3 are documented in the file ChangeLog.
Unsupported third party contributions are provided in directory "contrib". Unsupported third party contributions are provided in directory "contrib".

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.2 * Version 1.2.2.3
* *
* *
* WARNING: * WARNING:
@@ -20,8 +20,12 @@
* Constants * Constants
************************************************************************** **************************************************************************
* *
D ZLIB_VERSION C '1.2.2.2' Header's version * Versioning information.
D ZLIB_VERNUM C X'1222' *
D ZLIB_VERSION C '1.2.2.3'
D ZLIB_VERNUM C X'1223'
*
* 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

@@ -42,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

@@ -1,354 +1,364 @@
/* match.s -- Pentium-optimized version of longest_match() /* match.s -- Pentium-optimized version of longest_match()
* 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>
* *
* This is free software; you can redistribute it and/or modify it * This is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License. * under the terms of the GNU General Public License.
*/ */
#ifndef NO_UNDERLINE #ifndef NO_UNDERLINE
#define match_init _match_init #define match_init _match_init
#define longest_match _longest_match #define longest_match _longest_match
#endif #endif
#define MAX_MATCH (258) #define MAX_MATCH (258)
#define MIN_MATCH (3) #define MIN_MATCH (3)
#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) #define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) #define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7)
/* stack frame offsets */ /* stack frame offsets */
#define wmask 0 /* local copy of s->wmask */ #define wmask 0 /* local copy of s->wmask */
#define window 4 /* local copy of s->window */ #define window 4 /* local copy of s->window */
#define windowbestlen 8 /* s->window + bestlen */ #define windowbestlen 8 /* s->window + bestlen */
#define chainlenscanend 12 /* high word: current chain len */ #define chainlenscanend 12 /* high word: current chain len */
/* low word: last bytes sought */ /* low word: last bytes sought */
#define scanstart 16 /* first two bytes of string */ #define scanstart 16 /* first two bytes of string */
#define scanalign 20 /* dword-misalignment of string */ #define scanalign 20 /* dword-misalignment of string */
#define nicematch 24 /* a good enough match size */ #define nicematch 24 /* a good enough match size */
#define bestlen 28 /* size of best match so far */ #define bestlen 28 /* size of best match so far */
#define scan 32 /* ptr to string wanting match */ #define scan 32 /* ptr to string wanting match */
#define LocalVarsSize (36) #define LocalVarsSize (36)
/* saved ebx 36 */ /* saved ebx 36 */
/* saved edi 40 */ /* saved edi 40 */
/* saved esi 44 */ /* saved esi 44 */
/* saved ebp 48 */ /* saved ebp 48 */
/* return address 52 */ /* return address 52 */
#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 /* Offsets for fields in the deflate_state structure. These numbers
* are calculated from the definition of deflate_state, with the * are calculated from the definition of deflate_state, with the
* assumption that the compiler will dword-align the fields. (Thus, * assumption that the compiler will dword-align the fields. (Thus,
* changing the definition of deflate_state could easily cause this * changing the definition of deflate_state could easily cause this
* 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)
.file "match.S" #define dsPrevMatch (92+zlib1222add)
#define dsStrStart (100+zlib1222add)
.globl match_init, longest_match #define dsMatchStart (104+zlib1222add)
#define dsLookahead (108+zlib1222add)
.text #define dsPrevLen (112+zlib1222add)
#define dsMaxChainLen (116+zlib1222add)
/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ #define dsGoodMatch (132+zlib1222add)
#define dsNiceMatch (136+zlib1222add)
longest_match:
/* Save registers that the compiler may be using, and adjust %esp to */ .file "match.S"
/* make room for our stack frame. */
.globl match_init, longest_match
pushl %ebp
pushl %edi .text
pushl %esi
pushl %ebx /* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
subl $LocalVarsSize, %esp
longest_match:
/* Retrieve the function arguments. %ecx will hold cur_match */
/* throughout the entire function. %edx will hold the pointer to the */ /* Save registers that the compiler may be using, and adjust %esp to */
/* deflate_state structure during the function's setup (before */ /* make room for our stack frame. */
/* entering the main loop). */
pushl %ebp
movl deflatestate(%esp), %edx pushl %edi
movl curmatch(%esp), %ecx pushl %esi
pushl %ebx
/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ subl $LocalVarsSize, %esp
movl dsNiceMatch(%edx), %eax /* Retrieve the function arguments. %ecx will hold cur_match */
movl dsLookahead(%edx), %ebx /* throughout the entire function. %edx will hold the pointer to the */
cmpl %eax, %ebx /* deflate_state structure during the function's setup (before */
jl LookaheadLess /* entering the main loop). */
movl %eax, %ebx
LookaheadLess: movl %ebx, nicematch(%esp) movl deflatestate(%esp), %edx
movl curmatch(%esp), %ecx
/* register Bytef *scan = s->window + s->strstart; */
/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */
movl dsWindow(%edx), %esi
movl %esi, window(%esp) movl dsNiceMatch(%edx), %eax
movl dsStrStart(%edx), %ebp movl dsLookahead(%edx), %ebx
lea (%esi,%ebp), %edi cmpl %eax, %ebx
movl %edi, scan(%esp) jl LookaheadLess
movl %eax, %ebx
/* Determine how many bytes the scan ptr is off from being */ LookaheadLess: movl %ebx, nicematch(%esp)
/* dword-aligned. */
/* register Bytef *scan = s->window + s->strstart; */
movl %edi, %eax
negl %eax movl dsWindow(%edx), %esi
andl $3, %eax movl %esi, window(%esp)
movl %eax, scanalign(%esp) movl dsStrStart(%edx), %ebp
lea (%esi,%ebp), %edi
/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ movl %edi, scan(%esp)
/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
/* Determine how many bytes the scan ptr is off from being */
movl dsWSize(%edx), %eax /* dword-aligned. */
subl $MIN_LOOKAHEAD, %eax
subl %eax, %ebp movl %edi, %eax
jg LimitPositive negl %eax
xorl %ebp, %ebp andl $3, %eax
LimitPositive: movl %eax, scanalign(%esp)
/* unsigned chain_length = s->max_chain_length; */ /* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
/* if (s->prev_length >= s->good_match) { */ /* s->strstart - (IPos)MAX_DIST(s) : NIL; */
/* chain_length >>= 2; */
/* } */ movl dsWSize(%edx), %eax
subl $MIN_LOOKAHEAD, %eax
movl dsPrevLen(%edx), %eax subl %eax, %ebp
movl dsGoodMatch(%edx), %ebx jg LimitPositive
cmpl %ebx, %eax xorl %ebp, %ebp
movl dsMaxChainLen(%edx), %ebx LimitPositive:
jl LastMatchGood
shrl $2, %ebx /* unsigned chain_length = s->max_chain_length; */
LastMatchGood: /* if (s->prev_length >= s->good_match) { */
/* chain_length >>= 2; */
/* 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 scanend */ movl dsPrevLen(%edx), %eax
/* scanend value, which it will always accompany. */ movl dsGoodMatch(%edx), %ebx
cmpl %ebx, %eax
decl %ebx movl dsMaxChainLen(%edx), %ebx
shll $16, %ebx jl LastMatchGood
shrl $2, %ebx
/* int best_len = s->prev_length; */ LastMatchGood:
movl dsPrevLen(%edx), %eax /* chainlen is decremented once beforehand so that the function can */
movl %eax, bestlen(%esp) /* 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 scanend */
/* Store the sum of s->window + best_len in %esi locally, and in %esi. */ /* scanend value, which it will always accompany. */
addl %eax, %esi decl %ebx
movl %esi, windowbestlen(%esp) shll $16, %ebx
/* register ush scan_start = *(ushf*)scan; */ /* int best_len = s->prev_length; */
/* register ush scan_end = *(ushf*)(scan+best_len-1); */
movl dsPrevLen(%edx), %eax
movw (%edi), %bx movl %eax, bestlen(%esp)
movw %bx, scanstart(%esp)
movw -1(%edi,%eax), %bx /* Store the sum of s->window + best_len in %esi locally, and in %esi. */
movl %ebx, chainlenscanend(%esp)
addl %eax, %esi
/* Posf *prev = s->prev; */ movl %esi, windowbestlen(%esp)
/* uInt wmask = s->w_mask; */
/* register ush scan_start = *(ushf*)scan; */
movl dsPrev(%edx), %edi /* register ush scan_end = *(ushf*)(scan+best_len-1); */
movl dsWMask(%edx), %edx
mov %edx, wmask(%esp) movw (%edi), %bx
movw %bx, scanstart(%esp)
/* Jump into the main loop. */ movw -1(%edi,%eax), %bx
movl %ebx, chainlenscanend(%esp)
jmp LoopEntry
/* Posf *prev = s->prev; */
.balign 16 /* uInt wmask = s->w_mask; */
/* do { movl dsPrev(%edx), %edi
* match = s->window + cur_match; movl dsWMask(%edx), %edx
* if (*(ushf*)(match+best_len-1) != scan_end || mov %edx, wmask(%esp)
* *(ushf*)match != scan_start) continue;
* [...] /* Jump into the main loop. */
* } while ((cur_match = prev[cur_match & wmask]) > limit
* && --chain_length != 0); jmp LoopEntry
*
* Here is the inner loop of the function. The function will spend the .balign 16
* majority of its time in this loop, and majority of that time will
* be spent in the first ten instructions. /* do {
* * match = s->window + cur_match;
* Within this loop: * if (*(ushf*)(match+best_len-1) != scan_end ||
* %ebx = chainlenscanend - i.e., ((chainlen << 16) | scanend) * *(ushf*)match != scan_start) continue;
* %ecx = curmatch * [...]
* %edx = curmatch & wmask * } while ((cur_match = prev[cur_match & wmask]) > limit
* %esi = windowbestlen - i.e., (window + bestlen) * && --chain_length != 0);
* %edi = prev *
* %ebp = limit * 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
* Two optimization notes on the choice of instructions: * be spent in the first ten instructions.
* *
* The first instruction uses a 16-bit address, which costs an extra, * Within this loop:
* unpairable cycle. This is cheaper than doing a 32-bit access and * %ebx = chainlenscanend - i.e., ((chainlen << 16) | scanend)
* zeroing the high word, due to the 3-cycle misalignment penalty which * %ecx = curmatch
* would occur half the time. This also turns out to be cheaper than * %edx = curmatch & wmask
* doing two separate 8-bit accesses, as the memory is so rarely in the * %esi = windowbestlen - i.e., (window + bestlen)
* L1 cache. * %edi = prev
* * %ebp = limit
* The window buffer, however, apparently spends a lot of time in the *
* cache, and so it is faster to retrieve the word at the end of the * Two optimization notes on the choice of instructions:
* match string with two 8-bit loads. The instructions that test the *
* word at the beginning of the match string, however, are executed * The first instruction uses a 16-bit address, which costs an extra,
* much less frequently, and there it was cheaper to use 16-bit * unpairable cycle. This is cheaper than doing a 32-bit access and
* instructions, which avoided the necessity of saving off and * zeroing the high word, due to the 3-cycle misalignment penalty which
* subsequently reloading one of the other registers. * would occur half the time. This also turns out to be cheaper than
*/ * doing two separate 8-bit accesses, as the memory is so rarely in the
LookupLoop: * L1 cache.
/* 1 U & V */ *
movw (%edi,%edx,2), %cx /* 2 U pipe */ * The window buffer, however, apparently spends a lot of time in the
movl wmask(%esp), %edx /* 2 V pipe */ * cache, and so it is faster to retrieve the word at the end of the
cmpl %ebp, %ecx /* 3 U pipe */ * match string with two 8-bit loads. The instructions that test the
jbe LeaveNow /* 3 V pipe */ * word at the beginning of the match string, however, are executed
subl $0x00010000, %ebx /* 4 U pipe */ * much less frequently, and there it was cheaper to use 16-bit
js LeaveNow /* 4 V pipe */ * instructions, which avoided the necessity of saving off and
LoopEntry: movb -1(%esi,%ecx), %al /* 5 U pipe */ * subsequently reloading one of the other registers.
andl %ecx, %edx /* 5 V pipe */ */
cmpb %bl, %al /* 6 U pipe */ LookupLoop:
jnz LookupLoop /* 6 V pipe */ /* 1 U & V */
movb (%esi,%ecx), %ah movw (%edi,%edx,2), %cx /* 2 U pipe */
cmpb %bh, %ah movl wmask(%esp), %edx /* 2 V pipe */
jnz LookupLoop cmpl %ebp, %ecx /* 3 U pipe */
movl window(%esp), %eax jbe LeaveNow /* 3 V pipe */
movw (%eax,%ecx), %ax subl $0x00010000, %ebx /* 4 U pipe */
cmpw scanstart(%esp), %ax js LeaveNow /* 4 V pipe */
jnz LookupLoop LoopEntry: movb -1(%esi,%ecx), %al /* 5 U pipe */
andl %ecx, %edx /* 5 V pipe */
/* Store the current value of chainlen. */ cmpb %bl, %al /* 6 U pipe */
jnz LookupLoop /* 6 V pipe */
movl %ebx, chainlenscanend(%esp) movb (%esi,%ecx), %ah
cmpb %bh, %ah
/* Point %edi to the string under scrutiny, and %esi to the string we */ jnz LookupLoop
/* are hoping to match it up with. In actuality, %esi and %edi are */ movl window(%esp), %eax
/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ movw (%eax,%ecx), %ax
/* initialized to -(MAX_MATCH_8 - scanalign). */ cmpw scanstart(%esp), %ax
jnz LookupLoop
movl window(%esp), %esi
movl scan(%esp), %edi /* Store the current value of chainlen. */
addl %ecx, %esi
movl scanalign(%esp), %eax movl %ebx, chainlenscanend(%esp)
movl $(-MAX_MATCH_8), %edx
lea MAX_MATCH_8(%edi,%eax), %edi /* Point %edi to the string under scrutiny, and %esi to the string we */
lea MAX_MATCH_8(%esi,%eax), %esi /* are hoping to match it up with. In actuality, %esi and %edi are */
/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */
/* Test the strings for equality, 8 bytes at a time. At the end, /* initialized to -(MAX_MATCH_8 - scanalign). */
* adjust %edx so that it is offset to the exact byte that mismatched.
* movl window(%esp), %esi
* We already know at this point that the first three bytes of the movl scan(%esp), %edi
* strings match each other, and they can be safely passed over before addl %ecx, %esi
* starting the compare loop. So what this code does is skip over 0-3 movl scanalign(%esp), %eax
* bytes, as much as necessary in order to dword-align the %edi movl $(-MAX_MATCH_8), %edx
* pointer. (%esi will still be misaligned three times out of four.) lea MAX_MATCH_8(%edi,%eax), %edi
* lea MAX_MATCH_8(%esi,%eax), %esi
* It should be confessed that this loop usually does not represent
* much of the total running time. Replacing it with a more /* Test the strings for equality, 8 bytes at a time. At the end,
* straightforward "rep cmpsb" would not drastically degrade * adjust %edx so that it is offset to the exact byte that mismatched.
* performance. *
*/ * We already know at this point that the first three bytes of the
LoopCmps: * strings match each other, and they can be safely passed over before
movl (%esi,%edx), %eax * starting the compare loop. So what this code does is skip over 0-3
movl (%edi,%edx), %ebx * bytes, as much as necessary in order to dword-align the %edi
xorl %ebx, %eax * pointer. (%esi will still be misaligned three times out of four.)
jnz LeaveLoopCmps *
movl 4(%esi,%edx), %eax * It should be confessed that this loop usually does not represent
movl 4(%edi,%edx), %ebx * much of the total running time. Replacing it with a more
xorl %ebx, %eax * straightforward "rep cmpsb" would not drastically degrade
jnz LeaveLoopCmps4 * performance.
addl $8, %edx */
jnz LoopCmps LoopCmps:
jmp LenMaximum movl (%esi,%edx), %eax
LeaveLoopCmps4: addl $4, %edx movl (%edi,%edx), %ebx
LeaveLoopCmps: testl $0x0000FFFF, %eax xorl %ebx, %eax
jnz LenLower jnz LeaveLoopCmps
addl $2, %edx movl 4(%esi,%edx), %eax
shrl $16, %eax movl 4(%edi,%edx), %ebx
LenLower: subb $1, %al xorl %ebx, %eax
adcl $0, %edx jnz LeaveLoopCmps4
addl $8, %edx
/* Calculate the length of the match. If it is longer than MAX_MATCH, */ jnz LoopCmps
/* then automatically accept it as the best possible match and leave. */ jmp LenMaximum
LeaveLoopCmps4: addl $4, %edx
lea (%edi,%edx), %eax LeaveLoopCmps: testl $0x0000FFFF, %eax
movl scan(%esp), %edi jnz LenLower
subl %edi, %eax addl $2, %edx
cmpl $MAX_MATCH, %eax shrl $16, %eax
jge LenMaximum LenLower: subb $1, %al
adcl $0, %edx
/* 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. */ /* Calculate the length of the match. If it is longer than MAX_MATCH, */
/* then automatically accept it as the best possible match and leave. */
movl deflatestate(%esp), %edx
movl bestlen(%esp), %ebx lea (%edi,%edx), %eax
cmpl %ebx, %eax movl scan(%esp), %edi
jg LongerMatch subl %edi, %eax
movl chainlenscanend(%esp), %ebx cmpl $MAX_MATCH, %eax
movl windowbestlen(%esp), %esi jge LenMaximum
movl dsPrev(%edx), %edi
movl wmask(%esp), %edx /* If the length of the match is not longer than the best match we */
andl %ecx, %edx /* have so far, then forget it and return to the lookup loop. */
jmp LookupLoop
movl deflatestate(%esp), %edx
/* s->match_start = cur_match; */ movl bestlen(%esp), %ebx
/* best_len = len; */ cmpl %ebx, %eax
/* if (len >= nice_match) break; */ jg LongerMatch
/* scan_end = *(ushf*)(scan+best_len-1); */ movl chainlenscanend(%esp), %ebx
movl windowbestlen(%esp), %esi
LongerMatch: movl nicematch(%esp), %ebx movl dsPrev(%edx), %edi
movl %eax, bestlen(%esp) movl wmask(%esp), %edx
movl %ecx, dsMatchStart(%edx) andl %ecx, %edx
cmpl %ebx, %eax jmp LookupLoop
jge LeaveNow
movl window(%esp), %esi /* s->match_start = cur_match; */
addl %eax, %esi /* best_len = len; */
movl %esi, windowbestlen(%esp) /* if (len >= nice_match) break; */
movl chainlenscanend(%esp), %ebx /* scan_end = *(ushf*)(scan+best_len-1); */
movw -1(%edi,%eax), %bx
movl dsPrev(%edx), %edi LongerMatch: movl nicematch(%esp), %ebx
movl %ebx, chainlenscanend(%esp) movl %eax, bestlen(%esp)
movl wmask(%esp), %edx movl %ecx, dsMatchStart(%edx)
andl %ecx, %edx cmpl %ebx, %eax
jmp LookupLoop jge LeaveNow
movl window(%esp), %esi
/* Accept the current string, with the maximum possible length. */ addl %eax, %esi
movl %esi, windowbestlen(%esp)
LenMaximum: movl deflatestate(%esp), %edx movl chainlenscanend(%esp), %ebx
movl $MAX_MATCH, bestlen(%esp) movw -1(%edi,%eax), %bx
movl %ecx, dsMatchStart(%edx) movl dsPrev(%edx), %edi
movl %ebx, chainlenscanend(%esp)
/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ movl wmask(%esp), %edx
/* return s->lookahead; */ andl %ecx, %edx
jmp LookupLoop
LeaveNow:
movl deflatestate(%esp), %edx /* Accept the current string, with the maximum possible length. */
movl bestlen(%esp), %ebx
movl dsLookahead(%edx), %eax LenMaximum: movl deflatestate(%esp), %edx
cmpl %eax, %ebx movl $MAX_MATCH, bestlen(%esp)
jg LookaheadRet movl %ecx, dsMatchStart(%edx)
movl %ebx, %eax
LookaheadRet: /* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
/* return s->lookahead; */
/* Restore the stack and return from whence we came. */
LeaveNow:
addl $LocalVarsSize, %esp movl deflatestate(%esp), %edx
popl %ebx movl bestlen(%esp), %ebx
popl %esi movl dsLookahead(%edx), %eax
popl %edi cmpl %eax, %ebx
popl %ebp jg LookaheadRet
match_init: ret movl %ebx, %eax
LookaheadRet:
/* Restore the stack and return from whence we came. */
addl $LocalVarsSize, %esp
popl %ebx
popl %esi
popl %edi
popl %ebp
match_init: ret

View File

@@ -1,327 +1,329 @@
/* match.s -- Pentium-Pro-optimized version of longest_match() /* match.s -- Pentium-Pro-optimized version of longest_match()
* 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>
* *
* This is free software; you can redistribute it and/or modify it * This is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License. * under the terms of the GNU General Public License.
*/ */
#ifndef NO_UNDERLINE #ifndef NO_UNDERLINE
#define match_init _match_init #define match_init _match_init
#define longest_match _longest_match #define longest_match _longest_match
#endif #endif
#define MAX_MATCH (258) #define MAX_MATCH (258)
#define MIN_MATCH (3) #define MIN_MATCH (3)
#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) #define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) #define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7)
/* stack frame offsets */ /* stack frame offsets */
#define chainlenwmask 0 /* high word: current chain len */ #define chainlenwmask 0 /* high word: current chain len */
/* low word: s->wmask */ /* low word: s->wmask */
#define window 4 /* local copy of s->window */ #define window 4 /* local copy of s->window */
#define windowbestlen 8 /* s->window + bestlen */ #define windowbestlen 8 /* s->window + bestlen */
#define scanstart 16 /* first two bytes of string */ #define scanstart 16 /* first two bytes of string */
#define scanend 12 /* last two bytes of string */ #define scanend 12 /* last two bytes of string */
#define scanalign 20 /* dword-misalignment of string */ #define scanalign 20 /* dword-misalignment of string */
#define nicematch 24 /* a good enough match size */ #define nicematch 24 /* a good enough match size */
#define bestlen 28 /* size of best match so far */ #define bestlen 28 /* size of best match so far */
#define scan 32 /* ptr to string wanting match */ #define scan 32 /* ptr to string wanting match */
#define LocalVarsSize (36) #define LocalVarsSize (36)
/* saved ebx 36 */ /* saved ebx 36 */
/* saved edi 40 */ /* saved edi 40 */
/* saved esi 44 */ /* saved esi 44 */
/* saved ebp 48 */ /* saved ebp 48 */
/* return address 52 */ /* return address 52 */
#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 zlib1222add (8)
#define dsWMask 44
#define dsWindow 48 #define dsWSize (36+zlib1222add)
#define dsPrev 56 #define dsWMask (44+zlib1222add)
#define dsMatchLen 88 #define dsWindow (48+zlib1222add)
#define dsPrevMatch 92 #define dsPrev (56+zlib1222add)
#define dsStrStart 100 #define dsMatchLen (88+zlib1222add)
#define dsMatchStart 104 #define dsPrevMatch (92+zlib1222add)
#define dsLookahead 108 #define dsStrStart (100+zlib1222add)
#define dsPrevLen 112 #define dsMatchStart (104+zlib1222add)
#define dsMaxChainLen 116 #define dsLookahead (108+zlib1222add)
#define dsGoodMatch 132 #define dsPrevLen (112+zlib1222add)
#define dsNiceMatch 136 #define dsMaxChainLen (116+zlib1222add)
#define dsGoodMatch (132+zlib1222add)
#define dsNiceMatch (136+zlib1222add)
.file "match.S"
.globl match_init, longest_match .file "match.S"
.text .globl match_init, longest_match
/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ .text
longest_match: /* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
/* Save registers that the compiler may be using, and adjust %esp to */ longest_match:
/* make room for our stack frame. */
/* Save registers that the compiler may be using, and adjust %esp to */
pushl %ebp /* make room for our stack frame. */
pushl %edi
pushl %esi pushl %ebp
pushl %ebx pushl %edi
subl $LocalVarsSize, %esp pushl %esi
pushl %ebx
/* Retrieve the function arguments. %ecx will hold cur_match */ subl $LocalVarsSize, %esp
/* throughout the entire function. %edx will hold the pointer to the */
/* deflate_state structure during the function's setup (before */ /* Retrieve the function arguments. %ecx will hold cur_match */
/* entering the main loop). */ /* throughout the entire function. %edx will hold the pointer to the */
/* deflate_state structure during the function's setup (before */
movl deflatestate(%esp), %edx /* entering the main loop). */
movl curmatch(%esp), %ecx
movl deflatestate(%esp), %edx
/* uInt wmask = s->w_mask; */ movl curmatch(%esp), %ecx
/* unsigned chain_length = s->max_chain_length; */
/* if (s->prev_length >= s->good_match) { */ /* uInt wmask = s->w_mask; */
/* chain_length >>= 2; */ /* unsigned chain_length = s->max_chain_length; */
/* } */ /* if (s->prev_length >= s->good_match) { */
/* chain_length >>= 2; */
movl dsPrevLen(%edx), %eax /* } */
movl dsGoodMatch(%edx), %ebx
cmpl %ebx, %eax movl dsPrevLen(%edx), %eax
movl dsWMask(%edx), %eax movl dsGoodMatch(%edx), %ebx
movl dsMaxChainLen(%edx), %ebx cmpl %ebx, %eax
jl LastMatchGood movl dsWMask(%edx), %eax
shrl $2, %ebx movl dsMaxChainLen(%edx), %ebx
LastMatchGood: jl LastMatchGood
shrl $2, %ebx
/* chainlen is decremented once beforehand so that the function can */ LastMatchGood:
/* 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 */ /* chainlen is decremented once beforehand so that the function can */
/* value, which it will always accompany. */ /* 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 */
decl %ebx /* value, which it will always accompany. */
shll $16, %ebx
orl %eax, %ebx decl %ebx
movl %ebx, chainlenwmask(%esp) shll $16, %ebx
orl %eax, %ebx
/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ movl %ebx, chainlenwmask(%esp)
movl dsNiceMatch(%edx), %eax /* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */
movl dsLookahead(%edx), %ebx
cmpl %eax, %ebx movl dsNiceMatch(%edx), %eax
jl LookaheadLess movl dsLookahead(%edx), %ebx
movl %eax, %ebx cmpl %eax, %ebx
LookaheadLess: movl %ebx, nicematch(%esp) jl LookaheadLess
movl %eax, %ebx
/* register Bytef *scan = s->window + s->strstart; */ LookaheadLess: movl %ebx, nicematch(%esp)
movl dsWindow(%edx), %esi /* register Bytef *scan = s->window + s->strstart; */
movl %esi, window(%esp)
movl dsStrStart(%edx), %ebp movl dsWindow(%edx), %esi
lea (%esi,%ebp), %edi movl %esi, window(%esp)
movl %edi, scan(%esp) movl dsStrStart(%edx), %ebp
lea (%esi,%ebp), %edi
/* Determine how many bytes the scan ptr is off from being */ movl %edi, scan(%esp)
/* dword-aligned. */
/* Determine how many bytes the scan ptr is off from being */
movl %edi, %eax /* dword-aligned. */
negl %eax
andl $3, %eax movl %edi, %eax
movl %eax, scanalign(%esp) negl %eax
andl $3, %eax
/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ movl %eax, scanalign(%esp)
/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
movl dsWSize(%edx), %eax /* s->strstart - (IPos)MAX_DIST(s) : NIL; */
subl $MIN_LOOKAHEAD, %eax
subl %eax, %ebp movl dsWSize(%edx), %eax
jg LimitPositive subl $MIN_LOOKAHEAD, %eax
xorl %ebp, %ebp subl %eax, %ebp
LimitPositive: jg LimitPositive
xorl %ebp, %ebp
/* int best_len = s->prev_length; */ LimitPositive:
movl dsPrevLen(%edx), %eax /* int best_len = s->prev_length; */
movl %eax, bestlen(%esp)
movl dsPrevLen(%edx), %eax
/* Store the sum of s->window + best_len in %esi locally, and in %esi. */ movl %eax, bestlen(%esp)
addl %eax, %esi /* Store the sum of s->window + best_len in %esi locally, and in %esi. */
movl %esi, windowbestlen(%esp)
addl %eax, %esi
/* register ush scan_start = *(ushf*)scan; */ movl %esi, windowbestlen(%esp)
/* register ush scan_end = *(ushf*)(scan+best_len-1); */
/* Posf *prev = s->prev; */ /* register ush scan_start = *(ushf*)scan; */
/* register ush scan_end = *(ushf*)(scan+best_len-1); */
movzwl (%edi), %ebx /* Posf *prev = s->prev; */
movl %ebx, scanstart(%esp)
movzwl -1(%edi,%eax), %ebx movzwl (%edi), %ebx
movl %ebx, scanend(%esp) movl %ebx, scanstart(%esp)
movl dsPrev(%edx), %edi movzwl -1(%edi,%eax), %ebx
movl %ebx, scanend(%esp)
/* Jump into the main loop. */ movl dsPrev(%edx), %edi
movl chainlenwmask(%esp), %edx /* Jump into the main loop. */
jmp LoopEntry
movl chainlenwmask(%esp), %edx
.balign 16 jmp LoopEntry
/* do { .balign 16
* match = s->window + cur_match;
* if (*(ushf*)(match+best_len-1) != scan_end || /* do {
* *(ushf*)match != scan_start) continue; * match = s->window + cur_match;
* [...] * if (*(ushf*)(match+best_len-1) != scan_end ||
* } while ((cur_match = prev[cur_match & wmask]) > limit * *(ushf*)match != scan_start) continue;
* && --chain_length != 0); * [...]
* * } while ((cur_match = prev[cur_match & wmask]) > limit
* Here is the inner loop of the function. The function will spend the * && --chain_length != 0);
* majority of its time in this loop, and majority of that time will *
* be spent in the first ten instructions. * 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
* Within this loop: * be spent in the first ten instructions.
* %ebx = scanend *
* %ecx = curmatch * Within this loop:
* %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) * %ebx = scanend
* %esi = windowbestlen - i.e., (window + bestlen) * %ecx = curmatch
* %edi = prev * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
* %ebp = limit * %esi = windowbestlen - i.e., (window + bestlen)
*/ * %edi = prev
LookupLoop: * %ebp = limit
andl %edx, %ecx */
movzwl (%edi,%ecx,2), %ecx LookupLoop:
cmpl %ebp, %ecx andl %edx, %ecx
jbe LeaveNow movzwl (%edi,%ecx,2), %ecx
subl $0x00010000, %edx cmpl %ebp, %ecx
js LeaveNow jbe LeaveNow
LoopEntry: movzwl -1(%esi,%ecx), %eax subl $0x00010000, %edx
cmpl %ebx, %eax js LeaveNow
jnz LookupLoop LoopEntry: movzwl -1(%esi,%ecx), %eax
movl window(%esp), %eax cmpl %ebx, %eax
movzwl (%eax,%ecx), %eax jnz LookupLoop
cmpl scanstart(%esp), %eax movl window(%esp), %eax
jnz LookupLoop movzwl (%eax,%ecx), %eax
cmpl scanstart(%esp), %eax
/* Store the current value of chainlen. */ jnz LookupLoop
movl %edx, chainlenwmask(%esp) /* Store the current value of chainlen. */
/* Point %edi to the string under scrutiny, and %esi to the string we */ movl %edx, chainlenwmask(%esp)
/* are hoping to match it up with. In actuality, %esi and %edi are */
/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ /* Point %edi to the string under scrutiny, and %esi to the string we */
/* initialized to -(MAX_MATCH_8 - scanalign). */ /* are hoping to match it up with. In actuality, %esi and %edi are */
/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */
movl window(%esp), %esi /* initialized to -(MAX_MATCH_8 - scanalign). */
movl scan(%esp), %edi
addl %ecx, %esi movl window(%esp), %esi
movl scanalign(%esp), %eax movl scan(%esp), %edi
movl $(-MAX_MATCH_8), %edx addl %ecx, %esi
lea MAX_MATCH_8(%edi,%eax), %edi movl scanalign(%esp), %eax
lea MAX_MATCH_8(%esi,%eax), %esi movl $(-MAX_MATCH_8), %edx
lea MAX_MATCH_8(%edi,%eax), %edi
/* Test the strings for equality, 8 bytes at a time. At the end, lea MAX_MATCH_8(%esi,%eax), %esi
* adjust %edx so that it is offset to the exact byte that mismatched.
* /* Test the strings for equality, 8 bytes at a time. At the end,
* We already know at this point that the first three bytes of the * adjust %edx so that it is offset to the exact byte that mismatched.
* 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 * We already know at this point that the first three bytes of the
* bytes, as much as necessary in order to dword-align the %edi * strings match each other, and they can be safely passed over before
* pointer. (%esi will still be misaligned three times out of four.) * 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
* It should be confessed that this loop usually does not represent * pointer. (%esi will still be misaligned three times out of four.)
* much of the total running time. Replacing it with a more *
* straightforward "rep cmpsb" would not drastically degrade * It should be confessed that this loop usually does not represent
* performance. * much of the total running time. Replacing it with a more
*/ * straightforward "rep cmpsb" would not drastically degrade
LoopCmps: * performance.
movl (%esi,%edx), %eax */
xorl (%edi,%edx), %eax LoopCmps:
jnz LeaveLoopCmps movl (%esi,%edx), %eax
movl 4(%esi,%edx), %eax xorl (%edi,%edx), %eax
xorl 4(%edi,%edx), %eax jnz LeaveLoopCmps
jnz LeaveLoopCmps4 movl 4(%esi,%edx), %eax
addl $8, %edx xorl 4(%edi,%edx), %eax
jnz LoopCmps jnz LeaveLoopCmps4
jmp LenMaximum addl $8, %edx
LeaveLoopCmps4: addl $4, %edx jnz LoopCmps
LeaveLoopCmps: testl $0x0000FFFF, %eax jmp LenMaximum
jnz LenLower LeaveLoopCmps4: addl $4, %edx
addl $2, %edx LeaveLoopCmps: testl $0x0000FFFF, %eax
shrl $16, %eax jnz LenLower
LenLower: subb $1, %al addl $2, %edx
adcl $0, %edx shrl $16, %eax
LenLower: subb $1, %al
/* Calculate the length of the match. If it is longer than MAX_MATCH, */ adcl $0, %edx
/* then automatically accept it as the best possible match and leave. */
/* Calculate the length of the match. If it is longer than MAX_MATCH, */
lea (%edi,%edx), %eax /* then automatically accept it as the best possible match and leave. */
movl scan(%esp), %edi
subl %edi, %eax lea (%edi,%edx), %eax
cmpl $MAX_MATCH, %eax movl scan(%esp), %edi
jge LenMaximum subl %edi, %eax
cmpl $MAX_MATCH, %eax
/* If the length of the match is not longer than the best match we */ jge LenMaximum
/* have so far, then forget it and return to the lookup loop. */
/* If the length of the match is not longer than the best match we */
movl deflatestate(%esp), %edx /* have so far, then forget it and return to the lookup loop. */
movl bestlen(%esp), %ebx
cmpl %ebx, %eax movl deflatestate(%esp), %edx
jg LongerMatch movl bestlen(%esp), %ebx
movl windowbestlen(%esp), %esi cmpl %ebx, %eax
movl dsPrev(%edx), %edi jg LongerMatch
movl scanend(%esp), %ebx movl windowbestlen(%esp), %esi
movl chainlenwmask(%esp), %edx movl dsPrev(%edx), %edi
jmp LookupLoop movl scanend(%esp), %ebx
movl chainlenwmask(%esp), %edx
/* s->match_start = cur_match; */ jmp LookupLoop
/* best_len = len; */
/* if (len >= nice_match) break; */ /* s->match_start = cur_match; */
/* scan_end = *(ushf*)(scan+best_len-1); */ /* best_len = len; */
/* if (len >= nice_match) break; */
LongerMatch: movl nicematch(%esp), %ebx /* scan_end = *(ushf*)(scan+best_len-1); */
movl %eax, bestlen(%esp)
movl %ecx, dsMatchStart(%edx) LongerMatch: movl nicematch(%esp), %ebx
cmpl %ebx, %eax movl %eax, bestlen(%esp)
jge LeaveNow movl %ecx, dsMatchStart(%edx)
movl window(%esp), %esi cmpl %ebx, %eax
addl %eax, %esi jge LeaveNow
movl %esi, windowbestlen(%esp) movl window(%esp), %esi
movzwl -1(%edi,%eax), %ebx addl %eax, %esi
movl dsPrev(%edx), %edi movl %esi, windowbestlen(%esp)
movl %ebx, scanend(%esp) movzwl -1(%edi,%eax), %ebx
movl chainlenwmask(%esp), %edx movl dsPrev(%edx), %edi
jmp LookupLoop movl %ebx, scanend(%esp)
movl chainlenwmask(%esp), %edx
/* Accept the current string, with the maximum possible length. */ jmp LookupLoop
LenMaximum: movl deflatestate(%esp), %edx /* Accept the current string, with the maximum possible length. */
movl $MAX_MATCH, bestlen(%esp)
movl %ecx, dsMatchStart(%edx) LenMaximum: movl deflatestate(%esp), %edx
movl $MAX_MATCH, bestlen(%esp)
/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ movl %ecx, dsMatchStart(%edx)
/* return s->lookahead; */
/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
LeaveNow: /* return s->lookahead; */
movl deflatestate(%esp), %edx
movl bestlen(%esp), %ebx LeaveNow:
movl dsLookahead(%edx), %eax movl deflatestate(%esp), %edx
cmpl %eax, %ebx movl bestlen(%esp), %ebx
jg LookaheadRet movl dsLookahead(%edx), %eax
movl %ebx, %eax cmpl %eax, %ebx
LookaheadRet: jg LookaheadRet
movl %ebx, %eax
/* Restore the stack and return from whence we came. */ LookaheadRet:
addl $LocalVarsSize, %esp /* Restore the stack and return from whence we came. */
popl %ebx
popl %esi addl $LocalVarsSize, %esp
popl %edi popl %ebx
popl %ebp popl %esi
match_init: ret popl %edi
popl %ebp
match_init: ret

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.2 Copyright 1995-2004 Mark Adler "; " inflate9 1.2.2.3 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, 72, 199}; 133, 133, 133, 133, 144, 66, 71};
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,

View File

@@ -1,408 +1,413 @@
; match.asm -- Pentium-Pro optimized version of longest_match() ; match.asm -- Pentium-Pro optimized version of longest_match()
; ;
; Updated for zlib 1.1.3 and converted to MASM 6.1x ; Updated for zlib 1.1.3 and converted to MASM 6.1x
; Copyright (C) 2000 Dan Higdon <hdan@kinesoft.com> ; Copyright (C) 2000 Dan Higdon <hdan@kinesoft.com>
; and Chuck Walbourn <chuckw@kinesoft.com> ; and Chuck Walbourn <chuckw@kinesoft.com>
; Corrections by Cosmin Truta <cosmint@cs.ubbcluj.ro> ; Corrections by Cosmin Truta <cosmint@cs.ubbcluj.ro>
; ;
; This is free software; you can redistribute it and/or modify it ; This is free software; you can redistribute it and/or modify it
; under the terms of the GNU General Public License. ; under the terms of the GNU General Public License.
; 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>
;
.686P ; Modified by Gilles Vollant (2005) for add gzhead and gzindex
.MODEL FLAT
.686P
;=========================================================================== .MODEL FLAT
; EQUATES
;=========================================================================== ;===========================================================================
; EQUATES
MAX_MATCH EQU 258 ;===========================================================================
MIN_MATCH EQU 3
MIN_LOOKAHEAD EQU (MAX_MATCH + MIN_MATCH + 1) MAX_MATCH EQU 258
MAX_MATCH_8 EQU ((MAX_MATCH + 7) AND (NOT 7)) MIN_MATCH EQU 3
MIN_LOOKAHEAD EQU (MAX_MATCH + MIN_MATCH + 1)
;=========================================================================== MAX_MATCH_8 EQU ((MAX_MATCH + 7) AND (NOT 7))
; STRUCTURES
;=========================================================================== ;===========================================================================
; STRUCTURES
; This STRUCT assumes a 4-byte alignment ;===========================================================================
DEFLATE_STATE STRUCT ; This STRUCT assumes a 4-byte alignment
ds_strm dd ?
ds_status dd ? DEFLATE_STATE STRUCT
ds_pending_buf dd ? ds_strm dd ?
ds_pending_buf_size dd ? ds_status dd ?
ds_pending_out dd ? ds_pending_buf dd ?
ds_pending dd ? ds_pending_buf_size dd ?
ds_wrap dd ? ds_pending_out dd ?
ds_data_type db ? ds_pending dd ?
ds_method db ? ds_wrap dd ?
db ? ; padding ; gzhead and gzindex are added in zlib 1.2.2.2 (see deflate.h)
db ? ; padding ds_gzhead dd ?
ds_last_flush dd ? ds_gzindex dd ?
ds_w_size dd ? ; used ds_data_type db ?
ds_w_bits dd ? ds_method db ?
ds_w_mask dd ? ; used db ? ; padding
ds_window dd ? ; used db ? ; padding
ds_window_size dd ? ds_last_flush dd ?
ds_prev dd ? ; used ds_w_size dd ? ; used
ds_head dd ? ds_w_bits dd ?
ds_ins_h dd ? ds_w_mask dd ? ; used
ds_hash_size dd ? ds_window dd ? ; used
ds_hash_bits dd ? ds_window_size dd ?
ds_hash_mask dd ? ds_prev dd ? ; used
ds_hash_shift dd ? ds_head dd ?
ds_block_start dd ? ds_ins_h dd ?
ds_match_length dd ? ; used ds_hash_size dd ?
ds_prev_match dd ? ; used ds_hash_bits dd ?
ds_match_available dd ? ds_hash_mask dd ?
ds_strstart dd ? ; used ds_hash_shift dd ?
ds_match_start dd ? ; used ds_block_start dd ?
ds_lookahead dd ? ; used ds_match_length dd ? ; used
ds_prev_length dd ? ; used ds_prev_match dd ? ; used
ds_max_chain_length dd ? ; used ds_match_available dd ?
ds_max_laxy_match dd ? ds_strstart dd ? ; used
ds_level dd ? ds_match_start dd ? ; used
ds_strategy dd ? ds_lookahead dd ? ; used
ds_good_match dd ? ; used ds_prev_length dd ? ; used
ds_nice_match dd ? ; used ds_max_chain_length dd ? ; used
ds_max_laxy_match dd ?
; Don't need anymore of the struct for match ds_level dd ?
DEFLATE_STATE ENDS ds_strategy dd ?
ds_good_match dd ? ; used
;=========================================================================== ds_nice_match dd ? ; used
; CODE
;=========================================================================== ; Don't need anymore of the struct for match
_TEXT SEGMENT DEFLATE_STATE ENDS
;--------------------------------------------------------------------------- ;===========================================================================
; match_init ; CODE
;--------------------------------------------------------------------------- ;===========================================================================
ALIGN 4 _TEXT SEGMENT
PUBLIC _match_init
_match_init PROC ;---------------------------------------------------------------------------
; no initialization needed ; match_init
ret ;---------------------------------------------------------------------------
_match_init ENDP ALIGN 4
PUBLIC _match_init
;--------------------------------------------------------------------------- _match_init PROC
; uInt longest_match(deflate_state *deflatestate, IPos curmatch) ; no initialization needed
;--------------------------------------------------------------------------- ret
ALIGN 4 _match_init ENDP
PUBLIC _longest_match ;---------------------------------------------------------------------------
_longest_match PROC ; uInt longest_match(deflate_state *deflatestate, IPos curmatch)
;---------------------------------------------------------------------------
; Since this code uses EBP for a scratch register, the stack frame must ALIGN 4
; be manually constructed and referenced relative to the ESP register.
PUBLIC _longest_match
; Stack image _longest_match PROC
; Variables
chainlenwmask = 0 ; high word: current chain len ; Since this code uses EBP for a scratch register, the stack frame must
; low word: s->wmask ; be manually constructed and referenced relative to the ESP register.
window = 4 ; local copy of s->window
windowbestlen = 8 ; s->window + bestlen ; Stack image
scanend = 12 ; last two bytes of string ; Variables
scanstart = 16 ; first two bytes of string chainlenwmask = 0 ; high word: current chain len
scanalign = 20 ; dword-misalignment of string ; low word: s->wmask
nicematch = 24 ; a good enough match size window = 4 ; local copy of s->window
bestlen = 28 ; size of best match so far windowbestlen = 8 ; s->window + bestlen
scan = 32 ; ptr to string wanting match scanend = 12 ; last two bytes of string
varsize = 36 ; number of bytes (also offset to last saved register) scanstart = 16 ; first two bytes of string
scanalign = 20 ; dword-misalignment of string
; Saved Registers (actually pushed into place) nicematch = 24 ; a good enough match size
ebx_save = 36 bestlen = 28 ; size of best match so far
edi_save = 40 scan = 32 ; ptr to string wanting match
esi_save = 44 varsize = 36 ; number of bytes (also offset to last saved register)
ebp_save = 48
; Saved Registers (actually pushed into place)
; Parameters ebx_save = 36
retaddr = 52 edi_save = 40
deflatestate = 56 esi_save = 44
curmatch = 60 ebp_save = 48
; Save registers that the compiler may be using ; Parameters
push ebp retaddr = 52
push edi deflatestate = 56
push esi curmatch = 60
push ebx
; Save registers that the compiler may be using
; Allocate local variable space push ebp
sub esp,varsize push edi
push esi
; Retrieve the function arguments. ecx will hold cur_match push ebx
; throughout the entire function. edx will hold the pointer to the
; deflate_state structure during the function's setup (before ; Allocate local variable space
; entering the main loop). sub esp,varsize
mov edx, [esp+deflatestate] ; Retrieve the function arguments. ecx will hold cur_match
ASSUME edx:PTR DEFLATE_STATE ; throughout the entire function. edx will hold the pointer to the
; deflate_state structure during the function's setup (before
mov ecx, [esp+curmatch] ; entering the main loop).
; uInt wmask = s->w_mask; mov edx, [esp+deflatestate]
; unsigned chain_length = s->max_chain_length; ASSUME edx:PTR DEFLATE_STATE
; if (s->prev_length >= s->good_match) {
; chain_length >>= 2; mov ecx, [esp+curmatch]
; }
; uInt wmask = s->w_mask;
mov eax, [edx].ds_prev_length ; unsigned chain_length = s->max_chain_length;
mov ebx, [edx].ds_good_match ; if (s->prev_length >= s->good_match) {
cmp eax, ebx ; chain_length >>= 2;
mov eax, [edx].ds_w_mask ; }
mov ebx, [edx].ds_max_chain_length
jl SHORT LastMatchGood mov eax, [edx].ds_prev_length
shr ebx, 2 mov ebx, [edx].ds_good_match
LastMatchGood: cmp eax, ebx
mov eax, [edx].ds_w_mask
; chainlen is decremented once beforehand so that the function can mov ebx, [edx].ds_max_chain_length
; use the sign flag instead of the zero flag for the exit test. jl SHORT LastMatchGood
; It is then shifted into the high word, to make room for the wmask shr ebx, 2
; value, which it will always accompany. LastMatchGood:
dec ebx ; chainlen is decremented once beforehand so that the function can
shl ebx, 16 ; use the sign flag instead of the zero flag for the exit test.
or ebx, eax ; It is then shifted into the high word, to make room for the wmask
mov [esp+chainlenwmask], ebx ; value, which it will always accompany.
; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; dec ebx
shl ebx, 16
mov eax, [edx].ds_nice_match or ebx, eax
mov ebx, [edx].ds_lookahead mov [esp+chainlenwmask], ebx
cmp ebx, eax
jl SHORT LookaheadLess ; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
mov ebx, eax
LookaheadLess: mov eax, [edx].ds_nice_match
mov [esp+nicematch], ebx mov ebx, [edx].ds_lookahead
cmp ebx, eax
;/* register Bytef *scan = s->window + s->strstart; */ jl SHORT LookaheadLess
mov ebx, eax
mov esi, [edx].ds_window LookaheadLess:
mov [esp+window], esi mov [esp+nicematch], ebx
mov ebp, [edx].ds_strstart
lea edi, [esi+ebp] ;/* register Bytef *scan = s->window + s->strstart; */
mov [esp+scan],edi
mov esi, [edx].ds_window
;/* Determine how many bytes the scan ptr is off from being */ mov [esp+window], esi
;/* dword-aligned. */ mov ebp, [edx].ds_strstart
lea edi, [esi+ebp]
mov eax, edi mov [esp+scan],edi
neg eax
and eax, 3 ;/* Determine how many bytes the scan ptr is off from being */
mov [esp+scanalign], eax ;/* dword-aligned. */
;/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ mov eax, edi
;/* s->strstart - (IPos)MAX_DIST(s) : NIL; */ neg eax
and eax, 3
mov eax, [edx].ds_w_size mov [esp+scanalign], eax
sub eax, MIN_LOOKAHEAD
sub ebp, eax ;/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
jg SHORT LimitPositive ;/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
xor ebp, ebp
LimitPositive: mov eax, [edx].ds_w_size
sub eax, MIN_LOOKAHEAD
;/* int best_len = s->prev_length; */ sub ebp, eax
jg SHORT LimitPositive
mov eax, [edx].ds_prev_length xor ebp, ebp
mov [esp+bestlen], eax LimitPositive:
;/* Store the sum of s->window + best_len in %esi locally, and in %esi. */ ;/* int best_len = s->prev_length; */
add esi, eax mov eax, [edx].ds_prev_length
mov [esp+windowbestlen], esi mov [esp+bestlen], eax
;/* register ush scan_start = *(ushf*)scan; */ ;/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
;/* register ush scan_end = *(ushf*)(scan+best_len-1); */
;/* Posf *prev = s->prev; */ add esi, eax
mov [esp+windowbestlen], esi
movzx ebx, WORD PTR[edi]
mov [esp+scanstart], ebx ;/* register ush scan_start = *(ushf*)scan; */
movzx ebx, WORD PTR[eax+edi-1] ;/* register ush scan_end = *(ushf*)(scan+best_len-1); */
mov [esp+scanend], ebx ;/* Posf *prev = s->prev; */
mov edi, [edx].ds_prev
movzx ebx, WORD PTR[edi]
;/* Jump into the main loop. */ mov [esp+scanstart], ebx
movzx ebx, WORD PTR[eax+edi-1]
mov edx, [esp+chainlenwmask] mov [esp+scanend], ebx
jmp SHORT LoopEntry mov edi, [edx].ds_prev
;/* do { ;/* Jump into the main loop. */
; * match = s->window + cur_match;
; * if (*(ushf*)(match+best_len-1) != scan_end || mov edx, [esp+chainlenwmask]
; * *(ushf*)match != scan_start) continue; jmp SHORT LoopEntry
; * [...]
; * } while ((cur_match = prev[cur_match & wmask]) > limit ;/* do {
; * && --chain_length != 0); ; * match = s->window + cur_match;
; * ; * if (*(ushf*)(match+best_len-1) != scan_end ||
; * Here is the inner loop of the function. The function will spend the ; * *(ushf*)match != scan_start) continue;
; * majority of its time in this loop, and majority of that time will ; * [...]
; * be spent in the first ten instructions. ; * } while ((cur_match = prev[cur_match & wmask]) > limit
; * ; * && --chain_length != 0);
; * Within this loop: ; *
; * %ebx = scanend ; * Here is the inner loop of the function. The function will spend the
; * %ecx = curmatch ; * majority of its time in this loop, and majority of that time will
; * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) ; * be spent in the first ten instructions.
; * %esi = windowbestlen - i.e., (window + bestlen) ; *
; * %edi = prev ; * Within this loop:
; * %ebp = limit ; * %ebx = scanend
; */ ; * %ecx = curmatch
; * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
ALIGN 4 ; * %esi = windowbestlen - i.e., (window + bestlen)
LookupLoop: ; * %edi = prev
and ecx, edx ; * %ebp = limit
movzx ecx, WORD PTR[edi+ecx*2] ; */
cmp ecx, ebp
jbe LeaveNow ALIGN 4
sub edx, 000010000H LookupLoop:
js LeaveNow and ecx, edx
movzx ecx, WORD PTR[edi+ecx*2]
LoopEntry: cmp ecx, ebp
movzx eax, WORD PTR[esi+ecx-1] jbe LeaveNow
cmp eax, ebx sub edx, 000010000H
jnz SHORT LookupLoop js LeaveNow
mov eax, [esp+window] LoopEntry:
movzx eax, WORD PTR[eax+ecx] movzx eax, WORD PTR[esi+ecx-1]
cmp eax, [esp+scanstart] cmp eax, ebx
jnz SHORT LookupLoop jnz SHORT LookupLoop
;/* Store the current value of chainlen. */ mov eax, [esp+window]
movzx eax, WORD PTR[eax+ecx]
mov [esp+chainlenwmask], edx cmp eax, [esp+scanstart]
jnz SHORT LookupLoop
;/* 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 */ ;/* Store the current value of chainlen. */
;/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */
;/* initialized to -(MAX_MATCH_8 - scanalign). */ mov [esp+chainlenwmask], edx
mov esi, [esp+window] ;/* Point %edi to the string under scrutiny, and %esi to the string we */
mov edi, [esp+scan] ;/* are hoping to match it up with. In actuality, %esi and %edi are */
add esi, ecx ;/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */
mov eax, [esp+scanalign] ;/* initialized to -(MAX_MATCH_8 - scanalign). */
mov edx, -MAX_MATCH_8
lea edi, [edi+eax+MAX_MATCH_8] mov esi, [esp+window]
lea esi, [esi+eax+MAX_MATCH_8] mov edi, [esp+scan]
add esi, ecx
;/* Test the strings for equality, 8 bytes at a time. At the end, mov eax, [esp+scanalign]
; * adjust %edx so that it is offset to the exact byte that mismatched. mov edx, -MAX_MATCH_8
; * lea edi, [edi+eax+MAX_MATCH_8]
; * We already know at this point that the first three bytes of the lea esi, [esi+eax+MAX_MATCH_8]
; * 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 ;/* Test the strings for equality, 8 bytes at a time. At the end,
; * bytes, as much as necessary in order to dword-align the %edi ; * adjust %edx so that it is offset to the exact byte that mismatched.
; * pointer. (%esi will still be misaligned three times out of four.) ; *
; * ; * We already know at this point that the first three bytes of the
; * It should be confessed that this loop usually does not represent ; * strings match each other, and they can be safely passed over before
; * much of the total running time. Replacing it with a more ; * starting the compare loop. So what this code does is skip over 0-3
; * straightforward "rep cmpsb" would not drastically degrade ; * bytes, as much as necessary in order to dword-align the %edi
; * performance. ; * pointer. (%esi will still be misaligned three times out of four.)
; */ ; *
; * It should be confessed that this loop usually does not represent
LoopCmps: ; * much of the total running time. Replacing it with a more
mov eax, DWORD PTR[esi+edx] ; * straightforward "rep cmpsb" would not drastically degrade
xor eax, DWORD PTR[edi+edx] ; * performance.
jnz SHORT LeaveLoopCmps ; */
mov eax, DWORD PTR[esi+edx+4] LoopCmps:
xor eax, DWORD PTR[edi+edx+4] mov eax, DWORD PTR[esi+edx]
jnz SHORT LeaveLoopCmps4 xor eax, DWORD PTR[edi+edx]
jnz SHORT LeaveLoopCmps
add edx, 8
jnz SHORT LoopCmps mov eax, DWORD PTR[esi+edx+4]
jmp LenMaximum xor eax, DWORD PTR[edi+edx+4]
ALIGN 4 jnz SHORT LeaveLoopCmps4
LeaveLoopCmps4: add edx, 8
add edx, 4 jnz SHORT LoopCmps
jmp LenMaximum
LeaveLoopCmps: ALIGN 4
test eax, 00000FFFFH
jnz SHORT LenLower LeaveLoopCmps4:
add edx, 4
add edx, 2
shr eax, 16 LeaveLoopCmps:
test eax, 00000FFFFH
LenLower: jnz SHORT LenLower
sub al, 1
adc edx, 0 add edx, 2
shr eax, 16
;/* Calculate the length of the match. If it is longer than MAX_MATCH, */
;/* then automatically accept it as the best possible match and leave. */ LenLower:
sub al, 1
lea eax, [edi+edx] adc edx, 0
mov edi, [esp+scan]
sub eax, edi ;/* Calculate the length of the match. If it is longer than MAX_MATCH, */
cmp eax, MAX_MATCH ;/* then automatically accept it as the best possible match and leave. */
jge SHORT LenMaximum
lea eax, [edi+edx]
;/* If the length of the match is not longer than the best match we */ mov edi, [esp+scan]
;/* have so far, then forget it and return to the lookup loop. */ sub eax, edi
cmp eax, MAX_MATCH
mov edx, [esp+deflatestate] jge SHORT LenMaximum
mov ebx, [esp+bestlen]
cmp eax, ebx ;/* If the length of the match is not longer than the best match we */
jg SHORT LongerMatch ;/* have so far, then forget it and return to the lookup loop. */
mov esi, [esp+windowbestlen]
mov edi, [edx].ds_prev mov edx, [esp+deflatestate]
mov ebx, [esp+scanend] mov ebx, [esp+bestlen]
mov edx, [esp+chainlenwmask] cmp eax, ebx
jmp LookupLoop jg SHORT LongerMatch
ALIGN 4 mov esi, [esp+windowbestlen]
mov edi, [edx].ds_prev
;/* s->match_start = cur_match; */ mov ebx, [esp+scanend]
;/* best_len = len; */ mov edx, [esp+chainlenwmask]
;/* if (len >= nice_match) break; */ jmp LookupLoop
;/* scan_end = *(ushf*)(scan+best_len-1); */ ALIGN 4
LongerMatch: ;/* s->match_start = cur_match; */
mov ebx, [esp+nicematch] ;/* best_len = len; */
mov [esp+bestlen], eax ;/* if (len >= nice_match) break; */
mov [edx].ds_match_start, ecx ;/* scan_end = *(ushf*)(scan+best_len-1); */
cmp eax, ebx
jge SHORT LeaveNow LongerMatch:
mov esi, [esp+window] mov ebx, [esp+nicematch]
add esi, eax mov [esp+bestlen], eax
mov [esp+windowbestlen], esi mov [edx].ds_match_start, ecx
movzx ebx, WORD PTR[edi+eax-1] cmp eax, ebx
mov edi, [edx].ds_prev jge SHORT LeaveNow
mov [esp+scanend], ebx mov esi, [esp+window]
mov edx, [esp+chainlenwmask] add esi, eax
jmp LookupLoop mov [esp+windowbestlen], esi
ALIGN 4 movzx ebx, WORD PTR[edi+eax-1]
mov edi, [edx].ds_prev
;/* Accept the current string, with the maximum possible length. */ mov [esp+scanend], ebx
mov edx, [esp+chainlenwmask]
LenMaximum: jmp LookupLoop
mov edx, [esp+deflatestate] ALIGN 4
mov DWORD PTR[esp+bestlen], MAX_MATCH
mov [edx].ds_match_start, ecx ;/* Accept the current string, with the maximum possible length. */
;/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ LenMaximum:
;/* return s->lookahead; */ mov edx, [esp+deflatestate]
mov DWORD PTR[esp+bestlen], MAX_MATCH
LeaveNow: mov [edx].ds_match_start, ecx
mov edx, [esp+deflatestate]
mov ebx, [esp+bestlen] ;/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
mov eax, [edx].ds_lookahead ;/* return s->lookahead; */
cmp ebx, eax
jg SHORT LookaheadRet LeaveNow:
mov eax, ebx mov edx, [esp+deflatestate]
LookaheadRet: mov ebx, [esp+bestlen]
mov eax, [edx].ds_lookahead
; Restore the stack and return from whence we came. cmp ebx, eax
jg SHORT LookaheadRet
add esp, varsize mov eax, ebx
pop ebx LookaheadRet:
pop esi
pop edi ; Restore the stack and return from whence we came.
pop ebp
ret add esp, varsize
pop ebx
_longest_match ENDP pop esi
pop edi
_TEXT ENDS pop ebp
END ret
_longest_match ENDP
_TEXT ENDS
END

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,206 +1,62 @@
/* gvmat32.c -- C portion of the optimized longest_match for 32 bits x86 /* gvmat32.c -- C 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 prepare all parameters and call the assembly longest_match_gvasm * it prepare all parameters and call the assembly longest_match_gvasm
* 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
*/
#include "deflate.h"
#if defined(ASMV) && (!defined(NOOLDPENTIUMCODE))
#ifdef ASMV #include "deflate.h"
#define NIL 0
/* if your C compiler don't add underline before function name,
#define UNALIGNED_OK define ADD_UNDERLINE_ASMFUNC */
#ifdef ADD_UNDERLINE_ASMFUNC
#define longest_match_7fff _longest_match_7fff
/* if your C compiler don't add underline before function name, #define longest_match_686 _longest_match_686
define ADD_UNDERLINE_ASMFUNC */ #define cpudetect32 _cpudetect32
#ifdef ADD_UNDERLINE_ASMFUNC #endif
#define longest_match_7fff _longest_match_7fff
#define longest_match_686 _longest_match_686
#define cpudetect32 _cpudetect32 unsigned long cpudetect32();
#endif
uInt longest_match_c(
deflate_state *s,
IPos cur_match); /* current match */
void match_init()
{
} uInt longest_match_7fff(
deflate_state *s,
unsigned long cpudetect32(); IPos cur_match); /* current match */
uInt longest_match_c( uInt longest_match_686(
deflate_state *s, deflate_state *s,
IPos cur_match); /* current match */ IPos cur_match); /* current match */
uInt longest_match_7fff( static uInt iIsPPro=2;
deflate_state *s,
IPos cur_match); /* current match */ void match_init ()
{
uInt longest_match_686( iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0;
deflate_state *s, }
IPos cur_match); /* current match */
uInt longest_match(
uInt longest_match( deflate_state *s,
deflate_state *s, IPos cur_match) /* current match */
IPos cur_match) /* current match */ {
{ if (iIsPPro!=0)
static uInt iIsPPro=2; return longest_match_686(s,cur_match);
if ((s->w_mask == 0x7fff) && (iIsPPro==0)) if (s->w_mask != 0x7fff)
return longest_match_7fff(s,cur_match); return longest_match_686(s,cur_match);
if (iIsPPro==1) /* now ((s->w_mask == 0x7fff) && (iIsPPro==0)) */
return longest_match_686(s,cur_match); return longest_match_7fff(s,cur_match);
}
if (iIsPPro==2)
iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0;
#endif /* defined(ASMV) && (!defined(NOOLDPENTIUMCODE)) */
return longest_match_c(s,cur_match);
}
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 */

File diff suppressed because it is too large Load Diff

View File

@@ -1,63 +1,67 @@
Change in 1.01b (20 may 04) Change in 1.01e (12 feb 05)
- Integrate patch from Debian package (submited by Mark Brown) - Fix in zipOpen2 for globalcomment (Rolf Kalbermatter)
- Add tools mztools from Xavier Roche - Fix possible memory leak in unzip.c (Zoran Stevanovic)
Change in 1.01 (8 may 04) Change in 1.01b (20 may 04)
- fix buffer overrun risk in unzip.c (Xavier Roche) - Integrate patch from Debian package (submited by Mark Brown)
- fix a minor buffer insecurity in minizip.c (Mike Whittaker) - Add tools mztools from Xavier Roche
Change in 1.00: (10 sept 03) Change in 1.01 (8 may 04)
- rename to 1.00 - fix buffer overrun risk in unzip.c (Xavier Roche)
- cosmetic code change - fix a minor buffer insecurity in minizip.c (Mike Whittaker)
Change in 0.22: (19 May 03) Change in 1.00: (10 sept 03)
- crypting support (unless you define NOCRYPT) - rename to 1.00
- append file in existing zipfile - cosmetic code change
Change in 0.21: (10 Mar 03) Change in 0.22: (19 May 03)
- bug fixes - crypting support (unless you define NOCRYPT)
- append file in existing zipfile
Change in 0.17: (27 Jan 02)
- bug fixes Change in 0.21: (10 Mar 03)
- bug fixes
Change in 0.16: (19 Jan 02)
- Support of ioapi for virtualize zip file access Change in 0.17: (27 Jan 02)
- bug fixes
Change in 0.15: (19 Mar 98)
- fix memory leak in minizip.c Change in 0.16: (19 Jan 02)
- Support of ioapi for virtualize zip file access
Change in 0.14: (10 Mar 98)
- fix bugs in minizip.c sample for zipping big file Change in 0.15: (19 Mar 98)
- fix problem in month in date handling - fix memory leak in minizip.c
- fix bug in unzlocal_GetCurrentFileInfoInternal in unzip.c for
comment handling Change in 0.14: (10 Mar 98)
- fix bugs in minizip.c sample for zipping big file
Change in 0.13: (6 Mar 98) - fix problem in month in date handling
- fix bugs in zip.c - fix bug in unzlocal_GetCurrentFileInfoInternal in unzip.c for
- add real minizip sample comment handling
Change in 0.12: (4 Mar 98) Change in 0.13: (6 Mar 98)
- add zip.c and zip.h for creates .zip file - fix bugs in zip.c
- fix change_file_date in miniunz.c for Unix (Jean-loup Gailly) - add real minizip sample
- fix miniunz.c for file without specific record for directory
Change in 0.12: (4 Mar 98)
Change in 0.11: (3 Mar 98) - add zip.c and zip.h for creates .zip file
- fix bug in unzGetCurrentFileInfo for get extra field and comment - fix change_file_date in miniunz.c for Unix (Jean-loup Gailly)
- enhance miniunz sample, remove the bad unztst.c sample - fix miniunz.c for file without specific record for directory
Change in 0.10: (2 Mar 98) Change in 0.11: (3 Mar 98)
- fix bug in unzReadCurrentFile - fix bug in unzGetCurrentFileInfo for get extra field and comment
- rename unzip* to unz* function and structure - enhance miniunz sample, remove the bad unztst.c sample
- remove Windows-like hungary notation variable name
- modify some structure in unzip.h Change in 0.10: (2 Mar 98)
- add somes comment in source - fix bug in unzReadCurrentFile
- remove unzipGetcCurrentFile function - rename unzip* to unz* function and structure
- replace ZUNZEXPORT by ZEXPORT - remove Windows-like hungary notation variable name
- add unzGetLocalExtrafield for get the local extrafield info - modify some structure in unzip.h
- add a new sample, miniunz.c - add somes comment in source
- remove unzipGetcCurrentFile function
Change in 0.4: (25 Feb 98) - replace ZUNZEXPORT by ZEXPORT
- suppress the type unzipFileInZip. - add unzGetLocalExtrafield for get the local extrafield info
Only on file in the zipfile can be open at the same time - add a new sample, miniunz.c
- fix somes typo in code
- added tm_unz structure in unzip_file_info (date/time in readable format) Change in 0.4: (25 Feb 98)
- suppress the type unzipFileInZip.
Only on file in the zipfile can be open at the same time
- fix somes typo in code
- added tm_unz structure in unzip_file_info (date/time in readable format)

View File

@@ -1,25 +1,25 @@
CC=cc CC=cc
CFLAGS=-O -I../.. CFLAGS=-O -I../..
UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a
ZIP_OBJS = minizip.o zip.o ioapi.o ../../libz.a ZIP_OBJS = minizip.o zip.o ioapi.o ../../libz.a
.c.o: .c.o:
$(CC) -c $(CFLAGS) $*.c $(CC) -c $(CFLAGS) $*.c
all: miniunz minizip all: miniunz minizip
miniunz: $(UNZ_OBJS) miniunz: $(UNZ_OBJS)
$(CC) $(CFLAGS) -o $@ $(UNZ_OBJS) $(CC) $(CFLAGS) -o $@ $(UNZ_OBJS)
minizip: $(ZIP_OBJS) minizip: $(ZIP_OBJS)
$(CC) $(CFLAGS) -o $@ $(ZIP_OBJS) $(CC) $(CFLAGS) -o $@ $(ZIP_OBJS)
test: miniunz minizip test: miniunz minizip
./minizip test readme.txt ./minizip test readme.txt
./miniunz -l test.zip ./miniunz -l test.zip
mv readme.txt readme.old mv readme.txt readme.old
./miniunz test.zip ./miniunz test.zip
clean: clean:
/bin/rm -f *.o *~ minizip miniunz /bin/rm -f *.o *~ minizip miniunz

View File

@@ -1,132 +1,132 @@
/* 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
The encryption/decryption parts of this source code (as opposed to the The encryption/decryption parts of this source code (as opposed to the
non-echoing password parts) were originally written in Europe. The non-echoing password parts) were originally written in Europe. The
whole source package can be freely distributed, including from the USA. whole source package can be freely distributed, including from the USA.
(Prior to January 2000, re-export from the US was a violation of US law.) (Prior to January 2000, re-export from the US was a violation of US law.)
This encryption code is a direct transcription of the algorithm from This encryption code is a direct transcription of the algorithm from
Roger Schlafly, described by Phil Katz in the file appnote.txt. This Roger Schlafly, described by Phil Katz in the file appnote.txt. This
file (appnote.txt) is distributed with the PKZIP program (even in the file (appnote.txt) is distributed with the PKZIP program (even in the
version without encryption capabilities). version without encryption capabilities).
If you don't need crypting in your application, just define symbols If you don't need crypting in your application, just define symbols
NOCRYPT and NOUNCRYPT. NOCRYPT and NOUNCRYPT.
This code support the "Traditional PKWARE Encryption". This code support the "Traditional PKWARE Encryption".
The new AES encryption added on Zip format by Winzip (see the page The new AES encryption added on Zip format by Winzip (see the page
http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong
Encryption is not supported. Encryption is not supported.
*/ */
#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) #define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
/*********************************************************************** /***********************************************************************
* Return the next byte in the pseudo-random sequence * Return the next byte in the pseudo-random sequence
*/ */
static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab) static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
{ {
unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
* unpredictable manner on 16-bit systems; not a problem * unpredictable manner on 16-bit systems; not a problem
* with any known compiler so far, though */ * with any known compiler so far, though */
temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
} }
/*********************************************************************** /***********************************************************************
* Update the encryption keys with the next byte of plain text * Update the encryption keys with the next byte of plain text
*/ */
static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c) static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)
{ {
(*(pkeys+0)) = CRC32((*(pkeys+0)), c); (*(pkeys+0)) = CRC32((*(pkeys+0)), c);
(*(pkeys+1)) += (*(pkeys+0)) & 0xff; (*(pkeys+1)) += (*(pkeys+0)) & 0xff;
(*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
{ {
register int keyshift = (int)((*(pkeys+1)) >> 24); register int keyshift = (int)((*(pkeys+1)) >> 24);
(*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
} }
return c; return c;
} }
/*********************************************************************** /***********************************************************************
* Initialize the encryption keys and the random header according to * Initialize the encryption keys and the random header according to
* the given password. * the given password.
*/ */
static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab) static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
{ {
*(pkeys+0) = 305419896L; *(pkeys+0) = 305419896L;
*(pkeys+1) = 591751049L; *(pkeys+1) = 591751049L;
*(pkeys+2) = 878082192L; *(pkeys+2) = 878082192L;
while (*passwd != '\0') { while (*passwd != '\0') {
update_keys(pkeys,pcrc_32_tab,(int)*passwd); update_keys(pkeys,pcrc_32_tab,(int)*passwd);
passwd++; passwd++;
} }
} }
#define zdecode(pkeys,pcrc_32_tab,c) \ #define zdecode(pkeys,pcrc_32_tab,c) \
(update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
#define zencode(pkeys,pcrc_32_tab,c,t) \ #define zencode(pkeys,pcrc_32_tab,c,t) \
(t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED #ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
#define RAND_HEAD_LEN 12 #define RAND_HEAD_LEN 12
/* "last resort" source for second part of crypt seed pattern */ /* "last resort" source for second part of crypt seed pattern */
# ifndef ZCR_SEED2 # ifndef ZCR_SEED2
# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ # define ZCR_SEED2 3141592654UL /* use PI as default pattern */
# endif # endif
static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting) static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting)
const char *passwd; /* password string */ const char *passwd; /* password string */
unsigned char *buf; /* where to write header */ unsigned char *buf; /* where to write header */
int bufSize; int bufSize;
unsigned long* pkeys; unsigned long* pkeys;
const unsigned long* pcrc_32_tab; const unsigned long* pcrc_32_tab;
unsigned long crcForCrypting; unsigned long crcForCrypting;
{ {
int n; /* index in random header */ int n; /* index in random header */
int t; /* temporary */ int t; /* temporary */
int c; /* random byte */ int c; /* random byte */
unsigned char header[RAND_HEAD_LEN-2]; /* random header */ unsigned char header[RAND_HEAD_LEN-2]; /* random header */
static unsigned calls = 0; /* ensure different random header each time */ static unsigned calls = 0; /* ensure different random header each time */
if (bufSize<RAND_HEAD_LEN) if (bufSize<RAND_HEAD_LEN)
return 0; return 0;
/* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
* output of rand() to get less predictability, since rand() is * output of rand() to get less predictability, since rand() is
* often poorly implemented. * often poorly implemented.
*/ */
if (++calls == 1) if (++calls == 1)
{ {
srand((unsigned)(time(NULL) ^ ZCR_SEED2)); srand((unsigned)(time(NULL) ^ ZCR_SEED2));
} }
init_keys(passwd, pkeys, pcrc_32_tab); init_keys(passwd, pkeys, pcrc_32_tab);
for (n = 0; n < RAND_HEAD_LEN-2; n++) for (n = 0; n < RAND_HEAD_LEN-2; n++)
{ {
c = (rand() >> 7) & 0xff; c = (rand() >> 7) & 0xff;
header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
} }
/* Encrypt random header (last two bytes is high word of crc) */ /* Encrypt random header (last two bytes is high word of crc) */
init_keys(passwd, pkeys, pcrc_32_tab); init_keys(passwd, pkeys, pcrc_32_tab);
for (n = 0; n < RAND_HEAD_LEN-2; n++) for (n = 0; n < RAND_HEAD_LEN-2; n++)
{ {
buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
} }
buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
return n; return n;
} }
#endif #endif

View File

@@ -1,177 +1,177 @@
/* 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>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "zlib.h" #include "zlib.h"
#include "ioapi.h" #include "ioapi.h"
/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
#ifndef SEEK_CUR #ifndef SEEK_CUR
#define SEEK_CUR 1 #define SEEK_CUR 1
#endif #endif
#ifndef SEEK_END #ifndef SEEK_END
#define SEEK_END 2 #define SEEK_END 2
#endif #endif
#ifndef SEEK_SET #ifndef SEEK_SET
#define SEEK_SET 0 #define SEEK_SET 0
#endif #endif
voidpf ZCALLBACK fopen_file_func OF(( voidpf ZCALLBACK fopen_file_func OF((
voidpf opaque, voidpf opaque,
const char* filename, const char* filename,
int mode)); int mode));
uLong ZCALLBACK fread_file_func OF(( uLong ZCALLBACK fread_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream, voidpf stream,
void* buf, void* buf,
uLong size)); uLong size));
uLong ZCALLBACK fwrite_file_func OF(( uLong ZCALLBACK fwrite_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream, voidpf stream,
const void* buf, const void* buf,
uLong size)); uLong size));
long ZCALLBACK ftell_file_func OF(( long ZCALLBACK ftell_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream)); voidpf stream));
long ZCALLBACK fseek_file_func OF(( long ZCALLBACK fseek_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream, voidpf stream,
uLong offset, uLong offset,
int origin)); int origin));
int ZCALLBACK fclose_file_func OF(( int ZCALLBACK fclose_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream)); voidpf stream));
int ZCALLBACK ferror_file_func OF(( int ZCALLBACK ferror_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream)); voidpf stream));
voidpf ZCALLBACK fopen_file_func (opaque, filename, mode) voidpf ZCALLBACK fopen_file_func (opaque, filename, mode)
voidpf opaque; voidpf opaque;
const char* filename; const char* filename;
int mode; int mode;
{ {
FILE* file = NULL; FILE* file = NULL;
const char* mode_fopen = NULL; const char* mode_fopen = NULL;
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
mode_fopen = "rb"; mode_fopen = "rb";
else else
if (mode & ZLIB_FILEFUNC_MODE_EXISTING) if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
mode_fopen = "r+b"; mode_fopen = "r+b";
else else
if (mode & ZLIB_FILEFUNC_MODE_CREATE) if (mode & ZLIB_FILEFUNC_MODE_CREATE)
mode_fopen = "wb"; mode_fopen = "wb";
if ((filename!=NULL) && (mode_fopen != NULL)) if ((filename!=NULL) && (mode_fopen != NULL))
file = fopen(filename, mode_fopen); file = fopen(filename, mode_fopen);
return file; return file;
} }
uLong ZCALLBACK fread_file_func (opaque, stream, buf, size) uLong ZCALLBACK fread_file_func (opaque, stream, buf, size)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
void* buf; void* buf;
uLong size; uLong size;
{ {
uLong ret; uLong ret;
ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
return ret; return ret;
} }
uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size) uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
const void* buf; const void* buf;
uLong size; uLong size;
{ {
uLong ret; uLong ret;
ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
return ret; return ret;
} }
long ZCALLBACK ftell_file_func (opaque, stream) long ZCALLBACK ftell_file_func (opaque, stream)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
{ {
long ret; long ret;
ret = ftell((FILE *)stream); ret = ftell((FILE *)stream);
return ret; return ret;
} }
long ZCALLBACK fseek_file_func (opaque, stream, offset, origin) long ZCALLBACK fseek_file_func (opaque, stream, offset, origin)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
uLong offset; uLong offset;
int origin; int origin;
{ {
int fseek_origin=0; int fseek_origin=0;
long ret; long ret;
switch (origin) switch (origin)
{ {
case ZLIB_FILEFUNC_SEEK_CUR : case ZLIB_FILEFUNC_SEEK_CUR :
fseek_origin = SEEK_CUR; fseek_origin = SEEK_CUR;
break; break;
case ZLIB_FILEFUNC_SEEK_END : case ZLIB_FILEFUNC_SEEK_END :
fseek_origin = SEEK_END; fseek_origin = SEEK_END;
break; break;
case ZLIB_FILEFUNC_SEEK_SET : case ZLIB_FILEFUNC_SEEK_SET :
fseek_origin = SEEK_SET; fseek_origin = SEEK_SET;
break; break;
default: return -1; default: return -1;
} }
ret = 0; ret = 0;
fseek((FILE *)stream, offset, fseek_origin); fseek((FILE *)stream, offset, fseek_origin);
return ret; return ret;
} }
int ZCALLBACK fclose_file_func (opaque, stream) int ZCALLBACK fclose_file_func (opaque, stream)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
{ {
int ret; int ret;
ret = fclose((FILE *)stream); ret = fclose((FILE *)stream);
return ret; return ret;
} }
int ZCALLBACK ferror_file_func (opaque, stream) int ZCALLBACK ferror_file_func (opaque, stream)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
{ {
int ret; int ret;
ret = ferror((FILE *)stream); ret = ferror((FILE *)stream);
return ret; return ret;
} }
void fill_fopen_filefunc (pzlib_filefunc_def) void fill_fopen_filefunc (pzlib_filefunc_def)
zlib_filefunc_def* pzlib_filefunc_def; zlib_filefunc_def* pzlib_filefunc_def;
{ {
pzlib_filefunc_def->zopen_file = fopen_file_func; pzlib_filefunc_def->zopen_file = fopen_file_func;
pzlib_filefunc_def->zread_file = fread_file_func; pzlib_filefunc_def->zread_file = fread_file_func;
pzlib_filefunc_def->zwrite_file = fwrite_file_func; pzlib_filefunc_def->zwrite_file = fwrite_file_func;
pzlib_filefunc_def->ztell_file = ftell_file_func; pzlib_filefunc_def->ztell_file = ftell_file_func;
pzlib_filefunc_def->zseek_file = fseek_file_func; pzlib_filefunc_def->zseek_file = fseek_file_func;
pzlib_filefunc_def->zclose_file = fclose_file_func; pzlib_filefunc_def->zclose_file = fclose_file_func;
pzlib_filefunc_def->zerror_file = ferror_file_func; pzlib_filefunc_def->zerror_file = ferror_file_func;
pzlib_filefunc_def->opaque = NULL; pzlib_filefunc_def->opaque = NULL;
} }

View File

@@ -1,75 +1,75 @@
/* 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
#define _ZLIBIOAPI_H #define _ZLIBIOAPI_H
#define ZLIB_FILEFUNC_SEEK_CUR (1) #define ZLIB_FILEFUNC_SEEK_CUR (1)
#define ZLIB_FILEFUNC_SEEK_END (2) #define ZLIB_FILEFUNC_SEEK_END (2)
#define ZLIB_FILEFUNC_SEEK_SET (0) #define ZLIB_FILEFUNC_SEEK_SET (0)
#define ZLIB_FILEFUNC_MODE_READ (1) #define ZLIB_FILEFUNC_MODE_READ (1)
#define ZLIB_FILEFUNC_MODE_WRITE (2) #define ZLIB_FILEFUNC_MODE_WRITE (2)
#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) #define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
#define ZLIB_FILEFUNC_MODE_EXISTING (4) #define ZLIB_FILEFUNC_MODE_EXISTING (4)
#define ZLIB_FILEFUNC_MODE_CREATE (8) #define ZLIB_FILEFUNC_MODE_CREATE (8)
#ifndef ZCALLBACK #ifndef ZCALLBACK
#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) #if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
#define ZCALLBACK CALLBACK #define ZCALLBACK CALLBACK
#else #else
#define ZCALLBACK #define ZCALLBACK
#endif #endif
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));
typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));
typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
typedef struct zlib_filefunc_def_s typedef struct zlib_filefunc_def_s
{ {
open_file_func zopen_file; open_file_func zopen_file;
read_file_func zread_file; read_file_func zread_file;
write_file_func zwrite_file; write_file_func zwrite_file;
tell_file_func ztell_file; tell_file_func ztell_file;
seek_file_func zseek_file; seek_file_func zseek_file;
close_file_func zclose_file; close_file_func zclose_file;
testerror_file_func zerror_file; testerror_file_func zerror_file;
voidpf opaque; voidpf opaque;
} zlib_filefunc_def; } zlib_filefunc_def;
void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size)) #define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size))
#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size)) #define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size))
#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream)) #define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream))
#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode)) #define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode))
#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream)) #define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream))
#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream)) #define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream))
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

View File

@@ -1,270 +1,270 @@
/* iowin32.c -- IO base function header for compress/uncompress .zip /* iowin32.c -- IO base function header for compress/uncompress .zip
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>
#include "zlib.h" #include "zlib.h"
#include "ioapi.h" #include "ioapi.h"
#include "iowin32.h" #include "iowin32.h"
#ifndef INVALID_HANDLE_VALUE #ifndef INVALID_HANDLE_VALUE
#define INVALID_HANDLE_VALUE (0xFFFFFFFF) #define INVALID_HANDLE_VALUE (0xFFFFFFFF)
#endif #endif
#ifndef INVALID_SET_FILE_POINTER #ifndef INVALID_SET_FILE_POINTER
#define INVALID_SET_FILE_POINTER ((DWORD)-1) #define INVALID_SET_FILE_POINTER ((DWORD)-1)
#endif #endif
voidpf ZCALLBACK win32_open_file_func OF(( voidpf ZCALLBACK win32_open_file_func OF((
voidpf opaque, voidpf opaque,
const char* filename, const char* filename,
int mode)); int mode));
uLong ZCALLBACK win32_read_file_func OF(( uLong ZCALLBACK win32_read_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream, voidpf stream,
void* buf, void* buf,
uLong size)); uLong size));
uLong ZCALLBACK win32_write_file_func OF(( uLong ZCALLBACK win32_write_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream, voidpf stream,
const void* buf, const void* buf,
uLong size)); uLong size));
long ZCALLBACK win32_tell_file_func OF(( long ZCALLBACK win32_tell_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream)); voidpf stream));
long ZCALLBACK win32_seek_file_func OF(( long ZCALLBACK win32_seek_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream, voidpf stream,
uLong offset, uLong offset,
int origin)); int origin));
int ZCALLBACK win32_close_file_func OF(( int ZCALLBACK win32_close_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream)); voidpf stream));
int ZCALLBACK win32_error_file_func OF(( int ZCALLBACK win32_error_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream)); voidpf stream));
typedef struct typedef struct
{ {
HANDLE hf; HANDLE hf;
int error; int error;
} WIN32FILE_IOWIN; } WIN32FILE_IOWIN;
voidpf ZCALLBACK win32_open_file_func (opaque, filename, mode) voidpf ZCALLBACK win32_open_file_func (opaque, filename, mode)
voidpf opaque; voidpf opaque;
const char* filename; const char* filename;
int mode; int mode;
{ {
const char* mode_fopen = NULL; const char* mode_fopen = NULL;
DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ;
HANDLE hFile = 0; HANDLE hFile = 0;
voidpf ret=NULL; voidpf ret=NULL;
dwDesiredAccess = dwShareMode = dwFlagsAndAttributes = 0; dwDesiredAccess = dwShareMode = dwFlagsAndAttributes = 0;
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
{ {
dwDesiredAccess = GENERIC_READ; dwDesiredAccess = GENERIC_READ;
dwCreationDisposition = OPEN_EXISTING; dwCreationDisposition = OPEN_EXISTING;
dwShareMode = FILE_SHARE_READ; dwShareMode = FILE_SHARE_READ;
} }
else else
if (mode & ZLIB_FILEFUNC_MODE_EXISTING) if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
{ {
dwDesiredAccess = GENERIC_WRITE | GENERIC_READ; dwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
dwCreationDisposition = OPEN_EXISTING; dwCreationDisposition = OPEN_EXISTING;
} }
else else
if (mode & ZLIB_FILEFUNC_MODE_CREATE) if (mode & ZLIB_FILEFUNC_MODE_CREATE)
{ {
dwDesiredAccess = GENERIC_WRITE | GENERIC_READ; dwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
dwCreationDisposition = CREATE_ALWAYS; dwCreationDisposition = CREATE_ALWAYS;
} }
if ((filename!=NULL) && (dwDesiredAccess != 0)) if ((filename!=NULL) && (dwDesiredAccess != 0))
hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL,
dwCreationDisposition, dwFlagsAndAttributes, NULL); dwCreationDisposition, dwFlagsAndAttributes, NULL);
if (hFile == INVALID_HANDLE_VALUE) if (hFile == INVALID_HANDLE_VALUE)
hFile = NULL; hFile = NULL;
if (hFile != NULL) if (hFile != NULL)
{ {
WIN32FILE_IOWIN w32fiow; WIN32FILE_IOWIN w32fiow;
w32fiow.hf = hFile; w32fiow.hf = hFile;
w32fiow.error = 0; w32fiow.error = 0;
ret = malloc(sizeof(WIN32FILE_IOWIN)); ret = malloc(sizeof(WIN32FILE_IOWIN));
if (ret==NULL) if (ret==NULL)
CloseHandle(hFile); CloseHandle(hFile);
else *((WIN32FILE_IOWIN*)ret) = w32fiow; else *((WIN32FILE_IOWIN*)ret) = w32fiow;
} }
return ret; return ret;
} }
uLong ZCALLBACK win32_read_file_func (opaque, stream, buf, size) uLong ZCALLBACK win32_read_file_func (opaque, stream, buf, size)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
void* buf; void* buf;
uLong size; uLong size;
{ {
uLong ret=0; uLong ret=0;
HANDLE hFile = NULL; HANDLE hFile = NULL;
if (stream!=NULL) if (stream!=NULL)
hFile = ((WIN32FILE_IOWIN*)stream) -> hf; hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
if (hFile != NULL) if (hFile != NULL)
if (!ReadFile(hFile, buf, size, &ret, NULL)) if (!ReadFile(hFile, buf, size, &ret, NULL))
{ {
DWORD dwErr = GetLastError(); DWORD dwErr = GetLastError();
if (dwErr == ERROR_HANDLE_EOF) if (dwErr == ERROR_HANDLE_EOF)
dwErr = 0; dwErr = 0;
((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
} }
return ret; return ret;
} }
uLong ZCALLBACK win32_write_file_func (opaque, stream, buf, size) uLong ZCALLBACK win32_write_file_func (opaque, stream, buf, size)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
const void* buf; const void* buf;
uLong size; uLong size;
{ {
uLong ret=0; uLong ret=0;
HANDLE hFile = NULL; HANDLE hFile = NULL;
if (stream!=NULL) if (stream!=NULL)
hFile = ((WIN32FILE_IOWIN*)stream) -> hf; hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
if (hFile !=NULL) if (hFile !=NULL)
if (!WriteFile(hFile, buf, size, &ret, NULL)) if (!WriteFile(hFile, buf, size, &ret, NULL))
{ {
DWORD dwErr = GetLastError(); DWORD dwErr = GetLastError();
if (dwErr == ERROR_HANDLE_EOF) if (dwErr == ERROR_HANDLE_EOF)
dwErr = 0; dwErr = 0;
((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
} }
return ret; return ret;
} }
long ZCALLBACK win32_tell_file_func (opaque, stream) long ZCALLBACK win32_tell_file_func (opaque, stream)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
{ {
long ret=-1; long ret=-1;
HANDLE hFile = NULL; HANDLE hFile = NULL;
if (stream!=NULL) if (stream!=NULL)
hFile = ((WIN32FILE_IOWIN*)stream) -> hf; hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
if (hFile != NULL) if (hFile != NULL)
{ {
DWORD dwSet = SetFilePointer(hFile, 0, NULL, FILE_CURRENT); DWORD dwSet = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
if (dwSet == INVALID_SET_FILE_POINTER) if (dwSet == INVALID_SET_FILE_POINTER)
{ {
DWORD dwErr = GetLastError(); DWORD dwErr = GetLastError();
((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
ret = -1; ret = -1;
} }
else else
ret=(long)dwSet; ret=(long)dwSet;
} }
return ret; return ret;
} }
long ZCALLBACK win32_seek_file_func (opaque, stream, offset, origin) long ZCALLBACK win32_seek_file_func (opaque, stream, offset, origin)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
uLong offset; uLong offset;
int origin; int origin;
{ {
DWORD dwMoveMethod=0xFFFFFFFF; DWORD dwMoveMethod=0xFFFFFFFF;
HANDLE hFile = NULL; HANDLE hFile = NULL;
long ret=-1; long ret=-1;
if (stream!=NULL) if (stream!=NULL)
hFile = ((WIN32FILE_IOWIN*)stream) -> hf; hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
switch (origin) switch (origin)
{ {
case ZLIB_FILEFUNC_SEEK_CUR : case ZLIB_FILEFUNC_SEEK_CUR :
dwMoveMethod = FILE_CURRENT; dwMoveMethod = FILE_CURRENT;
break; break;
case ZLIB_FILEFUNC_SEEK_END : case ZLIB_FILEFUNC_SEEK_END :
dwMoveMethod = FILE_END; dwMoveMethod = FILE_END;
break; break;
case ZLIB_FILEFUNC_SEEK_SET : case ZLIB_FILEFUNC_SEEK_SET :
dwMoveMethod = FILE_BEGIN; dwMoveMethod = FILE_BEGIN;
break; break;
default: return -1; default: return -1;
} }
if (hFile != NULL) if (hFile != NULL)
{ {
DWORD dwSet = SetFilePointer(hFile, offset, NULL, dwMoveMethod); DWORD dwSet = SetFilePointer(hFile, offset, NULL, dwMoveMethod);
if (dwSet == INVALID_SET_FILE_POINTER) if (dwSet == INVALID_SET_FILE_POINTER)
{ {
DWORD dwErr = GetLastError(); DWORD dwErr = GetLastError();
((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
ret = -1; ret = -1;
} }
else else
ret=0; ret=0;
} }
return ret; return ret;
} }
int ZCALLBACK win32_close_file_func (opaque, stream) int ZCALLBACK win32_close_file_func (opaque, stream)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
{ {
int ret=-1; int ret=-1;
if (stream!=NULL) if (stream!=NULL)
{ {
HANDLE hFile; HANDLE hFile;
hFile = ((WIN32FILE_IOWIN*)stream) -> hf; hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
if (hFile != NULL) if (hFile != NULL)
{ {
CloseHandle(hFile); CloseHandle(hFile);
ret=0; ret=0;
} }
free(stream); free(stream);
} }
return ret; return ret;
} }
int ZCALLBACK win32_error_file_func (opaque, stream) int ZCALLBACK win32_error_file_func (opaque, stream)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
{ {
int ret=-1; int ret=-1;
if (stream!=NULL) if (stream!=NULL)
{ {
ret = ((WIN32FILE_IOWIN*)stream) -> error; ret = ((WIN32FILE_IOWIN*)stream) -> error;
} }
return ret; return ret;
} }
void fill_win32_filefunc (pzlib_filefunc_def) void fill_win32_filefunc (pzlib_filefunc_def)
zlib_filefunc_def* pzlib_filefunc_def; zlib_filefunc_def* pzlib_filefunc_def;
{ {
pzlib_filefunc_def->zopen_file = win32_open_file_func; pzlib_filefunc_def->zopen_file = win32_open_file_func;
pzlib_filefunc_def->zread_file = win32_read_file_func; pzlib_filefunc_def->zread_file = win32_read_file_func;
pzlib_filefunc_def->zwrite_file = win32_write_file_func; pzlib_filefunc_def->zwrite_file = win32_write_file_func;
pzlib_filefunc_def->ztell_file = win32_tell_file_func; pzlib_filefunc_def->ztell_file = win32_tell_file_func;
pzlib_filefunc_def->zseek_file = win32_seek_file_func; pzlib_filefunc_def->zseek_file = win32_seek_file_func;
pzlib_filefunc_def->zclose_file = win32_close_file_func; pzlib_filefunc_def->zclose_file = win32_close_file_func;
pzlib_filefunc_def->zerror_file = win32_error_file_func; pzlib_filefunc_def->zerror_file = win32_error_file_func;
pzlib_filefunc_def->opaque=NULL; pzlib_filefunc_def->opaque=NULL;
} }

View File

@@ -1,21 +1,21 @@
/* iowin32.h -- IO base function header for compress/uncompress .zip /* iowin32.h -- IO base function header for compress/uncompress .zip
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>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,420 +1,420 @@
/* /*
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>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#ifdef unix #ifdef unix
# include <unistd.h> # include <unistd.h>
# include <utime.h> # include <utime.h>
# include <sys/types.h> # include <sys/types.h>
# include <sys/stat.h> # include <sys/stat.h>
#else #else
# include <direct.h> # include <direct.h>
# include <io.h> # include <io.h>
#endif #endif
#include "zip.h" #include "zip.h"
#ifdef WIN32 #ifdef WIN32
#define USEWIN32IOAPI #define USEWIN32IOAPI
#include "iowin32.h" #include "iowin32.h"
#endif #endif
#define WRITEBUFFERSIZE (16384) #define WRITEBUFFERSIZE (16384)
#define MAXFILENAME (256) #define MAXFILENAME (256)
#ifdef WIN32 #ifdef WIN32
uLong filetime(f, tmzip, dt) uLong filetime(f, tmzip, dt)
char *f; /* name of file to get info on */ char *f; /* name of file to get info on */
tm_zip *tmzip; /* return value: access, modific. and creation times */ tm_zip *tmzip; /* return value: access, modific. and creation times */
uLong *dt; /* dostime */ uLong *dt; /* dostime */
{ {
int ret = 0; int ret = 0;
{ {
FILETIME ftLocal; FILETIME ftLocal;
HANDLE hFind; HANDLE hFind;
WIN32_FIND_DATA ff32; WIN32_FIND_DATA ff32;
hFind = FindFirstFile(f,&ff32); hFind = FindFirstFile(f,&ff32);
if (hFind != INVALID_HANDLE_VALUE) if (hFind != INVALID_HANDLE_VALUE)
{ {
FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal); FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal);
FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0); FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0);
FindClose(hFind); FindClose(hFind);
ret = 1; ret = 1;
} }
} }
return ret; return ret;
} }
#else #else
#ifdef unix #ifdef unix
uLong filetime(f, tmzip, dt) uLong filetime(f, tmzip, dt)
char *f; /* name of file to get info on */ char *f; /* name of file to get info on */
tm_zip *tmzip; /* return value: access, modific. and creation times */ tm_zip *tmzip; /* return value: access, modific. and creation times */
uLong *dt; /* dostime */ uLong *dt; /* dostime */
{ {
int ret=0; int ret=0;
struct stat s; /* results of stat() */ struct stat s; /* results of stat() */
struct tm* filedate; struct tm* filedate;
time_t tm_t=0; time_t tm_t=0;
if (strcmp(f,"-")!=0) if (strcmp(f,"-")!=0)
{ {
char name[MAXFILENAME+1]; char name[MAXFILENAME+1];
int len = strlen(f); int len = strlen(f);
if (len > MAXFILENAME) if (len > MAXFILENAME)
len = MAXFILENAME; len = MAXFILENAME;
strncpy(name, f,MAXFILENAME-1); strncpy(name, f,MAXFILENAME-1);
/* strncpy doesnt append the trailing NULL, of the string is too long. */ /* strncpy doesnt append the trailing NULL, of the string is too long. */
name[ MAXFILENAME ] = '\0'; name[ MAXFILENAME ] = '\0';
if (name[len - 1] == '/') if (name[len - 1] == '/')
name[len - 1] = '\0'; name[len - 1] = '\0';
/* not all systems allow stat'ing a file with / appended */ /* not all systems allow stat'ing a file with / appended */
if (stat(name,&s)==0) if (stat(name,&s)==0)
{ {
tm_t = s.st_mtime; tm_t = s.st_mtime;
ret = 1; ret = 1;
} }
} }
filedate = localtime(&tm_t); filedate = localtime(&tm_t);
tmzip->tm_sec = filedate->tm_sec; tmzip->tm_sec = filedate->tm_sec;
tmzip->tm_min = filedate->tm_min; tmzip->tm_min = filedate->tm_min;
tmzip->tm_hour = filedate->tm_hour; tmzip->tm_hour = filedate->tm_hour;
tmzip->tm_mday = filedate->tm_mday; tmzip->tm_mday = filedate->tm_mday;
tmzip->tm_mon = filedate->tm_mon ; tmzip->tm_mon = filedate->tm_mon ;
tmzip->tm_year = filedate->tm_year; tmzip->tm_year = filedate->tm_year;
return ret; return ret;
} }
#else #else
uLong filetime(f, tmzip, dt) uLong filetime(f, tmzip, dt)
char *f; /* name of file to get info on */ char *f; /* name of file to get info on */
tm_zip *tmzip; /* return value: access, modific. and creation times */ tm_zip *tmzip; /* return value: access, modific. and creation times */
uLong *dt; /* dostime */ uLong *dt; /* dostime */
{ {
return 0; return 0;
} }
#endif #endif
#endif #endif
int check_exist_file(filename) int check_exist_file(filename)
const char* filename; const char* filename;
{ {
FILE* ftestexist; FILE* ftestexist;
int ret = 1; int ret = 1;
ftestexist = fopen(filename,"rb"); ftestexist = fopen(filename,"rb");
if (ftestexist==NULL) if (ftestexist==NULL)
ret = 0; ret = 0;
else else
fclose(ftestexist); fclose(ftestexist);
return ret; return ret;
} }
void do_banner() void do_banner()
{ {
printf("MiniZip 1.01b, demo of zLib + Zip package written by Gilles Vollant\n"); printf("MiniZip 1.01b, demo of zLib + Zip package written by Gilles Vollant\n");
printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n"); printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n");
} }
void do_help() void do_help()
{ {
printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] file.zip [files_to_add]\n\n" \ printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] file.zip [files_to_add]\n\n" \
" -o Overwrite existing file.zip\n" \ " -o Overwrite existing file.zip\n" \
" -a Append to existing file.zip\n" \ " -a Append to existing file.zip\n" \
" -0 Store only\n" \ " -0 Store only\n" \
" -1 Compress faster\n" \ " -1 Compress faster\n" \
" -9 Compress better\n\n"); " -9 Compress better\n\n");
} }
/* calculate the CRC32 of a file, /* calculate the CRC32 of a file,
because to encrypt a file, we need known the CRC32 of the file before */ because to encrypt a file, we need known the CRC32 of the file before */
int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc) int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc)
{ {
unsigned long calculate_crc=0; unsigned long calculate_crc=0;
int err=ZIP_OK; int err=ZIP_OK;
FILE * fin = fopen(filenameinzip,"rb"); FILE * fin = fopen(filenameinzip,"rb");
unsigned long size_read = 0; unsigned long size_read = 0;
unsigned long total_read = 0; unsigned long total_read = 0;
if (fin==NULL) if (fin==NULL)
{ {
err = ZIP_ERRNO; err = ZIP_ERRNO;
} }
if (err == ZIP_OK) if (err == ZIP_OK)
do do
{ {
err = ZIP_OK; err = ZIP_OK;
size_read = (int)fread(buf,1,size_buf,fin); size_read = (int)fread(buf,1,size_buf,fin);
if (size_read < size_buf) if (size_read < size_buf)
if (feof(fin)==0) if (feof(fin)==0)
{ {
printf("error in reading %s\n",filenameinzip); printf("error in reading %s\n",filenameinzip);
err = ZIP_ERRNO; err = ZIP_ERRNO;
} }
if (size_read>0) if (size_read>0)
calculate_crc = crc32(calculate_crc,buf,size_read); calculate_crc = crc32(calculate_crc,buf,size_read);
total_read += size_read; total_read += size_read;
} while ((err == ZIP_OK) && (size_read>0)); } while ((err == ZIP_OK) && (size_read>0));
if (fin) if (fin)
fclose(fin); fclose(fin);
*result_crc=calculate_crc; *result_crc=calculate_crc;
printf("file %s crc %x\n",filenameinzip,calculate_crc); printf("file %s crc %x\n",filenameinzip,calculate_crc);
return err; return err;
} }
int main(argc,argv) int main(argc,argv)
int argc; int argc;
char *argv[]; char *argv[];
{ {
int i; int i;
int opt_overwrite=0; int opt_overwrite=0;
int opt_compress_level=Z_DEFAULT_COMPRESSION; int opt_compress_level=Z_DEFAULT_COMPRESSION;
int zipfilenamearg = 0; int zipfilenamearg = 0;
char filename_try[MAXFILENAME+16]; char filename_try[MAXFILENAME+16];
int zipok; int zipok;
int err=0; int err=0;
int size_buf=0; int size_buf=0;
void* buf=NULL; void* buf=NULL;
const char* password=NULL; const char* password=NULL;
do_banner(); do_banner();
if (argc==1) if (argc==1)
{ {
do_help(); do_help();
return 0; return 0;
} }
else else
{ {
for (i=1;i<argc;i++) for (i=1;i<argc;i++)
{ {
if ((*argv[i])=='-') if ((*argv[i])=='-')
{ {
const char *p=argv[i]+1; const char *p=argv[i]+1;
while ((*p)!='\0') while ((*p)!='\0')
{ {
char c=*(p++);; char c=*(p++);;
if ((c=='o') || (c=='O')) if ((c=='o') || (c=='O'))
opt_overwrite = 1; opt_overwrite = 1;
if ((c=='a') || (c=='A')) if ((c=='a') || (c=='A'))
opt_overwrite = 2; opt_overwrite = 2;
if ((c>='0') && (c<='9')) if ((c>='0') && (c<='9'))
opt_compress_level = c-'0'; opt_compress_level = c-'0';
if (((c=='p') || (c=='P')) && (i+1<argc)) if (((c=='p') || (c=='P')) && (i+1<argc))
{ {
password=argv[i+1]; password=argv[i+1];
i++; i++;
} }
} }
} }
else else
if (zipfilenamearg == 0) if (zipfilenamearg == 0)
zipfilenamearg = i ; zipfilenamearg = i ;
} }
} }
size_buf = WRITEBUFFERSIZE; size_buf = WRITEBUFFERSIZE;
buf = (void*)malloc(size_buf); buf = (void*)malloc(size_buf);
if (buf==NULL) if (buf==NULL)
{ {
printf("Error allocating memory\n"); printf("Error allocating memory\n");
return ZIP_INTERNALERROR; return ZIP_INTERNALERROR;
} }
if (zipfilenamearg==0) if (zipfilenamearg==0)
zipok=0; zipok=0;
else else
{ {
int i,len; int i,len;
int dot_found=0; int dot_found=0;
zipok = 1 ; zipok = 1 ;
strncpy(filename_try, argv[zipfilenamearg],MAXFILENAME-1); strncpy(filename_try, argv[zipfilenamearg],MAXFILENAME-1);
/* strncpy doesnt append the trailing NULL, of the string is too long. */ /* strncpy doesnt append the trailing NULL, of the string is too long. */
filename_try[ MAXFILENAME ] = '\0'; filename_try[ MAXFILENAME ] = '\0';
len=(int)strlen(filename_try); len=(int)strlen(filename_try);
for (i=0;i<len;i++) for (i=0;i<len;i++)
if (filename_try[i]=='.') if (filename_try[i]=='.')
dot_found=1; dot_found=1;
if (dot_found==0) if (dot_found==0)
strcat(filename_try,".zip"); strcat(filename_try,".zip");
if (opt_overwrite==2) if (opt_overwrite==2)
{ {
/* if the file don't exist, we not append file */ /* if the file don't exist, we not append file */
if (check_exist_file(filename_try)==0) if (check_exist_file(filename_try)==0)
opt_overwrite=1; opt_overwrite=1;
} }
else else
if (opt_overwrite==0) if (opt_overwrite==0)
if (check_exist_file(filename_try)!=0) if (check_exist_file(filename_try)!=0)
{ {
char rep=0; char rep=0;
do do
{ {
char answer[128]; char answer[128];
int ret; int ret;
printf("The file %s exists. Overwrite ? [y]es, [n]o, [a]ppend : ",filename_try); printf("The file %s exists. Overwrite ? [y]es, [n]o, [a]ppend : ",filename_try);
ret = scanf("%1s",answer); ret = scanf("%1s",answer);
if (ret != 1) if (ret != 1)
{ {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
rep = answer[0] ; rep = answer[0] ;
if ((rep>='a') && (rep<='z')) if ((rep>='a') && (rep<='z'))
rep -= 0x20; rep -= 0x20;
} }
while ((rep!='Y') && (rep!='N') && (rep!='A')); while ((rep!='Y') && (rep!='N') && (rep!='A'));
if (rep=='N') if (rep=='N')
zipok = 0; zipok = 0;
if (rep=='A') if (rep=='A')
opt_overwrite = 2; opt_overwrite = 2;
} }
} }
if (zipok==1) if (zipok==1)
{ {
zipFile zf; zipFile zf;
int errclose; int errclose;
# ifdef USEWIN32IOAPI # ifdef USEWIN32IOAPI
zlib_filefunc_def ffunc; zlib_filefunc_def ffunc;
fill_win32_filefunc(&ffunc); fill_win32_filefunc(&ffunc);
zf = zipOpen2(filename_try,(opt_overwrite==2) ? 2 : 0,NULL,&ffunc); zf = zipOpen2(filename_try,(opt_overwrite==2) ? 2 : 0,NULL,&ffunc);
# else # else
zf = zipOpen(filename_try,(opt_overwrite==2) ? 2 : 0); zf = zipOpen(filename_try,(opt_overwrite==2) ? 2 : 0);
# endif # endif
if (zf == NULL) if (zf == NULL)
{ {
printf("error opening %s\n",filename_try); printf("error opening %s\n",filename_try);
err= ZIP_ERRNO; err= ZIP_ERRNO;
} }
else else
printf("creating %s\n",filename_try); printf("creating %s\n",filename_try);
for (i=zipfilenamearg+1;(i<argc) && (err==ZIP_OK);i++) for (i=zipfilenamearg+1;(i<argc) && (err==ZIP_OK);i++)
{ {
if (!((((*(argv[i]))=='-') || ((*(argv[i]))=='/')) && if (!((((*(argv[i]))=='-') || ((*(argv[i]))=='/')) &&
((argv[i][1]=='o') || (argv[i][1]=='O') || ((argv[i][1]=='o') || (argv[i][1]=='O') ||
(argv[i][1]=='a') || (argv[i][1]=='A') || (argv[i][1]=='a') || (argv[i][1]=='A') ||
(argv[i][1]=='p') || (argv[i][1]=='P') || (argv[i][1]=='p') || (argv[i][1]=='P') ||
((argv[i][1]>='0') || (argv[i][1]<='9'))) && ((argv[i][1]>='0') || (argv[i][1]<='9'))) &&
(strlen(argv[i]) == 2))) (strlen(argv[i]) == 2)))
{ {
FILE * fin; FILE * fin;
int size_read; int size_read;
const char* filenameinzip = argv[i]; const char* filenameinzip = argv[i];
zip_fileinfo zi; zip_fileinfo zi;
unsigned long crcFile=0; unsigned long crcFile=0;
zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour = zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0; zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
zi.dosDate = 0; zi.dosDate = 0;
zi.internal_fa = 0; zi.internal_fa = 0;
zi.external_fa = 0; zi.external_fa = 0;
filetime(filenameinzip,&zi.tmz_date,&zi.dosDate); filetime(filenameinzip,&zi.tmz_date,&zi.dosDate);
/* /*
err = zipOpenNewFileInZip(zf,filenameinzip,&zi, err = zipOpenNewFileInZip(zf,filenameinzip,&zi,
NULL,0,NULL,0,NULL / * comment * /, NULL,0,NULL,0,NULL / * comment * /,
(opt_compress_level != 0) ? Z_DEFLATED : 0, (opt_compress_level != 0) ? Z_DEFLATED : 0,
opt_compress_level); opt_compress_level);
*/ */
if ((password != NULL) && (err==ZIP_OK)) if ((password != NULL) && (err==ZIP_OK))
err = getFileCrc(filenameinzip,buf,size_buf,&crcFile); err = getFileCrc(filenameinzip,buf,size_buf,&crcFile);
err = zipOpenNewFileInZip3(zf,filenameinzip,&zi, err = zipOpenNewFileInZip3(zf,filenameinzip,&zi,
NULL,0,NULL,0,NULL /* comment*/, NULL,0,NULL,0,NULL /* comment*/,
(opt_compress_level != 0) ? Z_DEFLATED : 0, (opt_compress_level != 0) ? Z_DEFLATED : 0,
opt_compress_level,0, opt_compress_level,0,
/* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */ /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
-MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
password,crcFile); password,crcFile);
if (err != ZIP_OK) if (err != ZIP_OK)
printf("error in opening %s in zipfile\n",filenameinzip); printf("error in opening %s in zipfile\n",filenameinzip);
else else
{ {
fin = fopen(filenameinzip,"rb"); fin = fopen(filenameinzip,"rb");
if (fin==NULL) if (fin==NULL)
{ {
err=ZIP_ERRNO; err=ZIP_ERRNO;
printf("error in opening %s for reading\n",filenameinzip); printf("error in opening %s for reading\n",filenameinzip);
} }
} }
if (err == ZIP_OK) if (err == ZIP_OK)
do do
{ {
err = ZIP_OK; err = ZIP_OK;
size_read = (int)fread(buf,1,size_buf,fin); size_read = (int)fread(buf,1,size_buf,fin);
if (size_read < size_buf) if (size_read < size_buf)
if (feof(fin)==0) if (feof(fin)==0)
{ {
printf("error in reading %s\n",filenameinzip); printf("error in reading %s\n",filenameinzip);
err = ZIP_ERRNO; err = ZIP_ERRNO;
} }
if (size_read>0) if (size_read>0)
{ {
err = zipWriteInFileInZip (zf,buf,size_read); err = zipWriteInFileInZip (zf,buf,size_read);
if (err<0) if (err<0)
{ {
printf("error in writing %s in the zipfile\n", printf("error in writing %s in the zipfile\n",
filenameinzip); filenameinzip);
} }
} }
} while ((err == ZIP_OK) && (size_read>0)); } while ((err == ZIP_OK) && (size_read>0));
if (fin) if (fin)
fclose(fin); fclose(fin);
if (err<0) if (err<0)
err=ZIP_ERRNO; err=ZIP_ERRNO;
else else
{ {
err = zipCloseFileInZip(zf); err = zipCloseFileInZip(zf);
if (err!=ZIP_OK) if (err!=ZIP_OK)
printf("error in closing %s in the zipfile\n", printf("error in closing %s in the zipfile\n",
filenameinzip); filenameinzip);
} }
} }
} }
errclose = zipClose(zf,NULL); errclose = zipClose(zf,NULL);
if (errclose != ZIP_OK) if (errclose != ZIP_OK)
printf("error in closing %s\n",filename_try); printf("error in closing %s\n",filename_try);
} }
else else
{ {
do_help(); do_help();
} }
free(buf); free(buf);
return 0; return 0;
} }

View File

@@ -1,281 +1,281 @@
/* /*
Additional tools for Minizip Additional tools for Minizip
Code: Xavier Roche '2004 Code: Xavier Roche '2004
License: Same as ZLIB (www.gzip.org) License: Same as ZLIB (www.gzip.org)
*/ */
/* Code */ /* Code */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "zlib.h" #include "zlib.h"
#include "unzip.h" #include "unzip.h"
#define READ_8(adr) ((unsigned char)*(adr)) #define READ_8(adr) ((unsigned char)*(adr))
#define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) ) #define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) )
#define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) ) #define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) )
#define WRITE_8(buff, n) do { \ #define WRITE_8(buff, n) do { \
*((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \ *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \
} while(0) } while(0)
#define WRITE_16(buff, n) do { \ #define WRITE_16(buff, n) do { \
WRITE_8((unsigned char*)(buff), n); \ WRITE_8((unsigned char*)(buff), n); \
WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \ WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \
} while(0) } while(0)
#define WRITE_32(buff, n) do { \ #define WRITE_32(buff, n) do { \
WRITE_16((unsigned char*)(buff), (n) & 0xffff); \ WRITE_16((unsigned char*)(buff), (n) & 0xffff); \
WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \ WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \
} while(0) } while(0)
extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered) extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered)
const char* file; const char* file;
const char* fileOut; const char* fileOut;
const char* fileOutTmp; const char* fileOutTmp;
uLong* nRecovered; uLong* nRecovered;
uLong* bytesRecovered; uLong* bytesRecovered;
{ {
int err = Z_OK; int err = Z_OK;
FILE* fpZip = fopen(file, "rb"); FILE* fpZip = fopen(file, "rb");
FILE* fpOut = fopen(fileOut, "wb"); FILE* fpOut = fopen(fileOut, "wb");
FILE* fpOutCD = fopen(fileOutTmp, "wb"); FILE* fpOutCD = fopen(fileOutTmp, "wb");
if (fpZip != NULL && fpOut != NULL) { if (fpZip != NULL && fpOut != NULL) {
int entries = 0; int entries = 0;
uLong totalBytes = 0; uLong totalBytes = 0;
char header[30]; char header[30];
char filename[256]; char filename[256];
char extra[1024]; char extra[1024];
int offset = 0; int offset = 0;
int offsetCD = 0; int offsetCD = 0;
while ( fread(header, 1, 30, fpZip) == 30 ) { while ( fread(header, 1, 30, fpZip) == 30 ) {
int currentOffset = offset; int currentOffset = offset;
/* File entry */ /* File entry */
if (READ_32(header) == 0x04034b50) { if (READ_32(header) == 0x04034b50) {
unsigned int version = READ_16(header + 4); unsigned int version = READ_16(header + 4);
unsigned int gpflag = READ_16(header + 6); unsigned int gpflag = READ_16(header + 6);
unsigned int method = READ_16(header + 8); unsigned int method = READ_16(header + 8);
unsigned int filetime = READ_16(header + 10); unsigned int filetime = READ_16(header + 10);
unsigned int filedate = READ_16(header + 12); unsigned int filedate = READ_16(header + 12);
unsigned int crc = READ_32(header + 14); /* crc */ unsigned int crc = READ_32(header + 14); /* crc */
unsigned int cpsize = READ_32(header + 18); /* compressed size */ unsigned int cpsize = READ_32(header + 18); /* compressed size */
unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */ unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */
unsigned int fnsize = READ_16(header + 26); /* file name length */ unsigned int fnsize = READ_16(header + 26); /* file name length */
unsigned int extsize = READ_16(header + 28); /* extra field length */ unsigned int extsize = READ_16(header + 28); /* extra field length */
filename[0] = extra[0] = '\0'; filename[0] = extra[0] = '\0';
/* Header */ /* Header */
if (fwrite(header, 1, 30, fpOut) == 30) { if (fwrite(header, 1, 30, fpOut) == 30) {
offset += 30; offset += 30;
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
break; break;
} }
/* Filename */ /* Filename */
if (fnsize > 0) { if (fnsize > 0) {
if (fread(filename, 1, fnsize, fpZip) == fnsize) { if (fread(filename, 1, fnsize, fpZip) == fnsize) {
if (fwrite(filename, 1, fnsize, fpOut) == fnsize) { if (fwrite(filename, 1, fnsize, fpOut) == fnsize) {
offset += fnsize; offset += fnsize;
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
break; break;
} }
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
break; break;
} }
} else { } else {
err = Z_STREAM_ERROR; err = Z_STREAM_ERROR;
break; break;
} }
/* Extra field */ /* Extra field */
if (extsize > 0) { if (extsize > 0) {
if (fread(extra, 1, extsize, fpZip) == extsize) { if (fread(extra, 1, extsize, fpZip) == extsize) {
if (fwrite(extra, 1, extsize, fpOut) == extsize) { if (fwrite(extra, 1, extsize, fpOut) == extsize) {
offset += extsize; offset += extsize;
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
break; break;
} }
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
break; break;
} }
} }
/* Data */ /* Data */
{ {
int dataSize = cpsize; int dataSize = cpsize;
if (dataSize == 0) { if (dataSize == 0) {
dataSize = uncpsize; dataSize = uncpsize;
} }
if (dataSize > 0) { if (dataSize > 0) {
char* data = malloc(dataSize); char* data = malloc(dataSize);
if (data != NULL) { if (data != NULL) {
if ((int)fread(data, 1, dataSize, fpZip) == dataSize) { if ((int)fread(data, 1, dataSize, fpZip) == dataSize) {
if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) { if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) {
offset += dataSize; offset += dataSize;
totalBytes += dataSize; totalBytes += dataSize;
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
} }
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
} }
free(data); free(data);
if (err != Z_OK) { if (err != Z_OK) {
break; break;
} }
} else { } else {
err = Z_MEM_ERROR; err = Z_MEM_ERROR;
break; break;
} }
} }
} }
/* Central directory entry */ /* Central directory entry */
{ {
char header[46]; char header[46];
char* comment = ""; char* comment = "";
int comsize = (int) strlen(comment); int comsize = (int) strlen(comment);
WRITE_32(header, 0x02014b50); WRITE_32(header, 0x02014b50);
WRITE_16(header + 4, version); WRITE_16(header + 4, version);
WRITE_16(header + 6, version); WRITE_16(header + 6, version);
WRITE_16(header + 8, gpflag); WRITE_16(header + 8, gpflag);
WRITE_16(header + 10, method); WRITE_16(header + 10, method);
WRITE_16(header + 12, filetime); WRITE_16(header + 12, filetime);
WRITE_16(header + 14, filedate); WRITE_16(header + 14, filedate);
WRITE_32(header + 16, crc); WRITE_32(header + 16, crc);
WRITE_32(header + 20, cpsize); WRITE_32(header + 20, cpsize);
WRITE_32(header + 24, uncpsize); WRITE_32(header + 24, uncpsize);
WRITE_16(header + 28, fnsize); WRITE_16(header + 28, fnsize);
WRITE_16(header + 30, extsize); WRITE_16(header + 30, extsize);
WRITE_16(header + 32, comsize); WRITE_16(header + 32, comsize);
WRITE_16(header + 34, 0); /* disk # */ WRITE_16(header + 34, 0); /* disk # */
WRITE_16(header + 36, 0); /* int attrb */ WRITE_16(header + 36, 0); /* int attrb */
WRITE_32(header + 38, 0); /* ext attrb */ WRITE_32(header + 38, 0); /* ext attrb */
WRITE_32(header + 42, currentOffset); WRITE_32(header + 42, currentOffset);
/* Header */ /* Header */
if (fwrite(header, 1, 46, fpOutCD) == 46) { if (fwrite(header, 1, 46, fpOutCD) == 46) {
offsetCD += 46; offsetCD += 46;
/* Filename */ /* Filename */
if (fnsize > 0) { if (fnsize > 0) {
if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) { if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) {
offsetCD += fnsize; offsetCD += fnsize;
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
break; break;
} }
} else { } else {
err = Z_STREAM_ERROR; err = Z_STREAM_ERROR;
break; break;
} }
/* Extra field */ /* Extra field */
if (extsize > 0) { if (extsize > 0) {
if (fwrite(extra, 1, extsize, fpOutCD) == extsize) { if (fwrite(extra, 1, extsize, fpOutCD) == extsize) {
offsetCD += extsize; offsetCD += extsize;
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
break; break;
} }
} }
/* Comment field */ /* Comment field */
if (comsize > 0) { if (comsize > 0) {
if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) { if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) {
offsetCD += comsize; offsetCD += comsize;
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
break; break;
} }
} }
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
break; break;
} }
} }
/* Success */ /* Success */
entries++; entries++;
} else { } else {
break; break;
} }
} }
/* Final central directory */ /* Final central directory */
{ {
int entriesZip = entries; int entriesZip = entries;
char header[22]; char header[22];
char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools"; char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools";
int comsize = (int) strlen(comment); int comsize = (int) strlen(comment);
if (entriesZip > 0xffff) { if (entriesZip > 0xffff) {
entriesZip = 0xffff; entriesZip = 0xffff;
} }
WRITE_32(header, 0x06054b50); WRITE_32(header, 0x06054b50);
WRITE_16(header + 4, 0); /* disk # */ WRITE_16(header + 4, 0); /* disk # */
WRITE_16(header + 6, 0); /* disk # */ WRITE_16(header + 6, 0); /* disk # */
WRITE_16(header + 8, entriesZip); /* hack */ WRITE_16(header + 8, entriesZip); /* hack */
WRITE_16(header + 10, entriesZip); /* hack */ WRITE_16(header + 10, entriesZip); /* hack */
WRITE_32(header + 12, offsetCD); /* size of CD */ WRITE_32(header + 12, offsetCD); /* size of CD */
WRITE_32(header + 16, offset); /* offset to CD */ WRITE_32(header + 16, offset); /* offset to CD */
WRITE_16(header + 20, comsize); /* comment */ WRITE_16(header + 20, comsize); /* comment */
/* Header */ /* Header */
if (fwrite(header, 1, 22, fpOutCD) == 22) { if (fwrite(header, 1, 22, fpOutCD) == 22) {
/* Comment field */ /* Comment field */
if (comsize > 0) { if (comsize > 0) {
if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) { if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) {
err = Z_ERRNO; err = Z_ERRNO;
} }
} }
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
} }
} }
/* Final merge (file + central directory) */ /* Final merge (file + central directory) */
fclose(fpOutCD); fclose(fpOutCD);
if (err == Z_OK) { if (err == Z_OK) {
fpOutCD = fopen(fileOutTmp, "rb"); fpOutCD = fopen(fileOutTmp, "rb");
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;
} }
} }
fclose(fpOutCD); fclose(fpOutCD);
} }
} }
/* Close */ /* Close */
fclose(fpZip); fclose(fpZip);
fclose(fpOut); fclose(fpOut);
/* Wipe temporary file */ /* Wipe temporary file */
(void)remove(fileOutTmp); (void)remove(fileOutTmp);
/* Number of recovered entries */ /* Number of recovered entries */
if (err == Z_OK) { if (err == Z_OK) {
if (nRecovered != NULL) { if (nRecovered != NULL) {
*nRecovered = entries; *nRecovered = entries;
} }
if (bytesRecovered != NULL) { if (bytesRecovered != NULL) {
*bytesRecovered = totalBytes; *bytesRecovered = totalBytes;
} }
} }
} else { } else {
err = Z_STREAM_ERROR; err = Z_STREAM_ERROR;
} }
return err; return err;
} }

View File

@@ -1,31 +1,31 @@
/* /*
Additional tools for Minizip Additional tools for Minizip
Code: Xavier Roche '2004 Code: Xavier Roche '2004
License: Same as ZLIB (www.gzip.org) License: Same as ZLIB (www.gzip.org)
*/ */
#ifndef _zip_tools_H #ifndef _zip_tools_H
#define _zip_tools_H #define _zip_tools_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#ifndef _ZLIB_H #ifndef _ZLIB_H
#include "zlib.h" #include "zlib.h"
#endif #endif
#include "unzip.h" #include "unzip.h"
/* Repair a ZIP file (missing central directory) /* Repair a ZIP file (missing central directory)
file: file to recover file: file to recover
fileOut: output file after recovery fileOut: output file after recovery
fileOutTmp: temporary file name used for recovery fileOutTmp: temporary file name used for recovery
*/ */
extern int ZEXPORT unzRepair(const char* file, extern int ZEXPORT unzRepair(const char* file,
const char* fileOut, const char* fileOut,
const char* fileOutTmp, const char* fileOutTmp,
uLong* nRecovered, uLong* nRecovered,
uLong* bytesRecovered); uLong* bytesRecovered);
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,352 +1,354 @@
/* 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.
Old compressions used by old PKZip 1.x 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
I WAIT FEEDBACK at mail info@winimage.com
Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
I WAIT FEEDBACK at mail info@winimage.com
Condition of use and distribution are the same than zlib : Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
This software is provided 'as-is', without any express or implied Condition of use and distribution are the same than zlib :
warranty. In no event will the authors be held liable for any damages
arising from the use of this software. This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
Permission is granted to anyone to use this software for any purpose, arising from the use of this software.
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions: Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
1. The origin of this software must not be misrepresented; you must not freely, subject to the following restrictions:
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be 1. The origin of this software must not be misrepresented; you must not
appreciated but is not required. claim that you wrote the original software. If you use this software
2. Altered source versions must be plainly marked as such, and must not be in a product, an acknowledgment in the product documentation would be
misrepresented as being the original software. appreciated but is not required.
3. This notice may not be removed or altered from any source distribution. 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.
*/
/* for more info about .ZIP format, see */
http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
http://www.info-zip.org/pub/infozip/doc/ /* for more info about .ZIP format, see
PkWare has also a specification at : http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
ftp://ftp.pkware.com/probdesc.zip http://www.info-zip.org/pub/infozip/doc/
*/ PkWare has also a specification at :
ftp://ftp.pkware.com/probdesc.zip
#ifndef _unz_H */
#define _unz_H
#ifndef _unz_H
#ifdef __cplusplus #define _unz_H
extern "C" {
#endif #ifdef __cplusplus
extern "C" {
#ifndef _ZLIB_H #endif
#include "zlib.h"
#endif #ifndef _ZLIB_H
#include "zlib.h"
#ifndef _ZLIBIOAPI_H #endif
#include "ioapi.h"
#endif #ifndef _ZLIBIOAPI_H
#include "ioapi.h"
#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) #endif
/* like the STRICT of WIN32, we define a pointer that cannot be converted
from (void*) without cast */ #if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
typedef struct TagunzFile__ { int unused; } unzFile__; /* like the STRICT of WIN32, we define a pointer that cannot be converted
typedef unzFile__ *unzFile; from (void*) without cast */
#else typedef struct TagunzFile__ { int unused; } unzFile__;
typedef voidp unzFile; typedef unzFile__ *unzFile;
#endif #else
typedef voidp unzFile;
#endif
#define UNZ_OK (0)
#define UNZ_END_OF_LIST_OF_FILE (-100)
#define UNZ_ERRNO (Z_ERRNO) #define UNZ_OK (0)
#define UNZ_EOF (0) #define UNZ_END_OF_LIST_OF_FILE (-100)
#define UNZ_PARAMERROR (-102) #define UNZ_ERRNO (Z_ERRNO)
#define UNZ_BADZIPFILE (-103) #define UNZ_EOF (0)
#define UNZ_INTERNALERROR (-104) #define UNZ_PARAMERROR (-102)
#define UNZ_CRCERROR (-105) #define UNZ_BADZIPFILE (-103)
#define UNZ_INTERNALERROR (-104)
/* tm_unz contain date/time info */ #define UNZ_CRCERROR (-105)
typedef struct tm_unz_s
{ /* tm_unz contain date/time info */
uInt tm_sec; /* seconds after the minute - [0,59] */ typedef struct tm_unz_s
uInt tm_min; /* minutes after the hour - [0,59] */ {
uInt tm_hour; /* hours since midnight - [0,23] */ uInt tm_sec; /* seconds after the minute - [0,59] */
uInt tm_mday; /* day of the month - [1,31] */ uInt tm_min; /* minutes after the hour - [0,59] */
uInt tm_mon; /* months since January - [0,11] */ uInt tm_hour; /* hours since midnight - [0,23] */
uInt tm_year; /* years - [1980..2044] */ uInt tm_mday; /* day of the month - [1,31] */
} tm_unz; uInt tm_mon; /* months since January - [0,11] */
uInt tm_year; /* years - [1980..2044] */
/* unz_global_info structure contain global data about the ZIPfile } tm_unz;
These data comes from the end of central dir */
typedef struct unz_global_info_s /* unz_global_info structure contain global data about the ZIPfile
{ These data comes from the end of central dir */
uLong number_entry; /* total number of entries in typedef struct unz_global_info_s
the central dir on this disk */ {
uLong size_comment; /* size of the global comment of the zipfile */ uLong number_entry; /* total number of entries in
} unz_global_info; the central dir on this disk */
uLong size_comment; /* size of the global comment of the zipfile */
} unz_global_info;
/* unz_file_info contain information about a file in the zipfile */
typedef struct unz_file_info_s
{ /* unz_file_info contain information about a file in the zipfile */
uLong version; /* version made by 2 bytes */ typedef struct unz_file_info_s
uLong version_needed; /* version needed to extract 2 bytes */ {
uLong flag; /* general purpose bit flag 2 bytes */ uLong version; /* version made by 2 bytes */
uLong compression_method; /* compression method 2 bytes */ uLong version_needed; /* version needed to extract 2 bytes */
uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ uLong flag; /* general purpose bit flag 2 bytes */
uLong crc; /* crc-32 4 bytes */ uLong compression_method; /* compression method 2 bytes */
uLong compressed_size; /* compressed size 4 bytes */ uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
uLong uncompressed_size; /* uncompressed size 4 bytes */ uLong crc; /* crc-32 4 bytes */
uLong size_filename; /* filename length 2 bytes */ uLong compressed_size; /* compressed size 4 bytes */
uLong size_file_extra; /* extra field length 2 bytes */ uLong uncompressed_size; /* uncompressed size 4 bytes */
uLong size_file_comment; /* file comment length 2 bytes */ uLong size_filename; /* filename length 2 bytes */
uLong size_file_extra; /* extra field length 2 bytes */
uLong disk_num_start; /* disk number start 2 bytes */ uLong size_file_comment; /* file comment length 2 bytes */
uLong internal_fa; /* internal file attributes 2 bytes */
uLong external_fa; /* external file attributes 4 bytes */ uLong disk_num_start; /* disk number start 2 bytes */
uLong internal_fa; /* internal file attributes 2 bytes */
tm_unz tmu_date; uLong external_fa; /* external file attributes 4 bytes */
} unz_file_info;
tm_unz tmu_date;
extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, } unz_file_info;
const char* fileName2,
int iCaseSensitivity)); extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
/* const char* fileName2,
Compare two filename (fileName1,fileName2). int iCaseSensitivity));
If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) /*
If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi Compare two filename (fileName1,fileName2).
or strcasecmp) If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
If iCaseSenisivity = 0, case sensitivity is defaut of your operating system If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
(like 1 on Unix, 2 on Windows) or strcasecmp)
*/ If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
(like 1 on Unix, 2 on Windows)
*/
extern unzFile ZEXPORT unzOpen OF((const char *path));
/*
Open a Zip file. path contain the full pathname (by example, extern unzFile ZEXPORT unzOpen OF((const char *path));
on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer /*
"zlib/zlib113.zip". Open a Zip file. path contain the full pathname (by example,
If the zipfile cannot be opened (file don't exist or in not valid), the on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer
return value is NULL. "zlib/zlib113.zip".
Else, the return value is a unzFile Handle, usable with other function If the zipfile cannot be opened (file don't exist or in not valid), the
of this unzip package. return value is NULL.
*/ Else, the return value is a unzFile Handle, usable with other function
of this unzip package.
extern unzFile ZEXPORT unzOpen2 OF((const char *path, */
zlib_filefunc_def* pzlib_filefunc_def));
/* extern unzFile ZEXPORT unzOpen2 OF((const char *path,
Open a Zip file, like unzOpen, but provide a set of file low level API zlib_filefunc_def* pzlib_filefunc_def));
for read/write the zip file (see ioapi.h) /*
*/ Open a Zip file, like unzOpen, but provide a set of file low level API
for read/write the zip file (see ioapi.h)
extern int ZEXPORT unzClose OF((unzFile file)); */
/*
Close a ZipFile opened with unzipOpen. extern int ZEXPORT unzClose OF((unzFile file));
If there is files inside the .Zip opened with unzOpenCurrentFile (see later), /*
these files MUST be closed with unzipCloseCurrentFile before call unzipClose. Close a ZipFile opened with unzipOpen.
return UNZ_OK if there is no problem. */ If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, return UNZ_OK if there is no problem. */
unz_global_info *pglobal_info));
/* extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
Write info about the ZipFile in the *pglobal_info structure. unz_global_info *pglobal_info));
No preparation of the structure is needed /*
return UNZ_OK if there is no problem. */ Write info about the ZipFile in the *pglobal_info structure.
No preparation of the structure is needed
return UNZ_OK if there is no problem. */
extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
char *szComment,
uLong uSizeBuf)); extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
/* char *szComment,
Get the global comment string of the ZipFile, in the szComment buffer. uLong uSizeBuf));
uSizeBuf is the size of the szComment buffer. /*
return the number of byte copied or an error code <0 Get the global comment string of the ZipFile, in the szComment buffer.
*/ uSizeBuf is the size of the szComment buffer.
return the number of byte copied or an error code <0
*/
/***************************************************************************/
/* Unzip package allow you browse the directory of the zipfile */
/***************************************************************************/
extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); /* Unzip package allow you browse the directory of the zipfile */
/*
Set the current file of the zipfile to the first file. extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
return UNZ_OK if there is no problem /*
*/ Set the current file of the zipfile to the first file.
return UNZ_OK if there is no problem
extern int ZEXPORT unzGoToNextFile OF((unzFile file)); */
/*
Set the current file of the zipfile to the next file. extern int ZEXPORT unzGoToNextFile OF((unzFile file));
return UNZ_OK if there is no problem /*
return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. Set the current file of the zipfile to the next file.
*/ return UNZ_OK if there is no problem
return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
extern int ZEXPORT unzLocateFile OF((unzFile file, */
const char *szFileName,
int iCaseSensitivity)); extern int ZEXPORT unzLocateFile OF((unzFile file,
/* const char *szFileName,
Try locate the file szFileName in the zipfile. int iCaseSensitivity));
For the iCaseSensitivity signification, see unzStringFileNameCompare /*
Try locate the file szFileName in the zipfile.
return value : For the iCaseSensitivity signification, see unzStringFileNameCompare
UNZ_OK if the file is found. It becomes the current file.
UNZ_END_OF_LIST_OF_FILE if the file is not found return value :
*/ UNZ_OK if the file is found. It becomes the current file.
UNZ_END_OF_LIST_OF_FILE if the file is not found
*/
/* ****************************************** */
/* Ryan supplied functions */
/* unz_file_info contain information about a file in the zipfile */ /* ****************************************** */
typedef struct unz_file_pos_s /* Ryan supplied functions */
{ /* unz_file_info contain information about a file in the zipfile */
uLong pos_in_zip_directory; /* offset in zip file directory */ typedef struct unz_file_pos_s
uLong num_of_file; /* # of file */ {
} unz_file_pos; uLong pos_in_zip_directory; /* offset in zip file directory */
uLong num_of_file; /* # of file */
extern int ZEXPORT unzGetFilePos( } unz_file_pos;
unzFile file,
unz_file_pos* file_pos); extern int ZEXPORT unzGetFilePos(
unzFile file,
extern int ZEXPORT unzGoToFilePos( unz_file_pos* file_pos);
unzFile file,
unz_file_pos* file_pos); extern int ZEXPORT unzGoToFilePos(
unzFile file,
/* ****************************************** */ unz_file_pos* file_pos);
extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, /* ****************************************** */
unz_file_info *pfile_info,
char *szFileName, extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
uLong fileNameBufferSize, unz_file_info *pfile_info,
void *extraField, char *szFileName,
uLong extraFieldBufferSize, uLong fileNameBufferSize,
char *szComment, void *extraField,
uLong commentBufferSize)); uLong extraFieldBufferSize,
/* char *szComment,
Get Info about the current file uLong commentBufferSize));
if pfile_info!=NULL, the *pfile_info structure will contain somes info about /*
the current file Get Info about the current file
if szFileName!=NULL, the filemane string will be copied in szFileName if pfile_info!=NULL, the *pfile_info structure will contain somes info about
(fileNameBufferSize is the size of the buffer) the current file
if extraField!=NULL, the extra field information will be copied in extraField if szFileName!=NULL, the filemane string will be copied in szFileName
(extraFieldBufferSize is the size of the buffer). (fileNameBufferSize is the size of the buffer)
This is the Central-header version of the extra field if extraField!=NULL, the extra field information will be copied in extraField
if szComment!=NULL, the comment string of the file will be copied in szComment (extraFieldBufferSize is the size of the buffer).
(commentBufferSize is the size of the buffer) This is the Central-header version of the extra field
*/ if szComment!=NULL, the comment string of the file will be copied in szComment
(commentBufferSize is the size of the buffer)
/***************************************************************************/ */
/* for reading the content of the current zipfile, you can open it, read data
from it, and close it (you can close it before reading all the file) /***************************************************************************/
*/ /* for reading the content of the current zipfile, you can open it, read data
from it, and close it (you can close it before reading all the file)
extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); */
/*
Open for reading data the current file in the zipfile. extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
If there is no error, the return value is UNZ_OK. /*
*/ Open for reading data the current file in the zipfile.
If there is no error, the return value is UNZ_OK.
extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, */
const char* password));
/* extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file,
Open for reading data the current file in the zipfile. const char* password));
password is a crypting password /*
If there is no error, the return value is UNZ_OK. Open for reading data the current file in the zipfile.
*/ password is a crypting password
If there is no error, the return value is UNZ_OK.
extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, */
int* method,
int* level, extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file,
int raw)); int* method,
/* int* level,
Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) int raw));
if raw==1 /*
*method will receive method of compression, *level will receive level of Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
compression if raw==1
note : you can set level parameter as NULL (if you did not want known level, *method will receive method of compression, *level will receive level of
but you CANNOT set method parameter as NULL compression
*/ note : you can set level parameter as NULL (if you did not want known level,
but you CANNOT set method parameter as NULL
extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, */
int* method,
int* level, extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file,
int raw, int* method,
const char* password)); int* level,
/* int raw,
Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) const char* password));
if raw==1 /*
*method will receive method of compression, *level will receive level of Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
compression if raw==1
note : you can set level parameter as NULL (if you did not want known level, *method will receive method of compression, *level will receive level of
but you CANNOT set method parameter as NULL compression
*/ note : you can set level parameter as NULL (if you did not want known level,
but you CANNOT set method parameter as NULL
*/
extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
/*
Close the file in zip opened with unzOpenCurrentFile extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
Return UNZ_CRCERROR if all the file was read but the CRC is not good /*
*/ Close the file in zip opened with unzOpenCurrentFile
Return UNZ_CRCERROR if all the file was read but the CRC is not good
extern int ZEXPORT unzReadCurrentFile OF((unzFile file, */
voidp buf,
unsigned len)); extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
/* voidp buf,
Read bytes from the current file (opened by unzOpenCurrentFile) unsigned len));
buf contain buffer where data must be copied /*
len the size of buf. Read bytes from the current file (opened by unzOpenCurrentFile)
buf contain buffer where data must be copied
return the number of byte copied if somes bytes are copied len the size of buf.
return 0 if the end of file was reached
return <0 with error code if there is an error return the number of byte copied if somes bytes are copied
(UNZ_ERRNO for IO error, or zLib error for uncompress error) return 0 if the end of file was reached
*/ return <0 with error code if there is an error
(UNZ_ERRNO for IO error, or zLib error for uncompress error)
extern z_off_t ZEXPORT unztell OF((unzFile file)); */
/*
Give the current position in uncompressed data extern z_off_t ZEXPORT unztell OF((unzFile file));
*/ /*
Give the current position in uncompressed data
extern int ZEXPORT unzeof OF((unzFile file)); */
/*
return 1 if the end of file was reached, 0 elsewhere extern int ZEXPORT unzeof OF((unzFile file));
*/ /*
return 1 if the end of file was reached, 0 elsewhere
extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, */
voidp buf,
unsigned len)); extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
/* voidp buf,
Read extra field from the current file (opened by unzOpenCurrentFile) unsigned len));
This is the local-header version of the extra field (sometimes, there is /*
more info in the local-header version than in the central-header) Read extra field from the current file (opened by unzOpenCurrentFile)
This is the local-header version of the extra field (sometimes, there is
if buf==NULL, it return the size of the local extra field more info in the local-header version than in the central-header)
if buf!=NULL, len is the size of the buffer, the extra header is copied in if buf==NULL, it return the size of the local extra field
buf.
the return value is the number of bytes copied in buf, or (if <0) if buf!=NULL, len is the size of the buffer, the extra header is copied in
the error code buf.
*/ the return value is the number of bytes copied in buf, or (if <0)
the error code
/***************************************************************************/ */
/* Get the current file offset */ /***************************************************************************/
extern uLong ZEXPORT unzGetOffset (unzFile file);
/* Get the current file offset */
/* Set the current file offset */ extern uLong ZEXPORT unzGetOffset (unzFile file);
extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);
/* Set the current file offset */
extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);
#ifdef __cplusplus
}
#endif #ifdef __cplusplus
}
#endif /* _unz_H */ #endif
#endif /* _unz_H */

File diff suppressed because it is too large Load Diff

View File

@@ -1,234 +1,235 @@
/* 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.
Old compressions used by old PKZip 1.x are not supported Encryption compatible with pkzip 2.04g only 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
I WAIT FEEDBACK at mail info@winimage.com
Visit also http://www.winimage.com/zLibDll/unzip.html for evolution I WAIT FEEDBACK at mail info@winimage.com
Visit also http://www.winimage.com/zLibDll/unzip.html for evolution
Condition of use and distribution are the same than zlib :
Condition of use and distribution are the same than zlib :
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages This software is provided 'as-is', without any express or implied
arising from the use of this software. warranty. In no event will the authors 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 Permission is granted to anyone to use this software for any purpose,
freely, subject to the following restrictions: 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 1. The origin of this software must not be misrepresented; you must not
in a product, an acknowledgment in the product documentation would be claim that you wrote the original software. If you use this software
appreciated but is not required. in a product, an acknowledgment in the product documentation would be
2. Altered source versions must be plainly marked as such, and must not be appreciated but is not required.
misrepresented as being the original software. 2. Altered source versions must be plainly marked as such, and must not be
3. This notice may not be removed or altered from any source distribution. misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
*/
/* for more info about .ZIP format, see
http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip /* for more info about .ZIP format, see
http://www.info-zip.org/pub/infozip/doc/ http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
PkWare has also a specification at : http://www.info-zip.org/pub/infozip/doc/
ftp://ftp.pkware.com/probdesc.zip PkWare has also a specification at :
*/ ftp://ftp.pkware.com/probdesc.zip
*/
#ifndef _zip_H
#define _zip_H #ifndef _zip_H
#define _zip_H
#ifdef __cplusplus
extern "C" { #ifdef __cplusplus
#endif extern "C" {
#endif
#ifndef _ZLIB_H
#include "zlib.h" #ifndef _ZLIB_H
#endif #include "zlib.h"
#endif
#ifndef _ZLIBIOAPI_H
#include "ioapi.h" #ifndef _ZLIBIOAPI_H
#endif #include "ioapi.h"
#endif
#if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
/* like the STRICT of WIN32, we define a pointer that cannot be converted #if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
from (void*) without cast */ /* like the STRICT of WIN32, we define a pointer that cannot be converted
typedef struct TagzipFile__ { int unused; } zipFile__; from (void*) without cast */
typedef zipFile__ *zipFile; typedef struct TagzipFile__ { int unused; } zipFile__;
#else typedef zipFile__ *zipFile;
typedef voidp zipFile; #else
#endif typedef voidp zipFile;
#endif
#define ZIP_OK (0)
#define ZIP_EOF (0) #define ZIP_OK (0)
#define ZIP_ERRNO (Z_ERRNO) #define ZIP_EOF (0)
#define ZIP_PARAMERROR (-102) #define ZIP_ERRNO (Z_ERRNO)
#define ZIP_BADZIPFILE (-103) #define ZIP_PARAMERROR (-102)
#define ZIP_INTERNALERROR (-104) #define ZIP_BADZIPFILE (-103)
#define ZIP_INTERNALERROR (-104)
#ifndef DEF_MEM_LEVEL
# if MAX_MEM_LEVEL >= 8 #ifndef DEF_MEM_LEVEL
# define DEF_MEM_LEVEL 8 # if MAX_MEM_LEVEL >= 8
# else # define DEF_MEM_LEVEL 8
# define DEF_MEM_LEVEL MAX_MEM_LEVEL # else
# endif # define DEF_MEM_LEVEL MAX_MEM_LEVEL
#endif # endif
/* default memLevel */ #endif
/* default memLevel */
/* tm_zip contain date/time info */
typedef struct tm_zip_s /* tm_zip contain date/time info */
{ typedef struct tm_zip_s
uInt tm_sec; /* seconds after the minute - [0,59] */ {
uInt tm_min; /* minutes after the hour - [0,59] */ uInt tm_sec; /* seconds after the minute - [0,59] */
uInt tm_hour; /* hours since midnight - [0,23] */ uInt tm_min; /* minutes after the hour - [0,59] */
uInt tm_mday; /* day of the month - [1,31] */ uInt tm_hour; /* hours since midnight - [0,23] */
uInt tm_mon; /* months since January - [0,11] */ uInt tm_mday; /* day of the month - [1,31] */
uInt tm_year; /* years - [1980..2044] */ uInt tm_mon; /* months since January - [0,11] */
} tm_zip; uInt tm_year; /* years - [1980..2044] */
} tm_zip;
typedef struct
{ typedef struct
tm_zip tmz_date; /* date in understandable format */ {
uLong dosDate; /* if dos_date == 0, tmu_date is used */ tm_zip tmz_date; /* date in understandable format */
/* uLong flag; */ /* general purpose bit flag 2 bytes */ uLong dosDate; /* if dos_date == 0, tmu_date is used */
/* uLong flag; */ /* general purpose bit flag 2 bytes */
uLong internal_fa; /* internal file attributes 2 bytes */
uLong external_fa; /* external file attributes 4 bytes */ uLong internal_fa; /* internal file attributes 2 bytes */
} zip_fileinfo; uLong external_fa; /* external file attributes 4 bytes */
} zip_fileinfo;
typedef const char* zipcharpc;
typedef const char* zipcharpc;
#define APPEND_STATUS_CREATE (0)
#define APPEND_STATUS_CREATEAFTER (1) #define APPEND_STATUS_CREATE (0)
#define APPEND_STATUS_ADDINZIP (2) #define APPEND_STATUS_CREATEAFTER (1)
#define APPEND_STATUS_ADDINZIP (2)
extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append));
/* extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append));
Create a zipfile. /*
pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on Create a zipfile.
an Unix computer "zlib/zlib113.zip". pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on
if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip an Unix computer "zlib/zlib113.zip".
will be created at the end of the file. if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip
(useful if the file contain a self extractor code) will be created at the end of the file.
if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will (useful if the file contain a self extractor code)
add files in existing zip (be sure you don't add file that doesn't exist) if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will
If the zipfile cannot be opened, the return value is NULL. add files in existing zip (be sure you don't add file that doesn't exist)
Else, the return value is a zipFile Handle, usable with other function If the zipfile cannot be opened, the return value is NULL.
of this zip package. Else, the return value is a zipFile Handle, usable with other function
*/ of this zip package.
*/
/* Note : there is no delete function into a zipfile.
If you want delete file into a zipfile, you must open a zipfile, and create another /* Note : there is no delete function into a zipfile.
Of couse, you can use RAW reading and writing to copy the file you did not want delte If you want delete file into a zipfile, you must open a zipfile, and create another
*/ Of couse, you can use RAW reading and writing to copy the file you did not want delte
*/
extern zipFile ZEXPORT zipOpen2 OF((const char *pathname,
int append, extern zipFile ZEXPORT zipOpen2 OF((const char *pathname,
zipcharpc* globalcomment, int append,
zlib_filefunc_def* pzlib_filefunc_def)); zipcharpc* globalcomment,
zlib_filefunc_def* pzlib_filefunc_def));
extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
const char* filename, extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
const zip_fileinfo* zipfi, const char* filename,
const void* extrafield_local, const zip_fileinfo* zipfi,
uInt size_extrafield_local, const void* extrafield_local,
const void* extrafield_global, uInt size_extrafield_local,
uInt size_extrafield_global, const void* extrafield_global,
const char* comment, uInt size_extrafield_global,
int method, const char* comment,
int level)); int method,
/* int level));
Open a file in the ZIP for writing. /*
filename : the filename in zip (if NULL, '-' without quote will be used Open a file in the ZIP for writing.
*zipfi contain supplemental information filename : the filename in zip (if NULL, '-' without quote will be used
if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local *zipfi contain supplemental information
contains the extrafield data the the local header if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global contains the extrafield data the the local header
contains the extrafield data the the local header if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
if comment != NULL, comment contain the comment string contains the extrafield data the the local header
method contain the compression method (0 for store, Z_DEFLATED for deflate) if comment != NULL, comment contain the comment string
level contain the level of compression (can be Z_DEFAULT_COMPRESSION) method contain the compression method (0 for store, Z_DEFLATED for deflate)
*/ level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
*/
extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file,
const char* filename, extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file,
const zip_fileinfo* zipfi, const char* filename,
const void* extrafield_local, const zip_fileinfo* zipfi,
uInt size_extrafield_local, const void* extrafield_local,
const void* extrafield_global, uInt size_extrafield_local,
uInt size_extrafield_global, const void* extrafield_global,
const char* comment, uInt size_extrafield_global,
int method, const char* comment,
int level, int method,
int raw)); int level,
int raw));
/*
Same than zipOpenNewFileInZip, except if raw=1, we write raw file /*
*/ Same than zipOpenNewFileInZip, except if raw=1, we write raw file
*/
extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file,
const char* filename, extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file,
const zip_fileinfo* zipfi, const char* filename,
const void* extrafield_local, const zip_fileinfo* zipfi,
uInt size_extrafield_local, const void* extrafield_local,
const void* extrafield_global, uInt size_extrafield_local,
uInt size_extrafield_global, const void* extrafield_global,
const char* comment, uInt size_extrafield_global,
int method, const char* comment,
int level, int method,
int raw, int level,
int windowBits, int raw,
int memLevel, int windowBits,
int strategy, int memLevel,
const char* password, int strategy,
uLong crcForCtypting)); const char* password,
uLong crcForCtypting));
/*
Same than zipOpenNewFileInZip2, except /*
windowBits,memLevel,,strategy : see parameter strategy in deflateInit2 Same than zipOpenNewFileInZip2, except
password : crypting password (NULL for no crypting) windowBits,memLevel,,strategy : see parameter strategy in deflateInit2
crcForCtypting : crc of file to compress (needed for crypting) password : crypting password (NULL for no crypting)
*/ crcForCtypting : crc of file to compress (needed for crypting)
*/
extern int ZEXPORT zipWriteInFileInZip OF((zipFile file,
const void* buf, extern int ZEXPORT zipWriteInFileInZip OF((zipFile file,
unsigned len)); const void* buf,
/* unsigned len));
Write data in the zipfile /*
*/ Write data in the zipfile
*/
extern int ZEXPORT zipCloseFileInZip OF((zipFile file));
/* extern int ZEXPORT zipCloseFileInZip OF((zipFile file));
Close the current file in the zipfile /*
*/ Close the current file in the zipfile
*/
extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file,
uLong uncompressed_size, extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file,
uLong crc32)); uLong uncompressed_size,
/* uLong crc32));
Close the current file in the zipfile, for fiel opened with /*
parameter raw=1 in zipOpenNewFileInZip2 Close the current file in the zipfile, for fiel opened with
uncompressed_size and crc32 are value for the uncompressed size parameter raw=1 in zipOpenNewFileInZip2
*/ uncompressed_size and crc32 are value for the uncompressed size
*/
extern int ZEXPORT zipClose OF((zipFile file,
const char* global_comment)); extern int ZEXPORT zipClose OF((zipFile file,
/* const char* global_comment));
Close the zipfile /*
*/ Close the zipfile
*/
#ifdef __cplusplus
} #ifdef __cplusplus
#endif }
#endif
#endif /* _zip_H */
#endif /* _zip_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

@@ -1,149 +1,258 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <windows.h> #include <windows.h>
#include "zlib.h" #include "zlib.h"
int ReadFileMemory(const char* filename,long* plFileSize,void** pFilePtr)
{ void MyDoMinus64(LARGE_INTEGER *R,LARGE_INTEGER A,LARGE_INTEGER B)
FILE* stream; {
void* ptr; R->HighPart = A.HighPart - B.HighPart;
int retVal=1; if (A.LowPart >= B.LowPart)
stream=fopen(filename, "rb"); R->LowPart = A.LowPart - B.LowPart;
if (stream==NULL) else
return 0; {
R->LowPart = A.LowPart - B.LowPart;
fseek(stream,0,SEEK_END); R->HighPart --;
}
*plFileSize=ftell(stream); }
fseek(stream,0,SEEK_SET);
ptr=malloc((*plFileSize)+1); #ifdef _AMD64_
if (ptr==NULL) unsigned _int64 myrdtsc();
retVal=0; void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64)
else {
{ // printf("rdtsc = %I64x\n",myrdtsc());
if (fread(ptr, 1, *plFileSize,stream) != (*plFileSize)) pbeginTime64->QuadPart=myrdtsc();
retVal=0; }
}
fclose(stream); LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf)
*pFilePtr=ptr; {
return retVal; LARGE_INTEGER LIres;
} unsigned _int64 res=myrdtsc()-((unsigned _int64)(beginTime64.QuadPart));
LIres.QuadPart=res;
int main(int argc, char *argv[]) // printf("rdtsc = %I64x\n",myrdtsc());
{ return LIres;
int BlockSizeCompress=0x8000; }
int BlockSizeUncompress=0x8000; #else
int cprLevel=Z_DEFAULT_COMPRESSION ; void myGetRDTSC32(LARGE_INTEGER * pbeginTime64)
long lFileSize; {
unsigned char* FilePtr; DWORD dwEdx,dwEax;
long lBufferSizeCpr; _asm
long lBufferSizeUncpr; {
long lCompressedSize=0; rdtsc
unsigned char* CprPtr; mov dwEax,eax
unsigned char* UncprPtr; mov dwEdx,edx
long lSizeCpr,lSizeUncpr; }
DWORD dwGetTick; pbeginTime64->LowPart=dwEax;
pbeginTime64->HighPart=dwEdx;
if (argc<=1) }
{
printf("run TestZlib <File> [BlockSizeCompress] [BlockSizeUncompress] [compres. level]\n"); void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64)
return 0; {
} myGetRDTSC32(pbeginTime64);
}
if (ReadFileMemory(argv[1],&lFileSize,&FilePtr)==0)
{ LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf)
printf("error reading %s\n",argv[1]); {
return 1; LARGE_INTEGER LIres,endTime64;
} myGetRDTSC32(&endTime64);
else printf("file %s read, %u bytes\n",argv[1],lFileSize);
LIres.LowPart=LIres.HighPart=0;
if (argc>=3) MyDoMinus64(&LIres,endTime64,beginTime64);
BlockSizeCompress=atol(argv[2]); return LIres;
}
if (argc>=4) #endif
BlockSizeUncompress=atol(argv[3]);
if (argc>=5) void BeginCountPerfCounter(LARGE_INTEGER * pbeginTime64,BOOL fComputeTimeQueryPerf)
cprLevel=(int)atol(argv[4]); {
if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(pbeginTime64)))
lBufferSizeCpr = lFileSize + (lFileSize/0x10) + 0x200; {
lBufferSizeUncpr = lBufferSizeCpr; pbeginTime64->LowPart = GetTickCount();
pbeginTime64->HighPart = 0;
CprPtr=(unsigned char*)malloc(lBufferSizeCpr + BlockSizeCompress); }
UncprPtr=(unsigned char*)malloc(lBufferSizeUncpr + BlockSizeUncompress); }
dwGetTick=GetTickCount(); DWORD GetMsecSincePerfCounter(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf)
{ {
z_stream zcpr; LARGE_INTEGER endTime64,ticksPerSecond,ticks;
int ret=Z_OK; DWORDLONG ticksShifted,tickSecShifted;
long lOrigToDo = lFileSize; DWORD dwLog=16+0;
long lOrigDone = 0; DWORD dwRet;
int step=0; if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(&endTime64)))
memset(&zcpr,0,sizeof(z_stream)); dwRet = (GetTickCount() - beginTime64.LowPart)*1;
deflateInit(&zcpr,cprLevel); else
{
zcpr.next_in = FilePtr; MyDoMinus64(&ticks,endTime64,beginTime64);
zcpr.next_out = CprPtr; QueryPerformanceFrequency(&ticksPerSecond);
do {
{ ticksShifted = Int64ShrlMod32(*(DWORDLONG*)&ticks,dwLog);
long all_read_before = zcpr.total_in; tickSecShifted = Int64ShrlMod32(*(DWORDLONG*)&ticksPerSecond,dwLog);
zcpr.avail_in = min(lOrigToDo,BlockSizeCompress);
zcpr.avail_out = BlockSizeCompress; }
ret=deflate(&zcpr,(zcpr.avail_in==lOrigToDo) ? Z_FINISH : Z_SYNC_FLUSH);
lOrigDone += (zcpr.total_in-all_read_before); dwRet = (DWORD)((((DWORD)ticksShifted)*1000)/(DWORD)(tickSecShifted));
lOrigToDo -= (zcpr.total_in-all_read_before); dwRet *=1;
step++; }
} while (ret==Z_OK); return dwRet;
}
lSizeCpr=zcpr.total_out;
deflateEnd(&zcpr); int ReadFileMemory(const char* filename,long* plFileSize,void** pFilePtr)
dwGetTick=GetTickCount()-dwGetTick; {
printf("total compress size = %u, in %u step\n",lSizeCpr,step); FILE* stream;
printf("time = %u msec = %f sec\n\n",dwGetTick,dwGetTick/(double)1000.); void* ptr;
} int retVal=1;
stream=fopen(filename, "rb");
dwGetTick=GetTickCount(); if (stream==NULL)
{ return 0;
z_stream zcpr;
int ret=Z_OK; fseek(stream,0,SEEK_END);
long lOrigToDo = lSizeCpr;
long lOrigDone = 0; *plFileSize=ftell(stream);
int step=0; fseek(stream,0,SEEK_SET);
memset(&zcpr,0,sizeof(z_stream)); ptr=malloc((*plFileSize)+1);
inflateInit(&zcpr); if (ptr==NULL)
retVal=0;
zcpr.next_in = CprPtr; else
zcpr.next_out = UncprPtr; {
if (fread(ptr, 1, *plFileSize,stream) != (*plFileSize))
retVal=0;
do }
{ fclose(stream);
long all_read_before = zcpr.total_in; *pFilePtr=ptr;
zcpr.avail_in = min(lOrigToDo,BlockSizeUncompress); return retVal;
zcpr.avail_out = BlockSizeUncompress; }
ret=inflate(&zcpr,Z_SYNC_FLUSH);
lOrigDone += (zcpr.total_in-all_read_before); int main(int argc, char *argv[])
lOrigToDo -= (zcpr.total_in-all_read_before); {
step++; int BlockSizeCompress=0x8000;
} while (ret==Z_OK); int BlockSizeUncompress=0x8000;
int cprLevel=Z_DEFAULT_COMPRESSION ;
lSizeUncpr=zcpr.total_out; long lFileSize;
inflateEnd(&zcpr); unsigned char* FilePtr;
dwGetTick=GetTickCount()-dwGetTick; long lBufferSizeCpr;
printf("total uncompress size = %u, in %u step\n",lSizeUncpr,step); long lBufferSizeUncpr;
printf("time = %u msec = %f sec\n\n",dwGetTick,dwGetTick/(double)1000.); long lCompressedSize=0;
} unsigned char* CprPtr;
unsigned char* UncprPtr;
if (lSizeUncpr==lFileSize) long lSizeCpr,lSizeUncpr;
{ DWORD dwGetTick,dwMsecQP;
if (memcmp(FilePtr,UncprPtr,lFileSize)==0) LARGE_INTEGER li_qp,li_rdtsc,dwResRdtsc;
printf("compare ok\n");
if (argc<=1)
} {
printf("run TestZlib <File> [BlockSizeCompress] [BlockSizeUncompress] [compres. level]\n");
return 0; return 0;
}
}
if (ReadFileMemory(argv[1],&lFileSize,&FilePtr)==0)
{
printf("error reading %s\n",argv[1]);
return 1;
}
else printf("file %s read, %u bytes\n",argv[1],lFileSize);
if (argc>=3)
BlockSizeCompress=atol(argv[2]);
if (argc>=4)
BlockSizeUncompress=atol(argv[3]);
if (argc>=5)
cprLevel=(int)atol(argv[4]);
lBufferSizeCpr = lFileSize + (lFileSize/0x10) + 0x200;
lBufferSizeUncpr = lBufferSizeCpr;
CprPtr=(unsigned char*)malloc(lBufferSizeCpr + BlockSizeCompress);
BeginCountPerfCounter(&li_qp,TRUE);
dwGetTick=GetTickCount();
BeginCountRdtsc(&li_rdtsc);
{
z_stream zcpr;
int ret=Z_OK;
long lOrigToDo = lFileSize;
long lOrigDone = 0;
int step=0;
memset(&zcpr,0,sizeof(z_stream));
deflateInit(&zcpr,cprLevel);
zcpr.next_in = FilePtr;
zcpr.next_out = CprPtr;
do
{
long all_read_before = zcpr.total_in;
zcpr.avail_in = min(lOrigToDo,BlockSizeCompress);
zcpr.avail_out = BlockSizeCompress;
ret=deflate(&zcpr,(zcpr.avail_in==lOrigToDo) ? Z_FINISH : Z_SYNC_FLUSH);
lOrigDone += (zcpr.total_in-all_read_before);
lOrigToDo -= (zcpr.total_in-all_read_before);
step++;
} while (ret==Z_OK);
lSizeCpr=zcpr.total_out;
deflateEnd(&zcpr);
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("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();
BeginCountRdtsc(&li_rdtsc);
{
z_stream zcpr;
int ret=Z_OK;
long lOrigToDo = lSizeCpr;
long lOrigDone = 0;
int step=0;
memset(&zcpr,0,sizeof(z_stream));
inflateInit(&zcpr);
zcpr.next_in = CprPtr;
zcpr.next_out = UncprPtr;
do
{
long all_read_before = zcpr.total_in;
zcpr.avail_in = min(lOrigToDo,BlockSizeUncompress);
zcpr.avail_out = BlockSizeUncompress;
ret=inflate(&zcpr,Z_SYNC_FLUSH);
lOrigDone += (zcpr.total_in-all_read_before);
lOrigToDo -= (zcpr.total_in-all_read_before);
step++;
} while (ret==Z_OK);
lSizeUncpr=zcpr.total_out;
inflateEnd(&zcpr);
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("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 (memcmp(FilePtr,UncprPtr,lFileSize)==0)
printf("compare ok\n");
}
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>

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,2 FILEVERSION 1,2,2,3
PRODUCTVERSION 1,2,2,2 PRODUCTVERSION 1,2,2,3
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.2\0" VALUE "FileVersion", "1.2.2.3\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"

View File

@@ -1,5 +1,5 @@
/* crc32.c -- compute the CRC-32 of a data stream /* crc32.c -- compute the CRC-32 of a data stream
* 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
* *
* 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
@@ -273,7 +273,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;
@@ -313,7 +313,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;

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.2 Copyright 1995-2004 Jean-loup Gailly "; " deflate 1.2.2.3 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
@@ -334,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;
@@ -452,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.
@@ -986,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

View File

@@ -4,6 +4,13 @@ fitblk.c
compress just enough input to nearly fill a requested output size compress just enough input to nearly fill a requested output size
- zlib isn't designed to do this, but fitblk does it anyway - 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 gzappend.c
append to a gzip file append to a gzip file
- illustrates the use of the Z_BLOCK flush parameter for inflate() - illustrates the use of the Z_BLOCK flush parameter for inflate()
@@ -27,3 +34,4 @@ zlib_how.html
zpipe.c zpipe.c
reads and writes zlib streams from stdin to stdout reads and writes zlib streams from stdin to stdout
- illustrates the proper use of deflate() and inflate() - illustrates the proper use of deflate() and inflate()
- deeply commented in zlib_how.html (see above)

692
examples/gun.c Normal file
View File

@@ -0,0 +1,692 @@
/* 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.2 20 March 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
*/
/*
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 = "unknown lzw flags set";
return Z_DATA_ERROR;
}
max = flags & 0x1f;
if (max < 9 || max > 16) {
strm->msg = "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 = "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 = "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 = "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 = "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 = "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 = "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 = "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.2 (20 Mar 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;
}

View File

@@ -420,10 +420,11 @@ The output of <tt>inflate()</tt> is handled identically to that of <tt>deflate()
} }
</b></pre> </b></pre>
The inner <tt>do</tt>-loop ends when <tt>inflate()</tt> has no more output as indicated 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>. 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> <pre><b>
} while (strm.avail_out == 0); } while (strm.avail_out == 0);
assert(strm.avail_in == 0); /* all input will be used */
</b></pre><!-- --> </b></pre><!-- -->
The outer <tt>do</tt>-loop ends when <tt>inflate()</tt> reports that it has reached the 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 end of the input <em>zlib</em> stream, has completed the decompression and integrity

View File

@@ -7,6 +7,7 @@
1.1 8 Nov 2004 Add void casting for unused return values 1.1 8 Nov 2004 Add void casting for unused return values
Use switch statement for inflate() return values Use switch statement for inflate() return values
1.2 9 Nov 2004 Add assertions to document zlib guarantees 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 <stdio.h>
@@ -127,7 +128,6 @@ int inf(FILE *source, FILE *dest)
return Z_ERRNO; return Z_ERRNO;
} }
} while (strm.avail_out == 0); } while (strm.avail_out == 0);
assert(strm.avail_in == 0); /* all input will be used */
/* done when inflate() says it's done */ /* done when inflate() says it's done */
} while (ret != Z_STREAM_END); } while (ret != Z_STREAM_END);

29
gzio.c
View File

@@ -1,5 +1,5 @@
/* gzio.c -- IO on .gz files /* gzio.c -- IO on .gz files
* 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
* *
* Compile this file with -DNO_GZCOMPRESS to avoid the compression code. * Compile this file with -DNO_GZCOMPRESS to avoid the compression code.
@@ -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;
} }
@@ -902,6 +899,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
*/ */

View File

@@ -1,5 +1,5 @@
/* inflate.c -- zlib decompression /* inflate.c -- zlib decompression
* 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
*/ */
@@ -1334,11 +1334,15 @@ z_streamp source;
/* copy state */ /* copy state */
zmemcpy(dest, source, sizeof(z_stream)); zmemcpy(dest, source, sizeof(z_stream));
zmemcpy(copy, state, sizeof(struct inflate_state)); zmemcpy(copy, state, sizeof(struct inflate_state));
copy->lencode = copy->codes + (state->lencode - state->codes); if (state->lencode >= state->codes &&
copy->distcode = copy->codes + (state->distcode - state->codes); state->lencode <= state->codes + ENOUGH - 1)
{
copy->lencode = copy->codes + (state->lencode - 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); zmemcpy(window, state->window, (uInt)(1U << state->wbits));
copy->window = window; copy->window = window;
dest->state = (voidpf)copy; dest->state = (voidpf)copy;
return Z_OK; return Z_OK;

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.2 Copyright 1995-2004 Mark Adler "; " inflate 1.2.2.3 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, 72, 199}; 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 66, 71};
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,
@@ -262,7 +262,7 @@ unsigned short FAR *work;
drop = root; drop = root;
/* increment past last table */ /* increment past last table */
next += 1U << curr; next += (unsigned)(1U << curr);
/* determine length of next table */ /* determine length of next table */
curr = len - drop; curr = len - drop;

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-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
*/ */
@@ -295,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

@@ -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.2" install="/opt/lib/" user="root:bin" permission="644"/> <QPG:Add file="../libz.so.1.2.2.3" 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.2"/> <QPG:Add file="libz.so" install="/opt/lib/" component="dev" filetype="symlink" linkto="libz.so.1.2.2.3"/>
<QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.2.2.2"/> <QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.2.2.3"/>
<QPG:Add file="../libz.so.1.2.2.2" install="/opt/lib/" component="slib"/> <QPG:Add file="../libz.so.1.2.2.3" 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.2</QPM:ReleaseVersion> <QPM:ReleaseVersion>1.2.2.3</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>

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,2 FILEVERSION 1,2,2,3
PRODUCTVERSION 1,2,2,2 PRODUCTVERSION 1,2,2,3
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.2\0" VALUE "FileVersion", "1.2.2.3\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.2\0" VALUE "ProductVersion", "1.2.2.3\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

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
*/ */
@@ -68,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__)
# define WIN32 # ifndef 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
*/ */
@@ -68,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__)
# define WIN32 # ifndef 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__)

4
zlib.3
View File

@@ -1,4 +1,4 @@
.TH ZLIB 3 "30 December 2004" .TH ZLIB 3 "27 May 2005"
.SH NAME .SH NAME
zlib \- compression/decompression library zlib \- compression/decompression library
.SH SYNOPSIS .SH SYNOPSIS
@@ -133,7 +133,7 @@ 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.2 Version 1.2.2.3
Copyright (C) 1995-2004 Jean-loup Gailly (jloup@gzip.org) Copyright (C) 1995-2004 Jean-loup Gailly (jloup@gzip.org)
and Mark Adler (madler@alumni.caltech.edu). and Mark Adler (madler@alumni.caltech.edu).
.LP .LP

37
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.2, December 30th, 2004 version 1.2.2.3, May 27th, 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.2" #define ZLIB_VERSION "1.2.2.3"
#define ZLIB_VERNUM 0x1222 #define ZLIB_VERNUM 0x1223
/* /*
The 'zlib' compression library provides in-memory compression and The 'zlib' compression library provides in-memory compression and
@@ -556,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
@@ -622,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));
/* /*
@@ -703,7 +722,7 @@ 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
@@ -1185,6 +1204,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

10
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-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
*/ */
@@ -17,7 +17,9 @@
#include "zlib.h" #include "zlib.h"
#ifdef STDC #ifdef STDC
# include <stddef.h> # ifndef _WIN32_WCE
# include <stddef.h>
# endif
# include <string.h> # include <string.h>
# include <stdlib.h> # include <stdlib.h>
#endif #endif
@@ -32,7 +34,9 @@
# endif # endif
extern int errno; extern int errno;
#else #else
# include <errno.h> # ifndef _WIN32_WCE
# include <errno.h>
# endif
#endif #endif
#ifndef local #ifndef local