zlib 1.2.3.4

This commit is contained in:
Mark Adler 2011-09-09 23:26:40 -07:00
parent 639be99788
commit f6194ef39a
45 changed files with 3663 additions and 873 deletions

View File

@ -1,6 +1,67 @@
ChangeLog file for zlib
Changes in 1.2.3.4 (21 Dec 2009)
- Use old school .SUFFIXES in Makefile.in for FreeBSD compatibility
- Update comments in configure and Makefile.in for default --shared
- Fix test -z's in configure [Marquess]
- Build examplesh and minigzipsh when not testing
- Change NULL's to Z_NULL's in deflate.c and in comments in zlib.h
- Import LDFLAGS from the environment in configure
- Fix configure to populate SFLAGS with discovered CFLAGS options
- Adapt make_vms.com to the new Makefile.in [Zinser]
- Add zlib2ansi script for C++ compilation [Marquess]
- Add _FILE_OFFSET_BITS=64 test to make test (when applicable)
- Add AMD64 assembler code for longest match to contrib [Teterin]
- Include options from $SFLAGS when doing $LDSHARED
- Simplify 64-bit file support by introducing z_off64_t type
- Make shared object files in objs directory to work around old Sun cc
- Use only three-part version number for Darwin shared compiles
- Add rc option to ar in Makefile.in for when ./configure not run
- Add -WI,-rpath,. to LDFLAGS for OSF 1 V4*
- Set LD_LIBRARYN32_PATH for SGI IRIX shared compile
- Protect against _FILE_OFFSET_BITS being defined when compiling zlib
- Rename Makefile.in targets allstatic to static and allshared to shared
- Fix static and shared Makefile.in targets to be independent
- Correct error return bug in gz_open() by setting state [Brown]
- Put spaces before ;;'s in configure for better sh compatibility
- Added pigz.c (parallel implementation of gzip) to examples/
- Correct constant in crc32.c to UL [Leventhal]
- Reject negative lengths in crc32_combine()
- Add inflateReset2() function to work like inflateEnd()/inflateInit2()
- Include sys/types.h for _LARGEFILE64_SOURCE [Brown]
- Correct typo in doc/algorithm.txt [Janik]
- Fix bug in adler32_combine() [Zhu]
- Catch missing-end-of-block-code error in all inflates and in puff
Assures that random input to inflate eventually results in an error
- Added enough.c (calculation of ENOUGH for inftrees.h) to examples/
- Update ENOUGH and its usage to reflect discovered bounds
- Fix gzerror() error report on empty input file [Brown]
- Add ush casts in trees.c to avoid pedantic runtime errors
- Fix typo in zlib.h uncompress() description [Reiss]
- Correct inflate() comments with regard to automatic header detection
- Remove deprecation comment on Z_PARTIAL_FLUSH (it stays)
- Put new version of gzlog (2.0) in examples with interruption recovery
- Add puff compile option to permit invalid distance-too-far streams
- Add puff TEST command options, ability to read piped input
- Prototype the *64 functions in zlib.h when _FILE_OFFSET_BITS == 64, but
_LARGEFILE64_SOURCE not defined
- Fix Z_FULL_FLUSH to truly erase the past by resetting s->strstart
- Fix deflateSetDictionary() to use all 32K for output consistency
- Remove extraneous #define MIN_LOOKAHEAD in deflate.c (in deflate.h)
- Clear bytes after deflate lookahead to avoid use of uninitialized data
- Change a limit in inftrees.c to be more transparent to Coverity Prevent
- Update win32/zlib.def with exported symbols from zlib.h
- Correct spelling error in zlib.h [Willem]
- Allow Z_BLOCK for deflate() to force a new block
- Allow negative bits in inflatePrime() to delete existing bit buffer
- Add Z_TREES flush option to inflate() to return at end of trees
- Add inflateMark() to return current state information for random access
- Added Makefile for NintendoDS to contrib [Costa]
- Add -w in configure compile tests to avoid spurious warnings [Beucler]
- Fix typos in zlib.h comments for deflateSetDictionary()
- Fix EOF detection in transparent gzread() [Maier]
Changes in 1.2.3.3 (2 October 2006)
- Make --shared the default for configure, add a --static option
- Add compile option to permit invalid distance-too-far streams
@ -10,7 +71,7 @@ Changes in 1.2.3.3 (2 October 2006)
- Use ftello() and fseeko() if available instead of ftell() and fseek()
- Provide two versions of all functions that use the z_off_t type for
binary compatibility -- a normal version and a 64-bit offset version,
per the Large File Support Extension when _LARGEFILE64_SUPPORT is
per the Large File Support Extension when _LARGEFILE64_SOURCE is
defined; use the 64-bit versions by default when _FILE_OFFSET_BITS
is defined to be 64
- Add a --uname= option to configure to perhaps help with cross-compiling

1
INDEX
View File

@ -10,6 +10,7 @@ treebuild.xml see http://treebuild.metux.de/
zlib.3 Man page for zlib
zlib.map Linux symbol information
zlib.pc.in Template for pkg-config descriptor
zlib2ansi perl script to convert source files for C++ compilation
amiga/ makefiles for Amiga SAS C
as400/ makefiles for IBM AS/400

112
Makefile
View File

@ -4,8 +4,8 @@
# To compile and test, type:
# ./configure; make test
# The call of configure is optional if you don't have special requirements
# If you wish to build zlib as a shared library, use: ./configure -s
# Normally configure builds both a static and a shared library.
# If you want to build just a static library, use: ./configure --static
# To use the asm code, type:
# cp contrib/asm?86/match.S ./match.S
@ -26,16 +26,17 @@ CFLAGS=-O
SFLAGS=-O
LDFLAGS=libz.a
LDFLAGS=-L. libz.a
LDSHARED=$(CC)
CPP=$(CC) -E
LIBS=libz.a
STATICLIB=libz.a
SHAREDLIB=libz.so
SHAREDLIBV=libz.so.1.2.3.3
SHAREDLIBV=libz.so.1.2.3.4
SHAREDLIBM=libz.so.1
LIBS=$(STATICLIB) $(SHAREDLIB)
AR=ar
AR=ar rc
RANLIB=ranlib
TAR=tar
SHELL=/bin/sh
@ -52,22 +53,30 @@ pkgconfigdir = ${libdir}/pkgconfig
OBJC = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
zutil.o inflate.o infback.o inftrees.o inffast.o
PIC_OBJC = adler32.lo compress.lo crc32.lo gzio.lo uncompr.lo deflate.lo trees.lo \
zutil.lo inflate.lo infback.lo inftrees.lo inffast.lo
# to use the asm code: make OBJA=match.o, PIC_OBJA=match.lo
OBJA =
# to use the asm code: make OBJA=match.o
PIC_OBJA =
OBJS = $(OBJC) $(OBJA)
PIC_OBJS = $(OBJS:%.o=%.lo)
PIC_OBJS = $(PIC_OBJC) $(PIC_OBJA)
TEST_OBJS = example.o minigzip.o
all: static shared
allstatic: example$(EXE) minigzip$(EXE)
static: example$(EXE) minigzip$(EXE)
allshared: examplesh$(EXE) minigzipsh$(EXE)
shared: examplesh$(EXE) minigzipsh$(EXE)
all: allstatic allshared
all64: example64$(EXE) minigzip64$(EXE)
teststatic: allstatic
check: test
test: all teststatic testshared
teststatic: static
@echo hello world | ./minigzip | ./minigzip -d || \
echo ' *** minigzip test FAILED ***' ; \
if ./example; then \
@ -76,8 +85,9 @@ teststatic: allstatic
echo ' *** zlib test FAILED ***'; \
fi
testshared: allshared
testshared: shared
@LD_LIBRARY_PATH=`pwd`:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
LD_LIBRARYN32_PATH=`pwd`:$(LD_LIBRARYN32_PATH) ; export LD_LIBRARYN32_PATH; \
DYLD_LIBRARY_PATH=`pwd`:$(DYLD_LIBRARY_PATH) ; export DYLD_LIBRARY_PATH; \
SHLIB_PATH=`pwd`:$(SHLIB_PATH) ; export SHLIB_PATH; \
echo hello world | ./minigzipsh | ./minigzipsh -d || \
@ -88,9 +98,14 @@ testshared: allshared
echo ' *** zlib shared test FAILED ***'; \
fi
test: teststatic testshared
check: test
test64: all64
@echo hello world | ./minigzip64 | ./minigzip64 -d || \
echo ' *** minigzip 64-bit test FAILED ***' ; \
if ./example64; then \
echo ' *** zlib 64-bit test OK ***'; \
else \
echo ' *** zlib 64-bit test FAILED ***'; \
fi
libz.a: $(OBJS)
$(AR) $@ $(OBJS)
@ -108,26 +123,43 @@ match.lo: match.S
mv _match.o match.lo
rm -f _match.s
%.lo: %.c
$(CC) $(SFLAGS) -DPIC -c $< -o $@
example64.o: example.c zlib.h zconf.h zlibdefs.h
$(CC) $(CFLAGS) -D_FILE_OFFSET_BITS=64 -c -o $@ $<
minigzip64.o: minigzip.c zlib.h zconf.h zlibdefs.h
$(CC) $(CFLAGS) -D_FILE_OFFSET_BITS=64 -c -o $@ $<
.SUFFIXES: .lo
.c.lo:
-@if [ ! -d objs ]; then mkdir objs; fi
$(CC) $(SFLAGS) -DPIC -c -o objs/$*.o $<
-@mv objs/$*.o $@
$(SHAREDLIBV): $(PIC_OBJS)
$(LDSHARED) -o $@ $(PIC_OBJS) -lc
$(LDSHARED) $(SFLAGS) -o $@ $(PIC_OBJS) -lc
rm -f $(SHAREDLIB) $(SHAREDLIBM)
ln -s $@ $(SHAREDLIB)
ln -s $@ $(SHAREDLIBM)
-@rmdir objs
example$(EXE): example.o $(LIBS)
example$(EXE): example.o $(STATICLIB)
$(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS)
minigzip$(EXE): minigzip.o $(LIBS)
minigzip$(EXE): minigzip.o $(STATICLIB)
$(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS)
examplesh$(EXE): example.o $(LIBS)
$(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDLIB)
examplesh$(EXE): example.o $(SHAREDLIBV)
$(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDLIBV)
minigzipsh$(EXE): minigzip.o $(LIBS)
$(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDLIB)
minigzipsh$(EXE): minigzip.o $(SHAREDLIBV)
$(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDLIBV)
example64$(EXE): example64.o $(STATICLIB)
$(CC) $(CFLAGS) -o $@ example64.o $(LDFLAGS)
minigzip64$(EXE): minigzip64.o $(STATICLIB)
$(CC) $(CFLAGS) -o $@ minigzip64.o $(LDFLAGS)
install-libs: $(LIBS)
-@if [ ! -d $(DESTDIR)$(exec_prefix) ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi
@ -168,8 +200,10 @@ mostlyclean: clean
clean:
rm -f *.o *.lo *~ \
example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \
example64$(EXE) minigzip64$(EXE) \
libz.* foo.gz so_locations \
_match.s maketree contrib/infback9/*.o
rm -rf objs
maintainer-clean: distclean
distclean: clean
@ -186,30 +220,20 @@ depend:
# DO NOT DELETE THIS LINE -- make depend depends on it.
adler32.o: zlib.h zconf.h zlibdefs.h
compress.o: zlib.h zconf.h zlibdefs.h
crc32.o: crc32.h zlib.h zconf.h zlibdefs.h
adler32.o gzio.o zutil.o: zutil.h zlib.h zconf.h zlibdefs.h
compress.o example.o minigzip.o uncompr.o: zlib.h zconf.h zlibdefs.h
crc32.o: zutil.h zlib.h zconf.h zlibdefs.h crc32.h
deflate.o: deflate.h zutil.h zlib.h zconf.h zlibdefs.h
example.o: zlib.h zconf.h zlibdefs.h
gzio.o: zutil.h zlib.h zconf.h zlibdefs.h
infback.o inflate.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h
inffast.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h
inflate.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h
infback.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h
inftrees.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h
minigzip.o: zlib.h zconf.h zlibdefs.h
trees.o: deflate.h zutil.h zlib.h zconf.h zlibdefs.h trees.h
uncompr.o: zlib.h zconf.h zlibdefs.h
zutil.o: zutil.h zlib.h zconf.h zlibdefs.h
adler32.lo: zlib.h zconf.h zlibdefs.h
compress.lo: zlib.h zconf.h zlibdefs.h
crc32.lo: crc32.h zlib.h zconf.h zlibdefs.h
adler32.lo gzio.lo zutil.lo: zutil.h zlib.h zconf.h zlibdefs.h
compress.lo example.lo minigzip.lo uncompr.lo: zlib.h zconf.h zlibdefs.h
crc32.lo: zutil.h zlib.h zconf.h zlibdefs.h crc32.h
deflate.lo: deflate.h zutil.h zlib.h zconf.h zlibdefs.h
gzio.lo: zutil.h zlib.h zconf.h zlibdefs.h
infback.lo inflate.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h
inffast.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h
inflate.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h
infback.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h
inftrees.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h
trees.lo: deflate.h zutil.h zlib.h zconf.h zlibdefs.h trees.h
uncompr.lo: zlib.h zconf.h zlibdefs.h
zutil.lo: zutil.h zlib.h zconf.h zlibdefs.h

View File

@ -4,8 +4,8 @@
# To compile and test, type:
# ./configure; make test
# The call of configure is optional if you don't have special requirements
# If you wish to build zlib as a shared library, use: ./configure -s
# Normally configure builds both a static and a shared library.
# If you want to build just a static library, use: ./configure --static
# To use the asm code, type:
# cp contrib/asm?86/match.S ./match.S
@ -26,16 +26,17 @@ CFLAGS=-O
SFLAGS=-O
LDFLAGS=libz.a
LDFLAGS=-L. libz.a
LDSHARED=$(CC)
CPP=$(CC) -E
LIBS=libz.a
STATICLIB=libz.a
SHAREDLIB=libz.so
SHAREDLIBV=libz.so.1.2.3.3
SHAREDLIBV=libz.so.1.2.3.4
SHAREDLIBM=libz.so.1
LIBS=$(STATICLIB) $(SHAREDLIB)
AR=ar
AR=ar rc
RANLIB=ranlib
TAR=tar
SHELL=/bin/sh
@ -52,22 +53,30 @@ pkgconfigdir = ${libdir}/pkgconfig
OBJC = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
zutil.o inflate.o infback.o inftrees.o inffast.o
PIC_OBJC = adler32.lo compress.lo crc32.lo gzio.lo uncompr.lo deflate.lo trees.lo \
zutil.lo inflate.lo infback.lo inftrees.lo inffast.lo
# to use the asm code: make OBJA=match.o, PIC_OBJA=match.lo
OBJA =
# to use the asm code: make OBJA=match.o
PIC_OBJA =
OBJS = $(OBJC) $(OBJA)
PIC_OBJS = $(OBJS:%.o=%.lo)
PIC_OBJS = $(PIC_OBJC) $(PIC_OBJA)
TEST_OBJS = example.o minigzip.o
all: static shared
allstatic: example$(EXE) minigzip$(EXE)
static: example$(EXE) minigzip$(EXE)
allshared: examplesh$(EXE) minigzipsh$(EXE)
shared: examplesh$(EXE) minigzipsh$(EXE)
all: allstatic allshared
all64: example64$(EXE) minigzip64$(EXE)
teststatic: allstatic
check: test
test: all teststatic testshared
teststatic: static
@echo hello world | ./minigzip | ./minigzip -d || \
echo ' *** minigzip test FAILED ***' ; \
if ./example; then \
@ -76,8 +85,9 @@ teststatic: allstatic
echo ' *** zlib test FAILED ***'; \
fi
testshared: allshared
testshared: shared
@LD_LIBRARY_PATH=`pwd`:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
LD_LIBRARYN32_PATH=`pwd`:$(LD_LIBRARYN32_PATH) ; export LD_LIBRARYN32_PATH; \
DYLD_LIBRARY_PATH=`pwd`:$(DYLD_LIBRARY_PATH) ; export DYLD_LIBRARY_PATH; \
SHLIB_PATH=`pwd`:$(SHLIB_PATH) ; export SHLIB_PATH; \
echo hello world | ./minigzipsh | ./minigzipsh -d || \
@ -88,9 +98,14 @@ testshared: allshared
echo ' *** zlib shared test FAILED ***'; \
fi
test: teststatic testshared
check: test
test64: all64
@echo hello world | ./minigzip64 | ./minigzip64 -d || \
echo ' *** minigzip 64-bit test FAILED ***' ; \
if ./example64; then \
echo ' *** zlib 64-bit test OK ***'; \
else \
echo ' *** zlib 64-bit test FAILED ***'; \
fi
libz.a: $(OBJS)
$(AR) $@ $(OBJS)
@ -108,26 +123,43 @@ match.lo: match.S
mv _match.o match.lo
rm -f _match.s
%.lo: %.c
$(CC) $(SFLAGS) -DPIC -c $< -o $@
example64.o: example.c zlib.h zconf.h zlibdefs.h
$(CC) $(CFLAGS) -D_FILE_OFFSET_BITS=64 -c -o $@ $<
minigzip64.o: minigzip.c zlib.h zconf.h zlibdefs.h
$(CC) $(CFLAGS) -D_FILE_OFFSET_BITS=64 -c -o $@ $<
.SUFFIXES: .lo
.c.lo:
-@if [ ! -d objs ]; then mkdir objs; fi
$(CC) $(SFLAGS) -DPIC -c -o objs/$*.o $<
-@mv objs/$*.o $@
$(SHAREDLIBV): $(PIC_OBJS)
$(LDSHARED) -o $@ $(PIC_OBJS) -lc
$(LDSHARED) $(SFLAGS) -o $@ $(PIC_OBJS) -lc
rm -f $(SHAREDLIB) $(SHAREDLIBM)
ln -s $@ $(SHAREDLIB)
ln -s $@ $(SHAREDLIBM)
-@rmdir objs
example$(EXE): example.o $(LIBS)
example$(EXE): example.o $(STATICLIB)
$(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS)
minigzip$(EXE): minigzip.o $(LIBS)
minigzip$(EXE): minigzip.o $(STATICLIB)
$(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS)
examplesh$(EXE): example.o $(LIBS)
$(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDLIB)
examplesh$(EXE): example.o $(SHAREDLIBV)
$(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDLIBV)
minigzipsh$(EXE): minigzip.o $(LIBS)
$(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDLIB)
minigzipsh$(EXE): minigzip.o $(SHAREDLIBV)
$(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDLIBV)
example64$(EXE): example64.o $(STATICLIB)
$(CC) $(CFLAGS) -o $@ example64.o $(LDFLAGS)
minigzip64$(EXE): minigzip64.o $(STATICLIB)
$(CC) $(CFLAGS) -o $@ minigzip64.o $(LDFLAGS)
install-libs: $(LIBS)
-@if [ ! -d $(DESTDIR)$(exec_prefix) ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi
@ -168,8 +200,10 @@ mostlyclean: clean
clean:
rm -f *.o *.lo *~ \
example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \
example64$(EXE) minigzip64$(EXE) \
libz.* foo.gz so_locations \
_match.s maketree contrib/infback9/*.o
rm -rf objs
maintainer-clean: distclean
distclean: clean
@ -186,30 +220,20 @@ depend:
# DO NOT DELETE THIS LINE -- make depend depends on it.
adler32.o: zlib.h zconf.h zlibdefs.h
compress.o: zlib.h zconf.h zlibdefs.h
crc32.o: crc32.h zlib.h zconf.h zlibdefs.h
adler32.o gzio.o zutil.o: zutil.h zlib.h zconf.h zlibdefs.h
compress.o example.o minigzip.o uncompr.o: zlib.h zconf.h zlibdefs.h
crc32.o: zutil.h zlib.h zconf.h zlibdefs.h crc32.h
deflate.o: deflate.h zutil.h zlib.h zconf.h zlibdefs.h
example.o: zlib.h zconf.h zlibdefs.h
gzio.o: zutil.h zlib.h zconf.h zlibdefs.h
infback.o inflate.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h
inffast.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h
inflate.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h
infback.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h
inftrees.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h
minigzip.o: zlib.h zconf.h zlibdefs.h
trees.o: deflate.h zutil.h zlib.h zconf.h zlibdefs.h trees.h
uncompr.o: zlib.h zconf.h zlibdefs.h
zutil.o: zutil.h zlib.h zconf.h zlibdefs.h
adler32.lo: zlib.h zconf.h zlibdefs.h
compress.lo: zlib.h zconf.h zlibdefs.h
crc32.lo: crc32.h zlib.h zconf.h zlibdefs.h
adler32.lo gzio.lo zutil.lo: zutil.h zlib.h zconf.h zlibdefs.h
compress.lo example.lo minigzip.lo uncompr.lo: zlib.h zconf.h zlibdefs.h
crc32.lo: zutil.h zlib.h zconf.h zlibdefs.h crc32.h
deflate.lo: deflate.h zutil.h zlib.h zconf.h zlibdefs.h
gzio.lo: zutil.h zlib.h zconf.h zlibdefs.h
infback.lo inflate.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h
inffast.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h
inflate.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h
infback.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h
inftrees.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h
trees.lo: deflate.h zutil.h zlib.h zconf.h zlibdefs.h trees.h
uncompr.lo: zlib.h zconf.h zlibdefs.h
zutil.lo: zutil.h zlib.h zconf.h zlibdefs.h

4
README
View File

@ -1,6 +1,6 @@
ZLIB DATA COMPRESSION LIBRARY
zlib 1.2.3.3 is a general purpose data compression library. All the code is
zlib 1.2.3.4 is a general purpose data compression library. All the code is
thread safe. The data format used by the zlib library is described by RFCs
(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.3.3 are documented in the file ChangeLog.
The changes made in version 1.2.3.4 are documented in the file ChangeLog.
Unsupported third party contributions are provided in directory "contrib".

View File

@ -1,21 +1,15 @@
/* adler32.c -- compute the Adler-32 checksum of a data stream
* Copyright (C) 1995-2006 Mark Adler
* Copyright (C) 1995-2007 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#define ZLIB_INTERNAL
#include "zlib.h"
#include "zutil.h"
#define local static
#ifdef _LARGEFILE64_SOURCE
local uLong adler32_combine_(uLong adler1, uLong adler2, off64_t len2);
#else
local uLong adler32_combine_(uLong adler1, uLong adler2, z_off_t len2);
#endif
local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2);
#define BASE 65521UL /* largest prime smaller than 65536 */
#define NMAX 5552
@ -137,11 +131,7 @@ uLong ZEXPORT adler32(adler, buf, len)
local uLong adler32_combine_(adler1, adler2, len2)
uLong adler1;
uLong adler2;
#ifdef _LARGEFILE64_SOURCE
off64_t len2;
#else
z_off_t len2;
#endif
z_off64_t len2;
{
unsigned long sum1;
unsigned long sum2;
@ -154,10 +144,10 @@ local uLong adler32_combine_(adler1, adler2, len2)
MOD(sum2);
sum1 += (adler2 & 0xffff) + BASE - 1;
sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
if (sum1 > BASE) sum1 -= BASE;
if (sum1 > BASE) sum1 -= BASE;
if (sum2 > (BASE << 1)) sum2 -= (BASE << 1);
if (sum2 > BASE) sum2 -= BASE;
if (sum1 >= BASE) sum1 -= BASE;
if (sum1 >= BASE) sum1 -= BASE;
if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1);
if (sum2 >= BASE) sum2 -= BASE;
return sum1 | (sum2 << 16);
}
@ -170,20 +160,10 @@ uLong ZEXPORT adler32_combine(adler1, adler2, len2)
return adler32_combine_(adler1, adler2, len2);
}
#ifdef _LARGEFILE64_SOURCE
uLong ZEXPORT adler32_combine64(adler1, adler2, len2)
uLong adler1;
uLong adler2;
off64_t len2;
z_off64_t len2;
{
return adler32_combine_(adler1, adler2, len2);
}
#else
uLong ZEXPORT adler32_combine64(adler1, adler2, len2)
uLong adler1;
uLong adler2;
z_off_t len2;
{
return adler32_combine_(adler1, adler2, len2);
}
#endif

View File

@ -1,7 +1,7 @@
* ZLIB.INC - Interface to the general purpose compression library
*
* ILE RPG400 version by Patrick Monnerat, DATASPHERE.
* Version 1.2.3.3
* Version 1.2.3.4
*
*
* WARNING:
@ -22,8 +22,8 @@
*
* Versioning information.
*
D ZLIB_VERSION C '1.2.3.3'
D ZLIB_VERNUM C X'1233'
D ZLIB_VERSION C '1.2.3.4'
D ZLIB_VERNUM C X'1234'
*
* Other equates.
*

140
configure vendored
View File

@ -1,26 +1,22 @@
#!/bin/sh
# configure script for zlib. This script is needed only if
# you wish to build a shared library and your system supports them,
# of if you need special compiler, flags or install directory.
# Otherwise, you can just use directly "make test; make install"
# configure script for zlib.
#
# To create a shared library, use "configure --shared"; by default a static
# library is created. If the primitive shared library support provided here
# does not work, use ftp://prep.ai.mit.edu/pub/gnu/libtool-*.tar.gz
# Normally configure builds both a static and a shared library.
# If you want to build just a static library, use: ./configure --static
#
# To impose specific compiler or flags or install directory, use for example:
# prefix=$HOME CC=cc CFLAGS="-O4" ./configure
# or for csh/tcsh users:
# (setenv prefix $HOME; setenv CC cc; setenv CFLAGS "-O4"; ./configure)
# LDSHARED is the command to be used to create a shared library
# Incorrect settings of CC or CFLAGS may prevent creating a shared library.
# If you have problems, try without defining CC and CFLAGS before reporting
# an error.
LIBS=libz.a
LDFLAGS="-L. ${LIBS}"
STATICLIB=libz.a
LDFLAGS="${LDFLAGS} -L. ${STATICLIB}"
VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`
VER3=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\\.[0-9]*\)\\..*/\1/p' < zlib.h`
VER2=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < zlib.h`
VER1=`sed -n -e '/VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < zlib.h`
AR=${AR-"ar"}
@ -45,22 +41,22 @@ case "$1" in
echo 'usage:'
echo ' configure [--shared] [--prefix=PREFIX] [--exec_prefix=EXPREFIX]'
echo ' [--libdir=LIBDIR] [--includedir=INCLUDEDIR] [--zprefix]'
exit 0;;
-p*=* | --prefix=*) prefix=`echo $1 | sed 's/[-a-z_]*=//'`; shift;;
-e*=* | --eprefix=*) exec_prefix=`echo $1 | sed 's/[-a-z_]*=//'`; shift;;
-l*=* | --libdir=*) libdir=`echo $1 | sed 's/[-a-z_]*=//'`; shift;;
-i*=* | --includedir=*) includedir=`echo $1 | sed 's/[-a-z_]*=//'`;shift;;
-u*=* | --uname=*) uname=`echo $1 | sed 's/[-a-z_]*=//'`;shift;;
-p* | --prefix) prefix="$2"; shift; shift;;
-e* | --eprefix) exec_prefix="$2"; shift; shift;;
-l* | --libdir) libdir="$2"; shift; shift;;
-i* | --includedir) includedir="$2"; shift; shift;;
-s* | --shared | --enable-shared) shared=1; shift;;
-t | --static) shared=0; shift;;
-z* | --zprefix) zprefix=1; shift;;
--sysconfdir=*) echo "ignored option: --sysconfdir"; shift;;
--localstatedir=*) echo "ignored option: --localstatedir"; shift;;
*) echo "unknown option: $1"; echo "$0 --help for help"; exit 1;;
exit 0 ;;
-p*=* | --prefix=*) prefix=`echo $1 | sed 's/[-a-z_]*=//'`; shift ;;
-e*=* | --eprefix=*) exec_prefix=`echo $1 | sed 's/[-a-z_]*=//'`; shift ;;
-l*=* | --libdir=*) libdir=`echo $1 | sed 's/[-a-z_]*=//'`; shift ;;
-i*=* | --includedir=*) includedir=`echo $1 | sed 's/[-a-z_]*=//'`;shift ;;
-u*=* | --uname=*) uname=`echo $1 | sed 's/[-a-z_]*=//'`;shift ;;
-p* | --prefix) prefix="$2"; shift; shift ;;
-e* | --eprefix) exec_prefix="$2"; shift; shift ;;
-l* | --libdir) libdir="$2"; shift; shift ;;
-i* | --includedir) includedir="$2"; shift; shift ;;
-s* | --shared | --enable-shared) shared=1; shift ;;
-t | --static) shared=0; shift ;;
-z* | --zprefix) zprefix=1; shift ;;
--sysconfdir=*) echo "ignored option: --sysconfdir"; shift ;;
--localstatedir=*) echo "ignored option: --localstatedir"; shift ;;
*) echo "unknown option: $1"; echo "$0 --help for help"; exit 1 ;;
esac
done
@ -75,44 +71,44 @@ cc=${CC-gcc}
cflags=${CFLAGS-"-O3"}
# to force the asm version use: CFLAGS="-O3 -DASMV" ./configure
case "$cc" in
*gcc*) gcc=1;;
*gcc*) gcc=1 ;;
esac
if test "$gcc" -eq 1 && ($cc -c $cflags $test.c) 2>/dev/null; then
CC="$cc"
SFLAGS="${CFLAGS-"-O3"} -fPIC"
CFLAGS="${CFLAGS-"-O3"}"
if test -z $uname; then
if test -z "$uname"; then
uname=`(uname -s || echo unknown) 2>/dev/null`
fi
case "$uname" in
Linux | linux | GNU | GNU/*) LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,zlib.map"};;
Linux | linux | GNU | GNU/*) LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,zlib.map"} ;;
CYGWIN* | Cygwin* | cygwin* | OS/2* )
EXE='.exe';;
EXE='.exe' ;;
QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4
# (alain.bonnefoy@icbt.com)
LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"};;
LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"} ;;
HP-UX*)
LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"}
case `(uname -m || echo unknown) 2>/dev/null` in
ia64)
shared_ext='.so'
SHAREDLIB='libz.so';;
SHAREDLIB='libz.so' ;;
*)
shared_ext='.sl'
SHAREDLIB='libz.sl';;
esac;;
SHAREDLIB='libz.sl' ;;
esac ;;
Darwin*) shared_ext='.dylib'
SHAREDLIB=libz$shared_ext
SHAREDLIBV=libz.$VER$shared_ext
SHAREDLIBM=libz.$VER1$shared_ext
LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER"};;
*) LDSHARED=${LDSHARED-"$cc -shared"};;
LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER3"} ;;
*) LDSHARED=${LDSHARED-"$cc -shared"} ;;
esac
else
# find system name and corresponding cc options
CC=${CC-cc}
if test -z $uname; then
if test -z "$uname"; then
uname=`(uname -sr || echo unknown) 2>/dev/null`
fi
case "$uname" in
@ -123,63 +119,64 @@ else
case `(uname -m || echo unknown) 2>/dev/null` in
ia64)
shared_ext='.so'
SHAREDLIB='libz.so';;
SHAREDLIB='libz.so' ;;
*)
shared_ext='.sl'
SHAREDLIB='libz.sl';;
esac;;
SHAREDLIB='libz.sl' ;;
esac ;;
IRIX*) SFLAGS=${CFLAGS-"-ansi -O2 -rpath ."}
CFLAGS=${CFLAGS-"-ansi -O2"}
LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"};;
LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"} ;;
OSF1\ V4*) SFLAGS=${CFLAGS-"-O -std1"}
CFLAGS=${CFLAGS-"-O -std1"}
LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so -Wl,-msym -Wl,-rpath,$(libdir) -Wl,-set_version,${VER}:1.0"};;
LDFLAGS="${LDFLAGS} -Wl,-rpath,."
LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so -Wl,-msym -Wl,-rpath,$(libdir) -Wl,-set_version,${VER}:1.0"} ;;
OSF1*) SFLAGS=${CFLAGS-"-O -std1"}
CFLAGS=${CFLAGS-"-O -std1"}
LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"};;
LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"} ;;
QNX*) SFLAGS=${CFLAGS-"-4 -O"}
CFLAGS=${CFLAGS-"-4 -O"}
LDSHARED=${LDSHARED-"cc"}
RANLIB=${RANLIB-"true"}
AR_RC="cc -A";;
AR_RC="cc -A" ;;
SCO_SV\ 3.2*) SFLAGS=${CFLAGS-"-O3 -dy -KPIC "}
CFLAGS=${CFLAGS-"-O3"}
LDSHARED=${LDSHARED-"cc -dy -KPIC -G"};;
LDSHARED=${LDSHARED-"cc -dy -KPIC -G"} ;;
SunOS\ 5*) LDSHARED=${LDSHARED-"cc -G"}
case `(uname -m || echo unknown) 2>/dev/null` in
i86*)
SFLAGS=${CFLAGS-"-xpentium -fast -KPIC -R."}
CFLAGS=${CFLAGS-"-xpentium -fast"};;
CFLAGS=${CFLAGS-"-xpentium -fast"} ;;
*)
SFLAGS=${CFLAGS-"-fast -xcg92 -KPIC -R."}
CFLAGS=${CFLAGS-"-fast -xcg92"};;
esac;;
CFLAGS=${CFLAGS-"-fast -xcg92"} ;;
esac ;;
SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"}
CFLAGS=${CFLAGS-"-O2"}
LDSHARED=${LDSHARED-"ld"};;
LDSHARED=${LDSHARED-"ld"} ;;
SunStudio\ 9*) SFLAGS=${CFLAGS-"-DUSE_MMAP -fast -xcode=pic32 -xtarget=ultra3 -xarch=v9b"}
CFLAGS=${CFLAGS-"-DUSE_MMAP -fast -xtarget=ultra3 -xarch=v9b"}
LDSHARED=${LDSHARED-"cc -xarch=v9b"};;
LDSHARED=${LDSHARED-"cc -xarch=v9b"} ;;
UNIX_System_V\ 4.2.0)
SFLAGS=${CFLAGS-"-KPIC -O"}
CFLAGS=${CFLAGS-"-O"}
LDSHARED=${LDSHARED-"cc -G"};;
LDSHARED=${LDSHARED-"cc -G"} ;;
UNIX_SV\ 4.2MP)
SFLAGS=${CFLAGS-"-Kconform_pic -O"}
CFLAGS=${CFLAGS-"-O"}
LDSHARED=${LDSHARED-"cc -G"};;
LDSHARED=${LDSHARED-"cc -G"} ;;
OpenUNIX\ 5)
SFLAGS=${CFLAGS-"-KPIC -O"}
CFLAGS=${CFLAGS-"-O"}
LDSHARED=${LDSHARED-"cc -G"};;
LDSHARED=${LDSHARED-"cc -G"} ;;
AIX*) # Courtesy of dbakker@arrayasolutions.com
SFLAGS=${CFLAGS-"-O -qmaxmem=8192"}
CFLAGS=${CFLAGS-"-O -qmaxmem=8192"}
LDSHARED=${LDSHARED-"xlc -G"};;
LDSHARED=${LDSHARED-"xlc -G"} ;;
# send working options for other systems to support@gzip.org
*) SFLAGS=${CFLAGS-"-O"}
CFLAGS=${CFLAGS-"-O"}
LDSHARED=${LDSHARED-"cc -shared"};;
LDSHARED=${LDSHARED-"cc -shared"} ;;
esac
fi
@ -190,16 +187,15 @@ SHAREDLIBM=${SHAREDLIBM-"libz$shared_ext.$VER1"}
if test $shared -eq 1; then
echo Checking for shared library support...
# we must test in two steps (cc then ld), required at least on SunOS 4.x
if test "`($CC -c $SFLAGS $test.c) 2>&1`" = "" &&
if test "`($CC -w -c $SFLAGS $test.c) 2>&1`" = "" &&
test "`($LDSHARED -o $test$shared_ext $test.o) 2>&1`" = ""; then
LIBS="$LIBS $SHAREDLIBV"
echo Building shared library $SHAREDLIBV with $CC.
elif test -z "$old_cc" -a -z "$old_cflags"; then
echo No shared library support.
shared=0;
else
echo Tested $CC -c $SFLAGS $test.c
$CC -c $SFLAGS $test.c
echo Tested $CC -w -c $SFLAGS $test.c
$CC -w -c $SFLAGS $test.c
echo Tested $LDSHARED -o $test$shared_ext $test.o
$LDSHARED -o $test$shared_ext $test.o
echo 'No shared library support; try without defining CC and CFLAGS'
@ -208,12 +204,12 @@ if test $shared -eq 1; then
fi
if test $shared -eq 0; then
LDSHARED="$CC"
ALL="allstatic"
TEST="teststatic"
echo Building static library $LIBS version $VER with $CC.
ALL="static"
TEST="all teststatic"
echo Building static library $STATICLIB version $VER with $CC.
else
ALL="allstatic allshared"
TEST="teststatic testshared"
ALL="static shared"
TEST="all teststatic testshared"
fi
cat > zlibdefs.h << EOF
@ -231,6 +227,8 @@ EOF
if test "`($CC -c $CFLAGS -D_LARGEFILE64_SOURCE=1 $test.c) 2>&1`" = ""; then
CFLAGS="${CFLAGS} -D_LARGEFILE64_SOURCE=1"
SFLAGS="${SFLAGS} -D_LARGEFILE64_SOURCE=1"
ALL="${ALL} all64"
TEST="${TEST} test64"
echo "Checking for off64_t... Yes."
echo "Checking for fseeko... Yes."
else
@ -345,6 +343,7 @@ EOF
echo "Checking for return value of vsnprintf()... Yes."
else
CFLAGS="$CFLAGS -DHAS_vsnprintf_void"
SFLAGS="$SFLAGS -DHAS_vsnprintf_void"
echo "Checking for return value of vsnprintf()... No."
echo " WARNING: apparently vsnprintf() does not return a value. zlib"
echo " can build but will be open to possible string-format security"
@ -352,6 +351,7 @@ EOF
fi
else
CFLAGS="$CFLAGS -DNO_vsnprintf"
SFLAGS="$SFLAGS -DNO_vsnprintf"
echo "Checking for vsnprintf() in stdio.h... No."
echo " WARNING: vsnprintf() not found, falling back to vsprintf(). zlib"
echo " can build but will be open to possible buffer-overflow security"
@ -383,6 +383,7 @@ EOF
echo "Checking for return value of vsprintf()... Yes."
else
CFLAGS="$CFLAGS -DHAS_vsprintf_void"
SFLAGS="$SFLAGS -DHAS_vsprintf_void"
echo "Checking for return value of vsprintf()... No."
echo " WARNING: apparently vsprintf() does not return a value. zlib"
echo " can build but will be open to possible string-format security"
@ -432,6 +433,7 @@ EOF
echo "Checking for return value of snprintf()... Yes."
else
CFLAGS="$CFLAGS -DHAS_snprintf_void"
SFLAGS="$SFLAGS -DHAS_snprintf_void"
echo "Checking for return value of snprintf()... No."
echo " WARNING: apparently snprintf() does not return a value. zlib"
echo " can build but will be open to possible string-format security"
@ -439,6 +441,7 @@ EOF
fi
else
CFLAGS="$CFLAGS -DNO_snprintf"
SFLAGS="$SFLAGS -DNO_snprintf"
echo "Checking for snprintf() in stdio.h... No."
echo " WARNING: snprintf() not found, falling back to sprintf(). zlib"
echo " can build but will be open to possible buffer-overflow security"
@ -464,6 +467,7 @@ EOF
echo "Checking for return value of sprintf()... Yes."
else
CFLAGS="$CFLAGS -DHAS_sprintf_void"
SFLAGS="$SFLAGS -DHAS_sprintf_void"
echo "Checking for return value of sprintf()... No."
echo " WARNING: apparently sprintf() does not return a value. zlib"
echo " can build but will be open to possible string-format security"
@ -481,6 +485,7 @@ if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
else
echo "Checking for errno.h... No."
CFLAGS="$CFLAGS -DNO_ERRNO_H"
SFLAGS="$SFLAGS -DNO_ERRNO_H"
fi
cat > $test.c <<EOF
@ -493,6 +498,7 @@ caddr_t hello() {
EOF
if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
CFLAGS="$CFLAGS -DUSE_MMAP"
SFLAGS="$SFLAGS -DUSE_MMAP"
echo Checking for mmap support... Yes.
else
echo Checking for mmap support... No.
@ -506,7 +512,7 @@ case $CFLAGS in
echo Checking for underline in external names... No.
else
echo Checking for underline in external names... Yes.
fi;;
fi ;;
esac
rm -f $test.[co] $test $test$shared_ext
@ -519,7 +525,7 @@ sed < Makefile.in "
/^LDFLAGS *=/s#=.*#=$LDFLAGS#
/^LDSHARED *=/s#=.*#=$LDSHARED#
/^CPP *=/s#=.*#=$CPP#
/^LIBS *=/s#=.*#=$LIBS#
/^STATICLIB *=/s#=.*#=$STATICLIB#
/^SHAREDLIB *=/s#=.*#=$SHAREDLIB#
/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV#
/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM#
@ -540,7 +546,7 @@ sed < zlib.pc.in "
/^CFLAGS *=/s#=.*#=$CFLAGS#
/^CPP *=/s#=.*#=$CPP#
/^LDSHARED *=/s#=.*#=$LDSHARED#
/^LIBS *=/s#=.*#=$LIBS#
/^STATICLIB *=/s#=.*#=$STATICLIB#
/^SHAREDLIB *=/s#=.*#=$SHAREDLIB#
/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV#
/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM#

View File

@ -8,6 +8,10 @@ ada/ by Dmitriy Anisimkov <anisimkov@yahoo.com>
Support for Ada
See http://zlib-ada.sourceforge.net/
amd64/ by Mikhail Teterin <mi@ALDAN.algebra.com>
asm code for AMD64
See patch at http://www.freebsd.org/cgi/query-pr.cgi?pr=bin/96393
asm586/
asm686/ by Brian Raiter <breadbox@muppetlabs.com>
asm code for Pentium and PPro/PII, using the AT&T (GNU as) syntax

357
contrib/amd64/amd64-match.S Normal file
View File

@ -0,0 +1,357 @@
/*
* match.S -- optimized version of longest_match()
* based on the similar work by Gilles Vollant, and Brian Raiter, written 1998
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the BSD License. Use by owners of Che Guevarra
* parafernalia is prohibited, where possible, and highly discouraged
* elsewhere.
*/
#ifndef NO_UNDERLINE
# define match_init _match_init
# define longest_match _longest_match
#endif
#define scanend ebx
#define scanendw bx
#define chainlenwmask edx /* high word: current chain len low word: s->wmask */
#define curmatch rsi
#define curmatchd esi
#define windowbestlen r8
#define scanalign r9
#define scanalignd r9d
#define window r10
#define bestlen r11
#define bestlend r11d
#define scanstart r12d
#define scanstartw r12w
#define scan r13
#define nicematch r14d
#define limit r15
#define limitd r15d
#define prev rcx
/*
* The 258 is a "magic number, not a parameter -- changing it
* breaks the hell loose
*/
#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 LocalVarsSize (112)
#define _chainlenwmask ( 8-LocalVarsSize)(%rsp)
#define _windowbestlen (16-LocalVarsSize)(%rsp)
#define save_r14 (24-LocalVarsSize)(%rsp)
#define save_rsi (32-LocalVarsSize)(%rsp)
#define save_rbx (40-LocalVarsSize)(%rsp)
#define save_r12 (56-LocalVarsSize)(%rsp)
#define save_r13 (64-LocalVarsSize)(%rsp)
#define save_r15 (80-LocalVarsSize)(%rsp)
/*
* On AMD64 the first argument of a function (in our case -- the pointer to
* deflate_state structure) is passed in %rdi, hence our offsets below are
* all off of that.
*/
#ifndef STRUCT_OFFSET
# define STRUCT_OFFSET (0)
#endif
#define dsWSize ( 56 + STRUCT_OFFSET)(%rdi)
#define dsWMask ( 64 + STRUCT_OFFSET)(%rdi)
#define dsWindow ( 72 + STRUCT_OFFSET)(%rdi)
#define dsPrev ( 88 + STRUCT_OFFSET)(%rdi)
#define dsMatchLen (136 + STRUCT_OFFSET)(%rdi)
#define dsPrevMatch (140 + STRUCT_OFFSET)(%rdi)
#define dsStrStart (148 + STRUCT_OFFSET)(%rdi)
#define dsMatchStart (152 + STRUCT_OFFSET)(%rdi)
#define dsLookahead (156 + STRUCT_OFFSET)(%rdi)
#define dsPrevLen (160 + STRUCT_OFFSET)(%rdi)
#define dsMaxChainLen (164 + STRUCT_OFFSET)(%rdi)
#define dsGoodMatch (180 + STRUCT_OFFSET)(%rdi)
#define dsNiceMatch (184 + STRUCT_OFFSET)(%rdi)
.globl match_init, longest_match
.text
/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
longest_match:
/*
* Retrieve the function arguments. %curmatch will hold cur_match
* throughout the entire function (passed via rsi on amd64).
* rdi will hold the pointer to the deflate_state (first arg on amd64)
*/
mov %rsi, save_rsi
mov %rbx, save_rbx
mov %r12, save_r12
mov %r13, save_r13
mov %r14, save_r14
mov %r15, save_r15
/* uInt wmask = s->w_mask; */
/* unsigned chain_length = s->max_chain_length; */
/* if (s->prev_length >= s->good_match) { */
/* chain_length >>= 2; */
/* } */
movl dsPrevLen, %eax
movl dsGoodMatch, %ebx
cmpl %ebx, %eax
movl dsWMask, %eax
movl dsMaxChainLen, %chainlenwmask
jl LastMatchGood
shrl $2, %chainlenwmask
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 %chainlenwmask
shll $16, %chainlenwmask
orl %eax, %chainlenwmask
/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */
movl dsNiceMatch, %eax
movl dsLookahead, %ebx
cmpl %eax, %ebx
jl LookaheadLess
movl %eax, %ebx
LookaheadLess: movl %ebx, %nicematch
/* register Bytef *scan = s->window + s->strstart; */
mov dsWindow, %window
movl dsStrStart, %limitd
lea (%limit, %window), %scan
/* Determine how many bytes the scan ptr is off from being */
/* dword-aligned. */
mov %scan, %scanalign
negl %scanalignd
andl $3, %scanalignd
/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
movl dsWSize, %eax
subl $MIN_LOOKAHEAD, %eax
xorl %ecx, %ecx
subl %eax, %limitd
cmovng %ecx, %limitd
/* int best_len = s->prev_length; */
movl dsPrevLen, %bestlend
/* Store the sum of s->window + best_len in %windowbestlen locally, and in memory. */
lea (%window, %bestlen), %windowbestlen
mov %windowbestlen, _windowbestlen
/* register ush scan_start = *(ushf*)scan; */
/* register ush scan_end = *(ushf*)(scan+best_len-1); */
/* Posf *prev = s->prev; */
movzwl (%scan), %scanstart
movzwl -1(%scan, %bestlen), %scanend
mov dsPrev, %prev
/* Jump into the main loop. */
movl %chainlenwmask, _chainlenwmask
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.
*/
LookupLoop:
andl %chainlenwmask, %curmatchd
movzwl (%prev, %curmatch, 2), %curmatchd
cmpl %limitd, %curmatchd
jbe LeaveNow
subl $0x00010000, %chainlenwmask
js LeaveNow
LoopEntry: cmpw -1(%windowbestlen, %curmatch), %scanendw
jne LookupLoop
cmpw %scanstartw, (%window, %curmatch)
jne LookupLoop
/* Store the current value of chainlen. */
movl %chainlenwmask, _chainlenwmask
/* %scan is the string under scrutiny, and %prev 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 $(-MAX_MATCH_8), %rdx
lea (%curmatch, %window), %windowbestlen
lea MAX_MATCH_8(%windowbestlen, %scanalign), %windowbestlen
lea MAX_MATCH_8(%scan, %scanalign), %prev
/* the prefetching below makes very little difference... */
prefetcht1 (%windowbestlen, %rdx)
prefetcht1 (%prev, %rdx)
/*
* Test the strings for equality, 8 bytes at a time. At the end,
* adjust %rdx so that it is offset to the exact byte that mismatched.
*
* 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 -- unrolling it, for example, makes no difference.
*/
#undef USE_SSE /* works, but is 6-7% slower, than non-SSE... */
LoopCmps:
#ifdef USE_SSE
/* Preload the SSE registers */
movdqu (%windowbestlen, %rdx), %xmm1
movdqu (%prev, %rdx), %xmm2
pcmpeqb %xmm2, %xmm1
movdqu 16(%windowbestlen, %rdx), %xmm3
movdqu 16(%prev, %rdx), %xmm4
pcmpeqb %xmm4, %xmm3
movdqu 32(%windowbestlen, %rdx), %xmm5
movdqu 32(%prev, %rdx), %xmm6
pcmpeqb %xmm6, %xmm5
movdqu 48(%windowbestlen, %rdx), %xmm7
movdqu 48(%prev, %rdx), %xmm8
pcmpeqb %xmm8, %xmm7
/* Check the comparisions' results */
pmovmskb %xmm1, %rax
notw %ax
bsfw %ax, %ax
jnz LeaveLoopCmps
add $16, %rdx
pmovmskb %xmm3, %rax
notw %ax
bsfw %ax, %ax
jnz LeaveLoopCmps
add $16, %rdx
pmovmskb %xmm5, %rax
notw %ax
bsfw %ax, %ax
jnz LeaveLoopCmps
add $16, %rdx
pmovmskb %xmm7, %rax
notw %ax
bsfw %ax, %ax
jnz LeaveLoopCmps
add $16, %rdx
jmp LoopCmps
LeaveLoopCmps: add %rax, %rdx
#else
mov (%windowbestlen, %rdx), %rax
xor (%prev, %rdx), %rax
jnz LeaveLoopCmps
add $8, %rdx
jnz LoopCmps
jmp LenMaximum
# if 0
/*
* This three-liner is tantalizingly simple, but bsf is a slow instruction,
* and the complicated alternative down below is quite a bit faster. Sad...
*/
LeaveLoopCmps: bsf %rax, %rax /* find the first non-zero bit */
shrl $3, %eax /* divide by 8 to get the byte */
add %rax, %rdx
# else
LeaveLoopCmps: testl $0xFFFFFFFF, %eax /* Check the first 4 bytes */
jnz Check16
add $4, %rdx
shr $32, %rax
Check16: testw $0xFFFF, %ax
jnz LenLower
add $2, %rdx
shrl $16, %eax
LenLower: subb $1, %al
adc $0, %rdx
# endif
#endif
/* 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 (%prev, %rdx), %rax
sub %scan, %rax
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. */
cmpl %bestlend, %eax
jg LongerMatch
mov _windowbestlen, %windowbestlen
mov dsPrev, %prev
movl _chainlenwmask, %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 %eax, %bestlend
movl %curmatchd, dsMatchStart
cmpl %nicematch, %eax
jge LeaveNow
lea (%window, %bestlen), %windowbestlen
mov %windowbestlen, _windowbestlen
movzwl -1(%scan, %rax), %scanend
mov dsPrev, %prev
movl _chainlenwmask, %chainlenwmask
jmp LookupLoop
/* Accept the current string, with the maximum possible length. */
LenMaximum:
movl $MAX_MATCH, %bestlend
movl %curmatchd, dsMatchStart
/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
/* return s->lookahead; */
LeaveNow:
movl dsLookahead, %eax
cmpl %eax, %bestlend
cmovngl %bestlend, %eax
LookaheadRet:
/* Restore the registers and return from whence we came. */
mov save_rsi, %rsi
mov save_rbx, %rbx
mov save_r12, %r12
mov save_r13, %r13
mov save_r14, %r14
mov save_r15, %r15
ret
match_init: ret

View File

@ -1,5 +1,5 @@
/* infback9.c -- inflate deflate64 data using a call-back interface
* Copyright (C) 1995-2006 Mark Adler
* Copyright (C) 1995-2008 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -433,7 +433,16 @@ void FAR *out_desc;
/* handle error breaks in while */
if (mode == BAD) break;
/* build code tables */
/* check for end-of-block code (better have one) */
if (state->lens[256] == 0) {
strm->msg = (char *)"invalid code -- missing end-of-block";
mode = BAD;
break;
}
/* build code tables -- note: do not change the lenbits or distbits
values here (9 and 6) without reading the comments in inftree9.h
concerning the ENOUGH constants, which depend on those values */
state->next = state->codes;
lencode = (code const FAR *)(state->next);
lenbits = 9;

View File

@ -1,5 +1,5 @@
/* inftree9.c -- generate Huffman trees for efficient decoding
* Copyright (C) 1995-2006 Mark Adler
* Copyright (C) 1995-2008 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.3.3 Copyright 1995-2006 Mark Adler ";
" inflate9 1.2.3.4 Copyright 1995-2008 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, 201, 203};
133, 133, 133, 133, 144, 72, 200};
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,
@ -160,11 +160,10 @@ unsigned short FAR *work;
entered in the tables.
used keeps track of how many table entries have been allocated from the
provided *table space. It is checked when a LENS table is being made
against the space in *table, ENOUGH, minus the maximum space needed by
the worst case distance code, MAXD. This should never happen, but the
sufficiency of ENOUGH has not been proven exhaustively, hence the check.
This assumes that when type == LENS, bits == 9.
provided *table space. It is checked for LENS and DIST tables against
the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
the initial root table size constants. See the comments in inftree9.h
for more information.
sym increments through all symbols, and the loop terminates when
all codes of length max, i.e. all codes, have been processed. This
@ -203,7 +202,8 @@ unsigned short FAR *work;
mask = used - 1; /* mask for comparing low */
/* check available table space */
if (type == LENS && used >= ENOUGH - MAXD)
if ((type == LENS && used >= ENOUGH_LENS) ||
(type == DISTS && used >= ENOUGH_DISTS))
return 1;
/* process all codes and make table entries */
@ -270,7 +270,8 @@ unsigned short FAR *work;
/* check for enough space */
used += 1U << curr;
if (type == LENS && used >= ENOUGH - MAXD)
if ((type == LENS && used >= ENOUGH_LENS) ||
(type == DISTS && used >= ENOUGH_DISTS))
return 1;
/* point entry in root table to sub-table */

View File

@ -1,5 +1,5 @@
/* inftree9.h -- header to use inftree9.c
* Copyright (C) 1995-2003 Mark Adler
* Copyright (C) 1995-2008 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -35,15 +35,21 @@ typedef struct {
01000000 - invalid code
*/
/* Maximum size of dynamic tree. The maximum found in a long but non-
exhaustive search was 1444 code structures (852 for length/literals
and 592 for distances, the latter actually the result of an
exhaustive search). The true maximum is not known, but the value
below is more than safe. */
#define ENOUGH 2048
#define MAXD 592
/* Maximum size of the dynamic table. The maximum number of code structures is
1446, which is the sum of 852 for literal/length codes and 594 for distance
codes. These values were found by exhaustive searches using the program
examples/enough.c found in the zlib distribtution. The arguments to that
program are the number of symbols, the initial root table size, and the
maximum bit length of a code. "enough 286 9 15" for literal/length codes
returns returns 852, and "enough 32 6 15" for distance codes returns 594.
The initial root table size (9 or 6) is found in the fifth argument of the
inflate_table() calls in infback9.c. If the root table size is changed,
then these maximum sizes would be need to be recalculated and updated. */
#define ENOUGH_LENS 852
#define ENOUGH_DISTS 594
#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)
/* Type of code to build for inftable() */
/* Type of code to build for inflate_table9() */
typedef enum {
CODES,
LENS,

126
contrib/nintendods/Makefile Normal file
View File

@ -0,0 +1,126 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
include $(DEVKITARM)/ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#---------------------------------------------------------------------------------
TARGET := $(shell basename $(CURDIR))
BUILD := build
SOURCES := ../../
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -mthumb -mthumb-interwork
CFLAGS := -Wall -O2\
-march=armv5te -mtune=arm946e-s \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM9
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
ASFLAGS := $(ARCH) -march=armv5te -mtune=arm946e-s
LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(LIBNDS)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/lib/libz.a
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
@[ -d $@ ] || mkdir -p include
@cp ../../*.h include
lib:
@[ -d $@ ] || mkdir -p $@
$(BUILD): lib
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) lib
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT) : $(OFILES)
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,5 @@
This Makefile requires devkitARM (http://www.devkitpro.org/category/devkitarm/) and works inside "contrib/nds". It is based on a devkitARM template.
Eduardo Costa <eduardo.m.costa@gmail.com>
January 3, 2009

BIN
contrib/puff/puff Executable file

Binary file not shown.

View File

@ -1,8 +1,8 @@
/*
* puff.c
* Copyright (C) 2002-2004 Mark Adler
* Copyright (C) 2002-2008 Mark Adler
* For conditions of distribution and use, see copyright notice in puff.h
* version 1.8, 9 Jan 2004
* version 2.0, 25 Jul 2008
*
* puff.c is a simple inflate written to be an unambiguous way to specify the
* deflate format. It is not written for speed but rather simplicity. As a
@ -61,6 +61,12 @@
* 1.7 3 Mar 2003 - Added test code for distribution
* - Added zlib-like license
* 1.8 9 Jan 2004 - Added some comments on no distance codes case
* 1.9 21 Feb 2008 - Fix bug on 16-bit integer architectures [Pohland]
* - Catch missing end-of-block symbol error
* 2.0 25 Jul 2008 - Add #define to permit distance too far back
* - Add option in TEST code for puff to write the data
* - Add option in TEST code to skip input bytes
* - Allow TEST code to read from piped stdin
*/
#include <setjmp.h> /* for setjmp(), longjmp(), and jmp_buf */
@ -194,7 +200,7 @@ struct huffman {
* Decode a code from the stream s using huffman table h. Return the symbol or
* a negative value if there is an error. If all of the lengths are zero, i.e.
* an empty code, or if the code is incomplete and an invalid code is received,
* then -9 is returned after reading MAXBITS bits.
* then -10 is returned after reading MAXBITS bits.
*
* Format notes:
*
@ -226,14 +232,14 @@ local int decode(struct state *s, struct huffman *h)
for (len = 1; len <= MAXBITS; len++) {
code |= bits(s, 1); /* get next bit */
count = h->count[len];
if (code < first + count) /* if length len, return symbol */
if (code - count < first) /* if length len, return symbol */
return h->symbol[index + (code - first)];
index += count; /* else update for next length */
first += count;
first <<= 1;
code <<= 1;
}
return -9; /* ran out of codes */
return -10; /* ran out of codes */
}
/*
@ -263,7 +269,7 @@ local int decode(struct state *s, struct huffman *h)
code |= bitbuf & 1;
bitbuf >>= 1;
count = *next++;
if (code < first + count) { /* if length len, return symbol */
if (code - count < first) { /* if length len, return symbol */
s->bitbuf = bitbuf;
s->bitcnt = (s->bitcnt - len) & 7;
return h->symbol[index + (code - first)];
@ -280,7 +286,7 @@ local int decode(struct state *s, struct huffman *h)
bitbuf = s->in[s->incnt++];
if (left > 8) left = 8;
}
return -9; /* ran out of codes */
return -10; /* ran out of codes */
}
#endif /* SLOW */
@ -448,21 +454,27 @@ local int codes(struct state *s,
else if (symbol > 256) { /* length */
/* get and compute length */
symbol -= 257;
if (symbol >= 29) return -9; /* invalid fixed code */
if (symbol >= 29) return -10; /* invalid fixed code */
len = lens[symbol] + bits(s, lext[symbol]);
/* get and check distance */
symbol = decode(s, distcode);
if (symbol < 0) return symbol; /* invalid symbol */
dist = dists[symbol] + bits(s, dext[symbol]);
#ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
if (dist > s->outcnt)
return -10; /* distance too far back */
return -11; /* distance too far back */
#endif
/* copy length bytes from distance bytes back */
if (s->out != NIL) {
if (s->outcnt + len > s->outlen) return 1;
while (len--) {
s->out[s->outcnt] = s->out[s->outcnt - dist];
s->out[s->outcnt] =
#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
dist > s->outcnt ? 0 :
#endif
s->out[s->outcnt - dist];
s->outcnt++;
}
}
@ -680,6 +692,10 @@ local int dynamic(struct state *s)
}
}
/* check for end-of-block code -- there better be one! */
if (lengths[256] == 0)
return -9;
/* build huffman table for literal/length codes */
err = construct(&lencode, lengths, nlen);
if (err < 0 || (err > 0 && nlen - lencode.count[0] != 1))
@ -724,8 +740,9 @@ local int dynamic(struct state *s)
* -6: dynamic block code description: repeat more than specified lengths
* -7: dynamic block code description: invalid literal/length code lengths
* -8: dynamic block code description: invalid distance code lengths
* -9: invalid literal/length or distance code in fixed or dynamic block
* -10: distance is too far back in fixed or dynamic block
* -9: dynamic block code description: missing end-of-block code
* -10: invalid literal/length or distance code in fixed or dynamic block
* -11: distance is too far back in fixed or dynamic block
*
* Format notes:
*
@ -783,54 +800,142 @@ int puff(unsigned char *dest, /* pointer to destination pointer */
}
#ifdef TEST
/* Example of how to use puff() */
/* Examples of how to use puff().
Usage: puff [-w] [-nnn] file
... | puff [-w] [-nnn]
where file is the input file with deflate data, nnn is the number of bytes
of input to skip before inflating (e.g. to skip a zlib or gzip header), and
-w is used to write the decompressed data to stdout */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
local unsigned char *yank(char *name, unsigned long *len)
/* Return size times approximately the cube root of 2, keeping the result as 1,
3, or 5 times a power of 2 -- the result is always > size, until the result
is the maximum value of an unsigned long, where it remains. This is useful
to keep reallocations less than ~33% over the actual data. */
local size_t bythirds(size_t size)
{
unsigned long size;
unsigned char *buf;
int n;
size_t m;
m = size;
for (n = 0; m; n++)
m >>= 1;
if (n < 3)
return size + 1;
n -= 3;
m = size >> n;
m += m == 6 ? 2 : 1;
m <<= n;
return m > size ? m : (size_t)(-1);
}
/* Read the input file *name, or stdin if name is NULL, into allocated memory.
Reallocate to larger buffers until the entire file is read in. Return a
pointer to the allocated data, or NULL if there was a memory allocation
failure. *len is the number of bytes of data read from the input file (even
if load() returns NULL). If the input file was empty or could not be opened
or read, *len is zero. */
local void *load(char *name, size_t *len)
{
size_t size;
void *buf, *swap;
FILE *in;
struct stat s;
*len = 0;
if (stat(name, &s)) return NULL;
if ((s.st_mode & S_IFMT) != S_IFREG) return NULL;
size = (unsigned long)(s.st_size);
if (size == 0 || (off_t)size != s.st_size) return NULL;
in = fopen(name, "r");
if (in == NULL) return NULL;
buf = malloc(size);
if (buf != NULL && fread(buf, 1, size, in) != size) {
free(buf);
buf = NULL;
buf = malloc(size = 4096);
if (buf == NULL)
return NULL;
in = name == NULL ? stdin : fopen(name, "rb");
if (in != NULL) {
for (;;) {
*len += fread((char *)buf + *len, 1, size - *len, in);
if (*len < size) break;
size = bythirds(size);
if (size == *len || (swap = realloc(buf, size)) == NULL) {
free(buf);
buf = NULL;
break;
}
buf = swap;
}
fclose(in);
}
fclose(in);
*len = size;
return buf;
}
int main(int argc, char **argv)
{
int ret;
unsigned char *source;
unsigned long len, sourcelen, destlen;
int ret, skip = 0, put = 0;
char *arg, *name = NULL;
unsigned char *source = NULL, *dest;
size_t len = 0;
unsigned long sourcelen, destlen;
if (argc < 2) return 2;
source = yank(argv[1], &len);
if (source == NULL) return 2;
sourcelen = len;
ret = puff(NIL, &destlen, source, &sourcelen);
if (ret)
printf("puff() failed with return code %d\n", ret);
else {
printf("puff() succeeded uncompressing %lu bytes\n", destlen);
if (sourcelen < len) printf("%lu compressed bytes unused\n",
len - sourcelen);
/* process arguments */
while (arg = *++argv, --argc)
if (arg[0] == '-') {
if (arg[1] == 'w' && arg[2] == 0)
put = 1;
else if (arg[1] >= '0' && arg[1] <= '9')
skip = atoi(arg + 1);
else {
fprintf(stderr, "invalid option %s\n", arg);
return 3;
}
}
else if (name != NULL) {
fprintf(stderr, "only one file name allowed\n");
return 3;
}
else
name = arg;
source = load(name, &len);
if (source == NULL) {
fprintf(stderr, "memory allocation failure\n");
return 4;
}
if (len == 0) {
fprintf(stderr, "could not read %s, or it was empty\n",
name == NULL ? "<stdin>" : name);
free(source);
return 3;
}
if (skip >= len) {
fprintf(stderr, "skip request of %d leaves no input\n", skip);
free(source);
return 3;
}
/* test inflate data with offset skip */
len -= skip;
sourcelen = (unsigned long)len;
ret = puff(NIL, &destlen, source + skip, &sourcelen);
if (ret)
fprintf(stderr, "puff() failed with return code %d\n", ret);
else {
fprintf(stderr, "puff() succeeded uncompressing %lu bytes\n", destlen);
if (sourcelen < len) fprintf(stderr, "%lu compressed bytes unused\n",
len - sourcelen);
}
/* if requested, inflate again and write decompressd data to stdout */
if (put) {
dest = malloc(destlen);
if (dest == NULL) {
fprintf(stderr, "memory allocation failure\n");
free(source);
return 4;
}
puff(dest, &destlen, source + skip, &sourcelen);
fwrite(dest, 1, destlen, stdout);
free(dest);
}
/* clean up */
free(source);
return ret;
}

View File

@ -1,6 +1,6 @@
/* puff.h
Copyright (C) 2002, 2003 Mark Adler, all rights reserved
version 1.7, 3 Mar 2002
Copyright (C) 2002-2008 Mark Adler, all rights reserved
version 1.9, 10 Jan 2008
This software is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages

View File

@ -2,8 +2,8 @@
#define IDR_VERSION1 1
IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
FILEVERSION 1,2,3,3
PRODUCTVERSION 1,2,3,3
FILEVERSION 1,2,3,4
PRODUCTVERSION 1,2,3,4
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.3.3\0"
VALUE "FileVersion", "1.2.3.4\0"
VALUE "InternalName", "zlib\0"
VALUE "OriginalFilename", "zlib.dll\0"
VALUE "ProductName", "ZLib.DLL\0"

32
crc32.c
View File

@ -53,7 +53,7 @@
/* Definitions for doing the crc four data bytes at a time. */
#ifdef BYFOUR
# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
# define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \
(((w)&0xff00)<<8)+(((w)&0xff)<<24))
local unsigned long crc32_little OF((unsigned long,
const unsigned char FAR *, unsigned));
@ -68,11 +68,7 @@
local unsigned long gf2_matrix_times OF((unsigned long *mat,
unsigned long vec));
local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
#ifdef _LARGEFILE64_SOURCE
local uLong crc32_combine_(uLong crc1, uLong crc2, off64_t len2);
#else
local uLong crc32_combine_(uLong crc1, uLong crc2, z_off_t len2);
#endif
local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2);
#ifdef DYNAMIC_CRC_TABLE
@ -376,23 +372,19 @@ local void gf2_matrix_square(square, mat)
local uLong crc32_combine_(crc1, crc2, len2)
uLong crc1;
uLong crc2;
#ifdef _LARGEFILE64_SOURCE
off64_t len2;
#else
z_off_t len2;
#endif
z_off64_t len2;
{
int n;
unsigned long row;
unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
/* degenerate case */
if (len2 == 0)
/* degenerate case (also disallow negative lengths) */
if (len2 <= 0)
return crc1;
/* put operator for one zero bit in odd */
odd[0] = 0xedb88320L; /* CRC-32 polynomial */
odd[0] = 0xedb88320UL; /* CRC-32 polynomial */
row = 1;
for (n = 1; n < GF2_DIM; n++) {
odd[n] = row;
@ -441,20 +433,10 @@ uLong ZEXPORT crc32_combine(crc1, crc2, len2)
return crc32_combine_(crc1, crc2, len2);
}
#ifdef _LARGEFILE64_SOURCE
uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
uLong crc1;
uLong crc2;
off64_t len2;
z_off64_t len2;
{
return crc32_combine_(crc1, crc2, len2);
}
#else
uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
uLong crc1;
uLong crc2;
z_off_t len2;
{
return crc32_combine_(crc1, crc2, len2);
}
#endif

View File

@ -1,5 +1,5 @@
/* deflate.c -- compress data using the deflation algorithm
* Copyright (C) 1995-2006 Jean-loup Gailly.
* Copyright (C) 1995-2009 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.3.3 Copyright 1995-2006 Jean-loup Gailly ";
" deflate 1.2.3.4 Copyright 1995-2009 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
@ -110,11 +110,6 @@ local void check_match OF((deflate_state *s, IPos start, IPos match,
#endif
/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
/* Minimum amount of lookahead, except at the end of the input file.
* See deflate.c for comments about the MIN_MATCH+1.
*/
/* Values for max_lazy_match, good_match and max_chain_length, depending on
* the desired pack level (0..9). The values given below have been tuned to
* exclude worst case performance for pathological files. Better values may be
@ -288,6 +283,8 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos));
s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos));
s->high_water = 0; /* nothing written to s->window yet */
s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
@ -332,8 +329,8 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
strm->adler = adler32(strm->adler, dictionary, dictLength);
if (length < MIN_MATCH) return Z_OK;
if (length > MAX_DIST(s)) {
length = MAX_DIST(s);
if (length > s->w_size) {
length = s->w_size;
dictionary += dictLength - length; /* use the tail of the dictionary */
}
zmemcpy(s->window, dictionary, length);
@ -513,16 +510,16 @@ uLong ZEXPORT deflateBound(strm, sourceLen)
break;
case 2: /* gzip wrapper */
wraplen = 18;
if (s->gzhead != NULL) { /* user-supplied gzip header */
if (s->gzhead->extra != NULL)
if (s->gzhead != Z_NULL) { /* user-supplied gzip header */
if (s->gzhead->extra != Z_NULL)
wraplen += 2 + s->gzhead->extra_len;
str = s->gzhead->name;
if (str != NULL)
if (str != Z_NULL)
do {
wraplen++;
} while (*str++);
str = s->gzhead->comment;
if (str != NULL)
if (str != Z_NULL)
do {
wraplen++;
} while (*str++);
@ -589,7 +586,7 @@ int ZEXPORT deflate (strm, flush)
deflate_state *s;
if (strm == Z_NULL || strm->state == Z_NULL ||
flush > Z_FINISH || flush < 0) {
flush > Z_BLOCK || flush < 0) {
return Z_STREAM_ERROR;
}
s = strm->state;
@ -613,7 +610,7 @@ int ZEXPORT deflate (strm, flush)
put_byte(s, 31);
put_byte(s, 139);
put_byte(s, 8);
if (s->gzhead == NULL) {
if (s->gzhead == Z_NULL) {
put_byte(s, 0);
put_byte(s, 0);
put_byte(s, 0);
@ -640,7 +637,7 @@ int ZEXPORT deflate (strm, flush)
(s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
4 : 0));
put_byte(s, s->gzhead->os & 0xff);
if (s->gzhead->extra != NULL) {
if (s->gzhead->extra != Z_NULL) {
put_byte(s, s->gzhead->extra_len & 0xff);
put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
}
@ -682,7 +679,7 @@ int ZEXPORT deflate (strm, flush)
}
#ifdef GZIP
if (s->status == EXTRA_STATE) {
if (s->gzhead->extra != NULL) {
if (s->gzhead->extra != Z_NULL) {
uInt beg = s->pending; /* start of bytes to update crc */
while (s->gzindex < (s->gzhead->extra_len & 0xffff)) {
@ -710,7 +707,7 @@ int ZEXPORT deflate (strm, flush)
s->status = NAME_STATE;
}
if (s->status == NAME_STATE) {
if (s->gzhead->name != NULL) {
if (s->gzhead->name != Z_NULL) {
uInt beg = s->pending; /* start of bytes to update crc */
int val;
@ -741,7 +738,7 @@ int ZEXPORT deflate (strm, flush)
s->status = COMMENT_STATE;
}
if (s->status == COMMENT_STATE) {
if (s->gzhead->comment != NULL) {
if (s->gzhead->comment != Z_NULL) {
uInt beg = s->pending; /* start of bytes to update crc */
int val;
@ -840,13 +837,17 @@ int ZEXPORT deflate (strm, flush)
if (bstate == block_done) {
if (flush == Z_PARTIAL_FLUSH) {
_tr_align(s);
} else { /* FULL_FLUSH or SYNC_FLUSH */
} else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */
_tr_stored_block(s, (char*)0, 0L, 0);
/* For a full flush, this empty block will be recognized
* as a special marker by inflate_sync().
*/
if (flush == Z_FULL_FLUSH) {
CLEAR_HASH(s); /* forget history */
if (s->lookahead == 0) {
s->strstart = 0;
s->block_start = 0L;
}
}
}
flush_pending(strm);
@ -1387,6 +1388,40 @@ local void fill_window(s)
*/
} while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
/* If the WIN_INIT bytes after the end of the current data have never been
* written, then zero those bytes in order to avoid memory check reports of
* the use of uninitialized (or uninitialised as Julian writes) bytes by
* the longest match routines. Update the high water mark for the next
* time through here. WIN_INIT is set to MAX_MATCH since the longest match
* routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
*/
if (s->high_water < s->window_size) {
ulg curr = s->strstart + (ulg)(s->lookahead);
ulg init;
if (s->high_water < curr) {
/* Previous high water mark below current data -- zero WIN_INIT
* bytes or up to end of window, whichever is less.
*/
init = s->window_size - curr;
if (init > WIN_INIT)
init = WIN_INIT;
zmemzero(s->window + curr, (unsigned)init);
s->high_water = curr + init;
}
else if (s->high_water < (ulg)curr + WIN_INIT) {
/* High water mark at or above current data, but below current data
* plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
* to end of window, whichever is less.
*/
init = (ulg)curr + WIN_INIT - s->high_water;
if (init > s->window_size - s->high_water)
init = s->window_size - s->high_water;
zmemzero(s->window + s->high_water, (unsigned)init);
s->high_water += init;
}
}
}
/* ===========================================================================

View File

@ -1,5 +1,5 @@
/* deflate.h -- internal compression state
* Copyright (C) 1995-2005 Jean-loup Gailly
* Copyright (C) 1995-2009 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -260,6 +260,13 @@ typedef struct internal_state {
* are always zero.
*/
ulg high_water;
/* High water mark offset in window for initialized bytes -- bytes above
* this are set to zero in order to avoid memory check warnings when
* longest match routines access bytes past the input. This is then
* updated to the new high water mark.
*/
} FAR deflate_state;
/* Output a byte on the stream.
@ -278,6 +285,10 @@ typedef struct internal_state {
* distances are limited to MAX_DIST instead of WSIZE.
*/
#define WIN_INIT MAX_MATCH
/* Number of bytes after end of data in window to initialize in order to avoid
memory checker errors from longest match routines */
/* in trees.c */
void _tr_init OF((deflate_state *s));
int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));

View File

@ -121,7 +121,7 @@ At least for deflate's output that generates new trees every several 10's of
kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code
would take too long if you're only decoding several thousand symbols. At the
other extreme, you could make a new table for every bit in the code. In fact,
that's essentially a Huffman tree. But then you spend two much time
that's essentially a Huffman tree. But then you spend too much time
traversing the tree while decoding, even for short symbols.
So the number of bits for the first lookup table is a trade of the time to

View File

@ -1,4 +1,10 @@
This directory contains examples of the use of zlib.
This directory contains examples of the use of zlib and other relevant
programs and documentation.
enough.c
calculation and justification of ENOUGH parameter in inftrees.h
- calculates the maximum table space used in inflate tree
construction over all possible Huffman codes
fitblk.c
compress just enough input to nearly fill a requested output size
@ -23,9 +29,16 @@ gzjoin.c
gzlog.c
gzlog.h
efficiently maintain a message log file in gzip format
- illustrates use of raw deflate and Z_SYNC_FLUSH
- illustrates use of gzip header extra field
efficiently and robustly maintain a message log file in gzip format
- illustrates use of raw deflate, Z_PARTIAL_FLUSH, deflatePrime(),
and deflateSetDictionary()
- illustrates use of a gzip header extra field
pigz.c
parallel implementation of gzip compression
- uses pthreads to speed up compression on multiple core machines
- illustrates the use of deflateSetDictionary() with raw deflate
- illustrates the use of crc32_combine()
zlib_how.html
painfully comprehensive description of zpipe.c (see below)

569
examples/enough.c Normal file
View File

@ -0,0 +1,569 @@
/* enough.c -- determine the maximum size of inflate's Huffman code tables over
* all possible valid and complete Huffman codes, subject to a length limit.
* Copyright (C) 2007, 2008 Mark Adler
* Version 1.3 17 February 2008 Mark Adler
*/
/* Version history:
1.0 3 Jan 2007 First version (derived from codecount.c version 1.4)
1.1 4 Jan 2007 Use faster incremental table usage computation
Prune examine() search on previously visited states
1.2 5 Jan 2007 Comments clean up
As inflate does, decrease root for short codes
Refuse cases where inflate would increase root
1.3 17 Feb 2008 Add argument for initial root table size
Fix bug for initial root table size == max - 1
Use a macro to compute the history index
*/
/*
Examine all possible Huffman codes for a given number of symbols and a
maximum code length in bits to determine the maximum table size for zilb's
inflate. Only complete Huffman codes are counted.
Two codes are considered distinct if the vectors of the number of codes per
length are not identical. So permutations of the symbol assignments result
in the same code for the counting, as do permutations of the assignments of
the bit values to the codes (i.e. only canonical codes are counted).
We build a code from shorter to longer lengths, determining how many symbols
are coded at each length. At each step, we have how many symbols remain to
be coded, what the last code length used was, and how many bit patterns of
that length remain unused. Then we add one to the code length and double the
number of unused patterns to graduate to the next code length. We then
assign all portions of the remaining symbols to that code length that
preserve the properties of a correct and eventually complete code. Those
properties are: we cannot use more bit patterns than are available; and when
all the symbols are used, there are exactly zero possible bit patterns
remaining.
The inflate Huffman decoding algorithm uses two-level lookup tables for
speed. There is a single first-level table to decode codes up to root bits
in length (root == 9 in the current inflate implementation). The table
has 1 << root entries and is indexed by the next root bits of input. Codes
shorter than root bits have replicated table entries, so that the correct
entry is pointed to regardless of the bits that follow the short code. If
the code is longer than root bits, then the table entry points to a second-
level table. The size of that table is determined by the longest code with
that root-bit prefix. If that longest code has length len, then the table
has size 1 << (len - root), to index the remaining bits in that set of
codes. Each subsequent root-bit prefix then has its own sub-table. The
total number of table entries required by the code is calculated
incrementally as the number of codes at each bit length is populated. When
all of the codes are shorter than root bits, then root is reduced to the
longest code length, resulting in a single, smaller, one-level table.
The inflate algorithm also provides for small values of root (relative to
the log2 of the number of symbols), where the shortest code has more bits
than root. In that case, root is increased to the length of the shortest
code. This program, by design, does not handle that case, so it is verified
that the number of symbols is less than 2^(root + 1).
In order to speed up the examination (by about ten orders of magnitude for
the default arguments), the intermediate states in the build-up of a code
are remembered and previously visited branches are pruned. The memory
required for this will increase rapidly with the total number of symbols and
the maximum code length in bits. However this is a very small price to pay
for the vast speedup.
First, all of the possible Huffman codes are counted, and reachable
intermediate states are noted by a non-zero count in a saved-results array.
Second, the intermediate states that lead to (root + 1) bit or longer codes
are used to look at all sub-codes from those junctures for their inflate
memory usage. (The amount of memory used is not affected by the number of
codes of root bits or less in length.) Third, the visited states in the
construction of those sub-codes and the associated calculation of the table
size is recalled in order to avoid recalculating from the same juncture.
Beginning the code examination at (root + 1) bit codes, which is enabled by
identifying the reachable nodes, accounts for about six of the orders of
magnitude of improvement for the default arguments. About another four
orders of magnitude come from not revisiting previous states. Out of
approximately 2x10^16 possible Huffman codes, only about 2x10^6 sub-codes
need to be examined to cover all of the possible table memory usage cases
for the default arguments of 286 symbols limited to 15-bit codes.
Note that an unsigned long long type is used for counting. It is quite easy
to exceed the capacity of an eight-byte integer with a large number of
symbols and a large maximum code length, so multiple-precision arithmetic
would need to replace the unsigned long long arithmetic in that case. This
program will abort if an overflow occurs. The big_t type identifies where
the counting takes place.
An unsigned long long type is also used for calculating the number of
possible codes remaining at the maximum length. This limits the maximum
code length to the number of bits in a long long minus the number of bits
needed to represent the symbols in a flat code. The code_t type identifies
where the bit pattern counting takes place.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define local static
/* special data types */
typedef unsigned long long big_t; /* type for code counting */
typedef unsigned long long code_t; /* type for bit pattern counting */
struct tab { /* type for been here check */
size_t len; /* length of bit vector in char's */
char *vec; /* allocated bit vector */
};
/* The array for saving results, num[], is indexed with this triplet:
syms: number of symbols remaining to code
left: number of available bit patterns at length len
len: number of bits in the codes currently being assigned
Those indices are constrained thusly when saving results:
syms: 3..totsym (totsym == total symbols to code)
left: 2..syms - 1, but only the evens (so syms == 8 -> 2, 4, 6)
len: 1..max - 1 (max == maximum code length in bits)
syms == 2 is not saved since that immediately leads to a single code. left
must be even, since it represents the number of available bit patterns at
the current length, which is double the number at the previous length.
left ends at syms-1 since left == syms immediately results in a single code.
(left > sym is not allowed since that would result in an incomplete code.)
len is less than max, since the code completes immediately when len == max.
The offset into the array is calculated for the three indices with the
first one (syms) being outermost, and the last one (len) being innermost.
We build the array with length max-1 lists for the len index, with syms-3
of those for each symbol. There are totsym-2 of those, with each one
varying in length as a function of sym. See the calculation of index in
count() for the index, and the calculation of size in main() for the size
of the array.
For the deflate example of 286 symbols limited to 15-bit codes, the array
has 284,284 entries, taking up 2.17 MB for an 8-byte big_t. More than
half of the space allocated for saved results is actually used -- not all
possible triplets are reached in the generation of valid Huffman codes.
*/
/* The array for tracking visited states, done[], is itself indexed identically
to the num[] array as described above for the (syms, left, len) triplet.
Each element in the array is further indexed by the (mem, rem) doublet,
where mem is the amount of inflate table space used so far, and rem is the
remaining unused entries in the current inflate sub-table. Each indexed
element is simply one bit indicating whether the state has been visited or
not. Since the ranges for mem and rem are not known a priori, each bit
vector is of a variable size, and grows as needed to accommodate the visited
states. mem and rem are used to calculate a single index in a triangular
array. Since the range of mem is expected in the default case to be about
ten times larger than the range of rem, the array is skewed to reduce the
memory usage, with eight times the range for mem than for rem. See the
calculations for offset and bit in beenhere() for the details.
For the deflate example of 286 symbols limited to 15-bit codes, the bit
vectors grow to total approximately 21 MB, in addition to the 4.3 MB done[]
array itself.
*/
/* Globals to avoid propagating constants or constant pointers recursively */
local int max; /* maximum allowed bit length for the codes */
local int root; /* size of base code table in bits */
local int large; /* largest code table so far */
local size_t size; /* number of elements in num and done */
local int *code; /* number of symbols assigned to each bit length */
local big_t *num; /* saved results array for code counting */
local struct tab *done; /* states already evaluated array */
/* Index function for num[] and done[] */
#define INDEX(i,j,k) (((size_t)((i-1)>>1)*((i-2)>>1)+(j>>1)-1)*(max-1)+k-1)
/* Free allocated space. Uses globals code, num, and done. */
local void cleanup(void)
{
size_t n;
if (done != NULL) {
for (n = 0; n < size; n++)
if (done[n].len)
free(done[n].vec);
free(done);
}
if (num != NULL)
free(num);
if (code != NULL)
free(code);
}
/* Return the number of possible Huffman codes using bit patterns of lengths
len through max inclusive, coding syms symbols, with left bit patterns of
length len unused -- return -1 if there is an overflow in the counting.
Keep a record of previous results in num to prevent repeating the same
calculation. Uses the globals max and num. */
local big_t count(int syms, int len, int left)
{
big_t sum; /* number of possible codes from this juncture */
big_t got; /* value returned from count() */
int least; /* least number of syms to use at this juncture */
int most; /* most number of syms to use at this juncture */
int use; /* number of bit patterns to use in next call */
size_t index; /* index of this case in *num */
/* see if only one possible code */
if (syms == left)
return 1;
/* note and verify the expected state */
assert(syms > left && left > 0 && len < max);
/* see if we've done this one already */
index = INDEX(syms, left, len);
got = num[index];
if (got)
return got; /* we have -- return the saved result */
/* we need to use at least this many bit patterns so that the code won't be
incomplete at the next length (more bit patterns than symbols) */
least = (left << 1) - syms;
if (least < 0)
least = 0;
/* we can use at most this many bit patterns, lest there not be enough
available for the remaining symbols at the maximum length (if there were
no limit to the code length, this would become: most = left - 1) */
most = (((code_t)left << (max - len)) - syms) /
(((code_t)1 << (max - len)) - 1);
/* count all possible codes from this juncture and add them up */
sum = 0;
for (use = least; use <= most; use++) {
got = count(syms - use, len + 1, (left - use) << 1);
sum += got;
if (got == -1 || sum < got) /* overflow */
return -1;
}
/* verify that all recursive calls are productive */
assert(sum != 0);
/* save the result and return it */
num[index] = sum;
return sum;
}
/* Return true if we've been here before, set to true if not. Set a bit in a
bit vector to indicate visiting this state. Each (syms,len,left) state
has a variable size bit vector indexed by (mem,rem). The bit vector is
lengthened if needed to allow setting the (mem,rem) bit. */
local int beenhere(int syms, int len, int left, int mem, int rem)
{
size_t index; /* index for this state's bit vector */
size_t offset; /* offset in this state's bit vector */
int bit; /* mask for this state's bit */
size_t length; /* length of the bit vector in bytes */
char *vector; /* new or enlarged bit vector */
/* point to vector for (syms,left,len), bit in vector for (mem,rem) */
index = INDEX(syms, left, len);
mem -= 1 << root;
offset = (mem >> 3) + rem;
offset = ((offset * (offset + 1)) >> 1) + rem;
bit = 1 << (mem & 7);
/* see if we've been here */
length = done[index].len;
if (offset < length && (done[index].vec[offset] & bit) != 0)
return 1; /* done this! */
/* we haven't been here before -- set the bit to show we have now */
/* see if we need to lengthen the vector in order to set the bit */
if (length <= offset) {
/* if we have one already, enlarge it, zero out the appended space */
if (length) {
do {
length <<= 1;
} while (length <= offset);
vector = realloc(done[index].vec, length);
if (vector != NULL)
memset(vector + done[index].len, 0, length - done[index].len);
}
/* otherwise we need to make a new vector and zero it out */
else {
length = 1 << (len - root);
while (length <= offset)
length <<= 1;
vector = calloc(length, sizeof(char));
}
/* in either case, bail if we can't get the memory */
if (vector == NULL) {
fputs("abort: unable to allocate enough memory\n", stderr);
cleanup();
exit(1);
}
/* install the new vector */
done[index].len = length;
done[index].vec = vector;
}
/* set the bit */
done[index].vec[offset] |= bit;
return 0;
}
/* Examine all possible codes from the given node (syms, len, left). Compute
the amount of memory required to build inflate's decoding tables, where the
number of code structures used so far is mem, and the number remaining in
the current sub-table is rem. Uses the globals max, code, root, large, and
done. */
local void examine(int syms, int len, int left, int mem, int rem)
{
int least; /* least number of syms to use at this juncture */
int most; /* most number of syms to use at this juncture */
int use; /* number of bit patterns to use in next call */
/* see if we have a complete code */
if (syms == left) {
/* set the last code entry */
code[len] = left;
/* complete computation of memory used by this code */
while (rem < left) {
left -= rem;
rem = 1 << (len - root);
mem += rem;
}
assert(rem == left);
/* if this is a new maximum, show the entries used and the sub-code */
if (mem > large) {
large = mem;
printf("max %d: ", mem);
for (use = root + 1; use <= max; use++)
if (code[use])
printf("%d[%d] ", code[use], use);
putchar('\n');
fflush(stdout);
}
/* remove entries as we drop back down in the recursion */
code[len] = 0;
return;
}
/* prune the tree if we can */
if (beenhere(syms, len, left, mem, rem))
return;
/* we need to use at least this many bit patterns so that the code won't be
incomplete at the next length (more bit patterns than symbols) */
least = (left << 1) - syms;
if (least < 0)
least = 0;
/* we can use at most this many bit patterns, lest there not be enough
available for the remaining symbols at the maximum length (if there were
no limit to the code length, this would become: most = left - 1) */
most = (((code_t)left << (max - len)) - syms) /
(((code_t)1 << (max - len)) - 1);
/* occupy least table spaces, creating new sub-tables as needed */
use = least;
while (rem < use) {
use -= rem;
rem = 1 << (len - root);
mem += rem;
}
rem -= use;
/* examine codes from here, updating table space as we go */
for (use = least; use <= most; use++) {
code[len] = use;
examine(syms - use, len + 1, (left - use) << 1,
mem + (rem ? 1 << (len - root) : 0), rem << 1);
if (rem == 0) {
rem = 1 << (len - root);
mem += rem;
}
rem--;
}
/* remove entries as we drop back down in the recursion */
code[len] = 0;
}
/* Look at all sub-codes starting with root + 1 bits. Look at only the valid
intermediate code states (syms, left, len). For each completed code,
calculate the amount of memory required by inflate to build the decoding
tables. Find the maximum amount of memory required and show the code that
requires that maximum. Uses the globals max, root, and num. */
local void enough(int syms)
{
int n; /* number of remaing symbols for this node */
int left; /* number of unused bit patterns at this length */
size_t index; /* index of this case in *num */
/* clear code */
for (n = 0; n <= max; n++)
code[n] = 0;
/* look at all (root + 1) bit and longer codes */
large = 1 << root; /* base table */
if (root < max) /* otherwise, there's only a base table */
for (n = 3; n <= syms; n++)
for (left = 2; left < n; left += 2)
{
/* look at all reachable (root + 1) bit nodes, and the
resulting codes (complete at root + 2 or more) */
index = INDEX(n, left, root + 1);
if (root + 1 < max && num[index]) /* reachable node */
examine(n, root + 1, left, 1 << root, 0);
/* also look at root bit codes with completions at root + 1
bits (not saved in num, since complete), just in case */
if (num[index - 1] && n <= left << 1)
examine((n - left) << 1, root + 1, (n - left) << 1,
1 << root, 0);
}
/* done */
printf("done: maximum of %d table entries\n", large);
}
/*
Examine and show the total number of possible Huffman codes for a given
maximum number of symbols, initial root table size, and maximum code length
in bits -- those are the command arguments in that order. The default
values are 286, 9, and 15 respectively, for the deflate literal/length code.
The possible codes are counted for each number of coded symbols from two to
the maximum. The counts for each of those and the total number of codes are
shown. The maximum number of inflate table entires is then calculated
across all possible codes. Each new maximum number of table entries and the
associated sub-code (starting at root + 1 == 10 bits) is shown.
To count and examine Huffman codes that are not length-limited, provide a
maximum length equal to the number of symbols minus one.
For the deflate literal/length code, use "enough". For the deflate distance
code, use "enough 30 6".
This uses the %llu printf format to print big_t numbers, which assumes that
big_t is an unsigned long long. If the big_t type is changed (for example
to a multiple precision type), the method of printing will also need to be
updated.
*/
int main(int argc, char **argv)
{
int syms; /* total number of symbols to code */
int n; /* number of symbols to code for this run */
big_t got; /* return value of count() */
big_t sum; /* accumulated number of codes over n */
/* set up globals for cleanup() */
code = NULL;
num = NULL;
done = NULL;
/* get arguments -- default to the deflate literal/length code */
syms = 286;
root = 9;
max = 15;
if (argc > 1) {
syms = atoi(argv[1]);
if (argc > 2) {
root = atoi(argv[2]);
if (argc > 3)
max = atoi(argv[3]);
}
}
if (argc > 4 || syms < 2 || root < 1 || max < 1) {
fputs("invalid arguments, need: [sym >= 2 [root >= 1 [max >= 1]]]\n",
stderr);
return 1;
}
/* if not restricting the code length, the longest is syms - 1 */
if (max > syms - 1)
max = syms - 1;
/* determine the number of bits in a code_t */
n = 0;
while (((code_t)1 << n) != 0)
n++;
/* make sure that the calculation of most will not overflow */
if (max > n || syms - 2 >= (((code_t)0 - 1) >> (max - 1))) {
fputs("abort: code length too long for internal types\n", stderr);
return 1;
}
/* reject impossible code requests */
if (syms - 1 > ((code_t)1 << max) - 1) {
fprintf(stderr, "%d symbols cannot be coded in %d bits\n",
syms, max);
return 1;
}
/* allocate code vector */
code = calloc(max + 1, sizeof(int));
if (code == NULL) {
fputs("abort: unable to allocate enough memory\n", stderr);
return 1;
}
/* determine size of saved results array, checking for overflows,
allocate and clear the array (set all to zero with calloc()) */
if (syms == 2) /* iff max == 1 */
num = NULL; /* won't be saving any results */
else {
size = syms >> 1;
if (size > ((size_t)0 - 1) / (n = (syms - 1) >> 1) ||
(size *= n, size > ((size_t)0 - 1) / (n = max - 1)) ||
(size *= n, size > ((size_t)0 - 1) / sizeof(big_t)) ||
(num = calloc(size, sizeof(big_t))) == NULL) {
fputs("abort: unable to allocate enough memory\n", stderr);
cleanup();
return 1;
}
}
/* count possible codes for all numbers of symbols, add up counts */
sum = 0;
for (n = 2; n <= syms; n++) {
got = count(n, 1, 2);
sum += got;
if (got == -1 || sum < got) { /* overflow */
fputs("abort: can't count that high!\n", stderr);
cleanup();
return 1;
}
printf("%llu %d-codes\n", got, n);
}
printf("%llu total codes for 2 to %d symbols", sum, syms);
if (max < syms - 1)
printf(" (%d-bit length limit)\n", max);
else
puts(" (no length limit)");
/* allocate and clear done array for beenhere() */
if (syms == 2)
done = NULL;
else if (size > ((size_t)0 - 1) / sizeof(struct tab) ||
(done = calloc(size, sizeof(struct tab))) == NULL) {
fputs("abort: unable to allocate enough memory\n", stderr);
cleanup();
return 1;
}
/* find and show maximum inflate table usage */
if (root > max) /* reduce root to max length */
root = max;
if (syms < ((code_t)1 << (root + 1)))
enough(syms);
else
puts("cannot handle minimum code lengths > root");
/* done */
cleanup();
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/* gzlog.h
Copyright (C) 2004 Mark Adler, all rights reserved
version 1.0, 26 Nov 2004
Copyright (C) 2004, 2008 Mark Adler, all rights reserved
version 2.0, 25 Apr 2008
This software is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages
@ -21,38 +21,69 @@
Mark Adler madler@alumni.caltech.edu
*/
/* Version History:
1.0 26 Nov 2004 First version
2.0 25 Apr 2008 Complete redesign for recovery of interrupted operations
Interface changed slightly in that now path is a prefix
Compression now occurs as needed during gzlog_write()
gzlog_write() now always leaves the log file as valid gzip
*/
/*
The gzlog object allows writing short messages to a gzipped log file,
opening the log file locked for small bursts, and then closing it. The log
object works by appending stored data to the gzip file until 1 MB has been
accumulated. At that time, the stored data is compressed, and replaces the
uncompressed data in the file. The log file is truncated to its new size at
that time. After closing, the log file is always valid gzip file that can
decompressed to recover what was written.
object works by appending stored (uncompressed) data to the gzip file until
1 MB has been accumulated. At that time, the stored data is compressed, and
replaces the uncompressed data in the file. The log file is truncated to
its new size at that time. After each write operation, the log file is a
valid gzip file that can decompressed to recover what was written.
A gzip header "extra" field contains two file offsets for appending. The
first points to just after the last compressed data. The second points to
the last stored block in the deflate stream, which is empty. All of the
data between those pointers is uncompressed.
The gzlog operations can be interupted at any point due to an application or
system crash, and the log file will be recovered the next time the log is
opened with gzlog_open().
*/
#ifndef GZLOG_H
#define GZLOG_H
/* gzlog object type */
typedef void gzlog;
/* Open a gzlog object, creating the log file if it does not exist. Return
NULL on error. Note that gzlog_open() could take a long time to return if
there is difficulty in locking the file. */
void *gzlog_open(char *path);
NULL on error. Note that gzlog_open() could take a while to complete if it
has to wait to verify that a lock is stale (possibly for five minutes), or
if there is significant contention with other instantiations of this object
when locking the resource. path is the prefix of the file names created by
this object. If path is "foo", then the log file will be "foo.gz", and
other auxiliary files will be created and destroyed during the process:
"foo.dict" for a compression dictionary, "foo.temp" for a temporary (next)
dictionary, "foo.add" for data being added or compressed, "foo.lock" for the
lock file, and "foo.repairs" to log recovery operations performed due to
interrupted gzlog operations. A gzlog_open() followed by a gzlog_close()
will recover a previously interrupted operation, if any. */
gzlog *gzlog_open(char *path);
/* Write to a gzlog object. Return non-zero on error. This function will
simply write data to the file uncompressed. Compression of the data
will not occur until gzlog_close() is called. It is expected that
gzlog_write() is used for a short message, and then gzlog_close() is
called. If a large amount of data is to be written, then the application
should write no more than 1 MB at a time with gzlog_write() before
calling gzlog_close() and then gzlog_open() again. */
int gzlog_write(void *log, char *data, size_t len);
/* Write to a gzlog object. Return zero on success, -1 if there is a file i/o
error on any of the gzlog files (this should not happen if gzlog_open()
succeeded, unless the device has run out of space or leftover auxiliary
files have permissions or ownership that prevent their use), -2 if there is
a memory allocation failure, or -3 if the log argument is invalid (e.g. if
it was not created by gzlog_open()). This function will write data to the
file uncompressed, until 1 MB has been accumulated, at which time that data
will be compressed. The log file will be a valid gzip file upon successful
return. */
int gzlog_write(gzlog *log, void *data, size_t len);
/* Close a gzlog object. Return non-zero on error. The log file is locked
until this function is called. This function will compress stored data
at the end of the gzip file if at least 1 MB has been accumulated. Note
that the file will not be a valid gzip file until this function completes.
*/
int gzlog_close(void *log);
/* Force compression of any uncompressed data in the log. This should be used
sparingly, if at all. The main application would be when a log file will
not be appended to again. If this is used to compress frequently while
appending, it will both significantly increase the execution time and
reduce the compression ratio. The return codes are the same as for
gzlog_write(). */
int gzlog_compress(gzlog *log);
/* Close a gzlog object. Return zero on success, -3 if the log argument is
invalid. The log object is freed, and so cannot be referenced again. */
int gzlog_close(gzlog *log);
#endif

452
examples/pigz.c Normal file
View File

@ -0,0 +1,452 @@
/* pigz.c -- parallel implementation of gzip
* Copyright (C) 2007 Mark Adler
* Version 1.1 28 January 2007 Mark Adler
*/
/* Version history:
1.0 17 Jan 2007 First version
1.1 28 Jan 2007 Avoid void * arithmetic (some compilers don't get that)
Add note about requiring zlib 1.2.3
Allow compression level 0 (no compression)
Completely rewrite parallelism -- add a write thread
Use deflateSetDictionary() to make use of history
Tune argument defaults to best performance on four cores
*/
/*
pigz compresses from stdin to stdout using threads to make use of multiple
processors and cores. The input is broken up into 128 KB chunks, and each
is compressed separately. The CRC for each chunk is also calculated
separately. The compressed chunks are written in order to the output,
and the overall CRC is calculated from the CRC's of the chunks.
The compressed data format generated is the gzip format using the deflate
compression method. First a gzip header is written, followed by raw deflate
partial streams. They are partial, in that they do not have a terminating
block. At the end, the deflate stream is terminated with a final empty
static block, and lastly a gzip trailer is written with the CRC and the
number of input bytes.
Each raw deflate partial stream is terminated by an empty stored block
(using the Z_SYNC_FLUSH option of zlib), in order to end that partial
bit stream at a byte boundary. That allows the partial streams to be
concantenated simply as sequences of bytes. This adds a very small four
or five byte overhead to the output for each input chunk.
zlib's crc32_combine() routine allows the calcuation of the CRC of the
entire input using the independent CRC's of the chunks. pigz requires zlib
version 1.2.3 or later, since that is the first version that provides the
crc32_combine() function.
pigz uses the POSIX pthread library for thread control and communication.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include "zlib.h"
#define local static
/* exit with error */
local void bail(char *msg)
{
fprintf(stderr, "pigz abort: %s\n", msg);
exit(1);
}
/* read up to len bytes into buf, repeating read() calls as needed */
local size_t readn(int desc, unsigned char *buf, size_t len)
{
ssize_t ret;
size_t got;
got = 0;
while (len) {
ret = read(desc, buf, len);
if (ret < 0)
bail("read error");
if (ret == 0)
break;
buf += ret;
len -= ret;
got += ret;
}
return got;
}
/* write len bytes, repeating write() calls as needed */
local void writen(int desc, unsigned char *buf, size_t len)
{
ssize_t ret;
while (len) {
ret = write(desc, buf, len);
if (ret < 1)
bail("write error");
buf += ret;
len -= ret;
}
}
/* a flag variable for communication between two threads */
struct flag {
int value; /* value of flag */
pthread_mutex_t lock; /* lock for checking and changing flag */
pthread_cond_t cond; /* condition for signaling on flag change */
};
/* initialize a flag for use, starting with value val */
local void flag_init(struct flag *me, int val)
{
me->value = val;
pthread_mutex_init(&(me->lock), NULL);
pthread_cond_init(&(me->cond), NULL);
}
/* set the flag to val, signal another process that may be waiting for it */
local void flag_set(struct flag *me, int val)
{
pthread_mutex_lock(&(me->lock));
me->value = val;
pthread_cond_signal(&(me->cond));
pthread_mutex_unlock(&(me->lock));
}
/* if it isn't already, wait for some other thread to set the flag to val */
local void flag_wait(struct flag *me, int val)
{
pthread_mutex_lock(&(me->lock));
while (me->value != val)
pthread_cond_wait(&(me->cond), &(me->lock));
pthread_mutex_unlock(&(me->lock));
}
/* if flag is equal to val, wait for some other thread to change it */
local void flag_wait_not(struct flag *me, int val)
{
pthread_mutex_lock(&(me->lock));
while (me->value == val)
pthread_cond_wait(&(me->cond), &(me->lock));
pthread_mutex_unlock(&(me->lock));
}
/* clean up the flag when done with it */
local void flag_done(struct flag *me)
{
pthread_cond_destroy(&(me->cond));
pthread_mutex_destroy(&(me->lock));
}
/* a unit of work to feed to compress_thread() -- it is assumed that the out
buffer is large enough to hold the maximum size len bytes could deflate to,
plus five bytes for the final sync marker */
struct work {
size_t len; /* length of input */
unsigned long crc; /* crc of input */
unsigned char *buf; /* input */
unsigned char *out; /* space for output (guaranteed big enough) */
z_stream strm; /* pre-initialized z_stream */
struct flag busy; /* busy flag indicating work unit in use */
pthread_t comp; /* this compression thread */
};
/* busy flag values */
#define IDLE 0 /* compress and writing done -- can start compress */
#define COMP 1 /* compress -- input and output buffers in use */
#define WRITE 2 /* compress done, writing output -- can read input */
/* read-only globals (set by main/read thread before others started) */
local int ind; /* input file descriptor */
local int outd; /* output file descriptor */
local int level; /* compression level */
local int procs; /* number of compression threads (>= 2) */
local size_t size; /* uncompressed input size per thread (>= 32K) */
local struct work *jobs; /* work units: jobs[0..procs-1] */
/* next and previous jobs[] indices */
#define NEXT(n) ((n) == procs - 1 ? 0 : (n) + 1)
#define PREV(n) ((n) == 0 ? procs - 1 : (n) - 1)
/* sliding dictionary size for deflate */
#define DICT 32768U
/* largest power of 2 that fits in an unsigned int -- used to limit requests
to zlib functions that use unsigned int lengths */
#define MAX ((((unsigned)-1) >> 1) + 1)
/* compress thread: compress the input in the provided work unit and compute
its crc -- assume that the amount of space at job->out is guaranteed to be
enough for the compressed output, as determined by the maximum expansion
of deflate compression -- use the input in the previous work unit (if there
is one) to set the deflate dictionary for better compression */
local void *compress_thread(void *arg)
{
size_t len; /* input length for this work unit */
unsigned long crc; /* crc of input data */
struct work *prev; /* previous work unit */
struct work *job = arg; /* work unit for this thread */
z_stream *strm = &(job->strm); /* zlib stream for this work unit */
/* reset state for a new compressed stream */
(void)deflateReset(strm);
/* initialize input, output, and crc */
strm->next_in = job->buf;
strm->next_out = job->out;
len = job->len;
crc = crc32(0L, Z_NULL, 0);
/* set dictionary if this isn't the first work unit, and if we will be
compressing something (the read thread assures that the dictionary
data in the previous work unit is still there) */
prev = jobs + PREV(job - jobs);
if (prev->buf != NULL && len != 0)
deflateSetDictionary(strm, prev->buf + (size - DICT), DICT);
/* run MAX-sized amounts of input through deflate and crc32 -- this loop
is needed for those cases where the integer type is smaller than the
size_t type, or when len is close to the limit of the size_t type */
while (len > MAX) {
strm->avail_in = MAX;
strm->avail_out = (unsigned)-1;
crc = crc32(crc, strm->next_in, strm->avail_in);
(void)deflate(strm, Z_NO_FLUSH);
len -= MAX;
}
/* run last piece through deflate and crc32, follow with a sync marker */
if (len) {
strm->avail_in = len;
strm->avail_out = (unsigned)-1;
crc = crc32(crc, strm->next_in, strm->avail_in);
(void)deflate(strm, Z_SYNC_FLUSH);
}
/* don't need to Z_FINISH, since we'd delete the last two bytes anyway */
/* return result */
job->crc = crc;
return NULL;
}
/* put a 4-byte integer into a byte array in LSB order */
#define PUT4(a,b) (*(a)=(b),(a)[1]=(b)>>8,(a)[2]=(b)>>16,(a)[3]=(b)>>24)
/* write thread: wait for compression threads to complete, write output in
order, also write gzip header and trailer around the compressed data */
local void *write_thread(void *arg)
{
int n; /* compress thread index */
size_t len; /* length of input processed */
unsigned long tot; /* total uncompressed size (overflow ok) */
unsigned long crc; /* CRC-32 of uncompressed data */
unsigned char wrap[10]; /* gzip header or trailer */
/* write simple gzip header */
memcpy(wrap, "\037\213\10\0\0\0\0\0\0\3", 10);
wrap[8] = level == 9 ? 2 : (level == 1 ? 4 : 0);
writen(outd, wrap, 10);
/* process output of compress threads until end of input */
tot = 0;
crc = crc32(0L, Z_NULL, 0);
n = 0;
do {
/* wait for compress thread to start, then wait to complete */
flag_wait(&(jobs[n].busy), COMP);
pthread_join(jobs[n].comp, NULL);
/* now that compress is done, allow read thread to use input buffer */
flag_set(&(jobs[n].busy), WRITE);
/* write compressed data and update length and crc */
writen(outd, jobs[n].out, jobs[n].strm.next_out - jobs[n].out);
len = jobs[n].len;
tot += len;
crc = crc32_combine(crc, jobs[n].crc, len);
/* release this work unit and go to the next work unit */
flag_set(&(jobs[n].busy), IDLE);
n = NEXT(n);
/* an input buffer less than size in length indicates end of input */
} while (len == size);
/* write final static block and gzip trailer (crc and len mod 2^32) */
wrap[0] = 3; wrap[1] = 0;
PUT4(wrap + 2, crc);
PUT4(wrap + 6, tot);
writen(outd, wrap, 10);
return NULL;
}
/* one-time initialization of a work unit -- this is where we set the deflate
compression level and request raw deflate, and also where we set the size
of the output buffer to guarantee enough space for a worst-case deflate
ending with a Z_SYNC_FLUSH */
local void job_init(struct work *job)
{
int ret; /* deflateInit2() return value */
job->buf = malloc(size);
job->out = malloc(size + (size >> 11) + 10);
job->strm.zfree = Z_NULL;
job->strm.zalloc = Z_NULL;
job->strm.opaque = Z_NULL;
ret = deflateInit2(&(job->strm), level, Z_DEFLATED, -15, 8,
Z_DEFAULT_STRATEGY);
if (job->buf == NULL || job->out == NULL || ret != Z_OK)
bail("not enough memory");
}
/* compress ind to outd in the gzip format, using multiple threads for the
compression and crc calculation and another thread for writing the output --
the read thread is the main thread */
local void read_thread(void)
{
int n; /* general index */
size_t got; /* amount read */
pthread_attr_t attr; /* thread attributes (left at defaults) */
pthread_t write; /* write thread */
/* set defaults (not all pthread implementations default to joinable) */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
/* allocate and set up work list (individual work units will be initialized
as needed, in case the input is short), assure that allocation size
arithmetic does not overflow */
if (size + (size >> 11) + 10 < (size >> 11) + 10 ||
(ssize_t)(size + (size >> 11) + 10) < 0 ||
((size_t)0 - 1) / procs <= sizeof(struct work) ||
(jobs = malloc(procs * sizeof(struct work))) == NULL)
bail("not enough memory");
for (n = 0; n < procs; n++) {
jobs[n].buf = NULL;
flag_init(&(jobs[n].busy), IDLE);
}
/* start write thread */
pthread_create(&write, &attr, write_thread, NULL);
/* read from input and start compress threads (write thread will pick up
the output of the compress threads) */
n = 0;
do {
/* initialize this work unit if it's the first time it's used */
if (jobs[n].buf == NULL)
job_init(jobs + n);
/* read input data, but wait for last compress on this work unit to be
done, and wait for the dictionary to be used by the last compress on
the next work unit */
flag_wait_not(&(jobs[n].busy), COMP);
flag_wait_not(&(jobs[NEXT(n)].busy), COMP);
got = readn(ind, jobs[n].buf, size);
/* start compress thread, but wait for write to be done first */
flag_wait(&(jobs[n].busy), IDLE);
jobs[n].len = got;
pthread_create(&(jobs[n].comp), &attr, compress_thread, jobs + n);
/* mark work unit so write thread knows compress was started */
flag_set(&(jobs[n].busy), COMP);
/* go to the next work unit */
n = NEXT(n);
/* do until end of input, indicated by a read less than size */
} while (got == size);
/* wait for the write thread to complete -- the write thread will join with
all of the compress threads, so this waits for all of the threads to
complete */
pthread_join(write, NULL);
/* free up all requested resources and return */
for (n = procs - 1; n >= 0; n--) {
flag_done(&(jobs[n].busy));
(void)deflateEnd(&(jobs[n].strm));
free(jobs[n].out);
free(jobs[n].buf);
}
free(jobs);
pthread_attr_destroy(&attr);
}
/* Process arguments for level, size, and procs, compress from stdin to
stdout in the gzip format. Note that procs must be at least two in
order to provide a dictionary in one work unit for the other work
unit, and that size must be at least 32K to store a full dictionary. */
int main(int argc, char **argv)
{
int n; /* general index */
int get; /* command line parameters to get */
char *arg; /* command line argument */
/* set defaults -- 32 processes and 128K buffers was found to provide
good utilization of four cores (about 97%) and balanced the overall
execution time impact of more threads against more dictionary
processing for a fixed amount of memory -- the memory usage for these
settings and full use of all work units (at least 4 MB of input) is
16.2 MB
*/
level = Z_DEFAULT_COMPRESSION;
procs = 32;
size = 131072UL;
/* process command-line arguments */
get = 0;
for (n = 1; n < argc; n++) {
arg = argv[n];
if (*arg == '-') {
while (*++arg)
if (*arg >= '0' && *arg <= '9') /* compression level */
level = *arg - '0';
else if (*arg == 'b') /* chunk size in K */
get |= 1;
else if (*arg == 'p') /* number of processes */
get |= 2;
else if (*arg == 'h') { /* help */
fputs("usage: pigz [-0..9] [-b blocksizeinK]", stderr);
fputs(" [-p processes] < foo > foo.gz\n", stderr);
return 0;
}
else
bail("invalid option");
}
else if (get & 1) {
if (get & 2)
bail("you need to separate the -b and -p options");
size = (size_t)(atol(arg)) << 10; /* chunk size */
if (size < DICT)
bail("invalid option");
get = 0;
}
else if (get & 2) {
procs = atoi(arg); /* processes */
if (procs < 2)
bail("invalid option");
get = 0;
}
else
bail("invalid option (you need to pipe input and output)");
}
if (get)
bail("missing option argument");
/* do parallel compression from stdin to stdout (the read thread starts up
the write thread and the compression threads, and they all join before
the read thread returns) */
ind = 0;
outd = 1;
read_thread();
/* done */
return 0;
}

98
gzio.c
View File

@ -1,5 +1,5 @@
/* gzio.c -- IO on .gz files
* Copyright (C) 1995-2006 Jean-loup Gailly.
* Copyright (C) 1995-2009 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.
@ -71,43 +71,32 @@ static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
typedef struct gz_stream {
z_stream stream;
int z_err; /* error code for last stream operation */
int z_eof; /* set if end of input file */
FILE *file; /* .gz file */
Byte *inbuf; /* input buffer */
Byte *outbuf; /* output buffer */
uLong crc; /* crc32 of uncompressed data */
char *msg; /* error message */
char *path; /* path name for debugging only */
int transparent; /* 1 if input file is not a .gz file */
char mode; /* 'w' or 'r' */
#ifdef _LARGEFILE64_SOURCE
off64_t start; /* start of compressed data in file (header skipped) */
off64_t in; /* bytes into deflate or inflate */
off64_t out; /* bytes out of deflate or inflate */
#else
z_off_t start; /* start of compressed data in file (header skipped) */
z_off_t in; /* bytes into deflate or inflate */
z_off_t out; /* bytes out of deflate or inflate */
#endif
int back; /* one character push-back */
int last; /* true if push-back is last character */
int z_err; /* error code for last stream operation */
int z_eof; /* set if end of input file */
FILE *file; /* .gz file */
Byte *inbuf; /* input buffer */
Byte *outbuf; /* output buffer */
uLong crc; /* crc32 of uncompressed data */
char *msg; /* error message */
char *path; /* path name for debugging only */
int transparent; /* 1 if input file is not a .gz file */
char mode; /* 'w' or 'r' */
z_off64_t start; /* start of compressed data in file */
z_off64_t in; /* bytes into deflate or inflate */
z_off64_t out; /* bytes out of deflate or inflate */
int back; /* one character push-back */
int last; /* true if push-back is last character */
} gz_stream;
local gzFile gz_open OF((const char *path, const char *mode, int fd,
int use64));
#ifdef _LARGEFILE64_SOURCE
local off64_t gz_seek OF((gzFile file, off64_t offset, int whence, int use64));
#else
local z_off_t gz_seek OF((gzFile file, z_off_t offset, int whence, int use64));
#endif
local int do_flush OF((gzFile file, int flush));
local int get_byte OF((gz_stream *s));
local void check_header OF((gz_stream *s));
local int destroy OF((gz_stream *s));
local void putLong OF((FILE *file, uLong x));
local uLong getLong OF((gz_stream *s));
local gzFile gz_open OF((const char *, const char *, int, int));
local z_off64_t gz_seek OF((gzFile, z_off64_t, int, int));
local int do_flush OF((gzFile, int));
local int get_byte OF((gz_stream *));
local void check_header OF((gz_stream *));
local int destroy OF((gz_stream *));
local void putLong OF((FILE *, uLong));
local uLong getLong OF((gz_stream *));
/* ===========================================================================
Opens a gzip (.gz) file for reading or writing. The mode parameter
@ -143,6 +132,7 @@ local gzFile gz_open (path, mode, fd, use64)
s->stream.next_in = s->inbuf = Z_NULL;
s->stream.next_out = s->outbuf = Z_NULL;
s->stream.avail_in = s->stream.avail_out = 0;
s->stream.state = Z_NULL;
s->file = NULL;
s->z_err = Z_OK;
s->z_eof = 0;
@ -442,7 +432,7 @@ int ZEXPORT gzread (file, buf, len)
if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
if (s->z_err == Z_STREAM_END) return 0; /* EOF */
if (s->z_err == Z_STREAM_END || s->z_eof) return 0; /* EOF */
next_out = (Byte*)buf;
s->stream.next_out = (Bytef*)buf;
@ -482,7 +472,7 @@ int ZEXPORT gzread (file, buf, len)
len -= s->stream.avail_out;
s->in += len;
s->out += len;
if (len == 0) s->z_eof = 1;
if (feof(s->file)) s->z_eof = 1;
return (int)len;
}
if (s->stream.avail_in == 0 && !s->z_eof) {
@ -803,15 +793,9 @@ int ZEXPORT gzflush (file, flush)
SEEK_END is not implemented, returns error.
In this version of the library, gzseek can be extremely slow.
*/
#ifdef _LARGEFILE64_SOURCE
local off64_t gz_seek (file, offset, whence, use64)
local z_off64_t gz_seek (file, offset, whence, use64)
gzFile file;
off64_t offset;
#else
local z_off_t gz_seek (file, offset, whence, use64)
gzFile file;
z_off_t offset;
#endif
z_off64_t offset;
int whence;
int use64;
{
@ -914,23 +898,17 @@ z_off_t ZEXPORT gzseek (file, offset, whence)
return (z_off_t)gz_seek(file, offset, whence, 0);
}
z_off64_t ZEXPORT gzseek64 (file, offset, whence)
gzFile file;
z_off64_t offset;
int whence;
{
#ifdef _LARGEFILE64_SOURCE
off64_t ZEXPORT gzseek64 (file, offset, whence)
gzFile file;
off64_t offset;
int whence;
{
return gz_seek(file, offset, whence, 1);
}
#else
z_off_t ZEXPORT gzseek64 (file, offset, whence)
gzFile file;
z_off_t offset;
int whence;
{
return gz_seek(file, offset, whence, 0);
}
#endif
}
/* ===========================================================================
Rewinds input file.
@ -968,11 +946,7 @@ z_off_t ZEXPORT gztell (file)
/* ===========================================================================
64-bit version
*/
#ifdef _LARGEFILE64_SOURCE
off64_t ZEXPORT gztell64 (file)
#else
z_off_t ZEXPORT gztell64 (file)
#endif
z_off64_t ZEXPORT gztell64 (file)
gzFile file;
{
return gzseek64(file, 0L, SEEK_CUR);

View File

@ -1,5 +1,5 @@
/* infback.c -- inflate using a call-back interface
* Copyright (C) 1995-2006 Mark Adler
* Copyright (C) 1995-2008 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -438,7 +438,16 @@ void FAR *out_desc;
/* handle error breaks in while */
if (state->mode == BAD) break;
/* build code tables */
/* check for end-of-block code (better have one) */
if (state->lens[256] == 0) {
strm->msg = (char *)"invalid code -- missing end-of-block";
state->mode = BAD;
break;
}
/* build code tables -- note: do not change the lenbits or distbits
values here (9 and 6) without reading the comments in inftrees.h
concerning the ENOUGH constants, which depend on those values */
state->next = state->codes;
state->lencode = (code const FAR *)(state->next);
state->lenbits = 9;

View File

@ -1,5 +1,5 @@
/* inffast.c -- fast decoding
* Copyright (C) 1995-2006 Mark Adler
* Copyright (C) 1995-2008 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -188,7 +188,8 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
op = dist - op; /* distance back in window */
if (op > whave) {
if (state->sane) {
strm->msg = (char *)"invalid distance too far back";
strm->msg =
(char *)"invalid distance too far back";
state->mode = BAD;
break;
}

136
inflate.c
View File

@ -1,5 +1,5 @@
/* inflate.c -- zlib decompression
* Copyright (C) 1995-2006 Mark Adler
* Copyright (C) 1995-2009 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -122,24 +122,47 @@ z_streamp strm;
state->bits = 0;
state->lencode = state->distcode = state->next = state->codes;
state->sane = 1;
state->back = -1;
Tracev((stderr, "inflate: reset\n"));
return Z_OK;
}
int ZEXPORT inflatePrime(strm, bits, value)
int ZEXPORT inflateReset2(strm, windowBits)
z_streamp strm;
int bits;
int value;
int windowBits;
{
int wrap;
struct inflate_state FAR *state;
/* get the state */
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state;
if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
value &= (1L << bits) - 1;
state->hold += value << state->bits;
state->bits += bits;
return Z_OK;
/* extract wrap request from windowBits parameter */
if (windowBits < 0) {
wrap = 0;
windowBits = -windowBits;
}
else {
wrap = (windowBits >> 4) + 1;
#ifdef GUNZIP
if (windowBits < 48)
windowBits &= 15;
#endif
}
/* set number of window bits, free window if different */
if (windowBits < 8 || windowBits > 15)
return Z_STREAM_ERROR;
if (state->wbits != windowBits && state->window != Z_NULL) {
ZFREE(strm, state->window);
state->window = Z_NULL;
}
/* update state and reset the rest of it */
state->wrap = wrap;
state->wbits = (unsigned)windowBits;
return inflateReset(strm);
}
int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
@ -148,6 +171,7 @@ int windowBits;
const char *version;
int stream_size;
{
int ret;
struct inflate_state FAR *state;
if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
@ -165,24 +189,13 @@ int stream_size;
if (state == Z_NULL) return Z_MEM_ERROR;
Tracev((stderr, "inflate: allocated\n"));
strm->state = (struct internal_state FAR *)state;
if (windowBits < 0) {
state->wrap = 0;
windowBits = -windowBits;
}
else {
state->wrap = (windowBits >> 4) + 1;
#ifdef GUNZIP
if (windowBits < 48) windowBits &= 15;
#endif
}
if (windowBits < 8 || windowBits > 15) {
state->window = Z_NULL;
ret = inflateReset2(strm, windowBits);
if (ret != Z_OK) {
ZFREE(strm, state);
strm->state = Z_NULL;
return Z_STREAM_ERROR;
}
state->wbits = (unsigned)windowBits;
state->window = Z_NULL;
return inflateReset(strm);
return ret;
}
int ZEXPORT inflateInit_(strm, version, stream_size)
@ -193,6 +206,27 @@ int stream_size;
return inflateInit2_(strm, DEF_WBITS, version, stream_size);
}
int ZEXPORT inflatePrime(strm, bits, value)
z_streamp strm;
int bits;
int value;
{
struct inflate_state FAR *state;
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state;
if (bits < 0) {
state->hold = 0;
state->bits = 0;
return Z_OK;
}
if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
value &= (1L << bits) - 1;
state->hold += value << state->bits;
state->bits += bits;
return Z_OK;
}
/*
Return state with length and distance decoding tables and index sizes set to
fixed code decoding. Normally this returns fixed tables from inffixed.h.
@ -772,7 +806,7 @@ int flush;
strm->adler = state->check = adler32(0L, Z_NULL, 0);
state->mode = TYPE;
case TYPE:
if (flush == Z_BLOCK) goto inf_leave;
if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
case TYPEDO:
if (state->last) {
BYTEBITS();
@ -792,7 +826,11 @@ int flush;
fixedtables(state);
Tracev((stderr, "inflate: fixed codes block%s\n",
state->last ? " (last)" : ""));
state->mode = LEN; /* decode codes */
state->mode = LEN_; /* decode codes */
if (flush == Z_TREES) {
DROPBITS(2);
goto inf_leave;
}
break;
case 2: /* dynamic block */
Tracev((stderr, "inflate: dynamic codes block%s\n",
@ -817,6 +855,9 @@ int flush;
Tracev((stderr, "inflate: stored length %u\n",
state->length));
INITBITS();
state->mode = COPY_;
if (flush == Z_TREES) goto inf_leave;
case COPY_:
state->mode = COPY;
case COPY:
copy = state->length;
@ -926,7 +967,16 @@ int flush;
/* handle error breaks in while */
if (state->mode == BAD) break;
/* build code tables */
/* check for end-of-block code (better have one) */
if (state->lens[256] == 0) {
strm->msg = (char *)"invalid code -- missing end-of-block";
state->mode = BAD;
break;
}
/* build code tables -- note: do not change the lenbits or distbits
values here (9 and 6) without reading the comments in inftrees.h
concerning the ENOUGH constants, which depend on those values */
state->next = state->codes;
state->lencode = (code const FAR *)(state->next);
state->lenbits = 9;
@ -947,14 +997,20 @@ int flush;
break;
}
Tracev((stderr, "inflate: codes ok\n"));
state->mode = LEN_;
if (flush == Z_TREES) goto inf_leave;
case LEN_:
state->mode = LEN;
case LEN:
if (have >= 6 && left >= 258) {
RESTORE();
inflate_fast(strm, out);
LOAD();
if (state->mode == TYPE)
state->back = -1;
break;
}
state->back = 0;
for (;;) {
here = state->lencode[BITS(state->lenbits)];
if ((unsigned)(here.bits) <= bits) break;
@ -969,8 +1025,10 @@ int flush;
PULLBYTE();
}
DROPBITS(last.bits);
state->back += last.bits;
}
DROPBITS(here.bits);
state->back += here.bits;
state->length = (unsigned)here.val;
if ((int)(here.op) == 0) {
Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
@ -981,6 +1039,7 @@ int flush;
}
if (here.op & 32) {
Tracevv((stderr, "inflate: end of block\n"));
state->back = -1;
state->mode = TYPE;
break;
}
@ -996,8 +1055,10 @@ int flush;
NEEDBITS(state->extra);
state->length += BITS(state->extra);
DROPBITS(state->extra);
state->back += state->extra;
}
Tracevv((stderr, "inflate: length %u\n", state->length));
state->was = state->length;
state->mode = DIST;
case DIST:
for (;;) {
@ -1014,8 +1075,10 @@ int flush;
PULLBYTE();
}
DROPBITS(last.bits);
state->back += last.bits;
}
DROPBITS(here.bits);
state->back += here.bits;
if (here.op & 64) {
strm->msg = (char *)"invalid distance code";
state->mode = BAD;
@ -1029,6 +1092,7 @@ int flush;
NEEDBITS(state->extra);
state->offset += BITS(state->extra);
DROPBITS(state->extra);
state->back += state->extra;
}
#ifdef INFLATE_STRICT
if (state->offset > state->dmax) {
@ -1066,6 +1130,9 @@ int flush;
}
if (copy > state->write) {
copy -= state->write;
/* %% problem here if copy > state->wsize -- avoid? */
/* %% or can (state->window + state->wsize) - copy */
/* %% but really should detect and reject this case */
from = state->window + (state->wsize - copy);
}
else
@ -1162,7 +1229,8 @@ int flush;
strm->adler = state->check =
UPDATE(state->check, strm->next_out - out, out);
strm->data_type = state->bits + (state->last ? 64 : 0) +
(state->mode == TYPE ? 128 : 0);
(state->mode == TYPE ? 128 : 0) +
(state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
ret = Z_BUF_ERROR;
return ret;
@ -1399,3 +1467,15 @@ int subvert;
return Z_DATA_ERROR;
#endif
}
long ZEXPORT inflateMark(strm)
z_streamp strm;
{
struct inflate_state FAR *state;
if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16;
state = (struct inflate_state FAR *)strm->state;
return ((long)(state->back) << 16) +
(state->mode == COPY ? state->length :
(state->mode == MATCH ? state->was - state->length : 0));
}

View File

@ -1,5 +1,5 @@
/* inflate.h -- internal inflate state definition
* Copyright (C) 1995-2006 Mark Adler
* Copyright (C) 1995-2009 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -32,11 +32,13 @@ typedef enum {
TYPE, /* i: waiting for type bits, including last-flag bit */
TYPEDO, /* i: same, but skip check to exit inflate on new block */
STORED, /* i: waiting for stored size (length and complement) */
COPY_, /* i/o: same as COPY below, but only first time in */
COPY, /* i/o: waiting for input or output to copy stored block */
TABLE, /* i: waiting for dynamic block table lengths */
LENLENS, /* i: waiting for code length code lengths */
CODELENS, /* i: waiting for length/lit and distance code lengths */
LEN, /* i: waiting for length/lit code */
LEN_, /* i: same as LEN below, but only first time in */
LEN, /* i: waiting for length/lit/eob code */
LENEXT, /* i: waiting for length extra bits */
DIST, /* i: waiting for distance code */
DISTEXT, /* i: waiting for distance extra bits */
@ -53,19 +55,21 @@ typedef enum {
/*
State transitions between above modes -
(most modes can go to the BAD or MEM mode -- not shown for clarity)
(most modes can go to BAD or MEM on error -- not shown for clarity)
Process header:
HEAD -> (gzip) or (zlib)
(gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME
NAME -> COMMENT -> HCRC -> TYPE
HEAD -> (gzip) or (zlib) or (raw)
(gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->
HCRC -> TYPE
(zlib) -> DICTID or TYPE
DICTID -> DICT -> TYPE
(raw) -> TYPEDO
Read deflate blocks:
TYPE -> STORED or TABLE or LEN or CHECK
STORED -> COPY -> TYPE
TABLE -> LENLENS -> CODELENS -> LEN
Read deflate codes:
TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK
STORED -> COPY_ -> COPY -> TYPE
TABLE -> LENLENS -> CODELENS -> LEN_
LEN_ -> LEN
Read deflate codes in fixed or dynamic block:
LEN -> LENEXT or LIT or TYPE
LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
LIT -> LEN
@ -113,4 +117,6 @@ struct inflate_state {
unsigned short work[288]; /* work area for code table building */
code codes[ENOUGH]; /* space for code tables */
int sane; /* if false, allow invalid distance too far */
int back; /* bits back of last unprocessed length/lit */
unsigned was; /* initial length of match */
};

View File

@ -1,5 +1,5 @@
/* inftrees.c -- generate Huffman trees for efficient decoding
* Copyright (C) 1995-2006 Mark Adler
* Copyright (C) 1995-2009 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.3.3 Copyright 1995-2006 Mark Adler ";
" inflate 1.2.3.4 Copyright 1995-2008 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, 201, 203};
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 200};
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,
@ -123,7 +123,7 @@ unsigned short FAR *work;
*bits = 1;
return 0; /* no symbols, but wait for decoding to report error */
}
for (min = 1; min <= MAXBITS; min++)
for (min = 1; min < max; min++)
if (count[min] != 0) break;
if (root < min) root = min;
@ -166,11 +166,10 @@ unsigned short FAR *work;
entered in the tables.
used keeps track of how many table entries have been allocated from the
provided *table space. It is checked when a LENS table is being made
against the space in *table, ENOUGH, minus the maximum space needed by
the worst case distance code, MAXD. This should never happen, but the
sufficiency of ENOUGH has not been proven exhaustively, hence the check.
This assumes that when type == LENS, bits == 9.
provided *table space. It is checked for LENS and DIST tables against
the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
the initial root table size constants. See the comments in inftrees.h
for more information.
sym increments through all symbols, and the loop terminates when
all codes of length max, i.e. all codes, have been processed. This
@ -209,7 +208,8 @@ unsigned short FAR *work;
mask = used - 1; /* mask for comparing low */
/* check available table space */
if (type == LENS && used >= ENOUGH - MAXD)
if ((type == LENS && used >= ENOUGH_LENS) ||
(type == DISTS && used >= ENOUGH_DISTS))
return 1;
/* process all codes and make table entries */
@ -277,7 +277,8 @@ unsigned short FAR *work;
/* check for enough space */
used += 1U << curr;
if (type == LENS && used >= ENOUGH - MAXD)
if ((type == LENS && used >= ENOUGH_LENS) ||
(type == DISTS && used >= ENOUGH_DISTS))
return 1;
/* point entry in root table to sub-table */

View File

@ -35,15 +35,22 @@ typedef struct {
01000000 - invalid code
*/
/* Maximum size of dynamic tree. The maximum found in a long but non-
exhaustive search was 1444 code structures (852 for length/literals
and 592 for distances, the latter actually the result of an
exhaustive search). The true maximum is not known, but the value
below is more than safe. */
#define ENOUGH 2048
#define MAXD 592
/* Maximum size of the dynamic table. The maximum number of code structures is
1444, which is the sum of 852 for literal/length codes and 592 for distance
codes. These values were found by exhaustive searches using the program
examples/enough.c found in the zlib distribtution. The arguments to that
program are the number of symbols, the initial root table size, and the
maximum bit length of a code. "enough 286 9 15" for literal/length codes
returns returns 852, and "enough 30 6 15" for distance codes returns 592.
The initial root table size (9 or 6) is found in the fifth argument of the
inflate_table() calls in inflate.c and infback.c. If the root table size is
changed, then these maximum sizes would be need to be recalculated and
updated. */
#define ENOUGH_LENS 852
#define ENOUGH_DISTS 592
#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)
/* Type of code to build for inftable() */
/* Type of code to build for inflate_table() */
typedef enum {
CODES,
LENS,

View File

@ -10,6 +10,7 @@ $!
$!------------------------------------------------------------------------------
$! Version history
$! 0.01 20060120 First version to receive a number
$! 0.02 20061008 Adapt to new Makefile.in
$!
$ on error then goto err_exit
$!
@ -353,7 +354,7 @@ $!
$CREA_OLIST:
$ open/read min makefile.in
$ open/write mod modules.opt
$ src_check = "OBJS ="
$ src_check = "OBJC ="
$MRLOOP:
$ read/end=mrdone min rec
$ if (f$extract(0,6,rec) .nes. src_check) then goto mrloop

View File

@ -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.3.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.3.3"/>
<QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.2.3.3"/>
<QPG:Add file="../libz.so.1.2.3.3" install="/opt/lib/" component="slib"/>
<QPG:Add file="../libz.so.1.2.3.4" install="/opt/lib/" user="root:bin" permission="644"/>
<QPG:Add file="libz.so" install="/opt/lib/" component="dev" filetype="symlink" linkto="libz.so.1.2.3.4"/>
<QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.2.3.4"/>
<QPG:Add file="../libz.so.1.2.3.4" install="/opt/lib/" component="slib"/>
</QPG:Files>
<QPG:PackageFilter>
@ -63,7 +63,7 @@
</QPM:ProductDescription>
<QPM:ReleaseDescription>
<QPM:ReleaseVersion>1.2.3.3</QPM:ReleaseVersion>
<QPM:ReleaseVersion>1.2.3.4</QPM:ReleaseVersion>
<QPM:ReleaseUrgency>Medium</QPM:ReleaseUrgency>
<QPM:ReleaseStability>Stable</QPM:ReleaseStability>
<QPM:ReleaseNoteMinor></QPM:ReleaseNoteMinor>

10
trees.c
View File

@ -1,5 +1,5 @@
/* trees.c -- output deflated data using Huffman coding
* Copyright (C) 1995-2006 Jean-loup Gailly
* Copyright (C) 1995-2009 Jean-loup Gailly
* detect_data_type() function provided freely by Cosmin Truta, 2006
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -204,12 +204,12 @@ local void send_bits(s, value, length)
* unused bits in value.
*/
if (s->bi_valid > (int)Buf_size - length) {
s->bi_buf |= (value << s->bi_valid);
s->bi_buf |= (ush)value << s->bi_valid;
put_short(s, s->bi_buf);
s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
s->bi_valid += length - Buf_size;
} else {
s->bi_buf |= value << s->bi_valid;
s->bi_buf |= (ush)value << s->bi_valid;
s->bi_valid += length;
}
}
@ -219,12 +219,12 @@ local void send_bits(s, value, length)
{ int len = length;\
if (s->bi_valid > (int)Buf_size - len) {\
int val = value;\
s->bi_buf |= (val << s->bi_valid);\
s->bi_buf |= (ush)val << s->bi_valid;\
put_short(s, s->bi_buf);\
s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
s->bi_valid += len - Buf_size;\
} else {\
s->bi_buf |= (value) << s->bi_valid;\
s->bi_buf |= (ush)(value) << s->bi_valid;\
s->bi_valid += len;\
}\
}

View File

@ -13,12 +13,18 @@ EXPORTS
deflateCopy
deflateReset
deflateParams
deflateTune
deflateBound
deflatePrime
deflateSetHeader
inflateSetDictionary
inflateSync
inflateCopy
inflateReset
inflateReset2
inflatePrime
inflateMark
inflateGetHeader
inflateBack
inflateBackEnd
zlibCompileFlags
@ -49,8 +55,8 @@ EXPORTS
gzclearerr
; checksum functions
adler32
adler32_combine
crc32
adler32_combine
crc32_combine
; various hacks, don't look :)
deflateInit_
@ -58,6 +64,12 @@ EXPORTS
inflateInit_
inflateInit2_
inflateBackInit_
gzopen64
gzseek64
gztell64
adler32_combine64
crc32_combine64
zError
inflateSyncPoint
get_crc_table
zError
inflateUndermine

View File

@ -1,5 +1,5 @@
/* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995-2006 Jean-loup Gailly.
* Copyright (C) 1995-2007 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -353,6 +353,10 @@ typedef uLong FAR uLongf;
#include "zlibdefs.h" /* created by configure */
#ifdef _LARGEFILE64_SOURCE
# include <sys/types.h>
#endif
#ifndef SEEK_SET
# define SEEK_SET 0 /* Seek from beginning of file. */
# define SEEK_CUR 1 /* Seek from current position. */

4
zlib.3
View File

@ -1,4 +1,4 @@
.TH ZLIB 3 "2 October 2006"
.TH ZLIB 3 "21 December 2009"
.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.3.3
Version 1.2.3.4
Copyright (C) 1995-2006 Jean-loup Gailly (jloup@gzip.org)
and Mark Adler (madler@alumni.caltech.edu).
.LP

169
zlib.h
View File

@ -1,7 +1,7 @@
/* zlib.h -- interface of the 'zlib' general purpose compression library
version 1.2.3.3, October 2nd, 2006
version 1.2.3.4, December 21st, 2009
Copyright (C) 1995-2006 Jean-loup Gailly and Mark Adler
Copyright (C) 1995-2009 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.3.3"
#define ZLIB_VERNUM 0x1233
#define ZLIB_VERSION "1.2.3.4"
#define ZLIB_VERNUM 0x1234
#define ZLIB_VER_MAJOR 1
#define ZLIB_VER_MINOR 2
#define ZLIB_VER_REVISION 3
@ -163,11 +163,12 @@ typedef gz_header FAR *gz_headerp;
/* constants */
#define Z_NO_FLUSH 0
#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
#define Z_PARTIAL_FLUSH 1
#define Z_SYNC_FLUSH 2
#define Z_FULL_FLUSH 3
#define Z_FINISH 4
#define Z_BLOCK 5
#define Z_TREES 6
/* Allowed flush values; see deflate() and inflate() below for details */
#define Z_OK 0
@ -273,7 +274,7 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
output buffer because there might be more output pending.
Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
decide how much data to accumualte before producing output, in order to
decide how much data to accumulate before producing output, in order to
maximize compression.
If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
@ -281,7 +282,26 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
that the decompressor can get all input data available so far. (In particular
avail_in is zero after the call if enough output space has been provided
before the call.) Flushing may degrade compression for some compression
algorithms and so it should be used only when necessary.
algorithms and so it should be used only when necessary. This completes the
current deflate block and follows it with an empty stored block that is three
bits plus filler bits to the next byte, followed by four bytes (00 00 ff ff).
If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the
output buffer, but the output is not aligned to a byte boundary. All of the
input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.
This completes the current deflate block and follows it with an empty fixed
codes block that is 10 bits long. This assures that enough bytes are output
in order for the decompressor to finish the block before the empty fixed code
block.
If flush is set to Z_BLOCK, a deflate block is completed and emitted, as
for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to
seven bits of the current block are held to be written as the next byte after
the next deflate block is completed. In this case, the decompressor may not
be provided enough bits at this point in order to complete decompression of
the data provided so far to the compressor. It may need to wait for the next
block to be emitted. This is for advanced applications that need to control
the emission of deflate blocks.
If flush is set to Z_FULL_FLUSH, all output is flushed as with
Z_SYNC_FLUSH, and the compression state is reset so that decompression can
@ -321,7 +341,7 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
processed or more output produced), Z_STREAM_END if all input has been
consumed and all output has been produced (only when flush is set to
Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible
(for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not
fatal, and deflate() can be called again with more input and more output
space to continue compressing.
@ -396,8 +416,8 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
must be called again after making room in the output buffer because there
might be more output pending.
The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH,
Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much
The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,
Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much
output as possible to the output buffer. Z_BLOCK requests that inflate() stop
if and when it gets to the next deflate block boundary. When decoding the
zlib or gzip format, this will cause inflate() to return immediately after
@ -415,7 +435,16 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
uncompressed data from that block has been written to strm->next_out. The
number of unused bits may in general be greater than seven, except when
bit 7 of data_type is set, in which case the number of unused bits will be
less than eight.
less than eight. data_type is set as noted here every time inflate()
returns for all flush options, and so can be used to determine the amount
of currently consumed input in bits.
The Z_TREES option behaves as Z_BLOCK does, but it also returns when the
end of each deflate block header is reached, before any actual data in that
block is decoded. This allows the caller to determine the length of the
deflate block header for later use in random access within a deflate block.
256 is added to the value of strm->data_type when inflate() returns
immediately after reaching the end of the deflate block header.
inflate() should normally be called until it returns Z_STREAM_END or an
error. However if all decompression is to be performed in a single step
@ -432,7 +461,7 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
possible to the output buffer, and always uses the faster approach on the
first call. So the only effect of the flush parameter in this implementation
is on the return value of inflate(), as noted below, or when it returns early
because Z_BLOCK is used.
because Z_BLOCK or Z_TREES is used.
If a preset dictionary is needed after this call (see inflateSetDictionary
below), inflate sets strm->adler to the adler32 checksum of the dictionary
@ -443,12 +472,12 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
checksum is equal to that saved by the compressor and returns Z_STREAM_END
only if the checksum is correct.
inflate() will decompress and check either zlib-wrapped or gzip-wrapped
deflate data. The header type is detected automatically. Any information
contained in the gzip header is not retained, so applications that need that
information should instead use raw inflate, see inflateInit2() below, or
inflateBack() and perform their own processing of the gzip header and
trailer.
inflate() can decompress and check either zlib-wrapped or gzip-wrapped
deflate data. The header type is detected automatically, if requested when
initializing with inflateInit2(). Any information contained in the gzip
header is not retained, so applications that need that information should
instead use raw inflate, see inflateInit2() below, or inflateBack() and
perform their own processing of the gzip header and trailer.
inflate() returns Z_OK if some progress has been made (more input processed
or more output produced), Z_STREAM_END if the end of the compressed data has
@ -456,7 +485,7 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
corrupted (input stream not conforming to the zlib format or incorrect check
value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory,
next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory,
Z_BUF_ERROR if no progress is possible or if there was not enough room in the
output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and
inflate() can be called again with more input and more output space to
@ -529,12 +558,12 @@ ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
random distribution. In this case, the compression algorithm is tuned to
compress them better. The effect of Z_FILTERED is to force more Huffman
coding and less string matching; it is somewhat intermediate between
Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as
Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy
parameter only affects the compression ratio but not the correctness of the
compressed output even if it is not set appropriately. Z_FIXED prevents the
use of dynamic Huffman codes, allowing for a simpler decoder for special
applications.
Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as
fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The
strategy parameter only affects the compression ratio but not the
correctness of the compressed output even if it is not set appropriately.
Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler
decoder for special applications.
deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
@ -561,11 +590,11 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
Depending on the size of the compression data structures selected by
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. In addition, the
current implementation of deflate will use at most the window size minus
262 bytes of the provided dictionary.
discarded, for example if the dictionary is larger than the window size
provided in deflateInit or deflateInit2. Thus the strings most likely to be
useful should be 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
@ -575,7 +604,7 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
adler32 value is not computed and strm->adler is not set.
deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
parameter is invalid (such as NULL dictionary) or the stream state is
parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
inconsistent (for example if deflate has already been called for this stream
or if the compression method is bsort). deflateSetDictionary does not
perform any compression: this will be done by deflate().
@ -595,7 +624,7 @@ ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
(such as zalloc being NULL). msg is left unchanged in both source and
(such as zalloc being Z_NULL). msg is left unchanged in both source and
destination.
*/
@ -607,7 +636,7 @@ ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
that may have been set by deflateInit2.
deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
stream state was inconsistent (such as zalloc or state being NULL).
stream state was inconsistent (such as zalloc or state being Z_NULL).
*/
ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
@ -760,7 +789,7 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
dictionary that was used for compression is provided.
inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
parameter is invalid (such as NULL dictionary) or the stream state is
parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
expected one (incorrect adler32 value). inflateSetDictionary does not
perform any decompression: this will be done by subsequent calls of
@ -794,7 +823,7 @@ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
(such as zalloc being NULL). msg is left unchanged in both source and
(such as zalloc being Z_NULL). msg is left unchanged in both source and
destination.
*/
@ -805,7 +834,19 @@ ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
The stream will keep attributes that may have been set by inflateInit2.
inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
stream state was inconsistent (such as zalloc or state being NULL).
stream state was inconsistent (such as zalloc or state being Z_NULL).
*/
ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,
int windowBits));
/*
This function is the same as inflateReset, but it also permits changing
the wrap and window size requests. The windowBits parameter is
interpreted the same as it is for inflateInit2.
inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source
stream state was inconsistent (such as zalloc or state being Z_NULL), or if
the windowBits parameter is invalid.
*/
ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
@ -820,10 +861,43 @@ ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
inflateReset(). bits must be less than or equal to 16, and that many of the
least significant bits of value will be inserted in the input.
If bits is negative, then the input stream bit buffer is emptied. Then
inflatePrime() can be called again to put bits in the buffer. This is used
to clear out bits leftover after feeding inflate a block description prior
to feeding inflate codes.
inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
stream state was inconsistent.
*/
ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));
/*
This function returns two values, one in the lower 16 bits of the return
value, and the other in the remaining upper bits, obtained by shifting the
return value down 16 bits. If the upper value is -1 and the lower value is
zero, then inflate() is currently decoding information outside of a block.
If the upper value is -1 and the lower value is non-zero, then inflate is in
the middle of a stored block, with the lower value equaling the number of
bytes from the input remaining to copy. If the upper value is not -1, then
it is the number of bits back from the current bit position in the input of
the code (literal or length/distance pair) currently being processed. In
that case the lower value is the number of bytes already emitted for that
code.
A code is being processed if inflate is waiting for more input to complete
decoding of the code, or if it has completed decoding but is waiting for
more output space to write the literal or match data.
inflateMark() is used to mark locations in the input data for random
access, which may be at bit positions, and to note those cases where the
output of a code may span boundaries of random access blocks. The current
location in the input stream can be determined from avail_in and data_type
as noted in the description for the Z_BLOCK flush parameter for inflate.
inflateMark returns the value noted above or -1 << 16 if the provided
source stream state was inconsistent.
*/
ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
gz_headerp head));
/*
@ -833,9 +907,9 @@ ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
As inflate() processes the gzip stream, head->done is zero until the header
is completed, at which time head->done is set to one. If a zlib stream is
being decoded, then head->done is set to -1 to indicate that there will be
no gzip header information forthcoming. Note that Z_BLOCK can be used to
force inflate() to return immediately after header processing is complete
and before any actual data is decompressed.
no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be
used to force inflate() to return immediately after header processing is
complete and before any actual data is decompressed.
The text, time, xflags, and os fields are filled in with the gzip header
contents. hcrc is set to true if there is a header CRC. (The header CRC
@ -952,7 +1026,7 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
nature of the error), or Z_STREAM_ERROR if the stream was not properly
initialized. In the case of Z_BUF_ERROR, an input or output error can be
distinguished using strm->next_in which will be Z_NULL only if in() returned
an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to
an error. If strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to
out() returning non-zero. (in() will always be called before out(), so
strm->next_in is assured to be defined if out() returns non-zero.) Note
that inflateBack() cannot return Z_OK.
@ -1065,7 +1139,7 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
entire uncompressed data. (The size of the uncompressed data must have
been saved previously by the compressor and transmitted to the decompressor
by some mechanism outside the scope of this compression library.)
Upon exit, destLen is the actual size of the compressed buffer.
Upon exit, destLen is the actual size of the uncompressed buffer.
This function can be used to decompress a whole file at once if the
input file is mmap'ed.
@ -1279,7 +1353,7 @@ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
/*
Update a running Adler-32 checksum with the bytes buf[0..len-1] and
return the updated checksum. If buf is NULL, this function returns
return the updated checksum. If buf is Z_NULL, this function returns
the required initial value for the checksum.
An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
much faster. Usage example:
@ -1305,7 +1379,7 @@ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
/*
Update a running CRC-32 with the bytes buf[0..len-1] and return the
updated CRC-32. If buf is NULL, this function returns the required initial
updated CRC-32. If buf is Z_NULL, this function returns the required initial
value for the for the crc. Pre- and post-conditioning (one's complement) is
performed within this function so it shouldn't be done by the application.
Usage example:
@ -1369,12 +1443,19 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, off64_t));
#endif
#if _FILE_OFFSET_BITS == 64
#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS == 64
# define gzopen gzopen64
# define gzseek gzseek64
# define gztell gztell64
# define adler32_combine adler32_combine64
# define crc32_combine crc32_combine64
# ifndef _LARGEFILE64_SOURCE
ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
ZEXTERN off_t ZEXPORT gzseek64 OF((gzFile, off_t, int));
ZEXTERN off_t ZEXPORT gztell64 OF((gzFile));
ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, off_t));
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, off_t));
# endif
#else
ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int));

View File

@ -42,3 +42,12 @@ ZLIB_1.2.2.3 {
ZLIB_1.2.2.4 {
inflatePrime;
} ZLIB_1.2.2.3;
ZLIB_1.2.3.3 {
inflateUndermine;
} ZLIB_1.2.2.4;
ZLIB_1.2.3.4 {
inflateReset2;
inflateMark;
} ZLIB_1.2.3.3;

152
zlib2ansi Executable file
View File

@ -0,0 +1,152 @@
#!/usr/bin/perl
# Transform K&R C function definitions into ANSI equivalent.
#
# Author: Paul Marquess
# Version: 1.0
# Date: 3 October 2006
# TODO
#
# Asumes no function pointer parameters. unless they are typedefed.
# Assumes no literal strings that look like function definitions
# Assumes functions start at the beginning of a line
use strict;
use warnings;
local $/;
$_ = <>;
my $sp = qr{ \s* (?: /\* .*? \*/ )? \s* }x; # assume no nested comments
my $d1 = qr{ $sp (?: [\w\*\s]+ $sp)* $sp \w+ $sp [\[\]\s]* $sp }x ;
my $decl = qr{ $sp (?: \w+ $sp )+ $d1 }xo ;
my $dList = qr{ $sp $decl (?: $sp , $d1 )* $sp ; $sp }xo ;
while (s/^
( # Start $1
( # Start $2
.*? # Minimal eat content
( ^ \w [\w\s\*]+ ) # $3 -- function name
\s* # optional whitespace
) # $2 - Matched up to before parameter list
\( \s* # Literal "(" + optional whitespace
( [^\)]+ ) # $4 - one or more anythings except ")"
\s* \) # optional whitespace surrounding a Literal ")"
( (?: $dList )+ ) # $5
$sp ^ { # literal "{" at start of line
) # Remember to $1
//xsom
)
{
my $all = $1 ;
my $prefix = $2;
my $param_list = $4 ;
my $params = $5;
StripComments($params);
StripComments($param_list);
$param_list =~ s/^\s+//;
$param_list =~ s/\s+$//;
my $i = 0 ;
my %pList = map { $_ => $i++ }
split /\s*,\s*/, $param_list;
my $pMatch = '(\b' . join('|', keys %pList) . '\b)\W*$' ;
my @params = split /\s*;\s*/, $params;
my @outParams = ();
foreach my $p (@params)
{
if ($p =~ /,/)
{
my @bits = split /\s*,\s*/, $p;
my $first = shift @bits;
$first =~ s/^\s*//;
push @outParams, $first;
$first =~ /^(\w+\s*)/;
my $type = $1 ;
push @outParams, map { $type . $_ } @bits;
}
else
{
$p =~ s/^\s+//;
push @outParams, $p;
}
}
my %tmp = map { /$pMatch/; $_ => $pList{$1} }
@outParams ;
@outParams = map { " $_" }
sort { $tmp{$a} <=> $tmp{$b} }
@outParams ;
print $prefix ;
print "(\n" . join(",\n", @outParams) . ")\n";
print "{" ;
}
# Output any trailing code.
print ;
exit 0;
sub StripComments
{
no warnings;
# Strip C & C++ coments
# From the perlfaq
$_[0] =~
s{
/\* ## Start of /* ... */ comment
[^*]*\*+ ## Non-* followed by 1-or-more *'s
(
[^/*][^*]*\*+
)* ## 0-or-more things which don't start with /
## but do end with '*'
/ ## End of /* ... */ comment
| ## OR C++ Comment
// ## Start of C++ comment //
[^\n]* ## followed by 0-or-more non end of line characters
| ## OR various things which aren't comments:
(
" ## Start of " ... " string
(
\\. ## Escaped char
| ## OR
[^"\\] ## Non "\
)*
" ## End of " ... " string
| ## OR
' ## Start of ' ... ' string
(
\\. ## Escaped char
| ## OR
[^'\\] ## Non '\
)*
' ## End of ' ... ' string
| ## OR
. ## Anything other char
[^/"'\\]* ## Chars which doesn't start a comment, string or escape
)
}{$2}gxs;
}

View File

@ -165,6 +165,12 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
#pragma warn -8004
#pragma warn -8008
#pragma warn -8066
#endif
#ifdef _LARGEFILE64_SOURCE
# define z_off64_t off64_t
#else
# define z_off64_t z_off_t
#endif
/* common defaults */