Initial commit of tinf v1.00 source.

This commit is contained in:
Joergen Ibsen 2012-11-13 23:14:45 +01:00
commit 93352fca2a
27 changed files with 2229 additions and 0 deletions

BIN
bin/tgunzip.exe Normal file

Binary file not shown.

View file

@ -0,0 +1,31 @@
##
## tgunzip - gzip decompressor example
##
## Borland C/C++ makefile (GNU Make)
##
## Copyright (c) 2003 by Joergen Ibsen / Jibz
## All Rights Reserved
##
## http://www.ibsensoftware.com/
##
target = tgunzip.exe
objects = tgunzip.obj
libs = ..\..\lib\tinf.lib
temps = tgunzip.tds
cflags = -a16 -K -O2 -OS -I..\..\src
ldflags = -C -q -Gn -x -Gz -ap -Tpe
.PHONY: all clean
all: $(target)
$(target): $(objects)
ilink32 $(ldflags) c0x32 $(objects), $@ , , import32 cw32 $(libs) , ,
%.obj : %.c
bcc32 $(cflags) -c $<
clean:
$(RM) $(objects) $(target) $(temps)

View file

@ -0,0 +1,30 @@
##
## tgunzip - gzip decompressor example
##
## DJGPP makefile
##
## Copyright (c) 2003 by Joergen Ibsen / Jibz
## All Rights Reserved
##
## http://www.ibsensoftware.com/
##
target = tgunzip.exe
objects = tgunzip.o
libs = ../../lib/libtinf.a
cflags = -s -Wall -Os -fomit-frame-pointer -I../../src
ldflags = $(cflags)
.PHONY: all clean
all: $(target)
$(target): $(objects)
gcc $(ldflags) -o $@ $^ $(libs)
%.o : %.c
gcc $(cflags) -o $@ -c $<
clean:
$(RM) $(objects) $(target)

View file

@ -0,0 +1,31 @@
##
## tgunzip - gzip decompressor example
##
## Digital Mars C/C++ makefile (GNU Make)
##
## Copyright (c) 2003 by Joergen Ibsen / Jibz
## All Rights Reserved
##
## http://www.ibsensoftware.com/
##
target = tgunzip.exe
objects = tgunzip.obj
libs = ..\..\lib\tinf.lib
temps = tgunzip.map
cflags = -s -mn -o+all -I..\..\src
ldflags = $(cflags)
.PHONY: all clean
all: $(target)
$(target): $(objects)
dmc $(ldflags) -o$@ $^ $(libs)
%.obj : %.c
dmc $(cflags) -c $<
clean:
$(RM) $(objects) $(target) $(temps)

View file

@ -0,0 +1,30 @@
##
## tgunzip - gzip decompressor example
##
## GCC makefile (Linux, FreeBSD, BeOS and QNX)
##
## Copyright (c) 2003 by Joergen Ibsen / Jibz
## All Rights Reserved
##
## http://www.ibsensoftware.com/
##
target = tgunzip
objects = tgunzip.o
libs = ../../lib/libtinf.a
cflags = -s -Wall -Os -I../../src
ldflags = $(cflags)
.PHONY: all clean
all: $(target)
$(target): $(objects)
gcc $(ldflags) -o $@ $^ $(libs)
%.o : %.c
gcc $(cflags) -c $<
clean:
$(RM) $(objects) $(target)

View file

@ -0,0 +1,28 @@
##
## tgunzip - gzip decompressor example
##
## MinGW / Cygwin makefile
##
## Copyright (c) 1998-2003 by Joergen Ibsen / Jibz
## All Rights Reserved
##
target = tgunzip.exe
objects = tgunzip.o
libs = ../../lib/libtinf.a
cflags = -s -Wall -Os -fomit-frame-pointer -I../../src
ldflags = $(cflags)
.PHONY: all clean
all: $(target)
$(target): $(objects)
gcc $(ldflags) -o $@ $^ $(libs)
%.o : %.c
gcc $(cflags) -o $@ -c $<
clean:
$(RM) $(target) $(objects)

View file

@ -0,0 +1,28 @@
##
## tgunzip - gzip decompressor example
##
## Visual C/C++ makefile (GNU Make)
##
## Copyright (c) 2003 by Joergen Ibsen / Jibz
## All Rights Reserved
##
target = tgunzip.exe
objects = tgunzip.obj
libs = ../../lib/tinf.lib
cflags = /nologo /W3 /O1 /G6 /W3 /Gy /GF /I..\..\src
ldflags = /nologo /release /opt:ref /opt:icf
.PHONY: all clean
all: $(target)
$(target): $(objects)
link $(ldflags) /out:$@ $^ $(libs)
%.obj : %.c
cl $(cflags) -c $<
clean:
$(RM) $(target) $(objects)

View file

@ -0,0 +1,31 @@
##
## tgunzip - gzip decompressor example
##
## Watcom / OpenWatcom C/C++ makefile (GNU Make)
##
## Copyright (c) 2003 by Joergen Ibsen / Jibz
## All Rights Reserved
##
## http://www.ibsensoftware.com/
##
target = tgunzip.exe
objects = tgunzip.obj
libs = ../../lib/tinf.lib
system = nt
cflags = -bt=$(system) -d0 -ox -I..\..\src
ldflags = system $(system)
.PHONY: all clean
all: $(target)
$(target): $(objects)
wlink $(ldflags) name $@ file {$^} library {$(libs)}
%.obj : %.c
wcc386 $(cflags) $<
clean:
$(RM) $(objects) $(target)

115
examples/tgunzip/tgunzip.c Normal file
View file

@ -0,0 +1,115 @@
/*
* tgunzip - gzip decompressor example
*
* Copyright (c) 2003 by Joergen Ibsen / Jibz
* All Rights Reserved
*
* http://www.ibsensoftware.com/
*
* 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include "tinf.h"
void exit_error(const char *what)
{
printf("ERROR: %s\n", what);
exit(1);
}
int main(int argc, char *argv[])
{
FILE *fin, *fout;
unsigned int len, dlen, outlen;
unsigned char *source, *dest;
int res;
printf("tgunzip - example from the tiny inflate library (www.ibsensoftware.com)\n\n");
if (argc < 3)
{
printf(
"Syntax: tgunzip <source> <destination>\n\n"
"Both input and output are kept in memory, so do not use this on huge files.\n");
return 1;
}
tinf_init();
/* -- open files -- */
if ((fin = fopen(argv[1], "rb")) == NULL) exit_error("source file");
if ((fout = fopen(argv[2], "wb")) == NULL) exit_error("destination file");
/* -- read source -- */
fseek(fin, 0, SEEK_END);
len = ftell(fin);
fseek(fin, 0, SEEK_SET);
source = (unsigned char *)malloc(len);
if (source == NULL) exit_error("memory");
if (fread(source, 1, len, fin) != len) exit_error("read");
fclose(fin);
/* -- get decompressed length -- */
dlen = source[len - 1];
dlen = 256*dlen + source[len - 2];
dlen = 256*dlen + source[len - 3];
dlen = 256*dlen + source[len - 4];
dest = (unsigned char *)malloc(dlen);
if (dest == NULL) exit_error("memory");
/* -- decompress data -- */
outlen = dlen;
res = tinf_gzip_uncompress(dest, &outlen, source, len);
if ((res != TINF_OK) || (outlen != dlen)) exit_error("inflate");
printf("decompressed %u bytes\n", outlen);
/* -- write output -- */
fwrite(dest, 1, outlen, fout);
fclose(fout);
return 0;
}

1
lib/empty.dir Normal file
View file

@ -0,0 +1 @@
--- empty dir ---

214
readme.txt Normal file
View file

@ -0,0 +1,214 @@
tinf - tiny inflate library
Version 1.00
Copyright (c) 2003 by Joergen Ibsen / Jibz
All Rights Reserved
http://www.ibsensoftware.com/
About
-----
tinf is a small library implementing the decompression algorithm for the
deflate compressed data format (called 'inflate'). Deflate compression is
used in e.g. zlib, gzip, zip and png.
I wrote it because I needed a small in-memory zlib decompressor for a self-
extracting archive, and the zlib library added 15k to my program. The tinf
code added only 2k.
Naturally the size difference is insignificant in most cases. Also, the
zlib library has many more features, is more secure, and mostly faster.
But if you have a project that calls for a small and simple deflate
decompressor, give it a try :-)
While the implementation should be fairly compliant, it does assume it is
given valid compressed data, and that there is sufficient space for the
decompressed data.
Simple wrappers for decompressing zlib streams and gzip'ed data in memory
are supplied.
tgunzip, an example command-line gzip decompressor in C, is included.
The inflate algorithm and data format are from 'DEFLATE Compressed Data
Format Specification version 1.3' (RFC 1951).
The zlib data format is from 'ZLIB Compressed Data Format Specification
version 3.3' (RFC 1950).
The gzip data format is from 'GZIP file format specification version 4.3'
(RFC 1952).
Ideas for future versions:
- the fixed Huffman trees could be built by tinf_decode_trees()
using a small table
- memory for the TINF_DATA object should be passed, to avoid using
more than 1k of stack space
- wrappers for unpacking zip archives and png images
- implement more in x86 assembler
- more sanity checks
- in tinf_uncompress, the (entry value of) destLen and sourceLen
are not used
- blocking of some sort, so everything does not have to be in mem
- optional table-based huffman decoder
Functionality
-------------
void tinf_init();
Initialise the global uninitialised data used by the decompression code.
This function must be called once before any calls to the decompression
functions.
int tinf_uncompress(void *dest,
unsigned int *destLen,
const void *source,
unsigned int sourceLen);
Decompress data in deflate compressed format from source[] to dest[].
destLen is set to the length of the decompressed data. Returns TINF_OK
on success, and TINF_DATA_ERROR on error.
int tinf_gzip_uncompress(void *dest,
unsigned int *destLen,
const void *source,
unsigned int sourceLen);
Decompress data in gzip compressed format from source[] to dest[]. destLen
is set to the length of the decompressed data. Returns TINF_OK on success,
and TINF_DATA_ERROR on error.
int tinf_zlib_uncompress(void *dest,
unsigned int *destLen,
const void *source,
unsigned int sourceLen);
Decompress data in zlib compressed format from source[] to dest[]. destLen
is set to the length of the decompressed data. Returns TINF_OK on success,
and TINF_DATA_ERROR on error.
unsigned int tinf_adler32(const void *data,
unsigned int length);
Computes the Adler-32 checksum of length bytes starting at data. Used by
tinf_zlib_uncompress().
unsigned int tinf_crc32(const void *data,
unsigned int length);
Computes the CRC32 checksum of length bytes starting at data. Used by
tinf_gzip_uncompress().
Source Code
-----------
The source code is ANSI C, and assumes that int is 32-bit. It has been
tested on the x86 platform under Windows and Linux.
The decompression functions should be endian-neutral, and also reentrant
and thread-safe (not tested).
In src/nasm there are 32-bit x86 assembler (386+) versions of some of the
files.
Makefiles (GNU Make style) for a number of compilers are included.
Frequently Asked Questions
--------------------------
Q: Is it really free? Can I use it in my commercial ExpenZip software?
A: It's open-source software, available under the zlib license (see
later), which means you can use it for free -- even in commercial
products. If you do, please be kind enough to add an acknowledgement.
Q: Did you just strip stuff from the zlib source to make it smaller?
A: No, tinf was written from scratch, using the RFC documentation of
the formats it supports.
Q: What do you mean by: 'the zlib library .. is more secure'?
A: The zlib decompression code checks the compressed data for validity
while decompressing, so even on corrupted data it will not crash.
The tinf code assumes it is given valid compressed data.
Q: I'm a Delphi programmer, can I use tinf?
A: Sure, the object files produced by both Borland C and Watcom C should
be linkable with Delphi.
Q: Will tinf work on UltraSTRANGE machines running WhackOS?
A: I have no idea .. please try it out and let me know!
Q: Why are all the makefiles in GNU Make style?
A: I'm used to GNU Make, and it has a number of features that are missing
in some of the other Make utilities.
Q: This is the first release, how can there be frequently asked questions?
A: Ok, ok .. I made the questions up ;-)
Greetings and Thanks
--------------------
- Jean-loup Gailly and Mark Adler for the zlib library.
- Eugene Suslikov (SEN) for making HIEW.
- Oleh Yuschuk for making OllyDbg.
- MinGW development team for making MinGW.
- NASM development team for making NASM.
A special thanks to the beta-testers:
- Gautier
- Lawrence E. Boothby
- METALBRAIN
- Oleg Prokhorov
- Veit Kannegieser
License
-------
tinf is made available under the zlib license:
tinf - tiny inflate library
Copyright (c) 2003 by Joergen Ibsen / Jibz
All Rights Reserved
http://www.ibsensoftware.com/
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.
History
-------
v1.00 *: First release.
Project started September 14th 2003.

78
src/adler32.c Normal file
View file

@ -0,0 +1,78 @@
/*
* Adler-32 checksum
*
* Copyright (c) 2003 by Joergen Ibsen / Jibz
* All Rights Reserved
*
* http://www.ibsensoftware.com/
*
* 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.
*/
/*
* Adler-32 algorithm taken from the zlib source, which is
* Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
*/
#include "tinf.h"
#define A32_BASE 65521
#define A32_NMAX 5552
unsigned int tinf_adler32(const void *data, unsigned int length)
{
const unsigned char *buf = (const unsigned char *)data;
unsigned int s1 = 1;
unsigned int s2 = 0;
while (length > 0)
{
int k = length < A32_NMAX ? length : A32_NMAX;
int i;
for (i = k / 16; i; --i, buf += 16)
{
s1 += buf[0]; s2 += s1; s1 += buf[1]; s2 += s1;
s1 += buf[2]; s2 += s1; s1 += buf[3]; s2 += s1;
s1 += buf[4]; s2 += s1; s1 += buf[5]; s2 += s1;
s1 += buf[6]; s2 += s1; s1 += buf[7]; s2 += s1;
s1 += buf[8]; s2 += s1; s1 += buf[9]; s2 += s1;
s1 += buf[10]; s2 += s1; s1 += buf[11]; s2 += s1;
s1 += buf[12]; s2 += s1; s1 += buf[13]; s2 += s1;
s1 += buf[14]; s2 += s1; s1 += buf[15]; s2 += s1;
}
for (i = k % 16; i; --i) { s1 += *buf++; s2 += s1; }
s1 %= A32_BASE;
s2 %= A32_BASE;
length -= k;
}
return (s2 << 16) | s1;
}

64
src/crc32.c Normal file
View file

@ -0,0 +1,64 @@
/*
* CRC32 checksum
*
* Copyright (c) 1998-2003 by Joergen Ibsen / Jibz
* All Rights Reserved
*
* http://www.ibsensoftware.com/
*
* 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.
*/
/*
* CRC32 algorithm taken from the zlib source, which is
* Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
*/
#include "tinf.h"
static const unsigned int tinf_crc32tab[16] = {
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190,
0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344,
0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278,
0xbdbdf21c
};
unsigned int tinf_crc32(const void *data, unsigned int length)
{
const unsigned char *buf = (const unsigned char *)data;
unsigned int crc = 0xffffffff;
unsigned int i;
if (length == 0) return 0;
for (i = 0; i < length; ++i)
{
crc ^= buf[i];
crc = tinf_crc32tab[crc & 0x0f] ^ (crc >> 4);
crc = tinf_crc32tab[crc & 0x0f] ^ (crc >> 4);
}
return crc ^ 0xffffffff;
}

34
src/makefile.b32 Normal file
View file

@ -0,0 +1,34 @@
##
## tinflib - tiny inflate library (inflate, gzip, zlib)
##
## Borland C/C++ makefile (GNU Make)
##
## Copyright (c) 2003 by Joergen Ibsen / Jibz
## All Rights Reserved
##
## http://www.ibsensoftware.com/
##
target = ..\lib\tinf.lib
objects = tinflate.obj tinfgzip.obj tinfzlib.obj adler32.obj crc32.obj
cflags = -a16 -K -O2 -OS
.PHONY: all clean
all: $(target)
$(target): $(objects)
$(RM) $@
echo $(patsubst %,+%,$(objects)) >> lib.cmd
tlib $@ /C @lib.cmd
$(RM) lib.cmd
%.obj : %.c
bcc32 $(cflags) -c $<
%.obj : %.nas
nasm -o $@ -f obj -D_OBJ_ -O3 -Inasm/ $<
clean:
$(RM) $(objects) $(target) $(temps)

33
src/makefile.dj2 Normal file
View file

@ -0,0 +1,33 @@
##
## tinflib - tiny inflate library (inflate, gzip, zlib)
##
## DJGPP makefile
##
## Copyright (c) 2003 by Joergen Ibsen / Jibz
## All Rights Reserved
##
## http://www.ibsensoftware.com/
##
target = ../lib/libtinf.a
objects = tinflate.o tinfgzip.o tinfzlib.o adler32.o crc32.o
cflags = -s -Wall -Os -fomit-frame-pointer
.PHONY: all clean
all: $(target)
$(target): $(objects)
$(RM) $@
ar -frsv $@ $^
ranlib $@
%.o : %.c
gcc $(cflags) -o $@ -c $<
%.o : %.nas
nasm -o $@ -f coff -O3 -Inasm/ $<
clean:
$(RM) $(objects) $(target)

32
src/makefile.dmc Normal file
View file

@ -0,0 +1,32 @@
##
## tinflib - tiny inflate library (inflate, gzip, zlib)
##
## Digital Mars C/C++ makefile (GNU Make)
##
## Copyright (c) 2003 by Joergen Ibsen / Jibz
## All Rights Reserved
##
## http://www.ibsensoftware.com/
##
target = ..\lib\tinf.lib
objects = tinflate.obj tinfgzip.obj tinfzlib.obj adler32.obj crc32.obj
cflags = -s -mn -o+all
.PHONY: all clean
all: $(target)
$(target): $(objects)
$(RM) $@
lib -c $@ $^
%.obj : %.c
dmc $(cflags) -c $<
%.obj : %.nas
nasm -o $@ -f obj -D_OBJ_ -O3 $<
clean:
$(RM) $(objects) $(target) $(temps)

34
src/makefile.elf Normal file
View file

@ -0,0 +1,34 @@
##
## tinflib - tiny inflate library (inflate, gzip, zlib)
##
## GCC makefile (Linux, FreeBSD, BeOS and QNX)
##
## Copyright (c) 2003 by Joergen Ibsen / Jibz
## All Rights Reserved
##
## http://www.ibsensoftware.com/
##
target = ../lib/libtinf.a
objects = tinflate.o tinfgzip.o tinfzlib.o adler32.o crc32.o
cflags = -s -Wall -Os
ldflags = $(cflags)
.PHONY: all clean
all: $(target)
$(target): $(objects)
$(RM) $@
ar -frsv $@ $^
ranlib $@
%.o : %.c
gcc $(cflags) -o $@ -c $<
%.o : %.nas
nasm -o $@ -f elf -D_ELF_ -O3 -Inasm/ $<
clean:
$(RM) $(objects) $(target)

31
src/makefile.mgw Normal file
View file

@ -0,0 +1,31 @@
##
## tinflib - tiny inflate library (inflate, gzip, zlib)
##
## MinGW / Cygwin makefile
##
## Copyright (c) 2003 by Joergen Ibsen / Jibz
## All Rights Reserved
##
target = ../lib/libtinf.a
objects = tinflate.o tinfgzip.o tinfzlib.o adler32.o crc32.o
cflags = -s -Wall -Os -fomit-frame-pointer
.PHONY: all clean
all: $(target)
$(target): $(objects)
$(RM) $@
ar -frsv $@ $^
ranlib $@
%.o : %.c
gcc $(cflags) -o $@ -c $<
%.o : %.nas
nasm -o $@ -f win32 -O3 -Inasm/ $<
clean:
$(RM) $(target) $(objects)

30
src/makefile.vc Normal file
View file

@ -0,0 +1,30 @@
##
## tinflib - tiny inflate library (inflate, gzip, zlib)
##
## Visual C++ Makefile (GNU Make)
##
## Copyright (c) 2003 by Joergen Ibsen / Jibz
## All Rights Reserved
##
target = ../lib/tinf.lib
objects = tinflate.obj tinfgzip.obj tinfzlib.obj adler32.obj crc32.obj
cflags = /nologo /W3 /O1 /G6 /W3 /Gy /GF
.PHONY: all clean
all: $(target)
$(target): $(objects)
$(RM) $@
lib /OUT:$@ $^
%.obj : %.c
cl $(cflags) -c $<
%.obj : %.nas
nasm -o $@ -f win32 -O3 -Inasm/ $<
clean:
$(RM) $(target) $(objects)

35
src/makefile.wat Normal file
View file

@ -0,0 +1,35 @@
##
## tinflib - tiny inflate library (inflate, gzip, zlib)
##
## Watcom / OpenWatcom C/C++ makefile (GNU Make)
##
## Copyright (c) 2003 by Joergen Ibsen / Jibz
## All Rights Reserved
##
## http://www.ibsensoftware.com/
##
target = ..\lib\tinf.lib
objects = tinflate.obj tinfgzip.obj tinfzlib.obj adler32.obj crc32.obj
system = nt
cflags = -bt=$(system) -d0 -obmlrs -s -zl
.PHONY: all clean
all: $(target)
$(target): $(objects)
$(RM) $@
echo $(patsubst %,+%,$(objects)) >> lib.cmd
wlib -c -n -q -s -fo -io $@ @lib.cmd
$(RM) lib.cmd
%.obj : %.c
wcc386 $(cflags) $<
%.obj : %.nas
nasm -o $@ -f obj -D_OBJ_ -O3 -Inasm/ $<
clean:
$(RM) $(objects) $(target)

118
src/nasm/crc32.nas Normal file
View file

@ -0,0 +1,118 @@
;;
;; NASM assembler crc32
;;
;; Copyright (c) 1998-2003 by Joergen Ibsen / Jibz
;; All Rights Reserved
;;
;; http://www.ibsensoftware.com/
;;
;; 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.
;;
; CRC32 algorithm taken from the zlib source, which is
; Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
cpu 386
bits 32
%include "nasmlcm.inc"
section lcmtext
lcmglobal tinf_crc32,8
lcmexport tinf_crc32,8
; =============================================================
lcmlabel tinf_crc32,8
; tinf_crc32(const void *data,
; unsigned int length);
.len$ equ 2*4 + 4 + 4
.dat$ equ 2*4 + 4
push esi
push edi
mov esi, [esp + .dat$] ; esi -> buffer
mov ecx, [esp + .len$] ; ecx = length
sub eax, eax ; crc = 0
test esi, esi
jz short .c_exit
test ecx, ecx
jz short .c_exit
dec eax ; crc = 0xffffffff
%ifdef _OBJ_
mov edi, tinf_crc32tab wrt FLAT ; edi -> crctab
%else
mov edi, tinf_crc32tab ; edi -> crctab
%endif
.c_next_byte:
xor al, [esi]
inc esi
mov edx, 0x0f
and edx, eax
shr eax, 4
xor eax, [edi + edx*4]
mov edx, 0x0f
and edx, eax
shr eax, 4
xor eax, [edi + edx*4]
dec ecx
jnz short .c_next_byte
not eax
.c_exit:
pop edi
pop esi
lcmret 8
; =============================================================
section lcmdata
tinf_crc32tab dd 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190
dd 0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344
dd 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278
dd 0xbdbdf21c
; =============================================================

326
src/nasm/nasmlcm.inc Normal file
View file

@ -0,0 +1,326 @@
;;
;; NASM linker compatibility macros 2002.07.24
;;
;; Copyright (c) 2001-2003 by Joergen Ibsen / Jibz
;; All Rights Reserved
;;
;; http://www.ibsensoftware.com/
;;
; define _ELF_ for ELF32 object files
; define _OBJ_ for OMF object files
; define _OBJ_ and _DLL_ for OMF object files for a dll (stdcall)
; define _MSLIBS_ for MS style Win32 import libs (lcmwinextern)
; default is DJGPP/WIN32 COFF object files
; remember to do lcm*extern before lcmimport
; ====================================================================
;
; There are differences between how the object formats that NASM
; supports work, and what features they support. Similarly there
; are differences between how complete and standard compliant the
; support for these formats are in linkers.
;
; The NASM linker compatibility macros (nasmlcm) were put together
; to ease my work by allowing a single source file to be assembled
; for use with a number of compilers/linkers.
;
; Currently obj/omf, win32/coff, djgpp/coff and elf32 output formats
; are supported. The following macros are available:
;
; lcmtext - section name for the code section
; lcmdata - section name for the initialized data section
; lcmbss - section name for the uninitialized data section
;
; lcmglobal - declare a function (two arguments) or data (one
; argument) as global in the current format
; lcmcglobal - same as lcmglobal, but uses C name decoration
;
; lcmextern - declare a function (two arguments) or data (one
; argument) as extern in the current format
; lcmcextern - same as lcmextern, but uses C name decoration
; lcmdllextern - same as lcmextern, but uses dll name decoration
; lcmwinextern - same as lcmextern, but uses name decoration for
; calling Win32 Api functions (see _MSLIBS_)
;
; lcmimport - declares a function (two arguments) or data (one
; argument) as imported in the current format
; lcmexport - declares a function (two arguments) or data (one
; argument) as exported in the current format
;
; lcmlabel - start label for a function in the current format
; lcmclabel - start label for a function with C name decoration
; lcmadjust - adjust stack after a function call in the current
; format
; lcmret - return from a function in the current format
; lcmcret - return from a C function
;
; The following defines change the format and behaviour:
;
; _ELF_ - the lcm*global macro adds :function and :data type
; specifiers
;
; _OBJ_ - section names are similar to those produced by
; Borland tools to increase compatibility with
; various OMF compatible linkers
;
; _DLL_ - functions are exported and imported with added
; size specifiers (_SomeFunction@12), lcmret adjusts
; stack (stdcall)
;
; _MSLIBS_ - the lcmwinextern macro prepends an underscore and
; adds size specification for functions, allowing
; the object file to be linked with MS libraries.
;
; ====================================================================
%ifndef NASMLCM_INC_INCLUDED
%define NASMLCM_INC_INCLUDED
%ifdef _DLL_
%ifndef _OBJ_
%error "_DLL_ needs _OBJ_ defined!"
%endif
%endif
; --- define lcm- section names ---
;
; a number of linkers require omf objects where the section
; names are equal to those produces by tasm.
%ifdef _OBJ_
%define lcmtext _TEXT class=CODE public use32 align=4 FLAT
%define lcmdata _DATA class=DATA public use32 align=4
%define lcmbss _BSS class=BSS public use32 align=4 FLAT
group FLAT
group DGROUP _DATA
%else ; _OBJ_
%define lcmtext .text
%define lcmdata .data
%define lcmbss .bss
%endif ; _OBJ_
; --- define lcmglobal and lcm*extern macros ---
;
; special handling of functions and data for ELF32
%ifdef _ELF_
%macro lcmglobal 2
global %{1}:function
%endmacro
%macro lcmglobal 1
global %{1}:data
%endmacro
%define lcmcglobal lcmglobal
%macro lcmextern 1-2
extern %1
%endmacro
%macro lcmcextern 0
%error lcmcextern not supported in ELF format
%endmacro
%macro lcmdllextern 0
%error lcmdllextern not supported in ELF format
%endmacro
%else ; _ELF_
%ifdef _DLL_
%macro lcmglobal 2
global _%1
global _%1@%2
%endmacro
%macro lcmglobal 1
global _%1
%define %1 _%1
%endmacro
%macro lcmcglobal 2
global _%1
%endmacro
%macro lcmcglobal 1
global _%1
%define %1 _%1
%endmacro
%macro lcmextern 2
extern _%1@%2
%define %1 _%1@%2
%endmacro
%macro lcmextern 1
extern _%1
%define %1 _%1
%endmacro
%else
%macro lcmglobal 2
global _%1
%endmacro
%macro lcmglobal 1
global _%1
%define %1 _%1
%endmacro
%define lcmcglobal lcmglobal
%macro lcmextern 1-2
extern _%1
%define %1 _%1
%endmacro
%endif
%macro lcmcextern 1-2
extern _%1
%define %1 _%1
%endmacro
%macro lcmdllextern 2
extern _%1@%2
%define %1 _%1@%2
%endmacro
%macro lcmdllextern 1
extern _%1
%define %1 _%1
%endmacro
%macro lcmwinextern 2
%ifdef _MSLIBS_
extern _%1@%2
%define %1 _%1@%2
%else
extern %1
%endif
%endmacro
%endif ; _ELF_
; --- define lcmimport and lcmexport ---
;
%ifdef _OBJ_
%macro lcmimport 2-3
import %1 %2 %3
%rotate 1
%endmacro
%ifdef _DLL_
%macro lcmexport 2
export _%1
export _%1@%2
%endmacro
%macro lcmexport 1
export _%1
%endmacro
%else
%macro lcmexport 1-2
%endmacro
%endif
%else ; _OBJ_
%macro lcmimport 2-3
%endmacro
%macro lcmexport 1-2
%endmacro
%endif ; _OBJ_
; --- define lcmlabel, lcmadjust and lcmret macros ---
;
; we need special labels and stdcall calling convention when
; assembling for a dll
%ifdef _ELF_
%macro lcmlabel 2
%1:
%endmacro
%define lcmclabel lcmlabel
%macro lcmadjust 1
%if %1 < 128
add esp, byte %1
%else
add esp, %1
%endif
%endmacro
%macro lcmret 1
ret
%endmacro
%define lcmcret lcmret
%else ; _ELF_
%ifdef _DLL_
%macro lcmlabel 2
_%1:
_%1@%2:
%endmacro
%macro lcmclabel 2
_%1:
%endmacro
%macro lcmadjust 1
%endmacro
%macro lcmret 1
%if %1 > 0
ret %1
%else
ret
%endif
%endmacro
%macro lcmcret 1
ret
%endmacro
%else
%macro lcmlabel 2
_%1:
%endmacro
%define lcmclabel lcmlabel
%macro lcmadjust 1
%if %1 < 128
add esp, byte %1
%else
add esp, %1
%endif
%endmacro
%macro lcmret 1
ret
%endmacro
%define lcmcret lcmret
%endif
%endif ; _ELF_
%endif ; NASMLCM_INC_INCLUDED

160
src/nasm/tinfzlib.nas Normal file
View file

@ -0,0 +1,160 @@
;;
;; tinfzlib - tiny zlib uncompress
;;
;; Copyright (c) 2003 by Joergen Ibsen / Jibz
;; All Rights Reserved
;;
;; http://www.ibsensoftware.com/
;;
;; 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.
;;
TINF_OK equ 0
TINF_DATA_ERROR equ (-3)
cpu 386
bits 32
%include "nasmlcm.inc"
section lcmtext
lcmglobal tinf_zlib_uncompress,16
lcmexport tinf_zlib_uncompress,16
lcmextern tinf_uncompress,16
lcmextern tinf_adler32,8
; =============================================================
lcmlabel tinf_zlib_uncompress,16
; tinf_zlib_uncompress(void *dest,
; unsigned int *destLen,
; const void *source,
; unsigned int sourceLen)
.slen$ equ 2*4 + 4 + 12
.src$ equ 2*4 + 4 + 8
.dlen$ equ 2*4 + 4 + 4
.dst$ equ 2*4 + 4
push esi
push ebx
mov esi, [esp + .src$] ; esi -> source
; -- get header bytes --
movzx eax, word [esi] ; al = cmf, ah = flg,
; -- check format --
; check method is deflate
; if ((cmf & 0x0f) != 8) return TINF_DATA_ERROR;
mov cl, 0x0f
and cl, al
cmp cl, 8
jne short .return_error
; check window size is valid
; if ((cmf >> 4) > 7) return TINF_DATA_ERROR;
mov ch, al
shr ch, 4
cmp ch, cl ; cl = 8 from above
jae short .return_error
; check there is no preset dictionary
; if (flg & 0x20) return TINF_DATA_ERROR;
test ah, 0x20
jnz short .return_error
; check checksum
; if ((256*cmf + flg) % 31) return TINF_DATA_ERROR;
xchg al, ah
xor edx, edx
lea ebx, [edx + 31]
div ebx
test edx, edx
jnz short .return_error
; -- get adler32 checksum --
mov ecx, [esp + .slen$] ; ecx = sourceLen
mov ebx, [esi + ecx - 4]
%ifdef BSWAP_OK
bswap ebx
%else ; BSWAP_OK
xchg bl, bh
rol ebx, 16
xchg bl, bh
%endif ; BSWAP_OK
; -- inflate --
; res = tinf_uncompress(dst, destLen, src + 2, sourceLen - 6);
lea eax, [ecx - 6]
push eax
lea eax, [esi + 2]
push eax
push dword [esp + 8 + .dlen$]
push dword [esp + 12 + .dst$]
call tinf_uncompress
add esp, byte 16
; if (res != TINF_OK) return TINF_DATA_ERROR;
test eax, eax
jnz short .return_error
; -- check adler32 checksum --
; if (a32 != tinf_adler32(dst, *destLen)) return TINF_DATA_ERROR;
mov eax, [esp + .dlen$];
push dword [eax]
push dword [esp + 4 + .dst$]
call tinf_adler32
add esp, byte 8
sub eax, ebx
jz short .return_eax
.return_error:
mov eax, TINF_DATA_ERROR
.return_eax:
pop ebx
pop esi
lcmret 16
; =============================================================
%ifdef _OBJ_
section lcmdata
%endif
; =============================================================

52
src/tinf.h Normal file
View file

@ -0,0 +1,52 @@
/*
* tinf - tiny inflate library (inflate, gzip, zlib)
*
* version 1.00
*
* Copyright (c) 2003 by Joergen Ibsen / Jibz
* All Rights Reserved
*
* http://www.ibsensoftware.com/
*/
#ifndef TINF_H_INCLUDED
#define TINF_H_INCLUDED
/* calling convention */
#ifndef TINFCC
#ifdef __WATCOMC__
#define TINFCC __cdecl
#else
#define TINFCC
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define TINF_OK 0
#define TINF_DATA_ERROR (-3)
/* function prototypes */
void TINFCC tinf_init();
int TINFCC tinf_uncompress(void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen);
int TINFCC tinf_gzip_uncompress(void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen);
int TINFCC tinf_zlib_uncompress(void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen);
unsigned int TINFCC tinf_adler32(const void *data, unsigned int length);
unsigned int TINFCC tinf_crc32(const void *data, unsigned int length);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* TINF_H_INCLUDED */

124
src/tinfgzip.c Normal file
View file

@ -0,0 +1,124 @@
/*
* tinfgzip - tiny gzip decompressor
*
* Copyright (c) 2003 by Joergen Ibsen / Jibz
* All Rights Reserved
*
* http://www.ibsensoftware.com/
*
* 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.
*/
#include "tinf.h"
#define FTEXT 1
#define FHCRC 2
#define FEXTRA 4
#define FNAME 8
#define FCOMMENT 16
int tinf_gzip_uncompress(void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen)
{
unsigned char *src = (unsigned char *)source;
unsigned char *dst = (unsigned char *)dest;
unsigned char *start;
unsigned int dlen, crc32;
int res;
unsigned char flg;
/* -- check format -- */
/* check id bytes */
if (src[0] != 0x1f || src[1] != 0x8b) return TINF_DATA_ERROR;
/* check method is deflate */
if (src[2] != 8) return TINF_DATA_ERROR;
/* get flag byte */
flg = src[3];
/* check that reserved bits are zero */
if (flg & 0xe0) return TINF_DATA_ERROR;
/* -- find start of compressed data -- */
/* skip base header of 10 bytes */
start = src + 10;
/* skip extra data if present */
if (flg & FEXTRA)
{
unsigned int xlen = start[1];
xlen = 256*xlen + start[0];
start += xlen + 2;
}
/* skip file name if present */
if (flg & FNAME) { while (*start) ++start; ++start; }
/* skip file comment if present */
if (flg & FCOMMENT) { while (*start) ++start; ++start; }
/* check header crc if present */
if (flg & FHCRC)
{
unsigned int hcrc = start[1];
hcrc = 256*hcrc + start[0];
if (hcrc != (tinf_crc32(src, start - src) & 0x0000ffff))
return TINF_DATA_ERROR;
start += 2;
}
/* -- get decompressed length -- */
dlen = src[sourceLen - 1];
dlen = 256*dlen + src[sourceLen - 2];
dlen = 256*dlen + src[sourceLen - 3];
dlen = 256*dlen + src[sourceLen - 4];
/* -- get crc32 of decompressed data -- */
crc32 = src[sourceLen - 5];
crc32 = 256*crc32 + src[sourceLen - 6];
crc32 = 256*crc32 + src[sourceLen - 7];
crc32 = 256*crc32 + src[sourceLen - 8];
/* -- decompress data -- */
res = tinf_uncompress(dst, destLen, start, src + sourceLen - start - 8);
if (res != TINF_OK) return TINF_DATA_ERROR;
if (*destLen != dlen) return TINF_DATA_ERROR;
/* -- check CRC32 checksum -- */
if (crc32 != tinf_crc32(dst, dlen)) return TINF_DATA_ERROR;
return TINF_OK;
}

457
src/tinflate.c Normal file
View file

@ -0,0 +1,457 @@
/*
* tinflate - tiny inflate
*
* Copyright (c) 2003 by Joergen Ibsen / Jibz
* All Rights Reserved
*
* http://www.ibsensoftware.com/
*
* 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.
*/
#include "tinf.h"
/* ------------------------------ *
* -- internal data structures -- *
* ------------------------------ */
typedef struct {
unsigned short table[16]; /* table of code length counts */
unsigned short trans[288]; /* code -> symbol translation table */
} TINF_TREE;
typedef struct {
const unsigned char *source;
unsigned int tag;
unsigned int bitcount;
unsigned char *dest;
unsigned int *destLen;
TINF_TREE ltree; /* dynamic length/symbol tree */
TINF_TREE dtree; /* dynamic distance tree */
} TINF_DATA;
/* --------------------------------------------------- *
* -- uninitialized global data (static structures) -- *
* --------------------------------------------------- */
TINF_TREE sltree; /* fixed length/symbol tree */
TINF_TREE sdtree; /* fixed distance tree */
/* extra bits and base tables for length codes */
unsigned char length_bits[30];
unsigned short length_base[30];
/* extra bits and base tables for distance codes */
unsigned char dist_bits[30];
unsigned short dist_base[30];
/* special ordering of code length codes */
const unsigned char clcidx[] = {
16, 17, 18, 0, 8, 7, 9, 6,
10, 5, 11, 4, 12, 3, 13, 2,
14, 1, 15
};
/* ----------------------- *
* -- utility functions -- *
* ----------------------- */
/* build extra bits and base tables */
static void tinf_build_bits_base(unsigned char *bits, unsigned short *base, int delta, int first)
{
int i, sum;
/* build bits table */
for (i = 0; i < delta; ++i) bits[i] = 0;
for (i = 0; i < 30 - delta; ++i) bits[i + delta] = i / delta;
/* build base table */
for (sum = first, i = 0; i < 30; ++i)
{
base[i] = sum;
sum += 1 << bits[i];
}
}
/* build the fixed huffman trees */
static void tinf_build_fixed_trees(TINF_TREE *lt, TINF_TREE *dt)
{
int i;
/* build fixed length tree */
for (i = 0; i < 7; ++i) lt->table[i] = 0;
lt->table[7] = 24;
lt->table[8] = 152;
lt->table[9] = 112;
for (i = 0; i < 24; ++i) lt->trans[i] = 256 + i;
for (i = 0; i < 144; ++i) lt->trans[24 + i] = i;
for (i = 0; i < 8; ++i) lt->trans[24 + 144 + i] = 280 + i;
for (i = 0; i < 112; ++i) lt->trans[24 + 144 + 8 + i] = 144 + i;
/* build fixed distance tree */
for (i = 0; i < 5; ++i) dt->table[i] = 0;
dt->table[5] = 32;
for (i = 0; i < 32; ++i) dt->trans[i] = i;
}
/* given an array of code lengths, build a tree */
static void tinf_build_tree(TINF_TREE *t, const unsigned char *lengths, unsigned int num)
{
unsigned short offs[16];
unsigned int i, sum;
/* clear code length count table */
for (i = 0; i < 16; ++i) t->table[i] = 0;
/* scan symbol lengths, and sum code length counts */
for (i = 0; i < num; ++i) t->table[lengths[i]]++;
t->table[0] = 0;
/* compute offset table for distribution sort */
for (sum = 0, i = 0; i < 16; ++i)
{
offs[i] = sum;
sum += t->table[i];
}
/* create code->symbol translation table (symbols sorted by code) */
for (i = 0; i < num; ++i)
{
if (lengths[i]) t->trans[offs[lengths[i]]++] = i;
}
}
/* ---------------------- *
* -- decode functions -- *
* ---------------------- */
/* get one bit from source stream */
static int tinf_getbit(TINF_DATA *d)
{
unsigned int bit;
/* check if tag is empty */
if (!d->bitcount--)
{
/* load next tag */
d->tag = *d->source++;
d->bitcount = 7;
}
/* shift bit out of tag */
bit = d->tag & 0x01;
d->tag >>= 1;
return bit;
}
/* read a num bit value from a stream and add base */
static unsigned int tinf_read_bits(TINF_DATA *d, int num, int base)
{
unsigned int val = 0;
/* read num bits */
if (num)
{
unsigned int limit = 1 << (num);
unsigned int mask;
for (mask = 1; mask < limit; mask *= 2)
if (tinf_getbit(d)) val += mask;
}
return val + base;
}
/* given a data stream and a tree, decode a symbol */
static int tinf_decode_symbol(TINF_DATA *d, TINF_TREE *t)
{
int sum = 0, cur = 0, len = 0;
/* get more bits while code value is above sum */
do {
cur = 2*cur + tinf_getbit(d);
++len;
sum += t->table[len];
cur -= t->table[len];
} while (cur >= 0);
return t->trans[sum + cur];
}
/* given a data stream, decode dynamic trees from it */
static void tinf_decode_trees(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt)
{
TINF_TREE code_tree;
unsigned char lengths[288+32];
unsigned int hlit, hdist, hclen;
unsigned int i, num, length;
/* get 5 bits HLIT (257-286) */
hlit = tinf_read_bits(d, 5, 257);
/* get 5 bits HDIST (1-32) */
hdist = tinf_read_bits(d, 5, 1);
/* get 4 bits HCLEN (4-19) */
hclen = tinf_read_bits(d, 4, 4);
for (i = 0; i < 19; ++i) lengths[i] = 0;
/* read code lengths for code length alphabet */
for (i = 0; i < hclen; ++i)
{
/* get 3 bits code length (0-7) */
unsigned int clen = tinf_read_bits(d, 3, 0);
lengths[clcidx[i]] = clen;
}
/* build code length tree */
tinf_build_tree(&code_tree, lengths, 19);
/* decode code lengths for the dynamic trees */
for (num = 0; num < hlit + hdist; )
{
int sym = tinf_decode_symbol(d, &code_tree);
switch (sym)
{
case 16:
/* copy previous code length 3-6 times (read 2 bits) */
{
unsigned char prev = lengths[num - 1];
for (length = tinf_read_bits(d, 2, 3); length; --length)
{
lengths[num++] = prev;
}
}
break;
case 17:
/* repeat code length 0 for 3-10 times (read 3 bits) */
for (length = tinf_read_bits(d, 3, 3); length; --length)
{
lengths[num++] = 0;
}
break;
case 18:
/* repeat code length 0 for 11-138 times (read 7 bits) */
for (length = tinf_read_bits(d, 7, 11); length; --length)
{
lengths[num++] = 0;
}
break;
default:
/* values 0-15 represent the actual code lengths */
lengths[num++] = sym;
break;
}
}
/* build dynamic trees */
tinf_build_tree(lt, lengths, hlit);
tinf_build_tree(dt, lengths + hlit, hdist);
}
/* ----------------------------- *
* -- block inflate functions -- *
* ----------------------------- */
/* given a stream and two trees, inflate a block of data */
static int tinf_inflate_block_data(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt)
{
/* remember current output position */
unsigned char *start = d->dest;
while (1)
{
int sym = tinf_decode_symbol(d, lt);
/* check for end of block */
if (sym == 256)
{
*d->destLen += d->dest - start;
return TINF_OK;
}
if (sym < 256)
{
*d->dest++ = sym;
} else {
int length, dist, offs;
int i;
sym -= 257;
/* possibly get more bits from length code */
length = tinf_read_bits(d, length_bits[sym], length_base[sym]);
dist = tinf_decode_symbol(d, dt);
/* possibly get more bits from distance code */
offs = tinf_read_bits(d, dist_bits[dist], dist_base[dist]);
/* copy match */
for (i = 0; i < length; ++i)
{
d->dest[i] = d->dest[i - offs];
}
d->dest += length;
}
}
}
/* inflate an uncompressed block of data */
static int tinf_inflate_uncompressed_block(TINF_DATA *d)
{
unsigned int length, invlength;
unsigned int i;
/* get length */
length = d->source[1];
length = 256*length + d->source[0];
/* get one's complement of length */
invlength = d->source[3];
invlength = 256*invlength + d->source[2];
/* check length */
if (length != (~invlength & 0x0000ffff)) return TINF_DATA_ERROR;
d->source += 4;
/* copy block */
for (i = length; i; --i) *d->dest++ = *d->source++;
/* make sure we start next block on a byte boundary */
d->bitcount = 0;
*d->destLen += length;
return TINF_OK;
}
/* inflate a block of data compressed with fixed huffman trees */
static int tinf_inflate_fixed_block(TINF_DATA *d)
{
/* decode block using fixed trees */
return tinf_inflate_block_data(d, &sltree, &sdtree);
}
/* inflate a block of data compressed with dynamic huffman trees */
static int tinf_inflate_dynamic_block(TINF_DATA *d)
{
/* decode trees from stream */
tinf_decode_trees(d, &d->ltree, &d->dtree);
/* decode block using decoded trees */
return tinf_inflate_block_data(d, &d->ltree, &d->dtree);
}
/* ---------------------- *
* -- public functions -- *
* ---------------------- */
/* initialize global (static) data */
void tinf_init()
{
/* build fixed huffman trees */
tinf_build_fixed_trees(&sltree, &sdtree);
/* build extra bits and base tables */
tinf_build_bits_base(length_bits, length_base, 4, 3);
tinf_build_bits_base(dist_bits, dist_base, 2, 1);
/* fix a special case */
length_bits[28] = 0;
length_base[28] = 258;
}
/* inflate stream from source to dest */
int tinf_uncompress(void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen)
{
TINF_DATA d;
int bfinal;
/* initialise data */
d.source = (const unsigned char *)source;
d.bitcount = 0;
d.dest = (unsigned char *)dest;
d.destLen = destLen;
*destLen = 0;
do {
unsigned int btype;
int res;
/* read final block flag */
bfinal = tinf_getbit(&d);
/* read block type (2 bits) */
btype = tinf_read_bits(&d, 2, 0);
/* decompress block */
switch (btype)
{
case 0:
/* decompress uncompressed block */
res = tinf_inflate_uncompressed_block(&d);
break;
case 1:
/* decompress block with fixed huffman trees */
res = tinf_inflate_fixed_block(&d);
break;
case 2:
/* decompress block with dynamic huffman trees */
res = tinf_inflate_dynamic_block(&d);
break;
default:
return TINF_DATA_ERROR;
}
if (res != TINF_OK) return TINF_DATA_ERROR;
} while (!bfinal);
return TINF_OK;
}

82
src/tinfzlib.c Normal file
View file

@ -0,0 +1,82 @@
/*
* tinfzlib - tiny zlib decompressor
*
* Copyright (c) 2003 by Joergen Ibsen / Jibz
* All Rights Reserved
*
* http://www.ibsensoftware.com/
*
* 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.
*/
#include "tinf.h"
int tinf_zlib_uncompress(void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen)
{
unsigned char *src = (unsigned char *)source;
unsigned char *dst = (unsigned char *)dest;
unsigned int a32;
int res;
unsigned char cmf, flg;
/* -- get header bytes -- */
cmf = src[0];
flg = src[1];
/* -- check format -- */
/* check checksum */
if ((256*cmf + flg) % 31) return TINF_DATA_ERROR;
/* check method is deflate */
if ((cmf & 0x0f) != 8) return TINF_DATA_ERROR;
/* check window size is valid */
if ((cmf >> 4) > 7) return TINF_DATA_ERROR;
/* check there is no preset dictionary */
if (flg & 0x20) return TINF_DATA_ERROR;
/* -- get adler32 checksum -- */
a32 = src[sourceLen - 4];
a32 = 256*a32 + src[sourceLen - 3];
a32 = 256*a32 + src[sourceLen - 2];
a32 = 256*a32 + src[sourceLen - 1];
/* -- inflate -- */
res = tinf_uncompress(dst, destLen, src + 2, sourceLen - 6);
if (res != TINF_OK) return TINF_DATA_ERROR;
/* -- check adler32 checksum -- */
if (a32 != tinf_adler32(dst, *destLen)) return TINF_DATA_ERROR;
return TINF_OK;
}