mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-09-21 20:44:09 +08:00
This commit was generated by cvs2svn to compensate for changes in r12470,
which included commits to RCS files with non-trunk default branches.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
+339
@@ -0,0 +1,339 @@
|
||||
|
||||
Frequently Asked Questions about zlib
|
||||
|
||||
|
||||
If your question is not there, please check the zlib home page
|
||||
http://www.zlib.org which may have more recent information.
|
||||
The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html
|
||||
|
||||
|
||||
1. Is zlib Y2K-compliant?
|
||||
|
||||
Yes. zlib doesn't handle dates.
|
||||
|
||||
2. Where can I get a Windows DLL version?
|
||||
|
||||
The zlib sources can be compiled without change to produce a DLL.
|
||||
See the file win32/DLL_FAQ.txt in the zlib distribution.
|
||||
Pointers to the precompiled DLL are found in the zlib web site at
|
||||
http://www.zlib.org.
|
||||
|
||||
3. Where can I get a Visual Basic interface to zlib?
|
||||
|
||||
See
|
||||
* http://www.dogma.net/markn/articles/zlibtool/zlibtool.htm
|
||||
* contrib/visual-basic.txt in the zlib distribution
|
||||
* win32/DLL_FAQ.txt in the zlib distribution
|
||||
|
||||
4. compress() returns Z_BUF_ERROR.
|
||||
|
||||
Make sure that before the call of compress, the length of the compressed
|
||||
buffer is equal to the total size of the compressed buffer and not
|
||||
zero. For Visual Basic, check that this parameter is passed by reference
|
||||
("as any"), not by value ("as long").
|
||||
|
||||
5. deflate() or inflate() returns Z_BUF_ERROR.
|
||||
|
||||
Before making the call, make sure that avail_in and avail_out are not
|
||||
zero. When setting the parameter flush equal to Z_FINISH, also make sure
|
||||
that avail_out is big enough to allow processing all pending input.
|
||||
Note that a Z_BUF_ERROR is not fatal--another call to deflate() or
|
||||
inflate() can be made with more input or output space. A Z_BUF_ERROR
|
||||
may in fact be unavoidable depending on how the functions are used, since
|
||||
it is not possible to tell whether or not there is more output pending
|
||||
when strm.avail_out returns with zero.
|
||||
|
||||
6. Where's the zlib documentation (man pages, etc.)?
|
||||
|
||||
It's in zlib.h for the moment, and Francis S. Lin has converted it to a
|
||||
web page zlib.html. Volunteers to transform this to Unix-style man pages,
|
||||
please contact us (zlib@gzip.org). Examples of zlib usage are in the files
|
||||
example.c and minigzip.c.
|
||||
|
||||
7. Why don't you use GNU autoconf or libtool or ...?
|
||||
|
||||
Because we would like to keep zlib as a very small and simple
|
||||
package. zlib is rather portable and doesn't need much configuration.
|
||||
|
||||
8. I found a bug in zlib.
|
||||
|
||||
Most of the time, such problems are due to an incorrect usage of
|
||||
zlib. Please try to reproduce the problem with a small program and send
|
||||
the corresponding source to us at zlib@gzip.org . Do not send
|
||||
multi-megabyte data files without prior agreement.
|
||||
|
||||
9. Why do I get "undefined reference to gzputc"?
|
||||
|
||||
If "make test" produces something like
|
||||
|
||||
example.o(.text+0x154): undefined reference to `gzputc'
|
||||
|
||||
check that you don't have old files libz.* in /usr/lib, /usr/local/lib or
|
||||
/usr/X11R6/lib. Remove any old versions, then do "make install".
|
||||
|
||||
10. I need a Delphi interface to zlib.
|
||||
|
||||
See the contrib/delphi directory in the zlib distribution.
|
||||
|
||||
11. Can zlib handle .zip archives?
|
||||
|
||||
Not by itself, no. See the directory contrib/minizip in the zlib
|
||||
distribution.
|
||||
|
||||
12. Can zlib handle .Z files?
|
||||
|
||||
No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt
|
||||
the code of uncompress on your own.
|
||||
|
||||
13. How can I make a Unix shared library?
|
||||
|
||||
make clean
|
||||
./configure -s
|
||||
make
|
||||
|
||||
14. How do I install a shared zlib library on Unix?
|
||||
|
||||
After the above, then:
|
||||
|
||||
make install
|
||||
|
||||
However, many flavors of Unix come with a shared zlib already installed.
|
||||
Before going to the trouble of compiling a shared version of zlib and
|
||||
trying to install it, you may want to check if it's already there! If you
|
||||
can #include <zlib.h>, it's there. The -lz option will probably link to it.
|
||||
|
||||
15. I have a question about OttoPDF.
|
||||
|
||||
We are not the authors of OttoPDF. The real author is on the OttoPDF web
|
||||
site: Joel Hainley, jhainley@myndkryme.com.
|
||||
|
||||
16. Can zlib decode Flate data in an Adobe PDF file?
|
||||
|
||||
Yes. See http://www.fastio.com/ (ClibPDF), or http://www.pdflib.com/ .
|
||||
To modify PDF forms, see http://sourceforge.net/projects/acroformtool/ .
|
||||
|
||||
17. Why am I getting this "register_frame_info not found" error on Solaris?
|
||||
|
||||
After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib
|
||||
generates an error such as:
|
||||
|
||||
ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so:
|
||||
symbol __register_frame_info: referenced symbol not found
|
||||
|
||||
The symbol __register_frame_info is not part of zlib, it is generated by
|
||||
the C compiler (cc or gcc). You must recompile applications using zlib
|
||||
which have this problem. This problem is specific to Solaris. See
|
||||
http://www.sunfreeware.com for Solaris versions of zlib and applications
|
||||
using zlib.
|
||||
|
||||
18. Why does gzip give an error on a file I make with compress/deflate?
|
||||
|
||||
The compress and deflate functions produce data in the zlib format, which
|
||||
is different and incompatible with the gzip format. The gz* functions in
|
||||
zlib on the other hand use the gzip format. Both the zlib and gzip
|
||||
formats use the same compressed data format internally, but have different
|
||||
headers and trailers around the compressed data.
|
||||
|
||||
19. Ok, so why are there two different formats?
|
||||
|
||||
The gzip format was designed to retain the directory information about
|
||||
a single file, such as the name and last modification date. The zlib
|
||||
format on the other hand was designed for in-memory and communication
|
||||
channel applications, and has a much more compact header and trailer and
|
||||
uses a faster integrity check than gzip.
|
||||
|
||||
20. Well that's nice, but how do I make a gzip file in memory?
|
||||
|
||||
You can request that deflate write the gzip format instead of the zlib
|
||||
format using deflateInit2(). You can also request that inflate decode
|
||||
the gzip format using inflateInit2(). Read zlib.h for more details.
|
||||
|
||||
21. Is zlib thread-safe?
|
||||
|
||||
Yes. However any library routines that zlib uses and any application-
|
||||
provided memory allocation routines must also be thread-safe. zlib's gz*
|
||||
functions use stdio library routines, and most of zlib's functions use the
|
||||
library memory allocation routines by default. zlib's Init functions allow
|
||||
for the application to provide custom memory allocation routines.
|
||||
|
||||
Of course, you should only operate on any given zlib or gzip stream from a
|
||||
single thread at a time.
|
||||
|
||||
22. Can I use zlib in my commercial application?
|
||||
|
||||
Yes. Please read the license in zlib.h.
|
||||
|
||||
23. Is zlib under the GNU license?
|
||||
|
||||
No. Please read the license in zlib.h.
|
||||
|
||||
24. The license says that altered source versions must be "plainly marked". So
|
||||
what exactly do I need to do to meet that requirement?
|
||||
|
||||
You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In
|
||||
particular, the final version number needs to be changed to "f", and an
|
||||
identification string should be appended to ZLIB_VERSION. Version numbers
|
||||
x.x.x.f are reserved for modifications to zlib by others than the zlib
|
||||
maintainers. For example, if the version of the base zlib you are altering
|
||||
is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and
|
||||
ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also
|
||||
update the version strings in deflate.c and inftrees.c.
|
||||
|
||||
For altered source distributions, you should also note the origin and
|
||||
nature of the changes in zlib.h, as well as in ChangeLog and README, along
|
||||
with the dates of the alterations. The origin should include at least your
|
||||
name (or your company's name), and an email address to contact for help or
|
||||
issues with the library.
|
||||
|
||||
Note that distributing a compiled zlib library along with zlib.h and
|
||||
zconf.h is also a source distribution, and so you should change
|
||||
ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes
|
||||
in zlib.h as you would for a full source distribution.
|
||||
|
||||
25. Will zlib work on a big-endian or little-endian architecture, and can I
|
||||
exchange compressed data between them?
|
||||
|
||||
Yes and yes.
|
||||
|
||||
26. Will zlib work on a 64-bit machine?
|
||||
|
||||
It should. It has been tested on 64-bit machines, and has no dependence
|
||||
on any data types being limited to 32-bits in length. If you have any
|
||||
difficulties, please provide a complete problem report to zlib@gzip.org
|
||||
|
||||
27. Will zlib decompress data from the PKWare Data Compression Library?
|
||||
|
||||
No. The PKWare DCL uses a completely different compressed data format
|
||||
than does PKZIP and zlib. However, you can look in zlib's contrib/blast
|
||||
directory for a possible solution to your problem.
|
||||
|
||||
28. Can I access data randomly in a compressed stream?
|
||||
|
||||
No, not without some preparation. If when compressing you periodically
|
||||
use Z_FULL_FLUSH, carefully write all the pending data at those points,
|
||||
and keep an index of those locations, then you can start decompression
|
||||
at those points. You have to be careful to not use Z_FULL_FLUSH too
|
||||
often, since it can significantly degrade compression.
|
||||
|
||||
29. Does zlib work on MVS, OS/390, CICS, etc.?
|
||||
|
||||
We don't know for sure. We have heard occasional reports of success on
|
||||
these systems. If you do use it on one of these, please provide us with
|
||||
a report, instructions, and patches that we can reference when we get
|
||||
these questions. Thanks.
|
||||
|
||||
30. Is there some simpler, easier to read version of inflate I can look at
|
||||
to understand the deflate format?
|
||||
|
||||
First off, you should read RFC 1951. Second, yes. Look in zlib's
|
||||
contrib/puff directory.
|
||||
|
||||
31. Does zlib infringe on any patents?
|
||||
|
||||
As far as we know, no. In fact, that was originally the whole point behind
|
||||
zlib. Look here for some more information:
|
||||
|
||||
http://www.gzip.org/#faq11
|
||||
|
||||
32. Can zlib work with greater than 4 GB of data?
|
||||
|
||||
Yes. inflate() and deflate() will process any amount of data correctly.
|
||||
Each call of inflate() or deflate() is limited to input and output chunks
|
||||
of the maximum value that can be stored in the compiler's "unsigned int"
|
||||
type, but there is no limit to the number of chunks. Note however that the
|
||||
strm.total_in and strm_total_out counters may be limited to 4 GB. These
|
||||
counters are provided as a convenience and are not used internally by
|
||||
inflate() or deflate(). The application can easily set up its own counters
|
||||
updated after each call of inflate() or deflate() to count beyond 4 GB.
|
||||
compress() and uncompress() may be limited to 4 GB, since they operate in a
|
||||
single call. gzseek() and gztell() may be limited to 4 GB depending on how
|
||||
zlib is compiled. See the zlibCompileFlags() function in zlib.h.
|
||||
|
||||
The word "may" appears several times above since there is a 4 GB limit
|
||||
only if the compiler's "long" type is 32 bits. If the compiler's "long"
|
||||
type is 64 bits, then the limit is 16 exabytes.
|
||||
|
||||
33. Does zlib have any security vulnerabilities?
|
||||
|
||||
The only one that we are aware of is potentially in gzprintf(). If zlib
|
||||
is compiled to use sprintf() or vsprintf(), then there is no protection
|
||||
against a buffer overflow of a 4K string space, other than the caller of
|
||||
gzprintf() assuring that the output will not exceed 4K. On the other
|
||||
hand, if zlib is compiled to use snprintf() or vsnprintf(), which should
|
||||
normally be the case, then there is no vulnerability. The ./configure
|
||||
script will display warnings if an insecure variation of sprintf() will
|
||||
be used by gzprintf(). Also the zlibCompileFlags() function will return
|
||||
information on what variant of sprintf() is used by gzprintf().
|
||||
|
||||
If you don't have snprintf() or vsnprintf() and would like one, you can
|
||||
find a portable implementation here:
|
||||
|
||||
http://www.ijs.si/software/snprintf/
|
||||
|
||||
Note that you should be using the most recent version of zlib. Versions
|
||||
1.1.3 and before were subject to a double-free vulnerability.
|
||||
|
||||
34. Is there a Java version of zlib?
|
||||
|
||||
Probably what you want is to use zlib in Java. zlib is already included
|
||||
as part of the Java SDK in the java.util.zip package. If you really want
|
||||
a version of zlib written in the Java language, look on the zlib home
|
||||
page for links: http://www.zlib.org/
|
||||
|
||||
35. I get this or that compiler or source-code scanner warning when I crank it
|
||||
up to maximally-pedantic. Can't you guys write proper code?
|
||||
|
||||
Many years ago, we gave up attempting to avoid warnings on every compiler
|
||||
in the universe. It just got to be a waste of time, and some compilers
|
||||
were downright silly. So now, we simply make sure that the code always
|
||||
works.
|
||||
|
||||
36. Valgrind (or some similar memory access checker) says that deflate is
|
||||
performing a conditional jump that depends on an uninitialized value.
|
||||
Isn't that a bug?
|
||||
|
||||
No. That is intentional for performance reasons, and the output of
|
||||
deflate is not affected. This only started showing up recently since
|
||||
zlib 1.2.x uses malloc() by default for allocations, whereas earlier
|
||||
versions used calloc(), which zeros out the allocated memory.
|
||||
|
||||
37. Will zlib read the (insert any ancient or arcane format here) compressed
|
||||
data format?
|
||||
|
||||
Probably not. Look in the comp.compression FAQ for pointers to various
|
||||
formats and associated software.
|
||||
|
||||
38. How can I encrypt/decrypt zip files with zlib?
|
||||
|
||||
zlib doesn't support encryption. The original PKZIP encryption is very weak
|
||||
and can be broken with freely available programs. To get strong encryption,
|
||||
use GnuPG, http://www.gnupg.org/ , which already includes zlib compression.
|
||||
For PKZIP compatible "encryption", look at http://www.info-zip.org/
|
||||
|
||||
39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
|
||||
|
||||
"gzip" is the gzip format, and "deflate" is the zlib format. They should
|
||||
probably have called the second one "zlib" instead to avoid confusion
|
||||
with the raw deflate compressed data format. While the HTTP 1.1 RFC 2616
|
||||
correctly points to the zlib specification in RFC 1950 for the "deflate"
|
||||
transfer encoding, there have been reports of servers and browsers that
|
||||
incorrectly produce or expect raw deflate data per the deflate
|
||||
specficiation in RFC 1951, most notably Microsoft. So even though the
|
||||
"deflate" transfer encoding using the zlib format would be the more
|
||||
efficient approach (and in fact exactly what the zlib format was designed
|
||||
for), using the "gzip" transfer encoding is probably more reliable due to
|
||||
an unfortunate choice of name on the part of the HTTP 1.1 authors.
|
||||
|
||||
Bottom line: use the gzip format for HTTP 1.1 encoding.
|
||||
|
||||
40. Does zlib support the new "Deflate64" format introduced by PKWare?
|
||||
|
||||
No. PKWare has apparently decided to keep that format proprietary, since
|
||||
they have not documented it as they have previous compression formats.
|
||||
In any case, the compression improvements are so modest compared to other
|
||||
more modern approaches, that it's not worth the effort to implement.
|
||||
|
||||
41. Can you please sign these lengthy legal documents and fax them back to us
|
||||
so that we can use your software in our product?
|
||||
|
||||
No. Go away. Shoo.
|
||||
@@ -0,0 +1,51 @@
|
||||
ChangeLog history of changes
|
||||
FAQ Frequently Asked Questions about zlib
|
||||
INDEX this file
|
||||
Makefile makefile for Unix (generated by configure)
|
||||
Makefile.in makefile for Unix (template for configure)
|
||||
README guess what
|
||||
algorithm.txt description of the (de)compression algorithm
|
||||
configure configure script for Unix
|
||||
zconf.in.h template for zconf.h (used by configure)
|
||||
|
||||
amiga/ makefiles for Amiga SAS C
|
||||
as400/ makefiles for IBM AS/400
|
||||
msdos/ makefiles for MSDOS
|
||||
old/ makefiles for various architectures and zlib documentation
|
||||
files that have not yet been updated for zlib 1.2.x
|
||||
projects/ projects for various Integrated Development Environments
|
||||
qnx/ makefiles for QNX
|
||||
win32/ makefiles for Windows
|
||||
|
||||
zlib public header files (must be kept):
|
||||
zconf.h
|
||||
zlib.h
|
||||
|
||||
private source files used to build the zlib library:
|
||||
adler32.c
|
||||
compress.c
|
||||
crc32.c
|
||||
crc32.h
|
||||
deflate.c
|
||||
deflate.h
|
||||
gzio.c
|
||||
infback.c
|
||||
inffast.c
|
||||
inffast.h
|
||||
inffixed.h
|
||||
inflate.c
|
||||
inflate.h
|
||||
inftrees.c
|
||||
inftrees.h
|
||||
trees.c
|
||||
trees.h
|
||||
uncompr.c
|
||||
zutil.c
|
||||
zutil.h
|
||||
|
||||
source files for sample programs:
|
||||
example.c
|
||||
minigzip.c
|
||||
|
||||
unsupported contribution by third parties
|
||||
See contrib/README.contrib
|
||||
@@ -0,0 +1,154 @@
|
||||
# Makefile for zlib
|
||||
# Copyright (C) 1995-2003 Jean-loup Gailly.
|
||||
# For conditions of distribution and use, see copyright notice in zlib.h
|
||||
|
||||
# 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
|
||||
|
||||
# To use the asm code, type:
|
||||
# cp contrib/asm?86/match.S ./match.S
|
||||
# make LOC=-DASMV OBJA=match.o
|
||||
|
||||
# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type:
|
||||
# make install
|
||||
# To install in $HOME instead of /usr/local, use:
|
||||
# make install prefix=$HOME
|
||||
|
||||
CC=cc
|
||||
|
||||
CFLAGS=-O
|
||||
#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
|
||||
#CFLAGS=-g -DDEBUG
|
||||
#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
|
||||
# -Wstrict-prototypes -Wmissing-prototypes
|
||||
|
||||
LDFLAGS=libz.a
|
||||
LDSHARED=$(CC)
|
||||
CPP=$(CC) -E
|
||||
|
||||
LIBS=libz.a
|
||||
SHAREDLIB=libz.so
|
||||
SHAREDLIBV=libz.so.1.2.2.2
|
||||
SHAREDLIBM=libz.so.1
|
||||
|
||||
AR=ar rc
|
||||
RANLIB=ranlib
|
||||
TAR=tar
|
||||
SHELL=/bin/sh
|
||||
EXE=
|
||||
|
||||
prefix = /usr/local
|
||||
exec_prefix = ${prefix}
|
||||
libdir = ${exec_prefix}/lib
|
||||
includedir = ${prefix}/include
|
||||
mandir = ${prefix}/share/man
|
||||
man3dir = ${mandir}/man3
|
||||
|
||||
OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
|
||||
zutil.o inflate.o infback.o inftrees.o inffast.o
|
||||
|
||||
OBJA =
|
||||
# to use the asm code: make OBJA=match.o
|
||||
|
||||
TEST_OBJS = example.o minigzip.o
|
||||
|
||||
all: example$(EXE) minigzip$(EXE)
|
||||
|
||||
check: test
|
||||
test: all
|
||||
@LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
|
||||
echo hello world | ./minigzip | ./minigzip -d || \
|
||||
echo ' *** minigzip test FAILED ***' ; \
|
||||
if ./example; then \
|
||||
echo ' *** zlib test OK ***'; \
|
||||
else \
|
||||
echo ' *** zlib test FAILED ***'; \
|
||||
fi
|
||||
|
||||
libz.a: $(OBJS) $(OBJA)
|
||||
$(AR) $@ $(OBJS) $(OBJA)
|
||||
-@ ($(RANLIB) $@ || true) >/dev/null 2>&1
|
||||
|
||||
match.o: match.S
|
||||
$(CPP) match.S > _match.s
|
||||
$(CC) -c _match.s
|
||||
mv _match.o match.o
|
||||
rm -f _match.s
|
||||
|
||||
$(SHAREDLIBV): $(OBJS)
|
||||
$(LDSHARED) -o $@ $(OBJS)
|
||||
rm -f $(SHAREDLIB) $(SHAREDLIBM)
|
||||
ln -s $@ $(SHAREDLIB)
|
||||
ln -s $@ $(SHAREDLIBM)
|
||||
|
||||
example$(EXE): example.o $(LIBS)
|
||||
$(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS)
|
||||
|
||||
minigzip$(EXE): minigzip.o $(LIBS)
|
||||
$(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS)
|
||||
|
||||
install: $(LIBS)
|
||||
-@if [ ! -d $(exec_prefix) ]; then mkdir -p $(exec_prefix); fi
|
||||
-@if [ ! -d $(includedir) ]; then mkdir -p $(includedir); fi
|
||||
-@if [ ! -d $(libdir) ]; then mkdir -p $(libdir); fi
|
||||
-@if [ ! -d $(man3dir) ]; then mkdir -p $(man3dir); fi
|
||||
cp zlib.h zconf.h $(includedir)
|
||||
chmod 644 $(includedir)/zlib.h $(includedir)/zconf.h
|
||||
cp $(LIBS) $(libdir)
|
||||
cd $(libdir); chmod 755 $(LIBS)
|
||||
-@(cd $(libdir); $(RANLIB) libz.a || true) >/dev/null 2>&1
|
||||
cd $(libdir); if test -f $(SHAREDLIBV); then \
|
||||
rm -f $(SHAREDLIB) $(SHAREDLIBM); \
|
||||
ln -s $(SHAREDLIBV) $(SHAREDLIB); \
|
||||
ln -s $(SHAREDLIBV) $(SHAREDLIBM); \
|
||||
(ldconfig || true) >/dev/null 2>&1; \
|
||||
fi
|
||||
cp zlib.3 $(man3dir)
|
||||
chmod 644 $(man3dir)/zlib.3
|
||||
# The ranlib in install is needed on NeXTSTEP which checks file times
|
||||
# ldconfig is for Linux
|
||||
|
||||
uninstall:
|
||||
cd $(includedir); \
|
||||
cd $(libdir); rm -f libz.a; \
|
||||
if test -f $(SHAREDLIBV); then \
|
||||
rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM); \
|
||||
fi
|
||||
cd $(man3dir); rm -f zlib.3
|
||||
|
||||
mostlyclean: clean
|
||||
clean:
|
||||
rm -f *.o *~ example$(EXE) minigzip$(EXE) \
|
||||
libz.* foo.gz so_locations \
|
||||
_match.s maketree contrib/infback9/*.o
|
||||
|
||||
maintainer-clean: distclean
|
||||
distclean: clean
|
||||
cp -p Makefile.in Makefile
|
||||
cp -p zconf.in.h zconf.h
|
||||
rm -f .DS_Store
|
||||
|
||||
tags:
|
||||
etags *.[ch]
|
||||
|
||||
depend:
|
||||
makedepend -- $(CFLAGS) -- *.[ch]
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
adler32.o: zlib.h zconf.h
|
||||
compress.o: zlib.h zconf.h
|
||||
crc32.o: crc32.h zlib.h zconf.h
|
||||
deflate.o: deflate.h zutil.h zlib.h zconf.h
|
||||
example.o: zlib.h zconf.h
|
||||
gzio.o: zutil.h zlib.h zconf.h
|
||||
inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inftrees.o: zutil.h zlib.h zconf.h inftrees.h
|
||||
minigzip.o: zlib.h zconf.h
|
||||
trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
|
||||
uncompr.o: zlib.h zconf.h
|
||||
zutil.o: zutil.h zlib.h zconf.h
|
||||
@@ -0,0 +1,154 @@
|
||||
# Makefile for zlib
|
||||
# Copyright (C) 1995-2003 Jean-loup Gailly.
|
||||
# For conditions of distribution and use, see copyright notice in zlib.h
|
||||
|
||||
# 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
|
||||
|
||||
# To use the asm code, type:
|
||||
# cp contrib/asm?86/match.S ./match.S
|
||||
# make LOC=-DASMV OBJA=match.o
|
||||
|
||||
# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type:
|
||||
# make install
|
||||
# To install in $HOME instead of /usr/local, use:
|
||||
# make install prefix=$HOME
|
||||
|
||||
CC=cc
|
||||
|
||||
CFLAGS=-O
|
||||
#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
|
||||
#CFLAGS=-g -DDEBUG
|
||||
#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
|
||||
# -Wstrict-prototypes -Wmissing-prototypes
|
||||
|
||||
LDFLAGS=libz.a
|
||||
LDSHARED=$(CC)
|
||||
CPP=$(CC) -E
|
||||
|
||||
LIBS=libz.a
|
||||
SHAREDLIB=libz.so
|
||||
SHAREDLIBV=libz.so.1.2.2.2
|
||||
SHAREDLIBM=libz.so.1
|
||||
|
||||
AR=ar rc
|
||||
RANLIB=ranlib
|
||||
TAR=tar
|
||||
SHELL=/bin/sh
|
||||
EXE=
|
||||
|
||||
prefix = /usr/local
|
||||
exec_prefix = ${prefix}
|
||||
libdir = ${exec_prefix}/lib
|
||||
includedir = ${prefix}/include
|
||||
mandir = ${prefix}/share/man
|
||||
man3dir = ${mandir}/man3
|
||||
|
||||
OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
|
||||
zutil.o inflate.o infback.o inftrees.o inffast.o
|
||||
|
||||
OBJA =
|
||||
# to use the asm code: make OBJA=match.o
|
||||
|
||||
TEST_OBJS = example.o minigzip.o
|
||||
|
||||
all: example$(EXE) minigzip$(EXE)
|
||||
|
||||
check: test
|
||||
test: all
|
||||
@LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
|
||||
echo hello world | ./minigzip | ./minigzip -d || \
|
||||
echo ' *** minigzip test FAILED ***' ; \
|
||||
if ./example; then \
|
||||
echo ' *** zlib test OK ***'; \
|
||||
else \
|
||||
echo ' *** zlib test FAILED ***'; \
|
||||
fi
|
||||
|
||||
libz.a: $(OBJS) $(OBJA)
|
||||
$(AR) $@ $(OBJS) $(OBJA)
|
||||
-@ ($(RANLIB) $@ || true) >/dev/null 2>&1
|
||||
|
||||
match.o: match.S
|
||||
$(CPP) match.S > _match.s
|
||||
$(CC) -c _match.s
|
||||
mv _match.o match.o
|
||||
rm -f _match.s
|
||||
|
||||
$(SHAREDLIBV): $(OBJS)
|
||||
$(LDSHARED) -o $@ $(OBJS)
|
||||
rm -f $(SHAREDLIB) $(SHAREDLIBM)
|
||||
ln -s $@ $(SHAREDLIB)
|
||||
ln -s $@ $(SHAREDLIBM)
|
||||
|
||||
example$(EXE): example.o $(LIBS)
|
||||
$(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS)
|
||||
|
||||
minigzip$(EXE): minigzip.o $(LIBS)
|
||||
$(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS)
|
||||
|
||||
install: $(LIBS)
|
||||
-@if [ ! -d $(exec_prefix) ]; then mkdir -p $(exec_prefix); fi
|
||||
-@if [ ! -d $(includedir) ]; then mkdir -p $(includedir); fi
|
||||
-@if [ ! -d $(libdir) ]; then mkdir -p $(libdir); fi
|
||||
-@if [ ! -d $(man3dir) ]; then mkdir -p $(man3dir); fi
|
||||
cp zlib.h zconf.h $(includedir)
|
||||
chmod 644 $(includedir)/zlib.h $(includedir)/zconf.h
|
||||
cp $(LIBS) $(libdir)
|
||||
cd $(libdir); chmod 755 $(LIBS)
|
||||
-@(cd $(libdir); $(RANLIB) libz.a || true) >/dev/null 2>&1
|
||||
cd $(libdir); if test -f $(SHAREDLIBV); then \
|
||||
rm -f $(SHAREDLIB) $(SHAREDLIBM); \
|
||||
ln -s $(SHAREDLIBV) $(SHAREDLIB); \
|
||||
ln -s $(SHAREDLIBV) $(SHAREDLIBM); \
|
||||
(ldconfig || true) >/dev/null 2>&1; \
|
||||
fi
|
||||
cp zlib.3 $(man3dir)
|
||||
chmod 644 $(man3dir)/zlib.3
|
||||
# The ranlib in install is needed on NeXTSTEP which checks file times
|
||||
# ldconfig is for Linux
|
||||
|
||||
uninstall:
|
||||
cd $(includedir); \
|
||||
cd $(libdir); rm -f libz.a; \
|
||||
if test -f $(SHAREDLIBV); then \
|
||||
rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM); \
|
||||
fi
|
||||
cd $(man3dir); rm -f zlib.3
|
||||
|
||||
mostlyclean: clean
|
||||
clean:
|
||||
rm -f *.o *~ example$(EXE) minigzip$(EXE) \
|
||||
libz.* foo.gz so_locations \
|
||||
_match.s maketree contrib/infback9/*.o
|
||||
|
||||
maintainer-clean: distclean
|
||||
distclean: clean
|
||||
cp -p Makefile.in Makefile
|
||||
cp -p zconf.in.h zconf.h
|
||||
rm -f .DS_Store
|
||||
|
||||
tags:
|
||||
etags *.[ch]
|
||||
|
||||
depend:
|
||||
makedepend -- $(CFLAGS) -- *.[ch]
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
adler32.o: zlib.h zconf.h
|
||||
compress.o: zlib.h zconf.h
|
||||
crc32.o: crc32.h zlib.h zconf.h
|
||||
deflate.o: deflate.h zutil.h zlib.h zconf.h
|
||||
example.o: zlib.h zconf.h
|
||||
gzio.o: zutil.h zlib.h zconf.h
|
||||
inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inftrees.o: zutil.h zlib.h zconf.h inftrees.h
|
||||
minigzip.o: zlib.h zconf.h
|
||||
trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
|
||||
uncompr.o: zlib.h zconf.h
|
||||
zutil.o: zutil.h zlib.h zconf.h
|
||||
@@ -0,0 +1,125 @@
|
||||
ZLIB DATA COMPRESSION LIBRARY
|
||||
|
||||
zlib 1.2.2.2 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)
|
||||
and rfc1952.txt (gzip format). These documents are also available in other
|
||||
formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
|
||||
|
||||
All functions of the compression library are documented in the file zlib.h
|
||||
(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example
|
||||
of the library is given in the file example.c which also tests that the library
|
||||
is working correctly. Another example is given in the file minigzip.c. The
|
||||
compression library itself is composed of all source files except example.c and
|
||||
minigzip.c.
|
||||
|
||||
To compile all files and run the test program, follow the instructions given at
|
||||
the top of Makefile. In short "make test; make install" should work for most
|
||||
machines. For Unix: "./configure; make test; make install". For MSDOS, use one
|
||||
of the special makefiles such as Makefile.msc. For VMS, use make_vms.com.
|
||||
|
||||
Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant
|
||||
<info@winimage.com> for the Windows DLL version. The zlib home page is
|
||||
http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem,
|
||||
please check this site to verify that you have the latest version of zlib;
|
||||
otherwise get the latest version and check whether the problem still exists or
|
||||
not.
|
||||
|
||||
PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking
|
||||
for help.
|
||||
|
||||
Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
|
||||
issue of Dr. Dobb's Journal; a copy of the article is available in
|
||||
http://dogma.net/markn/articles/zlibtool/zlibtool.htm
|
||||
|
||||
The changes made in version 1.2.2.2 are documented in the file ChangeLog.
|
||||
|
||||
Unsupported third party contributions are provided in directory "contrib".
|
||||
|
||||
A Java implementation of zlib is available in the Java Development Kit
|
||||
http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/package-summary.html
|
||||
See the zlib home page http://www.zlib.org for details.
|
||||
|
||||
A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org> is in the
|
||||
CPAN (Comprehensive Perl Archive Network) sites
|
||||
http://www.cpan.org/modules/by-module/Compress/
|
||||
|
||||
A Python interface to zlib written by A.M. Kuchling <amk@amk.ca> is
|
||||
available in Python 1.5 and later versions, see
|
||||
http://www.python.org/doc/lib/module-zlib.html
|
||||
|
||||
A zlib binding for TCL written by Andreas Kupries <a.kupries@westend.com> is
|
||||
availlable at http://www.oche.de/~akupries/soft/trf/trf_zip.html
|
||||
|
||||
An experimental package to read and write files in .zip format, written on top
|
||||
of zlib by Gilles Vollant <info@winimage.com>, is available in the
|
||||
contrib/minizip directory of zlib.
|
||||
|
||||
|
||||
Notes for some targets:
|
||||
|
||||
- For Windows DLL versions, please see win32/DLL_FAQ.txt
|
||||
|
||||
- For 64-bit Irix, deflate.c must be compiled without any optimization. With
|
||||
-O, one libpng test fails. The test works in 32 bit mode (with the -n32
|
||||
compiler flag). The compiler bug has been reported to SGI.
|
||||
|
||||
- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works
|
||||
when compiled with cc.
|
||||
|
||||
- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is
|
||||
necessary to get gzprintf working correctly. This is done by configure.
|
||||
|
||||
- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with
|
||||
other compilers. Use "make test" to check your compiler.
|
||||
|
||||
- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers.
|
||||
|
||||
- For PalmOs, see http://palmzlib.sourceforge.net/
|
||||
|
||||
- When building a shared, i.e. dynamic library on Mac OS X, the library must be
|
||||
installed before testing (do "make install" before "make test"), since the
|
||||
library location is specified in the library.
|
||||
|
||||
|
||||
Acknowledgments:
|
||||
|
||||
The deflate format used by zlib was defined by Phil Katz. The deflate
|
||||
and zlib specifications were written by L. Peter Deutsch. Thanks to all the
|
||||
people who reported problems and suggested various improvements in zlib;
|
||||
they are too numerous to cite here.
|
||||
|
||||
Copyright notice:
|
||||
|
||||
(C) 1995-2004 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
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Jean-loup Gailly Mark Adler
|
||||
jloup@gzip.org madler@alumni.caltech.edu
|
||||
|
||||
If you use the zlib library in a product, we would appreciate *not*
|
||||
receiving lengthy legal documents to sign. The sources are provided
|
||||
for free but without warranty of any kind. The library has been
|
||||
entirely written by Jean-loup Gailly and Mark Adler; it does not
|
||||
include third-party code.
|
||||
|
||||
If you redistribute modified sources, we would appreciate that you include
|
||||
in the file ChangeLog history information documenting your changes. Please
|
||||
read the FAQ for more information on the distribution of modified source
|
||||
versions.
|
||||
@@ -0,0 +1,149 @@
|
||||
/* adler32.c -- compute the Adler-32 checksum of a data stream
|
||||
* Copyright (C) 1995-2004 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include "zlib.h"
|
||||
|
||||
#define BASE 65521UL /* largest prime smaller than 65536 */
|
||||
#define NMAX 5552
|
||||
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
|
||||
|
||||
#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
|
||||
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
|
||||
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
|
||||
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
|
||||
#define DO16(buf) DO8(buf,0); DO8(buf,8);
|
||||
|
||||
/* use NO_DIVIDE if your processor does not do division in hardware */
|
||||
#ifdef NO_DIVIDE
|
||||
# define MOD(a) \
|
||||
do { \
|
||||
if (a >= (BASE << 16)) a -= (BASE << 16); \
|
||||
if (a >= (BASE << 15)) a -= (BASE << 15); \
|
||||
if (a >= (BASE << 14)) a -= (BASE << 14); \
|
||||
if (a >= (BASE << 13)) a -= (BASE << 13); \
|
||||
if (a >= (BASE << 12)) a -= (BASE << 12); \
|
||||
if (a >= (BASE << 11)) a -= (BASE << 11); \
|
||||
if (a >= (BASE << 10)) a -= (BASE << 10); \
|
||||
if (a >= (BASE << 9)) a -= (BASE << 9); \
|
||||
if (a >= (BASE << 8)) a -= (BASE << 8); \
|
||||
if (a >= (BASE << 7)) a -= (BASE << 7); \
|
||||
if (a >= (BASE << 6)) a -= (BASE << 6); \
|
||||
if (a >= (BASE << 5)) a -= (BASE << 5); \
|
||||
if (a >= (BASE << 4)) a -= (BASE << 4); \
|
||||
if (a >= (BASE << 3)) a -= (BASE << 3); \
|
||||
if (a >= (BASE << 2)) a -= (BASE << 2); \
|
||||
if (a >= (BASE << 1)) a -= (BASE << 1); \
|
||||
if (a >= BASE) a -= BASE; \
|
||||
} while (0)
|
||||
# define MOD4(a) \
|
||||
do { \
|
||||
if (a >= (BASE << 4)) a -= (BASE << 4); \
|
||||
if (a >= (BASE << 3)) a -= (BASE << 3); \
|
||||
if (a >= (BASE << 2)) a -= (BASE << 2); \
|
||||
if (a >= (BASE << 1)) a -= (BASE << 1); \
|
||||
if (a >= BASE) a -= BASE; \
|
||||
} while (0)
|
||||
#else
|
||||
# define MOD(a) a %= BASE
|
||||
# define MOD4(a) a %= BASE
|
||||
#endif
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32(adler, buf, len)
|
||||
uLong adler;
|
||||
const Bytef *buf;
|
||||
uInt len;
|
||||
{
|
||||
unsigned long sum2;
|
||||
unsigned n;
|
||||
|
||||
/* split Adler-32 into component sums */
|
||||
sum2 = (adler >> 16) & 0xffff;
|
||||
adler &= 0xffff;
|
||||
|
||||
/* in case user likes doing a byte at a time, keep it fast */
|
||||
if (len == 1) {
|
||||
adler += buf[0];
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
sum2 += adler;
|
||||
if (sum2 >= BASE)
|
||||
sum2 -= BASE;
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* initial Adler-32 value (deferred check for len == 1 speed) */
|
||||
if (buf == Z_NULL)
|
||||
return 1L;
|
||||
|
||||
/* in case short lengths are provided, keep it somewhat fast */
|
||||
if (len < 16) {
|
||||
while (len--) {
|
||||
adler += *buf++;
|
||||
sum2 += adler;
|
||||
}
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
MOD4(sum2); /* only added so many BASE's */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* do length NMAX blocks -- requires just one modulo operation */
|
||||
while (len >= NMAX) {
|
||||
len -= NMAX;
|
||||
n = NMAX / 16; /* NMAX is divisible by 16 */
|
||||
do {
|
||||
DO16(buf); /* 16 sums unrolled */
|
||||
buf += 16;
|
||||
} while (--n);
|
||||
MOD(adler);
|
||||
MOD(sum2);
|
||||
}
|
||||
|
||||
/* do remaining bytes (less than NMAX, still just one modulo) */
|
||||
if (len) { /* avoid modulos if none remaining */
|
||||
while (len >= 16) {
|
||||
len -= 16;
|
||||
DO16(buf);
|
||||
buf += 16;
|
||||
}
|
||||
while (len--) {
|
||||
adler += *buf++;
|
||||
sum2 += adler;
|
||||
}
|
||||
MOD(adler);
|
||||
MOD(sum2);
|
||||
}
|
||||
|
||||
/* return recombined sums */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32_combine(adler1, adler2, len2)
|
||||
uLong adler1;
|
||||
uLong adler2;
|
||||
z_off_t len2;
|
||||
{
|
||||
unsigned long sum1;
|
||||
unsigned long sum2;
|
||||
unsigned rem;
|
||||
|
||||
/* the derivation of this formula is left as an exercise for the reader */
|
||||
rem = (unsigned)(len2 % BASE);
|
||||
sum1 = adler1 & 0xffff;
|
||||
sum2 = rem * sum1;
|
||||
MOD(sum2);
|
||||
sum1 += (adler2 & 0xffff) + BASE - 1;
|
||||
sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
|
||||
if (sum1 > BASE) sum1 -= BASE;
|
||||
if (sum1 > BASE) sum1 -= BASE;
|
||||
if (sum2 > (BASE << 1)) sum2 -= (BASE << 1);
|
||||
if (sum2 > BASE) sum2 -= BASE;
|
||||
return sum1 | (sum2 << 16);
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
1. Compression algorithm (deflate)
|
||||
|
||||
The deflation algorithm used by gzip (also zip and zlib) is a variation of
|
||||
LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in
|
||||
the input data. The second occurrence of a string is replaced by a
|
||||
pointer to the previous string, in the form of a pair (distance,
|
||||
length). Distances are limited to 32K bytes, and lengths are limited
|
||||
to 258 bytes. When a string does not occur anywhere in the previous
|
||||
32K bytes, it is emitted as a sequence of literal bytes. (In this
|
||||
description, `string' must be taken as an arbitrary sequence of bytes,
|
||||
and is not restricted to printable characters.)
|
||||
|
||||
Literals or match lengths are compressed with one Huffman tree, and
|
||||
match distances are compressed with another tree. The trees are stored
|
||||
in a compact form at the start of each block. The blocks can have any
|
||||
size (except that the compressed data for one block must fit in
|
||||
available memory). A block is terminated when deflate() determines that
|
||||
it would be useful to start another block with fresh trees. (This is
|
||||
somewhat similar to the behavior of LZW-based _compress_.)
|
||||
|
||||
Duplicated strings are found using a hash table. All input strings of
|
||||
length 3 are inserted in the hash table. A hash index is computed for
|
||||
the next 3 bytes. If the hash chain for this index is not empty, all
|
||||
strings in the chain are compared with the current input string, and
|
||||
the longest match is selected.
|
||||
|
||||
The hash chains are searched starting with the most recent strings, to
|
||||
favor small distances and thus take advantage of the Huffman encoding.
|
||||
The hash chains are singly linked. There are no deletions from the
|
||||
hash chains, the algorithm simply discards matches that are too old.
|
||||
|
||||
To avoid a worst-case situation, very long hash chains are arbitrarily
|
||||
truncated at a certain length, determined by a runtime option (level
|
||||
parameter of deflateInit). So deflate() does not always find the longest
|
||||
possible match but generally finds a match which is long enough.
|
||||
|
||||
deflate() also defers the selection of matches with a lazy evaluation
|
||||
mechanism. After a match of length N has been found, deflate() searches for
|
||||
a longer match at the next input byte. If a longer match is found, the
|
||||
previous match is truncated to a length of one (thus producing a single
|
||||
literal byte) and the process of lazy evaluation begins again. Otherwise,
|
||||
the original match is kept, and the next match search is attempted only N
|
||||
steps later.
|
||||
|
||||
The lazy match evaluation is also subject to a runtime parameter. If
|
||||
the current match is long enough, deflate() reduces the search for a longer
|
||||
match, thus speeding up the whole process. If compression ratio is more
|
||||
important than speed, deflate() attempts a complete second search even if
|
||||
the first match is already long enough.
|
||||
|
||||
The lazy match evaluation is not performed for the fastest compression
|
||||
modes (level parameter 1 to 3). For these fast modes, new strings
|
||||
are inserted in the hash table only when no match was found, or
|
||||
when the match is not too long. This degrades the compression ratio
|
||||
but saves time since there are both fewer insertions and fewer searches.
|
||||
|
||||
|
||||
2. Decompression algorithm (inflate)
|
||||
|
||||
2.1 Introduction
|
||||
|
||||
The key question is how to represent a Huffman code (or any prefix code) so
|
||||
that you can decode fast. The most important characteristic is that shorter
|
||||
codes are much more common than longer codes, so pay attention to decoding the
|
||||
short codes fast, and let the long codes take longer to decode.
|
||||
|
||||
inflate() sets up a first level table that covers some number of bits of
|
||||
input less than the length of longest code. It gets that many bits from the
|
||||
stream, and looks it up in the table. The table will tell if the next
|
||||
code is that many bits or less and how many, and if it is, it will tell
|
||||
the value, else it will point to the next level table for which inflate()
|
||||
grabs more bits and tries to decode a longer code.
|
||||
|
||||
How many bits to make the first lookup is a tradeoff between the time it
|
||||
takes to decode and the time it takes to build the table. If building the
|
||||
table took no time (and if you had infinite memory), then there would only
|
||||
be a first level table to cover all the way to the longest code. However,
|
||||
building the table ends up taking a lot longer for more bits since short
|
||||
codes are replicated many times in such a table. What inflate() does is
|
||||
simply to make the number of bits in the first table a variable, and then
|
||||
to set that variable for the maximum speed.
|
||||
|
||||
For inflate, which has 286 possible codes for the literal/length tree, the size
|
||||
of the first table is nine bits. Also the distance trees have 30 possible
|
||||
values, and the size of the first table is six bits. Note that for each of
|
||||
those cases, the table ended up one bit longer than the ``average'' code
|
||||
length, i.e. the code length of an approximately flat code which would be a
|
||||
little more than eight bits for 286 symbols and a little less than five bits
|
||||
for 30 symbols.
|
||||
|
||||
|
||||
2.2 More details on the inflate table lookup
|
||||
|
||||
Ok, you want to know what this cleverly obfuscated inflate tree actually
|
||||
looks like. You are correct that it's not a Huffman tree. It is simply a
|
||||
lookup table for the first, let's say, nine bits of a Huffman symbol. The
|
||||
symbol could be as short as one bit or as long as 15 bits. If a particular
|
||||
symbol is shorter than nine bits, then that symbol's translation is duplicated
|
||||
in all those entries that start with that symbol's bits. For example, if the
|
||||
symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a
|
||||
symbol is nine bits long, it appears in the table once.
|
||||
|
||||
If the symbol is longer than nine bits, then that entry in the table points
|
||||
to another similar table for the remaining bits. Again, there are duplicated
|
||||
entries as needed. The idea is that most of the time the symbol will be short
|
||||
and there will only be one table look up. (That's whole idea behind data
|
||||
compression in the first place.) For the less frequent long symbols, there
|
||||
will be two lookups. If you had a compression method with really long
|
||||
symbols, you could have as many levels of lookups as is efficient. For
|
||||
inflate, two is enough.
|
||||
|
||||
So a table entry either points to another table (in which case nine bits in
|
||||
the above example are gobbled), or it contains the translation for the symbol
|
||||
and the number of bits to gobble. Then you start again with the next
|
||||
ungobbled bit.
|
||||
|
||||
You may wonder: why not just have one lookup table for how ever many bits the
|
||||
longest symbol is? The reason is that if you do that, you end up spending
|
||||
more time filling in duplicate symbol entries than you do actually decoding.
|
||||
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
|
||||
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
|
||||
fill out the table vs. the time spent looking at the second level and above of
|
||||
the table.
|
||||
|
||||
Here is an example, scaled down:
|
||||
|
||||
The code being decoded, with 10 symbols, from 1 to 6 bits long:
|
||||
|
||||
A: 0
|
||||
B: 10
|
||||
C: 1100
|
||||
D: 11010
|
||||
E: 11011
|
||||
F: 11100
|
||||
G: 11101
|
||||
H: 11110
|
||||
I: 111110
|
||||
J: 111111
|
||||
|
||||
Let's make the first table three bits long (eight entries):
|
||||
|
||||
000: A,1
|
||||
001: A,1
|
||||
010: A,1
|
||||
011: A,1
|
||||
100: B,2
|
||||
101: B,2
|
||||
110: -> table X (gobble 3 bits)
|
||||
111: -> table Y (gobble 3 bits)
|
||||
|
||||
Each entry is what the bits decode as and how many bits that is, i.e. how
|
||||
many bits to gobble. Or the entry points to another table, with the number of
|
||||
bits to gobble implicit in the size of the table.
|
||||
|
||||
Table X is two bits long since the longest code starting with 110 is five bits
|
||||
long:
|
||||
|
||||
00: C,1
|
||||
01: C,1
|
||||
10: D,2
|
||||
11: E,2
|
||||
|
||||
Table Y is three bits long since the longest code starting with 111 is six
|
||||
bits long:
|
||||
|
||||
000: F,2
|
||||
001: F,2
|
||||
010: G,2
|
||||
011: G,2
|
||||
100: H,2
|
||||
101: H,2
|
||||
110: I,3
|
||||
111: J,3
|
||||
|
||||
So what we have here are three tables with a total of 20 entries that had to
|
||||
be constructed. That's compared to 64 entries for a single table. Or
|
||||
compared to 16 entries for a Huffman tree (six two entry tables and one four
|
||||
entry table). Assuming that the code ideally represents the probability of
|
||||
the symbols, it takes on the average 1.25 lookups per symbol. That's compared
|
||||
to one lookup for the single table, or 1.66 lookups per symbol for the
|
||||
Huffman tree.
|
||||
|
||||
There, I think that gives you a picture of what's going on. For inflate, the
|
||||
meaning of a particular symbol is often more than just a letter. It can be a
|
||||
byte (a "literal"), or it can be either a length or a distance which
|
||||
indicates a base value and a number of bits to fetch after the code that is
|
||||
added to the base value. Or it might be the special end-of-block code. The
|
||||
data structures created in inftrees.c try to encode all that information
|
||||
compactly in the tables.
|
||||
|
||||
|
||||
Jean-loup Gailly Mark Adler
|
||||
jloup@gzip.org madler@alumni.caltech.edu
|
||||
|
||||
|
||||
References:
|
||||
|
||||
[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data
|
||||
Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3,
|
||||
pp. 337-343.
|
||||
|
||||
``DEFLATE Compressed Data Format Specification'' available in
|
||||
http://www.ietf.org/rfc/rfc1951.txt
|
||||
@@ -0,0 +1,66 @@
|
||||
# Amiga powerUP (TM) Makefile
|
||||
# makefile for libpng and SAS C V6.58/7.00 PPC compiler
|
||||
# Copyright (C) 1998 by Andreas R. Kleinert
|
||||
|
||||
LIBNAME = libzip.a
|
||||
|
||||
CC = scppc
|
||||
CFLAGS = NOSTKCHK NOSINT OPTIMIZE OPTGO OPTPEEP OPTINLOCAL OPTINL \
|
||||
OPTLOOP OPTRDEP=8 OPTDEP=8 OPTCOMP=8 NOVER
|
||||
AR = ppc-amigaos-ar cr
|
||||
RANLIB = ppc-amigaos-ranlib
|
||||
LD = ppc-amigaos-ld -r
|
||||
LDFLAGS = -o
|
||||
LDLIBS = LIB:scppc.a LIB:end.o
|
||||
RM = delete quiet
|
||||
|
||||
OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
|
||||
zutil.o inflate.o infback.o inftrees.o inffast.o
|
||||
|
||||
TEST_OBJS = example.o minigzip.o
|
||||
|
||||
all: example minigzip
|
||||
|
||||
check: test
|
||||
test: all
|
||||
example
|
||||
echo hello world | minigzip | minigzip -d
|
||||
|
||||
$(LIBNAME): $(OBJS)
|
||||
$(AR) $@ $(OBJS)
|
||||
-$(RANLIB) $@
|
||||
|
||||
example: example.o $(LIBNAME)
|
||||
$(LD) $(LDFLAGS) $@ LIB:c_ppc.o $@.o $(LIBNAME) $(LDLIBS)
|
||||
|
||||
minigzip: minigzip.o $(LIBNAME)
|
||||
$(LD) $(LDFLAGS) $@ LIB:c_ppc.o $@.o $(LIBNAME) $(LDLIBS)
|
||||
|
||||
mostlyclean: clean
|
||||
clean:
|
||||
$(RM) *.o example minigzip $(LIBNAME) foo.gz
|
||||
|
||||
zip:
|
||||
zip -ul9 zlib README ChangeLog Makefile Make????.??? Makefile.?? \
|
||||
descrip.mms *.[ch]
|
||||
|
||||
tgz:
|
||||
cd ..; tar cfz zlib/zlib.tgz zlib/README zlib/ChangeLog zlib/Makefile \
|
||||
zlib/Make????.??? zlib/Makefile.?? zlib/descrip.mms zlib/*.[ch]
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
adler32.o: zlib.h zconf.h
|
||||
compress.o: zlib.h zconf.h
|
||||
crc32.o: crc32.h zlib.h zconf.h
|
||||
deflate.o: deflate.h zutil.h zlib.h zconf.h
|
||||
example.o: zlib.h zconf.h
|
||||
gzio.o: zutil.h zlib.h zconf.h
|
||||
inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inftrees.o: zutil.h zlib.h zconf.h inftrees.h
|
||||
minigzip.o: zlib.h zconf.h
|
||||
trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
|
||||
uncompr.o: zlib.h zconf.h
|
||||
zutil.o: zutil.h zlib.h zconf.h
|
||||
@@ -0,0 +1,65 @@
|
||||
# SMakefile for zlib
|
||||
# Modified from the standard UNIX Makefile Copyright Jean-loup Gailly
|
||||
# Osma Ahvenlampi <Osma.Ahvenlampi@hut.fi>
|
||||
# Amiga, SAS/C 6.56 & Smake
|
||||
|
||||
CC=sc
|
||||
CFLAGS=OPT
|
||||
#CFLAGS=OPT CPU=68030
|
||||
#CFLAGS=DEBUG=LINE
|
||||
LDFLAGS=LIB z.lib
|
||||
|
||||
SCOPTIONS=OPTSCHED OPTINLINE OPTALIAS OPTTIME OPTINLOCAL STRMERGE \
|
||||
NOICONS PARMS=BOTH NOSTACKCHECK UTILLIB NOVERSION ERRORREXX \
|
||||
DEF=POSTINC
|
||||
|
||||
OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
|
||||
zutil.o inflate.o infback.o inftrees.o inffast.o
|
||||
|
||||
TEST_OBJS = example.o minigzip.o
|
||||
|
||||
all: SCOPTIONS example minigzip
|
||||
|
||||
check: test
|
||||
test: all
|
||||
example
|
||||
echo hello world | minigzip | minigzip -d
|
||||
|
||||
install: z.lib
|
||||
copy clone zlib.h zconf.h INCLUDE:
|
||||
copy clone z.lib LIB:
|
||||
|
||||
z.lib: $(OBJS)
|
||||
oml z.lib r $(OBJS)
|
||||
|
||||
example: example.o z.lib
|
||||
$(CC) $(CFLAGS) LINK TO $@ example.o $(LDFLAGS)
|
||||
|
||||
minigzip: minigzip.o z.lib
|
||||
$(CC) $(CFLAGS) LINK TO $@ minigzip.o $(LDFLAGS)
|
||||
|
||||
mostlyclean: clean
|
||||
clean:
|
||||
-delete force quiet example minigzip *.o z.lib foo.gz *.lnk SCOPTIONS
|
||||
|
||||
SCOPTIONS: Makefile.sas
|
||||
copy to $@ <from <
|
||||
$(SCOPTIONS)
|
||||
<
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
adler32.o: zlib.h zconf.h
|
||||
compress.o: zlib.h zconf.h
|
||||
crc32.o: crc32.h zlib.h zconf.h
|
||||
deflate.o: deflate.h zutil.h zlib.h zconf.h
|
||||
example.o: zlib.h zconf.h
|
||||
gzio.o: zutil.h zlib.h zconf.h
|
||||
inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inftrees.o: zutil.h zlib.h zconf.h inftrees.h
|
||||
minigzip.o: zlib.h zconf.h
|
||||
trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
|
||||
uncompr.o: zlib.h zconf.h
|
||||
zutil.o: zutil.h zlib.h zconf.h
|
||||
@@ -0,0 +1,132 @@
|
||||
STRPGMEXP PGMLVL(*CURRENT) SIGNATURE('ZLIB')
|
||||
|
||||
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
|
||||
/* Version 1.1.3 entry points. */
|
||||
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE ADLER32 ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("adler32")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE COMPRESS ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("compress")
|
||||
EXPORT SYMBOL("compress2")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE CRC32 ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("crc32")
|
||||
EXPORT SYMBOL("get_crc_table")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE DEFLATE ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("deflate")
|
||||
EXPORT SYMBOL("deflateEnd")
|
||||
EXPORT SYMBOL("deflateSetDictionary")
|
||||
EXPORT SYMBOL("deflateCopy")
|
||||
EXPORT SYMBOL("deflateReset")
|
||||
EXPORT SYMBOL("deflateParams")
|
||||
EXPORT SYMBOL("deflatePrime")
|
||||
EXPORT SYMBOL("deflateInit_")
|
||||
EXPORT SYMBOL("deflateInit2_")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE GZIO ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("gzopen")
|
||||
EXPORT SYMBOL("gzdopen")
|
||||
EXPORT SYMBOL("gzsetparams")
|
||||
EXPORT SYMBOL("gzread")
|
||||
EXPORT SYMBOL("gzwrite")
|
||||
EXPORT SYMBOL("gzprintf")
|
||||
EXPORT SYMBOL("gzputs")
|
||||
EXPORT SYMBOL("gzgets")
|
||||
EXPORT SYMBOL("gzputc")
|
||||
EXPORT SYMBOL("gzgetc")
|
||||
EXPORT SYMBOL("gzflush")
|
||||
EXPORT SYMBOL("gzseek")
|
||||
EXPORT SYMBOL("gzrewind")
|
||||
EXPORT SYMBOL("gztell")
|
||||
EXPORT SYMBOL("gzeof")
|
||||
EXPORT SYMBOL("gzclose")
|
||||
EXPORT SYMBOL("gzerror")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE INFLATE ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("inflate")
|
||||
EXPORT SYMBOL("inflateEnd")
|
||||
EXPORT SYMBOL("inflateSetDictionary")
|
||||
EXPORT SYMBOL("inflateSync")
|
||||
EXPORT SYMBOL("inflateReset")
|
||||
EXPORT SYMBOL("inflateInit_")
|
||||
EXPORT SYMBOL("inflateInit2_")
|
||||
EXPORT SYMBOL("inflateSyncPoint")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE UNCOMPR ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("uncompress")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE ZUTIL ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("zlibVersion")
|
||||
EXPORT SYMBOL("zError")
|
||||
|
||||
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
|
||||
/* Version 1.2.1 additional entry points. */
|
||||
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE COMPRESS ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("compressBound")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE DEFLATE ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("deflateBound")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE GZIO ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("gzungetc")
|
||||
EXPORT SYMBOL("gzclearerr")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE INFBACK ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("inflateBack")
|
||||
EXPORT SYMBOL("inflateBackEnd")
|
||||
EXPORT SYMBOL("inflateBackInit_")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE INFLATE ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("inflateCopy")
|
||||
|
||||
/********************************************************************/
|
||||
/* *MODULE ZUTIL ZLIB 01/02/01 00:15:09 */
|
||||
/********************************************************************/
|
||||
|
||||
EXPORT SYMBOL("zlibCompileFlags")
|
||||
|
||||
ENDPGMEXP
|
||||
@@ -0,0 +1,123 @@
|
||||
/******************************************************************************/
|
||||
/* */
|
||||
/* ZLIB */
|
||||
/* */
|
||||
/* Compile sources into modules and link them into a service program. */
|
||||
/* */
|
||||
/******************************************************************************/
|
||||
|
||||
PGM
|
||||
|
||||
/* Configuration adjustable parameters. */
|
||||
|
||||
DCL VAR(&SRCLIB) TYPE(*CHAR) LEN(10) +
|
||||
VALUE('ZLIB') /* Source library. */
|
||||
DCL VAR(&SRCFILE) TYPE(*CHAR) LEN(10) +
|
||||
VALUE('SOURCES') /* Source member file. */
|
||||
DCL VAR(&CTLFILE) TYPE(*CHAR) LEN(10) +
|
||||
VALUE('TOOLS') /* Control member file. */
|
||||
|
||||
DCL VAR(&MODLIB) TYPE(*CHAR) LEN(10) +
|
||||
VALUE('ZLIB') /* Module library. */
|
||||
|
||||
DCL VAR(&SRVLIB) TYPE(*CHAR) LEN(10) +
|
||||
VALUE('LGPL') /* Service program library. */
|
||||
|
||||
DCL VAR(&CFLAGS) TYPE(*CHAR) +
|
||||
VALUE('OPTIMIZE(40)') /* Compile options. */
|
||||
|
||||
|
||||
/* Working storage. */
|
||||
|
||||
DCL VAR(&CMDLEN) TYPE(*DEC) LEN(15 5) VALUE(300) /* Command length. */
|
||||
DCL VAR(&CMD) TYPE(*CHAR) LEN(512)
|
||||
|
||||
|
||||
/* Compile sources into modules. */
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/ADLER32) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/COMPRESS) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/CRC32) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/DEFLATE) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/GZIO) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/INFBACK) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/INFFAST) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/INFLATE) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/INFTREES) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/TREES) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/UNCOMPR) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
CHGVAR VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT +
|
||||
'/ZUTIL) SRCFILE(' *TCAT +
|
||||
&SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT +
|
||||
') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
|
||||
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
|
||||
|
||||
|
||||
/* Link modules into a service program. */
|
||||
|
||||
CRTSRVPGM SRVPGM(&SRVLIB/ZLIB) +
|
||||
MODULE(&MODLIB/ADLER32 &MODLIB/COMPRESS +
|
||||
&MODLIB/CRC32 &MODLIB/DEFLATE +
|
||||
&MODLIB/GZIO &MODLIB/INFBACK +
|
||||
&MODLIB/INFFAST &MODLIB/INFLATE +
|
||||
&MODLIB/INFTREES &MODLIB/TREES +
|
||||
&MODLIB/UNCOMPR &MODLIB/ZUTIL) +
|
||||
SRCFILE(&SRCLIB/&CTLFILE) SRCMBR(BNDSRC) +
|
||||
TEXT('ZLIB 1.2.2') TGTRLS(V4R4M0)
|
||||
|
||||
ENDPGM
|
||||
@@ -0,0 +1,111 @@
|
||||
ZLIB version 1.2.2 for AS400 installation instructions
|
||||
|
||||
I) From an AS400 *SAVF file:
|
||||
|
||||
1) Unpacking archive to an AS400 save file
|
||||
|
||||
On the AS400:
|
||||
|
||||
_ Create the ZLIB AS400 library:
|
||||
|
||||
CRTLIB LIB(ZLIB) TYPE(PROD) TEXT('ZLIB compression API library')
|
||||
|
||||
_ Create a work save file, for example:
|
||||
|
||||
CRTSAVF FILE(ZLIB/ZLIBSAVF)
|
||||
|
||||
On a PC connected to the target AS400:
|
||||
|
||||
_ Unpack the save file image to a PC file "ZLIBSAVF"
|
||||
_ Upload this file into the save file on the AS400, for example
|
||||
using ftp in BINARY mode.
|
||||
|
||||
|
||||
2) Populating the ZLIB AS400 source library
|
||||
|
||||
On the AS400:
|
||||
|
||||
_ Extract the saved objects into the ZLIB AS400 library using:
|
||||
|
||||
RSTOBJ OBJ(*ALL) SAVLIB(ZLIB) DEV(*SAVF) SAVF(ZLIB/ZLIBSAVF) RSTLIB(ZLIB)
|
||||
|
||||
|
||||
3) Customize installation:
|
||||
|
||||
_ Edit CL member ZLIB/TOOLS(COMPILE) and change parameters if needed,
|
||||
according to the comments.
|
||||
|
||||
_ Compile this member with:
|
||||
|
||||
CRTCLPGM PGM(ZLIB/COMPILE) SRCFILE(ZLIB/TOOLS) SRCMBR(COMPILE)
|
||||
|
||||
|
||||
4) Compile and generate the service program:
|
||||
|
||||
_ This can now be done by executing:
|
||||
|
||||
CALL PGM(ZLIB/COMPILE)
|
||||
|
||||
|
||||
|
||||
II) From the original source distribution:
|
||||
|
||||
1) On the AS400, create the source library:
|
||||
|
||||
CRTLIB LIB(ZLIB) TYPE(PROD) TEXT('ZLIB compression API library')
|
||||
|
||||
2) Create the source files:
|
||||
|
||||
CRTSRCPF FILE(ZLIB/SOURCES) RCDLEN(112) TEXT('ZLIB library modules')
|
||||
CRTSRCPF FILE(ZLIB/H) RCDLEN(112) TEXT('ZLIB library includes')
|
||||
CRTSRCPF FILE(ZLIB/TOOLS) RCDLEN(112) TEXT('ZLIB library control utilities')
|
||||
|
||||
3) From the machine hosting the distribution files, upload them (with
|
||||
FTP in text mode, for example) according to the following table:
|
||||
|
||||
Original AS400 AS400 AS400 AS400
|
||||
file file member type description
|
||||
SOURCES Original ZLIB C subprogram sources
|
||||
adler32.c ADLER32 C ZLIB - Compute the Adler-32 checksum of a dta strm
|
||||
compress.c COMPRESS C ZLIB - Compress a memory buffer
|
||||
crc32.c CRC32 C ZLIB - Compute the CRC-32 of a data stream
|
||||
deflate.c DEFLATE C ZLIB - Compress data using the deflation algorithm
|
||||
gzio.c GZIO C ZLIB - IO on .gz files
|
||||
infback.c INFBACK C ZLIB - Inflate using a callback interface
|
||||
inffast.c INFFAST C ZLIB - Fast proc. literals & length/distance pairs
|
||||
inflate.c INFLATE C ZLIB - Interface to inflate modules
|
||||
inftrees.c INFTREES C ZLIB - Generate Huffman trees for efficient decode
|
||||
trees.c TREES C ZLIB - Output deflated data using Huffman coding
|
||||
uncompr.c UNCOMPR C ZLIB - Decompress a memory buffer
|
||||
zutil.c ZUTIL C ZLIB - Target dependent utility functions
|
||||
H Original ZLIB C and ILE/RPG include files
|
||||
crc32.h CRC32 C ZLIB - CRC32 tables
|
||||
deflate.h DEFLATE C ZLIB - Internal compression state
|
||||
inffast.h INFFAST C ZLIB - Header to use inffast.c
|
||||
inffixed.h INFFIXED C ZLIB - Table for decoding fixed codes
|
||||
inflate.h INFLATE C ZLIB - Internal inflate state definitions
|
||||
inftrees.h INFTREES C ZLIB - Header to use inftrees.c
|
||||
trees.h TREES C ZLIB - Created automatically with -DGEN_TREES_H
|
||||
zconf.h ZCONF C ZLIB - Compression library configuration
|
||||
zlib.h ZLIB C ZLIB - Compression library C user interface
|
||||
as400/zlib.inc ZLIB.INC RPGLE ZLIB - Compression library ILE RPG user interface
|
||||
zutil.h ZUTIL C ZLIB - Internal interface and configuration
|
||||
TOOLS Building source software & AS/400 README
|
||||
as400/bndsrc BNDSRC Entry point exportation list
|
||||
as400/compile.clp COMPILE CLP Compile sources & generate service program
|
||||
as400/readme.txt README TXT Installation instructions
|
||||
|
||||
4) Continue as in I)3).
|
||||
|
||||
|
||||
|
||||
|
||||
Notes: For AS400 ILE RPG programmers, a /copy member defining the ZLIB
|
||||
API prototypes for ILE RPG can be found in ZLIB/H(ZLIB.INC).
|
||||
Please read comments in this member for more information.
|
||||
|
||||
Remember that most foreign textual data are ASCII coded: this
|
||||
implementation does not handle conversion from/to ASCII, so
|
||||
text data code conversions must be done explicitely.
|
||||
|
||||
Always open zipped files in binary mode.
|
||||
@@ -0,0 +1,327 @@
|
||||
* ZLIB.INC - Interface to the general purpose compression library
|
||||
*
|
||||
* ILE RPG400 version by Patrick Monnerat, DATASPHERE.
|
||||
* Version 1.2.2.2
|
||||
*
|
||||
*
|
||||
* WARNING:
|
||||
* Procedures inflateInit(), inflateInit2(), deflateInit(),
|
||||
* deflateInit2() and inflateBackInit() need to be called with
|
||||
* two additional arguments:
|
||||
* the package version string and the stream control structure.
|
||||
* size. This is needed because RPG lacks some macro feature.
|
||||
* Call these procedures as:
|
||||
* inflateInit(...: ZLIB_VERSION: %size(z_stream))
|
||||
*
|
||||
/if not defined(ZLIB_H_)
|
||||
/define ZLIB_H_
|
||||
*
|
||||
**************************************************************************
|
||||
* Constants
|
||||
**************************************************************************
|
||||
*
|
||||
D ZLIB_VERSION C '1.2.2.2' Header's version
|
||||
D ZLIB_VERNUM C X'1222'
|
||||
*
|
||||
D Z_NO_FLUSH C 0
|
||||
D Z_SYNC_FLUSH C 2
|
||||
D Z_FULL_FLUSH C 3
|
||||
D Z_FINISH C 4
|
||||
D Z_BLOCK C 5
|
||||
*
|
||||
D Z_OK C 0
|
||||
D Z_STREAM_END C 1
|
||||
D Z_NEED_DICT C 2
|
||||
D Z_ERRNO C -1
|
||||
D Z_STREAM_ERROR C -2
|
||||
D Z_DATA_ERROR C -3
|
||||
D Z_MEM_ERROR C -4
|
||||
D Z_BUF_ERROR C -5
|
||||
DZ_VERSION_ERROR C -6
|
||||
*
|
||||
D Z_NO_COMPRESSION...
|
||||
D C 0
|
||||
D Z_BEST_SPEED C 1
|
||||
D Z_BEST_COMPRESSION...
|
||||
D C 9
|
||||
D Z_DEFAULT_COMPRESSION...
|
||||
D C -1
|
||||
*
|
||||
D Z_FILTERED C 1
|
||||
D Z_HUFFMAN_ONLY C 2
|
||||
D Z_RLE C 3
|
||||
D Z_DEFAULT_STRATEGY...
|
||||
D C 0
|
||||
*
|
||||
D Z_BINARY C 0
|
||||
D Z_ASCII C 1
|
||||
D Z_UNKNOWN C 2
|
||||
*
|
||||
D Z_DEFLATED C 8
|
||||
*
|
||||
D Z_NULL C 0
|
||||
*
|
||||
**************************************************************************
|
||||
* Types
|
||||
**************************************************************************
|
||||
*
|
||||
D z_streamp S * Stream struct ptr
|
||||
D gzFile S * File pointer
|
||||
D z_off_t S 10i 0 Stream offsets
|
||||
*
|
||||
**************************************************************************
|
||||
* Structures
|
||||
**************************************************************************
|
||||
*
|
||||
* The GZIP encode/decode stream support structure.
|
||||
*
|
||||
D z_stream DS align based(z_streamp)
|
||||
D zs_next_in * Next input byte
|
||||
D zs_avail_in 10U 0 Byte cnt at next_in
|
||||
D zs_total_in 10U 0 Total bytes read
|
||||
D zs_next_out * Output buffer ptr
|
||||
D zs_avail_out 10U 0 Room left @ next_out
|
||||
D zs_total_out 10U 0 Total bytes written
|
||||
D zs_msg * Last errmsg or null
|
||||
D zs_state * Internal state
|
||||
D zs_zalloc * procptr Int. state allocator
|
||||
D zs_free * procptr Int. state dealloc.
|
||||
D zs_opaque * Private alloc. data
|
||||
D zs_data_type 10i 0 ASC/BIN best guess
|
||||
D zs_adler 10u 0 Uncompr. adler32 val
|
||||
D 10U 0 Reserved
|
||||
D 10U 0 Ptr. alignment
|
||||
*
|
||||
**************************************************************************
|
||||
* Utility function prototypes
|
||||
**************************************************************************
|
||||
*
|
||||
D compress PR 10I 0 extproc('compress')
|
||||
D dest 32767 options(*varsize) Destination buffer
|
||||
D destLen 10U 0 Destination length
|
||||
D source 32767 const options(*varsize) Source buffer
|
||||
D sourceLen 10u 0 value Source length
|
||||
*
|
||||
D compress2 PR 10I 0 extproc('compress2')
|
||||
D dest 32767 options(*varsize) Destination buffer
|
||||
D destLen 10U 0 Destination length
|
||||
D source 32767 const options(*varsize) Source buffer
|
||||
D sourceLen 10U 0 value Source length
|
||||
D level 10I 0 value Compression level
|
||||
*
|
||||
D compressBound PR 10U 0 extproc('compressBound')
|
||||
D sourceLen 10U 0 value
|
||||
*
|
||||
D uncompress PR 10I 0 extproc('uncompress')
|
||||
D dest 32767 options(*varsize) Destination buffer
|
||||
D destLen 10U 0 Destination length
|
||||
D source 32767 const options(*varsize) Source buffer
|
||||
D sourceLen 10U 0 value Source length
|
||||
*
|
||||
D gzopen PR extproc('gzopen')
|
||||
D like(gzFile)
|
||||
D path * value options(*string) File pathname
|
||||
D mode * value options(*string) Open mode
|
||||
*
|
||||
D gzdopen PR extproc('gzdopen')
|
||||
D like(gzFile)
|
||||
D fd 10i 0 value File descriptor
|
||||
D mode * value options(*string) Open mode
|
||||
*
|
||||
D gzsetparams PR 10I 0 extproc('gzsetparams')
|
||||
D file value like(gzFile) File pointer
|
||||
D level 10I 0 value
|
||||
D strategy 10i 0 value
|
||||
*
|
||||
D gzread PR 10I 0 extproc('gzread')
|
||||
D file value like(gzFile) File pointer
|
||||
D buf 32767 options(*varsize) Buffer
|
||||
D len 10u 0 value Buffer length
|
||||
*
|
||||
D gzwrite PR 10I 0 extproc('gzwrite')
|
||||
D file value like(gzFile) File pointer
|
||||
D buf 32767 const options(*varsize) Buffer
|
||||
D len 10u 0 value Buffer length
|
||||
*
|
||||
D gzputs PR 10I 0 extproc('gzputs')
|
||||
D file value like(gzFile) File pointer
|
||||
D s * value options(*string) String to output
|
||||
*
|
||||
D gzgets PR * extproc('gzgets')
|
||||
D file value like(gzFile) File pointer
|
||||
D buf 32767 options(*varsize) Read buffer
|
||||
D len 10i 0 value Buffer length
|
||||
*
|
||||
D gzflush PR 10i 0 extproc('gzflush')
|
||||
D file value like(gzFile) File pointer
|
||||
D flush 10I 0 value Type of flush
|
||||
*
|
||||
D gzseek PR extproc('gzseek')
|
||||
D like(z_off_t)
|
||||
D file value like(gzFile) File pointer
|
||||
D offset value like(z_off_t) Offset
|
||||
D whence 10i 0 value Origin
|
||||
*
|
||||
D gzrewind PR 10i 0 extproc('gzrewind')
|
||||
D file value like(gzFile) File pointer
|
||||
*
|
||||
D gztell PR extproc('gztell')
|
||||
D like(z_off_t)
|
||||
D file value like(gzFile) File pointer
|
||||
*
|
||||
D gzeof PR 10i 0 extproc('gzeof')
|
||||
D file value like(gzFile) File pointer
|
||||
*
|
||||
D gzclose PR 10i 0 extproc('gzclose')
|
||||
D file value like(gzFile) File pointer
|
||||
*
|
||||
D gzerror PR * extproc('gzerror') Error string
|
||||
D file value like(gzFile) File pointer
|
||||
D errnum 10I 0 Error code
|
||||
*
|
||||
D gzclearerr PR extproc('gzclearerr')
|
||||
D file value like(gzFile) File pointer
|
||||
*
|
||||
**************************************************************************
|
||||
* Basic function prototypes
|
||||
**************************************************************************
|
||||
*
|
||||
D zlibVersion PR * extproc('zlibVersion') Version string
|
||||
*
|
||||
D deflateInit PR 10I 0 extproc('deflateInit_') Init. compression
|
||||
D strm like(z_stream) Compression stream
|
||||
D level 10I 0 value Compression level
|
||||
D version * value options(*string) Version string
|
||||
D stream_size 10i 0 value Stream struct. size
|
||||
*
|
||||
D deflate PR 10I 0 extproc('deflate') Compress data
|
||||
D strm like(z_stream) Compression stream
|
||||
D flush 10I 0 value Flush type required
|
||||
*
|
||||
D deflateEnd PR 10I 0 extproc('deflateEnd') Termin. compression
|
||||
D strm like(z_stream) Compression stream
|
||||
*
|
||||
D inflateInit PR 10I 0 extproc('inflateInit_') Init. expansion
|
||||
D strm like(z_stream) Expansion stream
|
||||
D version * value options(*string) Version string
|
||||
D stream_size 10i 0 value Stream struct. size
|
||||
*
|
||||
D inflate PR 10I 0 extproc('inflate') Expand data
|
||||
D strm like(z_stream) Expansion stream
|
||||
D flush 10I 0 value Flush type required
|
||||
*
|
||||
D inflateEnd PR 10I 0 extproc('inflateEnd') Termin. expansion
|
||||
D strm like(z_stream) Expansion stream
|
||||
*
|
||||
**************************************************************************
|
||||
* Advanced function prototypes
|
||||
**************************************************************************
|
||||
*
|
||||
D deflateInit2 PR 10I 0 extproc('deflateInit2_') Init. compression
|
||||
D strm like(z_stream) Compression stream
|
||||
D level 10I 0 value Compression level
|
||||
D method 10I 0 value Compression method
|
||||
D windowBits 10I 0 value log2(window size)
|
||||
D memLevel 10I 0 value Mem/cmpress tradeoff
|
||||
D strategy 10I 0 value Compression stategy
|
||||
D version * value options(*string) Version string
|
||||
D stream_size 10i 0 value Stream struct. size
|
||||
*
|
||||
D deflateSetDictionary...
|
||||
D PR 10I 0 extproc('deflateSetDictionary') Init. dictionary
|
||||
D strm like(z_stream) Compression stream
|
||||
D dictionary 32767 const options(*varsize) Dictionary bytes
|
||||
D dictLength 10U 0 value Dictionary length
|
||||
*
|
||||
D deflateCopy PR 10I 0 extproc('deflateCopy') Compress strm 2 strm
|
||||
D dest like(z_stream) Destination stream
|
||||
D source like(z_stream) Source stream
|
||||
*
|
||||
D deflateReset PR 10I 0 extproc('deflateReset') End and init. stream
|
||||
D strm like(z_stream) Compression stream
|
||||
*
|
||||
D deflateParams PR 10I 0 extproc('deflateParams') Change level & strat
|
||||
D strm like(z_stream) Compression stream
|
||||
D level 10I 0 value Compression level
|
||||
D strategy 10I 0 value Compression stategy
|
||||
*
|
||||
D deflateBound PR 10U 0 extproc('deflateBound') Change level & strat
|
||||
D strm like(z_stream) Compression stream
|
||||
D sourcelen 10U 0 value Compression level
|
||||
*
|
||||
D deflatePrime PR 10I 0 extproc('deflatePrime') Change level & strat
|
||||
D strm like(z_stream) Compression stream
|
||||
D bits 10I 0 value Number of bits to insert
|
||||
D value 10I 0 value Bits to insert
|
||||
*
|
||||
D inflateInit2 PR 10I 0 extproc('inflateInit2_') Init. expansion
|
||||
D strm like(z_stream) Expansion stream
|
||||
D windowBits 10I 0 value log2(window size)
|
||||
D version * value options(*string) Version string
|
||||
D stream_size 10i 0 value Stream struct. size
|
||||
*
|
||||
D inflateSetDictionary...
|
||||
D PR 10I 0 extproc('inflateSetDictionary') Init. dictionary
|
||||
D strm like(z_stream) Expansion stream
|
||||
D dictionary 32767 const options(*varsize) Dictionary bytes
|
||||
D dictLength 10U 0 value Dictionary length
|
||||
*
|
||||
D inflateSync PR 10I 0 extproc('inflateSync') Sync. expansion
|
||||
D strm like(z_stream) Expansion stream
|
||||
*
|
||||
D inflateCopy PR 10I 0 extproc('inflateCopy')
|
||||
D dest like(z_stream) Destination stream
|
||||
D source like(z_stream) Source stream
|
||||
*
|
||||
D inflateReset PR 10I 0 extproc('inflateReset') End and init. stream
|
||||
D strm like(z_stream) Expansion stream
|
||||
*
|
||||
D inflateBackInit...
|
||||
D PR 10I 0 extproc('inflateBackInit_')
|
||||
D strm like(z_stream) Expansion stream
|
||||
D windowBits 10I 0 value Log2(buffer size)
|
||||
D window 32767 options(*varsize) Buffer
|
||||
D version * value options(*string) Version string
|
||||
D stream_size 10i 0 value Stream struct. size
|
||||
*
|
||||
D inflateBack PR 10I 0 extproc('inflateBack')
|
||||
D strm like(z_stream) Expansion stream
|
||||
D in * value procptr Input function
|
||||
D in_desc * value Input descriptor
|
||||
D out * value procptr Output function
|
||||
D out_desc * value Output descriptor
|
||||
*
|
||||
D inflateBackEnd PR 10I 0 extproc('inflateBackEnd')
|
||||
D strm like(z_stream) Expansion stream
|
||||
*
|
||||
D zlibCompileFlags...
|
||||
D PR 10U 0 extproc('zlibCompileFlags')
|
||||
*
|
||||
**************************************************************************
|
||||
* Checksum function prototypes
|
||||
**************************************************************************
|
||||
*
|
||||
D adler32 PR 10U 0 extproc('adler32') New checksum
|
||||
D adler 10U 0 value Old checksum
|
||||
D buf 32767 const options(*varsize) Bytes to accumulate
|
||||
D len 10U 0 value Buffer length
|
||||
*
|
||||
D crc32 PR 10U 0 extproc('crc32') New checksum
|
||||
D crc 10U 0 value Old checksum
|
||||
D buf 32767 const options(*varsize) Bytes to accumulate
|
||||
D len 10U 0 value Buffer length
|
||||
*
|
||||
**************************************************************************
|
||||
* Miscellaneous function prototypes
|
||||
**************************************************************************
|
||||
*
|
||||
D zError PR * extproc('zError') Error string
|
||||
D err 10I 0 value Error code
|
||||
*
|
||||
D inflateSyncPoint...
|
||||
D PR 10I 0 extproc('inflateSyncPoint')
|
||||
D strm like(z_stream) Expansion stream
|
||||
*
|
||||
D get_crc_table PR * extproc('get_crc_table') Ptr to ulongs
|
||||
*
|
||||
/endif
|
||||
@@ -0,0 +1,79 @@
|
||||
/* compress.c -- compress a memory buffer
|
||||
* Copyright (C) 1995-2003 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include "zlib.h"
|
||||
|
||||
/* ===========================================================================
|
||||
Compresses the source buffer into the destination buffer. The level
|
||||
parameter has the same meaning as in deflateInit. sourceLen is the byte
|
||||
length of the source buffer. Upon entry, destLen is the total size of the
|
||||
destination buffer, which must be at least 0.1% larger than sourceLen plus
|
||||
12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
|
||||
|
||||
compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
|
||||
memory, Z_BUF_ERROR if there was not enough room in the output buffer,
|
||||
Z_STREAM_ERROR if the level parameter is invalid.
|
||||
*/
|
||||
int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
int level;
|
||||
{
|
||||
z_stream stream;
|
||||
int err;
|
||||
|
||||
stream.next_in = (Bytef*)source;
|
||||
stream.avail_in = (uInt)sourceLen;
|
||||
#ifdef MAXSEG_64K
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
|
||||
#endif
|
||||
stream.next_out = dest;
|
||||
stream.avail_out = (uInt)*destLen;
|
||||
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
|
||||
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
|
||||
err = deflateInit(&stream, level);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
err = deflate(&stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
deflateEnd(&stream);
|
||||
return err == Z_OK ? Z_BUF_ERROR : err;
|
||||
}
|
||||
*destLen = stream.total_out;
|
||||
|
||||
err = deflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
*/
|
||||
int ZEXPORT compress (dest, destLen, source, sourceLen)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
{
|
||||
return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
If the default memLevel or windowBits for deflateInit() is changed, then
|
||||
this function needs to be updated.
|
||||
*/
|
||||
uLong ZEXPORT compressBound (sourceLen)
|
||||
uLong sourceLen;
|
||||
{
|
||||
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11;
|
||||
}
|
||||
+446
@@ -0,0 +1,446 @@
|
||||
#!/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"
|
||||
#
|
||||
# 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
|
||||
#
|
||||
# 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}"
|
||||
VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\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 rc"}
|
||||
RANLIB=${RANLIB-"ranlib"}
|
||||
prefix=${prefix-/usr/local}
|
||||
exec_prefix=${exec_prefix-'${prefix}'}
|
||||
libdir=${libdir-'${exec_prefix}/lib'}
|
||||
includedir=${includedir-'${prefix}/include'}
|
||||
mandir=${mandir-'${prefix}/share/man'}
|
||||
shared_ext='.so'
|
||||
shared=0
|
||||
gcc=0
|
||||
old_cc="$CC"
|
||||
old_cflags="$CFLAGS"
|
||||
|
||||
while test $# -ge 1
|
||||
do
|
||||
case "$1" in
|
||||
-h* | --h*)
|
||||
echo 'usage:'
|
||||
echo ' configure [--shared] [--prefix=PREFIX] [--exec_prefix=EXPREFIX]'
|
||||
echo ' [--libdir=LIBDIR] [--includedir=INCLUDEDIR]'
|
||||
exit 0;;
|
||||
-p*=* | --p*=*) prefix=`echo $1 | sed 's/[-a-z_]*=//'`; shift;;
|
||||
-e*=* | --e*=*) 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;;
|
||||
-p* | --p*) prefix="$2"; shift; shift;;
|
||||
-e* | --e*) exec_prefix="$2"; shift; shift;;
|
||||
-l* | --l*) libdir="$2"; shift; shift;;
|
||||
-i* | --i*) includedir="$2"; shift; shift;;
|
||||
-s* | --s*) shared=1; shift;;
|
||||
*) echo "unknown option: $1"; echo "$0 --help for help"; exit 1;;
|
||||
esac
|
||||
done
|
||||
|
||||
test=ztest$$
|
||||
cat > $test.c <<EOF
|
||||
extern int getchar();
|
||||
int hello() {return getchar();}
|
||||
EOF
|
||||
|
||||
test -z "$CC" && echo Checking for gcc...
|
||||
cc=${CC-gcc}
|
||||
cflags=${CFLAGS-"-O3"}
|
||||
# to force the asm version use: CFLAGS="-O3 -DASMV" ./configure
|
||||
case "$cc" in
|
||||
*gcc*) gcc=1;;
|
||||
esac
|
||||
|
||||
if test "$gcc" -eq 1 && ($cc -c $cflags $test.c) 2>/dev/null; then
|
||||
CC="$cc"
|
||||
SFLAGS=${CFLAGS-"-fPIC -O3"}
|
||||
CFLAGS="$cflags"
|
||||
case `(uname -s || echo unknown) 2>/dev/null` in
|
||||
Linux | linux | GNU | GNU/*) LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1"};;
|
||||
CYGWIN* | Cygwin* | cygwin* | OS/2* )
|
||||
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"};;
|
||||
HP-UX*) LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"}
|
||||
shared_ext='.sl'
|
||||
SHAREDLIB='libz.sl';;
|
||||
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"};;
|
||||
esac
|
||||
else
|
||||
# find system name and corresponding cc options
|
||||
CC=${CC-cc}
|
||||
case `(uname -sr || echo unknown) 2>/dev/null` in
|
||||
HP-UX*) SFLAGS=${CFLAGS-"-O +z"}
|
||||
CFLAGS=${CFLAGS-"-O"}
|
||||
# LDSHARED=${LDSHARED-"ld -b +vnocompatwarnings"}
|
||||
LDSHARED=${LDSHARED-"ld -b"}
|
||||
shared_ext='.sl'
|
||||
SHAREDLIB='libz.sl';;
|
||||
IRIX*) SFLAGS=${CFLAGS-"-ansi -O2 -rpath ."}
|
||||
CFLAGS=${CFLAGS-"-ansi -O2"}
|
||||
LDSHARED=${LDSHARED-"cc -shared"};;
|
||||
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"};;
|
||||
OSF1*) SFLAGS=${CFLAGS-"-O -std1"}
|
||||
CFLAGS=${CFLAGS-"-O -std1"}
|
||||
LDSHARED=${LDSHARED-"cc -shared"};;
|
||||
QNX*) SFLAGS=${CFLAGS-"-4 -O"}
|
||||
CFLAGS=${CFLAGS-"-4 -O"}
|
||||
LDSHARED=${LDSHARED-"cc"}
|
||||
RANLIB=${RANLIB-"true"}
|
||||
AR="cc -A";;
|
||||
SCO_SV\ 3.2*) SFLAGS=${CFLAGS-"-O3 -dy -KPIC "}
|
||||
CFLAGS=${CFLAGS-"-O3"}
|
||||
LDSHARED=${LDSHARED-"cc -dy -KPIC -G"};;
|
||||
SunOS\ 5*) SFLAGS=${CFLAGS-"-fast -xcg89 -KPIC -R."}
|
||||
CFLAGS=${CFLAGS-"-fast -xcg89"}
|
||||
LDSHARED=${LDSHARED-"cc -G"};;
|
||||
SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"}
|
||||
CFLAGS=${CFLAGS-"-O2"}
|
||||
LDSHARED=${LDSHARED-"ld"};;
|
||||
SunStudio\ 9*) SFLAGS=${CFLAGS-"-DUSE_MMAP -fast -xcode=pic32 -xtarget=ultra3 -xarch=v9b"}
|
||||
CFLAGS=${CFLAGS-"-DUSE_MMAP -fast -xtarget=ultra3 -xarch=v9b"}
|
||||
LDSHARED=${LDSHARED-"cc -xarch=v9b"};;
|
||||
UNIX_System_V\ 4.2.0)
|
||||
SFLAGS=${CFLAGS-"-KPIC -O"}
|
||||
CFLAGS=${CFLAGS-"-O"}
|
||||
LDSHARED=${LDSHARED-"cc -G"};;
|
||||
UNIX_SV\ 4.2MP)
|
||||
SFLAGS=${CFLAGS-"-Kconform_pic -O"}
|
||||
CFLAGS=${CFLAGS-"-O"}
|
||||
LDSHARED=${LDSHARED-"cc -G"};;
|
||||
OpenUNIX\ 5)
|
||||
SFLAGS=${CFLAGS-"-KPIC -O"}
|
||||
CFLAGS=${CFLAGS-"-O"}
|
||||
LDSHARED=${LDSHARED-"cc -G"};;
|
||||
AIX*) # Courtesy of dbakker@arrayasolutions.com
|
||||
SFLAGS=${CFLAGS-"-O -qmaxmem=8192"}
|
||||
CFLAGS=${CFLAGS-"-O -qmaxmem=8192"}
|
||||
LDSHARED=${LDSHARED-"xlc -G"};;
|
||||
# send working options for other systems to support@gzip.org
|
||||
*) SFLAGS=${CFLAGS-"-O"}
|
||||
CFLAGS=${CFLAGS-"-O"}
|
||||
LDSHARED=${LDSHARED-"cc -shared"};;
|
||||
esac
|
||||
fi
|
||||
|
||||
SHAREDLIB=${SHAREDLIB-"libz$shared_ext"}
|
||||
SHAREDLIBV=${SHAREDLIBV-"libz$shared_ext.$VER"}
|
||||
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`" = "" &&
|
||||
test "`($LDSHARED -o $test$shared_ext $test.o) 2>&1`" = ""; then
|
||||
CFLAGS="$SFLAGS"
|
||||
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 'No shared library support; try without defining CC and CFLAGS'
|
||||
shared=0;
|
||||
fi
|
||||
fi
|
||||
if test $shared -eq 0; then
|
||||
LDSHARED="$CC"
|
||||
echo Building static library $LIBS version $VER with $CC.
|
||||
else
|
||||
LDFLAGS="-L. ${SHAREDLIBV}"
|
||||
fi
|
||||
|
||||
cat > $test.c <<EOF
|
||||
#include <unistd.h>
|
||||
int main() { return 0; }
|
||||
EOF
|
||||
if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
|
||||
sed < zconf.in.h "/HAVE_UNISTD_H/s%0%1%" > zconf.h
|
||||
echo "Checking for unistd.h... Yes."
|
||||
else
|
||||
cp -p zconf.in.h zconf.h
|
||||
echo "Checking for unistd.h... No."
|
||||
fi
|
||||
|
||||
cat > $test.c <<EOF
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "zconf.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifndef STDC
|
||||
choke me
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
|
||||
if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
|
||||
echo "Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf()"
|
||||
|
||||
cat > $test.c <<EOF
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
int mytest(char *fmt, ...)
|
||||
{
|
||||
char buf[20];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
return (mytest("Hello%d\n", 1));
|
||||
}
|
||||
EOF
|
||||
|
||||
if test "`($CC $CFLAGS -o $test $test.c) 2>&1`" = ""; then
|
||||
echo "Checking for vsnprintf() in stdio.h... Yes."
|
||||
|
||||
cat >$test.c <<EOF
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
int mytest(char *fmt, ...)
|
||||
{
|
||||
int n;
|
||||
char buf[20];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
n = vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
return n;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
return (mytest("Hello%d\n", 1));
|
||||
}
|
||||
EOF
|
||||
|
||||
if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
|
||||
echo "Checking for return value of vsnprintf()... Yes."
|
||||
else
|
||||
CFLAGS="$CFLAGS -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"
|
||||
echo " vulnerabilities."
|
||||
fi
|
||||
else
|
||||
CFLAGS="$CFLAGS -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"
|
||||
echo " vulnerabilities."
|
||||
|
||||
cat >$test.c <<EOF
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
int mytest(char *fmt, ...)
|
||||
{
|
||||
int n;
|
||||
char buf[20];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
n = vsprintf(buf, fmt, ap);
|
||||
va_end(ap);
|
||||
return n;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
return (mytest("Hello%d\n", 1));
|
||||
}
|
||||
EOF
|
||||
|
||||
if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
|
||||
echo "Checking for return value of vsprintf()... Yes."
|
||||
else
|
||||
CFLAGS="$CFLAGS -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"
|
||||
echo " vulnerabilities."
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "Checking whether to use vs[n]printf() or s[n]printf()... using s[n]printf()"
|
||||
|
||||
cat >$test.c <<EOF
|
||||
#include <stdio.h>
|
||||
|
||||
int mytest()
|
||||
{
|
||||
char buf[20];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s", "foo");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
return (mytest());
|
||||
}
|
||||
EOF
|
||||
|
||||
if test "`($CC $CFLAGS -o $test $test.c) 2>&1`" = ""; then
|
||||
echo "Checking for snprintf() in stdio.h... Yes."
|
||||
|
||||
cat >$test.c <<EOF
|
||||
#include <stdio.h>
|
||||
|
||||
int mytest()
|
||||
{
|
||||
char buf[20];
|
||||
|
||||
return snprintf(buf, sizeof(buf), "%s", "foo");
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
return (mytest());
|
||||
}
|
||||
EOF
|
||||
|
||||
if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
|
||||
echo "Checking for return value of snprintf()... Yes."
|
||||
else
|
||||
CFLAGS="$CFLAGS -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"
|
||||
echo " vulnerabilities."
|
||||
fi
|
||||
else
|
||||
CFLAGS="$CFLAGS -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"
|
||||
echo " vulnerabilities."
|
||||
|
||||
cat >$test.c <<EOF
|
||||
#include <stdio.h>
|
||||
|
||||
int mytest()
|
||||
{
|
||||
char buf[20];
|
||||
|
||||
return sprintf(buf, "%s", "foo");
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
return (mytest());
|
||||
}
|
||||
EOF
|
||||
|
||||
if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
|
||||
echo "Checking for return value of sprintf()... Yes."
|
||||
else
|
||||
CFLAGS="$CFLAGS -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"
|
||||
echo " vulnerabilities."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
cat >$test.c <<EOF
|
||||
#include <errno.h>
|
||||
int main() { return 0; }
|
||||
EOF
|
||||
if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
|
||||
echo "Checking for errno.h... Yes."
|
||||
else
|
||||
echo "Checking for errno.h... No."
|
||||
CFLAGS="$CFLAGS -DNO_ERRNO_H"
|
||||
fi
|
||||
|
||||
cat > $test.c <<EOF
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
caddr_t hello() {
|
||||
return mmap((caddr_t)0, (off_t)0, PROT_READ, MAP_SHARED, 0, (off_t)0);
|
||||
}
|
||||
EOF
|
||||
if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
|
||||
CFLAGS="$CFLAGS -DUSE_MMAP"
|
||||
echo Checking for mmap support... Yes.
|
||||
else
|
||||
echo Checking for mmap support... No.
|
||||
fi
|
||||
|
||||
CPP=${CPP-"$CC -E"}
|
||||
case $CFLAGS in
|
||||
*ASMV*)
|
||||
if test "`nm $test.o | grep _hello`" = ""; then
|
||||
CPP="$CPP -DNO_UNDERLINE"
|
||||
echo Checking for underline in external names... No.
|
||||
else
|
||||
echo Checking for underline in external names... Yes.
|
||||
fi;;
|
||||
esac
|
||||
|
||||
rm -f $test.[co] $test $test$shared_ext
|
||||
|
||||
# udpate Makefile
|
||||
sed < Makefile.in "
|
||||
/^CC *=/s#=.*#=$CC#
|
||||
/^CFLAGS *=/s#=.*#=$CFLAGS#
|
||||
/^CPP *=/s#=.*#=$CPP#
|
||||
/^LDSHARED *=/s#=.*#=$LDSHARED#
|
||||
/^LIBS *=/s#=.*#=$LIBS#
|
||||
/^SHAREDLIB *=/s#=.*#=$SHAREDLIB#
|
||||
/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV#
|
||||
/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM#
|
||||
/^AR *=/s#=.*#=$AR#
|
||||
/^RANLIB *=/s#=.*#=$RANLIB#
|
||||
/^EXE *=/s#=.*#=$EXE#
|
||||
/^prefix *=/s#=.*#=$prefix#
|
||||
/^exec_prefix *=/s#=.*#=$exec_prefix#
|
||||
/^libdir *=/s#=.*#=$libdir#
|
||||
/^includedir *=/s#=.*#=$includedir#
|
||||
/^mandir *=/s#=.*#=$mandir#
|
||||
/^LDFLAGS *=/s#=.*#=$LDFLAGS#
|
||||
" > Makefile
|
||||
@@ -0,0 +1,67 @@
|
||||
All files under this contrib directory are UNSUPPORTED. There were
|
||||
provided by users of zlib and were not tested by the authors of zlib.
|
||||
Use at your own risk. Please contact the authors of the contributions
|
||||
for help about these, not the zlib authors. Thanks.
|
||||
|
||||
|
||||
ada/ by Dmitriy Anisimkov <anisimkov@yahoo.com>
|
||||
Support for Ada
|
||||
See http://zlib-ada.sourceforge.net/
|
||||
|
||||
asm586/
|
||||
asm686/ by Brian Raiter <breadbox@muppetlabs.com>
|
||||
asm code for Pentium and PPro/PII, using the AT&T (GNU as) syntax
|
||||
See http://www.muppetlabs.com/~breadbox/software/assembly.html
|
||||
|
||||
blast/ by Mark Adler <madler@alumni.caltech.edu>
|
||||
Decompressor for output of PKWare Data Compression Library (DCL)
|
||||
|
||||
delphi/ by Cosmin Truta <cosmint@cs.ubbcluj.ro>
|
||||
Support for Delphi and C++ Builder
|
||||
|
||||
dotzlib/ by Henrik Ravn <henrik@ravn.com>
|
||||
Support for Microsoft .Net and Visual C++ .Net
|
||||
|
||||
infback9/ by Mark Adler <madler@alumni.caltech.edu>
|
||||
Unsupported diffs to infback to decode the deflate64 format
|
||||
|
||||
inflate86/ by Chris Anderson <christop@charm.net>
|
||||
Tuned x86 gcc asm code to replace inflate_fast()
|
||||
|
||||
iostream/ by Kevin Ruland <kevin@rodin.wustl.edu>
|
||||
A C++ I/O streams interface to the zlib gz* functions
|
||||
|
||||
iostream2/ by Tyge Løvset <Tyge.Lovset@cmr.no>
|
||||
Another C++ I/O streams interface
|
||||
|
||||
iostream3/ by Ludwig Schwardt <schwardt@sun.ac.za>
|
||||
and Kevin Ruland <kevin@rodin.wustl.edu>
|
||||
Yet another C++ I/O streams interface
|
||||
|
||||
masm686/ by Dan Higdon <hdan@kinesoft.com>
|
||||
and Chuck Walbourn <chuckw@kinesoft.com>
|
||||
asm code for Pentium Pro/PII, using the MASM syntax
|
||||
|
||||
masmx86/ by Gilles Vollant <info@winimage.com>
|
||||
x86 asm code to replace longest_match() and inflate_fast(),
|
||||
for Visual C++ and MASM
|
||||
|
||||
minizip/ by Gilles Vollant <info@winimage.com>
|
||||
Mini zip and unzip based on zlib
|
||||
See http://www.winimage.com/zLibDll/unzip.html
|
||||
|
||||
pascal/ by Bob Dellaca <bobdl@xtra.co.nz> et al.
|
||||
Support for Pascal
|
||||
|
||||
puff/ by Mark Adler <madler@alumni.caltech.edu>
|
||||
Small, low memory usage inflate. Also serves to provide an
|
||||
unambiguous description of the deflate format.
|
||||
|
||||
testzlib/ by Gilles Vollant <info@winimage.com>
|
||||
Example of the use of zlib
|
||||
|
||||
untgz/ by Pedro A. Aranda Gutierrez <paag@tid.es>
|
||||
A very simple tar.gz file extractor using zlib
|
||||
|
||||
vstudio/ by Gilles Vollant <info@winimage.com>
|
||||
Building a minizip-enhanced zlib with Microsoft Visual Studio
|
||||
@@ -0,0 +1,106 @@
|
||||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2004 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
--
|
||||
-- $Id$
|
||||
|
||||
-- This demo program provided by Dr Steve Sangwine <sjs@essex.ac.uk>
|
||||
--
|
||||
-- Demonstration of a problem with Zlib-Ada (already fixed) when a buffer
|
||||
-- of exactly the correct size is used for decompressed data, and the last
|
||||
-- few bytes passed in to Zlib are checksum bytes.
|
||||
|
||||
-- This program compresses a string of text, and then decompresses the
|
||||
-- compressed text into a buffer of the same size as the original text.
|
||||
|
||||
with Ada.Streams; use Ada.Streams;
|
||||
with Ada.Text_IO;
|
||||
|
||||
with ZLib; use ZLib;
|
||||
|
||||
procedure Buffer_Demo is
|
||||
EOL : Character renames ASCII.LF;
|
||||
Text : constant String
|
||||
:= "Four score and seven years ago our fathers brought forth," & EOL &
|
||||
"upon this continent, a new nation, conceived in liberty," & EOL &
|
||||
"and dedicated to the proposition that `all men are created equal'.";
|
||||
|
||||
Source : Stream_Element_Array (1 .. Text'Length);
|
||||
for Source'Address use Text'Address;
|
||||
|
||||
begin
|
||||
Ada.Text_IO.Put (Text);
|
||||
Ada.Text_IO.New_Line;
|
||||
Ada.Text_IO.Put_Line
|
||||
("Uncompressed size : " & Positive'Image (Text'Length) & " bytes");
|
||||
|
||||
declare
|
||||
Compressed_Data : Stream_Element_Array (1 .. Text'Length);
|
||||
L : Stream_Element_Offset;
|
||||
begin
|
||||
Compress : declare
|
||||
Compressor : Filter_Type;
|
||||
I : Stream_Element_Offset;
|
||||
begin
|
||||
Deflate_Init (Compressor);
|
||||
|
||||
-- Compress the whole of T at once.
|
||||
|
||||
Translate (Compressor, Source, I, Compressed_Data, L, Finish);
|
||||
pragma Assert (I = Source'Last);
|
||||
|
||||
Close (Compressor);
|
||||
|
||||
Ada.Text_IO.Put_Line
|
||||
("Compressed size : "
|
||||
& Stream_Element_Offset'Image (L) & " bytes");
|
||||
end Compress;
|
||||
|
||||
-- Now we decompress the data, passing short blocks of data to Zlib
|
||||
-- (because this demonstrates the problem - the last block passed will
|
||||
-- contain checksum information and there will be no output, only a
|
||||
-- check inside Zlib that the checksum is correct).
|
||||
|
||||
Decompress : declare
|
||||
Decompressor : Filter_Type;
|
||||
|
||||
Uncompressed_Data : Stream_Element_Array (1 .. Text'Length);
|
||||
|
||||
Block_Size : constant := 4;
|
||||
-- This makes sure that the last block contains
|
||||
-- only Adler checksum data.
|
||||
|
||||
P : Stream_Element_Offset := Compressed_Data'First - 1;
|
||||
O : Stream_Element_Offset;
|
||||
begin
|
||||
Inflate_Init (Decompressor);
|
||||
|
||||
loop
|
||||
Translate
|
||||
(Decompressor,
|
||||
Compressed_Data
|
||||
(P + 1 .. Stream_Element_Offset'Min (P + Block_Size, L)),
|
||||
P,
|
||||
Uncompressed_Data
|
||||
(Total_Out (Decompressor) + 1 .. Uncompressed_Data'Last),
|
||||
O,
|
||||
No_Flush);
|
||||
|
||||
Ada.Text_IO.Put_Line
|
||||
("Total in : " & Count'Image (Total_In (Decompressor)) &
|
||||
", out : " & Count'Image (Total_Out (Decompressor)));
|
||||
|
||||
exit when P = L;
|
||||
end loop;
|
||||
|
||||
Ada.Text_IO.New_Line;
|
||||
Ada.Text_IO.Put_Line
|
||||
("Decompressed text matches original text : "
|
||||
& Boolean'Image (Uncompressed_Data = Source));
|
||||
end Decompress;
|
||||
end;
|
||||
end Buffer_Demo;
|
||||
@@ -0,0 +1,156 @@
|
||||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
-- Continuous test for ZLib multithreading. If the test would fail
|
||||
-- we should provide thread safe allocation routines for the Z_Stream.
|
||||
--
|
||||
-- $Id$
|
||||
|
||||
with ZLib;
|
||||
with Ada.Streams;
|
||||
with Ada.Numerics.Discrete_Random;
|
||||
with Ada.Text_IO;
|
||||
with Ada.Exceptions;
|
||||
with Ada.Task_Identification;
|
||||
|
||||
procedure MTest is
|
||||
use Ada.Streams;
|
||||
use ZLib;
|
||||
|
||||
Stop : Boolean := False;
|
||||
|
||||
pragma Atomic (Stop);
|
||||
|
||||
subtype Visible_Symbols is Stream_Element range 16#20# .. 16#7E#;
|
||||
|
||||
package Random_Elements is
|
||||
new Ada.Numerics.Discrete_Random (Visible_Symbols);
|
||||
|
||||
task type Test_Task;
|
||||
|
||||
task body Test_Task is
|
||||
Buffer : Stream_Element_Array (1 .. 100_000);
|
||||
Gen : Random_Elements.Generator;
|
||||
|
||||
Buffer_First : Stream_Element_Offset;
|
||||
Compare_First : Stream_Element_Offset;
|
||||
|
||||
Deflate : Filter_Type;
|
||||
Inflate : Filter_Type;
|
||||
|
||||
procedure Further (Item : in Stream_Element_Array);
|
||||
|
||||
procedure Read_Buffer
|
||||
(Item : out Ada.Streams.Stream_Element_Array;
|
||||
Last : out Ada.Streams.Stream_Element_Offset);
|
||||
|
||||
-------------
|
||||
-- Further --
|
||||
-------------
|
||||
|
||||
procedure Further (Item : in Stream_Element_Array) is
|
||||
|
||||
procedure Compare (Item : in Stream_Element_Array);
|
||||
|
||||
-------------
|
||||
-- Compare --
|
||||
-------------
|
||||
|
||||
procedure Compare (Item : in Stream_Element_Array) is
|
||||
Next_First : Stream_Element_Offset := Compare_First + Item'Length;
|
||||
begin
|
||||
if Buffer (Compare_First .. Next_First - 1) /= Item then
|
||||
raise Program_Error;
|
||||
end if;
|
||||
|
||||
Compare_First := Next_First;
|
||||
end Compare;
|
||||
|
||||
procedure Compare_Write is new ZLib.Write (Write => Compare);
|
||||
begin
|
||||
Compare_Write (Inflate, Item, No_Flush);
|
||||
end Further;
|
||||
|
||||
-----------------
|
||||
-- Read_Buffer --
|
||||
-----------------
|
||||
|
||||
procedure Read_Buffer
|
||||
(Item : out Ada.Streams.Stream_Element_Array;
|
||||
Last : out Ada.Streams.Stream_Element_Offset)
|
||||
is
|
||||
Buff_Diff : Stream_Element_Offset := Buffer'Last - Buffer_First;
|
||||
Next_First : Stream_Element_Offset;
|
||||
begin
|
||||
if Item'Length <= Buff_Diff then
|
||||
Last := Item'Last;
|
||||
|
||||
Next_First := Buffer_First + Item'Length;
|
||||
|
||||
Item := Buffer (Buffer_First .. Next_First - 1);
|
||||
|
||||
Buffer_First := Next_First;
|
||||
else
|
||||
Last := Item'First + Buff_Diff;
|
||||
Item (Item'First .. Last) := Buffer (Buffer_First .. Buffer'Last);
|
||||
Buffer_First := Buffer'Last + 1;
|
||||
end if;
|
||||
end Read_Buffer;
|
||||
|
||||
procedure Translate is new Generic_Translate
|
||||
(Data_In => Read_Buffer,
|
||||
Data_Out => Further);
|
||||
|
||||
begin
|
||||
Random_Elements.Reset (Gen);
|
||||
|
||||
Buffer := (others => 20);
|
||||
|
||||
Main : loop
|
||||
for J in Buffer'Range loop
|
||||
Buffer (J) := Random_Elements.Random (Gen);
|
||||
|
||||
Deflate_Init (Deflate);
|
||||
Inflate_Init (Inflate);
|
||||
|
||||
Buffer_First := Buffer'First;
|
||||
Compare_First := Buffer'First;
|
||||
|
||||
Translate (Deflate);
|
||||
|
||||
if Compare_First /= Buffer'Last + 1 then
|
||||
raise Program_Error;
|
||||
end if;
|
||||
|
||||
Ada.Text_IO.Put_Line
|
||||
(Ada.Task_Identification.Image
|
||||
(Ada.Task_Identification.Current_Task)
|
||||
& Stream_Element_Offset'Image (J)
|
||||
& ZLib.Count'Image (Total_Out (Deflate)));
|
||||
|
||||
Close (Deflate);
|
||||
Close (Inflate);
|
||||
|
||||
exit Main when Stop;
|
||||
end loop;
|
||||
end loop Main;
|
||||
exception
|
||||
when E : others =>
|
||||
Ada.Text_IO.Put_Line (Ada.Exceptions.Exception_Information (E));
|
||||
Stop := True;
|
||||
end Test_Task;
|
||||
|
||||
Test : array (1 .. 4) of Test_Task;
|
||||
|
||||
pragma Unreferenced (Test);
|
||||
|
||||
Dummy : Character;
|
||||
|
||||
begin
|
||||
Ada.Text_IO.Get_Immediate (Dummy);
|
||||
Stop := True;
|
||||
end MTest;
|
||||
@@ -0,0 +1,156 @@
|
||||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id$
|
||||
|
||||
-- Test/demo program for the generic read interface.
|
||||
|
||||
with Ada.Numerics.Discrete_Random;
|
||||
with Ada.Streams;
|
||||
with Ada.Text_IO;
|
||||
|
||||
with ZLib;
|
||||
|
||||
procedure Read is
|
||||
|
||||
use Ada.Streams;
|
||||
|
||||
------------------------------------
|
||||
-- Test configuration parameters --
|
||||
------------------------------------
|
||||
|
||||
File_Size : Stream_Element_Offset := 100_000;
|
||||
|
||||
Continuous : constant Boolean := False;
|
||||
-- If this constant is True, the test would be repeated again and again,
|
||||
-- with increment File_Size for every iteration.
|
||||
|
||||
Header : constant ZLib.Header_Type := ZLib.Default;
|
||||
-- Do not use Header other than Default in ZLib versions 1.1.4 and older.
|
||||
|
||||
Init_Random : constant := 8;
|
||||
-- We are using the same random sequence, in case of we catch bug,
|
||||
-- so we would be able to reproduce it.
|
||||
|
||||
-- End --
|
||||
|
||||
Pack_Size : Stream_Element_Offset;
|
||||
Offset : Stream_Element_Offset;
|
||||
|
||||
Filter : ZLib.Filter_Type;
|
||||
|
||||
subtype Visible_Symbols
|
||||
is Stream_Element range 16#20# .. 16#7E#;
|
||||
|
||||
package Random_Elements is new
|
||||
Ada.Numerics.Discrete_Random (Visible_Symbols);
|
||||
|
||||
Gen : Random_Elements.Generator;
|
||||
Period : constant Stream_Element_Offset := 200;
|
||||
-- Period constant variable for random generator not to be very random.
|
||||
-- Bigger period, harder random.
|
||||
|
||||
Read_Buffer : Stream_Element_Array (1 .. 2048);
|
||||
Read_First : Stream_Element_Offset;
|
||||
Read_Last : Stream_Element_Offset;
|
||||
|
||||
procedure Reset;
|
||||
|
||||
procedure Read
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset);
|
||||
-- this procedure is for generic instantiation of
|
||||
-- ZLib.Read
|
||||
-- reading data from the File_In.
|
||||
|
||||
procedure Read is new ZLib.Read
|
||||
(Read,
|
||||
Read_Buffer,
|
||||
Rest_First => Read_First,
|
||||
Rest_Last => Read_Last);
|
||||
|
||||
----------
|
||||
-- Read --
|
||||
----------
|
||||
|
||||
procedure Read
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset) is
|
||||
begin
|
||||
Last := Stream_Element_Offset'Min
|
||||
(Item'Last,
|
||||
Item'First + File_Size - Offset);
|
||||
|
||||
for J in Item'First .. Last loop
|
||||
if J < Item'First + Period then
|
||||
Item (J) := Random_Elements.Random (Gen);
|
||||
else
|
||||
Item (J) := Item (J - Period);
|
||||
end if;
|
||||
|
||||
Offset := Offset + 1;
|
||||
end loop;
|
||||
end Read;
|
||||
|
||||
-----------
|
||||
-- Reset --
|
||||
-----------
|
||||
|
||||
procedure Reset is
|
||||
begin
|
||||
Random_Elements.Reset (Gen, Init_Random);
|
||||
Pack_Size := 0;
|
||||
Offset := 1;
|
||||
Read_First := Read_Buffer'Last + 1;
|
||||
Read_Last := Read_Buffer'Last;
|
||||
end Reset;
|
||||
|
||||
begin
|
||||
Ada.Text_IO.Put_Line ("ZLib " & ZLib.Version);
|
||||
|
||||
loop
|
||||
for Level in ZLib.Compression_Level'Range loop
|
||||
|
||||
Ada.Text_IO.Put ("Level ="
|
||||
& ZLib.Compression_Level'Image (Level));
|
||||
|
||||
-- Deflate using generic instantiation.
|
||||
|
||||
ZLib.Deflate_Init
|
||||
(Filter,
|
||||
Level,
|
||||
Header => Header);
|
||||
|
||||
Reset;
|
||||
|
||||
Ada.Text_IO.Put
|
||||
(Stream_Element_Offset'Image (File_Size) & " ->");
|
||||
|
||||
loop
|
||||
declare
|
||||
Buffer : Stream_Element_Array (1 .. 1024);
|
||||
Last : Stream_Element_Offset;
|
||||
begin
|
||||
Read (Filter, Buffer, Last);
|
||||
|
||||
Pack_Size := Pack_Size + Last - Buffer'First + 1;
|
||||
|
||||
exit when Last < Buffer'Last;
|
||||
end;
|
||||
end loop;
|
||||
|
||||
Ada.Text_IO.Put_Line (Stream_Element_Offset'Image (Pack_Size));
|
||||
|
||||
ZLib.Close (Filter);
|
||||
end loop;
|
||||
|
||||
exit when not Continuous;
|
||||
|
||||
File_Size := File_Size + 1;
|
||||
end loop;
|
||||
end Read;
|
||||
@@ -0,0 +1,65 @@
|
||||
ZLib for Ada thick binding (ZLib.Ada)
|
||||
Release 1.3
|
||||
|
||||
ZLib.Ada is a thick binding interface to the popular ZLib data
|
||||
compression library, available at http://www.gzip.org/zlib/.
|
||||
It provides Ada-style access to the ZLib C library.
|
||||
|
||||
|
||||
Here are the main changes since ZLib.Ada 1.2:
|
||||
|
||||
- Attension: ZLib.Read generic routine have a initialization requirement
|
||||
for Read_Last parameter now. It is a bit incompartible with previous version,
|
||||
but extends functionality, we could use new parameters Allow_Read_Some and
|
||||
Flush now.
|
||||
|
||||
- Added Is_Open routines to ZLib and ZLib.Streams packages.
|
||||
|
||||
- Add pragma Assert to check Stream_Element is 8 bit.
|
||||
|
||||
- Fix extraction to buffer with exact known decompressed size. Error reported by
|
||||
Steve Sangwine.
|
||||
|
||||
- Fix definition of ULong (changed to unsigned_long), fix regression on 64 bits
|
||||
computers. Patch provided by Pascal Obry.
|
||||
|
||||
- Add Status_Error exception definition.
|
||||
|
||||
- Add pragma Assertion that Ada.Streams.Stream_Element size is 8 bit.
|
||||
|
||||
|
||||
How to build ZLib.Ada under GNAT
|
||||
|
||||
You should have the ZLib library already build on your computer, before
|
||||
building ZLib.Ada. Make the directory of ZLib.Ada sources current and
|
||||
issue the command:
|
||||
|
||||
gnatmake test -largs -L<directory where libz.a is> -lz
|
||||
|
||||
Or use the GNAT project file build for GNAT 3.15 or later:
|
||||
|
||||
gnatmake -Pzlib.gpr -L<directory where libz.a is>
|
||||
|
||||
|
||||
How to build ZLib.Ada under Aonix ObjectAda for Win32 7.2.2
|
||||
|
||||
1. Make a project with all *.ads and *.adb files from the distribution.
|
||||
2. Build the libz.a library from the ZLib C sources.
|
||||
3. Rename libz.a to z.lib.
|
||||
4. Add the library z.lib to the project.
|
||||
5. Add the libc.lib library from the ObjectAda distribution to the project.
|
||||
6. Build the executable using test.adb as a main procedure.
|
||||
|
||||
|
||||
How to use ZLib.Ada
|
||||
|
||||
The source files test.adb and read.adb are small demo programs that show
|
||||
the main functionality of ZLib.Ada.
|
||||
|
||||
The routines from the package specifications are commented.
|
||||
|
||||
|
||||
Homepage: http://zlib-ada.sourceforge.net/
|
||||
Author: Dmitriy Anisimkov <anisimkov@yahoo.com>
|
||||
|
||||
Contributors: Pascal Obry <pascal@obry.org>, Steve Sangwine <sjs@essex.ac.uk>
|
||||
@@ -0,0 +1,463 @@
|
||||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id$
|
||||
|
||||
-- The program has a few aims.
|
||||
-- 1. Test ZLib.Ada95 thick binding functionality.
|
||||
-- 2. Show the example of use main functionality of the ZLib.Ada95 binding.
|
||||
-- 3. Build this program automatically compile all ZLib.Ada95 packages under
|
||||
-- GNAT Ada95 compiler.
|
||||
|
||||
with ZLib.Streams;
|
||||
with Ada.Streams.Stream_IO;
|
||||
with Ada.Numerics.Discrete_Random;
|
||||
|
||||
with Ada.Text_IO;
|
||||
|
||||
with Ada.Calendar;
|
||||
|
||||
procedure Test is
|
||||
|
||||
use Ada.Streams;
|
||||
use Stream_IO;
|
||||
|
||||
------------------------------------
|
||||
-- Test configuration parameters --
|
||||
------------------------------------
|
||||
|
||||
File_Size : Count := 100_000;
|
||||
Continuous : constant Boolean := False;
|
||||
|
||||
Header : constant ZLib.Header_Type := ZLib.Default;
|
||||
-- ZLib.None;
|
||||
-- ZLib.Auto;
|
||||
-- ZLib.GZip;
|
||||
-- Do not use Header other then Default in ZLib versions 1.1.4
|
||||
-- and older.
|
||||
|
||||
Strategy : constant ZLib.Strategy_Type := ZLib.Default_Strategy;
|
||||
Init_Random : constant := 10;
|
||||
|
||||
-- End --
|
||||
|
||||
In_File_Name : constant String := "testzlib.in";
|
||||
-- Name of the input file
|
||||
|
||||
Z_File_Name : constant String := "testzlib.zlb";
|
||||
-- Name of the compressed file.
|
||||
|
||||
Out_File_Name : constant String := "testzlib.out";
|
||||
-- Name of the decompressed file.
|
||||
|
||||
File_In : File_Type;
|
||||
File_Out : File_Type;
|
||||
File_Back : File_Type;
|
||||
File_Z : ZLib.Streams.Stream_Type;
|
||||
|
||||
Filter : ZLib.Filter_Type;
|
||||
|
||||
Time_Stamp : Ada.Calendar.Time;
|
||||
|
||||
procedure Generate_File;
|
||||
-- Generate file of spetsified size with some random data.
|
||||
-- The random data is repeatable, for the good compression.
|
||||
|
||||
procedure Compare_Streams
|
||||
(Left, Right : in out Root_Stream_Type'Class);
|
||||
-- The procedure compearing data in 2 streams.
|
||||
-- It is for compare data before and after compression/decompression.
|
||||
|
||||
procedure Compare_Files (Left, Right : String);
|
||||
-- Compare files. Based on the Compare_Streams.
|
||||
|
||||
procedure Copy_Streams
|
||||
(Source, Target : in out Root_Stream_Type'Class;
|
||||
Buffer_Size : in Stream_Element_Offset := 1024);
|
||||
-- Copying data from one stream to another. It is for test stream
|
||||
-- interface of the library.
|
||||
|
||||
procedure Data_In
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset);
|
||||
-- this procedure is for generic instantiation of
|
||||
-- ZLib.Generic_Translate.
|
||||
-- reading data from the File_In.
|
||||
|
||||
procedure Data_Out (Item : in Stream_Element_Array);
|
||||
-- this procedure is for generic instantiation of
|
||||
-- ZLib.Generic_Translate.
|
||||
-- writing data to the File_Out.
|
||||
|
||||
procedure Stamp;
|
||||
-- Store the timestamp to the local variable.
|
||||
|
||||
procedure Print_Statistic (Msg : String; Data_Size : ZLib.Count);
|
||||
-- Print the time statistic with the message.
|
||||
|
||||
procedure Translate is new ZLib.Generic_Translate
|
||||
(Data_In => Data_In,
|
||||
Data_Out => Data_Out);
|
||||
-- This procedure is moving data from File_In to File_Out
|
||||
-- with compression or decompression, depend on initialization of
|
||||
-- Filter parameter.
|
||||
|
||||
-------------------
|
||||
-- Compare_Files --
|
||||
-------------------
|
||||
|
||||
procedure Compare_Files (Left, Right : String) is
|
||||
Left_File, Right_File : File_Type;
|
||||
begin
|
||||
Open (Left_File, In_File, Left);
|
||||
Open (Right_File, In_File, Right);
|
||||
Compare_Streams (Stream (Left_File).all, Stream (Right_File).all);
|
||||
Close (Left_File);
|
||||
Close (Right_File);
|
||||
end Compare_Files;
|
||||
|
||||
---------------------
|
||||
-- Compare_Streams --
|
||||
---------------------
|
||||
|
||||
procedure Compare_Streams
|
||||
(Left, Right : in out Ada.Streams.Root_Stream_Type'Class)
|
||||
is
|
||||
Left_Buffer, Right_Buffer : Stream_Element_Array (0 .. 16#FFF#);
|
||||
Left_Last, Right_Last : Stream_Element_Offset;
|
||||
begin
|
||||
loop
|
||||
Read (Left, Left_Buffer, Left_Last);
|
||||
Read (Right, Right_Buffer, Right_Last);
|
||||
|
||||
if Left_Last /= Right_Last then
|
||||
Ada.Text_IO.Put_Line ("Compare error :"
|
||||
& Stream_Element_Offset'Image (Left_Last)
|
||||
& " /= "
|
||||
& Stream_Element_Offset'Image (Right_Last));
|
||||
|
||||
raise Constraint_Error;
|
||||
|
||||
elsif Left_Buffer (0 .. Left_Last)
|
||||
/= Right_Buffer (0 .. Right_Last)
|
||||
then
|
||||
Ada.Text_IO.Put_Line ("ERROR: IN and OUT files is not equal.");
|
||||
raise Constraint_Error;
|
||||
|
||||
end if;
|
||||
|
||||
exit when Left_Last < Left_Buffer'Last;
|
||||
end loop;
|
||||
end Compare_Streams;
|
||||
|
||||
------------------
|
||||
-- Copy_Streams --
|
||||
------------------
|
||||
|
||||
procedure Copy_Streams
|
||||
(Source, Target : in out Ada.Streams.Root_Stream_Type'Class;
|
||||
Buffer_Size : in Stream_Element_Offset := 1024)
|
||||
is
|
||||
Buffer : Stream_Element_Array (1 .. Buffer_Size);
|
||||
Last : Stream_Element_Offset;
|
||||
begin
|
||||
loop
|
||||
Read (Source, Buffer, Last);
|
||||
Write (Target, Buffer (1 .. Last));
|
||||
|
||||
exit when Last < Buffer'Last;
|
||||
end loop;
|
||||
end Copy_Streams;
|
||||
|
||||
-------------
|
||||
-- Data_In --
|
||||
-------------
|
||||
|
||||
procedure Data_In
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset) is
|
||||
begin
|
||||
Read (File_In, Item, Last);
|
||||
end Data_In;
|
||||
|
||||
--------------
|
||||
-- Data_Out --
|
||||
--------------
|
||||
|
||||
procedure Data_Out (Item : in Stream_Element_Array) is
|
||||
begin
|
||||
Write (File_Out, Item);
|
||||
end Data_Out;
|
||||
|
||||
-------------------
|
||||
-- Generate_File --
|
||||
-------------------
|
||||
|
||||
procedure Generate_File is
|
||||
subtype Visible_Symbols is Stream_Element range 16#20# .. 16#7E#;
|
||||
|
||||
package Random_Elements is
|
||||
new Ada.Numerics.Discrete_Random (Visible_Symbols);
|
||||
|
||||
Gen : Random_Elements.Generator;
|
||||
Buffer : Stream_Element_Array := (1 .. 77 => 16#20#) & 10;
|
||||
|
||||
Buffer_Count : constant Count := File_Size / Buffer'Length;
|
||||
-- Number of same buffers in the packet.
|
||||
|
||||
Density : constant Count := 30; -- from 0 to Buffer'Length - 2;
|
||||
|
||||
procedure Fill_Buffer (J, D : in Count);
|
||||
-- Change the part of the buffer.
|
||||
|
||||
-----------------
|
||||
-- Fill_Buffer --
|
||||
-----------------
|
||||
|
||||
procedure Fill_Buffer (J, D : in Count) is
|
||||
begin
|
||||
for K in 0 .. D loop
|
||||
Buffer
|
||||
(Stream_Element_Offset ((J + K) mod (Buffer'Length - 1) + 1))
|
||||
:= Random_Elements.Random (Gen);
|
||||
|
||||
end loop;
|
||||
end Fill_Buffer;
|
||||
|
||||
begin
|
||||
Random_Elements.Reset (Gen, Init_Random);
|
||||
|
||||
Create (File_In, Out_File, In_File_Name);
|
||||
|
||||
Fill_Buffer (1, Buffer'Length - 2);
|
||||
|
||||
for J in 1 .. Buffer_Count loop
|
||||
Write (File_In, Buffer);
|
||||
|
||||
Fill_Buffer (J, Density);
|
||||
end loop;
|
||||
|
||||
-- fill remain size.
|
||||
|
||||
Write
|
||||
(File_In,
|
||||
Buffer
|
||||
(1 .. Stream_Element_Offset
|
||||
(File_Size - Buffer'Length * Buffer_Count)));
|
||||
|
||||
Flush (File_In);
|
||||
Close (File_In);
|
||||
end Generate_File;
|
||||
|
||||
---------------------
|
||||
-- Print_Statistic --
|
||||
---------------------
|
||||
|
||||
procedure Print_Statistic (Msg : String; Data_Size : ZLib.Count) is
|
||||
use Ada.Calendar;
|
||||
use Ada.Text_IO;
|
||||
|
||||
package Count_IO is new Integer_IO (ZLib.Count);
|
||||
|
||||
Curr_Dur : Duration := Clock - Time_Stamp;
|
||||
begin
|
||||
Put (Msg);
|
||||
|
||||
Set_Col (20);
|
||||
Ada.Text_IO.Put ("size =");
|
||||
|
||||
Count_IO.Put
|
||||
(Data_Size,
|
||||
Width => Stream_IO.Count'Image (File_Size)'Length);
|
||||
|
||||
Put_Line (" duration =" & Duration'Image (Curr_Dur));
|
||||
end Print_Statistic;
|
||||
|
||||
-----------
|
||||
-- Stamp --
|
||||
-----------
|
||||
|
||||
procedure Stamp is
|
||||
begin
|
||||
Time_Stamp := Ada.Calendar.Clock;
|
||||
end Stamp;
|
||||
|
||||
begin
|
||||
Ada.Text_IO.Put_Line ("ZLib " & ZLib.Version);
|
||||
|
||||
loop
|
||||
Generate_File;
|
||||
|
||||
for Level in ZLib.Compression_Level'Range loop
|
||||
|
||||
Ada.Text_IO.Put_Line ("Level ="
|
||||
& ZLib.Compression_Level'Image (Level));
|
||||
|
||||
-- Test generic interface.
|
||||
Open (File_In, In_File, In_File_Name);
|
||||
Create (File_Out, Out_File, Z_File_Name);
|
||||
|
||||
Stamp;
|
||||
|
||||
-- Deflate using generic instantiation.
|
||||
|
||||
ZLib.Deflate_Init
|
||||
(Filter => Filter,
|
||||
Level => Level,
|
||||
Strategy => Strategy,
|
||||
Header => Header);
|
||||
|
||||
Translate (Filter);
|
||||
Print_Statistic ("Generic compress", ZLib.Total_Out (Filter));
|
||||
ZLib.Close (Filter);
|
||||
|
||||
Close (File_In);
|
||||
Close (File_Out);
|
||||
|
||||
Open (File_In, In_File, Z_File_Name);
|
||||
Create (File_Out, Out_File, Out_File_Name);
|
||||
|
||||
Stamp;
|
||||
|
||||
-- Inflate using generic instantiation.
|
||||
|
||||
ZLib.Inflate_Init (Filter, Header => Header);
|
||||
|
||||
Translate (Filter);
|
||||
Print_Statistic ("Generic decompress", ZLib.Total_Out (Filter));
|
||||
|
||||
ZLib.Close (Filter);
|
||||
|
||||
Close (File_In);
|
||||
Close (File_Out);
|
||||
|
||||
Compare_Files (In_File_Name, Out_File_Name);
|
||||
|
||||
-- Test stream interface.
|
||||
|
||||
-- Compress to the back stream.
|
||||
|
||||
Open (File_In, In_File, In_File_Name);
|
||||
Create (File_Back, Out_File, Z_File_Name);
|
||||
|
||||
Stamp;
|
||||
|
||||
ZLib.Streams.Create
|
||||
(Stream => File_Z,
|
||||
Mode => ZLib.Streams.Out_Stream,
|
||||
Back => ZLib.Streams.Stream_Access
|
||||
(Stream (File_Back)),
|
||||
Back_Compressed => True,
|
||||
Level => Level,
|
||||
Strategy => Strategy,
|
||||
Header => Header);
|
||||
|
||||
Copy_Streams
|
||||
(Source => Stream (File_In).all,
|
||||
Target => File_Z);
|
||||
|
||||
-- Flushing internal buffers to the back stream.
|
||||
|
||||
ZLib.Streams.Flush (File_Z, ZLib.Finish);
|
||||
|
||||
Print_Statistic ("Write compress",
|
||||
ZLib.Streams.Write_Total_Out (File_Z));
|
||||
|
||||
ZLib.Streams.Close (File_Z);
|
||||
|
||||
Close (File_In);
|
||||
Close (File_Back);
|
||||
|
||||
-- Compare reading from original file and from
|
||||
-- decompression stream.
|
||||
|
||||
Open (File_In, In_File, In_File_Name);
|
||||
Open (File_Back, In_File, Z_File_Name);
|
||||
|
||||
ZLib.Streams.Create
|
||||
(Stream => File_Z,
|
||||
Mode => ZLib.Streams.In_Stream,
|
||||
Back => ZLib.Streams.Stream_Access
|
||||
(Stream (File_Back)),
|
||||
Back_Compressed => True,
|
||||
Header => Header);
|
||||
|
||||
Stamp;
|
||||
Compare_Streams (Stream (File_In).all, File_Z);
|
||||
|
||||
Print_Statistic ("Read decompress",
|
||||
ZLib.Streams.Read_Total_Out (File_Z));
|
||||
|
||||
ZLib.Streams.Close (File_Z);
|
||||
Close (File_In);
|
||||
Close (File_Back);
|
||||
|
||||
-- Compress by reading from compression stream.
|
||||
|
||||
Open (File_Back, In_File, In_File_Name);
|
||||
Create (File_Out, Out_File, Z_File_Name);
|
||||
|
||||
ZLib.Streams.Create
|
||||
(Stream => File_Z,
|
||||
Mode => ZLib.Streams.In_Stream,
|
||||
Back => ZLib.Streams.Stream_Access
|
||||
(Stream (File_Back)),
|
||||
Back_Compressed => False,
|
||||
Level => Level,
|
||||
Strategy => Strategy,
|
||||
Header => Header);
|
||||
|
||||
Stamp;
|
||||
Copy_Streams
|
||||
(Source => File_Z,
|
||||
Target => Stream (File_Out).all);
|
||||
|
||||
Print_Statistic ("Read compress",
|
||||
ZLib.Streams.Read_Total_Out (File_Z));
|
||||
|
||||
ZLib.Streams.Close (File_Z);
|
||||
|
||||
Close (File_Out);
|
||||
Close (File_Back);
|
||||
|
||||
-- Decompress to decompression stream.
|
||||
|
||||
Open (File_In, In_File, Z_File_Name);
|
||||
Create (File_Back, Out_File, Out_File_Name);
|
||||
|
||||
ZLib.Streams.Create
|
||||
(Stream => File_Z,
|
||||
Mode => ZLib.Streams.Out_Stream,
|
||||
Back => ZLib.Streams.Stream_Access
|
||||
(Stream (File_Back)),
|
||||
Back_Compressed => False,
|
||||
Header => Header);
|
||||
|
||||
Stamp;
|
||||
|
||||
Copy_Streams
|
||||
(Source => Stream (File_In).all,
|
||||
Target => File_Z);
|
||||
|
||||
Print_Statistic ("Write decompress",
|
||||
ZLib.Streams.Write_Total_Out (File_Z));
|
||||
|
||||
ZLib.Streams.Close (File_Z);
|
||||
Close (File_In);
|
||||
Close (File_Back);
|
||||
|
||||
Compare_Files (In_File_Name, Out_File_Name);
|
||||
end loop;
|
||||
|
||||
Ada.Text_IO.Put_Line (Count'Image (File_Size) & " Ok.");
|
||||
|
||||
exit when not Continuous;
|
||||
|
||||
File_Size := File_Size + 1;
|
||||
end loop;
|
||||
end Test;
|
||||
@@ -0,0 +1,225 @@
|
||||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id$
|
||||
|
||||
with Ada.Unchecked_Deallocation;
|
||||
|
||||
package body ZLib.Streams is
|
||||
|
||||
-----------
|
||||
-- Close --
|
||||
-----------
|
||||
|
||||
procedure Close (Stream : in out Stream_Type) is
|
||||
procedure Free is new Ada.Unchecked_Deallocation
|
||||
(Stream_Element_Array, Buffer_Access);
|
||||
begin
|
||||
if Stream.Mode = Out_Stream or Stream.Mode = Duplex then
|
||||
-- We should flush the data written by the writer.
|
||||
|
||||
Flush (Stream, Finish);
|
||||
|
||||
Close (Stream.Writer);
|
||||
end if;
|
||||
|
||||
if Stream.Mode = In_Stream or Stream.Mode = Duplex then
|
||||
Close (Stream.Reader);
|
||||
Free (Stream.Buffer);
|
||||
end if;
|
||||
end Close;
|
||||
|
||||
------------
|
||||
-- Create --
|
||||
------------
|
||||
|
||||
procedure Create
|
||||
(Stream : out Stream_Type;
|
||||
Mode : in Stream_Mode;
|
||||
Back : in Stream_Access;
|
||||
Back_Compressed : in Boolean;
|
||||
Level : in Compression_Level := Default_Compression;
|
||||
Strategy : in Strategy_Type := Default_Strategy;
|
||||
Header : in Header_Type := Default;
|
||||
Read_Buffer_Size : in Ada.Streams.Stream_Element_Offset
|
||||
:= Default_Buffer_Size;
|
||||
Write_Buffer_Size : in Ada.Streams.Stream_Element_Offset
|
||||
:= Default_Buffer_Size)
|
||||
is
|
||||
|
||||
subtype Buffer_Subtype is Stream_Element_Array (1 .. Read_Buffer_Size);
|
||||
|
||||
procedure Init_Filter
|
||||
(Filter : in out Filter_Type;
|
||||
Compress : in Boolean);
|
||||
|
||||
-----------------
|
||||
-- Init_Filter --
|
||||
-----------------
|
||||
|
||||
procedure Init_Filter
|
||||
(Filter : in out Filter_Type;
|
||||
Compress : in Boolean) is
|
||||
begin
|
||||
if Compress then
|
||||
Deflate_Init
|
||||
(Filter, Level, Strategy, Header => Header);
|
||||
else
|
||||
Inflate_Init (Filter, Header => Header);
|
||||
end if;
|
||||
end Init_Filter;
|
||||
|
||||
begin
|
||||
Stream.Back := Back;
|
||||
Stream.Mode := Mode;
|
||||
|
||||
if Mode = Out_Stream or Mode = Duplex then
|
||||
Init_Filter (Stream.Writer, Back_Compressed);
|
||||
Stream.Buffer_Size := Write_Buffer_Size;
|
||||
else
|
||||
Stream.Buffer_Size := 0;
|
||||
end if;
|
||||
|
||||
if Mode = In_Stream or Mode = Duplex then
|
||||
Init_Filter (Stream.Reader, not Back_Compressed);
|
||||
|
||||
Stream.Buffer := new Buffer_Subtype;
|
||||
Stream.Rest_First := Stream.Buffer'Last + 1;
|
||||
Stream.Rest_Last := Stream.Buffer'Last;
|
||||
end if;
|
||||
end Create;
|
||||
|
||||
-----------
|
||||
-- Flush --
|
||||
-----------
|
||||
|
||||
procedure Flush
|
||||
(Stream : in out Stream_Type;
|
||||
Mode : in Flush_Mode := Sync_Flush)
|
||||
is
|
||||
Buffer : Stream_Element_Array (1 .. Stream.Buffer_Size);
|
||||
Last : Stream_Element_Offset;
|
||||
begin
|
||||
loop
|
||||
Flush (Stream.Writer, Buffer, Last, Mode);
|
||||
|
||||
Ada.Streams.Write (Stream.Back.all, Buffer (1 .. Last));
|
||||
|
||||
exit when Last < Buffer'Last;
|
||||
end loop;
|
||||
end Flush;
|
||||
|
||||
-------------
|
||||
-- Is_Open --
|
||||
-------------
|
||||
|
||||
function Is_Open (Stream : Stream_Type) return Boolean is
|
||||
begin
|
||||
return Is_Open (Stream.Reader) or else Is_Open (Stream.Writer);
|
||||
end Is_Open;
|
||||
|
||||
----------
|
||||
-- Read --
|
||||
----------
|
||||
|
||||
procedure Read
|
||||
(Stream : in out Stream_Type;
|
||||
Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset)
|
||||
is
|
||||
|
||||
procedure Read
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset);
|
||||
|
||||
----------
|
||||
-- Read --
|
||||
----------
|
||||
|
||||
procedure Read
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset) is
|
||||
begin
|
||||
Ada.Streams.Read (Stream.Back.all, Item, Last);
|
||||
end Read;
|
||||
|
||||
procedure Read is new ZLib.Read
|
||||
(Read => Read,
|
||||
Buffer => Stream.Buffer.all,
|
||||
Rest_First => Stream.Rest_First,
|
||||
Rest_Last => Stream.Rest_Last);
|
||||
|
||||
begin
|
||||
Read (Stream.Reader, Item, Last);
|
||||
end Read;
|
||||
|
||||
-------------------
|
||||
-- Read_Total_In --
|
||||
-------------------
|
||||
|
||||
function Read_Total_In (Stream : in Stream_Type) return Count is
|
||||
begin
|
||||
return Total_In (Stream.Reader);
|
||||
end Read_Total_In;
|
||||
|
||||
--------------------
|
||||
-- Read_Total_Out --
|
||||
--------------------
|
||||
|
||||
function Read_Total_Out (Stream : in Stream_Type) return Count is
|
||||
begin
|
||||
return Total_Out (Stream.Reader);
|
||||
end Read_Total_Out;
|
||||
|
||||
-----------
|
||||
-- Write --
|
||||
-----------
|
||||
|
||||
procedure Write
|
||||
(Stream : in out Stream_Type;
|
||||
Item : in Stream_Element_Array)
|
||||
is
|
||||
|
||||
procedure Write (Item : in Stream_Element_Array);
|
||||
|
||||
-----------
|
||||
-- Write --
|
||||
-----------
|
||||
|
||||
procedure Write (Item : in Stream_Element_Array) is
|
||||
begin
|
||||
Ada.Streams.Write (Stream.Back.all, Item);
|
||||
end Write;
|
||||
|
||||
procedure Write is new ZLib.Write
|
||||
(Write => Write,
|
||||
Buffer_Size => Stream.Buffer_Size);
|
||||
|
||||
begin
|
||||
Write (Stream.Writer, Item, No_Flush);
|
||||
end Write;
|
||||
|
||||
--------------------
|
||||
-- Write_Total_In --
|
||||
--------------------
|
||||
|
||||
function Write_Total_In (Stream : in Stream_Type) return Count is
|
||||
begin
|
||||
return Total_In (Stream.Writer);
|
||||
end Write_Total_In;
|
||||
|
||||
---------------------
|
||||
-- Write_Total_Out --
|
||||
---------------------
|
||||
|
||||
function Write_Total_Out (Stream : in Stream_Type) return Count is
|
||||
begin
|
||||
return Total_Out (Stream.Writer);
|
||||
end Write_Total_Out;
|
||||
|
||||
end ZLib.Streams;
|
||||
@@ -0,0 +1,114 @@
|
||||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id$
|
||||
|
||||
package ZLib.Streams is
|
||||
|
||||
type Stream_Mode is (In_Stream, Out_Stream, Duplex);
|
||||
|
||||
type Stream_Access is access all Ada.Streams.Root_Stream_Type'Class;
|
||||
|
||||
type Stream_Type is
|
||||
new Ada.Streams.Root_Stream_Type with private;
|
||||
|
||||
procedure Read
|
||||
(Stream : in out Stream_Type;
|
||||
Item : out Ada.Streams.Stream_Element_Array;
|
||||
Last : out Ada.Streams.Stream_Element_Offset);
|
||||
|
||||
procedure Write
|
||||
(Stream : in out Stream_Type;
|
||||
Item : in Ada.Streams.Stream_Element_Array);
|
||||
|
||||
procedure Flush
|
||||
(Stream : in out Stream_Type;
|
||||
Mode : in Flush_Mode := Sync_Flush);
|
||||
-- Flush the written data to the back stream,
|
||||
-- all data placed to the compressor is flushing to the Back stream.
|
||||
-- Should not be used untill necessary, becouse it is decreasing
|
||||
-- compression.
|
||||
|
||||
function Read_Total_In (Stream : in Stream_Type) return Count;
|
||||
pragma Inline (Read_Total_In);
|
||||
-- Return total number of bytes read from back stream so far.
|
||||
|
||||
function Read_Total_Out (Stream : in Stream_Type) return Count;
|
||||
pragma Inline (Read_Total_Out);
|
||||
-- Return total number of bytes read so far.
|
||||
|
||||
function Write_Total_In (Stream : in Stream_Type) return Count;
|
||||
pragma Inline (Write_Total_In);
|
||||
-- Return total number of bytes written so far.
|
||||
|
||||
function Write_Total_Out (Stream : in Stream_Type) return Count;
|
||||
pragma Inline (Write_Total_Out);
|
||||
-- Return total number of bytes written to the back stream.
|
||||
|
||||
procedure Create
|
||||
(Stream : out Stream_Type;
|
||||
Mode : in Stream_Mode;
|
||||
Back : in Stream_Access;
|
||||
Back_Compressed : in Boolean;
|
||||
Level : in Compression_Level := Default_Compression;
|
||||
Strategy : in Strategy_Type := Default_Strategy;
|
||||
Header : in Header_Type := Default;
|
||||
Read_Buffer_Size : in Ada.Streams.Stream_Element_Offset
|
||||
:= Default_Buffer_Size;
|
||||
Write_Buffer_Size : in Ada.Streams.Stream_Element_Offset
|
||||
:= Default_Buffer_Size);
|
||||
-- Create the Comression/Decompression stream.
|
||||
-- If mode is In_Stream then Write operation is disabled.
|
||||
-- If mode is Out_Stream then Read operation is disabled.
|
||||
|
||||
-- If Back_Compressed is true then
|
||||
-- Data written to the Stream is compressing to the Back stream
|
||||
-- and data read from the Stream is decompressed data from the Back stream.
|
||||
|
||||
-- If Back_Compressed is false then
|
||||
-- Data written to the Stream is decompressing to the Back stream
|
||||
-- and data read from the Stream is compressed data from the Back stream.
|
||||
|
||||
-- !!! When the Need_Header is False ZLib-Ada is using undocumented
|
||||
-- ZLib 1.1.4 functionality to do not create/wait for ZLib headers.
|
||||
|
||||
function Is_Open (Stream : Stream_Type) return Boolean;
|
||||
|
||||
procedure Close (Stream : in out Stream_Type);
|
||||
|
||||
private
|
||||
|
||||
use Ada.Streams;
|
||||
|
||||
type Buffer_Access is access all Stream_Element_Array;
|
||||
|
||||
type Stream_Type
|
||||
is new Root_Stream_Type with
|
||||
record
|
||||
Mode : Stream_Mode;
|
||||
|
||||
Buffer : Buffer_Access;
|
||||
Rest_First : Stream_Element_Offset;
|
||||
Rest_Last : Stream_Element_Offset;
|
||||
-- Buffer for Read operation.
|
||||
-- We need to have this buffer in the record
|
||||
-- becouse not all read data from back stream
|
||||
-- could be processed during the read operation.
|
||||
|
||||
Buffer_Size : Stream_Element_Offset;
|
||||
-- Buffer size for write operation.
|
||||
-- We do not need to have this buffer
|
||||
-- in the record becouse all data could be
|
||||
-- processed in the write operation.
|
||||
|
||||
Back : Stream_Access;
|
||||
Reader : Filter_Type;
|
||||
Writer : Filter_Type;
|
||||
end record;
|
||||
|
||||
end ZLib.Streams;
|
||||
@@ -0,0 +1,141 @@
|
||||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id$
|
||||
|
||||
package body ZLib.Thin is
|
||||
|
||||
ZLIB_VERSION : constant Chars_Ptr := zlibVersion;
|
||||
|
||||
Z_Stream_Size : constant Int := Z_Stream'Size / System.Storage_Unit;
|
||||
|
||||
--------------
|
||||
-- Avail_In --
|
||||
--------------
|
||||
|
||||
function Avail_In (Strm : in Z_Stream) return UInt is
|
||||
begin
|
||||
return Strm.Avail_In;
|
||||
end Avail_In;
|
||||
|
||||
---------------
|
||||
-- Avail_Out --
|
||||
---------------
|
||||
|
||||
function Avail_Out (Strm : in Z_Stream) return UInt is
|
||||
begin
|
||||
return Strm.Avail_Out;
|
||||
end Avail_Out;
|
||||
|
||||
------------------
|
||||
-- Deflate_Init --
|
||||
------------------
|
||||
|
||||
function Deflate_Init
|
||||
(strm : Z_Streamp;
|
||||
level : Int;
|
||||
method : Int;
|
||||
windowBits : Int;
|
||||
memLevel : Int;
|
||||
strategy : Int)
|
||||
return Int is
|
||||
begin
|
||||
return deflateInit2
|
||||
(strm,
|
||||
level,
|
||||
method,
|
||||
windowBits,
|
||||
memLevel,
|
||||
strategy,
|
||||
ZLIB_VERSION,
|
||||
Z_Stream_Size);
|
||||
end Deflate_Init;
|
||||
|
||||
------------------
|
||||
-- Inflate_Init --
|
||||
------------------
|
||||
|
||||
function Inflate_Init (strm : Z_Streamp; windowBits : Int) return Int is
|
||||
begin
|
||||
return inflateInit2 (strm, windowBits, ZLIB_VERSION, Z_Stream_Size);
|
||||
end Inflate_Init;
|
||||
|
||||
------------------------
|
||||
-- Last_Error_Message --
|
||||
------------------------
|
||||
|
||||
function Last_Error_Message (Strm : in Z_Stream) return String is
|
||||
use Interfaces.C.Strings;
|
||||
begin
|
||||
if Strm.msg = Null_Ptr then
|
||||
return "";
|
||||
else
|
||||
return Value (Strm.msg);
|
||||
end if;
|
||||
end Last_Error_Message;
|
||||
|
||||
------------
|
||||
-- Set_In --
|
||||
------------
|
||||
|
||||
procedure Set_In
|
||||
(Strm : in out Z_Stream;
|
||||
Buffer : in Voidp;
|
||||
Size : in UInt) is
|
||||
begin
|
||||
Strm.Next_In := Buffer;
|
||||
Strm.Avail_In := Size;
|
||||
end Set_In;
|
||||
|
||||
------------------
|
||||
-- Set_Mem_Func --
|
||||
------------------
|
||||
|
||||
procedure Set_Mem_Func
|
||||
(Strm : in out Z_Stream;
|
||||
Opaque : in Voidp;
|
||||
Alloc : in alloc_func;
|
||||
Free : in free_func) is
|
||||
begin
|
||||
Strm.opaque := Opaque;
|
||||
Strm.zalloc := Alloc;
|
||||
Strm.zfree := Free;
|
||||
end Set_Mem_Func;
|
||||
|
||||
-------------
|
||||
-- Set_Out --
|
||||
-------------
|
||||
|
||||
procedure Set_Out
|
||||
(Strm : in out Z_Stream;
|
||||
Buffer : in Voidp;
|
||||
Size : in UInt) is
|
||||
begin
|
||||
Strm.Next_Out := Buffer;
|
||||
Strm.Avail_Out := Size;
|
||||
end Set_Out;
|
||||
|
||||
--------------
|
||||
-- Total_In --
|
||||
--------------
|
||||
|
||||
function Total_In (Strm : in Z_Stream) return ULong is
|
||||
begin
|
||||
return Strm.Total_In;
|
||||
end Total_In;
|
||||
|
||||
---------------
|
||||
-- Total_Out --
|
||||
---------------
|
||||
|
||||
function Total_Out (Strm : in Z_Stream) return ULong is
|
||||
begin
|
||||
return Strm.Total_Out;
|
||||
end Total_Out;
|
||||
|
||||
end ZLib.Thin;
|
||||
@@ -0,0 +1,450 @@
|
||||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id$
|
||||
|
||||
with Interfaces.C.Strings;
|
||||
|
||||
with System;
|
||||
|
||||
private package ZLib.Thin is
|
||||
|
||||
-- From zconf.h
|
||||
|
||||
MAX_MEM_LEVEL : constant := 9; -- zconf.h:105
|
||||
-- zconf.h:105
|
||||
MAX_WBITS : constant := 15; -- zconf.h:115
|
||||
-- 32K LZ77 window
|
||||
-- zconf.h:115
|
||||
SEEK_SET : constant := 8#0000#; -- zconf.h:244
|
||||
-- Seek from beginning of file.
|
||||
-- zconf.h:244
|
||||
SEEK_CUR : constant := 1; -- zconf.h:245
|
||||
-- Seek from current position.
|
||||
-- zconf.h:245
|
||||
SEEK_END : constant := 2; -- zconf.h:246
|
||||
-- Set file pointer to EOF plus "offset"
|
||||
-- zconf.h:246
|
||||
|
||||
type Byte is new Interfaces.C.unsigned_char; -- 8 bits
|
||||
-- zconf.h:214
|
||||
type UInt is new Interfaces.C.unsigned; -- 16 bits or more
|
||||
-- zconf.h:216
|
||||
type Int is new Interfaces.C.int;
|
||||
|
||||
type ULong is new Interfaces.C.unsigned_long; -- 32 bits or more
|
||||
-- zconf.h:217
|
||||
subtype Chars_Ptr is Interfaces.C.Strings.chars_ptr;
|
||||
|
||||
type ULong_Access is access ULong;
|
||||
type Int_Access is access Int;
|
||||
|
||||
subtype Voidp is System.Address; -- zconf.h:232
|
||||
|
||||
subtype Byte_Access is Voidp;
|
||||
|
||||
Nul : constant Voidp := System.Null_Address;
|
||||
-- end from zconf
|
||||
|
||||
Z_NO_FLUSH : constant := 8#0000#; -- zlib.h:125
|
||||
-- zlib.h:125
|
||||
Z_PARTIAL_FLUSH : constant := 1; -- zlib.h:126
|
||||
-- will be removed, use
|
||||
-- Z_SYNC_FLUSH instead
|
||||
-- zlib.h:126
|
||||
Z_SYNC_FLUSH : constant := 2; -- zlib.h:127
|
||||
-- zlib.h:127
|
||||
Z_FULL_FLUSH : constant := 3; -- zlib.h:128
|
||||
-- zlib.h:128
|
||||
Z_FINISH : constant := 4; -- zlib.h:129
|
||||
-- zlib.h:129
|
||||
Z_OK : constant := 8#0000#; -- zlib.h:132
|
||||
-- zlib.h:132
|
||||
Z_STREAM_END : constant := 1; -- zlib.h:133
|
||||
-- zlib.h:133
|
||||
Z_NEED_DICT : constant := 2; -- zlib.h:134
|
||||
-- zlib.h:134
|
||||
Z_ERRNO : constant := -1; -- zlib.h:135
|
||||
-- zlib.h:135
|
||||
Z_STREAM_ERROR : constant := -2; -- zlib.h:136
|
||||
-- zlib.h:136
|
||||
Z_DATA_ERROR : constant := -3; -- zlib.h:137
|
||||
-- zlib.h:137
|
||||
Z_MEM_ERROR : constant := -4; -- zlib.h:138
|
||||
-- zlib.h:138
|
||||
Z_BUF_ERROR : constant := -5; -- zlib.h:139
|
||||
-- zlib.h:139
|
||||
Z_VERSION_ERROR : constant := -6; -- zlib.h:140
|
||||
-- zlib.h:140
|
||||
Z_NO_COMPRESSION : constant := 8#0000#; -- zlib.h:145
|
||||
-- zlib.h:145
|
||||
Z_BEST_SPEED : constant := 1; -- zlib.h:146
|
||||
-- zlib.h:146
|
||||
Z_BEST_COMPRESSION : constant := 9; -- zlib.h:147
|
||||
-- zlib.h:147
|
||||
Z_DEFAULT_COMPRESSION : constant := -1; -- zlib.h:148
|
||||
-- zlib.h:148
|
||||
Z_FILTERED : constant := 1; -- zlib.h:151
|
||||
-- zlib.h:151
|
||||
Z_HUFFMAN_ONLY : constant := 2; -- zlib.h:152
|
||||
-- zlib.h:152
|
||||
Z_DEFAULT_STRATEGY : constant := 8#0000#; -- zlib.h:153
|
||||
-- zlib.h:153
|
||||
Z_BINARY : constant := 8#0000#; -- zlib.h:156
|
||||
-- zlib.h:156
|
||||
Z_ASCII : constant := 1; -- zlib.h:157
|
||||
-- zlib.h:157
|
||||
Z_UNKNOWN : constant := 2; -- zlib.h:158
|
||||
-- zlib.h:158
|
||||
Z_DEFLATED : constant := 8; -- zlib.h:161
|
||||
-- zlib.h:161
|
||||
Z_NULL : constant := 8#0000#; -- zlib.h:164
|
||||
-- for initializing zalloc, zfree, opaque
|
||||
-- zlib.h:164
|
||||
type gzFile is new Voidp; -- zlib.h:646
|
||||
|
||||
type Z_Stream is private;
|
||||
|
||||
type Z_Streamp is access all Z_Stream; -- zlib.h:89
|
||||
|
||||
type alloc_func is access function
|
||||
(Opaque : Voidp;
|
||||
Items : UInt;
|
||||
Size : UInt)
|
||||
return Voidp; -- zlib.h:63
|
||||
|
||||
type free_func is access procedure (opaque : Voidp; address : Voidp);
|
||||
|
||||
function zlibVersion return Chars_Ptr;
|
||||
|
||||
function Deflate (strm : Z_Streamp; flush : Int) return Int;
|
||||
|
||||
function DeflateEnd (strm : Z_Streamp) return Int;
|
||||
|
||||
function Inflate (strm : Z_Streamp; flush : Int) return Int;
|
||||
|
||||
function InflateEnd (strm : Z_Streamp) return Int;
|
||||
|
||||
function deflateSetDictionary
|
||||
(strm : Z_Streamp;
|
||||
dictionary : Byte_Access;
|
||||
dictLength : UInt)
|
||||
return Int;
|
||||
|
||||
function deflateCopy (dest : Z_Streamp; source : Z_Streamp) return Int;
|
||||
-- zlib.h:478
|
||||
|
||||
function deflateReset (strm : Z_Streamp) return Int; -- zlib.h:495
|
||||
|
||||
function deflateParams
|
||||
(strm : Z_Streamp;
|
||||
level : Int;
|
||||
strategy : Int)
|
||||
return Int; -- zlib.h:506
|
||||
|
||||
function inflateSetDictionary
|
||||
(strm : Z_Streamp;
|
||||
dictionary : Byte_Access;
|
||||
dictLength : UInt)
|
||||
return Int; -- zlib.h:548
|
||||
|
||||
function inflateSync (strm : Z_Streamp) return Int; -- zlib.h:565
|
||||
|
||||
function inflateReset (strm : Z_Streamp) return Int; -- zlib.h:580
|
||||
|
||||
function compress
|
||||
(dest : Byte_Access;
|
||||
destLen : ULong_Access;
|
||||
source : Byte_Access;
|
||||
sourceLen : ULong)
|
||||
return Int; -- zlib.h:601
|
||||
|
||||
function compress2
|
||||
(dest : Byte_Access;
|
||||
destLen : ULong_Access;
|
||||
source : Byte_Access;
|
||||
sourceLen : ULong;
|
||||
level : Int)
|
||||
return Int; -- zlib.h:615
|
||||
|
||||
function uncompress
|
||||
(dest : Byte_Access;
|
||||
destLen : ULong_Access;
|
||||
source : Byte_Access;
|
||||
sourceLen : ULong)
|
||||
return Int;
|
||||
|
||||
function gzopen (path : Chars_Ptr; mode : Chars_Ptr) return gzFile;
|
||||
|
||||
function gzdopen (fd : Int; mode : Chars_Ptr) return gzFile;
|
||||
|
||||
function gzsetparams
|
||||
(file : gzFile;
|
||||
level : Int;
|
||||
strategy : Int)
|
||||
return Int;
|
||||
|
||||
function gzread
|
||||
(file : gzFile;
|
||||
buf : Voidp;
|
||||
len : UInt)
|
||||
return Int;
|
||||
|
||||
function gzwrite
|
||||
(file : in gzFile;
|
||||
buf : in Voidp;
|
||||
len : in UInt)
|
||||
return Int;
|
||||
|
||||
function gzprintf (file : in gzFile; format : in Chars_Ptr) return Int;
|
||||
|
||||
function gzputs (file : in gzFile; s : in Chars_Ptr) return Int;
|
||||
|
||||
function gzgets
|
||||
(file : gzFile;
|
||||
buf : Chars_Ptr;
|
||||
len : Int)
|
||||
return Chars_Ptr;
|
||||
|
||||
function gzputc (file : gzFile; char : Int) return Int;
|
||||
|
||||
function gzgetc (file : gzFile) return Int;
|
||||
|
||||
function gzflush (file : gzFile; flush : Int) return Int;
|
||||
|
||||
function gzseek
|
||||
(file : gzFile;
|
||||
offset : Int;
|
||||
whence : Int)
|
||||
return Int;
|
||||
|
||||
function gzrewind (file : gzFile) return Int;
|
||||
|
||||
function gztell (file : gzFile) return Int;
|
||||
|
||||
function gzeof (file : gzFile) return Int;
|
||||
|
||||
function gzclose (file : gzFile) return Int;
|
||||
|
||||
function gzerror (file : gzFile; errnum : Int_Access) return Chars_Ptr;
|
||||
|
||||
function adler32
|
||||
(adler : ULong;
|
||||
buf : Byte_Access;
|
||||
len : UInt)
|
||||
return ULong;
|
||||
|
||||
function crc32
|
||||
(crc : ULong;
|
||||
buf : Byte_Access;
|
||||
len : UInt)
|
||||
return ULong;
|
||||
|
||||
function deflateInit
|
||||
(strm : Z_Streamp;
|
||||
level : Int;
|
||||
version : Chars_Ptr;
|
||||
stream_size : Int)
|
||||
return Int;
|
||||
|
||||
function deflateInit2
|
||||
(strm : Z_Streamp;
|
||||
level : Int;
|
||||
method : Int;
|
||||
windowBits : Int;
|
||||
memLevel : Int;
|
||||
strategy : Int;
|
||||
version : Chars_Ptr;
|
||||
stream_size : Int)
|
||||
return Int;
|
||||
|
||||
function Deflate_Init
|
||||
(strm : Z_Streamp;
|
||||
level : Int;
|
||||
method : Int;
|
||||
windowBits : Int;
|
||||
memLevel : Int;
|
||||
strategy : Int)
|
||||
return Int;
|
||||
pragma Inline (Deflate_Init);
|
||||
|
||||
function inflateInit
|
||||
(strm : Z_Streamp;
|
||||
version : Chars_Ptr;
|
||||
stream_size : Int)
|
||||
return Int;
|
||||
|
||||
function inflateInit2
|
||||
(strm : in Z_Streamp;
|
||||
windowBits : in Int;
|
||||
version : in Chars_Ptr;
|
||||
stream_size : in Int)
|
||||
return Int;
|
||||
|
||||
function inflateBackInit
|
||||
(strm : in Z_Streamp;
|
||||
windowBits : in Int;
|
||||
window : in Byte_Access;
|
||||
version : in Chars_Ptr;
|
||||
stream_size : in Int)
|
||||
return Int;
|
||||
-- Size of window have to be 2**windowBits.
|
||||
|
||||
function Inflate_Init (strm : Z_Streamp; windowBits : Int) return Int;
|
||||
pragma Inline (Inflate_Init);
|
||||
|
||||
function zError (err : Int) return Chars_Ptr;
|
||||
|
||||
function inflateSyncPoint (z : Z_Streamp) return Int;
|
||||
|
||||
function get_crc_table return ULong_Access;
|
||||
|
||||
-- Interface to the available fields of the z_stream structure.
|
||||
-- The application must update next_in and avail_in when avail_in has
|
||||
-- dropped to zero. It must update next_out and avail_out when avail_out
|
||||
-- has dropped to zero. The application must initialize zalloc, zfree and
|
||||
-- opaque before calling the init function.
|
||||
|
||||
procedure Set_In
|
||||
(Strm : in out Z_Stream;
|
||||
Buffer : in Voidp;
|
||||
Size : in UInt);
|
||||
pragma Inline (Set_In);
|
||||
|
||||
procedure Set_Out
|
||||
(Strm : in out Z_Stream;
|
||||
Buffer : in Voidp;
|
||||
Size : in UInt);
|
||||
pragma Inline (Set_Out);
|
||||
|
||||
procedure Set_Mem_Func
|
||||
(Strm : in out Z_Stream;
|
||||
Opaque : in Voidp;
|
||||
Alloc : in alloc_func;
|
||||
Free : in free_func);
|
||||
pragma Inline (Set_Mem_Func);
|
||||
|
||||
function Last_Error_Message (Strm : in Z_Stream) return String;
|
||||
pragma Inline (Last_Error_Message);
|
||||
|
||||
function Avail_Out (Strm : in Z_Stream) return UInt;
|
||||
pragma Inline (Avail_Out);
|
||||
|
||||
function Avail_In (Strm : in Z_Stream) return UInt;
|
||||
pragma Inline (Avail_In);
|
||||
|
||||
function Total_In (Strm : in Z_Stream) return ULong;
|
||||
pragma Inline (Total_In);
|
||||
|
||||
function Total_Out (Strm : in Z_Stream) return ULong;
|
||||
pragma Inline (Total_Out);
|
||||
|
||||
function inflateCopy
|
||||
(dest : in Z_Streamp;
|
||||
Source : in Z_Streamp)
|
||||
return Int;
|
||||
|
||||
function compressBound (Source_Len : in ULong) return ULong;
|
||||
|
||||
function deflateBound
|
||||
(Strm : in Z_Streamp;
|
||||
Source_Len : in ULong)
|
||||
return ULong;
|
||||
|
||||
function gzungetc (C : in Int; File : in gzFile) return Int;
|
||||
|
||||
function zlibCompileFlags return ULong;
|
||||
|
||||
private
|
||||
|
||||
type Z_Stream is record -- zlib.h:68
|
||||
Next_In : Voidp := Nul; -- next input byte
|
||||
Avail_In : UInt := 0; -- number of bytes available at next_in
|
||||
Total_In : ULong := 0; -- total nb of input bytes read so far
|
||||
Next_Out : Voidp := Nul; -- next output byte should be put there
|
||||
Avail_Out : UInt := 0; -- remaining free space at next_out
|
||||
Total_Out : ULong := 0; -- total nb of bytes output so far
|
||||
msg : Chars_Ptr; -- last error message, NULL if no error
|
||||
state : Voidp; -- not visible by applications
|
||||
zalloc : alloc_func := null; -- used to allocate the internal state
|
||||
zfree : free_func := null; -- used to free the internal state
|
||||
opaque : Voidp; -- private data object passed to
|
||||
-- zalloc and zfree
|
||||
data_type : Int; -- best guess about the data type:
|
||||
-- ascii or binary
|
||||
adler : ULong; -- adler32 value of the uncompressed
|
||||
-- data
|
||||
reserved : ULong; -- reserved for future use
|
||||
end record;
|
||||
|
||||
pragma Convention (C, Z_Stream);
|
||||
|
||||
pragma Import (C, zlibVersion, "zlibVersion");
|
||||
pragma Import (C, Deflate, "deflate");
|
||||
pragma Import (C, DeflateEnd, "deflateEnd");
|
||||
pragma Import (C, Inflate, "inflate");
|
||||
pragma Import (C, InflateEnd, "inflateEnd");
|
||||
pragma Import (C, deflateSetDictionary, "deflateSetDictionary");
|
||||
pragma Import (C, deflateCopy, "deflateCopy");
|
||||
pragma Import (C, deflateReset, "deflateReset");
|
||||
pragma Import (C, deflateParams, "deflateParams");
|
||||
pragma Import (C, inflateSetDictionary, "inflateSetDictionary");
|
||||
pragma Import (C, inflateSync, "inflateSync");
|
||||
pragma Import (C, inflateReset, "inflateReset");
|
||||
pragma Import (C, compress, "compress");
|
||||
pragma Import (C, compress2, "compress2");
|
||||
pragma Import (C, uncompress, "uncompress");
|
||||
pragma Import (C, gzopen, "gzopen");
|
||||
pragma Import (C, gzdopen, "gzdopen");
|
||||
pragma Import (C, gzsetparams, "gzsetparams");
|
||||
pragma Import (C, gzread, "gzread");
|
||||
pragma Import (C, gzwrite, "gzwrite");
|
||||
pragma Import (C, gzprintf, "gzprintf");
|
||||
pragma Import (C, gzputs, "gzputs");
|
||||
pragma Import (C, gzgets, "gzgets");
|
||||
pragma Import (C, gzputc, "gzputc");
|
||||
pragma Import (C, gzgetc, "gzgetc");
|
||||
pragma Import (C, gzflush, "gzflush");
|
||||
pragma Import (C, gzseek, "gzseek");
|
||||
pragma Import (C, gzrewind, "gzrewind");
|
||||
pragma Import (C, gztell, "gztell");
|
||||
pragma Import (C, gzeof, "gzeof");
|
||||
pragma Import (C, gzclose, "gzclose");
|
||||
pragma Import (C, gzerror, "gzerror");
|
||||
pragma Import (C, adler32, "adler32");
|
||||
pragma Import (C, crc32, "crc32");
|
||||
pragma Import (C, deflateInit, "deflateInit_");
|
||||
pragma Import (C, inflateInit, "inflateInit_");
|
||||
pragma Import (C, deflateInit2, "deflateInit2_");
|
||||
pragma Import (C, inflateInit2, "inflateInit2_");
|
||||
pragma Import (C, zError, "zError");
|
||||
pragma Import (C, inflateSyncPoint, "inflateSyncPoint");
|
||||
pragma Import (C, get_crc_table, "get_crc_table");
|
||||
|
||||
-- since zlib 1.2.0:
|
||||
|
||||
pragma Import (C, inflateCopy, "inflateCopy");
|
||||
pragma Import (C, compressBound, "compressBound");
|
||||
pragma Import (C, deflateBound, "deflateBound");
|
||||
pragma Import (C, gzungetc, "gzungetc");
|
||||
pragma Import (C, zlibCompileFlags, "zlibCompileFlags");
|
||||
|
||||
pragma Import (C, inflateBackInit, "inflateBackInit_");
|
||||
|
||||
-- I stopped binding the inflateBack routines, becouse realize that
|
||||
-- it does not support zlib and gzip headers for now, and have no
|
||||
-- symmetric deflateBack routines.
|
||||
-- ZLib-Ada is symmetric regarding deflate/inflate data transformation
|
||||
-- and has a similar generic callback interface for the
|
||||
-- deflate/inflate transformation based on the regular Deflate/Inflate
|
||||
-- routines.
|
||||
|
||||
-- pragma Import (C, inflateBack, "inflateBack");
|
||||
-- pragma Import (C, inflateBackEnd, "inflateBackEnd");
|
||||
|
||||
end ZLib.Thin;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,328 @@
|
||||
------------------------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2004 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- This library is free software; you can redistribute it and/or modify --
|
||||
-- it under the terms of the GNU General Public License as published by --
|
||||
-- the Free Software Foundation; either version 2 of the License, or (at --
|
||||
-- your option) any later version. --
|
||||
-- --
|
||||
-- This library is distributed in the hope that it will be useful, but --
|
||||
-- WITHOUT ANY WARRANTY; without even the implied warranty of --
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU --
|
||||
-- General Public License for more details. --
|
||||
-- --
|
||||
-- You should have received a copy of the GNU General Public License --
|
||||
-- along with this library; if not, write to the Free Software Foundation, --
|
||||
-- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. --
|
||||
-- --
|
||||
-- As a special exception, if other files instantiate generics from this --
|
||||
-- unit, or you link this unit with other files to produce an executable, --
|
||||
-- this unit does not by itself cause the resulting executable to be --
|
||||
-- covered by the GNU General Public License. This exception does not --
|
||||
-- however invalidate any other reasons why the executable file might be --
|
||||
-- covered by the GNU Public License. --
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
-- $Id$
|
||||
|
||||
with Ada.Streams;
|
||||
|
||||
with Interfaces;
|
||||
|
||||
package ZLib is
|
||||
|
||||
ZLib_Error : exception;
|
||||
Status_Error : exception;
|
||||
|
||||
type Compression_Level is new Integer range -1 .. 9;
|
||||
|
||||
type Flush_Mode is private;
|
||||
|
||||
type Compression_Method is private;
|
||||
|
||||
type Window_Bits_Type is new Integer range 8 .. 15;
|
||||
|
||||
type Memory_Level_Type is new Integer range 1 .. 9;
|
||||
|
||||
type Unsigned_32 is new Interfaces.Unsigned_32;
|
||||
|
||||
type Strategy_Type is private;
|
||||
|
||||
type Header_Type is (None, Auto, Default, GZip);
|
||||
-- Header type usage have a some limitation for inflate.
|
||||
-- See comment for Inflate_Init.
|
||||
|
||||
subtype Count is Ada.Streams.Stream_Element_Count;
|
||||
|
||||
Default_Memory_Level : constant Memory_Level_Type := 8;
|
||||
Default_Window_Bits : constant Window_Bits_Type := 15;
|
||||
|
||||
----------------------------------
|
||||
-- Compression method constants --
|
||||
----------------------------------
|
||||
|
||||
Deflated : constant Compression_Method;
|
||||
-- Only one method allowed in this ZLib version
|
||||
|
||||
---------------------------------
|
||||
-- Compression level constants --
|
||||
---------------------------------
|
||||
|
||||
No_Compression : constant Compression_Level := 0;
|
||||
Best_Speed : constant Compression_Level := 1;
|
||||
Best_Compression : constant Compression_Level := 9;
|
||||
Default_Compression : constant Compression_Level := -1;
|
||||
|
||||
--------------------------
|
||||
-- Flush mode constants --
|
||||
--------------------------
|
||||
|
||||
No_Flush : constant Flush_Mode;
|
||||
-- Regular way for compression, no flush
|
||||
|
||||
Partial_Flush : constant Flush_Mode;
|
||||
-- Will be removed, use Z_SYNC_FLUSH instead
|
||||
|
||||
Sync_Flush : constant Flush_Mode;
|
||||
-- All pending output is flushed to the output buffer and the output
|
||||
-- is aligned on a byte boundary, so that the decompressor can get all
|
||||
-- input data available so far. (In particular 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.
|
||||
|
||||
Block_Flush : constant Flush_Mode;
|
||||
-- Z_BLOCK requests that inflate() stop
|
||||
-- if and when it get to the next deflate block boundary. When decoding the
|
||||
-- zlib or gzip format, this will cause inflate() to return immediately
|
||||
-- after the header and before the first block. When doing a raw inflate,
|
||||
-- inflate() will go ahead and process the first block, and will return
|
||||
-- when it gets to the end of that block, or when it runs out of data.
|
||||
|
||||
Full_Flush : constant Flush_Mode;
|
||||
-- All output is flushed as with SYNC_FLUSH, and the compression state
|
||||
-- is reset so that decompression can restart from this point if previous
|
||||
-- compressed data has been damaged or if random access is desired. Using
|
||||
-- Full_Flush too often can seriously degrade the compression.
|
||||
|
||||
Finish : constant Flush_Mode;
|
||||
-- Just for tell the compressor that input data is complete.
|
||||
|
||||
------------------------------------
|
||||
-- Compression strategy constants --
|
||||
------------------------------------
|
||||
|
||||
-- RLE stategy could be used only in version 1.2.0 and later.
|
||||
|
||||
Filtered : constant Strategy_Type;
|
||||
Huffman_Only : constant Strategy_Type;
|
||||
RLE : constant Strategy_Type;
|
||||
Default_Strategy : constant Strategy_Type;
|
||||
|
||||
Default_Buffer_Size : constant := 4096;
|
||||
|
||||
type Filter_Type is tagged limited private;
|
||||
-- The filter is for compression and for decompression.
|
||||
-- The usage of the type is depend of its initialization.
|
||||
|
||||
function Version return String;
|
||||
pragma Inline (Version);
|
||||
-- Return string representation of the ZLib version.
|
||||
|
||||
procedure Deflate_Init
|
||||
(Filter : in out Filter_Type;
|
||||
Level : in Compression_Level := Default_Compression;
|
||||
Strategy : in Strategy_Type := Default_Strategy;
|
||||
Method : in Compression_Method := Deflated;
|
||||
Window_Bits : in Window_Bits_Type := Default_Window_Bits;
|
||||
Memory_Level : in Memory_Level_Type := Default_Memory_Level;
|
||||
Header : in Header_Type := Default);
|
||||
-- Compressor initialization.
|
||||
-- When Header parameter is Auto or Default, then default zlib header
|
||||
-- would be provided for compressed data.
|
||||
-- When Header is GZip, then gzip header would be set instead of
|
||||
-- default header.
|
||||
-- When Header is None, no header would be set for compressed data.
|
||||
|
||||
procedure Inflate_Init
|
||||
(Filter : in out Filter_Type;
|
||||
Window_Bits : in Window_Bits_Type := Default_Window_Bits;
|
||||
Header : in Header_Type := Default);
|
||||
-- Decompressor initialization.
|
||||
-- Default header type mean that ZLib default header is expecting in the
|
||||
-- input compressed stream.
|
||||
-- Header type None mean that no header is expecting in the input stream.
|
||||
-- GZip header type mean that GZip header is expecting in the
|
||||
-- input compressed stream.
|
||||
-- Auto header type mean that header type (GZip or Native) would be
|
||||
-- detected automatically in the input stream.
|
||||
-- Note that header types parameter values None, GZip and Auto are
|
||||
-- supported for inflate routine only in ZLib versions 1.2.0.2 and later.
|
||||
-- Deflate_Init is supporting all header types.
|
||||
|
||||
function Is_Open (Filter : in Filter_Type) return Boolean;
|
||||
pragma Inline (Is_Open);
|
||||
-- Is the filter opened for compression or decompression.
|
||||
|
||||
procedure Close
|
||||
(Filter : in out Filter_Type;
|
||||
Ignore_Error : in Boolean := False);
|
||||
-- Closing the compression or decompressor.
|
||||
-- If stream is closing before the complete and Ignore_Error is False,
|
||||
-- The exception would be raised.
|
||||
|
||||
generic
|
||||
with procedure Data_In
|
||||
(Item : out Ada.Streams.Stream_Element_Array;
|
||||
Last : out Ada.Streams.Stream_Element_Offset);
|
||||
with procedure Data_Out
|
||||
(Item : in Ada.Streams.Stream_Element_Array);
|
||||
procedure Generic_Translate
|
||||
(Filter : in out Filter_Type;
|
||||
In_Buffer_Size : in Integer := Default_Buffer_Size;
|
||||
Out_Buffer_Size : in Integer := Default_Buffer_Size);
|
||||
-- Compress/decompress data fetch from Data_In routine and pass the result
|
||||
-- to the Data_Out routine. User should provide Data_In and Data_Out
|
||||
-- for compression/decompression data flow.
|
||||
-- Compression or decompression depend on Filter initialization.
|
||||
|
||||
function Total_In (Filter : in Filter_Type) return Count;
|
||||
pragma Inline (Total_In);
|
||||
-- Returns total number of input bytes read so far
|
||||
|
||||
function Total_Out (Filter : in Filter_Type) return Count;
|
||||
pragma Inline (Total_Out);
|
||||
-- Returns total number of bytes output so far
|
||||
|
||||
function CRC32
|
||||
(CRC : in Unsigned_32;
|
||||
Data : in Ada.Streams.Stream_Element_Array)
|
||||
return Unsigned_32;
|
||||
pragma Inline (CRC32);
|
||||
-- Compute CRC32, it could be necessary for make gzip format
|
||||
|
||||
procedure CRC32
|
||||
(CRC : in out Unsigned_32;
|
||||
Data : in Ada.Streams.Stream_Element_Array);
|
||||
pragma Inline (CRC32);
|
||||
-- Compute CRC32, it could be necessary for make gzip format
|
||||
|
||||
-------------------------------------------------
|
||||
-- Below is more complex low level routines. --
|
||||
-------------------------------------------------
|
||||
|
||||
procedure Translate
|
||||
(Filter : in out Filter_Type;
|
||||
In_Data : in Ada.Streams.Stream_Element_Array;
|
||||
In_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Out_Data : out Ada.Streams.Stream_Element_Array;
|
||||
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Flush : in Flush_Mode);
|
||||
-- Compress/decompress the In_Data buffer and place the result into
|
||||
-- Out_Data. In_Last is the index of last element from In_Data accepted by
|
||||
-- the Filter. Out_Last is the last element of the received data from
|
||||
-- Filter. To tell the filter that incoming data are complete put the
|
||||
-- Flush parameter to Finish.
|
||||
|
||||
function Stream_End (Filter : in Filter_Type) return Boolean;
|
||||
pragma Inline (Stream_End);
|
||||
-- Return the true when the stream is complete.
|
||||
|
||||
procedure Flush
|
||||
(Filter : in out Filter_Type;
|
||||
Out_Data : out Ada.Streams.Stream_Element_Array;
|
||||
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Flush : in Flush_Mode);
|
||||
pragma Inline (Flush);
|
||||
-- Flushing the data from the compressor.
|
||||
|
||||
generic
|
||||
with procedure Write
|
||||
(Item : in Ada.Streams.Stream_Element_Array);
|
||||
-- User should provide this routine for accept
|
||||
-- compressed/decompressed data.
|
||||
|
||||
Buffer_Size : in Ada.Streams.Stream_Element_Offset
|
||||
:= Default_Buffer_Size;
|
||||
-- Buffer size for Write user routine.
|
||||
|
||||
procedure Write
|
||||
(Filter : in out Filter_Type;
|
||||
Item : in Ada.Streams.Stream_Element_Array;
|
||||
Flush : in Flush_Mode := No_Flush);
|
||||
-- Compress/Decompress data from Item to the generic parameter procedure
|
||||
-- Write. Output buffer size could be set in Buffer_Size generic parameter.
|
||||
|
||||
generic
|
||||
with procedure Read
|
||||
(Item : out Ada.Streams.Stream_Element_Array;
|
||||
Last : out Ada.Streams.Stream_Element_Offset);
|
||||
-- User should provide data for compression/decompression
|
||||
-- thru this routine.
|
||||
|
||||
Buffer : in out Ada.Streams.Stream_Element_Array;
|
||||
-- Buffer for keep remaining data from the previous
|
||||
-- back read.
|
||||
|
||||
Rest_First, Rest_Last : in out Ada.Streams.Stream_Element_Offset;
|
||||
-- Rest_First have to be initialized to Buffer'Last + 1
|
||||
-- Rest_Last have to be initialized to Buffer'Last
|
||||
-- before usage.
|
||||
|
||||
Allow_Read_Some : in Boolean := False;
|
||||
-- Is it allowed to return Last < Item'Last before end of data.
|
||||
|
||||
procedure Read
|
||||
(Filter : in out Filter_Type;
|
||||
Item : out Ada.Streams.Stream_Element_Array;
|
||||
Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Flush : in Flush_Mode := No_Flush);
|
||||
-- Compress/Decompress data from generic parameter procedure Read to the
|
||||
-- Item. User should provide Buffer and initialized Rest_First, Rest_Last
|
||||
-- indicators. If Allow_Read_Some is True, Read routines could return
|
||||
-- Last < Item'Last only at end of stream.
|
||||
|
||||
private
|
||||
|
||||
use Ada.Streams;
|
||||
|
||||
pragma Assert (Ada.Streams.Stream_Element'Size = 8);
|
||||
pragma Assert (Ada.Streams.Stream_Element'Modulus = 2**8);
|
||||
|
||||
type Flush_Mode is new Integer range 0 .. 5;
|
||||
|
||||
type Compression_Method is new Integer range 8 .. 8;
|
||||
|
||||
type Strategy_Type is new Integer range 0 .. 3;
|
||||
|
||||
No_Flush : constant Flush_Mode := 0;
|
||||
Partial_Flush : constant Flush_Mode := 1;
|
||||
Sync_Flush : constant Flush_Mode := 2;
|
||||
Full_Flush : constant Flush_Mode := 3;
|
||||
Finish : constant Flush_Mode := 4;
|
||||
Block_Flush : constant Flush_Mode := 5;
|
||||
|
||||
Filtered : constant Strategy_Type := 1;
|
||||
Huffman_Only : constant Strategy_Type := 2;
|
||||
RLE : constant Strategy_Type := 3;
|
||||
Default_Strategy : constant Strategy_Type := 0;
|
||||
|
||||
Deflated : constant Compression_Method := 8;
|
||||
|
||||
type Z_Stream;
|
||||
|
||||
type Z_Stream_Access is access all Z_Stream;
|
||||
|
||||
type Filter_Type is tagged limited record
|
||||
Strm : Z_Stream_Access;
|
||||
Compression : Boolean;
|
||||
Stream_End : Boolean;
|
||||
Header : Header_Type;
|
||||
CRC : Unsigned_32;
|
||||
Offset : Stream_Element_Offset;
|
||||
-- Offset for gzip header/footer output.
|
||||
end record;
|
||||
|
||||
end ZLib;
|
||||
@@ -0,0 +1,20 @@
|
||||
project Zlib is
|
||||
|
||||
for Languages use ("Ada");
|
||||
for Source_Dirs use (".");
|
||||
for Object_Dir use ".";
|
||||
for Main use ("test.adb", "mtest.adb", "read.adb", "buffer_demo");
|
||||
|
||||
package Compiler is
|
||||
for Default_Switches ("ada") use ("-gnatwcfilopru", "-gnatVcdfimorst", "-gnatyabcefhiklmnoprst");
|
||||
end Compiler;
|
||||
|
||||
package Linker is
|
||||
for Default_Switches ("ada") use ("-lz");
|
||||
end Linker;
|
||||
|
||||
package Builder is
|
||||
for Default_Switches ("ada") use ("-s", "-gnatQ");
|
||||
end Builder;
|
||||
|
||||
end Zlib;
|
||||
@@ -0,0 +1,43 @@
|
||||
This is a patched version of zlib modified to use
|
||||
Pentium-optimized assembly code in the deflation algorithm. The files
|
||||
changed/added by this patch are:
|
||||
|
||||
README.586
|
||||
match.S
|
||||
|
||||
The effectiveness of these modifications is a bit marginal, as the the
|
||||
program's bottleneck seems to be mostly L1-cache contention, for which
|
||||
there is no real way to work around without rewriting the basic
|
||||
algorithm. The speedup on average is around 5-10% (which is generally
|
||||
less than the amount of variance between subsequent executions).
|
||||
However, when used at level 9 compression, the cache contention can
|
||||
drop enough for the assembly version to achieve 10-20% speedup (and
|
||||
sometimes more, depending on the amount of overall redundancy in the
|
||||
files). Even here, though, cache contention can still be the limiting
|
||||
factor, depending on the nature of the program using the zlib library.
|
||||
This may also mean that better improvements will be seen on a Pentium
|
||||
with MMX, which suffers much less from L1-cache contention, but I have
|
||||
not yet verified this.
|
||||
|
||||
Note that this code has been tailored for the Pentium in particular,
|
||||
and will not perform well on the Pentium Pro (due to the use of a
|
||||
partial register in the inner loop).
|
||||
|
||||
If you are using an assembler other than GNU as, you will have to
|
||||
translate match.S to use your assembler's syntax. (Have fun.)
|
||||
|
||||
Brian Raiter
|
||||
breadbox@muppetlabs.com
|
||||
April, 1998
|
||||
|
||||
|
||||
Added for zlib 1.1.3:
|
||||
|
||||
The patches come from
|
||||
http://www.muppetlabs.com/~breadbox/software/assembly.html
|
||||
|
||||
To compile zlib with this asm file, copy match.S to the zlib directory
|
||||
then do:
|
||||
|
||||
CFLAGS="-O3 -DASMV" ./configure
|
||||
make OBJA=match.o
|
||||
@@ -0,0 +1,354 @@
|
||||
/* match.s -- Pentium-optimized version of longest_match()
|
||||
* Written for zlib 1.1.2
|
||||
* Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License.
|
||||
*/
|
||||
|
||||
#ifndef NO_UNDERLINE
|
||||
#define match_init _match_init
|
||||
#define longest_match _longest_match
|
||||
#endif
|
||||
|
||||
#define MAX_MATCH (258)
|
||||
#define MIN_MATCH (3)
|
||||
#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
|
||||
#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7)
|
||||
|
||||
/* stack frame offsets */
|
||||
|
||||
#define wmask 0 /* local copy of s->wmask */
|
||||
#define window 4 /* local copy of s->window */
|
||||
#define windowbestlen 8 /* s->window + bestlen */
|
||||
#define chainlenscanend 12 /* high word: current chain len */
|
||||
/* low word: last bytes sought */
|
||||
#define scanstart 16 /* first two bytes of string */
|
||||
#define scanalign 20 /* dword-misalignment of string */
|
||||
#define nicematch 24 /* a good enough match size */
|
||||
#define bestlen 28 /* size of best match so far */
|
||||
#define scan 32 /* ptr to string wanting match */
|
||||
|
||||
#define LocalVarsSize (36)
|
||||
/* saved ebx 36 */
|
||||
/* saved edi 40 */
|
||||
/* saved esi 44 */
|
||||
/* saved ebp 48 */
|
||||
/* return address 52 */
|
||||
#define deflatestate 56 /* the function arguments */
|
||||
#define curmatch 60
|
||||
|
||||
/* Offsets for fields in the deflate_state structure. These numbers
|
||||
* are calculated from the definition of deflate_state, with the
|
||||
* assumption that the compiler will dword-align the fields. (Thus,
|
||||
* changing the definition of deflate_state could easily cause this
|
||||
* program to crash horribly, without so much as a warning at
|
||||
* compile time. Sigh.)
|
||||
*/
|
||||
#define dsWSize 36
|
||||
#define dsWMask 44
|
||||
#define dsWindow 48
|
||||
#define dsPrev 56
|
||||
#define dsMatchLen 88
|
||||
#define dsPrevMatch 92
|
||||
#define dsStrStart 100
|
||||
#define dsMatchStart 104
|
||||
#define dsLookahead 108
|
||||
#define dsPrevLen 112
|
||||
#define dsMaxChainLen 116
|
||||
#define dsGoodMatch 132
|
||||
#define dsNiceMatch 136
|
||||
|
||||
|
||||
.file "match.S"
|
||||
|
||||
.globl match_init, longest_match
|
||||
|
||||
.text
|
||||
|
||||
/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
|
||||
|
||||
longest_match:
|
||||
|
||||
/* Save registers that the compiler may be using, and adjust %esp to */
|
||||
/* make room for our stack frame. */
|
||||
|
||||
pushl %ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %ebx
|
||||
subl $LocalVarsSize, %esp
|
||||
|
||||
/* Retrieve the function arguments. %ecx will hold cur_match */
|
||||
/* throughout the entire function. %edx will hold the pointer to the */
|
||||
/* deflate_state structure during the function's setup (before */
|
||||
/* entering the main loop). */
|
||||
|
||||
movl deflatestate(%esp), %edx
|
||||
movl curmatch(%esp), %ecx
|
||||
|
||||
/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */
|
||||
|
||||
movl dsNiceMatch(%edx), %eax
|
||||
movl dsLookahead(%edx), %ebx
|
||||
cmpl %eax, %ebx
|
||||
jl LookaheadLess
|
||||
movl %eax, %ebx
|
||||
LookaheadLess: movl %ebx, nicematch(%esp)
|
||||
|
||||
/* register Bytef *scan = s->window + s->strstart; */
|
||||
|
||||
movl dsWindow(%edx), %esi
|
||||
movl %esi, window(%esp)
|
||||
movl dsStrStart(%edx), %ebp
|
||||
lea (%esi,%ebp), %edi
|
||||
movl %edi, scan(%esp)
|
||||
|
||||
/* Determine how many bytes the scan ptr is off from being */
|
||||
/* dword-aligned. */
|
||||
|
||||
movl %edi, %eax
|
||||
negl %eax
|
||||
andl $3, %eax
|
||||
movl %eax, scanalign(%esp)
|
||||
|
||||
/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
|
||||
/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
|
||||
|
||||
movl dsWSize(%edx), %eax
|
||||
subl $MIN_LOOKAHEAD, %eax
|
||||
subl %eax, %ebp
|
||||
jg LimitPositive
|
||||
xorl %ebp, %ebp
|
||||
LimitPositive:
|
||||
|
||||
/* unsigned chain_length = s->max_chain_length; */
|
||||
/* if (s->prev_length >= s->good_match) { */
|
||||
/* chain_length >>= 2; */
|
||||
/* } */
|
||||
|
||||
movl dsPrevLen(%edx), %eax
|
||||
movl dsGoodMatch(%edx), %ebx
|
||||
cmpl %ebx, %eax
|
||||
movl dsMaxChainLen(%edx), %ebx
|
||||
jl LastMatchGood
|
||||
shrl $2, %ebx
|
||||
LastMatchGood:
|
||||
|
||||
/* chainlen is decremented once beforehand so that the function can */
|
||||
/* use the sign flag instead of the zero flag for the exit test. */
|
||||
/* It is then shifted into the high word, to make room for the scanend */
|
||||
/* scanend value, which it will always accompany. */
|
||||
|
||||
decl %ebx
|
||||
shll $16, %ebx
|
||||
|
||||
/* int best_len = s->prev_length; */
|
||||
|
||||
movl dsPrevLen(%edx), %eax
|
||||
movl %eax, bestlen(%esp)
|
||||
|
||||
/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
|
||||
|
||||
addl %eax, %esi
|
||||
movl %esi, windowbestlen(%esp)
|
||||
|
||||
/* register ush scan_start = *(ushf*)scan; */
|
||||
/* register ush scan_end = *(ushf*)(scan+best_len-1); */
|
||||
|
||||
movw (%edi), %bx
|
||||
movw %bx, scanstart(%esp)
|
||||
movw -1(%edi,%eax), %bx
|
||||
movl %ebx, chainlenscanend(%esp)
|
||||
|
||||
/* Posf *prev = s->prev; */
|
||||
/* uInt wmask = s->w_mask; */
|
||||
|
||||
movl dsPrev(%edx), %edi
|
||||
movl dsWMask(%edx), %edx
|
||||
mov %edx, wmask(%esp)
|
||||
|
||||
/* Jump into the main loop. */
|
||||
|
||||
jmp LoopEntry
|
||||
|
||||
.balign 16
|
||||
|
||||
/* do {
|
||||
* match = s->window + cur_match;
|
||||
* if (*(ushf*)(match+best_len-1) != scan_end ||
|
||||
* *(ushf*)match != scan_start) continue;
|
||||
* [...]
|
||||
* } while ((cur_match = prev[cur_match & wmask]) > limit
|
||||
* && --chain_length != 0);
|
||||
*
|
||||
* Here is the inner loop of the function. The function will spend the
|
||||
* majority of its time in this loop, and majority of that time will
|
||||
* be spent in the first ten instructions.
|
||||
*
|
||||
* Within this loop:
|
||||
* %ebx = chainlenscanend - i.e., ((chainlen << 16) | scanend)
|
||||
* %ecx = curmatch
|
||||
* %edx = curmatch & wmask
|
||||
* %esi = windowbestlen - i.e., (window + bestlen)
|
||||
* %edi = prev
|
||||
* %ebp = limit
|
||||
*
|
||||
* Two optimization notes on the choice of instructions:
|
||||
*
|
||||
* The first instruction uses a 16-bit address, which costs an extra,
|
||||
* unpairable cycle. This is cheaper than doing a 32-bit access and
|
||||
* zeroing the high word, due to the 3-cycle misalignment penalty which
|
||||
* would occur half the time. This also turns out to be cheaper than
|
||||
* doing two separate 8-bit accesses, as the memory is so rarely in the
|
||||
* L1 cache.
|
||||
*
|
||||
* The window buffer, however, apparently spends a lot of time in the
|
||||
* cache, and so it is faster to retrieve the word at the end of the
|
||||
* match string with two 8-bit loads. The instructions that test the
|
||||
* word at the beginning of the match string, however, are executed
|
||||
* much less frequently, and there it was cheaper to use 16-bit
|
||||
* instructions, which avoided the necessity of saving off and
|
||||
* subsequently reloading one of the other registers.
|
||||
*/
|
||||
LookupLoop:
|
||||
/* 1 U & V */
|
||||
movw (%edi,%edx,2), %cx /* 2 U pipe */
|
||||
movl wmask(%esp), %edx /* 2 V pipe */
|
||||
cmpl %ebp, %ecx /* 3 U pipe */
|
||||
jbe LeaveNow /* 3 V pipe */
|
||||
subl $0x00010000, %ebx /* 4 U pipe */
|
||||
js LeaveNow /* 4 V pipe */
|
||||
LoopEntry: movb -1(%esi,%ecx), %al /* 5 U pipe */
|
||||
andl %ecx, %edx /* 5 V pipe */
|
||||
cmpb %bl, %al /* 6 U pipe */
|
||||
jnz LookupLoop /* 6 V pipe */
|
||||
movb (%esi,%ecx), %ah
|
||||
cmpb %bh, %ah
|
||||
jnz LookupLoop
|
||||
movl window(%esp), %eax
|
||||
movw (%eax,%ecx), %ax
|
||||
cmpw scanstart(%esp), %ax
|
||||
jnz LookupLoop
|
||||
|
||||
/* Store the current value of chainlen. */
|
||||
|
||||
movl %ebx, chainlenscanend(%esp)
|
||||
|
||||
/* Point %edi to the string under scrutiny, and %esi to the string we */
|
||||
/* are hoping to match it up with. In actuality, %esi and %edi are */
|
||||
/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */
|
||||
/* initialized to -(MAX_MATCH_8 - scanalign). */
|
||||
|
||||
movl window(%esp), %esi
|
||||
movl scan(%esp), %edi
|
||||
addl %ecx, %esi
|
||||
movl scanalign(%esp), %eax
|
||||
movl $(-MAX_MATCH_8), %edx
|
||||
lea MAX_MATCH_8(%edi,%eax), %edi
|
||||
lea MAX_MATCH_8(%esi,%eax), %esi
|
||||
|
||||
/* Test the strings for equality, 8 bytes at a time. At the end,
|
||||
* adjust %edx so that it is offset to the exact byte that mismatched.
|
||||
*
|
||||
* We already know at this point that the first three bytes of the
|
||||
* strings match each other, and they can be safely passed over before
|
||||
* starting the compare loop. So what this code does is skip over 0-3
|
||||
* bytes, as much as necessary in order to dword-align the %edi
|
||||
* pointer. (%esi will still be misaligned three times out of four.)
|
||||
*
|
||||
* It should be confessed that this loop usually does not represent
|
||||
* much of the total running time. Replacing it with a more
|
||||
* straightforward "rep cmpsb" would not drastically degrade
|
||||
* performance.
|
||||
*/
|
||||
LoopCmps:
|
||||
movl (%esi,%edx), %eax
|
||||
movl (%edi,%edx), %ebx
|
||||
xorl %ebx, %eax
|
||||
jnz LeaveLoopCmps
|
||||
movl 4(%esi,%edx), %eax
|
||||
movl 4(%edi,%edx), %ebx
|
||||
xorl %ebx, %eax
|
||||
jnz LeaveLoopCmps4
|
||||
addl $8, %edx
|
||||
jnz LoopCmps
|
||||
jmp LenMaximum
|
||||
LeaveLoopCmps4: addl $4, %edx
|
||||
LeaveLoopCmps: testl $0x0000FFFF, %eax
|
||||
jnz LenLower
|
||||
addl $2, %edx
|
||||
shrl $16, %eax
|
||||
LenLower: subb $1, %al
|
||||
adcl $0, %edx
|
||||
|
||||
/* Calculate the length of the match. If it is longer than MAX_MATCH, */
|
||||
/* then automatically accept it as the best possible match and leave. */
|
||||
|
||||
lea (%edi,%edx), %eax
|
||||
movl scan(%esp), %edi
|
||||
subl %edi, %eax
|
||||
cmpl $MAX_MATCH, %eax
|
||||
jge LenMaximum
|
||||
|
||||
/* If the length of the match is not longer than the best match we */
|
||||
/* have so far, then forget it and return to the lookup loop. */
|
||||
|
||||
movl deflatestate(%esp), %edx
|
||||
movl bestlen(%esp), %ebx
|
||||
cmpl %ebx, %eax
|
||||
jg LongerMatch
|
||||
movl chainlenscanend(%esp), %ebx
|
||||
movl windowbestlen(%esp), %esi
|
||||
movl dsPrev(%edx), %edi
|
||||
movl wmask(%esp), %edx
|
||||
andl %ecx, %edx
|
||||
jmp LookupLoop
|
||||
|
||||
/* s->match_start = cur_match; */
|
||||
/* best_len = len; */
|
||||
/* if (len >= nice_match) break; */
|
||||
/* scan_end = *(ushf*)(scan+best_len-1); */
|
||||
|
||||
LongerMatch: movl nicematch(%esp), %ebx
|
||||
movl %eax, bestlen(%esp)
|
||||
movl %ecx, dsMatchStart(%edx)
|
||||
cmpl %ebx, %eax
|
||||
jge LeaveNow
|
||||
movl window(%esp), %esi
|
||||
addl %eax, %esi
|
||||
movl %esi, windowbestlen(%esp)
|
||||
movl chainlenscanend(%esp), %ebx
|
||||
movw -1(%edi,%eax), %bx
|
||||
movl dsPrev(%edx), %edi
|
||||
movl %ebx, chainlenscanend(%esp)
|
||||
movl wmask(%esp), %edx
|
||||
andl %ecx, %edx
|
||||
jmp LookupLoop
|
||||
|
||||
/* Accept the current string, with the maximum possible length. */
|
||||
|
||||
LenMaximum: movl deflatestate(%esp), %edx
|
||||
movl $MAX_MATCH, bestlen(%esp)
|
||||
movl %ecx, dsMatchStart(%edx)
|
||||
|
||||
/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
|
||||
/* return s->lookahead; */
|
||||
|
||||
LeaveNow:
|
||||
movl deflatestate(%esp), %edx
|
||||
movl bestlen(%esp), %ebx
|
||||
movl dsLookahead(%edx), %eax
|
||||
cmpl %eax, %ebx
|
||||
jg LookaheadRet
|
||||
movl %ebx, %eax
|
||||
LookaheadRet:
|
||||
|
||||
/* Restore the stack and return from whence we came. */
|
||||
|
||||
addl $LocalVarsSize, %esp
|
||||
popl %ebx
|
||||
popl %esi
|
||||
popl %edi
|
||||
popl %ebp
|
||||
match_init: ret
|
||||
@@ -0,0 +1,34 @@
|
||||
This is a patched version of zlib, modified to use
|
||||
Pentium-Pro-optimized assembly code in the deflation algorithm. The
|
||||
files changed/added by this patch are:
|
||||
|
||||
README.686
|
||||
match.S
|
||||
|
||||
The speedup that this patch provides varies, depending on whether the
|
||||
compiler used to build the original version of zlib falls afoul of the
|
||||
PPro's speed traps. My own tests show a speedup of around 10-20% at
|
||||
the default compression level, and 20-30% using -9, against a version
|
||||
compiled using gcc 2.7.2.3. Your mileage may vary.
|
||||
|
||||
Note that this code has been tailored for the PPro/PII in particular,
|
||||
and will not perform particuarly well on a Pentium.
|
||||
|
||||
If you are using an assembler other than GNU as, you will have to
|
||||
translate match.S to use your assembler's syntax. (Have fun.)
|
||||
|
||||
Brian Raiter
|
||||
breadbox@muppetlabs.com
|
||||
April, 1998
|
||||
|
||||
|
||||
Added for zlib 1.1.3:
|
||||
|
||||
The patches come from
|
||||
http://www.muppetlabs.com/~breadbox/software/assembly.html
|
||||
|
||||
To compile zlib with this asm file, copy match.S to the zlib directory
|
||||
then do:
|
||||
|
||||
CFLAGS="-O3 -DASMV" ./configure
|
||||
make OBJA=match.o
|
||||
@@ -0,0 +1,327 @@
|
||||
/* match.s -- Pentium-Pro-optimized version of longest_match()
|
||||
* Written for zlib 1.1.2
|
||||
* Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License.
|
||||
*/
|
||||
|
||||
#ifndef NO_UNDERLINE
|
||||
#define match_init _match_init
|
||||
#define longest_match _longest_match
|
||||
#endif
|
||||
|
||||
#define MAX_MATCH (258)
|
||||
#define MIN_MATCH (3)
|
||||
#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
|
||||
#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7)
|
||||
|
||||
/* stack frame offsets */
|
||||
|
||||
#define chainlenwmask 0 /* high word: current chain len */
|
||||
/* low word: s->wmask */
|
||||
#define window 4 /* local copy of s->window */
|
||||
#define windowbestlen 8 /* s->window + bestlen */
|
||||
#define scanstart 16 /* first two bytes of string */
|
||||
#define scanend 12 /* last two bytes of string */
|
||||
#define scanalign 20 /* dword-misalignment of string */
|
||||
#define nicematch 24 /* a good enough match size */
|
||||
#define bestlen 28 /* size of best match so far */
|
||||
#define scan 32 /* ptr to string wanting match */
|
||||
|
||||
#define LocalVarsSize (36)
|
||||
/* saved ebx 36 */
|
||||
/* saved edi 40 */
|
||||
/* saved esi 44 */
|
||||
/* saved ebp 48 */
|
||||
/* return address 52 */
|
||||
#define deflatestate 56 /* the function arguments */
|
||||
#define curmatch 60
|
||||
|
||||
/* Offsets for fields in the deflate_state structure. These numbers
|
||||
* are calculated from the definition of deflate_state, with the
|
||||
* assumption that the compiler will dword-align the fields. (Thus,
|
||||
* changing the definition of deflate_state could easily cause this
|
||||
* program to crash horribly, without so much as a warning at
|
||||
* compile time. Sigh.)
|
||||
*/
|
||||
#define dsWSize 36
|
||||
#define dsWMask 44
|
||||
#define dsWindow 48
|
||||
#define dsPrev 56
|
||||
#define dsMatchLen 88
|
||||
#define dsPrevMatch 92
|
||||
#define dsStrStart 100
|
||||
#define dsMatchStart 104
|
||||
#define dsLookahead 108
|
||||
#define dsPrevLen 112
|
||||
#define dsMaxChainLen 116
|
||||
#define dsGoodMatch 132
|
||||
#define dsNiceMatch 136
|
||||
|
||||
|
||||
.file "match.S"
|
||||
|
||||
.globl match_init, longest_match
|
||||
|
||||
.text
|
||||
|
||||
/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
|
||||
|
||||
longest_match:
|
||||
|
||||
/* Save registers that the compiler may be using, and adjust %esp to */
|
||||
/* make room for our stack frame. */
|
||||
|
||||
pushl %ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %ebx
|
||||
subl $LocalVarsSize, %esp
|
||||
|
||||
/* Retrieve the function arguments. %ecx will hold cur_match */
|
||||
/* throughout the entire function. %edx will hold the pointer to the */
|
||||
/* deflate_state structure during the function's setup (before */
|
||||
/* entering the main loop). */
|
||||
|
||||
movl deflatestate(%esp), %edx
|
||||
movl curmatch(%esp), %ecx
|
||||
|
||||
/* uInt wmask = s->w_mask; */
|
||||
/* unsigned chain_length = s->max_chain_length; */
|
||||
/* if (s->prev_length >= s->good_match) { */
|
||||
/* chain_length >>= 2; */
|
||||
/* } */
|
||||
|
||||
movl dsPrevLen(%edx), %eax
|
||||
movl dsGoodMatch(%edx), %ebx
|
||||
cmpl %ebx, %eax
|
||||
movl dsWMask(%edx), %eax
|
||||
movl dsMaxChainLen(%edx), %ebx
|
||||
jl LastMatchGood
|
||||
shrl $2, %ebx
|
||||
LastMatchGood:
|
||||
|
||||
/* chainlen is decremented once beforehand so that the function can */
|
||||
/* use the sign flag instead of the zero flag for the exit test. */
|
||||
/* It is then shifted into the high word, to make room for the wmask */
|
||||
/* value, which it will always accompany. */
|
||||
|
||||
decl %ebx
|
||||
shll $16, %ebx
|
||||
orl %eax, %ebx
|
||||
movl %ebx, chainlenwmask(%esp)
|
||||
|
||||
/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */
|
||||
|
||||
movl dsNiceMatch(%edx), %eax
|
||||
movl dsLookahead(%edx), %ebx
|
||||
cmpl %eax, %ebx
|
||||
jl LookaheadLess
|
||||
movl %eax, %ebx
|
||||
LookaheadLess: movl %ebx, nicematch(%esp)
|
||||
|
||||
/* register Bytef *scan = s->window + s->strstart; */
|
||||
|
||||
movl dsWindow(%edx), %esi
|
||||
movl %esi, window(%esp)
|
||||
movl dsStrStart(%edx), %ebp
|
||||
lea (%esi,%ebp), %edi
|
||||
movl %edi, scan(%esp)
|
||||
|
||||
/* Determine how many bytes the scan ptr is off from being */
|
||||
/* dword-aligned. */
|
||||
|
||||
movl %edi, %eax
|
||||
negl %eax
|
||||
andl $3, %eax
|
||||
movl %eax, scanalign(%esp)
|
||||
|
||||
/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
|
||||
/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
|
||||
|
||||
movl dsWSize(%edx), %eax
|
||||
subl $MIN_LOOKAHEAD, %eax
|
||||
subl %eax, %ebp
|
||||
jg LimitPositive
|
||||
xorl %ebp, %ebp
|
||||
LimitPositive:
|
||||
|
||||
/* int best_len = s->prev_length; */
|
||||
|
||||
movl dsPrevLen(%edx), %eax
|
||||
movl %eax, bestlen(%esp)
|
||||
|
||||
/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
|
||||
|
||||
addl %eax, %esi
|
||||
movl %esi, windowbestlen(%esp)
|
||||
|
||||
/* register ush scan_start = *(ushf*)scan; */
|
||||
/* register ush scan_end = *(ushf*)(scan+best_len-1); */
|
||||
/* Posf *prev = s->prev; */
|
||||
|
||||
movzwl (%edi), %ebx
|
||||
movl %ebx, scanstart(%esp)
|
||||
movzwl -1(%edi,%eax), %ebx
|
||||
movl %ebx, scanend(%esp)
|
||||
movl dsPrev(%edx), %edi
|
||||
|
||||
/* Jump into the main loop. */
|
||||
|
||||
movl chainlenwmask(%esp), %edx
|
||||
jmp LoopEntry
|
||||
|
||||
.balign 16
|
||||
|
||||
/* do {
|
||||
* match = s->window + cur_match;
|
||||
* if (*(ushf*)(match+best_len-1) != scan_end ||
|
||||
* *(ushf*)match != scan_start) continue;
|
||||
* [...]
|
||||
* } while ((cur_match = prev[cur_match & wmask]) > limit
|
||||
* && --chain_length != 0);
|
||||
*
|
||||
* Here is the inner loop of the function. The function will spend the
|
||||
* majority of its time in this loop, and majority of that time will
|
||||
* be spent in the first ten instructions.
|
||||
*
|
||||
* Within this loop:
|
||||
* %ebx = scanend
|
||||
* %ecx = curmatch
|
||||
* %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
|
||||
* %esi = windowbestlen - i.e., (window + bestlen)
|
||||
* %edi = prev
|
||||
* %ebp = limit
|
||||
*/
|
||||
LookupLoop:
|
||||
andl %edx, %ecx
|
||||
movzwl (%edi,%ecx,2), %ecx
|
||||
cmpl %ebp, %ecx
|
||||
jbe LeaveNow
|
||||
subl $0x00010000, %edx
|
||||
js LeaveNow
|
||||
LoopEntry: movzwl -1(%esi,%ecx), %eax
|
||||
cmpl %ebx, %eax
|
||||
jnz LookupLoop
|
||||
movl window(%esp), %eax
|
||||
movzwl (%eax,%ecx), %eax
|
||||
cmpl scanstart(%esp), %eax
|
||||
jnz LookupLoop
|
||||
|
||||
/* Store the current value of chainlen. */
|
||||
|
||||
movl %edx, chainlenwmask(%esp)
|
||||
|
||||
/* Point %edi to the string under scrutiny, and %esi to the string we */
|
||||
/* are hoping to match it up with. In actuality, %esi and %edi are */
|
||||
/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */
|
||||
/* initialized to -(MAX_MATCH_8 - scanalign). */
|
||||
|
||||
movl window(%esp), %esi
|
||||
movl scan(%esp), %edi
|
||||
addl %ecx, %esi
|
||||
movl scanalign(%esp), %eax
|
||||
movl $(-MAX_MATCH_8), %edx
|
||||
lea MAX_MATCH_8(%edi,%eax), %edi
|
||||
lea MAX_MATCH_8(%esi,%eax), %esi
|
||||
|
||||
/* Test the strings for equality, 8 bytes at a time. At the end,
|
||||
* adjust %edx so that it is offset to the exact byte that mismatched.
|
||||
*
|
||||
* We already know at this point that the first three bytes of the
|
||||
* strings match each other, and they can be safely passed over before
|
||||
* starting the compare loop. So what this code does is skip over 0-3
|
||||
* bytes, as much as necessary in order to dword-align the %edi
|
||||
* pointer. (%esi will still be misaligned three times out of four.)
|
||||
*
|
||||
* It should be confessed that this loop usually does not represent
|
||||
* much of the total running time. Replacing it with a more
|
||||
* straightforward "rep cmpsb" would not drastically degrade
|
||||
* performance.
|
||||
*/
|
||||
LoopCmps:
|
||||
movl (%esi,%edx), %eax
|
||||
xorl (%edi,%edx), %eax
|
||||
jnz LeaveLoopCmps
|
||||
movl 4(%esi,%edx), %eax
|
||||
xorl 4(%edi,%edx), %eax
|
||||
jnz LeaveLoopCmps4
|
||||
addl $8, %edx
|
||||
jnz LoopCmps
|
||||
jmp LenMaximum
|
||||
LeaveLoopCmps4: addl $4, %edx
|
||||
LeaveLoopCmps: testl $0x0000FFFF, %eax
|
||||
jnz LenLower
|
||||
addl $2, %edx
|
||||
shrl $16, %eax
|
||||
LenLower: subb $1, %al
|
||||
adcl $0, %edx
|
||||
|
||||
/* Calculate the length of the match. If it is longer than MAX_MATCH, */
|
||||
/* then automatically accept it as the best possible match and leave. */
|
||||
|
||||
lea (%edi,%edx), %eax
|
||||
movl scan(%esp), %edi
|
||||
subl %edi, %eax
|
||||
cmpl $MAX_MATCH, %eax
|
||||
jge LenMaximum
|
||||
|
||||
/* If the length of the match is not longer than the best match we */
|
||||
/* have so far, then forget it and return to the lookup loop. */
|
||||
|
||||
movl deflatestate(%esp), %edx
|
||||
movl bestlen(%esp), %ebx
|
||||
cmpl %ebx, %eax
|
||||
jg LongerMatch
|
||||
movl windowbestlen(%esp), %esi
|
||||
movl dsPrev(%edx), %edi
|
||||
movl scanend(%esp), %ebx
|
||||
movl chainlenwmask(%esp), %edx
|
||||
jmp LookupLoop
|
||||
|
||||
/* s->match_start = cur_match; */
|
||||
/* best_len = len; */
|
||||
/* if (len >= nice_match) break; */
|
||||
/* scan_end = *(ushf*)(scan+best_len-1); */
|
||||
|
||||
LongerMatch: movl nicematch(%esp), %ebx
|
||||
movl %eax, bestlen(%esp)
|
||||
movl %ecx, dsMatchStart(%edx)
|
||||
cmpl %ebx, %eax
|
||||
jge LeaveNow
|
||||
movl window(%esp), %esi
|
||||
addl %eax, %esi
|
||||
movl %esi, windowbestlen(%esp)
|
||||
movzwl -1(%edi,%eax), %ebx
|
||||
movl dsPrev(%edx), %edi
|
||||
movl %ebx, scanend(%esp)
|
||||
movl chainlenwmask(%esp), %edx
|
||||
jmp LookupLoop
|
||||
|
||||
/* Accept the current string, with the maximum possible length. */
|
||||
|
||||
LenMaximum: movl deflatestate(%esp), %edx
|
||||
movl $MAX_MATCH, bestlen(%esp)
|
||||
movl %ecx, dsMatchStart(%edx)
|
||||
|
||||
/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
|
||||
/* return s->lookahead; */
|
||||
|
||||
LeaveNow:
|
||||
movl deflatestate(%esp), %edx
|
||||
movl bestlen(%esp), %ebx
|
||||
movl dsLookahead(%edx), %eax
|
||||
cmpl %eax, %ebx
|
||||
jg LookaheadRet
|
||||
movl %ebx, %eax
|
||||
LookaheadRet:
|
||||
|
||||
/* Restore the stack and return from whence we came. */
|
||||
|
||||
addl $LocalVarsSize, %esp
|
||||
popl %ebx
|
||||
popl %esi
|
||||
popl %edi
|
||||
popl %ebp
|
||||
match_init: ret
|
||||
@@ -0,0 +1,8 @@
|
||||
blast: blast.c blast.h
|
||||
cc -DTEST -o blast blast.c
|
||||
|
||||
test: blast
|
||||
blast < test.pk | cmp - test.txt
|
||||
|
||||
clean:
|
||||
rm -f blast blast.o
|
||||
@@ -0,0 +1,4 @@
|
||||
Read blast.h for purpose and usage.
|
||||
|
||||
Mark Adler
|
||||
madler@alumni.caltech.edu
|
||||
@@ -0,0 +1,444 @@
|
||||
/* blast.c
|
||||
* Copyright (C) 2003 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in blast.h
|
||||
* version 1.1, 16 Feb 2003
|
||||
*
|
||||
* blast.c decompresses data compressed by the PKWare Compression Library.
|
||||
* This function provides functionality similar to the explode() function of
|
||||
* the PKWare library, hence the name "blast".
|
||||
*
|
||||
* This decompressor is based on the excellent format description provided by
|
||||
* Ben Rudiak-Gould in comp.compression on August 13, 2001. Interestingly, the
|
||||
* example Ben provided in the post is incorrect. The distance 110001 should
|
||||
* instead be 111000. When corrected, the example byte stream becomes:
|
||||
*
|
||||
* 00 04 82 24 25 8f 80 7f
|
||||
*
|
||||
* which decompresses to "AIAIAIAIAIAIA" (without the quotes).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Change history:
|
||||
*
|
||||
* 1.0 12 Feb 2003 - First version
|
||||
* 1.1 16 Feb 2003 - Fixed distance check for > 4 GB uncompressed data
|
||||
*/
|
||||
|
||||
#include <setjmp.h> /* for setjmp(), longjmp(), and jmp_buf */
|
||||
#include "blast.h" /* prototype for blast() */
|
||||
|
||||
#define local static /* for local function definitions */
|
||||
#define MAXBITS 13 /* maximum code length */
|
||||
#define MAXWIN 4096 /* maximum window size */
|
||||
|
||||
/* input and output state */
|
||||
struct state {
|
||||
/* input state */
|
||||
blast_in infun; /* input function provided by user */
|
||||
void *inhow; /* opaque information passed to infun() */
|
||||
unsigned char *in; /* next input location */
|
||||
unsigned left; /* available input at in */
|
||||
int bitbuf; /* bit buffer */
|
||||
int bitcnt; /* number of bits in bit buffer */
|
||||
|
||||
/* input limit error return state for bits() and decode() */
|
||||
jmp_buf env;
|
||||
|
||||
/* output state */
|
||||
blast_out outfun; /* output function provided by user */
|
||||
void *outhow; /* opaque information passed to outfun() */
|
||||
unsigned next; /* index of next write location in out[] */
|
||||
int first; /* true to check distances (for first 4K) */
|
||||
unsigned char out[MAXWIN]; /* output buffer and sliding window */
|
||||
};
|
||||
|
||||
/*
|
||||
* Return need bits from the input stream. This always leaves less than
|
||||
* eight bits in the buffer. bits() works properly for need == 0.
|
||||
*
|
||||
* Format notes:
|
||||
*
|
||||
* - Bits are stored in bytes from the least significant bit to the most
|
||||
* significant bit. Therefore bits are dropped from the bottom of the bit
|
||||
* buffer, using shift right, and new bytes are appended to the top of the
|
||||
* bit buffer, using shift left.
|
||||
*/
|
||||
local int bits(struct state *s, int need)
|
||||
{
|
||||
int val; /* bit accumulator */
|
||||
|
||||
/* load at least need bits into val */
|
||||
val = s->bitbuf;
|
||||
while (s->bitcnt < need) {
|
||||
if (s->left == 0) {
|
||||
s->left = s->infun(s->inhow, &(s->in));
|
||||
if (s->left == 0) longjmp(s->env, 1); /* out of input */
|
||||
}
|
||||
val |= (int)(*(s->in)++) << s->bitcnt; /* load eight bits */
|
||||
s->left--;
|
||||
s->bitcnt += 8;
|
||||
}
|
||||
|
||||
/* drop need bits and update buffer, always zero to seven bits left */
|
||||
s->bitbuf = val >> need;
|
||||
s->bitcnt -= need;
|
||||
|
||||
/* return need bits, zeroing the bits above that */
|
||||
return val & ((1 << need) - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Huffman code decoding tables. count[1..MAXBITS] is the number of symbols of
|
||||
* each length, which for a canonical code are stepped through in order.
|
||||
* symbol[] are the symbol values in canonical order, where the number of
|
||||
* entries is the sum of the counts in count[]. The decoding process can be
|
||||
* seen in the function decode() below.
|
||||
*/
|
||||
struct huffman {
|
||||
short *count; /* number of symbols of each length */
|
||||
short *symbol; /* canonically ordered symbols */
|
||||
};
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Format notes:
|
||||
*
|
||||
* - The codes as stored in the compressed data are bit-reversed relative to
|
||||
* a simple integer ordering of codes of the same lengths. Hence below the
|
||||
* bits are pulled from the compressed data one at a time and used to
|
||||
* build the code value reversed from what is in the stream in order to
|
||||
* permit simple integer comparisons for decoding.
|
||||
*
|
||||
* - The first code for the shortest length is all ones. Subsequent codes of
|
||||
* the same length are simply integer decrements of the previous code. When
|
||||
* moving up a length, a one bit is appended to the code. For a complete
|
||||
* code, the last code of the longest length will be all zeros. To support
|
||||
* this ordering, the bits pulled during decoding are inverted to apply the
|
||||
* more "natural" ordering starting with all zeros and incrementing.
|
||||
*/
|
||||
local int decode(struct state *s, struct huffman *h)
|
||||
{
|
||||
int len; /* current number of bits in code */
|
||||
int code; /* len bits being decoded */
|
||||
int first; /* first code of length len */
|
||||
int count; /* number of codes of length len */
|
||||
int index; /* index of first code of length len in symbol table */
|
||||
int bitbuf; /* bits from stream */
|
||||
int left; /* bits left in next or left to process */
|
||||
short *next; /* next number of codes */
|
||||
|
||||
bitbuf = s->bitbuf;
|
||||
left = s->bitcnt;
|
||||
code = first = index = 0;
|
||||
len = 1;
|
||||
next = h->count + 1;
|
||||
while (1) {
|
||||
while (left--) {
|
||||
code |= (bitbuf & 1) ^ 1; /* invert code */
|
||||
bitbuf >>= 1;
|
||||
count = *next++;
|
||||
if (code < first + count) { /* if length len, return symbol */
|
||||
s->bitbuf = bitbuf;
|
||||
s->bitcnt = (s->bitcnt - len) & 7;
|
||||
return h->symbol[index + (code - first)];
|
||||
}
|
||||
index += count; /* else update for next length */
|
||||
first += count;
|
||||
first <<= 1;
|
||||
code <<= 1;
|
||||
len++;
|
||||
}
|
||||
left = (MAXBITS+1) - len;
|
||||
if (left == 0) break;
|
||||
if (s->left == 0) {
|
||||
s->left = s->infun(s->inhow, &(s->in));
|
||||
if (s->left == 0) longjmp(s->env, 1); /* out of input */
|
||||
}
|
||||
bitbuf = *(s->in)++;
|
||||
s->left--;
|
||||
if (left > 8) left = 8;
|
||||
}
|
||||
return -9; /* ran out of codes */
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a list of repeated code lengths rep[0..n-1], where each byte is a
|
||||
* count (high four bits + 1) and a code length (low four bits), generate the
|
||||
* list of code lengths. This compaction reduces the size of the object code.
|
||||
* Then given the list of code lengths length[0..n-1] representing a canonical
|
||||
* Huffman code for n symbols, construct the tables required to decode those
|
||||
* codes. Those tables are the number of codes of each length, and the symbols
|
||||
* sorted by length, retaining their original order within each length. The
|
||||
* return value is zero for a complete code set, negative for an over-
|
||||
* subscribed code set, and positive for an incomplete code set. The tables
|
||||
* can be used if the return value is zero or positive, but they cannot be used
|
||||
* if the return value is negative. If the return value is zero, it is not
|
||||
* possible for decode() using that table to return an error--any stream of
|
||||
* enough bits will resolve to a symbol. If the return value is positive, then
|
||||
* it is possible for decode() using that table to return an error for received
|
||||
* codes past the end of the incomplete lengths.
|
||||
*/
|
||||
local int construct(struct huffman *h, const unsigned char *rep, int n)
|
||||
{
|
||||
int symbol; /* current symbol when stepping through length[] */
|
||||
int len; /* current length when stepping through h->count[] */
|
||||
int left; /* number of possible codes left of current length */
|
||||
short offs[MAXBITS+1]; /* offsets in symbol table for each length */
|
||||
short length[256]; /* code lengths */
|
||||
|
||||
/* convert compact repeat counts into symbol bit length list */
|
||||
symbol = 0;
|
||||
do {
|
||||
len = *rep++;
|
||||
left = (len >> 4) + 1;
|
||||
len &= 15;
|
||||
do {
|
||||
length[symbol++] = len;
|
||||
} while (--left);
|
||||
} while (--n);
|
||||
n = symbol;
|
||||
|
||||
/* count number of codes of each length */
|
||||
for (len = 0; len <= MAXBITS; len++)
|
||||
h->count[len] = 0;
|
||||
for (symbol = 0; symbol < n; symbol++)
|
||||
(h->count[length[symbol]])++; /* assumes lengths are within bounds */
|
||||
if (h->count[0] == n) /* no codes! */
|
||||
return 0; /* complete, but decode() will fail */
|
||||
|
||||
/* check for an over-subscribed or incomplete set of lengths */
|
||||
left = 1; /* one possible code of zero length */
|
||||
for (len = 1; len <= MAXBITS; len++) {
|
||||
left <<= 1; /* one more bit, double codes left */
|
||||
left -= h->count[len]; /* deduct count from possible codes */
|
||||
if (left < 0) return left; /* over-subscribed--return negative */
|
||||
} /* left > 0 means incomplete */
|
||||
|
||||
/* generate offsets into symbol table for each length for sorting */
|
||||
offs[1] = 0;
|
||||
for (len = 1; len < MAXBITS; len++)
|
||||
offs[len + 1] = offs[len] + h->count[len];
|
||||
|
||||
/*
|
||||
* put symbols in table sorted by length, by symbol order within each
|
||||
* length
|
||||
*/
|
||||
for (symbol = 0; symbol < n; symbol++)
|
||||
if (length[symbol] != 0)
|
||||
h->symbol[offs[length[symbol]]++] = symbol;
|
||||
|
||||
/* return zero for complete set, positive for incomplete set */
|
||||
return left;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode PKWare Compression Library stream.
|
||||
*
|
||||
* Format notes:
|
||||
*
|
||||
* - First byte is 0 if literals are uncoded or 1 if they are coded. Second
|
||||
* byte is 4, 5, or 6 for the number of extra bits in the distance code.
|
||||
* This is the base-2 logarithm of the dictionary size minus six.
|
||||
*
|
||||
* - Compressed data is a combination of literals and length/distance pairs
|
||||
* terminated by an end code. Literals are either Huffman coded or
|
||||
* uncoded bytes. A length/distance pair is a coded length followed by a
|
||||
* coded distance to represent a string that occurs earlier in the
|
||||
* uncompressed data that occurs again at the current location.
|
||||
*
|
||||
* - A bit preceding a literal or length/distance pair indicates which comes
|
||||
* next, 0 for literals, 1 for length/distance.
|
||||
*
|
||||
* - If literals are uncoded, then the next eight bits are the literal, in the
|
||||
* normal bit order in th stream, i.e. no bit-reversal is needed. Similarly,
|
||||
* no bit reversal is needed for either the length extra bits or the distance
|
||||
* extra bits.
|
||||
*
|
||||
* - Literal bytes are simply written to the output. A length/distance pair is
|
||||
* an instruction to copy previously uncompressed bytes to the output. The
|
||||
* copy is from distance bytes back in the output stream, copying for length
|
||||
* bytes.
|
||||
*
|
||||
* - Distances pointing before the beginning of the output data are not
|
||||
* permitted.
|
||||
*
|
||||
* - Overlapped copies, where the length is greater than the distance, are
|
||||
* allowed and common. For example, a distance of one and a length of 518
|
||||
* simply copies the last byte 518 times. A distance of four and a length of
|
||||
* twelve copies the last four bytes three times. A simple forward copy
|
||||
* ignoring whether the length is greater than the distance or not implements
|
||||
* this correctly.
|
||||
*/
|
||||
local int decomp(struct state *s)
|
||||
{
|
||||
int lit; /* true if literals are coded */
|
||||
int dict; /* log2(dictionary size) - 6 */
|
||||
int symbol; /* decoded symbol, extra bits for distance */
|
||||
int len; /* length for copy */
|
||||
int dist; /* distance for copy */
|
||||
int copy; /* copy counter */
|
||||
unsigned char *from, *to; /* copy pointers */
|
||||
static int virgin = 1; /* build tables once */
|
||||
static short litcnt[MAXBITS+1], litsym[256]; /* litcode memory */
|
||||
static short lencnt[MAXBITS+1], lensym[16]; /* lencode memory */
|
||||
static short distcnt[MAXBITS+1], distsym[64]; /* distcode memory */
|
||||
static struct huffman litcode = {litcnt, litsym}; /* length code */
|
||||
static struct huffman lencode = {lencnt, lensym}; /* length code */
|
||||
static struct huffman distcode = {distcnt, distsym};/* distance code */
|
||||
/* bit lengths of literal codes */
|
||||
static const unsigned char litlen[] = {
|
||||
11, 124, 8, 7, 28, 7, 188, 13, 76, 4, 10, 8, 12, 10, 12, 10, 8, 23, 8,
|
||||
9, 7, 6, 7, 8, 7, 6, 55, 8, 23, 24, 12, 11, 7, 9, 11, 12, 6, 7, 22, 5,
|
||||
7, 24, 6, 11, 9, 6, 7, 22, 7, 11, 38, 7, 9, 8, 25, 11, 8, 11, 9, 12,
|
||||
8, 12, 5, 38, 5, 38, 5, 11, 7, 5, 6, 21, 6, 10, 53, 8, 7, 24, 10, 27,
|
||||
44, 253, 253, 253, 252, 252, 252, 13, 12, 45, 12, 45, 12, 61, 12, 45,
|
||||
44, 173};
|
||||
/* bit lengths of length codes 0..15 */
|
||||
static const unsigned char lenlen[] = {2, 35, 36, 53, 38, 23};
|
||||
/* bit lengths of distance codes 0..63 */
|
||||
static const unsigned char distlen[] = {2, 20, 53, 230, 247, 151, 248};
|
||||
static const short base[16] = { /* base for length codes */
|
||||
3, 2, 4, 5, 6, 7, 8, 9, 10, 12, 16, 24, 40, 72, 136, 264};
|
||||
static const char extra[16] = { /* extra bits for length codes */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8};
|
||||
|
||||
/* set up decoding tables (once--might not be thread-safe) */
|
||||
if (virgin) {
|
||||
construct(&litcode, litlen, sizeof(litlen));
|
||||
construct(&lencode, lenlen, sizeof(lenlen));
|
||||
construct(&distcode, distlen, sizeof(distlen));
|
||||
virgin = 0;
|
||||
}
|
||||
|
||||
/* read header */
|
||||
lit = bits(s, 8);
|
||||
if (lit > 1) return -1;
|
||||
dict = bits(s, 8);
|
||||
if (dict < 4 || dict > 6) return -2;
|
||||
|
||||
/* decode literals and length/distance pairs */
|
||||
do {
|
||||
if (bits(s, 1)) {
|
||||
/* get length */
|
||||
symbol = decode(s, &lencode);
|
||||
len = base[symbol] + bits(s, extra[symbol]);
|
||||
if (len == 519) break; /* end code */
|
||||
|
||||
/* get distance */
|
||||
symbol = len == 2 ? 2 : dict;
|
||||
dist = decode(s, &distcode) << symbol;
|
||||
dist += bits(s, symbol);
|
||||
dist++;
|
||||
if (s->first && dist > s->next)
|
||||
return -3; /* distance too far back */
|
||||
|
||||
/* copy length bytes from distance bytes back */
|
||||
do {
|
||||
to = s->out + s->next;
|
||||
from = to - dist;
|
||||
copy = MAXWIN;
|
||||
if (s->next < dist) {
|
||||
from += copy;
|
||||
copy = dist;
|
||||
}
|
||||
copy -= s->next;
|
||||
if (copy > len) copy = len;
|
||||
len -= copy;
|
||||
s->next += copy;
|
||||
do {
|
||||
*to++ = *from++;
|
||||
} while (--copy);
|
||||
if (s->next == MAXWIN) {
|
||||
if (s->outfun(s->outhow, s->out, s->next)) return 1;
|
||||
s->next = 0;
|
||||
s->first = 0;
|
||||
}
|
||||
} while (len != 0);
|
||||
}
|
||||
else {
|
||||
/* get literal and write it */
|
||||
symbol = lit ? decode(s, &litcode) : bits(s, 8);
|
||||
s->out[s->next++] = symbol;
|
||||
if (s->next == MAXWIN) {
|
||||
if (s->outfun(s->outhow, s->out, s->next)) return 1;
|
||||
s->next = 0;
|
||||
s->first = 0;
|
||||
}
|
||||
}
|
||||
} while (1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* See comments in blast.h */
|
||||
int blast(blast_in infun, void *inhow, blast_out outfun, void *outhow)
|
||||
{
|
||||
struct state s; /* input/output state */
|
||||
int err; /* return value */
|
||||
|
||||
/* initialize input state */
|
||||
s.infun = infun;
|
||||
s.inhow = inhow;
|
||||
s.left = 0;
|
||||
s.bitbuf = 0;
|
||||
s.bitcnt = 0;
|
||||
|
||||
/* initialize output state */
|
||||
s.outfun = outfun;
|
||||
s.outhow = outhow;
|
||||
s.next = 0;
|
||||
s.first = 1;
|
||||
|
||||
/* return if bits() or decode() tries to read past available input */
|
||||
if (setjmp(s.env) != 0) /* if came back here via longjmp(), */
|
||||
err = 2; /* then skip decomp(), return error */
|
||||
else
|
||||
err = decomp(&s); /* decompress */
|
||||
|
||||
/* write any leftover output and update the error code if needed */
|
||||
if (err != 1 && s.next && s.outfun(s.outhow, s.out, s.next) && err == 0)
|
||||
err = 1;
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
/* Example of how to use blast() */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define CHUNK 16384
|
||||
|
||||
local unsigned inf(void *how, unsigned char **buf)
|
||||
{
|
||||
static unsigned char hold[CHUNK];
|
||||
|
||||
*buf = hold;
|
||||
return fread(hold, 1, CHUNK, (FILE *)how);
|
||||
}
|
||||
|
||||
local int outf(void *how, unsigned char *buf, unsigned len)
|
||||
{
|
||||
return fwrite(buf, 1, len, (FILE *)how) != len;
|
||||
}
|
||||
|
||||
/* Decompress a PKWare Compression Library stream from stdin to stdout */
|
||||
int main(void)
|
||||
{
|
||||
int ret, n;
|
||||
|
||||
/* decompress to stdout */
|
||||
ret = blast(inf, stdin, outf, stdout);
|
||||
if (ret != 0) fprintf(stderr, "blast error: %d\n", ret);
|
||||
|
||||
/* see if there are any leftover bytes */
|
||||
n = 0;
|
||||
while (getchar() != EOF) n++;
|
||||
if (n) fprintf(stderr, "blast warning: %d unused bytes of input\n", n);
|
||||
|
||||
/* return blast() error code */
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,71 @@
|
||||
/* blast.h -- interface for blast.c
|
||||
Copyright (C) 2003 Mark Adler
|
||||
version 1.1, 16 Feb 2003
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the author be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Mark Adler madler@alumni.caltech.edu
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* blast() decompresses the PKWare Data Compression Library (DCL) compressed
|
||||
* format. It provides the same functionality as the explode() function in
|
||||
* that library. (Note: PKWare overused the "implode" verb, and the format
|
||||
* used by their library implode() function is completely different and
|
||||
* incompatible with the implode compression method supported by PKZIP.)
|
||||
*/
|
||||
|
||||
|
||||
typedef unsigned (*blast_in)(void *how, unsigned char **buf);
|
||||
typedef int (*blast_out)(void *how, unsigned char *buf, unsigned len);
|
||||
/* Definitions for input/output functions passed to blast(). See below for
|
||||
* what the provided functions need to do.
|
||||
*/
|
||||
|
||||
|
||||
int blast(blast_in infun, void *inhow, blast_out outfun, void *outhow);
|
||||
/* Decompress input to output using the provided infun() and outfun() calls.
|
||||
* On success, the return value of blast() is zero. If there is an error in
|
||||
* the source data, i.e. it is not in the proper format, then a negative value
|
||||
* is returned. If there is not enough input available or there is not enough
|
||||
* output space, then a positive error is returned.
|
||||
*
|
||||
* The input function is invoked: len = infun(how, &buf), where buf is set by
|
||||
* infun() to point to the input buffer, and infun() returns the number of
|
||||
* available bytes there. If infun() returns zero, then blast() returns with
|
||||
* an input error. (blast() only asks for input if it needs it.) inhow is for
|
||||
* use by the application to pass an input descriptor to infun(), if desired.
|
||||
*
|
||||
* The output function is invoked: err = outfun(how, buf, len), where the bytes
|
||||
* to be written are buf[0..len-1]. If err is not zero, then blast() returns
|
||||
* with an output error. outfun() is always called with len <= 4096. outhow
|
||||
* is for use by the application to pass an output descriptor to outfun(), if
|
||||
* desired.
|
||||
*
|
||||
* The return codes are:
|
||||
*
|
||||
* 2: ran out of input before completing decompression
|
||||
* 1: output error before completing decompression
|
||||
* 0: successful decompression
|
||||
* -1: literal flag not zero or one
|
||||
* -2: dictionary size not in 4..6
|
||||
* -3: distance is too far back
|
||||
*
|
||||
* At the bottom of blast.c is an example program that uses blast() that can be
|
||||
* compiled to produce a command-line decompression filter by defining TEST.
|
||||
*/
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
AIAIAIAIAIAIA
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
unit ZLibConst;
|
||||
|
||||
interface
|
||||
|
||||
resourcestring
|
||||
sTargetBufferTooSmall = 'ZLib error: target buffer may be too small';
|
||||
sInvalidStreamOp = 'Invalid stream operation';
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
||||
@@ -0,0 +1,76 @@
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
This directory contains an update to the ZLib interface unit,
|
||||
distributed by Borland as a Delphi supplemental component.
|
||||
|
||||
The original ZLib unit is Copyright (c) 1997,99 Borland Corp.,
|
||||
and is based on zlib version 1.0.4. There are a series of bugs
|
||||
and security problems associated with that old zlib version, and
|
||||
we recommend the users to update their ZLib unit.
|
||||
|
||||
|
||||
Summary of modifications
|
||||
========================
|
||||
|
||||
- Improved makefile, adapted to zlib version 1.2.1.
|
||||
|
||||
- Some field types from TZStreamRec are changed from Integer to
|
||||
Longint, for consistency with the zlib.h header, and for 64-bit
|
||||
readiness.
|
||||
|
||||
- The zlib_version constant is updated.
|
||||
|
||||
- The new Z_RLE strategy has its corresponding symbolic constant.
|
||||
|
||||
- The allocation and deallocation functions and function types
|
||||
(TAlloc, TFree, zlibAllocMem and zlibFreeMem) are now cdecl,
|
||||
and _malloc and _free are added as C RTL stubs. As a result,
|
||||
the original C sources of zlib can be compiled out of the box,
|
||||
and linked to the ZLib unit.
|
||||
|
||||
|
||||
Suggestions for improvements
|
||||
============================
|
||||
|
||||
Currently, the ZLib unit provides only a limited wrapper around
|
||||
the zlib library, and much of the original zlib functionality is
|
||||
missing. Handling compressed file formats like ZIP/GZIP or PNG
|
||||
cannot be implemented without having this functionality.
|
||||
Applications that handle these formats are either using their own,
|
||||
duplicated code, or not using the ZLib unit at all.
|
||||
|
||||
Here are a few suggestions:
|
||||
|
||||
- Checksum class wrappers around adler32() and crc32(), similar
|
||||
to the Java classes that implement the java.util.zip.Checksum
|
||||
interface.
|
||||
|
||||
- The ability to read and write raw deflate streams, without the
|
||||
zlib stream header and trailer. Raw deflate streams are used
|
||||
in the ZIP file format.
|
||||
|
||||
- The ability to read and write gzip streams, used in the GZIP
|
||||
file format, and normally produced by the gzip program.
|
||||
|
||||
- The ability to select a different compression strategy, useful
|
||||
to PNG and MNG image compression, and to multimedia compression
|
||||
in general. Besides the compression level
|
||||
|
||||
TCompressionLevel = (clNone, clFastest, clDefault, clMax);
|
||||
|
||||
which, in fact, could have used the 'z' prefix and avoided
|
||||
TColor-like symbols
|
||||
|
||||
TCompressionLevel = (zcNone, zcFastest, zcDefault, zcMax);
|
||||
|
||||
there could be a compression strategy
|
||||
|
||||
TCompressionStrategy = (zsDefault, zsFiltered, zsHuffmanOnly, zsRle);
|
||||
|
||||
- ZIP and GZIP stream handling via TStreams.
|
||||
|
||||
|
||||
--
|
||||
Cosmin Truta <cosmint@cs.ubbcluj.ro>
|
||||
@@ -0,0 +1,93 @@
|
||||
# Makefile for zlib
|
||||
# For use with Delphi and C++ Builder under Win32
|
||||
# Updated for zlib 1.2.x by Cosmin Truta
|
||||
|
||||
# ------------ Borland C++ ------------
|
||||
|
||||
# This project uses the Delphi (fastcall/register) calling convention:
|
||||
LOC = -DZEXPORT=__fastcall -DZEXPORTVA=__cdecl
|
||||
|
||||
CC = bcc32
|
||||
LD = bcc32
|
||||
AR = tlib
|
||||
# do not use "-pr" in CFLAGS
|
||||
CFLAGS = -a -d -k- -O2 $(LOC)
|
||||
LDFLAGS =
|
||||
|
||||
|
||||
# variables
|
||||
ZLIB_LIB = zlib.lib
|
||||
|
||||
OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infback.obj
|
||||
OBJ2 = inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
|
||||
OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzio.obj+infback.obj
|
||||
OBJP2 = +inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj
|
||||
|
||||
|
||||
# targets
|
||||
all: $(ZLIB_LIB) example.exe minigzip.exe
|
||||
|
||||
.c.obj:
|
||||
$(CC) -c $(CFLAGS) $*.c
|
||||
|
||||
adler32.obj: adler32.c zlib.h zconf.h
|
||||
|
||||
compress.obj: compress.c zlib.h zconf.h
|
||||
|
||||
crc32.obj: crc32.c zlib.h zconf.h crc32.h
|
||||
|
||||
deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h
|
||||
|
||||
gzio.obj: gzio.c zutil.h zlib.h zconf.h
|
||||
|
||||
infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
|
||||
inffast.h inffixed.h
|
||||
|
||||
inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
|
||||
inffast.h
|
||||
|
||||
inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
|
||||
inffast.h inffixed.h
|
||||
|
||||
inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h
|
||||
|
||||
trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h
|
||||
|
||||
uncompr.obj: uncompr.c zlib.h zconf.h
|
||||
|
||||
zutil.obj: zutil.c zutil.h zlib.h zconf.h
|
||||
|
||||
example.obj: example.c zlib.h zconf.h
|
||||
|
||||
minigzip.obj: minigzip.c zlib.h zconf.h
|
||||
|
||||
|
||||
# For the sake of the old Borland make,
|
||||
# the command line is cut to fit in the MS-DOS 128 byte limit:
|
||||
$(ZLIB_LIB): $(OBJ1) $(OBJ2)
|
||||
-del $(ZLIB_LIB)
|
||||
$(AR) $(ZLIB_LIB) $(OBJP1)
|
||||
$(AR) $(ZLIB_LIB) $(OBJP2)
|
||||
|
||||
|
||||
# testing
|
||||
test: example.exe minigzip.exe
|
||||
example
|
||||
echo hello world | minigzip | minigzip -d
|
||||
|
||||
example.exe: example.obj $(ZLIB_LIB)
|
||||
$(LD) $(LDFLAGS) example.obj $(ZLIB_LIB)
|
||||
|
||||
minigzip.exe: minigzip.obj $(ZLIB_LIB)
|
||||
$(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB)
|
||||
|
||||
|
||||
# cleanup
|
||||
clean:
|
||||
-del *.obj
|
||||
-del *.exe
|
||||
-del *.lib
|
||||
-del *.tds
|
||||
-del zlib.bak
|
||||
-del foo.gz
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<project name="DotZLib" default="build" basedir="./DotZLib">
|
||||
<description>A .Net wrapper library around ZLib1.dll</description>
|
||||
|
||||
<property name="nunit.location" value="c:/program files/NUnit V2.1/bin" />
|
||||
<property name="build.root" value="bin" />
|
||||
|
||||
<property name="debug" value="true" />
|
||||
<property name="nunit" value="true" />
|
||||
|
||||
<property name="build.folder" value="${build.root}/debug/" if="${debug}" />
|
||||
<property name="build.folder" value="${build.root}/release/" unless="${debug}" />
|
||||
|
||||
<target name="clean" description="Remove all generated files">
|
||||
<delete dir="${build.root}" failonerror="false" />
|
||||
</target>
|
||||
|
||||
<target name="build" description="compiles the source code">
|
||||
|
||||
<mkdir dir="${build.folder}" />
|
||||
<csc target="library" output="${build.folder}DotZLib.dll" debug="${debug}">
|
||||
<references basedir="${nunit.location}">
|
||||
<includes if="${nunit}" name="nunit.framework.dll" />
|
||||
</references>
|
||||
<sources>
|
||||
<includes name="*.cs" />
|
||||
<excludes name="UnitTests.cs" unless="${nunit}" />
|
||||
</sources>
|
||||
<arg value="/d:nunit" if="${nunit}" />
|
||||
</csc>
|
||||
</target>
|
||||
|
||||
</project>
|
||||
Binary file not shown.
@@ -0,0 +1,21 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 8.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotZLib", "DotZLib\DotZLib.csproj", "{BB1EE0B1-1808-46CB-B786-949D91117FC5}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
Debug = Debug
|
||||
Release = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{BB1EE0B1-1808-46CB-B786-949D91117FC5}.Debug.ActiveCfg = Debug|.NET
|
||||
{BB1EE0B1-1808-46CB-B786-949D91117FC5}.Debug.Build.0 = Debug|.NET
|
||||
{BB1EE0B1-1808-46CB-B786-949D91117FC5}.Release.ActiveCfg = Release|.NET
|
||||
{BB1EE0B1-1808-46CB-B786-949D91117FC5}.Release.Build.0 = Release|.NET
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,58 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
//
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
//
|
||||
[assembly: AssemblyTitle("DotZLib")]
|
||||
[assembly: AssemblyDescription(".Net bindings for ZLib compression dll 1.2.x")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Henrik Ravn")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("(c) 2004 by Henrik Ravn")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
//
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
//
|
||||
// In order to sign your assembly you must specify a key to use. Refer to the
|
||||
// Microsoft .NET Framework documentation for more information on assembly signing.
|
||||
//
|
||||
// Use the attributes below to control which key is used for signing.
|
||||
//
|
||||
// Notes:
|
||||
// (*) If no key is specified, the assembly is not signed.
|
||||
// (*) KeyName refers to a key that has been installed in the Crypto Service
|
||||
// Provider (CSP) on your machine. KeyFile refers to a file which contains
|
||||
// a key.
|
||||
// (*) If the KeyFile and the KeyName values are both specified, the
|
||||
// following processing occurs:
|
||||
// (1) If the KeyName can be found in the CSP, that key is used.
|
||||
// (2) If the KeyName does not exist and the KeyFile does exist, the key
|
||||
// in the KeyFile is installed into the CSP and used.
|
||||
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
|
||||
// When specifying the KeyFile, the location of the KeyFile should be
|
||||
// relative to the project output directory which is
|
||||
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
|
||||
// located in the project directory, you would specify the AssemblyKeyFile
|
||||
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
|
||||
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
|
||||
// documentation for more information on this.
|
||||
//
|
||||
[assembly: AssemblyDelaySign(false)]
|
||||
[assembly: AssemblyKeyFile("")]
|
||||
[assembly: AssemblyKeyName("")]
|
||||
@@ -0,0 +1,202 @@
|
||||
//
|
||||
// © Copyright Henrik Ravn 2004
|
||||
//
|
||||
// Use, modification and distribution are subject to the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
|
||||
namespace DotZLib
|
||||
{
|
||||
#region ChecksumGeneratorBase
|
||||
/// <summary>
|
||||
/// Implements the common functionality needed for all <see cref="ChecksumGenerator"/>s
|
||||
/// </summary>
|
||||
/// <example></example>
|
||||
public abstract class ChecksumGeneratorBase : ChecksumGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// The value of the current checksum
|
||||
/// </summary>
|
||||
protected uint _current;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the checksum generator base - the current checksum is
|
||||
/// set to zero
|
||||
/// </summary>
|
||||
public ChecksumGeneratorBase()
|
||||
{
|
||||
_current = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the checksum generator basewith a specified value
|
||||
/// </summary>
|
||||
/// <param name="initialValue">The value to set the current checksum to</param>
|
||||
public ChecksumGeneratorBase(uint initialValue)
|
||||
{
|
||||
_current = initialValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the current checksum to zero
|
||||
/// </summary>
|
||||
public void Reset() { _current = 0; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current checksum value
|
||||
/// </summary>
|
||||
public uint Value { get { return _current; } }
|
||||
|
||||
/// <summary>
|
||||
/// Updates the current checksum with part of an array of bytes
|
||||
/// </summary>
|
||||
/// <param name="data">The data to update the checksum with</param>
|
||||
/// <param name="offset">Where in <c>data</c> to start updating</param>
|
||||
/// <param name="count">The number of bytes from <c>data</c> to use</param>
|
||||
/// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception>
|
||||
/// <exception cref="NullReferenceException"><c>data</c> is a null reference</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception>
|
||||
/// <remarks>All the other <c>Update</c> methods are implmeneted in terms of this one.
|
||||
/// This is therefore the only method a derived class has to implement</remarks>
|
||||
public abstract void Update(byte[] data, int offset, int count);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the current checksum with an array of bytes.
|
||||
/// </summary>
|
||||
/// <param name="data">The data to update the checksum with</param>
|
||||
public void Update(byte[] data)
|
||||
{
|
||||
Update(data, 0, data.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the current checksum with the data from a string
|
||||
/// </summary>
|
||||
/// <param name="data">The string to update the checksum with</param>
|
||||
/// <remarks>The characters in the string are converted by the UTF-8 encoding</remarks>
|
||||
public void Update(string data)
|
||||
{
|
||||
Update(Encoding.UTF8.GetBytes(data));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the current checksum with the data from a string, using a specific encoding
|
||||
/// </summary>
|
||||
/// <param name="data">The string to update the checksum with</param>
|
||||
/// <param name="encoding">The encoding to use</param>
|
||||
public void Update(string data, Encoding encoding)
|
||||
{
|
||||
Update(encoding.GetBytes(data));
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region CRC32
|
||||
/// <summary>
|
||||
/// Implements a CRC32 checksum generator
|
||||
/// </summary>
|
||||
public sealed class CRC32Checksum : ChecksumGeneratorBase
|
||||
{
|
||||
#region DLL imports
|
||||
|
||||
[DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
|
||||
private static extern uint crc32(uint crc, int data, uint length);
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the CRC32 checksum generator
|
||||
/// </summary>
|
||||
public CRC32Checksum() : base() {}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the CRC32 checksum generator with a specified value
|
||||
/// </summary>
|
||||
/// <param name="initialValue">The value to set the current checksum to</param>
|
||||
public CRC32Checksum(uint initialValue) : base(initialValue) {}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the current checksum with part of an array of bytes
|
||||
/// </summary>
|
||||
/// <param name="data">The data to update the checksum with</param>
|
||||
/// <param name="offset">Where in <c>data</c> to start updating</param>
|
||||
/// <param name="count">The number of bytes from <c>data</c> to use</param>
|
||||
/// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception>
|
||||
/// <exception cref="NullReferenceException"><c>data</c> is a null reference</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception>
|
||||
public override void Update(byte[] data, int offset, int count)
|
||||
{
|
||||
if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException();
|
||||
if ((offset+count) > data.Length) throw new ArgumentException();
|
||||
GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned);
|
||||
try
|
||||
{
|
||||
_current = crc32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count);
|
||||
}
|
||||
finally
|
||||
{
|
||||
hData.Free();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Adler
|
||||
/// <summary>
|
||||
/// Implements a checksum generator that computes the Adler checksum on data
|
||||
/// </summary>
|
||||
public sealed class AdlerChecksum : ChecksumGeneratorBase
|
||||
{
|
||||
#region DLL imports
|
||||
|
||||
[DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
|
||||
private static extern uint adler32(uint adler, int data, uint length);
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Adler checksum generator
|
||||
/// </summary>
|
||||
public AdlerChecksum() : base() {}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Adler checksum generator with a specified value
|
||||
/// </summary>
|
||||
/// <param name="initialValue">The value to set the current checksum to</param>
|
||||
public AdlerChecksum(uint initialValue) : base(initialValue) {}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the current checksum with part of an array of bytes
|
||||
/// </summary>
|
||||
/// <param name="data">The data to update the checksum with</param>
|
||||
/// <param name="offset">Where in <c>data</c> to start updating</param>
|
||||
/// <param name="count">The number of bytes from <c>data</c> to use</param>
|
||||
/// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception>
|
||||
/// <exception cref="NullReferenceException"><c>data</c> is a null reference</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception>
|
||||
public override void Update(byte[] data, int offset, int count)
|
||||
{
|
||||
if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException();
|
||||
if ((offset+count) > data.Length) throw new ArgumentException();
|
||||
GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned);
|
||||
try
|
||||
{
|
||||
_current = adler32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count);
|
||||
}
|
||||
finally
|
||||
{
|
||||
hData.Free();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
//
|
||||
// © Copyright Henrik Ravn 2004
|
||||
//
|
||||
// Use, modification and distribution are subject to the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace DotZLib
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// This class implements a circular buffer
|
||||
/// </summary>
|
||||
internal class CircularBuffer
|
||||
{
|
||||
#region Private data
|
||||
private int _capacity;
|
||||
private int _head;
|
||||
private int _tail;
|
||||
private int _size;
|
||||
private byte[] _buffer;
|
||||
#endregion
|
||||
|
||||
public CircularBuffer(int capacity)
|
||||
{
|
||||
Debug.Assert( capacity > 0 );
|
||||
_buffer = new byte[capacity];
|
||||
_capacity = capacity;
|
||||
_head = 0;
|
||||
_tail = 0;
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
public int Size { get { return _size; } }
|
||||
|
||||
public int Put(byte[] source, int offset, int count)
|
||||
{
|
||||
Debug.Assert( count > 0 );
|
||||
int trueCount = Math.Min(count, _capacity - Size);
|
||||
for (int i = 0; i < trueCount; ++i)
|
||||
_buffer[(_tail+i) % _capacity] = source[offset+i];
|
||||
_tail += trueCount;
|
||||
_tail %= _capacity;
|
||||
_size += trueCount;
|
||||
return trueCount;
|
||||
}
|
||||
|
||||
public bool Put(byte b)
|
||||
{
|
||||
if (Size == _capacity) // no room
|
||||
return false;
|
||||
_buffer[_tail++] = b;
|
||||
_tail %= _capacity;
|
||||
++_size;
|
||||
return true;
|
||||
}
|
||||
|
||||
public int Get(byte[] destination, int offset, int count)
|
||||
{
|
||||
int trueCount = Math.Min(count,Size);
|
||||
for (int i = 0; i < trueCount; ++i)
|
||||
destination[offset + i] = _buffer[(_head+i) % _capacity];
|
||||
_head += trueCount;
|
||||
_head %= _capacity;
|
||||
_size -= trueCount;
|
||||
return trueCount;
|
||||
}
|
||||
|
||||
public int Get()
|
||||
{
|
||||
if (Size == 0)
|
||||
return -1;
|
||||
|
||||
int result = (int)_buffer[_head++ % _capacity];
|
||||
--_size;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
//
|
||||
// © Copyright Henrik Ravn 2004
|
||||
//
|
||||
// Use, modification and distribution are subject to the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace DotZLib
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements the common functionality needed for all <see cref="Codec"/>s
|
||||
/// </summary>
|
||||
public abstract class CodecBase : Codec, IDisposable
|
||||
{
|
||||
|
||||
#region Data members
|
||||
|
||||
/// <summary>
|
||||
/// Instance of the internal zlib buffer structure that is
|
||||
/// passed to all functions in the zlib dll
|
||||
/// </summary>
|
||||
internal ZStream _ztream = new ZStream();
|
||||
|
||||
/// <summary>
|
||||
/// True if the object instance has been disposed, false otherwise
|
||||
/// </summary>
|
||||
protected bool _isDisposed = false;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the internal buffers
|
||||
/// </summary>
|
||||
protected const int kBufferSize = 16384;
|
||||
|
||||
private byte[] _outBuffer = new byte[kBufferSize];
|
||||
private byte[] _inBuffer = new byte[kBufferSize];
|
||||
|
||||
private GCHandle _hInput;
|
||||
private GCHandle _hOutput;
|
||||
|
||||
private uint _checksum = 0;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <c>CodeBase</c> class.
|
||||
/// </summary>
|
||||
public CodecBase()
|
||||
{
|
||||
try
|
||||
{
|
||||
_hInput = GCHandle.Alloc(_inBuffer, GCHandleType.Pinned);
|
||||
_hOutput = GCHandle.Alloc(_outBuffer, GCHandleType.Pinned);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
CleanUp(false);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#region Codec Members
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when more processed data are available.
|
||||
/// </summary>
|
||||
public event DataAvailableHandler DataAvailable;
|
||||
|
||||
/// <summary>
|
||||
/// Fires the <see cref="DataAvailable"/> event
|
||||
/// </summary>
|
||||
protected void OnDataAvailable()
|
||||
{
|
||||
if (_ztream.total_out > 0)
|
||||
{
|
||||
if (DataAvailable != null)
|
||||
DataAvailable( _outBuffer, 0, (int)_ztream.total_out);
|
||||
resetOutput();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds more data to the codec to be processed.
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array containing the data to be added to the codec</param>
|
||||
/// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks>
|
||||
public void Add(byte[] data)
|
||||
{
|
||||
Add(data,0,data.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds more data to the codec to be processed.
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array containing the data to be added to the codec</param>
|
||||
/// <param name="offset">The index of the first byte to add from <c>data</c></param>
|
||||
/// <param name="count">The number of bytes to add</param>
|
||||
/// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks>
|
||||
/// <remarks>This must be implemented by a derived class</remarks>
|
||||
public abstract void Add(byte[] data, int offset, int count);
|
||||
|
||||
/// <summary>
|
||||
/// Finishes up any pending data that needs to be processed and handled.
|
||||
/// </summary>
|
||||
/// <remarks>This must be implemented by a derived class</remarks>
|
||||
public abstract void Finish();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the checksum of the data that has been added so far
|
||||
/// </summary>
|
||||
public uint Checksum { get { return _checksum; } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Destructor & IDisposable stuff
|
||||
|
||||
/// <summary>
|
||||
/// Destroys this instance
|
||||
/// </summary>
|
||||
~CodecBase()
|
||||
{
|
||||
CleanUp(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases any unmanaged resources and calls the <see cref="CleanUp()"/> method of the derived class
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
CleanUp(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs any codec specific cleanup
|
||||
/// </summary>
|
||||
/// <remarks>This must be implemented by a derived class</remarks>
|
||||
protected abstract void CleanUp();
|
||||
|
||||
// performs the release of the handles and calls the dereived CleanUp()
|
||||
private void CleanUp(bool isDisposing)
|
||||
{
|
||||
if (!_isDisposed)
|
||||
{
|
||||
CleanUp();
|
||||
if (_hInput.IsAllocated)
|
||||
_hInput.Free();
|
||||
if (_hOutput.IsAllocated)
|
||||
_hOutput.Free();
|
||||
|
||||
_isDisposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper methods
|
||||
|
||||
/// <summary>
|
||||
/// Copies a number of bytes to the internal codec buffer - ready for proccesing
|
||||
/// </summary>
|
||||
/// <param name="data">The byte array that contains the data to copy</param>
|
||||
/// <param name="startIndex">The index of the first byte to copy</param>
|
||||
/// <param name="count">The number of bytes to copy from <c>data</c></param>
|
||||
protected void copyInput(byte[] data, int startIndex, int count)
|
||||
{
|
||||
Array.Copy(data, startIndex, _inBuffer,0, count);
|
||||
_ztream.next_in = _hInput.AddrOfPinnedObject();
|
||||
_ztream.total_in = 0;
|
||||
_ztream.avail_in = (uint)count;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the internal output buffers to a known state - ready for processing
|
||||
/// </summary>
|
||||
protected void resetOutput()
|
||||
{
|
||||
_ztream.total_out = 0;
|
||||
_ztream.avail_out = kBufferSize;
|
||||
_ztream.next_out = _hOutput.AddrOfPinnedObject();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the running checksum property
|
||||
/// </summary>
|
||||
/// <param name="newSum">The new checksum value</param>
|
||||
protected void setChecksum(uint newSum)
|
||||
{
|
||||
_checksum = newSum;
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user