flate

deflate implementation
git clone git://git.suckless.org/flate
Log | Files | Refs | README

commit 1b3aea40ec37c7d9fcce28ebe271ecd895200702
parent a832945746253cae75977ce7daa5a14ad34a3885
Author: nsz <nszabolcs@gmail.com>
Date:   Mon, 20 Apr 2009 20:35:17 +0200

cleanups, gcov
Diffstat:
Makefile | 13+++++++++++++
README | 1+
inflate.c | 87++++++++++++++++++++++++++++++++++---------------------------------------------
3 files changed, 51 insertions(+), 50 deletions(-)

diff --git a/Makefile b/Makefile @@ -12,3 +12,16 @@ ${OBJ}: Makefile ${CC} -c ${CFLAGS} $< clean: rm -f ${OBJ} inflate + + +gcov: inflate.c + gcc -fprofile-arcs -ftest-coverage -pg ${CFLAGS} $< + ./a.out test.dat > /dev/null + gcov -b $< > /dev/null + gprof a.out > $<.gprof + gcc ${CFLAGS} $< + valgrind -v --leak-check=yes ./a.out > /dev/null 2> a.valgrind + grep ERROR a.valgrind >a.err.valgrind + grep alloc a.valgrind >a.alloc.valgrind + rm a.out *.gcno *.gcda gmon.out + diff --git a/README b/README @@ -5,6 +5,7 @@ source: tinf from ibsensoftware puff from zlib libflate from plan 9 + halibut/deflate from putty build: make diff --git a/inflate.c b/inflate.c @@ -1,10 +1,12 @@ /* TODO: - error check (src len, dst len) - fillbits(s, n) -> faster getbits() + error check (src len, dst len, hufftree) clever io p9 hufftable int types + speedup: + fillbits(s, n) -> faster getbits() + loop unroll in decode_symbol */ typedef unsigned char uchar; @@ -13,21 +15,17 @@ typedef unsigned int uint; typedef unsigned long ulong; enum { - HuffBits = 16, /* maximum bits in a encoded code */ + HuffBits = 16, /* max number of bits in a code */ Nlit = 256, /* number of lit codes */ Nlen = 29, /* number of len codes */ Nlitlen = Nlit + Nlen + 3, /* number of litlen codes + block end + 2 unused */ - Ndist = 30, /* number of offset codes */ - Nclen = 19, /* number of codelen codes */ - LenShift = 10 /* code = len<<LenShift|code */ -/* LitlenBits = 7,*/ /* number of bits in litlen decode table */ -/* DistBits = 6,*/ /* number of bits in offset decode table */ -/* ClenBits = 6*/ /* number of bits in code len decode table */ + Ndist = 30, /* number of distance codes */ + Nclen = 19, /* number of code length codes */ }; typedef struct { - ushort count[HuffBits]; /* code bit len -> count */ - ushort symbol[Nlitlen]; /* litlen code -> symbol */ + ushort count[HuffBits]; /* code bit length -> count */ + ushort symbol[Nlitlen]; /* symbols ordered by code length */ } HuffTree; typedef struct { @@ -46,7 +44,6 @@ typedef struct { static HuffTree ltree; /* fixed lit/len tree */ static HuffTree dtree; /* fixed distance tree */ -/* extra bits and base tables for length codes */ static uchar lenbits[Nlen] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, @@ -55,7 +52,6 @@ static uchar lenbits[Nlen] = { static ushort lenbase[Nlen]; -/* extra bits and base tables for distance codes */ static uchar distbits[Ndist] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, @@ -92,15 +88,15 @@ static void init_fixed_trees(void) { ltree.count[9] = 112; for (i = 0; i < 24; i++) ltree.symbol[i] = 256 + i; - for (i = 0; i < 144; ++i) + for (i = 0; i < 144; i++) ltree.symbol[24 + i] = i; - for (i = 0; i < 8; ++i) + for (i = 0; i < 8; i++) ltree.symbol[24 + 144 + i] = 280 + i; - for (i = 0; i < 112; ++i) + for (i = 0; i < 112; i++) ltree.symbol[24 + 144 + 8 + i] = 144 + i; dtree.count[5] = Ndist; - for (i = 0; i < Ndist; ++i) + for (i = 0; i < Ndist; i++) dtree.symbol[i] = i; } @@ -121,16 +117,12 @@ static void build_tree(HuffTree *t, const uchar *lens, uint n) { sum += t->count[i]; } - /* create code->symbol translation table (symbols sorted by code) */ + /* sort symbols by code length */ for (i = 0; i < n; i++) if (lens[i]) t->symbol[offs[lens[i]]++] = i; } -/* - * decode functions - */ - /* get one bit from s->src stream */ static uint getbit(FlateStream *s) { uint bit; @@ -162,10 +154,12 @@ static uint decode_symbol(FlateStream *s, HuffTree *t) { /* get bits while code value is above sum */ do { - cur <<= 1; - cur |= getbit(s); len++; + if (len >= HuffBits) + /* error */; sum += t->count[len]; + cur <<= 1; + cur |= getbit(s); cur -= t->count[len]; } while (cur >= 0); @@ -182,7 +176,8 @@ static void decode_trees(FlateStream *s, HuffTree *lt, HuffTree *dt) { nlit = 257 + getbits(s, 5); ndist = 1 + getbits(s, 5); nclen = 4 + getbits(s, 4); - /*if (nlit > Nlitlen || ndist > Ndist) */ + if (nlit > Nlitlen || ndist > Ndist) + /* error */; /* build code length tree */ for (i = 0; i < Nclen; i++) @@ -212,9 +207,8 @@ static void decode_trees(FlateStream *s, HuffTree *lt, HuffTree *dt) { /* repeat 0 for 11-138 times */ for (len = 11 + getbits(s, 7); len; len--) lens[i++] = 0; - } else { - /* error */ - } + } else + /* error */; } /* build dynamic trees */ @@ -237,8 +231,8 @@ static int decode_block(FlateStream *s, HuffTree *lt, HuffTree *dt) { if (sym < 256) *s->dst++ = sym; else { - int len, dist; - int i; + uint len, dist; + uint i; sym -= 257; if (sym >= Nlen) @@ -257,7 +251,6 @@ static int decode_block(FlateStream *s, HuffTree *lt, HuffTree *dt) { } } -/* inflate an uncompressed block of data */ static int inflate_uncompressed_block(FlateStream *s) { uint len, invlen; @@ -277,20 +270,17 @@ static int inflate_uncompressed_block(FlateStream *s) { return 0; } -/* inflate a block of data compressed with fixed huffman trees */ static int inflate_fixed_block(FlateStream *s) { return decode_block(s, &ltree, &dtree); } -/* inflate a block of data compressed with dynamic huffman trees */ static int inflate_dynamic_block(FlateStream *s) { decode_trees(s, &s->ltree, &s->dtree); return decode_block(s, &s->ltree, &s->dtree); } -/* - * extern functions - */ + +/* extern functions */ /* initialize global (static) data */ void inflate_init(void) { @@ -301,7 +291,7 @@ void inflate_init(void) { /* inflate stream from src to dst */ int inflate(void *dst, uint *dstlen, const void *src, uint srclen) { FlateStream s; - uint bfinal; + uint final; s.src = src; s.nbits = 0; @@ -309,17 +299,14 @@ int inflate(void *dst, uint *dstlen, const void *src, uint srclen) { s.dstlen = dstlen; *dstlen = 0; do { - uint btype; + uint blocktype; int res; - /* read final block flag */ - bfinal = getbit(&s); - - /* read block type */ - btype = getbits(&s, 2); + final = getbit(&s); + blocktype = getbits(&s, 2); /* decompress block */ - switch (btype) { + switch (blocktype) { case 0: res = inflate_uncompressed_block(&s); break; @@ -334,7 +321,7 @@ int inflate(void *dst, uint *dstlen, const void *src, uint srclen) { } if (res != 0) return -1; - } while (!bfinal); + } while (!final); return 0; } @@ -343,7 +330,7 @@ int inflate(void *dst, uint *dstlen, const void *src, uint srclen) { #include <stdlib.h> unsigned char *readall(char *name, uint *len) { - ulong size = 1 << 20; + ulong size = 1 << 22; uchar *buf; FILE *in; @@ -359,7 +346,7 @@ unsigned char *readall(char *name, uint *len) { int main(int argc, char **argv) { int ret; uchar *src; - uint srclen, dstlen=1<<16; + uint srclen, dstlen=1<<22; uchar *dst; if (argc < 2) @@ -368,10 +355,10 @@ int main(int argc, char **argv) { inflate_init(); ret = inflate(dst = malloc(dstlen), &dstlen, src, srclen); if (ret) - puts("inflate: error\n"); + fputs("inflate: error\n", stderr); else - printf("inflate: uncompressed %u bytes\n", dstlen); - puts((char *)dst); + fprintf(stderr, "inflate: uncompressed %u bytes\n", dstlen); + fwrite(dst, 1, dstlen, stdout); free(dst); free(src); return ret;