zlib 1.2.2.3
This commit is contained in:
parent
0484693e17
commit
6b8233bfe0
21
ChangeLog
21
ChangeLog
@ -1,6 +1,27 @@
|
||||
|
||||
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)
|
||||
- Replace structure assignments in deflate.c and inflate.c with zmemcpy to
|
||||
avoid implicit memcpy calls (portability for no-library compilation)
|
||||
|
2
Makefile
2
Makefile
@ -30,7 +30,7 @@ CPP=$(CC) -E
|
||||
|
||||
LIBS=libz.a
|
||||
SHAREDLIB=libz.so
|
||||
SHAREDLIBV=libz.so.1.2.2.2
|
||||
SHAREDLIBV=libz.so.1.2.2.3
|
||||
SHAREDLIBM=libz.so.1
|
||||
|
||||
AR=ar rc
|
||||
|
@ -30,7 +30,7 @@ CPP=$(CC) -E
|
||||
|
||||
LIBS=libz.a
|
||||
SHAREDLIB=libz.so
|
||||
SHAREDLIBV=libz.so.1.2.2.2
|
||||
SHAREDLIBV=libz.so.1.2.2.3
|
||||
SHAREDLIBM=libz.so.1
|
||||
|
||||
AR=ar rc
|
||||
|
4
README
4
README
@ -1,6 +1,6 @@
|
||||
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
|
||||
(Request for Comments) 1950 to 1952 in the files
|
||||
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
|
||||
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".
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
* ZLIB.INC - Interface to the general purpose compression library
|
||||
*
|
||||
* ILE RPG400 version by Patrick Monnerat, DATASPHERE.
|
||||
* Version 1.2.2.2
|
||||
* Version 1.2.2.3
|
||||
*
|
||||
*
|
||||
* WARNING:
|
||||
@ -20,8 +20,12 @@
|
||||
* Constants
|
||||
**************************************************************************
|
||||
*
|
||||
D ZLIB_VERSION C '1.2.2.2' Header's version
|
||||
D ZLIB_VERNUM C X'1222'
|
||||
* Versioning information.
|
||||
*
|
||||
D ZLIB_VERSION C '1.2.2.3'
|
||||
D ZLIB_VERNUM C X'1223'
|
||||
*
|
||||
* Other equates.
|
||||
*
|
||||
D Z_NO_FLUSH C 0
|
||||
D Z_SYNC_FLUSH C 2
|
||||
|
@ -42,6 +42,10 @@ masm686/ by Dan Higdon <hdan@kinesoft.com>
|
||||
and Chuck Walbourn <chuckw@kinesoft.com>
|
||||
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>
|
||||
x86 asm code to replace longest_match() and inflate_fast(),
|
||||
for Visual C++ and MASM
|
||||
|
@ -1,354 +1,364 @@
|
||||
/* match.s -- Pentium-optimized version of longest_match()
|
||||
* Written for zlib 1.1.2
|
||||
* Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License.
|
||||
*/
|
||||
|
||||
#ifndef NO_UNDERLINE
|
||||
#define match_init _match_init
|
||||
#define longest_match _longest_match
|
||||
#endif
|
||||
|
||||
#define MAX_MATCH (258)
|
||||
#define MIN_MATCH (3)
|
||||
#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
|
||||
#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7)
|
||||
|
||||
/* stack frame offsets */
|
||||
|
||||
#define wmask 0 /* local copy of s->wmask */
|
||||
#define window 4 /* local copy of s->window */
|
||||
#define windowbestlen 8 /* s->window + bestlen */
|
||||
#define chainlenscanend 12 /* high word: current chain len */
|
||||
/* low word: last bytes sought */
|
||||
#define scanstart 16 /* first two bytes of string */
|
||||
#define scanalign 20 /* dword-misalignment of string */
|
||||
#define nicematch 24 /* a good enough match size */
|
||||
#define bestlen 28 /* size of best match so far */
|
||||
#define scan 32 /* ptr to string wanting match */
|
||||
|
||||
#define LocalVarsSize (36)
|
||||
/* saved ebx 36 */
|
||||
/* saved edi 40 */
|
||||
/* saved esi 44 */
|
||||
/* saved ebp 48 */
|
||||
/* return address 52 */
|
||||
#define deflatestate 56 /* the function arguments */
|
||||
#define curmatch 60
|
||||
|
||||
/* 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.)
|
||||
*/
|
||||
#define dsWSize 36
|
||||
#define dsWMask 44
|
||||
#define dsWindow 48
|
||||
#define dsPrev 56
|
||||
#define dsMatchLen 88
|
||||
#define dsPrevMatch 92
|
||||
#define dsStrStart 100
|
||||
#define dsMatchStart 104
|
||||
#define dsLookahead 108
|
||||
#define dsPrevLen 112
|
||||
#define dsMaxChainLen 116
|
||||
#define dsGoodMatch 132
|
||||
#define dsNiceMatch 136
|
||||
|
||||
|
||||
.file "match.S"
|
||||
|
||||
.globl match_init, longest_match
|
||||
|
||||
.text
|
||||
|
||||
/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
|
||||
|
||||
longest_match:
|
||||
|
||||
/* Save registers that the compiler may be using, and adjust %esp to */
|
||||
/* make room for our stack frame. */
|
||||
|
||||
pushl %ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %ebx
|
||||
subl $LocalVarsSize, %esp
|
||||
|
||||
/* Retrieve the function arguments. %ecx 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). */
|
||||
|
||||
movl deflatestate(%esp), %edx
|
||||
movl curmatch(%esp), %ecx
|
||||
|
||||
/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */
|
||||
|
||||
movl dsNiceMatch(%edx), %eax
|
||||
movl dsLookahead(%edx), %ebx
|
||||
cmpl %eax, %ebx
|
||||
jl LookaheadLess
|
||||
movl %eax, %ebx
|
||||
LookaheadLess: movl %ebx, nicematch(%esp)
|
||||
|
||||
/* register Bytef *scan = s->window + s->strstart; */
|
||||
|
||||
movl dsWindow(%edx), %esi
|
||||
movl %esi, window(%esp)
|
||||
movl dsStrStart(%edx), %ebp
|
||||
lea (%esi,%ebp), %edi
|
||||
movl %edi, scan(%esp)
|
||||
|
||||
/* Determine how many bytes the scan ptr is off from being */
|
||||
/* dword-aligned. */
|
||||
|
||||
movl %edi, %eax
|
||||
negl %eax
|
||||
andl $3, %eax
|
||||
movl %eax, scanalign(%esp)
|
||||
|
||||
/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
|
||||
/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
|
||||
|
||||
movl dsWSize(%edx), %eax
|
||||
subl $MIN_LOOKAHEAD, %eax
|
||||
subl %eax, %ebp
|
||||
jg LimitPositive
|
||||
xorl %ebp, %ebp
|
||||
LimitPositive:
|
||||
|
||||
/* 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 dsMaxChainLen(%edx), %ebx
|
||||
jl LastMatchGood
|
||||
shrl $2, %ebx
|
||||
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 scanend */
|
||||
/* scanend value, which it will always accompany. */
|
||||
|
||||
decl %ebx
|
||||
shll $16, %ebx
|
||||
|
||||
/* int best_len = s->prev_length; */
|
||||
|
||||
movl dsPrevLen(%edx), %eax
|
||||
movl %eax, bestlen(%esp)
|
||||
|
||||
/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
|
||||
|
||||
addl %eax, %esi
|
||||
movl %esi, windowbestlen(%esp)
|
||||
|
||||
/* register ush scan_start = *(ushf*)scan; */
|
||||
/* register ush scan_end = *(ushf*)(scan+best_len-1); */
|
||||
|
||||
movw (%edi), %bx
|
||||
movw %bx, scanstart(%esp)
|
||||
movw -1(%edi,%eax), %bx
|
||||
movl %ebx, chainlenscanend(%esp)
|
||||
|
||||
/* Posf *prev = s->prev; */
|
||||
/* uInt wmask = s->w_mask; */
|
||||
|
||||
movl dsPrev(%edx), %edi
|
||||
movl dsWMask(%edx), %edx
|
||||
mov %edx, wmask(%esp)
|
||||
|
||||
/* Jump into the main loop. */
|
||||
|
||||
jmp LoopEntry
|
||||
|
||||
.balign 16
|
||||
|
||||
/* 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 = chainlenscanend - i.e., ((chainlen << 16) | scanend)
|
||||
* %ecx = curmatch
|
||||
* %edx = curmatch & wmask
|
||||
* %esi = windowbestlen - i.e., (window + bestlen)
|
||||
* %edi = prev
|
||||
* %ebp = limit
|
||||
*
|
||||
* Two optimization notes on the choice of instructions:
|
||||
*
|
||||
* The first instruction uses a 16-bit address, which costs an extra,
|
||||
* unpairable cycle. This is cheaper than doing a 32-bit access and
|
||||
* zeroing the high word, due to the 3-cycle misalignment penalty which
|
||||
* 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
|
||||
* L1 cache.
|
||||
*
|
||||
* 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
|
||||
* match string with two 8-bit loads. The instructions that test the
|
||||
* word at the beginning of the match string, however, are executed
|
||||
* much less frequently, and there it was cheaper to use 16-bit
|
||||
* instructions, which avoided the necessity of saving off and
|
||||
* subsequently reloading one of the other registers.
|
||||
*/
|
||||
LookupLoop:
|
||||
/* 1 U & V */
|
||||
movw (%edi,%edx,2), %cx /* 2 U pipe */
|
||||
movl wmask(%esp), %edx /* 2 V pipe */
|
||||
cmpl %ebp, %ecx /* 3 U pipe */
|
||||
jbe LeaveNow /* 3 V pipe */
|
||||
subl $0x00010000, %ebx /* 4 U pipe */
|
||||
js LeaveNow /* 4 V pipe */
|
||||
LoopEntry: movb -1(%esi,%ecx), %al /* 5 U pipe */
|
||||
andl %ecx, %edx /* 5 V pipe */
|
||||
cmpb %bl, %al /* 6 U pipe */
|
||||
jnz LookupLoop /* 6 V pipe */
|
||||
movb (%esi,%ecx), %ah
|
||||
cmpb %bh, %ah
|
||||
jnz LookupLoop
|
||||
movl window(%esp), %eax
|
||||
movw (%eax,%ecx), %ax
|
||||
cmpw scanstart(%esp), %ax
|
||||
jnz LookupLoop
|
||||
|
||||
/* Store the current value of chainlen. */
|
||||
|
||||
movl %ebx, chainlenscanend(%esp)
|
||||
|
||||
/* 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). */
|
||||
|
||||
movl window(%esp), %esi
|
||||
movl scan(%esp), %edi
|
||||
addl %ecx, %esi
|
||||
movl scanalign(%esp), %eax
|
||||
movl $(-MAX_MATCH_8), %edx
|
||||
lea MAX_MATCH_8(%edi,%eax), %edi
|
||||
lea MAX_MATCH_8(%esi,%eax), %esi
|
||||
|
||||
/* 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:
|
||||
movl (%esi,%edx), %eax
|
||||
movl (%edi,%edx), %ebx
|
||||
xorl %ebx, %eax
|
||||
jnz LeaveLoopCmps
|
||||
movl 4(%esi,%edx), %eax
|
||||
movl 4(%edi,%edx), %ebx
|
||||
xorl %ebx, %eax
|
||||
jnz LeaveLoopCmps4
|
||||
addl $8, %edx
|
||||
jnz LoopCmps
|
||||
jmp LenMaximum
|
||||
LeaveLoopCmps4: addl $4, %edx
|
||||
LeaveLoopCmps: testl $0x0000FFFF, %eax
|
||||
jnz LenLower
|
||||
addl $2, %edx
|
||||
shrl $16, %eax
|
||||
LenLower: subb $1, %al
|
||||
adcl $0, %edx
|
||||
|
||||
/* 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 (%edi,%edx), %eax
|
||||
movl scan(%esp), %edi
|
||||
subl %edi, %eax
|
||||
cmpl $MAX_MATCH, %eax
|
||||
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. */
|
||||
|
||||
movl deflatestate(%esp), %edx
|
||||
movl bestlen(%esp), %ebx
|
||||
cmpl %ebx, %eax
|
||||
jg LongerMatch
|
||||
movl chainlenscanend(%esp), %ebx
|
||||
movl windowbestlen(%esp), %esi
|
||||
movl dsPrev(%edx), %edi
|
||||
movl wmask(%esp), %edx
|
||||
andl %ecx, %edx
|
||||
jmp LookupLoop
|
||||
|
||||
/* s->match_start = cur_match; */
|
||||
/* best_len = len; */
|
||||
/* if (len >= nice_match) break; */
|
||||
/* scan_end = *(ushf*)(scan+best_len-1); */
|
||||
|
||||
LongerMatch: movl nicematch(%esp), %ebx
|
||||
movl %eax, bestlen(%esp)
|
||||
movl %ecx, dsMatchStart(%edx)
|
||||
cmpl %ebx, %eax
|
||||
jge LeaveNow
|
||||
movl window(%esp), %esi
|
||||
addl %eax, %esi
|
||||
movl %esi, windowbestlen(%esp)
|
||||
movl chainlenscanend(%esp), %ebx
|
||||
movw -1(%edi,%eax), %bx
|
||||
movl dsPrev(%edx), %edi
|
||||
movl %ebx, chainlenscanend(%esp)
|
||||
movl wmask(%esp), %edx
|
||||
andl %ecx, %edx
|
||||
jmp LookupLoop
|
||||
|
||||
/* Accept the current string, with the maximum possible length. */
|
||||
|
||||
LenMaximum: movl deflatestate(%esp), %edx
|
||||
movl $MAX_MATCH, bestlen(%esp)
|
||||
movl %ecx, dsMatchStart(%edx)
|
||||
|
||||
/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
|
||||
/* return s->lookahead; */
|
||||
|
||||
LeaveNow:
|
||||
movl deflatestate(%esp), %edx
|
||||
movl bestlen(%esp), %ebx
|
||||
movl dsLookahead(%edx), %eax
|
||||
cmpl %eax, %ebx
|
||||
jg LookaheadRet
|
||||
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
|
||||
/* match.s -- Pentium-optimized version of longest_match()
|
||||
* Written for zlib 1.1.2
|
||||
* Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License.
|
||||
*/
|
||||
|
||||
#ifndef NO_UNDERLINE
|
||||
#define match_init _match_init
|
||||
#define longest_match _longest_match
|
||||
#endif
|
||||
|
||||
#define MAX_MATCH (258)
|
||||
#define MIN_MATCH (3)
|
||||
#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
|
||||
#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7)
|
||||
|
||||
/* stack frame offsets */
|
||||
|
||||
#define wmask 0 /* local copy of s->wmask */
|
||||
#define window 4 /* local copy of s->window */
|
||||
#define windowbestlen 8 /* s->window + bestlen */
|
||||
#define chainlenscanend 12 /* high word: current chain len */
|
||||
/* low word: last bytes sought */
|
||||
#define scanstart 16 /* first two bytes of string */
|
||||
#define scanalign 20 /* dword-misalignment of string */
|
||||
#define nicematch 24 /* a good enough match size */
|
||||
#define bestlen 28 /* size of best match so far */
|
||||
#define scan 32 /* ptr to string wanting match */
|
||||
|
||||
#define LocalVarsSize (36)
|
||||
/* saved ebx 36 */
|
||||
/* saved edi 40 */
|
||||
/* saved esi 44 */
|
||||
/* saved ebp 48 */
|
||||
/* return address 52 */
|
||||
#define deflatestate 56 /* the function arguments */
|
||||
#define curmatch 60
|
||||
|
||||
/* 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").
|
||||
*/
|
||||
|
||||
#define zlib1222add (8)
|
||||
|
||||
#define dsWSize (36+zlib1222add)
|
||||
#define dsWMask (44+zlib1222add)
|
||||
#define dsWindow (48+zlib1222add)
|
||||
#define dsPrev (56+zlib1222add)
|
||||
#define dsMatchLen (88+zlib1222add)
|
||||
#define dsPrevMatch (92+zlib1222add)
|
||||
#define dsStrStart (100+zlib1222add)
|
||||
#define dsMatchStart (104+zlib1222add)
|
||||
#define dsLookahead (108+zlib1222add)
|
||||
#define dsPrevLen (112+zlib1222add)
|
||||
#define dsMaxChainLen (116+zlib1222add)
|
||||
#define dsGoodMatch (132+zlib1222add)
|
||||
#define dsNiceMatch (136+zlib1222add)
|
||||
|
||||
|
||||
.file "match.S"
|
||||
|
||||
.globl match_init, longest_match
|
||||
|
||||
.text
|
||||
|
||||
/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
|
||||
|
||||
longest_match:
|
||||
|
||||
/* Save registers that the compiler may be using, and adjust %esp to */
|
||||
/* make room for our stack frame. */
|
||||
|
||||
pushl %ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %ebx
|
||||
subl $LocalVarsSize, %esp
|
||||
|
||||
/* Retrieve the function arguments. %ecx 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). */
|
||||
|
||||
movl deflatestate(%esp), %edx
|
||||
movl curmatch(%esp), %ecx
|
||||
|
||||
/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */
|
||||
|
||||
movl dsNiceMatch(%edx), %eax
|
||||
movl dsLookahead(%edx), %ebx
|
||||
cmpl %eax, %ebx
|
||||
jl LookaheadLess
|
||||
movl %eax, %ebx
|
||||
LookaheadLess: movl %ebx, nicematch(%esp)
|
||||
|
||||
/* register Bytef *scan = s->window + s->strstart; */
|
||||
|
||||
movl dsWindow(%edx), %esi
|
||||
movl %esi, window(%esp)
|
||||
movl dsStrStart(%edx), %ebp
|
||||
lea (%esi,%ebp), %edi
|
||||
movl %edi, scan(%esp)
|
||||
|
||||
/* Determine how many bytes the scan ptr is off from being */
|
||||
/* dword-aligned. */
|
||||
|
||||
movl %edi, %eax
|
||||
negl %eax
|
||||
andl $3, %eax
|
||||
movl %eax, scanalign(%esp)
|
||||
|
||||
/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
|
||||
/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
|
||||
|
||||
movl dsWSize(%edx), %eax
|
||||
subl $MIN_LOOKAHEAD, %eax
|
||||
subl %eax, %ebp
|
||||
jg LimitPositive
|
||||
xorl %ebp, %ebp
|
||||
LimitPositive:
|
||||
|
||||
/* 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 dsMaxChainLen(%edx), %ebx
|
||||
jl LastMatchGood
|
||||
shrl $2, %ebx
|
||||
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 scanend */
|
||||
/* scanend value, which it will always accompany. */
|
||||
|
||||
decl %ebx
|
||||
shll $16, %ebx
|
||||
|
||||
/* int best_len = s->prev_length; */
|
||||
|
||||
movl dsPrevLen(%edx), %eax
|
||||
movl %eax, bestlen(%esp)
|
||||
|
||||
/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
|
||||
|
||||
addl %eax, %esi
|
||||
movl %esi, windowbestlen(%esp)
|
||||
|
||||
/* register ush scan_start = *(ushf*)scan; */
|
||||
/* register ush scan_end = *(ushf*)(scan+best_len-1); */
|
||||
|
||||
movw (%edi), %bx
|
||||
movw %bx, scanstart(%esp)
|
||||
movw -1(%edi,%eax), %bx
|
||||
movl %ebx, chainlenscanend(%esp)
|
||||
|
||||
/* Posf *prev = s->prev; */
|
||||
/* uInt wmask = s->w_mask; */
|
||||
|
||||
movl dsPrev(%edx), %edi
|
||||
movl dsWMask(%edx), %edx
|
||||
mov %edx, wmask(%esp)
|
||||
|
||||
/* Jump into the main loop. */
|
||||
|
||||
jmp LoopEntry
|
||||
|
||||
.balign 16
|
||||
|
||||
/* 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 = chainlenscanend - i.e., ((chainlen << 16) | scanend)
|
||||
* %ecx = curmatch
|
||||
* %edx = curmatch & wmask
|
||||
* %esi = windowbestlen - i.e., (window + bestlen)
|
||||
* %edi = prev
|
||||
* %ebp = limit
|
||||
*
|
||||
* Two optimization notes on the choice of instructions:
|
||||
*
|
||||
* The first instruction uses a 16-bit address, which costs an extra,
|
||||
* unpairable cycle. This is cheaper than doing a 32-bit access and
|
||||
* zeroing the high word, due to the 3-cycle misalignment penalty which
|
||||
* 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
|
||||
* L1 cache.
|
||||
*
|
||||
* 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
|
||||
* match string with two 8-bit loads. The instructions that test the
|
||||
* word at the beginning of the match string, however, are executed
|
||||
* much less frequently, and there it was cheaper to use 16-bit
|
||||
* instructions, which avoided the necessity of saving off and
|
||||
* subsequently reloading one of the other registers.
|
||||
*/
|
||||
LookupLoop:
|
||||
/* 1 U & V */
|
||||
movw (%edi,%edx,2), %cx /* 2 U pipe */
|
||||
movl wmask(%esp), %edx /* 2 V pipe */
|
||||
cmpl %ebp, %ecx /* 3 U pipe */
|
||||
jbe LeaveNow /* 3 V pipe */
|
||||
subl $0x00010000, %ebx /* 4 U pipe */
|
||||
js LeaveNow /* 4 V pipe */
|
||||
LoopEntry: movb -1(%esi,%ecx), %al /* 5 U pipe */
|
||||
andl %ecx, %edx /* 5 V pipe */
|
||||
cmpb %bl, %al /* 6 U pipe */
|
||||
jnz LookupLoop /* 6 V pipe */
|
||||
movb (%esi,%ecx), %ah
|
||||
cmpb %bh, %ah
|
||||
jnz LookupLoop
|
||||
movl window(%esp), %eax
|
||||
movw (%eax,%ecx), %ax
|
||||
cmpw scanstart(%esp), %ax
|
||||
jnz LookupLoop
|
||||
|
||||
/* Store the current value of chainlen. */
|
||||
|
||||
movl %ebx, chainlenscanend(%esp)
|
||||
|
||||
/* 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). */
|
||||
|
||||
movl window(%esp), %esi
|
||||
movl scan(%esp), %edi
|
||||
addl %ecx, %esi
|
||||
movl scanalign(%esp), %eax
|
||||
movl $(-MAX_MATCH_8), %edx
|
||||
lea MAX_MATCH_8(%edi,%eax), %edi
|
||||
lea MAX_MATCH_8(%esi,%eax), %esi
|
||||
|
||||
/* 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:
|
||||
movl (%esi,%edx), %eax
|
||||
movl (%edi,%edx), %ebx
|
||||
xorl %ebx, %eax
|
||||
jnz LeaveLoopCmps
|
||||
movl 4(%esi,%edx), %eax
|
||||
movl 4(%edi,%edx), %ebx
|
||||
xorl %ebx, %eax
|
||||
jnz LeaveLoopCmps4
|
||||
addl $8, %edx
|
||||
jnz LoopCmps
|
||||
jmp LenMaximum
|
||||
LeaveLoopCmps4: addl $4, %edx
|
||||
LeaveLoopCmps: testl $0x0000FFFF, %eax
|
||||
jnz LenLower
|
||||
addl $2, %edx
|
||||
shrl $16, %eax
|
||||
LenLower: subb $1, %al
|
||||
adcl $0, %edx
|
||||
|
||||
/* 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 (%edi,%edx), %eax
|
||||
movl scan(%esp), %edi
|
||||
subl %edi, %eax
|
||||
cmpl $MAX_MATCH, %eax
|
||||
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. */
|
||||
|
||||
movl deflatestate(%esp), %edx
|
||||
movl bestlen(%esp), %ebx
|
||||
cmpl %ebx, %eax
|
||||
jg LongerMatch
|
||||
movl chainlenscanend(%esp), %ebx
|
||||
movl windowbestlen(%esp), %esi
|
||||
movl dsPrev(%edx), %edi
|
||||
movl wmask(%esp), %edx
|
||||
andl %ecx, %edx
|
||||
jmp LookupLoop
|
||||
|
||||
/* s->match_start = cur_match; */
|
||||
/* best_len = len; */
|
||||
/* if (len >= nice_match) break; */
|
||||
/* scan_end = *(ushf*)(scan+best_len-1); */
|
||||
|
||||
LongerMatch: movl nicematch(%esp), %ebx
|
||||
movl %eax, bestlen(%esp)
|
||||
movl %ecx, dsMatchStart(%edx)
|
||||
cmpl %ebx, %eax
|
||||
jge LeaveNow
|
||||
movl window(%esp), %esi
|
||||
addl %eax, %esi
|
||||
movl %esi, windowbestlen(%esp)
|
||||
movl chainlenscanend(%esp), %ebx
|
||||
movw -1(%edi,%eax), %bx
|
||||
movl dsPrev(%edx), %edi
|
||||
movl %ebx, chainlenscanend(%esp)
|
||||
movl wmask(%esp), %edx
|
||||
andl %ecx, %edx
|
||||
jmp LookupLoop
|
||||
|
||||
/* Accept the current string, with the maximum possible length. */
|
||||
|
||||
LenMaximum: movl deflatestate(%esp), %edx
|
||||
movl $MAX_MATCH, bestlen(%esp)
|
||||
movl %ecx, dsMatchStart(%edx)
|
||||
|
||||
/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
|
||||
/* return s->lookahead; */
|
||||
|
||||
LeaveNow:
|
||||
movl deflatestate(%esp), %edx
|
||||
movl bestlen(%esp), %ebx
|
||||
movl dsLookahead(%edx), %eax
|
||||
cmpl %eax, %ebx
|
||||
jg LookaheadRet
|
||||
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
|
||||
|
@ -1,327 +1,329 @@
|
||||
/* match.s -- Pentium-Pro-optimized version of longest_match()
|
||||
* Written for zlib 1.1.2
|
||||
* Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License.
|
||||
*/
|
||||
|
||||
#ifndef NO_UNDERLINE
|
||||
#define match_init _match_init
|
||||
#define longest_match _longest_match
|
||||
#endif
|
||||
|
||||
#define MAX_MATCH (258)
|
||||
#define MIN_MATCH (3)
|
||||
#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
|
||||
#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7)
|
||||
|
||||
/* stack frame offsets */
|
||||
|
||||
#define chainlenwmask 0 /* high word: current chain len */
|
||||
/* low word: s->wmask */
|
||||
#define window 4 /* local copy of s->window */
|
||||
#define windowbestlen 8 /* s->window + bestlen */
|
||||
#define scanstart 16 /* first two bytes of string */
|
||||
#define scanend 12 /* last two bytes of string */
|
||||
#define scanalign 20 /* dword-misalignment of string */
|
||||
#define nicematch 24 /* a good enough match size */
|
||||
#define bestlen 28 /* size of best match so far */
|
||||
#define scan 32 /* ptr to string wanting match */
|
||||
|
||||
#define LocalVarsSize (36)
|
||||
/* saved ebx 36 */
|
||||
/* saved edi 40 */
|
||||
/* saved esi 44 */
|
||||
/* saved ebp 48 */
|
||||
/* return address 52 */
|
||||
#define deflatestate 56 /* the function arguments */
|
||||
#define curmatch 60
|
||||
|
||||
/* 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.)
|
||||
*/
|
||||
#define dsWSize 36
|
||||
#define dsWMask 44
|
||||
#define dsWindow 48
|
||||
#define dsPrev 56
|
||||
#define dsMatchLen 88
|
||||
#define dsPrevMatch 92
|
||||
#define dsStrStart 100
|
||||
#define dsMatchStart 104
|
||||
#define dsLookahead 108
|
||||
#define dsPrevLen 112
|
||||
#define dsMaxChainLen 116
|
||||
#define dsGoodMatch 132
|
||||
#define dsNiceMatch 136
|
||||
|
||||
|
||||
.file "match.S"
|
||||
|
||||
.globl match_init, longest_match
|
||||
|
||||
.text
|
||||
|
||||
/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
|
||||
|
||||
longest_match:
|
||||
|
||||
/* Save registers that the compiler may be using, and adjust %esp to */
|
||||
/* make room for our stack frame. */
|
||||
|
||||
pushl %ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %ebx
|
||||
subl $LocalVarsSize, %esp
|
||||
|
||||
/* Retrieve the function arguments. %ecx 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). */
|
||||
|
||||
movl deflatestate(%esp), %edx
|
||||
movl curmatch(%esp), %ecx
|
||||
|
||||
/* uInt wmask = s->w_mask; */
|
||||
/* 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 dsWMask(%edx), %eax
|
||||
movl dsMaxChainLen(%edx), %ebx
|
||||
jl LastMatchGood
|
||||
shrl $2, %ebx
|
||||
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. */
|
||||
|
||||
decl %ebx
|
||||
shll $16, %ebx
|
||||
orl %eax, %ebx
|
||||
movl %ebx, chainlenwmask(%esp)
|
||||
|
||||
/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */
|
||||
|
||||
movl dsNiceMatch(%edx), %eax
|
||||
movl dsLookahead(%edx), %ebx
|
||||
cmpl %eax, %ebx
|
||||
jl LookaheadLess
|
||||
movl %eax, %ebx
|
||||
LookaheadLess: movl %ebx, nicematch(%esp)
|
||||
|
||||
/* register Bytef *scan = s->window + s->strstart; */
|
||||
|
||||
movl dsWindow(%edx), %esi
|
||||
movl %esi, window(%esp)
|
||||
movl dsStrStart(%edx), %ebp
|
||||
lea (%esi,%ebp), %edi
|
||||
movl %edi, scan(%esp)
|
||||
|
||||
/* Determine how many bytes the scan ptr is off from being */
|
||||
/* dword-aligned. */
|
||||
|
||||
movl %edi, %eax
|
||||
negl %eax
|
||||
andl $3, %eax
|
||||
movl %eax, scanalign(%esp)
|
||||
|
||||
/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
|
||||
/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
|
||||
|
||||
movl dsWSize(%edx), %eax
|
||||
subl $MIN_LOOKAHEAD, %eax
|
||||
subl %eax, %ebp
|
||||
jg LimitPositive
|
||||
xorl %ebp, %ebp
|
||||
LimitPositive:
|
||||
|
||||
/* int best_len = s->prev_length; */
|
||||
|
||||
movl dsPrevLen(%edx), %eax
|
||||
movl %eax, bestlen(%esp)
|
||||
|
||||
/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
|
||||
|
||||
addl %eax, %esi
|
||||
movl %esi, windowbestlen(%esp)
|
||||
|
||||
/* register ush scan_start = *(ushf*)scan; */
|
||||
/* register ush scan_end = *(ushf*)(scan+best_len-1); */
|
||||
/* Posf *prev = s->prev; */
|
||||
|
||||
movzwl (%edi), %ebx
|
||||
movl %ebx, scanstart(%esp)
|
||||
movzwl -1(%edi,%eax), %ebx
|
||||
movl %ebx, scanend(%esp)
|
||||
movl dsPrev(%edx), %edi
|
||||
|
||||
/* Jump into the main loop. */
|
||||
|
||||
movl chainlenwmask(%esp), %edx
|
||||
jmp LoopEntry
|
||||
|
||||
.balign 16
|
||||
|
||||
/* 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
|
||||
* %ecx = curmatch
|
||||
* %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
|
||||
* %esi = windowbestlen - i.e., (window + bestlen)
|
||||
* %edi = prev
|
||||
* %ebp = limit
|
||||
*/
|
||||
LookupLoop:
|
||||
andl %edx, %ecx
|
||||
movzwl (%edi,%ecx,2), %ecx
|
||||
cmpl %ebp, %ecx
|
||||
jbe LeaveNow
|
||||
subl $0x00010000, %edx
|
||||
js LeaveNow
|
||||
LoopEntry: movzwl -1(%esi,%ecx), %eax
|
||||
cmpl %ebx, %eax
|
||||
jnz LookupLoop
|
||||
movl window(%esp), %eax
|
||||
movzwl (%eax,%ecx), %eax
|
||||
cmpl scanstart(%esp), %eax
|
||||
jnz LookupLoop
|
||||
|
||||
/* Store the current value of chainlen. */
|
||||
|
||||
movl %edx, chainlenwmask(%esp)
|
||||
|
||||
/* 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). */
|
||||
|
||||
movl window(%esp), %esi
|
||||
movl scan(%esp), %edi
|
||||
addl %ecx, %esi
|
||||
movl scanalign(%esp), %eax
|
||||
movl $(-MAX_MATCH_8), %edx
|
||||
lea MAX_MATCH_8(%edi,%eax), %edi
|
||||
lea MAX_MATCH_8(%esi,%eax), %esi
|
||||
|
||||
/* 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:
|
||||
movl (%esi,%edx), %eax
|
||||
xorl (%edi,%edx), %eax
|
||||
jnz LeaveLoopCmps
|
||||
movl 4(%esi,%edx), %eax
|
||||
xorl 4(%edi,%edx), %eax
|
||||
jnz LeaveLoopCmps4
|
||||
addl $8, %edx
|
||||
jnz LoopCmps
|
||||
jmp LenMaximum
|
||||
LeaveLoopCmps4: addl $4, %edx
|
||||
LeaveLoopCmps: testl $0x0000FFFF, %eax
|
||||
jnz LenLower
|
||||
addl $2, %edx
|
||||
shrl $16, %eax
|
||||
LenLower: subb $1, %al
|
||||
adcl $0, %edx
|
||||
|
||||
/* 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 (%edi,%edx), %eax
|
||||
movl scan(%esp), %edi
|
||||
subl %edi, %eax
|
||||
cmpl $MAX_MATCH, %eax
|
||||
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. */
|
||||
|
||||
movl deflatestate(%esp), %edx
|
||||
movl bestlen(%esp), %ebx
|
||||
cmpl %ebx, %eax
|
||||
jg LongerMatch
|
||||
movl windowbestlen(%esp), %esi
|
||||
movl dsPrev(%edx), %edi
|
||||
movl scanend(%esp), %ebx
|
||||
movl chainlenwmask(%esp), %edx
|
||||
jmp LookupLoop
|
||||
|
||||
/* s->match_start = cur_match; */
|
||||
/* best_len = len; */
|
||||
/* if (len >= nice_match) break; */
|
||||
/* scan_end = *(ushf*)(scan+best_len-1); */
|
||||
|
||||
LongerMatch: movl nicematch(%esp), %ebx
|
||||
movl %eax, bestlen(%esp)
|
||||
movl %ecx, dsMatchStart(%edx)
|
||||
cmpl %ebx, %eax
|
||||
jge LeaveNow
|
||||
movl window(%esp), %esi
|
||||
addl %eax, %esi
|
||||
movl %esi, windowbestlen(%esp)
|
||||
movzwl -1(%edi,%eax), %ebx
|
||||
movl dsPrev(%edx), %edi
|
||||
movl %ebx, scanend(%esp)
|
||||
movl chainlenwmask(%esp), %edx
|
||||
jmp LookupLoop
|
||||
|
||||
/* Accept the current string, with the maximum possible length. */
|
||||
|
||||
LenMaximum: movl deflatestate(%esp), %edx
|
||||
movl $MAX_MATCH, bestlen(%esp)
|
||||
movl %ecx, dsMatchStart(%edx)
|
||||
|
||||
/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
|
||||
/* return s->lookahead; */
|
||||
|
||||
LeaveNow:
|
||||
movl deflatestate(%esp), %edx
|
||||
movl bestlen(%esp), %ebx
|
||||
movl dsLookahead(%edx), %eax
|
||||
cmpl %eax, %ebx
|
||||
jg LookaheadRet
|
||||
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
|
||||
/* match.s -- Pentium-Pro-optimized version of longest_match()
|
||||
* Written for zlib 1.1.2
|
||||
* Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License.
|
||||
*/
|
||||
|
||||
#ifndef NO_UNDERLINE
|
||||
#define match_init _match_init
|
||||
#define longest_match _longest_match
|
||||
#endif
|
||||
|
||||
#define MAX_MATCH (258)
|
||||
#define MIN_MATCH (3)
|
||||
#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
|
||||
#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7)
|
||||
|
||||
/* stack frame offsets */
|
||||
|
||||
#define chainlenwmask 0 /* high word: current chain len */
|
||||
/* low word: s->wmask */
|
||||
#define window 4 /* local copy of s->window */
|
||||
#define windowbestlen 8 /* s->window + bestlen */
|
||||
#define scanstart 16 /* first two bytes of string */
|
||||
#define scanend 12 /* last two bytes of string */
|
||||
#define scanalign 20 /* dword-misalignment of string */
|
||||
#define nicematch 24 /* a good enough match size */
|
||||
#define bestlen 28 /* size of best match so far */
|
||||
#define scan 32 /* ptr to string wanting match */
|
||||
|
||||
#define LocalVarsSize (36)
|
||||
/* saved ebx 36 */
|
||||
/* saved edi 40 */
|
||||
/* saved esi 44 */
|
||||
/* saved ebp 48 */
|
||||
/* return address 52 */
|
||||
#define deflatestate 56 /* the function arguments */
|
||||
#define curmatch 60
|
||||
|
||||
/* 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").
|
||||
*/
|
||||
|
||||
#define zlib1222add (8)
|
||||
|
||||
#define dsWSize (36+zlib1222add)
|
||||
#define dsWMask (44+zlib1222add)
|
||||
#define dsWindow (48+zlib1222add)
|
||||
#define dsPrev (56+zlib1222add)
|
||||
#define dsMatchLen (88+zlib1222add)
|
||||
#define dsPrevMatch (92+zlib1222add)
|
||||
#define dsStrStart (100+zlib1222add)
|
||||
#define dsMatchStart (104+zlib1222add)
|
||||
#define dsLookahead (108+zlib1222add)
|
||||
#define dsPrevLen (112+zlib1222add)
|
||||
#define dsMaxChainLen (116+zlib1222add)
|
||||
#define dsGoodMatch (132+zlib1222add)
|
||||
#define dsNiceMatch (136+zlib1222add)
|
||||
|
||||
|
||||
.file "match.S"
|
||||
|
||||
.globl match_init, longest_match
|
||||
|
||||
.text
|
||||
|
||||
/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
|
||||
|
||||
longest_match:
|
||||
|
||||
/* Save registers that the compiler may be using, and adjust %esp to */
|
||||
/* make room for our stack frame. */
|
||||
|
||||
pushl %ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %ebx
|
||||
subl $LocalVarsSize, %esp
|
||||
|
||||
/* Retrieve the function arguments. %ecx 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). */
|
||||
|
||||
movl deflatestate(%esp), %edx
|
||||
movl curmatch(%esp), %ecx
|
||||
|
||||
/* uInt wmask = s->w_mask; */
|
||||
/* 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 dsWMask(%edx), %eax
|
||||
movl dsMaxChainLen(%edx), %ebx
|
||||
jl LastMatchGood
|
||||
shrl $2, %ebx
|
||||
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. */
|
||||
|
||||
decl %ebx
|
||||
shll $16, %ebx
|
||||
orl %eax, %ebx
|
||||
movl %ebx, chainlenwmask(%esp)
|
||||
|
||||
/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */
|
||||
|
||||
movl dsNiceMatch(%edx), %eax
|
||||
movl dsLookahead(%edx), %ebx
|
||||
cmpl %eax, %ebx
|
||||
jl LookaheadLess
|
||||
movl %eax, %ebx
|
||||
LookaheadLess: movl %ebx, nicematch(%esp)
|
||||
|
||||
/* register Bytef *scan = s->window + s->strstart; */
|
||||
|
||||
movl dsWindow(%edx), %esi
|
||||
movl %esi, window(%esp)
|
||||
movl dsStrStart(%edx), %ebp
|
||||
lea (%esi,%ebp), %edi
|
||||
movl %edi, scan(%esp)
|
||||
|
||||
/* Determine how many bytes the scan ptr is off from being */
|
||||
/* dword-aligned. */
|
||||
|
||||
movl %edi, %eax
|
||||
negl %eax
|
||||
andl $3, %eax
|
||||
movl %eax, scanalign(%esp)
|
||||
|
||||
/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
|
||||
/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
|
||||
|
||||
movl dsWSize(%edx), %eax
|
||||
subl $MIN_LOOKAHEAD, %eax
|
||||
subl %eax, %ebp
|
||||
jg LimitPositive
|
||||
xorl %ebp, %ebp
|
||||
LimitPositive:
|
||||
|
||||
/* int best_len = s->prev_length; */
|
||||
|
||||
movl dsPrevLen(%edx), %eax
|
||||
movl %eax, bestlen(%esp)
|
||||
|
||||
/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
|
||||
|
||||
addl %eax, %esi
|
||||
movl %esi, windowbestlen(%esp)
|
||||
|
||||
/* register ush scan_start = *(ushf*)scan; */
|
||||
/* register ush scan_end = *(ushf*)(scan+best_len-1); */
|
||||
/* Posf *prev = s->prev; */
|
||||
|
||||
movzwl (%edi), %ebx
|
||||
movl %ebx, scanstart(%esp)
|
||||
movzwl -1(%edi,%eax), %ebx
|
||||
movl %ebx, scanend(%esp)
|
||||
movl dsPrev(%edx), %edi
|
||||
|
||||
/* Jump into the main loop. */
|
||||
|
||||
movl chainlenwmask(%esp), %edx
|
||||
jmp LoopEntry
|
||||
|
||||
.balign 16
|
||||
|
||||
/* 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
|
||||
* %ecx = curmatch
|
||||
* %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
|
||||
* %esi = windowbestlen - i.e., (window + bestlen)
|
||||
* %edi = prev
|
||||
* %ebp = limit
|
||||
*/
|
||||
LookupLoop:
|
||||
andl %edx, %ecx
|
||||
movzwl (%edi,%ecx,2), %ecx
|
||||
cmpl %ebp, %ecx
|
||||
jbe LeaveNow
|
||||
subl $0x00010000, %edx
|
||||
js LeaveNow
|
||||
LoopEntry: movzwl -1(%esi,%ecx), %eax
|
||||
cmpl %ebx, %eax
|
||||
jnz LookupLoop
|
||||
movl window(%esp), %eax
|
||||
movzwl (%eax,%ecx), %eax
|
||||
cmpl scanstart(%esp), %eax
|
||||
jnz LookupLoop
|
||||
|
||||
/* Store the current value of chainlen. */
|
||||
|
||||
movl %edx, chainlenwmask(%esp)
|
||||
|
||||
/* 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). */
|
||||
|
||||
movl window(%esp), %esi
|
||||
movl scan(%esp), %edi
|
||||
addl %ecx, %esi
|
||||
movl scanalign(%esp), %eax
|
||||
movl $(-MAX_MATCH_8), %edx
|
||||
lea MAX_MATCH_8(%edi,%eax), %edi
|
||||
lea MAX_MATCH_8(%esi,%eax), %esi
|
||||
|
||||
/* 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:
|
||||
movl (%esi,%edx), %eax
|
||||
xorl (%edi,%edx), %eax
|
||||
jnz LeaveLoopCmps
|
||||
movl 4(%esi,%edx), %eax
|
||||
xorl 4(%edi,%edx), %eax
|
||||
jnz LeaveLoopCmps4
|
||||
addl $8, %edx
|
||||
jnz LoopCmps
|
||||
jmp LenMaximum
|
||||
LeaveLoopCmps4: addl $4, %edx
|
||||
LeaveLoopCmps: testl $0x0000FFFF, %eax
|
||||
jnz LenLower
|
||||
addl $2, %edx
|
||||
shrl $16, %eax
|
||||
LenLower: subb $1, %al
|
||||
adcl $0, %edx
|
||||
|
||||
/* 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 (%edi,%edx), %eax
|
||||
movl scan(%esp), %edi
|
||||
subl %edi, %eax
|
||||
cmpl $MAX_MATCH, %eax
|
||||
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. */
|
||||
|
||||
movl deflatestate(%esp), %edx
|
||||
movl bestlen(%esp), %ebx
|
||||
cmpl %ebx, %eax
|
||||
jg LongerMatch
|
||||
movl windowbestlen(%esp), %esi
|
||||
movl dsPrev(%edx), %edi
|
||||
movl scanend(%esp), %ebx
|
||||
movl chainlenwmask(%esp), %edx
|
||||
jmp LookupLoop
|
||||
|
||||
/* s->match_start = cur_match; */
|
||||
/* best_len = len; */
|
||||
/* if (len >= nice_match) break; */
|
||||
/* scan_end = *(ushf*)(scan+best_len-1); */
|
||||
|
||||
LongerMatch: movl nicematch(%esp), %ebx
|
||||
movl %eax, bestlen(%esp)
|
||||
movl %ecx, dsMatchStart(%edx)
|
||||
cmpl %ebx, %eax
|
||||
jge LeaveNow
|
||||
movl window(%esp), %esi
|
||||
addl %eax, %esi
|
||||
movl %esi, windowbestlen(%esp)
|
||||
movzwl -1(%edi,%eax), %ebx
|
||||
movl dsPrev(%edx), %edi
|
||||
movl %ebx, scanend(%esp)
|
||||
movl chainlenwmask(%esp), %edx
|
||||
jmp LookupLoop
|
||||
|
||||
/* Accept the current string, with the maximum possible length. */
|
||||
|
||||
LenMaximum: movl deflatestate(%esp), %edx
|
||||
movl $MAX_MATCH, bestlen(%esp)
|
||||
movl %ecx, dsMatchStart(%edx)
|
||||
|
||||
/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
|
||||
/* return s->lookahead; */
|
||||
|
||||
LeaveNow:
|
||||
movl deflatestate(%esp), %edx
|
||||
movl bestlen(%esp), %ebx
|
||||
movl dsLookahead(%edx), %eax
|
||||
cmpl %eax, %ebx
|
||||
jg LookaheadRet
|
||||
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
|
||||
|
@ -16,6 +16,10 @@
|
||||
* zlib.h must be included before this header file.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
ZEXTERN int ZEXPORT inflateBack9 OF((z_stream FAR *strm,
|
||||
in_func in, void FAR *in_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) \
|
||||
inflateBack9Init_((strm), (window), \
|
||||
ZLIB_VERSION, sizeof(z_stream))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
#define MAXBITS 15
|
||||
|
||||
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
|
||||
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 */
|
||||
128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129,
|
||||
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 */
|
||||
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49,
|
||||
65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073,
|
||||
|
@ -1,408 +1,413 @@
|
||||
|
||||
; match.asm -- Pentium-Pro optimized version of longest_match()
|
||||
;
|
||||
; Updated for zlib 1.1.3 and converted to MASM 6.1x
|
||||
; Copyright (C) 2000 Dan Higdon <hdan@kinesoft.com>
|
||||
; and Chuck Walbourn <chuckw@kinesoft.com>
|
||||
; Corrections by Cosmin Truta <cosmint@cs.ubbcluj.ro>
|
||||
;
|
||||
; This is free software; you can redistribute it and/or modify it
|
||||
; under the terms of the GNU General Public License.
|
||||
|
||||
; Based on match.S
|
||||
; Written for zlib 1.1.2
|
||||
; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
|
||||
|
||||
.686P
|
||||
.MODEL FLAT
|
||||
|
||||
;===========================================================================
|
||||
; EQUATES
|
||||
;===========================================================================
|
||||
|
||||
MAX_MATCH EQU 258
|
||||
MIN_MATCH EQU 3
|
||||
MIN_LOOKAHEAD EQU (MAX_MATCH + MIN_MATCH + 1)
|
||||
MAX_MATCH_8 EQU ((MAX_MATCH + 7) AND (NOT 7))
|
||||
|
||||
;===========================================================================
|
||||
; STRUCTURES
|
||||
;===========================================================================
|
||||
|
||||
; This STRUCT assumes a 4-byte alignment
|
||||
|
||||
DEFLATE_STATE STRUCT
|
||||
ds_strm dd ?
|
||||
ds_status dd ?
|
||||
ds_pending_buf dd ?
|
||||
ds_pending_buf_size dd ?
|
||||
ds_pending_out dd ?
|
||||
ds_pending dd ?
|
||||
ds_wrap dd ?
|
||||
ds_data_type db ?
|
||||
ds_method db ?
|
||||
db ? ; padding
|
||||
db ? ; padding
|
||||
ds_last_flush dd ?
|
||||
ds_w_size dd ? ; used
|
||||
ds_w_bits dd ?
|
||||
ds_w_mask dd ? ; used
|
||||
ds_window dd ? ; used
|
||||
ds_window_size dd ?
|
||||
ds_prev dd ? ; used
|
||||
ds_head dd ?
|
||||
ds_ins_h dd ?
|
||||
ds_hash_size dd ?
|
||||
ds_hash_bits dd ?
|
||||
ds_hash_mask dd ?
|
||||
ds_hash_shift dd ?
|
||||
ds_block_start dd ?
|
||||
ds_match_length dd ? ; used
|
||||
ds_prev_match dd ? ; used
|
||||
ds_match_available dd ?
|
||||
ds_strstart dd ? ; used
|
||||
ds_match_start dd ? ; used
|
||||
ds_lookahead dd ? ; used
|
||||
ds_prev_length dd ? ; used
|
||||
ds_max_chain_length dd ? ; used
|
||||
ds_max_laxy_match dd ?
|
||||
ds_level dd ?
|
||||
ds_strategy dd ?
|
||||
ds_good_match dd ? ; used
|
||||
ds_nice_match dd ? ; used
|
||||
|
||||
; Don't need anymore of the struct for match
|
||||
DEFLATE_STATE ENDS
|
||||
|
||||
;===========================================================================
|
||||
; CODE
|
||||
;===========================================================================
|
||||
_TEXT SEGMENT
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; match_init
|
||||
;---------------------------------------------------------------------------
|
||||
ALIGN 4
|
||||
PUBLIC _match_init
|
||||
_match_init PROC
|
||||
; no initialization needed
|
||||
ret
|
||||
_match_init ENDP
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; uInt longest_match(deflate_state *deflatestate, IPos curmatch)
|
||||
;---------------------------------------------------------------------------
|
||||
ALIGN 4
|
||||
|
||||
PUBLIC _longest_match
|
||||
_longest_match PROC
|
||||
|
||||
; Since this code uses EBP for a scratch register, the stack frame must
|
||||
; be manually constructed and referenced relative to the ESP register.
|
||||
|
||||
; Stack image
|
||||
; Variables
|
||||
chainlenwmask = 0 ; high word: current chain len
|
||||
; low word: s->wmask
|
||||
window = 4 ; local copy of s->window
|
||||
windowbestlen = 8 ; s->window + bestlen
|
||||
scanend = 12 ; last two bytes of string
|
||||
scanstart = 16 ; first two bytes of string
|
||||
scanalign = 20 ; dword-misalignment of string
|
||||
nicematch = 24 ; a good enough match size
|
||||
bestlen = 28 ; size of best match so far
|
||||
scan = 32 ; ptr to string wanting match
|
||||
varsize = 36 ; number of bytes (also offset to last saved register)
|
||||
|
||||
; Saved Registers (actually pushed into place)
|
||||
ebx_save = 36
|
||||
edi_save = 40
|
||||
esi_save = 44
|
||||
ebp_save = 48
|
||||
|
||||
; Parameters
|
||||
retaddr = 52
|
||||
deflatestate = 56
|
||||
curmatch = 60
|
||||
|
||||
; Save registers that the compiler may be using
|
||||
push ebp
|
||||
push edi
|
||||
push esi
|
||||
push ebx
|
||||
|
||||
; Allocate local variable space
|
||||
sub esp,varsize
|
||||
|
||||
; Retrieve the function arguments. ecx 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).
|
||||
|
||||
mov edx, [esp+deflatestate]
|
||||
ASSUME edx:PTR DEFLATE_STATE
|
||||
|
||||
mov ecx, [esp+curmatch]
|
||||
|
||||
; uInt wmask = s->w_mask;
|
||||
; unsigned chain_length = s->max_chain_length;
|
||||
; if (s->prev_length >= s->good_match) {
|
||||
; chain_length >>= 2;
|
||||
; }
|
||||
|
||||
mov eax, [edx].ds_prev_length
|
||||
mov ebx, [edx].ds_good_match
|
||||
cmp eax, ebx
|
||||
mov eax, [edx].ds_w_mask
|
||||
mov ebx, [edx].ds_max_chain_length
|
||||
jl SHORT 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 [esp+chainlenwmask], ebx
|
||||
|
||||
; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
|
||||
|
||||
mov eax, [edx].ds_nice_match
|
||||
mov ebx, [edx].ds_lookahead
|
||||
cmp ebx, eax
|
||||
jl SHORT LookaheadLess
|
||||
mov ebx, eax
|
||||
LookaheadLess:
|
||||
mov [esp+nicematch], ebx
|
||||
|
||||
;/* register Bytef *scan = s->window + s->strstart; */
|
||||
|
||||
mov esi, [edx].ds_window
|
||||
mov [esp+window], esi
|
||||
mov ebp, [edx].ds_strstart
|
||||
lea edi, [esi+ebp]
|
||||
mov [esp+scan],edi
|
||||
|
||||
;/* Determine how many bytes the scan ptr is off from being */
|
||||
;/* dword-aligned. */
|
||||
|
||||
mov eax, edi
|
||||
neg eax
|
||||
and eax, 3
|
||||
mov [esp+scanalign], eax
|
||||
|
||||
;/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
|
||||
;/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
|
||||
|
||||
mov eax, [edx].ds_w_size
|
||||
sub eax, MIN_LOOKAHEAD
|
||||
sub ebp, eax
|
||||
jg SHORT LimitPositive
|
||||
xor ebp, ebp
|
||||
LimitPositive:
|
||||
|
||||
;/* int best_len = s->prev_length; */
|
||||
|
||||
mov eax, [edx].ds_prev_length
|
||||
mov [esp+bestlen], eax
|
||||
|
||||
;/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
|
||||
|
||||
add esi, eax
|
||||
mov [esp+windowbestlen], esi
|
||||
|
||||
;/* register ush scan_start = *(ushf*)scan; */
|
||||
;/* register ush scan_end = *(ushf*)(scan+best_len-1); */
|
||||
;/* Posf *prev = s->prev; */
|
||||
|
||||
movzx ebx, WORD PTR[edi]
|
||||
mov [esp+scanstart], ebx
|
||||
movzx ebx, WORD PTR[eax+edi-1]
|
||||
mov [esp+scanend], ebx
|
||||
mov edi, [edx].ds_prev
|
||||
|
||||
;/* Jump into the main loop. */
|
||||
|
||||
mov edx, [esp+chainlenwmask]
|
||||
jmp SHORT LoopEntry
|
||||
|
||||
;/* 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
|
||||
; * %ecx = curmatch
|
||||
; * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
|
||||
; * %esi = windowbestlen - i.e., (window + bestlen)
|
||||
; * %edi = prev
|
||||
; * %ebp = limit
|
||||
; */
|
||||
|
||||
ALIGN 4
|
||||
LookupLoop:
|
||||
and ecx, edx
|
||||
movzx ecx, WORD PTR[edi+ecx*2]
|
||||
cmp ecx, ebp
|
||||
jbe LeaveNow
|
||||
sub edx, 000010000H
|
||||
js LeaveNow
|
||||
|
||||
LoopEntry:
|
||||
movzx eax, WORD PTR[esi+ecx-1]
|
||||
cmp eax, ebx
|
||||
jnz SHORT LookupLoop
|
||||
|
||||
mov eax, [esp+window]
|
||||
movzx eax, WORD PTR[eax+ecx]
|
||||
cmp eax, [esp+scanstart]
|
||||
jnz SHORT LookupLoop
|
||||
|
||||
;/* Store the current value of chainlen. */
|
||||
|
||||
mov [esp+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). */
|
||||
|
||||
mov esi, [esp+window]
|
||||
mov edi, [esp+scan]
|
||||
add esi, ecx
|
||||
mov eax, [esp+scanalign]
|
||||
mov edx, -MAX_MATCH_8
|
||||
lea edi, [edi+eax+MAX_MATCH_8]
|
||||
lea esi, [esi+eax+MAX_MATCH_8]
|
||||
|
||||
;/* 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, DWORD PTR[esi+edx]
|
||||
xor eax, DWORD PTR[edi+edx]
|
||||
jnz SHORT LeaveLoopCmps
|
||||
|
||||
mov eax, DWORD PTR[esi+edx+4]
|
||||
xor eax, DWORD PTR[edi+edx+4]
|
||||
jnz SHORT LeaveLoopCmps4
|
||||
|
||||
add edx, 8
|
||||
jnz SHORT LoopCmps
|
||||
jmp LenMaximum
|
||||
ALIGN 4
|
||||
|
||||
LeaveLoopCmps4:
|
||||
add edx, 4
|
||||
|
||||
LeaveLoopCmps:
|
||||
test eax, 00000FFFFH
|
||||
jnz SHORT LenLower
|
||||
|
||||
add edx, 2
|
||||
shr eax, 16
|
||||
|
||||
LenLower:
|
||||
sub al, 1
|
||||
adc edx, 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 eax, [edi+edx]
|
||||
mov edi, [esp+scan]
|
||||
sub eax, edi
|
||||
cmp eax, MAX_MATCH
|
||||
jge SHORT 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. */
|
||||
|
||||
mov edx, [esp+deflatestate]
|
||||
mov ebx, [esp+bestlen]
|
||||
cmp eax, ebx
|
||||
jg SHORT LongerMatch
|
||||
mov esi, [esp+windowbestlen]
|
||||
mov edi, [edx].ds_prev
|
||||
mov ebx, [esp+scanend]
|
||||
mov edx, [esp+chainlenwmask]
|
||||
jmp LookupLoop
|
||||
ALIGN 4
|
||||
|
||||
;/* s->match_start = cur_match; */
|
||||
;/* best_len = len; */
|
||||
;/* if (len >= nice_match) break; */
|
||||
;/* scan_end = *(ushf*)(scan+best_len-1); */
|
||||
|
||||
LongerMatch:
|
||||
mov ebx, [esp+nicematch]
|
||||
mov [esp+bestlen], eax
|
||||
mov [edx].ds_match_start, ecx
|
||||
cmp eax, ebx
|
||||
jge SHORT LeaveNow
|
||||
mov esi, [esp+window]
|
||||
add esi, eax
|
||||
mov [esp+windowbestlen], esi
|
||||
movzx ebx, WORD PTR[edi+eax-1]
|
||||
mov edi, [edx].ds_prev
|
||||
mov [esp+scanend], ebx
|
||||
mov edx, [esp+chainlenwmask]
|
||||
jmp LookupLoop
|
||||
ALIGN 4
|
||||
|
||||
;/* Accept the current string, with the maximum possible length. */
|
||||
|
||||
LenMaximum:
|
||||
mov edx, [esp+deflatestate]
|
||||
mov DWORD PTR[esp+bestlen], MAX_MATCH
|
||||
mov [edx].ds_match_start, ecx
|
||||
|
||||
;/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
|
||||
;/* return s->lookahead; */
|
||||
|
||||
LeaveNow:
|
||||
mov edx, [esp+deflatestate]
|
||||
mov ebx, [esp+bestlen]
|
||||
mov eax, [edx].ds_lookahead
|
||||
cmp ebx, eax
|
||||
jg SHORT LookaheadRet
|
||||
mov eax, ebx
|
||||
LookaheadRet:
|
||||
|
||||
; Restore the stack and return from whence we came.
|
||||
|
||||
add esp, varsize
|
||||
pop ebx
|
||||
pop esi
|
||||
pop edi
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
_longest_match ENDP
|
||||
|
||||
_TEXT ENDS
|
||||
END
|
||||
|
||||
; match.asm -- Pentium-Pro optimized version of longest_match()
|
||||
;
|
||||
; Updated for zlib 1.1.3 and converted to MASM 6.1x
|
||||
; Copyright (C) 2000 Dan Higdon <hdan@kinesoft.com>
|
||||
; and Chuck Walbourn <chuckw@kinesoft.com>
|
||||
; Corrections by Cosmin Truta <cosmint@cs.ubbcluj.ro>
|
||||
;
|
||||
; This is free software; you can redistribute it and/or modify it
|
||||
; under the terms of the GNU General Public License.
|
||||
|
||||
; Based on match.S
|
||||
; Written for zlib 1.1.2
|
||||
; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
|
||||
;
|
||||
; Modified by Gilles Vollant (2005) for add gzhead and gzindex
|
||||
|
||||
.686P
|
||||
.MODEL FLAT
|
||||
|
||||
;===========================================================================
|
||||
; EQUATES
|
||||
;===========================================================================
|
||||
|
||||
MAX_MATCH EQU 258
|
||||
MIN_MATCH EQU 3
|
||||
MIN_LOOKAHEAD EQU (MAX_MATCH + MIN_MATCH + 1)
|
||||
MAX_MATCH_8 EQU ((MAX_MATCH + 7) AND (NOT 7))
|
||||
|
||||
;===========================================================================
|
||||
; STRUCTURES
|
||||
;===========================================================================
|
||||
|
||||
; This STRUCT assumes a 4-byte alignment
|
||||
|
||||
DEFLATE_STATE STRUCT
|
||||
ds_strm dd ?
|
||||
ds_status dd ?
|
||||
ds_pending_buf dd ?
|
||||
ds_pending_buf_size dd ?
|
||||
ds_pending_out dd ?
|
||||
ds_pending dd ?
|
||||
ds_wrap dd ?
|
||||
; gzhead and gzindex are added in zlib 1.2.2.2 (see deflate.h)
|
||||
ds_gzhead dd ?
|
||||
ds_gzindex dd ?
|
||||
ds_data_type db ?
|
||||
ds_method db ?
|
||||
db ? ; padding
|
||||
db ? ; padding
|
||||
ds_last_flush dd ?
|
||||
ds_w_size dd ? ; used
|
||||
ds_w_bits dd ?
|
||||
ds_w_mask dd ? ; used
|
||||
ds_window dd ? ; used
|
||||
ds_window_size dd ?
|
||||
ds_prev dd ? ; used
|
||||
ds_head dd ?
|
||||
ds_ins_h dd ?
|
||||
ds_hash_size dd ?
|
||||
ds_hash_bits dd ?
|
||||
ds_hash_mask dd ?
|
||||
ds_hash_shift dd ?
|
||||
ds_block_start dd ?
|
||||
ds_match_length dd ? ; used
|
||||
ds_prev_match dd ? ; used
|
||||
ds_match_available dd ?
|
||||
ds_strstart dd ? ; used
|
||||
ds_match_start dd ? ; used
|
||||
ds_lookahead dd ? ; used
|
||||
ds_prev_length dd ? ; used
|
||||
ds_max_chain_length dd ? ; used
|
||||
ds_max_laxy_match dd ?
|
||||
ds_level dd ?
|
||||
ds_strategy dd ?
|
||||
ds_good_match dd ? ; used
|
||||
ds_nice_match dd ? ; used
|
||||
|
||||
; Don't need anymore of the struct for match
|
||||
DEFLATE_STATE ENDS
|
||||
|
||||
;===========================================================================
|
||||
; CODE
|
||||
;===========================================================================
|
||||
_TEXT SEGMENT
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; match_init
|
||||
;---------------------------------------------------------------------------
|
||||
ALIGN 4
|
||||
PUBLIC _match_init
|
||||
_match_init PROC
|
||||
; no initialization needed
|
||||
ret
|
||||
_match_init ENDP
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; uInt longest_match(deflate_state *deflatestate, IPos curmatch)
|
||||
;---------------------------------------------------------------------------
|
||||
ALIGN 4
|
||||
|
||||
PUBLIC _longest_match
|
||||
_longest_match PROC
|
||||
|
||||
; Since this code uses EBP for a scratch register, the stack frame must
|
||||
; be manually constructed and referenced relative to the ESP register.
|
||||
|
||||
; Stack image
|
||||
; Variables
|
||||
chainlenwmask = 0 ; high word: current chain len
|
||||
; low word: s->wmask
|
||||
window = 4 ; local copy of s->window
|
||||
windowbestlen = 8 ; s->window + bestlen
|
||||
scanend = 12 ; last two bytes of string
|
||||
scanstart = 16 ; first two bytes of string
|
||||
scanalign = 20 ; dword-misalignment of string
|
||||
nicematch = 24 ; a good enough match size
|
||||
bestlen = 28 ; size of best match so far
|
||||
scan = 32 ; ptr to string wanting match
|
||||
varsize = 36 ; number of bytes (also offset to last saved register)
|
||||
|
||||
; Saved Registers (actually pushed into place)
|
||||
ebx_save = 36
|
||||
edi_save = 40
|
||||
esi_save = 44
|
||||
ebp_save = 48
|
||||
|
||||
; Parameters
|
||||
retaddr = 52
|
||||
deflatestate = 56
|
||||
curmatch = 60
|
||||
|
||||
; Save registers that the compiler may be using
|
||||
push ebp
|
||||
push edi
|
||||
push esi
|
||||
push ebx
|
||||
|
||||
; Allocate local variable space
|
||||
sub esp,varsize
|
||||
|
||||
; Retrieve the function arguments. ecx 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).
|
||||
|
||||
mov edx, [esp+deflatestate]
|
||||
ASSUME edx:PTR DEFLATE_STATE
|
||||
|
||||
mov ecx, [esp+curmatch]
|
||||
|
||||
; uInt wmask = s->w_mask;
|
||||
; unsigned chain_length = s->max_chain_length;
|
||||
; if (s->prev_length >= s->good_match) {
|
||||
; chain_length >>= 2;
|
||||
; }
|
||||
|
||||
mov eax, [edx].ds_prev_length
|
||||
mov ebx, [edx].ds_good_match
|
||||
cmp eax, ebx
|
||||
mov eax, [edx].ds_w_mask
|
||||
mov ebx, [edx].ds_max_chain_length
|
||||
jl SHORT 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 [esp+chainlenwmask], ebx
|
||||
|
||||
; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
|
||||
|
||||
mov eax, [edx].ds_nice_match
|
||||
mov ebx, [edx].ds_lookahead
|
||||
cmp ebx, eax
|
||||
jl SHORT LookaheadLess
|
||||
mov ebx, eax
|
||||
LookaheadLess:
|
||||
mov [esp+nicematch], ebx
|
||||
|
||||
;/* register Bytef *scan = s->window + s->strstart; */
|
||||
|
||||
mov esi, [edx].ds_window
|
||||
mov [esp+window], esi
|
||||
mov ebp, [edx].ds_strstart
|
||||
lea edi, [esi+ebp]
|
||||
mov [esp+scan],edi
|
||||
|
||||
;/* Determine how many bytes the scan ptr is off from being */
|
||||
;/* dword-aligned. */
|
||||
|
||||
mov eax, edi
|
||||
neg eax
|
||||
and eax, 3
|
||||
mov [esp+scanalign], eax
|
||||
|
||||
;/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
|
||||
;/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
|
||||
|
||||
mov eax, [edx].ds_w_size
|
||||
sub eax, MIN_LOOKAHEAD
|
||||
sub ebp, eax
|
||||
jg SHORT LimitPositive
|
||||
xor ebp, ebp
|
||||
LimitPositive:
|
||||
|
||||
;/* int best_len = s->prev_length; */
|
||||
|
||||
mov eax, [edx].ds_prev_length
|
||||
mov [esp+bestlen], eax
|
||||
|
||||
;/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
|
||||
|
||||
add esi, eax
|
||||
mov [esp+windowbestlen], esi
|
||||
|
||||
;/* register ush scan_start = *(ushf*)scan; */
|
||||
;/* register ush scan_end = *(ushf*)(scan+best_len-1); */
|
||||
;/* Posf *prev = s->prev; */
|
||||
|
||||
movzx ebx, WORD PTR[edi]
|
||||
mov [esp+scanstart], ebx
|
||||
movzx ebx, WORD PTR[eax+edi-1]
|
||||
mov [esp+scanend], ebx
|
||||
mov edi, [edx].ds_prev
|
||||
|
||||
;/* Jump into the main loop. */
|
||||
|
||||
mov edx, [esp+chainlenwmask]
|
||||
jmp SHORT LoopEntry
|
||||
|
||||
;/* 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
|
||||
; * %ecx = curmatch
|
||||
; * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
|
||||
; * %esi = windowbestlen - i.e., (window + bestlen)
|
||||
; * %edi = prev
|
||||
; * %ebp = limit
|
||||
; */
|
||||
|
||||
ALIGN 4
|
||||
LookupLoop:
|
||||
and ecx, edx
|
||||
movzx ecx, WORD PTR[edi+ecx*2]
|
||||
cmp ecx, ebp
|
||||
jbe LeaveNow
|
||||
sub edx, 000010000H
|
||||
js LeaveNow
|
||||
|
||||
LoopEntry:
|
||||
movzx eax, WORD PTR[esi+ecx-1]
|
||||
cmp eax, ebx
|
||||
jnz SHORT LookupLoop
|
||||
|
||||
mov eax, [esp+window]
|
||||
movzx eax, WORD PTR[eax+ecx]
|
||||
cmp eax, [esp+scanstart]
|
||||
jnz SHORT LookupLoop
|
||||
|
||||
;/* Store the current value of chainlen. */
|
||||
|
||||
mov [esp+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). */
|
||||
|
||||
mov esi, [esp+window]
|
||||
mov edi, [esp+scan]
|
||||
add esi, ecx
|
||||
mov eax, [esp+scanalign]
|
||||
mov edx, -MAX_MATCH_8
|
||||
lea edi, [edi+eax+MAX_MATCH_8]
|
||||
lea esi, [esi+eax+MAX_MATCH_8]
|
||||
|
||||
;/* 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, DWORD PTR[esi+edx]
|
||||
xor eax, DWORD PTR[edi+edx]
|
||||
jnz SHORT LeaveLoopCmps
|
||||
|
||||
mov eax, DWORD PTR[esi+edx+4]
|
||||
xor eax, DWORD PTR[edi+edx+4]
|
||||
jnz SHORT LeaveLoopCmps4
|
||||
|
||||
add edx, 8
|
||||
jnz SHORT LoopCmps
|
||||
jmp LenMaximum
|
||||
ALIGN 4
|
||||
|
||||
LeaveLoopCmps4:
|
||||
add edx, 4
|
||||
|
||||
LeaveLoopCmps:
|
||||
test eax, 00000FFFFH
|
||||
jnz SHORT LenLower
|
||||
|
||||
add edx, 2
|
||||
shr eax, 16
|
||||
|
||||
LenLower:
|
||||
sub al, 1
|
||||
adc edx, 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 eax, [edi+edx]
|
||||
mov edi, [esp+scan]
|
||||
sub eax, edi
|
||||
cmp eax, MAX_MATCH
|
||||
jge SHORT 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. */
|
||||
|
||||
mov edx, [esp+deflatestate]
|
||||
mov ebx, [esp+bestlen]
|
||||
cmp eax, ebx
|
||||
jg SHORT LongerMatch
|
||||
mov esi, [esp+windowbestlen]
|
||||
mov edi, [edx].ds_prev
|
||||
mov ebx, [esp+scanend]
|
||||
mov edx, [esp+chainlenwmask]
|
||||
jmp LookupLoop
|
||||
ALIGN 4
|
||||
|
||||
;/* s->match_start = cur_match; */
|
||||
;/* best_len = len; */
|
||||
;/* if (len >= nice_match) break; */
|
||||
;/* scan_end = *(ushf*)(scan+best_len-1); */
|
||||
|
||||
LongerMatch:
|
||||
mov ebx, [esp+nicematch]
|
||||
mov [esp+bestlen], eax
|
||||
mov [edx].ds_match_start, ecx
|
||||
cmp eax, ebx
|
||||
jge SHORT LeaveNow
|
||||
mov esi, [esp+window]
|
||||
add esi, eax
|
||||
mov [esp+windowbestlen], esi
|
||||
movzx ebx, WORD PTR[edi+eax-1]
|
||||
mov edi, [edx].ds_prev
|
||||
mov [esp+scanend], ebx
|
||||
mov edx, [esp+chainlenwmask]
|
||||
jmp LookupLoop
|
||||
ALIGN 4
|
||||
|
||||
;/* Accept the current string, with the maximum possible length. */
|
||||
|
||||
LenMaximum:
|
||||
mov edx, [esp+deflatestate]
|
||||
mov DWORD PTR[esp+bestlen], MAX_MATCH
|
||||
mov [edx].ds_match_start, ecx
|
||||
|
||||
;/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
|
||||
;/* return s->lookahead; */
|
||||
|
||||
LeaveNow:
|
||||
mov edx, [esp+deflatestate]
|
||||
mov ebx, [esp+bestlen]
|
||||
mov eax, [edx].ds_lookahead
|
||||
cmp ebx, eax
|
||||
jg SHORT LookaheadRet
|
||||
mov eax, ebx
|
||||
LookaheadRet:
|
||||
|
||||
; Restore the stack and return from whence we came.
|
||||
|
||||
add esp, varsize
|
||||
pop ebx
|
||||
pop esi
|
||||
pop edi
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
_longest_match ENDP
|
||||
|
||||
_TEXT ENDS
|
||||
END
|
||||
|
2
contrib/masmx64/bld_ml64.bat
Normal file
2
contrib/masmx64/bld_ml64.bat
Normal 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
464
contrib/masmx64/gvmat64.asm
Normal 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
BIN
contrib/masmx64/gvmat64.obj
Normal file
Binary file not shown.
186
contrib/masmx64/inffas8664.c
Normal file
186
contrib/masmx64/inffas8664.c
Normal 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
|
392
contrib/masmx64/inffasx64.asm
Normal file
392
contrib/masmx64/inffasx64.asm
Normal 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
|
BIN
contrib/masmx64/inffasx64.obj
Normal file
BIN
contrib/masmx64/inffasx64.obj
Normal file
Binary file not shown.
28
contrib/masmx64/readme.txt
Normal file
28
contrib/masmx64/readme.txt
Normal 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)
|
2
contrib/masmx86/bld_ml32.bat
Normal file
2
contrib/masmx86/bld_ml32.bat
Normal 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
@ -1,206 +1,62 @@
|
||||
/* gvmat32.c -- C portion of the optimized longest_match for 32 bits x86
|
||||
* Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.
|
||||
* File written by Gilles Vollant, by modifiying the longest_match
|
||||
* from Jean-loup Gailly in deflate.c
|
||||
* it prepare all parameters and call the assembly longest_match_gvasm
|
||||
* longest_match execute standard C code is wmask != 0x7fff
|
||||
* (assembly code is faster with a fixed wmask)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "deflate.h"
|
||||
|
||||
#ifdef ASMV
|
||||
#define NIL 0
|
||||
|
||||
#define UNALIGNED_OK
|
||||
|
||||
|
||||
/* if your C compiler don't add underline before function name,
|
||||
define ADD_UNDERLINE_ASMFUNC */
|
||||
#ifdef ADD_UNDERLINE_ASMFUNC
|
||||
#define longest_match_7fff _longest_match_7fff
|
||||
#define longest_match_686 _longest_match_686
|
||||
#define cpudetect32 _cpudetect32
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void match_init()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned long cpudetect32();
|
||||
|
||||
uInt longest_match_c(
|
||||
deflate_state *s,
|
||||
IPos cur_match); /* current match */
|
||||
|
||||
|
||||
uInt longest_match_7fff(
|
||||
deflate_state *s,
|
||||
IPos cur_match); /* current match */
|
||||
|
||||
uInt longest_match_686(
|
||||
deflate_state *s,
|
||||
IPos cur_match); /* current match */
|
||||
|
||||
uInt longest_match(
|
||||
deflate_state *s,
|
||||
IPos cur_match) /* current match */
|
||||
{
|
||||
static uInt iIsPPro=2;
|
||||
|
||||
if ((s->w_mask == 0x7fff) && (iIsPPro==0))
|
||||
return longest_match_7fff(s,cur_match);
|
||||
|
||||
if (iIsPPro==1)
|
||||
return longest_match_686(s,cur_match);
|
||||
|
||||
if (iIsPPro==2)
|
||||
iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0;
|
||||
|
||||
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 */
|
||||
/* gvmat32.c -- C portion of the optimized longest_match for 32 bits x86
|
||||
* Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.
|
||||
* File written by Gilles Vollant, by modifiying the longest_match
|
||||
* from Jean-loup Gailly in deflate.c
|
||||
* it prepare all parameters and call the assembly longest_match_gvasm
|
||||
* longest_match execute standard C code is wmask != 0x7fff
|
||||
* (assembly code is faster with a fixed wmask)
|
||||
*
|
||||
* Read comment at beginning of gvmat32.asm for more information
|
||||
*/
|
||||
|
||||
#if defined(ASMV) && (!defined(NOOLDPENTIUMCODE))
|
||||
#include "deflate.h"
|
||||
|
||||
/* if your C compiler don't add underline before function name,
|
||||
define ADD_UNDERLINE_ASMFUNC */
|
||||
#ifdef ADD_UNDERLINE_ASMFUNC
|
||||
#define longest_match_7fff _longest_match_7fff
|
||||
#define longest_match_686 _longest_match_686
|
||||
#define cpudetect32 _cpudetect32
|
||||
#endif
|
||||
|
||||
|
||||
unsigned long cpudetect32();
|
||||
|
||||
uInt longest_match_c(
|
||||
deflate_state *s,
|
||||
IPos cur_match); /* current match */
|
||||
|
||||
|
||||
uInt longest_match_7fff(
|
||||
deflate_state *s,
|
||||
IPos cur_match); /* current match */
|
||||
|
||||
uInt longest_match_686(
|
||||
deflate_state *s,
|
||||
IPos cur_match); /* current match */
|
||||
|
||||
|
||||
static uInt iIsPPro=2;
|
||||
|
||||
void match_init ()
|
||||
{
|
||||
iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0;
|
||||
}
|
||||
|
||||
uInt longest_match(
|
||||
deflate_state *s,
|
||||
IPos cur_match) /* current match */
|
||||
{
|
||||
if (iIsPPro!=0)
|
||||
return longest_match_686(s,cur_match);
|
||||
|
||||
if (s->w_mask != 0x7fff)
|
||||
return longest_match_686(s,cur_match);
|
||||
|
||||
/* now ((s->w_mask == 0x7fff) && (iIsPPro==0)) */
|
||||
return longest_match_7fff(s,cur_match);
|
||||
}
|
||||
|
||||
|
||||
#endif /* defined(ASMV) && (!defined(NOOLDPENTIUMCODE)) */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,63 +1,67 @@
|
||||
Change in 1.01b (20 may 04)
|
||||
- Integrate patch from Debian package (submited by Mark Brown)
|
||||
- Add tools mztools from Xavier Roche
|
||||
|
||||
Change in 1.01 (8 may 04)
|
||||
- fix buffer overrun risk in unzip.c (Xavier Roche)
|
||||
- fix a minor buffer insecurity in minizip.c (Mike Whittaker)
|
||||
|
||||
Change in 1.00: (10 sept 03)
|
||||
- rename to 1.00
|
||||
- cosmetic code change
|
||||
|
||||
Change in 0.22: (19 May 03)
|
||||
- crypting support (unless you define NOCRYPT)
|
||||
- append file in existing zipfile
|
||||
|
||||
Change in 0.21: (10 Mar 03)
|
||||
- bug fixes
|
||||
|
||||
Change in 0.17: (27 Jan 02)
|
||||
- bug fixes
|
||||
|
||||
Change in 0.16: (19 Jan 02)
|
||||
- Support of ioapi for virtualize zip file access
|
||||
|
||||
Change in 0.15: (19 Mar 98)
|
||||
- fix memory leak in minizip.c
|
||||
|
||||
Change in 0.14: (10 Mar 98)
|
||||
- fix bugs in minizip.c sample for zipping big file
|
||||
- fix problem in month in date handling
|
||||
- fix bug in unzlocal_GetCurrentFileInfoInternal in unzip.c for
|
||||
comment handling
|
||||
|
||||
Change in 0.13: (6 Mar 98)
|
||||
- fix bugs in zip.c
|
||||
- add real minizip sample
|
||||
|
||||
Change in 0.12: (4 Mar 98)
|
||||
- add zip.c and zip.h for creates .zip file
|
||||
- fix change_file_date in miniunz.c for Unix (Jean-loup Gailly)
|
||||
- fix miniunz.c for file without specific record for directory
|
||||
|
||||
Change in 0.11: (3 Mar 98)
|
||||
- fix bug in unzGetCurrentFileInfo for get extra field and comment
|
||||
- enhance miniunz sample, remove the bad unztst.c sample
|
||||
|
||||
Change in 0.10: (2 Mar 98)
|
||||
- fix bug in unzReadCurrentFile
|
||||
- rename unzip* to unz* function and structure
|
||||
- remove Windows-like hungary notation variable name
|
||||
- modify some structure in unzip.h
|
||||
- add somes comment in source
|
||||
- remove unzipGetcCurrentFile function
|
||||
- replace ZUNZEXPORT by ZEXPORT
|
||||
- add unzGetLocalExtrafield for get the local extrafield info
|
||||
- add a new sample, miniunz.c
|
||||
|
||||
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)
|
||||
Change in 1.01e (12 feb 05)
|
||||
- Fix in zipOpen2 for globalcomment (Rolf Kalbermatter)
|
||||
- Fix possible memory leak in unzip.c (Zoran Stevanovic)
|
||||
|
||||
Change in 1.01b (20 may 04)
|
||||
- Integrate patch from Debian package (submited by Mark Brown)
|
||||
- Add tools mztools from Xavier Roche
|
||||
|
||||
Change in 1.01 (8 may 04)
|
||||
- fix buffer overrun risk in unzip.c (Xavier Roche)
|
||||
- fix a minor buffer insecurity in minizip.c (Mike Whittaker)
|
||||
|
||||
Change in 1.00: (10 sept 03)
|
||||
- rename to 1.00
|
||||
- cosmetic code change
|
||||
|
||||
Change in 0.22: (19 May 03)
|
||||
- crypting support (unless you define NOCRYPT)
|
||||
- append file in existing zipfile
|
||||
|
||||
Change in 0.21: (10 Mar 03)
|
||||
- bug fixes
|
||||
|
||||
Change in 0.17: (27 Jan 02)
|
||||
- bug fixes
|
||||
|
||||
Change in 0.16: (19 Jan 02)
|
||||
- Support of ioapi for virtualize zip file access
|
||||
|
||||
Change in 0.15: (19 Mar 98)
|
||||
- fix memory leak in minizip.c
|
||||
|
||||
Change in 0.14: (10 Mar 98)
|
||||
- fix bugs in minizip.c sample for zipping big file
|
||||
- fix problem in month in date handling
|
||||
- fix bug in unzlocal_GetCurrentFileInfoInternal in unzip.c for
|
||||
comment handling
|
||||
|
||||
Change in 0.13: (6 Mar 98)
|
||||
- fix bugs in zip.c
|
||||
- add real minizip sample
|
||||
|
||||
Change in 0.12: (4 Mar 98)
|
||||
- add zip.c and zip.h for creates .zip file
|
||||
- fix change_file_date in miniunz.c for Unix (Jean-loup Gailly)
|
||||
- fix miniunz.c for file without specific record for directory
|
||||
|
||||
Change in 0.11: (3 Mar 98)
|
||||
- fix bug in unzGetCurrentFileInfo for get extra field and comment
|
||||
- enhance miniunz sample, remove the bad unztst.c sample
|
||||
|
||||
Change in 0.10: (2 Mar 98)
|
||||
- fix bug in unzReadCurrentFile
|
||||
- rename unzip* to unz* function and structure
|
||||
- remove Windows-like hungary notation variable name
|
||||
- modify some structure in unzip.h
|
||||
- add somes comment in source
|
||||
- remove unzipGetcCurrentFile function
|
||||
- replace ZUNZEXPORT by ZEXPORT
|
||||
- add unzGetLocalExtrafield for get the local extrafield info
|
||||
- add a new sample, miniunz.c
|
||||
|
||||
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)
|
||||
|
@ -1,25 +1,25 @@
|
||||
CC=cc
|
||||
CFLAGS=-O -I../..
|
||||
|
||||
UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a
|
||||
ZIP_OBJS = minizip.o zip.o ioapi.o ../../libz.a
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $*.c
|
||||
|
||||
all: miniunz minizip
|
||||
|
||||
miniunz: $(UNZ_OBJS)
|
||||
$(CC) $(CFLAGS) -o $@ $(UNZ_OBJS)
|
||||
|
||||
minizip: $(ZIP_OBJS)
|
||||
$(CC) $(CFLAGS) -o $@ $(ZIP_OBJS)
|
||||
|
||||
test: miniunz minizip
|
||||
./minizip test readme.txt
|
||||
./miniunz -l test.zip
|
||||
mv readme.txt readme.old
|
||||
./miniunz test.zip
|
||||
|
||||
clean:
|
||||
/bin/rm -f *.o *~ minizip miniunz
|
||||
CC=cc
|
||||
CFLAGS=-O -I../..
|
||||
|
||||
UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a
|
||||
ZIP_OBJS = minizip.o zip.o ioapi.o ../../libz.a
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $*.c
|
||||
|
||||
all: miniunz minizip
|
||||
|
||||
miniunz: $(UNZ_OBJS)
|
||||
$(CC) $(CFLAGS) -o $@ $(UNZ_OBJS)
|
||||
|
||||
minizip: $(ZIP_OBJS)
|
||||
$(CC) $(CFLAGS) -o $@ $(ZIP_OBJS)
|
||||
|
||||
test: miniunz minizip
|
||||
./minizip test readme.txt
|
||||
./miniunz -l test.zip
|
||||
mv readme.txt readme.old
|
||||
./miniunz test.zip
|
||||
|
||||
clean:
|
||||
/bin/rm -f *.o *~ minizip miniunz
|
||||
|
@ -1,132 +1,132 @@
|
||||
/* crypt.h -- base code for crypt/uncrypt ZIPfile
|
||||
|
||||
|
||||
Version 1.01, May 8th, 2004
|
||||
|
||||
Copyright (C) 1998-2004 Gilles Vollant
|
||||
|
||||
This code is a modified version of crypting code in Infozip distribution
|
||||
|
||||
The encryption/decryption parts of this source code (as opposed to the
|
||||
non-echoing password parts) were originally written in Europe. The
|
||||
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.)
|
||||
|
||||
This encryption code is a direct transcription of the algorithm from
|
||||
Roger Schlafly, described by Phil Katz in the file appnote.txt. This
|
||||
file (appnote.txt) is distributed with the PKZIP program (even in the
|
||||
version without encryption capabilities).
|
||||
|
||||
If you don't need crypting in your application, just define symbols
|
||||
NOCRYPT and NOUNCRYPT.
|
||||
|
||||
This code support the "Traditional PKWARE Encryption".
|
||||
|
||||
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
|
||||
Encryption is not supported.
|
||||
*/
|
||||
|
||||
#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
|
||||
|
||||
/***********************************************************************
|
||||
* Return the next byte in the pseudo-random sequence
|
||||
*/
|
||||
static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
|
||||
{
|
||||
unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
|
||||
* unpredictable manner on 16-bit systems; not a problem
|
||||
* with any known compiler so far, though */
|
||||
|
||||
temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
|
||||
return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* 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)
|
||||
{
|
||||
(*(pkeys+0)) = CRC32((*(pkeys+0)), c);
|
||||
(*(pkeys+1)) += (*(pkeys+0)) & 0xff;
|
||||
(*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
|
||||
{
|
||||
register int keyshift = (int)((*(pkeys+1)) >> 24);
|
||||
(*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Initialize the encryption keys and the random header according to
|
||||
* the given password.
|
||||
*/
|
||||
static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
|
||||
{
|
||||
*(pkeys+0) = 305419896L;
|
||||
*(pkeys+1) = 591751049L;
|
||||
*(pkeys+2) = 878082192L;
|
||||
while (*passwd != '\0') {
|
||||
update_keys(pkeys,pcrc_32_tab,(int)*passwd);
|
||||
passwd++;
|
||||
}
|
||||
}
|
||||
|
||||
#define zdecode(pkeys,pcrc_32_tab,c) \
|
||||
(update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
|
||||
|
||||
#define zencode(pkeys,pcrc_32_tab,c,t) \
|
||||
(t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
|
||||
|
||||
#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
|
||||
|
||||
#define RAND_HEAD_LEN 12
|
||||
/* "last resort" source for second part of crypt seed pattern */
|
||||
# ifndef ZCR_SEED2
|
||||
# define ZCR_SEED2 3141592654UL /* use PI as default pattern */
|
||||
# endif
|
||||
|
||||
static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting)
|
||||
const char *passwd; /* password string */
|
||||
unsigned char *buf; /* where to write header */
|
||||
int bufSize;
|
||||
unsigned long* pkeys;
|
||||
const unsigned long* pcrc_32_tab;
|
||||
unsigned long crcForCrypting;
|
||||
{
|
||||
int n; /* index in random header */
|
||||
int t; /* temporary */
|
||||
int c; /* random byte */
|
||||
unsigned char header[RAND_HEAD_LEN-2]; /* random header */
|
||||
static unsigned calls = 0; /* ensure different random header each time */
|
||||
|
||||
if (bufSize<RAND_HEAD_LEN)
|
||||
return 0;
|
||||
|
||||
/* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
|
||||
* output of rand() to get less predictability, since rand() is
|
||||
* often poorly implemented.
|
||||
*/
|
||||
if (++calls == 1)
|
||||
{
|
||||
srand((unsigned)(time(NULL) ^ ZCR_SEED2));
|
||||
}
|
||||
init_keys(passwd, pkeys, pcrc_32_tab);
|
||||
for (n = 0; n < RAND_HEAD_LEN-2; n++)
|
||||
{
|
||||
c = (rand() >> 7) & 0xff;
|
||||
header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
|
||||
}
|
||||
/* Encrypt random header (last two bytes is high word of crc) */
|
||||
init_keys(passwd, pkeys, pcrc_32_tab);
|
||||
for (n = 0; n < RAND_HEAD_LEN-2; n++)
|
||||
{
|
||||
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 >> 24) & 0xff, t);
|
||||
return n;
|
||||
}
|
||||
|
||||
#endif
|
||||
/* crypt.h -- base code for crypt/uncrypt ZIPfile
|
||||
|
||||
|
||||
Version 1.01e, February 12th, 2005
|
||||
|
||||
Copyright (C) 1998-2005 Gilles Vollant
|
||||
|
||||
This code is a modified version of crypting code in Infozip distribution
|
||||
|
||||
The encryption/decryption parts of this source code (as opposed to the
|
||||
non-echoing password parts) were originally written in Europe. The
|
||||
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.)
|
||||
|
||||
This encryption code is a direct transcription of the algorithm from
|
||||
Roger Schlafly, described by Phil Katz in the file appnote.txt. This
|
||||
file (appnote.txt) is distributed with the PKZIP program (even in the
|
||||
version without encryption capabilities).
|
||||
|
||||
If you don't need crypting in your application, just define symbols
|
||||
NOCRYPT and NOUNCRYPT.
|
||||
|
||||
This code support the "Traditional PKWARE Encryption".
|
||||
|
||||
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
|
||||
Encryption is not supported.
|
||||
*/
|
||||
|
||||
#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
|
||||
|
||||
/***********************************************************************
|
||||
* Return the next byte in the pseudo-random sequence
|
||||
*/
|
||||
static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
|
||||
{
|
||||
unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
|
||||
* unpredictable manner on 16-bit systems; not a problem
|
||||
* with any known compiler so far, though */
|
||||
|
||||
temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
|
||||
return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* 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)
|
||||
{
|
||||
(*(pkeys+0)) = CRC32((*(pkeys+0)), c);
|
||||
(*(pkeys+1)) += (*(pkeys+0)) & 0xff;
|
||||
(*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
|
||||
{
|
||||
register int keyshift = (int)((*(pkeys+1)) >> 24);
|
||||
(*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Initialize the encryption keys and the random header according to
|
||||
* the given password.
|
||||
*/
|
||||
static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
|
||||
{
|
||||
*(pkeys+0) = 305419896L;
|
||||
*(pkeys+1) = 591751049L;
|
||||
*(pkeys+2) = 878082192L;
|
||||
while (*passwd != '\0') {
|
||||
update_keys(pkeys,pcrc_32_tab,(int)*passwd);
|
||||
passwd++;
|
||||
}
|
||||
}
|
||||
|
||||
#define zdecode(pkeys,pcrc_32_tab,c) \
|
||||
(update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
|
||||
|
||||
#define zencode(pkeys,pcrc_32_tab,c,t) \
|
||||
(t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
|
||||
|
||||
#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
|
||||
|
||||
#define RAND_HEAD_LEN 12
|
||||
/* "last resort" source for second part of crypt seed pattern */
|
||||
# ifndef ZCR_SEED2
|
||||
# define ZCR_SEED2 3141592654UL /* use PI as default pattern */
|
||||
# endif
|
||||
|
||||
static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting)
|
||||
const char *passwd; /* password string */
|
||||
unsigned char *buf; /* where to write header */
|
||||
int bufSize;
|
||||
unsigned long* pkeys;
|
||||
const unsigned long* pcrc_32_tab;
|
||||
unsigned long crcForCrypting;
|
||||
{
|
||||
int n; /* index in random header */
|
||||
int t; /* temporary */
|
||||
int c; /* random byte */
|
||||
unsigned char header[RAND_HEAD_LEN-2]; /* random header */
|
||||
static unsigned calls = 0; /* ensure different random header each time */
|
||||
|
||||
if (bufSize<RAND_HEAD_LEN)
|
||||
return 0;
|
||||
|
||||
/* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
|
||||
* output of rand() to get less predictability, since rand() is
|
||||
* often poorly implemented.
|
||||
*/
|
||||
if (++calls == 1)
|
||||
{
|
||||
srand((unsigned)(time(NULL) ^ ZCR_SEED2));
|
||||
}
|
||||
init_keys(passwd, pkeys, pcrc_32_tab);
|
||||
for (n = 0; n < RAND_HEAD_LEN-2; n++)
|
||||
{
|
||||
c = (rand() >> 7) & 0xff;
|
||||
header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
|
||||
}
|
||||
/* Encrypt random header (last two bytes is high word of crc) */
|
||||
init_keys(passwd, pkeys, pcrc_32_tab);
|
||||
for (n = 0; n < RAND_HEAD_LEN-2; n++)
|
||||
{
|
||||
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 >> 24) & 0xff, t);
|
||||
return n;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,177 +1,177 @@
|
||||
/* ioapi.c -- IO base function header for compress/uncompress .zip
|
||||
files using zlib + zip or unzip API
|
||||
|
||||
Version 1.01, May 8th, 2004
|
||||
|
||||
Copyright (C) 1998-2004 Gilles Vollant
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "zlib.h"
|
||||
#include "ioapi.h"
|
||||
|
||||
|
||||
|
||||
/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
|
||||
|
||||
#ifndef SEEK_CUR
|
||||
#define SEEK_CUR 1
|
||||
#endif
|
||||
|
||||
#ifndef SEEK_END
|
||||
#define SEEK_END 2
|
||||
#endif
|
||||
|
||||
#ifndef SEEK_SET
|
||||
#define SEEK_SET 0
|
||||
#endif
|
||||
|
||||
voidpf ZCALLBACK fopen_file_func OF((
|
||||
voidpf opaque,
|
||||
const char* filename,
|
||||
int mode));
|
||||
|
||||
uLong ZCALLBACK fread_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream,
|
||||
void* buf,
|
||||
uLong size));
|
||||
|
||||
uLong ZCALLBACK fwrite_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream,
|
||||
const void* buf,
|
||||
uLong size));
|
||||
|
||||
long ZCALLBACK ftell_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream));
|
||||
|
||||
long ZCALLBACK fseek_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream,
|
||||
uLong offset,
|
||||
int origin));
|
||||
|
||||
int ZCALLBACK fclose_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream));
|
||||
|
||||
int ZCALLBACK ferror_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream));
|
||||
|
||||
|
||||
voidpf ZCALLBACK fopen_file_func (opaque, filename, mode)
|
||||
voidpf opaque;
|
||||
const char* filename;
|
||||
int mode;
|
||||
{
|
||||
FILE* file = NULL;
|
||||
const char* mode_fopen = NULL;
|
||||
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
|
||||
mode_fopen = "rb";
|
||||
else
|
||||
if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
|
||||
mode_fopen = "r+b";
|
||||
else
|
||||
if (mode & ZLIB_FILEFUNC_MODE_CREATE)
|
||||
mode_fopen = "wb";
|
||||
|
||||
if ((filename!=NULL) && (mode_fopen != NULL))
|
||||
file = fopen(filename, mode_fopen);
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
uLong ZCALLBACK fread_file_func (opaque, stream, buf, size)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
void* buf;
|
||||
uLong size;
|
||||
{
|
||||
uLong ret;
|
||||
ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
const void* buf;
|
||||
uLong size;
|
||||
{
|
||||
uLong ret;
|
||||
ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
long ZCALLBACK ftell_file_func (opaque, stream)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
{
|
||||
long ret;
|
||||
ret = ftell((FILE *)stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
long ZCALLBACK fseek_file_func (opaque, stream, offset, origin)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
uLong offset;
|
||||
int origin;
|
||||
{
|
||||
int fseek_origin=0;
|
||||
long ret;
|
||||
switch (origin)
|
||||
{
|
||||
case ZLIB_FILEFUNC_SEEK_CUR :
|
||||
fseek_origin = SEEK_CUR;
|
||||
break;
|
||||
case ZLIB_FILEFUNC_SEEK_END :
|
||||
fseek_origin = SEEK_END;
|
||||
break;
|
||||
case ZLIB_FILEFUNC_SEEK_SET :
|
||||
fseek_origin = SEEK_SET;
|
||||
break;
|
||||
default: return -1;
|
||||
}
|
||||
ret = 0;
|
||||
fseek((FILE *)stream, offset, fseek_origin);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ZCALLBACK fclose_file_func (opaque, stream)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
{
|
||||
int ret;
|
||||
ret = fclose((FILE *)stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ZCALLBACK ferror_file_func (opaque, stream)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
{
|
||||
int ret;
|
||||
ret = ferror((FILE *)stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void fill_fopen_filefunc (pzlib_filefunc_def)
|
||||
zlib_filefunc_def* pzlib_filefunc_def;
|
||||
{
|
||||
pzlib_filefunc_def->zopen_file = fopen_file_func;
|
||||
pzlib_filefunc_def->zread_file = fread_file_func;
|
||||
pzlib_filefunc_def->zwrite_file = fwrite_file_func;
|
||||
pzlib_filefunc_def->ztell_file = ftell_file_func;
|
||||
pzlib_filefunc_def->zseek_file = fseek_file_func;
|
||||
pzlib_filefunc_def->zclose_file = fclose_file_func;
|
||||
pzlib_filefunc_def->zerror_file = ferror_file_func;
|
||||
pzlib_filefunc_def->opaque = NULL;
|
||||
}
|
||||
/* ioapi.c -- IO base function header for compress/uncompress .zip
|
||||
files using zlib + zip or unzip API
|
||||
|
||||
Version 1.01e, February 12th, 2005
|
||||
|
||||
Copyright (C) 1998-2005 Gilles Vollant
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "zlib.h"
|
||||
#include "ioapi.h"
|
||||
|
||||
|
||||
|
||||
/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
|
||||
|
||||
#ifndef SEEK_CUR
|
||||
#define SEEK_CUR 1
|
||||
#endif
|
||||
|
||||
#ifndef SEEK_END
|
||||
#define SEEK_END 2
|
||||
#endif
|
||||
|
||||
#ifndef SEEK_SET
|
||||
#define SEEK_SET 0
|
||||
#endif
|
||||
|
||||
voidpf ZCALLBACK fopen_file_func OF((
|
||||
voidpf opaque,
|
||||
const char* filename,
|
||||
int mode));
|
||||
|
||||
uLong ZCALLBACK fread_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream,
|
||||
void* buf,
|
||||
uLong size));
|
||||
|
||||
uLong ZCALLBACK fwrite_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream,
|
||||
const void* buf,
|
||||
uLong size));
|
||||
|
||||
long ZCALLBACK ftell_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream));
|
||||
|
||||
long ZCALLBACK fseek_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream,
|
||||
uLong offset,
|
||||
int origin));
|
||||
|
||||
int ZCALLBACK fclose_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream));
|
||||
|
||||
int ZCALLBACK ferror_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream));
|
||||
|
||||
|
||||
voidpf ZCALLBACK fopen_file_func (opaque, filename, mode)
|
||||
voidpf opaque;
|
||||
const char* filename;
|
||||
int mode;
|
||||
{
|
||||
FILE* file = NULL;
|
||||
const char* mode_fopen = NULL;
|
||||
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
|
||||
mode_fopen = "rb";
|
||||
else
|
||||
if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
|
||||
mode_fopen = "r+b";
|
||||
else
|
||||
if (mode & ZLIB_FILEFUNC_MODE_CREATE)
|
||||
mode_fopen = "wb";
|
||||
|
||||
if ((filename!=NULL) && (mode_fopen != NULL))
|
||||
file = fopen(filename, mode_fopen);
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
uLong ZCALLBACK fread_file_func (opaque, stream, buf, size)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
void* buf;
|
||||
uLong size;
|
||||
{
|
||||
uLong ret;
|
||||
ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
const void* buf;
|
||||
uLong size;
|
||||
{
|
||||
uLong ret;
|
||||
ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
long ZCALLBACK ftell_file_func (opaque, stream)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
{
|
||||
long ret;
|
||||
ret = ftell((FILE *)stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
long ZCALLBACK fseek_file_func (opaque, stream, offset, origin)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
uLong offset;
|
||||
int origin;
|
||||
{
|
||||
int fseek_origin=0;
|
||||
long ret;
|
||||
switch (origin)
|
||||
{
|
||||
case ZLIB_FILEFUNC_SEEK_CUR :
|
||||
fseek_origin = SEEK_CUR;
|
||||
break;
|
||||
case ZLIB_FILEFUNC_SEEK_END :
|
||||
fseek_origin = SEEK_END;
|
||||
break;
|
||||
case ZLIB_FILEFUNC_SEEK_SET :
|
||||
fseek_origin = SEEK_SET;
|
||||
break;
|
||||
default: return -1;
|
||||
}
|
||||
ret = 0;
|
||||
fseek((FILE *)stream, offset, fseek_origin);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ZCALLBACK fclose_file_func (opaque, stream)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
{
|
||||
int ret;
|
||||
ret = fclose((FILE *)stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ZCALLBACK ferror_file_func (opaque, stream)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
{
|
||||
int ret;
|
||||
ret = ferror((FILE *)stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void fill_fopen_filefunc (pzlib_filefunc_def)
|
||||
zlib_filefunc_def* pzlib_filefunc_def;
|
||||
{
|
||||
pzlib_filefunc_def->zopen_file = fopen_file_func;
|
||||
pzlib_filefunc_def->zread_file = fread_file_func;
|
||||
pzlib_filefunc_def->zwrite_file = fwrite_file_func;
|
||||
pzlib_filefunc_def->ztell_file = ftell_file_func;
|
||||
pzlib_filefunc_def->zseek_file = fseek_file_func;
|
||||
pzlib_filefunc_def->zclose_file = fclose_file_func;
|
||||
pzlib_filefunc_def->zerror_file = ferror_file_func;
|
||||
pzlib_filefunc_def->opaque = NULL;
|
||||
}
|
||||
|
@ -1,75 +1,75 @@
|
||||
/* ioapi.h -- IO base function header for compress/uncompress .zip
|
||||
files using zlib + zip or unzip API
|
||||
|
||||
Version 1.01, May 8th, 2004
|
||||
|
||||
Copyright (C) 1998-2004 Gilles Vollant
|
||||
*/
|
||||
|
||||
#ifndef _ZLIBIOAPI_H
|
||||
#define _ZLIBIOAPI_H
|
||||
|
||||
|
||||
#define ZLIB_FILEFUNC_SEEK_CUR (1)
|
||||
#define ZLIB_FILEFUNC_SEEK_END (2)
|
||||
#define ZLIB_FILEFUNC_SEEK_SET (0)
|
||||
|
||||
#define ZLIB_FILEFUNC_MODE_READ (1)
|
||||
#define ZLIB_FILEFUNC_MODE_WRITE (2)
|
||||
#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
|
||||
|
||||
#define ZLIB_FILEFUNC_MODE_EXISTING (4)
|
||||
#define ZLIB_FILEFUNC_MODE_CREATE (8)
|
||||
|
||||
|
||||
#ifndef ZCALLBACK
|
||||
|
||||
#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
|
||||
#define ZCALLBACK CALLBACK
|
||||
#else
|
||||
#define ZCALLBACK
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
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 *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 *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 *testerror_file_func) OF((voidpf opaque, voidpf stream));
|
||||
|
||||
typedef struct zlib_filefunc_def_s
|
||||
{
|
||||
open_file_func zopen_file;
|
||||
read_file_func zread_file;
|
||||
write_file_func zwrite_file;
|
||||
tell_file_func ztell_file;
|
||||
seek_file_func zseek_file;
|
||||
close_file_func zclose_file;
|
||||
testerror_file_func zerror_file;
|
||||
voidpf opaque;
|
||||
} zlib_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 ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size))
|
||||
#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 ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream))
|
||||
#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream))
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* ioapi.h -- IO base function header for compress/uncompress .zip
|
||||
files using zlib + zip or unzip API
|
||||
|
||||
Version 1.01e, February 12th, 2005
|
||||
|
||||
Copyright (C) 1998-2005 Gilles Vollant
|
||||
*/
|
||||
|
||||
#ifndef _ZLIBIOAPI_H
|
||||
#define _ZLIBIOAPI_H
|
||||
|
||||
|
||||
#define ZLIB_FILEFUNC_SEEK_CUR (1)
|
||||
#define ZLIB_FILEFUNC_SEEK_END (2)
|
||||
#define ZLIB_FILEFUNC_SEEK_SET (0)
|
||||
|
||||
#define ZLIB_FILEFUNC_MODE_READ (1)
|
||||
#define ZLIB_FILEFUNC_MODE_WRITE (2)
|
||||
#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
|
||||
|
||||
#define ZLIB_FILEFUNC_MODE_EXISTING (4)
|
||||
#define ZLIB_FILEFUNC_MODE_CREATE (8)
|
||||
|
||||
|
||||
#ifndef ZCALLBACK
|
||||
|
||||
#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
|
||||
#define ZCALLBACK CALLBACK
|
||||
#else
|
||||
#define ZCALLBACK
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
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 *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 *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 *testerror_file_func) OF((voidpf opaque, voidpf stream));
|
||||
|
||||
typedef struct zlib_filefunc_def_s
|
||||
{
|
||||
open_file_func zopen_file;
|
||||
read_file_func zread_file;
|
||||
write_file_func zwrite_file;
|
||||
tell_file_func ztell_file;
|
||||
seek_file_func zseek_file;
|
||||
close_file_func zclose_file;
|
||||
testerror_file_func zerror_file;
|
||||
voidpf opaque;
|
||||
} zlib_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 ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size))
|
||||
#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 ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream))
|
||||
#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream))
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,270 +1,270 @@
|
||||
/* iowin32.c -- IO base function header for compress/uncompress .zip
|
||||
files using zlib + zip or unzip API
|
||||
This IO API version uses the Win32 API (for Microsoft Windows)
|
||||
|
||||
Version 1.01, May 8th, 2004
|
||||
|
||||
Copyright (C) 1998-2004 Gilles Vollant
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "zlib.h"
|
||||
#include "ioapi.h"
|
||||
#include "iowin32.h"
|
||||
|
||||
#ifndef INVALID_HANDLE_VALUE
|
||||
#define INVALID_HANDLE_VALUE (0xFFFFFFFF)
|
||||
#endif
|
||||
|
||||
#ifndef INVALID_SET_FILE_POINTER
|
||||
#define INVALID_SET_FILE_POINTER ((DWORD)-1)
|
||||
#endif
|
||||
|
||||
voidpf ZCALLBACK win32_open_file_func OF((
|
||||
voidpf opaque,
|
||||
const char* filename,
|
||||
int mode));
|
||||
|
||||
uLong ZCALLBACK win32_read_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream,
|
||||
void* buf,
|
||||
uLong size));
|
||||
|
||||
uLong ZCALLBACK win32_write_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream,
|
||||
const void* buf,
|
||||
uLong size));
|
||||
|
||||
long ZCALLBACK win32_tell_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream));
|
||||
|
||||
long ZCALLBACK win32_seek_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream,
|
||||
uLong offset,
|
||||
int origin));
|
||||
|
||||
int ZCALLBACK win32_close_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream));
|
||||
|
||||
int ZCALLBACK win32_error_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream));
|
||||
|
||||
typedef struct
|
||||
{
|
||||
HANDLE hf;
|
||||
int error;
|
||||
} WIN32FILE_IOWIN;
|
||||
|
||||
voidpf ZCALLBACK win32_open_file_func (opaque, filename, mode)
|
||||
voidpf opaque;
|
||||
const char* filename;
|
||||
int mode;
|
||||
{
|
||||
const char* mode_fopen = NULL;
|
||||
DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ;
|
||||
HANDLE hFile = 0;
|
||||
voidpf ret=NULL;
|
||||
|
||||
dwDesiredAccess = dwShareMode = dwFlagsAndAttributes = 0;
|
||||
|
||||
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
|
||||
{
|
||||
dwDesiredAccess = GENERIC_READ;
|
||||
dwCreationDisposition = OPEN_EXISTING;
|
||||
dwShareMode = FILE_SHARE_READ;
|
||||
}
|
||||
else
|
||||
if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
|
||||
{
|
||||
dwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
|
||||
dwCreationDisposition = OPEN_EXISTING;
|
||||
}
|
||||
else
|
||||
if (mode & ZLIB_FILEFUNC_MODE_CREATE)
|
||||
{
|
||||
dwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
|
||||
dwCreationDisposition = CREATE_ALWAYS;
|
||||
}
|
||||
|
||||
if ((filename!=NULL) && (dwDesiredAccess != 0))
|
||||
hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL,
|
||||
dwCreationDisposition, dwFlagsAndAttributes, NULL);
|
||||
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
hFile = NULL;
|
||||
|
||||
if (hFile != NULL)
|
||||
{
|
||||
WIN32FILE_IOWIN w32fiow;
|
||||
w32fiow.hf = hFile;
|
||||
w32fiow.error = 0;
|
||||
ret = malloc(sizeof(WIN32FILE_IOWIN));
|
||||
if (ret==NULL)
|
||||
CloseHandle(hFile);
|
||||
else *((WIN32FILE_IOWIN*)ret) = w32fiow;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
uLong ZCALLBACK win32_read_file_func (opaque, stream, buf, size)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
void* buf;
|
||||
uLong size;
|
||||
{
|
||||
uLong ret=0;
|
||||
HANDLE hFile = NULL;
|
||||
if (stream!=NULL)
|
||||
hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
|
||||
if (hFile != NULL)
|
||||
if (!ReadFile(hFile, buf, size, &ret, NULL))
|
||||
{
|
||||
DWORD dwErr = GetLastError();
|
||||
if (dwErr == ERROR_HANDLE_EOF)
|
||||
dwErr = 0;
|
||||
((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
uLong ZCALLBACK win32_write_file_func (opaque, stream, buf, size)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
const void* buf;
|
||||
uLong size;
|
||||
{
|
||||
uLong ret=0;
|
||||
HANDLE hFile = NULL;
|
||||
if (stream!=NULL)
|
||||
hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
|
||||
|
||||
if (hFile !=NULL)
|
||||
if (!WriteFile(hFile, buf, size, &ret, NULL))
|
||||
{
|
||||
DWORD dwErr = GetLastError();
|
||||
if (dwErr == ERROR_HANDLE_EOF)
|
||||
dwErr = 0;
|
||||
((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
long ZCALLBACK win32_tell_file_func (opaque, stream)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
{
|
||||
long ret=-1;
|
||||
HANDLE hFile = NULL;
|
||||
if (stream!=NULL)
|
||||
hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
|
||||
if (hFile != NULL)
|
||||
{
|
||||
DWORD dwSet = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
|
||||
if (dwSet == INVALID_SET_FILE_POINTER)
|
||||
{
|
||||
DWORD dwErr = GetLastError();
|
||||
((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
|
||||
ret = -1;
|
||||
}
|
||||
else
|
||||
ret=(long)dwSet;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
long ZCALLBACK win32_seek_file_func (opaque, stream, offset, origin)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
uLong offset;
|
||||
int origin;
|
||||
{
|
||||
DWORD dwMoveMethod=0xFFFFFFFF;
|
||||
HANDLE hFile = NULL;
|
||||
|
||||
long ret=-1;
|
||||
if (stream!=NULL)
|
||||
hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
|
||||
switch (origin)
|
||||
{
|
||||
case ZLIB_FILEFUNC_SEEK_CUR :
|
||||
dwMoveMethod = FILE_CURRENT;
|
||||
break;
|
||||
case ZLIB_FILEFUNC_SEEK_END :
|
||||
dwMoveMethod = FILE_END;
|
||||
break;
|
||||
case ZLIB_FILEFUNC_SEEK_SET :
|
||||
dwMoveMethod = FILE_BEGIN;
|
||||
break;
|
||||
default: return -1;
|
||||
}
|
||||
|
||||
if (hFile != NULL)
|
||||
{
|
||||
DWORD dwSet = SetFilePointer(hFile, offset, NULL, dwMoveMethod);
|
||||
if (dwSet == INVALID_SET_FILE_POINTER)
|
||||
{
|
||||
DWORD dwErr = GetLastError();
|
||||
((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
|
||||
ret = -1;
|
||||
}
|
||||
else
|
||||
ret=0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ZCALLBACK win32_close_file_func (opaque, stream)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
{
|
||||
int ret=-1;
|
||||
|
||||
if (stream!=NULL)
|
||||
{
|
||||
HANDLE hFile;
|
||||
hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
|
||||
if (hFile != NULL)
|
||||
{
|
||||
CloseHandle(hFile);
|
||||
ret=0;
|
||||
}
|
||||
free(stream);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ZCALLBACK win32_error_file_func (opaque, stream)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
{
|
||||
int ret=-1;
|
||||
if (stream!=NULL)
|
||||
{
|
||||
ret = ((WIN32FILE_IOWIN*)stream) -> error;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void fill_win32_filefunc (pzlib_filefunc_def)
|
||||
zlib_filefunc_def* pzlib_filefunc_def;
|
||||
{
|
||||
pzlib_filefunc_def->zopen_file = win32_open_file_func;
|
||||
pzlib_filefunc_def->zread_file = win32_read_file_func;
|
||||
pzlib_filefunc_def->zwrite_file = win32_write_file_func;
|
||||
pzlib_filefunc_def->ztell_file = win32_tell_file_func;
|
||||
pzlib_filefunc_def->zseek_file = win32_seek_file_func;
|
||||
pzlib_filefunc_def->zclose_file = win32_close_file_func;
|
||||
pzlib_filefunc_def->zerror_file = win32_error_file_func;
|
||||
pzlib_filefunc_def->opaque=NULL;
|
||||
}
|
||||
/* iowin32.c -- IO base function header for compress/uncompress .zip
|
||||
files using zlib + zip or unzip API
|
||||
This IO API version uses the Win32 API (for Microsoft Windows)
|
||||
|
||||
Version 1.01e, February 12th, 2005
|
||||
|
||||
Copyright (C) 1998-2005 Gilles Vollant
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "zlib.h"
|
||||
#include "ioapi.h"
|
||||
#include "iowin32.h"
|
||||
|
||||
#ifndef INVALID_HANDLE_VALUE
|
||||
#define INVALID_HANDLE_VALUE (0xFFFFFFFF)
|
||||
#endif
|
||||
|
||||
#ifndef INVALID_SET_FILE_POINTER
|
||||
#define INVALID_SET_FILE_POINTER ((DWORD)-1)
|
||||
#endif
|
||||
|
||||
voidpf ZCALLBACK win32_open_file_func OF((
|
||||
voidpf opaque,
|
||||
const char* filename,
|
||||
int mode));
|
||||
|
||||
uLong ZCALLBACK win32_read_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream,
|
||||
void* buf,
|
||||
uLong size));
|
||||
|
||||
uLong ZCALLBACK win32_write_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream,
|
||||
const void* buf,
|
||||
uLong size));
|
||||
|
||||
long ZCALLBACK win32_tell_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream));
|
||||
|
||||
long ZCALLBACK win32_seek_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream,
|
||||
uLong offset,
|
||||
int origin));
|
||||
|
||||
int ZCALLBACK win32_close_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream));
|
||||
|
||||
int ZCALLBACK win32_error_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream));
|
||||
|
||||
typedef struct
|
||||
{
|
||||
HANDLE hf;
|
||||
int error;
|
||||
} WIN32FILE_IOWIN;
|
||||
|
||||
voidpf ZCALLBACK win32_open_file_func (opaque, filename, mode)
|
||||
voidpf opaque;
|
||||
const char* filename;
|
||||
int mode;
|
||||
{
|
||||
const char* mode_fopen = NULL;
|
||||
DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ;
|
||||
HANDLE hFile = 0;
|
||||
voidpf ret=NULL;
|
||||
|
||||
dwDesiredAccess = dwShareMode = dwFlagsAndAttributes = 0;
|
||||
|
||||
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
|
||||
{
|
||||
dwDesiredAccess = GENERIC_READ;
|
||||
dwCreationDisposition = OPEN_EXISTING;
|
||||
dwShareMode = FILE_SHARE_READ;
|
||||
}
|
||||
else
|
||||
if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
|
||||
{
|
||||
dwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
|
||||
dwCreationDisposition = OPEN_EXISTING;
|
||||
}
|
||||
else
|
||||
if (mode & ZLIB_FILEFUNC_MODE_CREATE)
|
||||
{
|
||||
dwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
|
||||
dwCreationDisposition = CREATE_ALWAYS;
|
||||
}
|
||||
|
||||
if ((filename!=NULL) && (dwDesiredAccess != 0))
|
||||
hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL,
|
||||
dwCreationDisposition, dwFlagsAndAttributes, NULL);
|
||||
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
hFile = NULL;
|
||||
|
||||
if (hFile != NULL)
|
||||
{
|
||||
WIN32FILE_IOWIN w32fiow;
|
||||
w32fiow.hf = hFile;
|
||||
w32fiow.error = 0;
|
||||
ret = malloc(sizeof(WIN32FILE_IOWIN));
|
||||
if (ret==NULL)
|
||||
CloseHandle(hFile);
|
||||
else *((WIN32FILE_IOWIN*)ret) = w32fiow;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
uLong ZCALLBACK win32_read_file_func (opaque, stream, buf, size)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
void* buf;
|
||||
uLong size;
|
||||
{
|
||||
uLong ret=0;
|
||||
HANDLE hFile = NULL;
|
||||
if (stream!=NULL)
|
||||
hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
|
||||
if (hFile != NULL)
|
||||
if (!ReadFile(hFile, buf, size, &ret, NULL))
|
||||
{
|
||||
DWORD dwErr = GetLastError();
|
||||
if (dwErr == ERROR_HANDLE_EOF)
|
||||
dwErr = 0;
|
||||
((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
uLong ZCALLBACK win32_write_file_func (opaque, stream, buf, size)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
const void* buf;
|
||||
uLong size;
|
||||
{
|
||||
uLong ret=0;
|
||||
HANDLE hFile = NULL;
|
||||
if (stream!=NULL)
|
||||
hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
|
||||
|
||||
if (hFile !=NULL)
|
||||
if (!WriteFile(hFile, buf, size, &ret, NULL))
|
||||
{
|
||||
DWORD dwErr = GetLastError();
|
||||
if (dwErr == ERROR_HANDLE_EOF)
|
||||
dwErr = 0;
|
||||
((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
long ZCALLBACK win32_tell_file_func (opaque, stream)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
{
|
||||
long ret=-1;
|
||||
HANDLE hFile = NULL;
|
||||
if (stream!=NULL)
|
||||
hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
|
||||
if (hFile != NULL)
|
||||
{
|
||||
DWORD dwSet = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
|
||||
if (dwSet == INVALID_SET_FILE_POINTER)
|
||||
{
|
||||
DWORD dwErr = GetLastError();
|
||||
((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
|
||||
ret = -1;
|
||||
}
|
||||
else
|
||||
ret=(long)dwSet;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
long ZCALLBACK win32_seek_file_func (opaque, stream, offset, origin)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
uLong offset;
|
||||
int origin;
|
||||
{
|
||||
DWORD dwMoveMethod=0xFFFFFFFF;
|
||||
HANDLE hFile = NULL;
|
||||
|
||||
long ret=-1;
|
||||
if (stream!=NULL)
|
||||
hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
|
||||
switch (origin)
|
||||
{
|
||||
case ZLIB_FILEFUNC_SEEK_CUR :
|
||||
dwMoveMethod = FILE_CURRENT;
|
||||
break;
|
||||
case ZLIB_FILEFUNC_SEEK_END :
|
||||
dwMoveMethod = FILE_END;
|
||||
break;
|
||||
case ZLIB_FILEFUNC_SEEK_SET :
|
||||
dwMoveMethod = FILE_BEGIN;
|
||||
break;
|
||||
default: return -1;
|
||||
}
|
||||
|
||||
if (hFile != NULL)
|
||||
{
|
||||
DWORD dwSet = SetFilePointer(hFile, offset, NULL, dwMoveMethod);
|
||||
if (dwSet == INVALID_SET_FILE_POINTER)
|
||||
{
|
||||
DWORD dwErr = GetLastError();
|
||||
((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
|
||||
ret = -1;
|
||||
}
|
||||
else
|
||||
ret=0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ZCALLBACK win32_close_file_func (opaque, stream)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
{
|
||||
int ret=-1;
|
||||
|
||||
if (stream!=NULL)
|
||||
{
|
||||
HANDLE hFile;
|
||||
hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
|
||||
if (hFile != NULL)
|
||||
{
|
||||
CloseHandle(hFile);
|
||||
ret=0;
|
||||
}
|
||||
free(stream);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ZCALLBACK win32_error_file_func (opaque, stream)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
{
|
||||
int ret=-1;
|
||||
if (stream!=NULL)
|
||||
{
|
||||
ret = ((WIN32FILE_IOWIN*)stream) -> error;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void fill_win32_filefunc (pzlib_filefunc_def)
|
||||
zlib_filefunc_def* pzlib_filefunc_def;
|
||||
{
|
||||
pzlib_filefunc_def->zopen_file = win32_open_file_func;
|
||||
pzlib_filefunc_def->zread_file = win32_read_file_func;
|
||||
pzlib_filefunc_def->zwrite_file = win32_write_file_func;
|
||||
pzlib_filefunc_def->ztell_file = win32_tell_file_func;
|
||||
pzlib_filefunc_def->zseek_file = win32_seek_file_func;
|
||||
pzlib_filefunc_def->zclose_file = win32_close_file_func;
|
||||
pzlib_filefunc_def->zerror_file = win32_error_file_func;
|
||||
pzlib_filefunc_def->opaque=NULL;
|
||||
}
|
||||
|
@ -1,21 +1,21 @@
|
||||
/* iowin32.h -- IO base function header for compress/uncompress .zip
|
||||
files using zlib + zip or unzip API
|
||||
This IO API version uses the Win32 API (for Microsoft Windows)
|
||||
|
||||
Version 1.01, May 8th, 2004
|
||||
|
||||
Copyright (C) 1998-2004 Gilles Vollant
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* iowin32.h -- IO base function header for compress/uncompress .zip
|
||||
files using zlib + zip or unzip API
|
||||
This IO API version uses the Win32 API (for Microsoft Windows)
|
||||
|
||||
Version 1.01e, February 12th, 2005
|
||||
|
||||
Copyright (C) 1998-2005 Gilles Vollant
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,420 +1,420 @@
|
||||
/*
|
||||
minizip.c
|
||||
Version 1.01b, May 30th, 2004
|
||||
|
||||
Copyright (C) 1998-2004 Gilles Vollant
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef unix
|
||||
# include <unistd.h>
|
||||
# include <utime.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
#else
|
||||
# include <direct.h>
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#include "zip.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define USEWIN32IOAPI
|
||||
#include "iowin32.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define WRITEBUFFERSIZE (16384)
|
||||
#define MAXFILENAME (256)
|
||||
|
||||
#ifdef WIN32
|
||||
uLong filetime(f, tmzip, dt)
|
||||
char *f; /* name of file to get info on */
|
||||
tm_zip *tmzip; /* return value: access, modific. and creation times */
|
||||
uLong *dt; /* dostime */
|
||||
{
|
||||
int ret = 0;
|
||||
{
|
||||
FILETIME ftLocal;
|
||||
HANDLE hFind;
|
||||
WIN32_FIND_DATA ff32;
|
||||
|
||||
hFind = FindFirstFile(f,&ff32);
|
||||
if (hFind != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal);
|
||||
FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0);
|
||||
FindClose(hFind);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
#ifdef unix
|
||||
uLong filetime(f, tmzip, dt)
|
||||
char *f; /* name of file to get info on */
|
||||
tm_zip *tmzip; /* return value: access, modific. and creation times */
|
||||
uLong *dt; /* dostime */
|
||||
{
|
||||
int ret=0;
|
||||
struct stat s; /* results of stat() */
|
||||
struct tm* filedate;
|
||||
time_t tm_t=0;
|
||||
|
||||
if (strcmp(f,"-")!=0)
|
||||
{
|
||||
char name[MAXFILENAME+1];
|
||||
int len = strlen(f);
|
||||
if (len > MAXFILENAME)
|
||||
len = MAXFILENAME;
|
||||
|
||||
strncpy(name, f,MAXFILENAME-1);
|
||||
/* strncpy doesnt append the trailing NULL, of the string is too long. */
|
||||
name[ MAXFILENAME ] = '\0';
|
||||
|
||||
if (name[len - 1] == '/')
|
||||
name[len - 1] = '\0';
|
||||
/* not all systems allow stat'ing a file with / appended */
|
||||
if (stat(name,&s)==0)
|
||||
{
|
||||
tm_t = s.st_mtime;
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
filedate = localtime(&tm_t);
|
||||
|
||||
tmzip->tm_sec = filedate->tm_sec;
|
||||
tmzip->tm_min = filedate->tm_min;
|
||||
tmzip->tm_hour = filedate->tm_hour;
|
||||
tmzip->tm_mday = filedate->tm_mday;
|
||||
tmzip->tm_mon = filedate->tm_mon ;
|
||||
tmzip->tm_year = filedate->tm_year;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
uLong filetime(f, tmzip, dt)
|
||||
char *f; /* name of file to get info on */
|
||||
tm_zip *tmzip; /* return value: access, modific. and creation times */
|
||||
uLong *dt; /* dostime */
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
int check_exist_file(filename)
|
||||
const char* filename;
|
||||
{
|
||||
FILE* ftestexist;
|
||||
int ret = 1;
|
||||
ftestexist = fopen(filename,"rb");
|
||||
if (ftestexist==NULL)
|
||||
ret = 0;
|
||||
else
|
||||
fclose(ftestexist);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void do_banner()
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
void do_help()
|
||||
{
|
||||
printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] file.zip [files_to_add]\n\n" \
|
||||
" -o Overwrite existing file.zip\n" \
|
||||
" -a Append to existing file.zip\n" \
|
||||
" -0 Store only\n" \
|
||||
" -1 Compress faster\n" \
|
||||
" -9 Compress better\n\n");
|
||||
}
|
||||
|
||||
/* calculate the CRC32 of a file,
|
||||
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)
|
||||
{
|
||||
unsigned long calculate_crc=0;
|
||||
int err=ZIP_OK;
|
||||
FILE * fin = fopen(filenameinzip,"rb");
|
||||
unsigned long size_read = 0;
|
||||
unsigned long total_read = 0;
|
||||
if (fin==NULL)
|
||||
{
|
||||
err = ZIP_ERRNO;
|
||||
}
|
||||
|
||||
if (err == ZIP_OK)
|
||||
do
|
||||
{
|
||||
err = ZIP_OK;
|
||||
size_read = (int)fread(buf,1,size_buf,fin);
|
||||
if (size_read < size_buf)
|
||||
if (feof(fin)==0)
|
||||
{
|
||||
printf("error in reading %s\n",filenameinzip);
|
||||
err = ZIP_ERRNO;
|
||||
}
|
||||
|
||||
if (size_read>0)
|
||||
calculate_crc = crc32(calculate_crc,buf,size_read);
|
||||
total_read += size_read;
|
||||
|
||||
} while ((err == ZIP_OK) && (size_read>0));
|
||||
|
||||
if (fin)
|
||||
fclose(fin);
|
||||
|
||||
*result_crc=calculate_crc;
|
||||
printf("file %s crc %x\n",filenameinzip,calculate_crc);
|
||||
return err;
|
||||
}
|
||||
|
||||
int main(argc,argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int i;
|
||||
int opt_overwrite=0;
|
||||
int opt_compress_level=Z_DEFAULT_COMPRESSION;
|
||||
int zipfilenamearg = 0;
|
||||
char filename_try[MAXFILENAME+16];
|
||||
int zipok;
|
||||
int err=0;
|
||||
int size_buf=0;
|
||||
void* buf=NULL;
|
||||
const char* password=NULL;
|
||||
|
||||
|
||||
do_banner();
|
||||
if (argc==1)
|
||||
{
|
||||
do_help();
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=1;i<argc;i++)
|
||||
{
|
||||
if ((*argv[i])=='-')
|
||||
{
|
||||
const char *p=argv[i]+1;
|
||||
|
||||
while ((*p)!='\0')
|
||||
{
|
||||
char c=*(p++);;
|
||||
if ((c=='o') || (c=='O'))
|
||||
opt_overwrite = 1;
|
||||
if ((c=='a') || (c=='A'))
|
||||
opt_overwrite = 2;
|
||||
if ((c>='0') && (c<='9'))
|
||||
opt_compress_level = c-'0';
|
||||
|
||||
if (((c=='p') || (c=='P')) && (i+1<argc))
|
||||
{
|
||||
password=argv[i+1];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (zipfilenamearg == 0)
|
||||
zipfilenamearg = i ;
|
||||
}
|
||||
}
|
||||
|
||||
size_buf = WRITEBUFFERSIZE;
|
||||
buf = (void*)malloc(size_buf);
|
||||
if (buf==NULL)
|
||||
{
|
||||
printf("Error allocating memory\n");
|
||||
return ZIP_INTERNALERROR;
|
||||
}
|
||||
|
||||
if (zipfilenamearg==0)
|
||||
zipok=0;
|
||||
else
|
||||
{
|
||||
int i,len;
|
||||
int dot_found=0;
|
||||
|
||||
zipok = 1 ;
|
||||
strncpy(filename_try, argv[zipfilenamearg],MAXFILENAME-1);
|
||||
/* strncpy doesnt append the trailing NULL, of the string is too long. */
|
||||
filename_try[ MAXFILENAME ] = '\0';
|
||||
|
||||
len=(int)strlen(filename_try);
|
||||
for (i=0;i<len;i++)
|
||||
if (filename_try[i]=='.')
|
||||
dot_found=1;
|
||||
|
||||
if (dot_found==0)
|
||||
strcat(filename_try,".zip");
|
||||
|
||||
if (opt_overwrite==2)
|
||||
{
|
||||
/* if the file don't exist, we not append file */
|
||||
if (check_exist_file(filename_try)==0)
|
||||
opt_overwrite=1;
|
||||
}
|
||||
else
|
||||
if (opt_overwrite==0)
|
||||
if (check_exist_file(filename_try)!=0)
|
||||
{
|
||||
char rep=0;
|
||||
do
|
||||
{
|
||||
char answer[128];
|
||||
int ret;
|
||||
printf("The file %s exists. Overwrite ? [y]es, [n]o, [a]ppend : ",filename_try);
|
||||
ret = scanf("%1s",answer);
|
||||
if (ret != 1)
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
rep = answer[0] ;
|
||||
if ((rep>='a') && (rep<='z'))
|
||||
rep -= 0x20;
|
||||
}
|
||||
while ((rep!='Y') && (rep!='N') && (rep!='A'));
|
||||
if (rep=='N')
|
||||
zipok = 0;
|
||||
if (rep=='A')
|
||||
opt_overwrite = 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (zipok==1)
|
||||
{
|
||||
zipFile zf;
|
||||
int errclose;
|
||||
# ifdef USEWIN32IOAPI
|
||||
zlib_filefunc_def ffunc;
|
||||
fill_win32_filefunc(&ffunc);
|
||||
zf = zipOpen2(filename_try,(opt_overwrite==2) ? 2 : 0,NULL,&ffunc);
|
||||
# else
|
||||
zf = zipOpen(filename_try,(opt_overwrite==2) ? 2 : 0);
|
||||
# endif
|
||||
|
||||
if (zf == NULL)
|
||||
{
|
||||
printf("error opening %s\n",filename_try);
|
||||
err= ZIP_ERRNO;
|
||||
}
|
||||
else
|
||||
printf("creating %s\n",filename_try);
|
||||
|
||||
for (i=zipfilenamearg+1;(i<argc) && (err==ZIP_OK);i++)
|
||||
{
|
||||
if (!((((*(argv[i]))=='-') || ((*(argv[i]))=='/')) &&
|
||||
((argv[i][1]=='o') || (argv[i][1]=='O') ||
|
||||
(argv[i][1]=='a') || (argv[i][1]=='A') ||
|
||||
(argv[i][1]=='p') || (argv[i][1]=='P') ||
|
||||
((argv[i][1]>='0') || (argv[i][1]<='9'))) &&
|
||||
(strlen(argv[i]) == 2)))
|
||||
{
|
||||
FILE * fin;
|
||||
int size_read;
|
||||
const char* filenameinzip = argv[i];
|
||||
zip_fileinfo zi;
|
||||
unsigned long crcFile=0;
|
||||
|
||||
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.dosDate = 0;
|
||||
zi.internal_fa = 0;
|
||||
zi.external_fa = 0;
|
||||
filetime(filenameinzip,&zi.tmz_date,&zi.dosDate);
|
||||
|
||||
/*
|
||||
err = zipOpenNewFileInZip(zf,filenameinzip,&zi,
|
||||
NULL,0,NULL,0,NULL / * comment * /,
|
||||
(opt_compress_level != 0) ? Z_DEFLATED : 0,
|
||||
opt_compress_level);
|
||||
*/
|
||||
if ((password != NULL) && (err==ZIP_OK))
|
||||
err = getFileCrc(filenameinzip,buf,size_buf,&crcFile);
|
||||
|
||||
err = zipOpenNewFileInZip3(zf,filenameinzip,&zi,
|
||||
NULL,0,NULL,0,NULL /* comment*/,
|
||||
(opt_compress_level != 0) ? Z_DEFLATED : 0,
|
||||
opt_compress_level,0,
|
||||
/* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
|
||||
-MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
|
||||
password,crcFile);
|
||||
|
||||
if (err != ZIP_OK)
|
||||
printf("error in opening %s in zipfile\n",filenameinzip);
|
||||
else
|
||||
{
|
||||
fin = fopen(filenameinzip,"rb");
|
||||
if (fin==NULL)
|
||||
{
|
||||
err=ZIP_ERRNO;
|
||||
printf("error in opening %s for reading\n",filenameinzip);
|
||||
}
|
||||
}
|
||||
|
||||
if (err == ZIP_OK)
|
||||
do
|
||||
{
|
||||
err = ZIP_OK;
|
||||
size_read = (int)fread(buf,1,size_buf,fin);
|
||||
if (size_read < size_buf)
|
||||
if (feof(fin)==0)
|
||||
{
|
||||
printf("error in reading %s\n",filenameinzip);
|
||||
err = ZIP_ERRNO;
|
||||
}
|
||||
|
||||
if (size_read>0)
|
||||
{
|
||||
err = zipWriteInFileInZip (zf,buf,size_read);
|
||||
if (err<0)
|
||||
{
|
||||
printf("error in writing %s in the zipfile\n",
|
||||
filenameinzip);
|
||||
}
|
||||
|
||||
}
|
||||
} while ((err == ZIP_OK) && (size_read>0));
|
||||
|
||||
if (fin)
|
||||
fclose(fin);
|
||||
|
||||
if (err<0)
|
||||
err=ZIP_ERRNO;
|
||||
else
|
||||
{
|
||||
err = zipCloseFileInZip(zf);
|
||||
if (err!=ZIP_OK)
|
||||
printf("error in closing %s in the zipfile\n",
|
||||
filenameinzip);
|
||||
}
|
||||
}
|
||||
}
|
||||
errclose = zipClose(zf,NULL);
|
||||
if (errclose != ZIP_OK)
|
||||
printf("error in closing %s\n",filename_try);
|
||||
}
|
||||
else
|
||||
{
|
||||
do_help();
|
||||
}
|
||||
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
minizip.c
|
||||
Version 1.01e, February 12th, 2005
|
||||
|
||||
Copyright (C) 1998-2005 Gilles Vollant
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef unix
|
||||
# include <unistd.h>
|
||||
# include <utime.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
#else
|
||||
# include <direct.h>
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#include "zip.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define USEWIN32IOAPI
|
||||
#include "iowin32.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define WRITEBUFFERSIZE (16384)
|
||||
#define MAXFILENAME (256)
|
||||
|
||||
#ifdef WIN32
|
||||
uLong filetime(f, tmzip, dt)
|
||||
char *f; /* name of file to get info on */
|
||||
tm_zip *tmzip; /* return value: access, modific. and creation times */
|
||||
uLong *dt; /* dostime */
|
||||
{
|
||||
int ret = 0;
|
||||
{
|
||||
FILETIME ftLocal;
|
||||
HANDLE hFind;
|
||||
WIN32_FIND_DATA ff32;
|
||||
|
||||
hFind = FindFirstFile(f,&ff32);
|
||||
if (hFind != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal);
|
||||
FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0);
|
||||
FindClose(hFind);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
#ifdef unix
|
||||
uLong filetime(f, tmzip, dt)
|
||||
char *f; /* name of file to get info on */
|
||||
tm_zip *tmzip; /* return value: access, modific. and creation times */
|
||||
uLong *dt; /* dostime */
|
||||
{
|
||||
int ret=0;
|
||||
struct stat s; /* results of stat() */
|
||||
struct tm* filedate;
|
||||
time_t tm_t=0;
|
||||
|
||||
if (strcmp(f,"-")!=0)
|
||||
{
|
||||
char name[MAXFILENAME+1];
|
||||
int len = strlen(f);
|
||||
if (len > MAXFILENAME)
|
||||
len = MAXFILENAME;
|
||||
|
||||
strncpy(name, f,MAXFILENAME-1);
|
||||
/* strncpy doesnt append the trailing NULL, of the string is too long. */
|
||||
name[ MAXFILENAME ] = '\0';
|
||||
|
||||
if (name[len - 1] == '/')
|
||||
name[len - 1] = '\0';
|
||||
/* not all systems allow stat'ing a file with / appended */
|
||||
if (stat(name,&s)==0)
|
||||
{
|
||||
tm_t = s.st_mtime;
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
filedate = localtime(&tm_t);
|
||||
|
||||
tmzip->tm_sec = filedate->tm_sec;
|
||||
tmzip->tm_min = filedate->tm_min;
|
||||
tmzip->tm_hour = filedate->tm_hour;
|
||||
tmzip->tm_mday = filedate->tm_mday;
|
||||
tmzip->tm_mon = filedate->tm_mon ;
|
||||
tmzip->tm_year = filedate->tm_year;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
uLong filetime(f, tmzip, dt)
|
||||
char *f; /* name of file to get info on */
|
||||
tm_zip *tmzip; /* return value: access, modific. and creation times */
|
||||
uLong *dt; /* dostime */
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
int check_exist_file(filename)
|
||||
const char* filename;
|
||||
{
|
||||
FILE* ftestexist;
|
||||
int ret = 1;
|
||||
ftestexist = fopen(filename,"rb");
|
||||
if (ftestexist==NULL)
|
||||
ret = 0;
|
||||
else
|
||||
fclose(ftestexist);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void do_banner()
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
void do_help()
|
||||
{
|
||||
printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] file.zip [files_to_add]\n\n" \
|
||||
" -o Overwrite existing file.zip\n" \
|
||||
" -a Append to existing file.zip\n" \
|
||||
" -0 Store only\n" \
|
||||
" -1 Compress faster\n" \
|
||||
" -9 Compress better\n\n");
|
||||
}
|
||||
|
||||
/* calculate the CRC32 of a file,
|
||||
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)
|
||||
{
|
||||
unsigned long calculate_crc=0;
|
||||
int err=ZIP_OK;
|
||||
FILE * fin = fopen(filenameinzip,"rb");
|
||||
unsigned long size_read = 0;
|
||||
unsigned long total_read = 0;
|
||||
if (fin==NULL)
|
||||
{
|
||||
err = ZIP_ERRNO;
|
||||
}
|
||||
|
||||
if (err == ZIP_OK)
|
||||
do
|
||||
{
|
||||
err = ZIP_OK;
|
||||
size_read = (int)fread(buf,1,size_buf,fin);
|
||||
if (size_read < size_buf)
|
||||
if (feof(fin)==0)
|
||||
{
|
||||
printf("error in reading %s\n",filenameinzip);
|
||||
err = ZIP_ERRNO;
|
||||
}
|
||||
|
||||
if (size_read>0)
|
||||
calculate_crc = crc32(calculate_crc,buf,size_read);
|
||||
total_read += size_read;
|
||||
|
||||
} while ((err == ZIP_OK) && (size_read>0));
|
||||
|
||||
if (fin)
|
||||
fclose(fin);
|
||||
|
||||
*result_crc=calculate_crc;
|
||||
printf("file %s crc %x\n",filenameinzip,calculate_crc);
|
||||
return err;
|
||||
}
|
||||
|
||||
int main(argc,argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int i;
|
||||
int opt_overwrite=0;
|
||||
int opt_compress_level=Z_DEFAULT_COMPRESSION;
|
||||
int zipfilenamearg = 0;
|
||||
char filename_try[MAXFILENAME+16];
|
||||
int zipok;
|
||||
int err=0;
|
||||
int size_buf=0;
|
||||
void* buf=NULL;
|
||||
const char* password=NULL;
|
||||
|
||||
|
||||
do_banner();
|
||||
if (argc==1)
|
||||
{
|
||||
do_help();
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=1;i<argc;i++)
|
||||
{
|
||||
if ((*argv[i])=='-')
|
||||
{
|
||||
const char *p=argv[i]+1;
|
||||
|
||||
while ((*p)!='\0')
|
||||
{
|
||||
char c=*(p++);;
|
||||
if ((c=='o') || (c=='O'))
|
||||
opt_overwrite = 1;
|
||||
if ((c=='a') || (c=='A'))
|
||||
opt_overwrite = 2;
|
||||
if ((c>='0') && (c<='9'))
|
||||
opt_compress_level = c-'0';
|
||||
|
||||
if (((c=='p') || (c=='P')) && (i+1<argc))
|
||||
{
|
||||
password=argv[i+1];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (zipfilenamearg == 0)
|
||||
zipfilenamearg = i ;
|
||||
}
|
||||
}
|
||||
|
||||
size_buf = WRITEBUFFERSIZE;
|
||||
buf = (void*)malloc(size_buf);
|
||||
if (buf==NULL)
|
||||
{
|
||||
printf("Error allocating memory\n");
|
||||
return ZIP_INTERNALERROR;
|
||||
}
|
||||
|
||||
if (zipfilenamearg==0)
|
||||
zipok=0;
|
||||
else
|
||||
{
|
||||
int i,len;
|
||||
int dot_found=0;
|
||||
|
||||
zipok = 1 ;
|
||||
strncpy(filename_try, argv[zipfilenamearg],MAXFILENAME-1);
|
||||
/* strncpy doesnt append the trailing NULL, of the string is too long. */
|
||||
filename_try[ MAXFILENAME ] = '\0';
|
||||
|
||||
len=(int)strlen(filename_try);
|
||||
for (i=0;i<len;i++)
|
||||
if (filename_try[i]=='.')
|
||||
dot_found=1;
|
||||
|
||||
if (dot_found==0)
|
||||
strcat(filename_try,".zip");
|
||||
|
||||
if (opt_overwrite==2)
|
||||
{
|
||||
/* if the file don't exist, we not append file */
|
||||
if (check_exist_file(filename_try)==0)
|
||||
opt_overwrite=1;
|
||||
}
|
||||
else
|
||||
if (opt_overwrite==0)
|
||||
if (check_exist_file(filename_try)!=0)
|
||||
{
|
||||
char rep=0;
|
||||
do
|
||||
{
|
||||
char answer[128];
|
||||
int ret;
|
||||
printf("The file %s exists. Overwrite ? [y]es, [n]o, [a]ppend : ",filename_try);
|
||||
ret = scanf("%1s",answer);
|
||||
if (ret != 1)
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
rep = answer[0] ;
|
||||
if ((rep>='a') && (rep<='z'))
|
||||
rep -= 0x20;
|
||||
}
|
||||
while ((rep!='Y') && (rep!='N') && (rep!='A'));
|
||||
if (rep=='N')
|
||||
zipok = 0;
|
||||
if (rep=='A')
|
||||
opt_overwrite = 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (zipok==1)
|
||||
{
|
||||
zipFile zf;
|
||||
int errclose;
|
||||
# ifdef USEWIN32IOAPI
|
||||
zlib_filefunc_def ffunc;
|
||||
fill_win32_filefunc(&ffunc);
|
||||
zf = zipOpen2(filename_try,(opt_overwrite==2) ? 2 : 0,NULL,&ffunc);
|
||||
# else
|
||||
zf = zipOpen(filename_try,(opt_overwrite==2) ? 2 : 0);
|
||||
# endif
|
||||
|
||||
if (zf == NULL)
|
||||
{
|
||||
printf("error opening %s\n",filename_try);
|
||||
err= ZIP_ERRNO;
|
||||
}
|
||||
else
|
||||
printf("creating %s\n",filename_try);
|
||||
|
||||
for (i=zipfilenamearg+1;(i<argc) && (err==ZIP_OK);i++)
|
||||
{
|
||||
if (!((((*(argv[i]))=='-') || ((*(argv[i]))=='/')) &&
|
||||
((argv[i][1]=='o') || (argv[i][1]=='O') ||
|
||||
(argv[i][1]=='a') || (argv[i][1]=='A') ||
|
||||
(argv[i][1]=='p') || (argv[i][1]=='P') ||
|
||||
((argv[i][1]>='0') || (argv[i][1]<='9'))) &&
|
||||
(strlen(argv[i]) == 2)))
|
||||
{
|
||||
FILE * fin;
|
||||
int size_read;
|
||||
const char* filenameinzip = argv[i];
|
||||
zip_fileinfo zi;
|
||||
unsigned long crcFile=0;
|
||||
|
||||
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.dosDate = 0;
|
||||
zi.internal_fa = 0;
|
||||
zi.external_fa = 0;
|
||||
filetime(filenameinzip,&zi.tmz_date,&zi.dosDate);
|
||||
|
||||
/*
|
||||
err = zipOpenNewFileInZip(zf,filenameinzip,&zi,
|
||||
NULL,0,NULL,0,NULL / * comment * /,
|
||||
(opt_compress_level != 0) ? Z_DEFLATED : 0,
|
||||
opt_compress_level);
|
||||
*/
|
||||
if ((password != NULL) && (err==ZIP_OK))
|
||||
err = getFileCrc(filenameinzip,buf,size_buf,&crcFile);
|
||||
|
||||
err = zipOpenNewFileInZip3(zf,filenameinzip,&zi,
|
||||
NULL,0,NULL,0,NULL /* comment*/,
|
||||
(opt_compress_level != 0) ? Z_DEFLATED : 0,
|
||||
opt_compress_level,0,
|
||||
/* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
|
||||
-MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
|
||||
password,crcFile);
|
||||
|
||||
if (err != ZIP_OK)
|
||||
printf("error in opening %s in zipfile\n",filenameinzip);
|
||||
else
|
||||
{
|
||||
fin = fopen(filenameinzip,"rb");
|
||||
if (fin==NULL)
|
||||
{
|
||||
err=ZIP_ERRNO;
|
||||
printf("error in opening %s for reading\n",filenameinzip);
|
||||
}
|
||||
}
|
||||
|
||||
if (err == ZIP_OK)
|
||||
do
|
||||
{
|
||||
err = ZIP_OK;
|
||||
size_read = (int)fread(buf,1,size_buf,fin);
|
||||
if (size_read < size_buf)
|
||||
if (feof(fin)==0)
|
||||
{
|
||||
printf("error in reading %s\n",filenameinzip);
|
||||
err = ZIP_ERRNO;
|
||||
}
|
||||
|
||||
if (size_read>0)
|
||||
{
|
||||
err = zipWriteInFileInZip (zf,buf,size_read);
|
||||
if (err<0)
|
||||
{
|
||||
printf("error in writing %s in the zipfile\n",
|
||||
filenameinzip);
|
||||
}
|
||||
|
||||
}
|
||||
} while ((err == ZIP_OK) && (size_read>0));
|
||||
|
||||
if (fin)
|
||||
fclose(fin);
|
||||
|
||||
if (err<0)
|
||||
err=ZIP_ERRNO;
|
||||
else
|
||||
{
|
||||
err = zipCloseFileInZip(zf);
|
||||
if (err!=ZIP_OK)
|
||||
printf("error in closing %s in the zipfile\n",
|
||||
filenameinzip);
|
||||
}
|
||||
}
|
||||
}
|
||||
errclose = zipClose(zf,NULL);
|
||||
if (errclose != ZIP_OK)
|
||||
printf("error in closing %s\n",filename_try);
|
||||
}
|
||||
else
|
||||
{
|
||||
do_help();
|
||||
}
|
||||
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,281 +1,281 @@
|
||||
/*
|
||||
Additional tools for Minizip
|
||||
Code: Xavier Roche '2004
|
||||
License: Same as ZLIB (www.gzip.org)
|
||||
*/
|
||||
|
||||
/* Code */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "zlib.h"
|
||||
#include "unzip.h"
|
||||
|
||||
#define READ_8(adr) ((unsigned char)*(adr))
|
||||
#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 WRITE_8(buff, n) do { \
|
||||
*((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \
|
||||
} while(0)
|
||||
#define WRITE_16(buff, n) do { \
|
||||
WRITE_8((unsigned char*)(buff), n); \
|
||||
WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \
|
||||
} while(0)
|
||||
#define WRITE_32(buff, n) do { \
|
||||
WRITE_16((unsigned char*)(buff), (n) & 0xffff); \
|
||||
WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \
|
||||
} while(0)
|
||||
|
||||
extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered)
|
||||
const char* file;
|
||||
const char* fileOut;
|
||||
const char* fileOutTmp;
|
||||
uLong* nRecovered;
|
||||
uLong* bytesRecovered;
|
||||
{
|
||||
int err = Z_OK;
|
||||
FILE* fpZip = fopen(file, "rb");
|
||||
FILE* fpOut = fopen(fileOut, "wb");
|
||||
FILE* fpOutCD = fopen(fileOutTmp, "wb");
|
||||
if (fpZip != NULL && fpOut != NULL) {
|
||||
int entries = 0;
|
||||
uLong totalBytes = 0;
|
||||
char header[30];
|
||||
char filename[256];
|
||||
char extra[1024];
|
||||
int offset = 0;
|
||||
int offsetCD = 0;
|
||||
while ( fread(header, 1, 30, fpZip) == 30 ) {
|
||||
int currentOffset = offset;
|
||||
|
||||
/* File entry */
|
||||
if (READ_32(header) == 0x04034b50) {
|
||||
unsigned int version = READ_16(header + 4);
|
||||
unsigned int gpflag = READ_16(header + 6);
|
||||
unsigned int method = READ_16(header + 8);
|
||||
unsigned int filetime = READ_16(header + 10);
|
||||
unsigned int filedate = READ_16(header + 12);
|
||||
unsigned int crc = READ_32(header + 14); /* crc */
|
||||
unsigned int cpsize = READ_32(header + 18); /* compressed size */
|
||||
unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */
|
||||
unsigned int fnsize = READ_16(header + 26); /* file name length */
|
||||
unsigned int extsize = READ_16(header + 28); /* extra field length */
|
||||
filename[0] = extra[0] = '\0';
|
||||
|
||||
/* Header */
|
||||
if (fwrite(header, 1, 30, fpOut) == 30) {
|
||||
offset += 30;
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Filename */
|
||||
if (fnsize > 0) {
|
||||
if (fread(filename, 1, fnsize, fpZip) == fnsize) {
|
||||
if (fwrite(filename, 1, fnsize, fpOut) == fnsize) {
|
||||
offset += fnsize;
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
err = Z_STREAM_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Extra field */
|
||||
if (extsize > 0) {
|
||||
if (fread(extra, 1, extsize, fpZip) == extsize) {
|
||||
if (fwrite(extra, 1, extsize, fpOut) == extsize) {
|
||||
offset += extsize;
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Data */
|
||||
{
|
||||
int dataSize = cpsize;
|
||||
if (dataSize == 0) {
|
||||
dataSize = uncpsize;
|
||||
}
|
||||
if (dataSize > 0) {
|
||||
char* data = malloc(dataSize);
|
||||
if (data != NULL) {
|
||||
if ((int)fread(data, 1, dataSize, fpZip) == dataSize) {
|
||||
if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) {
|
||||
offset += dataSize;
|
||||
totalBytes += dataSize;
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
}
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
}
|
||||
free(data);
|
||||
if (err != Z_OK) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
err = Z_MEM_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Central directory entry */
|
||||
{
|
||||
char header[46];
|
||||
char* comment = "";
|
||||
int comsize = (int) strlen(comment);
|
||||
WRITE_32(header, 0x02014b50);
|
||||
WRITE_16(header + 4, version);
|
||||
WRITE_16(header + 6, version);
|
||||
WRITE_16(header + 8, gpflag);
|
||||
WRITE_16(header + 10, method);
|
||||
WRITE_16(header + 12, filetime);
|
||||
WRITE_16(header + 14, filedate);
|
||||
WRITE_32(header + 16, crc);
|
||||
WRITE_32(header + 20, cpsize);
|
||||
WRITE_32(header + 24, uncpsize);
|
||||
WRITE_16(header + 28, fnsize);
|
||||
WRITE_16(header + 30, extsize);
|
||||
WRITE_16(header + 32, comsize);
|
||||
WRITE_16(header + 34, 0); /* disk # */
|
||||
WRITE_16(header + 36, 0); /* int attrb */
|
||||
WRITE_32(header + 38, 0); /* ext attrb */
|
||||
WRITE_32(header + 42, currentOffset);
|
||||
/* Header */
|
||||
if (fwrite(header, 1, 46, fpOutCD) == 46) {
|
||||
offsetCD += 46;
|
||||
|
||||
/* Filename */
|
||||
if (fnsize > 0) {
|
||||
if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) {
|
||||
offsetCD += fnsize;
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
err = Z_STREAM_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Extra field */
|
||||
if (extsize > 0) {
|
||||
if (fwrite(extra, 1, extsize, fpOutCD) == extsize) {
|
||||
offsetCD += extsize;
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Comment field */
|
||||
if (comsize > 0) {
|
||||
if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) {
|
||||
offsetCD += comsize;
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Success */
|
||||
entries++;
|
||||
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Final central directory */
|
||||
{
|
||||
int entriesZip = entries;
|
||||
char header[22];
|
||||
char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools";
|
||||
int comsize = (int) strlen(comment);
|
||||
if (entriesZip > 0xffff) {
|
||||
entriesZip = 0xffff;
|
||||
}
|
||||
WRITE_32(header, 0x06054b50);
|
||||
WRITE_16(header + 4, 0); /* disk # */
|
||||
WRITE_16(header + 6, 0); /* disk # */
|
||||
WRITE_16(header + 8, entriesZip); /* hack */
|
||||
WRITE_16(header + 10, entriesZip); /* hack */
|
||||
WRITE_32(header + 12, offsetCD); /* size of CD */
|
||||
WRITE_32(header + 16, offset); /* offset to CD */
|
||||
WRITE_16(header + 20, comsize); /* comment */
|
||||
|
||||
/* Header */
|
||||
if (fwrite(header, 1, 22, fpOutCD) == 22) {
|
||||
|
||||
/* Comment field */
|
||||
if (comsize > 0) {
|
||||
if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) {
|
||||
err = Z_ERRNO;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
}
|
||||
}
|
||||
|
||||
/* Final merge (file + central directory) */
|
||||
fclose(fpOutCD);
|
||||
if (err == Z_OK) {
|
||||
fpOutCD = fopen(fileOutTmp, "rb");
|
||||
if (fpOutCD != NULL) {
|
||||
int nRead;
|
||||
char buffer[8192];
|
||||
while ( (nRead = fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) {
|
||||
if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) {
|
||||
err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(fpOutCD);
|
||||
}
|
||||
}
|
||||
|
||||
/* Close */
|
||||
fclose(fpZip);
|
||||
fclose(fpOut);
|
||||
|
||||
/* Wipe temporary file */
|
||||
(void)remove(fileOutTmp);
|
||||
|
||||
/* Number of recovered entries */
|
||||
if (err == Z_OK) {
|
||||
if (nRecovered != NULL) {
|
||||
*nRecovered = entries;
|
||||
}
|
||||
if (bytesRecovered != NULL) {
|
||||
*bytesRecovered = totalBytes;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = Z_STREAM_ERROR;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
/*
|
||||
Additional tools for Minizip
|
||||
Code: Xavier Roche '2004
|
||||
License: Same as ZLIB (www.gzip.org)
|
||||
*/
|
||||
|
||||
/* Code */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "zlib.h"
|
||||
#include "unzip.h"
|
||||
|
||||
#define READ_8(adr) ((unsigned char)*(adr))
|
||||
#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 WRITE_8(buff, n) do { \
|
||||
*((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \
|
||||
} while(0)
|
||||
#define WRITE_16(buff, n) do { \
|
||||
WRITE_8((unsigned char*)(buff), n); \
|
||||
WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \
|
||||
} while(0)
|
||||
#define WRITE_32(buff, n) do { \
|
||||
WRITE_16((unsigned char*)(buff), (n) & 0xffff); \
|
||||
WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \
|
||||
} while(0)
|
||||
|
||||
extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered)
|
||||
const char* file;
|
||||
const char* fileOut;
|
||||
const char* fileOutTmp;
|
||||
uLong* nRecovered;
|
||||
uLong* bytesRecovered;
|
||||
{
|
||||
int err = Z_OK;
|
||||
FILE* fpZip = fopen(file, "rb");
|
||||
FILE* fpOut = fopen(fileOut, "wb");
|
||||
FILE* fpOutCD = fopen(fileOutTmp, "wb");
|
||||
if (fpZip != NULL && fpOut != NULL) {
|
||||
int entries = 0;
|
||||
uLong totalBytes = 0;
|
||||
char header[30];
|
||||
char filename[256];
|
||||
char extra[1024];
|
||||
int offset = 0;
|
||||
int offsetCD = 0;
|
||||
while ( fread(header, 1, 30, fpZip) == 30 ) {
|
||||
int currentOffset = offset;
|
||||
|
||||
/* File entry */
|
||||
if (READ_32(header) == 0x04034b50) {
|
||||
unsigned int version = READ_16(header + 4);
|
||||
unsigned int gpflag = READ_16(header + 6);
|
||||
unsigned int method = READ_16(header + 8);
|
||||
unsigned int filetime = READ_16(header + 10);
|
||||
unsigned int filedate = READ_16(header + 12);
|
||||
unsigned int crc = READ_32(header + 14); /* crc */
|
||||
unsigned int cpsize = READ_32(header + 18); /* compressed size */
|
||||
unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */
|
||||
unsigned int fnsize = READ_16(header + 26); /* file name length */
|
||||
unsigned int extsize = READ_16(header + 28); /* extra field length */
|
||||
filename[0] = extra[0] = '\0';
|
||||
|
||||
/* Header */
|
||||
if (fwrite(header, 1, 30, fpOut) == 30) {
|
||||
offset += 30;
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Filename */
|
||||
if (fnsize > 0) {
|
||||
if (fread(filename, 1, fnsize, fpZip) == fnsize) {
|
||||
if (fwrite(filename, 1, fnsize, fpOut) == fnsize) {
|
||||
offset += fnsize;
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
err = Z_STREAM_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Extra field */
|
||||
if (extsize > 0) {
|
||||
if (fread(extra, 1, extsize, fpZip) == extsize) {
|
||||
if (fwrite(extra, 1, extsize, fpOut) == extsize) {
|
||||
offset += extsize;
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Data */
|
||||
{
|
||||
int dataSize = cpsize;
|
||||
if (dataSize == 0) {
|
||||
dataSize = uncpsize;
|
||||
}
|
||||
if (dataSize > 0) {
|
||||
char* data = malloc(dataSize);
|
||||
if (data != NULL) {
|
||||
if ((int)fread(data, 1, dataSize, fpZip) == dataSize) {
|
||||
if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) {
|
||||
offset += dataSize;
|
||||
totalBytes += dataSize;
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
}
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
}
|
||||
free(data);
|
||||
if (err != Z_OK) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
err = Z_MEM_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Central directory entry */
|
||||
{
|
||||
char header[46];
|
||||
char* comment = "";
|
||||
int comsize = (int) strlen(comment);
|
||||
WRITE_32(header, 0x02014b50);
|
||||
WRITE_16(header + 4, version);
|
||||
WRITE_16(header + 6, version);
|
||||
WRITE_16(header + 8, gpflag);
|
||||
WRITE_16(header + 10, method);
|
||||
WRITE_16(header + 12, filetime);
|
||||
WRITE_16(header + 14, filedate);
|
||||
WRITE_32(header + 16, crc);
|
||||
WRITE_32(header + 20, cpsize);
|
||||
WRITE_32(header + 24, uncpsize);
|
||||
WRITE_16(header + 28, fnsize);
|
||||
WRITE_16(header + 30, extsize);
|
||||
WRITE_16(header + 32, comsize);
|
||||
WRITE_16(header + 34, 0); /* disk # */
|
||||
WRITE_16(header + 36, 0); /* int attrb */
|
||||
WRITE_32(header + 38, 0); /* ext attrb */
|
||||
WRITE_32(header + 42, currentOffset);
|
||||
/* Header */
|
||||
if (fwrite(header, 1, 46, fpOutCD) == 46) {
|
||||
offsetCD += 46;
|
||||
|
||||
/* Filename */
|
||||
if (fnsize > 0) {
|
||||
if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) {
|
||||
offsetCD += fnsize;
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
err = Z_STREAM_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Extra field */
|
||||
if (extsize > 0) {
|
||||
if (fwrite(extra, 1, extsize, fpOutCD) == extsize) {
|
||||
offsetCD += extsize;
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Comment field */
|
||||
if (comsize > 0) {
|
||||
if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) {
|
||||
offsetCD += comsize;
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Success */
|
||||
entries++;
|
||||
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Final central directory */
|
||||
{
|
||||
int entriesZip = entries;
|
||||
char header[22];
|
||||
char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools";
|
||||
int comsize = (int) strlen(comment);
|
||||
if (entriesZip > 0xffff) {
|
||||
entriesZip = 0xffff;
|
||||
}
|
||||
WRITE_32(header, 0x06054b50);
|
||||
WRITE_16(header + 4, 0); /* disk # */
|
||||
WRITE_16(header + 6, 0); /* disk # */
|
||||
WRITE_16(header + 8, entriesZip); /* hack */
|
||||
WRITE_16(header + 10, entriesZip); /* hack */
|
||||
WRITE_32(header + 12, offsetCD); /* size of CD */
|
||||
WRITE_32(header + 16, offset); /* offset to CD */
|
||||
WRITE_16(header + 20, comsize); /* comment */
|
||||
|
||||
/* Header */
|
||||
if (fwrite(header, 1, 22, fpOutCD) == 22) {
|
||||
|
||||
/* Comment field */
|
||||
if (comsize > 0) {
|
||||
if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) {
|
||||
err = Z_ERRNO;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
err = Z_ERRNO;
|
||||
}
|
||||
}
|
||||
|
||||
/* Final merge (file + central directory) */
|
||||
fclose(fpOutCD);
|
||||
if (err == Z_OK) {
|
||||
fpOutCD = fopen(fileOutTmp, "rb");
|
||||
if (fpOutCD != NULL) {
|
||||
int nRead;
|
||||
char buffer[8192];
|
||||
while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) {
|
||||
if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) {
|
||||
err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(fpOutCD);
|
||||
}
|
||||
}
|
||||
|
||||
/* Close */
|
||||
fclose(fpZip);
|
||||
fclose(fpOut);
|
||||
|
||||
/* Wipe temporary file */
|
||||
(void)remove(fileOutTmp);
|
||||
|
||||
/* Number of recovered entries */
|
||||
if (err == Z_OK) {
|
||||
if (nRecovered != NULL) {
|
||||
*nRecovered = entries;
|
||||
}
|
||||
if (bytesRecovered != NULL) {
|
||||
*bytesRecovered = totalBytes;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = Z_STREAM_ERROR;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
@ -1,31 +1,31 @@
|
||||
/*
|
||||
Additional tools for Minizip
|
||||
Code: Xavier Roche '2004
|
||||
License: Same as ZLIB (www.gzip.org)
|
||||
*/
|
||||
|
||||
#ifndef _zip_tools_H
|
||||
#define _zip_tools_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _ZLIB_H
|
||||
#include "zlib.h"
|
||||
#endif
|
||||
|
||||
#include "unzip.h"
|
||||
|
||||
/* Repair a ZIP file (missing central directory)
|
||||
file: file to recover
|
||||
fileOut: output file after recovery
|
||||
fileOutTmp: temporary file name used for recovery
|
||||
*/
|
||||
extern int ZEXPORT unzRepair(const char* file,
|
||||
const char* fileOut,
|
||||
const char* fileOutTmp,
|
||||
uLong* nRecovered,
|
||||
uLong* bytesRecovered);
|
||||
|
||||
#endif
|
||||
/*
|
||||
Additional tools for Minizip
|
||||
Code: Xavier Roche '2004
|
||||
License: Same as ZLIB (www.gzip.org)
|
||||
*/
|
||||
|
||||
#ifndef _zip_tools_H
|
||||
#define _zip_tools_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _ZLIB_H
|
||||
#include "zlib.h"
|
||||
#endif
|
||||
|
||||
#include "unzip.h"
|
||||
|
||||
/* Repair a ZIP file (missing central directory)
|
||||
file: file to recover
|
||||
fileOut: output file after recovery
|
||||
fileOutTmp: temporary file name used for recovery
|
||||
*/
|
||||
extern int ZEXPORT unzRepair(const char* file,
|
||||
const char* fileOut,
|
||||
const char* fileOutTmp,
|
||||
uLong* nRecovered,
|
||||
uLong* bytesRecovered);
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,352 +1,354 @@
|
||||
/* unzip.h -- IO for uncompress .zip files using zlib
|
||||
Version 1.01, May 8th, 2004
|
||||
|
||||
Copyright (C) 1998-2004 Gilles Vollant
|
||||
|
||||
This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
|
||||
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
|
||||
|
||||
|
||||
I WAIT FEEDBACK at mail info@winimage.com
|
||||
Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
|
||||
|
||||
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
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/* 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/
|
||||
PkWare has also a specification at :
|
||||
ftp://ftp.pkware.com/probdesc.zip
|
||||
*/
|
||||
|
||||
#ifndef _unz_H
|
||||
#define _unz_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _ZLIB_H
|
||||
#include "zlib.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ZLIBIOAPI_H
|
||||
#include "ioapi.h"
|
||||
#endif
|
||||
|
||||
#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
|
||||
/* like the STRICT of WIN32, we define a pointer that cannot be converted
|
||||
from (void*) without cast */
|
||||
typedef struct TagunzFile__ { int unused; } unzFile__;
|
||||
typedef unzFile__ *unzFile;
|
||||
#else
|
||||
typedef voidp unzFile;
|
||||
#endif
|
||||
|
||||
|
||||
#define UNZ_OK (0)
|
||||
#define UNZ_END_OF_LIST_OF_FILE (-100)
|
||||
#define UNZ_ERRNO (Z_ERRNO)
|
||||
#define UNZ_EOF (0)
|
||||
#define UNZ_PARAMERROR (-102)
|
||||
#define UNZ_BADZIPFILE (-103)
|
||||
#define UNZ_INTERNALERROR (-104)
|
||||
#define UNZ_CRCERROR (-105)
|
||||
|
||||
/* tm_unz contain date/time info */
|
||||
typedef struct tm_unz_s
|
||||
{
|
||||
uInt tm_sec; /* seconds after the minute - [0,59] */
|
||||
uInt tm_min; /* minutes after the hour - [0,59] */
|
||||
uInt tm_hour; /* hours since midnight - [0,23] */
|
||||
uInt tm_mday; /* day of the month - [1,31] */
|
||||
uInt tm_mon; /* months since January - [0,11] */
|
||||
uInt tm_year; /* years - [1980..2044] */
|
||||
} tm_unz;
|
||||
|
||||
/* unz_global_info structure contain global data about the ZIPfile
|
||||
These data comes from the end of central dir */
|
||||
typedef struct unz_global_info_s
|
||||
{
|
||||
uLong number_entry; /* total number of entries in
|
||||
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
|
||||
{
|
||||
uLong version; /* version made by 2 bytes */
|
||||
uLong version_needed; /* version needed to extract 2 bytes */
|
||||
uLong flag; /* general purpose bit flag 2 bytes */
|
||||
uLong compression_method; /* compression method 2 bytes */
|
||||
uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
|
||||
uLong crc; /* crc-32 4 bytes */
|
||||
uLong compressed_size; /* compressed size 4 bytes */
|
||||
uLong uncompressed_size; /* uncompressed size 4 bytes */
|
||||
uLong size_filename; /* filename length 2 bytes */
|
||||
uLong size_file_extra; /* extra field length 2 bytes */
|
||||
uLong size_file_comment; /* file comment length 2 bytes */
|
||||
|
||||
uLong disk_num_start; /* disk number start 2 bytes */
|
||||
uLong internal_fa; /* internal file attributes 2 bytes */
|
||||
uLong external_fa; /* external file attributes 4 bytes */
|
||||
|
||||
tm_unz tmu_date;
|
||||
} unz_file_info;
|
||||
|
||||
extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
|
||||
const char* fileName2,
|
||||
int iCaseSensitivity));
|
||||
/*
|
||||
Compare two filename (fileName1,fileName2).
|
||||
If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
|
||||
If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
|
||||
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,
|
||||
on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer
|
||||
"zlib/zlib113.zip".
|
||||
If the zipfile cannot be opened (file don't exist or in not valid), the
|
||||
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));
|
||||
/*
|
||||
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.
|
||||
If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
|
||||
these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
|
||||
return UNZ_OK if there is no problem. */
|
||||
|
||||
extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
|
||||
unz_global_info *pglobal_info));
|
||||
/*
|
||||
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));
|
||||
/*
|
||||
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));
|
||||
/*
|
||||
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.
|
||||
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));
|
||||
/*
|
||||
Try locate the file szFileName in the zipfile.
|
||||
For the iCaseSensitivity signification, see unzStringFileNameCompare
|
||||
|
||||
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
|
||||
{
|
||||
uLong pos_in_zip_directory; /* offset in zip file directory */
|
||||
uLong num_of_file; /* # of file */
|
||||
} unz_file_pos;
|
||||
|
||||
extern int ZEXPORT unzGetFilePos(
|
||||
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,
|
||||
uLong fileNameBufferSize,
|
||||
void *extraField,
|
||||
uLong extraFieldBufferSize,
|
||||
char *szComment,
|
||||
uLong commentBufferSize));
|
||||
/*
|
||||
Get Info about the current file
|
||||
if pfile_info!=NULL, the *pfile_info structure will contain somes info about
|
||||
the current file
|
||||
if szFileName!=NULL, the filemane string will be copied in szFileName
|
||||
(fileNameBufferSize is the size of the buffer)
|
||||
if extraField!=NULL, the extra field information will be copied in extraField
|
||||
(extraFieldBufferSize 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)
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
|
||||
/*
|
||||
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));
|
||||
/*
|
||||
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,
|
||||
int raw));
|
||||
/*
|
||||
Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
|
||||
if raw==1
|
||||
*method will receive method of compression, *level will receive level of
|
||||
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,
|
||||
int raw,
|
||||
const char* password));
|
||||
/*
|
||||
Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
|
||||
if raw==1
|
||||
*method will receive method of compression, *level will receive level of
|
||||
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
|
||||
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));
|
||||
/*
|
||||
Read bytes from the current file (opened by unzOpenCurrentFile)
|
||||
buf contain buffer where data must be copied
|
||||
len the size of buf.
|
||||
|
||||
return the number of byte copied if somes bytes are copied
|
||||
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 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));
|
||||
/*
|
||||
Read extra field from the current file (opened by unzOpenCurrentFile)
|
||||
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)
|
||||
|
||||
if buf==NULL, it return the size of the local extra field
|
||||
|
||||
if buf!=NULL, len is the size of the buffer, the extra header is copied in
|
||||
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);
|
||||
|
||||
/* Set the current file offset */
|
||||
extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _unz_H */
|
||||
/* unzip.h -- IO for uncompress .zip files using zlib
|
||||
Version 1.01e, February 12th, 2005
|
||||
|
||||
Copyright (C) 1998-2005 Gilles Vollant
|
||||
|
||||
This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
|
||||
WinZip, InfoZip tools and compatible.
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/* 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/
|
||||
PkWare has also a specification at :
|
||||
ftp://ftp.pkware.com/probdesc.zip
|
||||
*/
|
||||
|
||||
#ifndef _unz_H
|
||||
#define _unz_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _ZLIB_H
|
||||
#include "zlib.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ZLIBIOAPI_H
|
||||
#include "ioapi.h"
|
||||
#endif
|
||||
|
||||
#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
|
||||
/* like the STRICT of WIN32, we define a pointer that cannot be converted
|
||||
from (void*) without cast */
|
||||
typedef struct TagunzFile__ { int unused; } unzFile__;
|
||||
typedef unzFile__ *unzFile;
|
||||
#else
|
||||
typedef voidp unzFile;
|
||||
#endif
|
||||
|
||||
|
||||
#define UNZ_OK (0)
|
||||
#define UNZ_END_OF_LIST_OF_FILE (-100)
|
||||
#define UNZ_ERRNO (Z_ERRNO)
|
||||
#define UNZ_EOF (0)
|
||||
#define UNZ_PARAMERROR (-102)
|
||||
#define UNZ_BADZIPFILE (-103)
|
||||
#define UNZ_INTERNALERROR (-104)
|
||||
#define UNZ_CRCERROR (-105)
|
||||
|
||||
/* tm_unz contain date/time info */
|
||||
typedef struct tm_unz_s
|
||||
{
|
||||
uInt tm_sec; /* seconds after the minute - [0,59] */
|
||||
uInt tm_min; /* minutes after the hour - [0,59] */
|
||||
uInt tm_hour; /* hours since midnight - [0,23] */
|
||||
uInt tm_mday; /* day of the month - [1,31] */
|
||||
uInt tm_mon; /* months since January - [0,11] */
|
||||
uInt tm_year; /* years - [1980..2044] */
|
||||
} tm_unz;
|
||||
|
||||
/* unz_global_info structure contain global data about the ZIPfile
|
||||
These data comes from the end of central dir */
|
||||
typedef struct unz_global_info_s
|
||||
{
|
||||
uLong number_entry; /* total number of entries in
|
||||
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
|
||||
{
|
||||
uLong version; /* version made by 2 bytes */
|
||||
uLong version_needed; /* version needed to extract 2 bytes */
|
||||
uLong flag; /* general purpose bit flag 2 bytes */
|
||||
uLong compression_method; /* compression method 2 bytes */
|
||||
uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
|
||||
uLong crc; /* crc-32 4 bytes */
|
||||
uLong compressed_size; /* compressed size 4 bytes */
|
||||
uLong uncompressed_size; /* uncompressed size 4 bytes */
|
||||
uLong size_filename; /* filename length 2 bytes */
|
||||
uLong size_file_extra; /* extra field length 2 bytes */
|
||||
uLong size_file_comment; /* file comment length 2 bytes */
|
||||
|
||||
uLong disk_num_start; /* disk number start 2 bytes */
|
||||
uLong internal_fa; /* internal file attributes 2 bytes */
|
||||
uLong external_fa; /* external file attributes 4 bytes */
|
||||
|
||||
tm_unz tmu_date;
|
||||
} unz_file_info;
|
||||
|
||||
extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
|
||||
const char* fileName2,
|
||||
int iCaseSensitivity));
|
||||
/*
|
||||
Compare two filename (fileName1,fileName2).
|
||||
If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
|
||||
If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
|
||||
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,
|
||||
on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer
|
||||
"zlib/zlib113.zip".
|
||||
If the zipfile cannot be opened (file don't exist or in not valid), the
|
||||
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));
|
||||
/*
|
||||
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.
|
||||
If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
|
||||
these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
|
||||
return UNZ_OK if there is no problem. */
|
||||
|
||||
extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
|
||||
unz_global_info *pglobal_info));
|
||||
/*
|
||||
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));
|
||||
/*
|
||||
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));
|
||||
/*
|
||||
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.
|
||||
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));
|
||||
/*
|
||||
Try locate the file szFileName in the zipfile.
|
||||
For the iCaseSensitivity signification, see unzStringFileNameCompare
|
||||
|
||||
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
|
||||
{
|
||||
uLong pos_in_zip_directory; /* offset in zip file directory */
|
||||
uLong num_of_file; /* # of file */
|
||||
} unz_file_pos;
|
||||
|
||||
extern int ZEXPORT unzGetFilePos(
|
||||
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,
|
||||
uLong fileNameBufferSize,
|
||||
void *extraField,
|
||||
uLong extraFieldBufferSize,
|
||||
char *szComment,
|
||||
uLong commentBufferSize));
|
||||
/*
|
||||
Get Info about the current file
|
||||
if pfile_info!=NULL, the *pfile_info structure will contain somes info about
|
||||
the current file
|
||||
if szFileName!=NULL, the filemane string will be copied in szFileName
|
||||
(fileNameBufferSize is the size of the buffer)
|
||||
if extraField!=NULL, the extra field information will be copied in extraField
|
||||
(extraFieldBufferSize 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)
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
|
||||
/*
|
||||
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));
|
||||
/*
|
||||
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,
|
||||
int raw));
|
||||
/*
|
||||
Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
|
||||
if raw==1
|
||||
*method will receive method of compression, *level will receive level of
|
||||
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,
|
||||
int raw,
|
||||
const char* password));
|
||||
/*
|
||||
Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
|
||||
if raw==1
|
||||
*method will receive method of compression, *level will receive level of
|
||||
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
|
||||
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));
|
||||
/*
|
||||
Read bytes from the current file (opened by unzOpenCurrentFile)
|
||||
buf contain buffer where data must be copied
|
||||
len the size of buf.
|
||||
|
||||
return the number of byte copied if somes bytes are copied
|
||||
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 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));
|
||||
/*
|
||||
Read extra field from the current file (opened by unzOpenCurrentFile)
|
||||
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)
|
||||
|
||||
if buf==NULL, it return the size of the local extra field
|
||||
|
||||
if buf!=NULL, len is the size of the buffer, the extra header is copied in
|
||||
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);
|
||||
|
||||
/* Set the current file offset */
|
||||
extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _unz_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,234 +1,235 @@
|
||||
/* zip.h -- IO for compress .zip files using zlib
|
||||
Version 1.01, May 8th, 2004
|
||||
|
||||
Copyright (C) 1998-2004 Gilles Vollant
|
||||
|
||||
This unzip package allow creates .ZIP file, compatible with PKZip 2.04g
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/* 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/
|
||||
PkWare has also a specification at :
|
||||
ftp://ftp.pkware.com/probdesc.zip
|
||||
*/
|
||||
|
||||
#ifndef _zip_H
|
||||
#define _zip_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _ZLIB_H
|
||||
#include "zlib.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ZLIBIOAPI_H
|
||||
#include "ioapi.h"
|
||||
#endif
|
||||
|
||||
#if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
|
||||
/* like the STRICT of WIN32, we define a pointer that cannot be converted
|
||||
from (void*) without cast */
|
||||
typedef struct TagzipFile__ { int unused; } zipFile__;
|
||||
typedef zipFile__ *zipFile;
|
||||
#else
|
||||
typedef voidp zipFile;
|
||||
#endif
|
||||
|
||||
#define ZIP_OK (0)
|
||||
#define ZIP_EOF (0)
|
||||
#define ZIP_ERRNO (Z_ERRNO)
|
||||
#define ZIP_PARAMERROR (-102)
|
||||
#define ZIP_BADZIPFILE (-103)
|
||||
#define ZIP_INTERNALERROR (-104)
|
||||
|
||||
#ifndef DEF_MEM_LEVEL
|
||||
# if MAX_MEM_LEVEL >= 8
|
||||
# define DEF_MEM_LEVEL 8
|
||||
# else
|
||||
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
|
||||
# endif
|
||||
#endif
|
||||
/* default memLevel */
|
||||
|
||||
/* 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_hour; /* hours since midnight - [0,23] */
|
||||
uInt tm_mday; /* day of the month - [1,31] */
|
||||
uInt tm_mon; /* months since January - [0,11] */
|
||||
uInt tm_year; /* years - [1980..2044] */
|
||||
} tm_zip;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
tm_zip tmz_date; /* date in understandable format */
|
||||
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 */
|
||||
} zip_fileinfo;
|
||||
|
||||
typedef const char* zipcharpc;
|
||||
|
||||
|
||||
#define APPEND_STATUS_CREATE (0)
|
||||
#define APPEND_STATUS_CREATEAFTER (1)
|
||||
#define APPEND_STATUS_ADDINZIP (2)
|
||||
|
||||
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
|
||||
an Unix computer "zlib/zlib113.zip".
|
||||
if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip
|
||||
will be created at the end of the file.
|
||||
(useful if the file contain a self extractor code)
|
||||
if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will
|
||||
add files in existing zip (be sure you don't add file that doesn't exist)
|
||||
If the zipfile cannot be opened, the return value is NULL.
|
||||
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
|
||||
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,
|
||||
zipcharpc* globalcomment,
|
||||
zlib_filefunc_def* pzlib_filefunc_def));
|
||||
|
||||
extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
|
||||
const char* filename,
|
||||
const zip_fileinfo* zipfi,
|
||||
const void* extrafield_local,
|
||||
uInt size_extrafield_local,
|
||||
const void* extrafield_global,
|
||||
uInt size_extrafield_global,
|
||||
const char* comment,
|
||||
int method,
|
||||
int level));
|
||||
/*
|
||||
Open a file in the ZIP for writing.
|
||||
filename : the filename in zip (if NULL, '-' without quote will be used
|
||||
*zipfi contain supplemental information
|
||||
if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
|
||||
contains the extrafield data the the local header
|
||||
if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
|
||||
contains the extrafield data the the local header
|
||||
if comment != NULL, comment contain the comment string
|
||||
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,
|
||||
const zip_fileinfo* zipfi,
|
||||
const void* extrafield_local,
|
||||
uInt size_extrafield_local,
|
||||
const void* extrafield_global,
|
||||
uInt size_extrafield_global,
|
||||
const char* comment,
|
||||
int method,
|
||||
int level,
|
||||
int raw));
|
||||
|
||||
/*
|
||||
Same than zipOpenNewFileInZip, except if raw=1, we write raw file
|
||||
*/
|
||||
|
||||
extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file,
|
||||
const char* filename,
|
||||
const zip_fileinfo* zipfi,
|
||||
const void* extrafield_local,
|
||||
uInt size_extrafield_local,
|
||||
const void* extrafield_global,
|
||||
uInt size_extrafield_global,
|
||||
const char* comment,
|
||||
int method,
|
||||
int level,
|
||||
int raw,
|
||||
int windowBits,
|
||||
int memLevel,
|
||||
int strategy,
|
||||
const char* password,
|
||||
uLong crcForCtypting));
|
||||
|
||||
/*
|
||||
Same than zipOpenNewFileInZip2, except
|
||||
windowBits,memLevel,,strategy : see parameter strategy in deflateInit2
|
||||
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,
|
||||
unsigned len));
|
||||
/*
|
||||
Write data in the zipfile
|
||||
*/
|
||||
|
||||
extern int ZEXPORT zipCloseFileInZip OF((zipFile file));
|
||||
/*
|
||||
Close the current file in the zipfile
|
||||
*/
|
||||
|
||||
extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file,
|
||||
uLong uncompressed_size,
|
||||
uLong crc32));
|
||||
/*
|
||||
Close the current file in the zipfile, for fiel opened with
|
||||
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));
|
||||
/*
|
||||
Close the zipfile
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _zip_H */
|
||||
/* zip.h -- IO for compress .zip files using zlib
|
||||
Version 1.01e, February 12th, 2005
|
||||
|
||||
Copyright (C) 1998-2005 Gilles Vollant
|
||||
|
||||
This unzip package allow creates .ZIP file, compatible with PKZip 2.04g
|
||||
WinZip, InfoZip tools and compatible.
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/* 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/
|
||||
PkWare has also a specification at :
|
||||
ftp://ftp.pkware.com/probdesc.zip
|
||||
*/
|
||||
|
||||
#ifndef _zip_H
|
||||
#define _zip_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _ZLIB_H
|
||||
#include "zlib.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ZLIBIOAPI_H
|
||||
#include "ioapi.h"
|
||||
#endif
|
||||
|
||||
#if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
|
||||
/* like the STRICT of WIN32, we define a pointer that cannot be converted
|
||||
from (void*) without cast */
|
||||
typedef struct TagzipFile__ { int unused; } zipFile__;
|
||||
typedef zipFile__ *zipFile;
|
||||
#else
|
||||
typedef voidp zipFile;
|
||||
#endif
|
||||
|
||||
#define ZIP_OK (0)
|
||||
#define ZIP_EOF (0)
|
||||
#define ZIP_ERRNO (Z_ERRNO)
|
||||
#define ZIP_PARAMERROR (-102)
|
||||
#define ZIP_BADZIPFILE (-103)
|
||||
#define ZIP_INTERNALERROR (-104)
|
||||
|
||||
#ifndef DEF_MEM_LEVEL
|
||||
# if MAX_MEM_LEVEL >= 8
|
||||
# define DEF_MEM_LEVEL 8
|
||||
# else
|
||||
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
|
||||
# endif
|
||||
#endif
|
||||
/* default memLevel */
|
||||
|
||||
/* 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_hour; /* hours since midnight - [0,23] */
|
||||
uInt tm_mday; /* day of the month - [1,31] */
|
||||
uInt tm_mon; /* months since January - [0,11] */
|
||||
uInt tm_year; /* years - [1980..2044] */
|
||||
} tm_zip;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
tm_zip tmz_date; /* date in understandable format */
|
||||
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 */
|
||||
} zip_fileinfo;
|
||||
|
||||
typedef const char* zipcharpc;
|
||||
|
||||
|
||||
#define APPEND_STATUS_CREATE (0)
|
||||
#define APPEND_STATUS_CREATEAFTER (1)
|
||||
#define APPEND_STATUS_ADDINZIP (2)
|
||||
|
||||
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
|
||||
an Unix computer "zlib/zlib113.zip".
|
||||
if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip
|
||||
will be created at the end of the file.
|
||||
(useful if the file contain a self extractor code)
|
||||
if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will
|
||||
add files in existing zip (be sure you don't add file that doesn't exist)
|
||||
If the zipfile cannot be opened, the return value is NULL.
|
||||
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
|
||||
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,
|
||||
zipcharpc* globalcomment,
|
||||
zlib_filefunc_def* pzlib_filefunc_def));
|
||||
|
||||
extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
|
||||
const char* filename,
|
||||
const zip_fileinfo* zipfi,
|
||||
const void* extrafield_local,
|
||||
uInt size_extrafield_local,
|
||||
const void* extrafield_global,
|
||||
uInt size_extrafield_global,
|
||||
const char* comment,
|
||||
int method,
|
||||
int level));
|
||||
/*
|
||||
Open a file in the ZIP for writing.
|
||||
filename : the filename in zip (if NULL, '-' without quote will be used
|
||||
*zipfi contain supplemental information
|
||||
if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
|
||||
contains the extrafield data the the local header
|
||||
if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
|
||||
contains the extrafield data the the local header
|
||||
if comment != NULL, comment contain the comment string
|
||||
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,
|
||||
const zip_fileinfo* zipfi,
|
||||
const void* extrafield_local,
|
||||
uInt size_extrafield_local,
|
||||
const void* extrafield_global,
|
||||
uInt size_extrafield_global,
|
||||
const char* comment,
|
||||
int method,
|
||||
int level,
|
||||
int raw));
|
||||
|
||||
/*
|
||||
Same than zipOpenNewFileInZip, except if raw=1, we write raw file
|
||||
*/
|
||||
|
||||
extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file,
|
||||
const char* filename,
|
||||
const zip_fileinfo* zipfi,
|
||||
const void* extrafield_local,
|
||||
uInt size_extrafield_local,
|
||||
const void* extrafield_global,
|
||||
uInt size_extrafield_global,
|
||||
const char* comment,
|
||||
int method,
|
||||
int level,
|
||||
int raw,
|
||||
int windowBits,
|
||||
int memLevel,
|
||||
int strategy,
|
||||
const char* password,
|
||||
uLong crcForCtypting));
|
||||
|
||||
/*
|
||||
Same than zipOpenNewFileInZip2, except
|
||||
windowBits,memLevel,,strategy : see parameter strategy in deflateInit2
|
||||
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,
|
||||
unsigned len));
|
||||
/*
|
||||
Write data in the zipfile
|
||||
*/
|
||||
|
||||
extern int ZEXPORT zipCloseFileInZip OF((zipFile file));
|
||||
/*
|
||||
Close the current file in the zipfile
|
||||
*/
|
||||
|
||||
extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file,
|
||||
uLong uncompressed_size,
|
||||
uLong crc32));
|
||||
/*
|
||||
Close the current file in the zipfile, for fiel opened with
|
||||
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));
|
||||
/*
|
||||
Close the zipfile
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _zip_H */
|
||||
|
18
contrib/testzlib/rdtsc64.asm
Normal file
18
contrib/testzlib/rdtsc64.asm
Normal 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
|
BIN
contrib/testzlib/rdtsc64.obj
Normal file
BIN
contrib/testzlib/rdtsc64.obj
Normal file
Binary file not shown.
@ -1,149 +1,258 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
#include "zlib.h"
|
||||
|
||||
int ReadFileMemory(const char* filename,long* plFileSize,void** pFilePtr)
|
||||
{
|
||||
FILE* stream;
|
||||
void* ptr;
|
||||
int retVal=1;
|
||||
stream=fopen(filename, "rb");
|
||||
if (stream==NULL)
|
||||
return 0;
|
||||
|
||||
fseek(stream,0,SEEK_END);
|
||||
|
||||
*plFileSize=ftell(stream);
|
||||
fseek(stream,0,SEEK_SET);
|
||||
ptr=malloc((*plFileSize)+1);
|
||||
if (ptr==NULL)
|
||||
retVal=0;
|
||||
else
|
||||
{
|
||||
if (fread(ptr, 1, *plFileSize,stream) != (*plFileSize))
|
||||
retVal=0;
|
||||
}
|
||||
fclose(stream);
|
||||
*pFilePtr=ptr;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int BlockSizeCompress=0x8000;
|
||||
int BlockSizeUncompress=0x8000;
|
||||
int cprLevel=Z_DEFAULT_COMPRESSION ;
|
||||
long lFileSize;
|
||||
unsigned char* FilePtr;
|
||||
long lBufferSizeCpr;
|
||||
long lBufferSizeUncpr;
|
||||
long lCompressedSize=0;
|
||||
unsigned char* CprPtr;
|
||||
unsigned char* UncprPtr;
|
||||
long lSizeCpr,lSizeUncpr;
|
||||
DWORD dwGetTick;
|
||||
|
||||
if (argc<=1)
|
||||
{
|
||||
printf("run TestZlib <File> [BlockSizeCompress] [BlockSizeUncompress] [compres. level]\n");
|
||||
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);
|
||||
UncprPtr=(unsigned char*)malloc(lBufferSizeUncpr + BlockSizeUncompress);
|
||||
|
||||
dwGetTick=GetTickCount();
|
||||
{
|
||||
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;
|
||||
printf("total compress size = %u, in %u step\n",lSizeCpr,step);
|
||||
printf("time = %u msec = %f sec\n\n",dwGetTick,dwGetTick/(double)1000.);
|
||||
}
|
||||
|
||||
dwGetTick=GetTickCount();
|
||||
{
|
||||
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;
|
||||
printf("total uncompress size = %u, in %u step\n",lSizeUncpr,step);
|
||||
printf("time = %u msec = %f sec\n\n",dwGetTick,dwGetTick/(double)1000.);
|
||||
}
|
||||
|
||||
if (lSizeUncpr==lFileSize)
|
||||
{
|
||||
if (memcmp(FilePtr,UncprPtr,lFileSize)==0)
|
||||
printf("compare ok\n");
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
#include "zlib.h"
|
||||
|
||||
|
||||
void MyDoMinus64(LARGE_INTEGER *R,LARGE_INTEGER A,LARGE_INTEGER B)
|
||||
{
|
||||
R->HighPart = A.HighPart - B.HighPart;
|
||||
if (A.LowPart >= B.LowPart)
|
||||
R->LowPart = A.LowPart - B.LowPart;
|
||||
else
|
||||
{
|
||||
R->LowPart = A.LowPart - B.LowPart;
|
||||
R->HighPart --;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _AMD64_
|
||||
unsigned _int64 myrdtsc();
|
||||
void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64)
|
||||
{
|
||||
// printf("rdtsc = %I64x\n",myrdtsc());
|
||||
pbeginTime64->QuadPart=myrdtsc();
|
||||
}
|
||||
|
||||
LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf)
|
||||
{
|
||||
LARGE_INTEGER LIres;
|
||||
unsigned _int64 res=myrdtsc()-((unsigned _int64)(beginTime64.QuadPart));
|
||||
LIres.QuadPart=res;
|
||||
// printf("rdtsc = %I64x\n",myrdtsc());
|
||||
return LIres;
|
||||
}
|
||||
#else
|
||||
void myGetRDTSC32(LARGE_INTEGER * pbeginTime64)
|
||||
{
|
||||
DWORD dwEdx,dwEax;
|
||||
_asm
|
||||
{
|
||||
rdtsc
|
||||
mov dwEax,eax
|
||||
mov dwEdx,edx
|
||||
}
|
||||
pbeginTime64->LowPart=dwEax;
|
||||
pbeginTime64->HighPart=dwEdx;
|
||||
}
|
||||
|
||||
void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64)
|
||||
{
|
||||
myGetRDTSC32(pbeginTime64);
|
||||
}
|
||||
|
||||
LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf)
|
||||
{
|
||||
LARGE_INTEGER LIres,endTime64;
|
||||
myGetRDTSC32(&endTime64);
|
||||
|
||||
LIres.LowPart=LIres.HighPart=0;
|
||||
MyDoMinus64(&LIres,endTime64,beginTime64);
|
||||
return LIres;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void BeginCountPerfCounter(LARGE_INTEGER * pbeginTime64,BOOL fComputeTimeQueryPerf)
|
||||
{
|
||||
if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(pbeginTime64)))
|
||||
{
|
||||
pbeginTime64->LowPart = GetTickCount();
|
||||
pbeginTime64->HighPart = 0;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD GetMsecSincePerfCounter(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf)
|
||||
{
|
||||
LARGE_INTEGER endTime64,ticksPerSecond,ticks;
|
||||
DWORDLONG ticksShifted,tickSecShifted;
|
||||
DWORD dwLog=16+0;
|
||||
DWORD dwRet;
|
||||
if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(&endTime64)))
|
||||
dwRet = (GetTickCount() - beginTime64.LowPart)*1;
|
||||
else
|
||||
{
|
||||
MyDoMinus64(&ticks,endTime64,beginTime64);
|
||||
QueryPerformanceFrequency(&ticksPerSecond);
|
||||
|
||||
|
||||
{
|
||||
ticksShifted = Int64ShrlMod32(*(DWORDLONG*)&ticks,dwLog);
|
||||
tickSecShifted = Int64ShrlMod32(*(DWORDLONG*)&ticksPerSecond,dwLog);
|
||||
|
||||
}
|
||||
|
||||
dwRet = (DWORD)((((DWORD)ticksShifted)*1000)/(DWORD)(tickSecShifted));
|
||||
dwRet *=1;
|
||||
}
|
||||
return dwRet;
|
||||
}
|
||||
|
||||
int ReadFileMemory(const char* filename,long* plFileSize,void** pFilePtr)
|
||||
{
|
||||
FILE* stream;
|
||||
void* ptr;
|
||||
int retVal=1;
|
||||
stream=fopen(filename, "rb");
|
||||
if (stream==NULL)
|
||||
return 0;
|
||||
|
||||
fseek(stream,0,SEEK_END);
|
||||
|
||||
*plFileSize=ftell(stream);
|
||||
fseek(stream,0,SEEK_SET);
|
||||
ptr=malloc((*plFileSize)+1);
|
||||
if (ptr==NULL)
|
||||
retVal=0;
|
||||
else
|
||||
{
|
||||
if (fread(ptr, 1, *plFileSize,stream) != (*plFileSize))
|
||||
retVal=0;
|
||||
}
|
||||
fclose(stream);
|
||||
*pFilePtr=ptr;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int BlockSizeCompress=0x8000;
|
||||
int BlockSizeUncompress=0x8000;
|
||||
int cprLevel=Z_DEFAULT_COMPRESSION ;
|
||||
long lFileSize;
|
||||
unsigned char* FilePtr;
|
||||
long lBufferSizeCpr;
|
||||
long lBufferSizeUncpr;
|
||||
long lCompressedSize=0;
|
||||
unsigned char* CprPtr;
|
||||
unsigned char* UncprPtr;
|
||||
long lSizeCpr,lSizeUncpr;
|
||||
DWORD dwGetTick,dwMsecQP;
|
||||
LARGE_INTEGER li_qp,li_rdtsc,dwResRdtsc;
|
||||
|
||||
if (argc<=1)
|
||||
{
|
||||
printf("run TestZlib <File> [BlockSizeCompress] [BlockSizeUncompress] [compres. level]\n");
|
||||
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;
|
||||
}
|
||||
|
10
contrib/testzlib/testzlib.txt
Normal file
10
contrib/testzlib/testzlib.txt
Normal 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
|
32
contrib/testzlib/testzlib8.sln
Normal file
32
contrib/testzlib/testzlib8.sln
Normal 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
|
638
contrib/testzlib/testzlib8.vcproj
Normal file
638
contrib/testzlib/testzlib8.vcproj
Normal 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.
@ -2,8 +2,8 @@
|
||||
|
||||
#define IDR_VERSION1 1
|
||||
IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
|
||||
FILEVERSION 1,2,2,2
|
||||
PRODUCTVERSION 1,2,2,2
|
||||
FILEVERSION 1,2,2,3
|
||||
PRODUCTVERSION 1,2,2,3
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
FILEFLAGS 0
|
||||
FILEOS VOS_DOS_WINDOWS32
|
||||
@ -17,7 +17,7 @@ BEGIN
|
||||
|
||||
BEGIN
|
||||
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 "OriginalFilename", "zlib.dll\0"
|
||||
VALUE "ProductName", "ZLib.DLL\0"
|
||||
|
6
crc32.c
6
crc32.c
@ -1,5 +1,5 @@
|
||||
/* 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
|
||||
*
|
||||
* 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--;
|
||||
}
|
||||
|
||||
buf4 = (const u4 FAR *)buf;
|
||||
buf4 = (const u4 FAR *)(const void FAR *)buf;
|
||||
while (len >= 32) {
|
||||
DOLIT32;
|
||||
len -= 32;
|
||||
@ -313,7 +313,7 @@ local unsigned long crc32_big(crc, buf, len)
|
||||
len--;
|
||||
}
|
||||
|
||||
buf4 = (const u4 FAR *)buf;
|
||||
buf4 = (const u4 FAR *)(const void FAR *)buf;
|
||||
buf4--;
|
||||
while (len >= 32) {
|
||||
DOBIG32;
|
||||
|
27
deflate.c
27
deflate.c
@ -1,5 +1,5 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
@ -52,7 +52,7 @@
|
||||
#include "deflate.h"
|
||||
|
||||
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
|
||||
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 > MAX_DIST(s)) {
|
||||
length = MAX_DIST(s);
|
||||
#ifndef USE_DICT_HEAD
|
||||
dictionary += dictLength - length; /* use the tail of the dictionary */
|
||||
#endif
|
||||
}
|
||||
zmemcpy(s->window, dictionary, length);
|
||||
s->strstart = length;
|
||||
@ -452,6 +450,25 @@ int ZEXPORT deflateParams(strm, level, strategy)
|
||||
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
|
||||
* 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_available = 0;
|
||||
s->ins_h = 0;
|
||||
#ifndef FASTEST
|
||||
#ifdef ASMV
|
||||
match_init(); /* initialize the asm code */
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef FASTEST
|
||||
|
@ -4,6 +4,13 @@ fitblk.c
|
||||
compress just enough input to nearly fill a requested output size
|
||||
- zlib isn't designed to do this, but fitblk does it anyway
|
||||
|
||||
gun.c
|
||||
uncompress a gzip file
|
||||
- illustrates the use of inflateBack() for high speed file-to-file
|
||||
decompression using call-back functions
|
||||
- is approximately twice as fast as gzip -d
|
||||
- also provides Unix uncompress functionality, again twice as fast
|
||||
|
||||
gzappend.c
|
||||
append to a gzip file
|
||||
- illustrates the use of the Z_BLOCK flush parameter for inflate()
|
||||
@ -27,3 +34,4 @@ zlib_how.html
|
||||
zpipe.c
|
||||
reads and writes zlib streams from stdin to stdout
|
||||
- illustrates the proper use of deflate() and inflate()
|
||||
- deeply commented in zlib_how.html (see above)
|
||||
|
692
examples/gun.c
Normal file
692
examples/gun.c
Normal 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;
|
||||
}
|
@ -420,10 +420,11 @@ The output of <tt>inflate()</tt> is handled identically to that of <tt>deflate()
|
||||
}
|
||||
</b></pre>
|
||||
The inner <tt>do</tt>-loop ends when <tt>inflate()</tt> has no more output as indicated
|
||||
by not filling the output buffer, just as for <tt>deflate()</tt>.
|
||||
by not filling the output buffer, just as for <tt>deflate()</tt>. In this case, we cannot
|
||||
assert that <tt>strm.avail_in</tt> will be zero, since the deflate stream may end before the file
|
||||
does.
|
||||
<pre><b>
|
||||
} while (strm.avail_out == 0);
|
||||
assert(strm.avail_in == 0); /* all input will be used */
|
||||
</b></pre><!-- -->
|
||||
The outer <tt>do</tt>-loop ends when <tt>inflate()</tt> reports that it has reached the
|
||||
end of the input <em>zlib</em> stream, has completed the decompression and integrity
|
||||
|
@ -7,6 +7,7 @@
|
||||
1.1 8 Nov 2004 Add void casting for unused return values
|
||||
Use switch statement for inflate() return values
|
||||
1.2 9 Nov 2004 Add assertions to document zlib guarantees
|
||||
1.3 6 Apr 2005 Remove incorrect assertion in inf()
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@ -127,7 +128,6 @@ int inf(FILE *source, FILE *dest)
|
||||
return Z_ERRNO;
|
||||
}
|
||||
} while (strm.avail_out == 0);
|
||||
assert(strm.avail_in == 0); /* all input will be used */
|
||||
|
||||
/* done when inflate() says it's done */
|
||||
} while (ret != Z_STREAM_END);
|
||||
|
29
gzio.c
29
gzio.c
@ -1,5 +1,5 @@
|
||||
/* 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
|
||||
*
|
||||
* 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->stream.avail_in == 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) {
|
||||
s->z_eof = 1;
|
||||
if (ferror(s->file)) s->z_err = Z_ERRNO;
|
||||
@ -300,7 +300,7 @@ local void check_header(s)
|
||||
if (len < 2) {
|
||||
if (len) s->inbuf[0] = s->stream.next_in[0];
|
||||
errno = 0;
|
||||
len = fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
|
||||
len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
|
||||
if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO;
|
||||
s->stream.avail_in += len;
|
||||
s->stream.next_in = s->inbuf;
|
||||
@ -415,6 +415,7 @@ int ZEXPORT gzread (file, buf, len)
|
||||
s->stream.avail_out--;
|
||||
s->back = EOF;
|
||||
s->out++;
|
||||
start++;
|
||||
if (s->last) {
|
||||
s->z_err = Z_STREAM_END;
|
||||
return 1;
|
||||
@ -436,8 +437,8 @@ int ZEXPORT gzread (file, buf, len)
|
||||
s->stream.avail_in -= n;
|
||||
}
|
||||
if (s->stream.avail_out > 0) {
|
||||
s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out,
|
||||
s->file);
|
||||
s->stream.avail_out -=
|
||||
(uInt)fread(next_out, 1, s->stream.avail_out, s->file);
|
||||
}
|
||||
len -= s->stream.avail_out;
|
||||
s->in += len;
|
||||
@ -448,17 +449,13 @@ int ZEXPORT gzread (file, buf, len)
|
||||
if (s->stream.avail_in == 0 && !s->z_eof) {
|
||||
|
||||
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) {
|
||||
s->z_eof = 1;
|
||||
if (ferror(s->file)) {
|
||||
s->z_err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
if (feof(s->file)) { /* avoid error for empty file */
|
||||
s->z_err = Z_STREAM_END;
|
||||
break;
|
||||
}
|
||||
}
|
||||
s->stream.next_in = s->inbuf;
|
||||
}
|
||||
@ -902,6 +899,18 @@ int ZEXPORT gzeof (file)
|
||||
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
|
||||
*/
|
||||
|
12
inflate.c
12
inflate.c
@ -1,5 +1,5 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
@ -1334,11 +1334,15 @@ z_streamp source;
|
||||
/* copy state */
|
||||
zmemcpy(dest, source, sizeof(z_stream));
|
||||
zmemcpy(copy, state, sizeof(struct inflate_state));
|
||||
copy->lencode = copy->codes + (state->lencode - state->codes);
|
||||
copy->distcode = copy->codes + (state->distcode - state->codes);
|
||||
if (state->lencode >= 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);
|
||||
if (window != Z_NULL)
|
||||
zmemcpy(window, state->window, 1U << state->wbits);
|
||||
zmemcpy(window, state->window, (uInt)(1U << state->wbits));
|
||||
copy->window = window;
|
||||
dest->state = (voidpf)copy;
|
||||
return Z_OK;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
#define MAXBITS 15
|
||||
|
||||
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
|
||||
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};
|
||||
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,
|
||||
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 */
|
||||
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,
|
||||
@ -262,7 +262,7 @@ unsigned short FAR *work;
|
||||
drop = root;
|
||||
|
||||
/* increment past last table */
|
||||
next += 1U << curr;
|
||||
next += (unsigned)(1U << curr);
|
||||
|
||||
/* determine length of next table */
|
||||
curr = len - drop;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
@ -295,6 +295,8 @@ int main(argc, argv)
|
||||
break;
|
||||
argc--, argv++;
|
||||
}
|
||||
if (outmode[3] == ' ')
|
||||
outmode[3] = 0;
|
||||
if (argc == 0) {
|
||||
SET_BINARY_MODE(stdin);
|
||||
SET_BINARY_MODE(stdout);
|
||||
|
@ -25,10 +25,10 @@
|
||||
<QPG:Files>
|
||||
<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="../libz.so.1.2.2.2" 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.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.2.2.2"/>
|
||||
<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/" user="root:bin" permission="644"/>
|
||||
<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.3"/>
|
||||
<QPG:Add file="../libz.so.1.2.2.3" install="/opt/lib/" component="slib"/>
|
||||
</QPG:Files>
|
||||
|
||||
<QPG:PackageFilter>
|
||||
@ -63,7 +63,7 @@
|
||||
</QPM:ProductDescription>
|
||||
|
||||
<QPM:ReleaseDescription>
|
||||
<QPM:ReleaseVersion>1.2.2.2</QPM:ReleaseVersion>
|
||||
<QPM:ReleaseVersion>1.2.2.3</QPM:ReleaseVersion>
|
||||
<QPM:ReleaseUrgency>Medium</QPM:ReleaseUrgency>
|
||||
<QPM:ReleaseStability>Stable</QPM:ReleaseStability>
|
||||
<QPM:ReleaseNoteMinor></QPM:ReleaseNoteMinor>
|
||||
|
@ -5,8 +5,8 @@ VS_VERSION_INFO VERSIONINFO
|
||||
#else
|
||||
VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
|
||||
#endif
|
||||
FILEVERSION 1,2,2,2
|
||||
PRODUCTVERSION 1,2,2,2
|
||||
FILEVERSION 1,2,2,3
|
||||
PRODUCTVERSION 1,2,2,3
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 1
|
||||
@ -23,12 +23,12 @@ BEGIN
|
||||
//language ID = U.S. English, char set = Windows, Multilingual
|
||||
BEGIN
|
||||
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 "LegalCopyright", "(C) 1995-2004 Jean-loup Gailly & Mark Adler\0"
|
||||
VALUE "OriginalFilename", "zlib1.dll\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"
|
||||
END
|
||||
END
|
||||
|
8
zconf.h
8
zconf.h
@ -1,5 +1,5 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
@ -68,8 +68,10 @@
|
||||
#if defined(_WINDOWS) && !defined(WINDOWS)
|
||||
# define WINDOWS
|
||||
#endif
|
||||
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
|
||||
# define WIN32
|
||||
#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
|
||||
# ifndef WIN32
|
||||
# define WIN32
|
||||
# endif
|
||||
#endif
|
||||
#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
|
||||
# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
@ -68,8 +68,10 @@
|
||||
#if defined(_WINDOWS) && !defined(WINDOWS)
|
||||
# define WINDOWS
|
||||
#endif
|
||||
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
|
||||
# define WIN32
|
||||
#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
|
||||
# ifndef WIN32
|
||||
# define WIN32
|
||||
# endif
|
||||
#endif
|
||||
#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
|
||||
# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
|
||||
|
4
zlib.3
4
zlib.3
@ -1,4 +1,4 @@
|
||||
.TH ZLIB 3 "30 December 2004"
|
||||
.TH ZLIB 3 "27 May 2005"
|
||||
.SH NAME
|
||||
zlib \- compression/decompression library
|
||||
.SH SYNOPSIS
|
||||
@ -133,7 +133,7 @@ before asking for help.
|
||||
Send questions and/or comments to zlib@gzip.org,
|
||||
or (for the Windows DLL version) to Gilles Vollant (info@winimage.com).
|
||||
.SH AUTHORS
|
||||
Version 1.2.2.2
|
||||
Version 1.2.2.3
|
||||
Copyright (C) 1995-2004 Jean-loup Gailly (jloup@gzip.org)
|
||||
and Mark Adler (madler@alumni.caltech.edu).
|
||||
.LP
|
||||
|
37
zlib.h
37
zlib.h
@ -1,7 +1,7 @@
|
||||
/* 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
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@ -37,8 +37,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ZLIB_VERSION "1.2.2.2"
|
||||
#define ZLIB_VERNUM 0x1222
|
||||
#define ZLIB_VERSION "1.2.2.3"
|
||||
#define ZLIB_VERNUM 0x1223
|
||||
|
||||
/*
|
||||
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
|
||||
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
|
||||
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
|
||||
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.
|
||||
*/
|
||||
|
||||
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,
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
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));
|
||||
/*
|
||||
Flushes all pending output if necessary, closes the compressed file
|
||||
|
10
zutil.h
10
zutil.h
@ -1,5 +1,5 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
@ -17,7 +17,9 @@
|
||||
#include "zlib.h"
|
||||
|
||||
#ifdef STDC
|
||||
# include <stddef.h>
|
||||
# ifndef _WIN32_WCE
|
||||
# include <stddef.h>
|
||||
# endif
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
@ -32,7 +34,9 @@
|
||||
# endif
|
||||
extern int errno;
|
||||
#else
|
||||
# include <errno.h>
|
||||
# ifndef _WIN32_WCE
|
||||
# include <errno.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef local
|
||||
|
Loading…
x
Reference in New Issue
Block a user