flate

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

commit 31fab0436815a7314aee7f320c610ecf6897223f
parent 7b98214df9de69821c5e453e7da7ade99e8516e7
Author: nsz <nszabolcs@gmail.com>
Date:   Wed, 15 Jul 2009 07:26:44 +0200

deflate fix clencode bug
Diffstat:
deflate_simple.c | 116+++++++++++++++++++++++++++++++++++--------------------------------------------
1 file changed, 52 insertions(+), 64 deletions(-)

diff --git a/deflate_simple.c b/deflate_simple.c @@ -2,11 +2,11 @@ #include <string.h> #include <stdio.h> - /* TODO: hufflen: parent+heap only - match: check backwards + match: check backwards, lazy + block end: lcount, dcount */ typedef unsigned char uchar; @@ -18,7 +18,6 @@ enum { MaxMatch = 258, MaxChainStep = 64, HashSize = 2039, - HashChars = 3, /* TODO: unused */ WinSize = 1 << 15, SymSize = 1 << 16, @@ -87,6 +86,7 @@ static uchar clenorder[Nclen] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; + static uint revcode(uint c, int n) { int i; uint r = 0; @@ -256,7 +256,7 @@ static void putbits(State *s, uint bits, int n) { } static int clencodes(int *codes, int *extra, uchar *llen, int nlit, uchar *dlen, int ndist) { - int i, c, r, rb; + int i, c, r, rr; int n = 0; /* int exbits = 0;*/ @@ -267,14 +267,14 @@ static int clencodes(int *codes, int *extra, uchar *llen, int nlit, uchar *dlen, for (i = 0; i < nlit + ndist;) { /* run length encoding */ c = codes[i]; - for (r = 1; r < nlit + ndist && codes[i + r] == c; r++); + for (r = 1; i + r < nlit + ndist && codes[i + r] == c; r++); i += r; if (c == 0) { while (r >= 11) { - rb = r > 138 ? 138 : r; + rr = r > 138 ? 138 : r; codes[n] = 18; - extra[n++] = rb - 11; - r -= rb; + extra[n++] = rr - 11; + r -= rr; /* exbits += 7;*/ } if (r >= 3) { @@ -287,10 +287,10 @@ static int clencodes(int *codes, int *extra, uchar *llen, int nlit, uchar *dlen, while (r--) { codes[n++] = c; while (r >= 3) { - rb = r > 6 ? 6 : r; + rr = r > 6 ? 6 : r; codes[n] = 16; - extra[n++] = rb - 3; - r -= rb; + extra[n++] = rr - 3; + r -= rr; /* exbits += 2;*/ } } @@ -319,7 +319,6 @@ static void putblock(State *s, ushort *lcode, uchar *llen, ushort *dcode, uchar c = *p++; putbits(s, dcode[c & 0xff], dlen[c & 0xff]); putbits(s, c >> 16, (c >> 8) & 0xff); - } } /* EOB */ @@ -343,7 +342,6 @@ static void emitblock(State *s, int blocklen) { huffcodes(dcode, dlen, Ndist); for (nlit = Nlitlen; nlit > Nlit && llen[nlit-1] == 0; nlit--); for (ndist = Ndist; ndist > 1 && dlen[ndist-1] == 0; ndist--); - nc = clencodes(codes, extra, llen, nlit, dlen, ndist); memset(cfreq, 0, sizeof(cfreq)); for (i = 0; i < nc; i++) @@ -367,7 +365,6 @@ static void emitblock(State *s, int blocklen) { if (c == 18) dynsize += 7; } -fprintf(stderr, "tree len: %d bits: %d\n", nc, dynsize); for (p = s->lzbuf, plit = s->src; p != s->lzp;) { c = *p++; if (c >= LzRunlen) { @@ -394,7 +391,7 @@ fprintf(stderr, "tree len: %d bits: %d\n", nc, dynsize); putbits(s, s->lastblock, 1); if (dynsize < fixsize && dynsize < uncsize) { -fprintf(stderr, "dyn "); + /* dynamic code */ putbits(s, 2, 2); putbits(s, nlit - 257, 5); putbits(s, ndist - 1, 5); @@ -416,10 +413,11 @@ fprintf(stderr, "dyn "); /* block data + eob */ putblock(s, lcode, llen, dcode, dlen); } else if (fixsize < uncsize) { -fprintf(stderr, "fix "); + /* fixed code */ putbits(s, 1, 2); putblock(s, fixed_lcode, fixed_llen, fixed_dcode, fixed_dlen); } else { + /* uncompressed */ putbits(s, 0, 2); putbits(s, 0, 7); /* align to byte boundary */ s->nbits = 0; @@ -430,10 +428,8 @@ fprintf(stderr, "fix "); fprintf(stderr, "blocklen: %d lzlen: %d dynsize: %d fixsize: %d uncsize: %d\n", blocklen, s->lzp - s->lzbuf, dynsize, fixsize, uncsize); } + static void recordlit(State *s, ushort lit) { -/* -fprintf(stderr, "%3d %c\n", lit, lit); -*/ s->runlen++; s->lfreq[lit]++; } @@ -455,9 +451,7 @@ static int bisect(ushort *base, int len, int n) { static void recordmatch(State *s, Match m) { int i; -/* -fprintf(stderr, "m %d, %d\n", m.dist, m.len); -*/ + if (s->runlen) { *s->lzp++ = s->runlen | LzRunlen; s->runlen = 0; @@ -515,48 +509,7 @@ static void newblock(State *s, uchar *src) { s->lfreq[i] = 0; for (i = 0; i < Ndist; i++) s->dfreq[i] = 0; -} - -static void lzcompress(State *s, uchar *src, int len) { - int step; - int hash; - Match m; - - newblock(s, src); - while (len > 0) { - m = getmatch(s, src, len); - if (m.len >= MinMatch) { - recordmatch(s, m); - step = m.len; - } else { - recordlit(s, *src); - step = 1; - } - while (step > 0) { - if (len >= MinMatch) { - hash = gethash(src); - s->chain[s->pos] = s->head[hash]; - s->head[hash] = s->pos; - s->pos = (s->pos + 1) % WinSize; - } - src++; - len--; - step--; - } - if (src - s->src > 1 << 15) { - if (s->runlen) - *s->lzp++ = s->runlen | LzRunlen; - s->lfreq[256]++; /* EOB */ - emitblock(s, src - s->src); - newblock(s, src); - } - } - if (s->runlen) - *s->lzp++ = s->runlen | LzRunlen; s->lfreq[256]++; /* EOB */ - s->lastblock = 1; - emitblock(s, src - s->src); - putbits(s, 0, 7); } static void lzinit(State *s) { @@ -586,10 +539,45 @@ static void lzinit(State *s) { int deflate(uchar *src, int len, uchar *dst) { State s; + int step; + int hash; + Match m; lzinit(&s); + newblock(&s, src); s.dst = dst; - lzcompress(&s, src, len); + while (len > 0) { + m = getmatch(&s, src, len); + if (m.len >= MinMatch) { + recordmatch(&s, m); + step = m.len; + } else { + recordlit(&s, *src); + step = 1; + } + while (step > 0) { + if (len >= MinMatch) { + hash = gethash(src); + s.chain[s.pos] = s.head[hash]; + s.head[hash] = s.pos; + s.pos = (s.pos + 1) % WinSize; + } + src++; + len--; + step--; + } + if (src - s.src > 1 << 15) { + if (s.runlen) + *s.lzp++ = s.runlen | LzRunlen; + emitblock(&s, src - s.src); + newblock(&s, src); + } + } + if (s.runlen) + *s.lzp++ = s.runlen | LzRunlen; + s.lastblock = 1; + emitblock(&s, src - s.src); + putbits(&s, 0, 7); return s.dst - dst; }