commit 162823bea29ac79fd3fb107de28c4032fc9db7f5
parent 9de8fb994bd9a86f1f0948249d5fe49d6a9ea97d
Author: nsz@tpx <unknown>
Date: Sun, 9 Aug 2009 10:29:26 +0200
winsize = 2*maxdist + maxmatch
Diffstat:
deflate.c | | | 136 | +++++++++++++++++++++++++++++++++++++------------------------------------------ |
1 file changed, 63 insertions(+), 73 deletions(-)
diff --git a/deflate.c b/deflate.c
@@ -29,17 +29,17 @@ spec case tests:
*/
enum {
- WinSize = 1 << 15,
- DstSize = 2*WinSize + 8,
- RbufSize = 1 << 13,
- RunlenFlag = 1 << 15,
- MinMatch = 3,
- MaxMatch = 258,
- BigDist = 1 << 12,
- MaxDist = WinSize - MaxMatch,
+ MinMatch = 3,
+ MaxMatch = 258,
MaxChainLen = 256,
- HashBits = 13,
- HashSize = 1 << HashBits,
+ HashBits = 13,
+ HashSize = 1 << HashBits,
+ BigDist = 1 << 12,
+ MaxDist = 1 << 15,
+ WinSize = 2*MaxDist + MaxMatch,
+ DstSize = 2*WinSize + 8,
+ RbufSize = 1 << 13,
+ RunlenFlag = 1 << 15,
CodeBits = 16, /* max number of bits in a code + 1 */
EOB = 256, /* end of block symbol */
@@ -73,14 +73,14 @@ typedef struct {
uchar *dstbegin;
uint bits;
int nbits;
- int lfreq[Nlitlen];
- int dfreq[Ndist];
+ uchar win[WinSize];
ushort head[HashSize]; /* position of hash chain heads */
- ushort chain[WinSize]; /* hash chains next */
- uchar win[2*WinSize];
+ ushort chain[MaxDist]; /* hash chains next */
Runlen rbuf[RbufSize]; /* literal run length, match len, match dist */
Runlen *rend; /* current pos in rbuf */
int run; /* literal count */
+ int lfreq[Nlitlen];
+ int dfreq[Ndist];
uchar dstbuf[DstSize];
} State;
@@ -335,16 +335,17 @@ static void putblock(State *s, ushort *lcode, uchar *llen, ushort *dcode, uchar
putbits(s, lcode[EOB], llen[EOB]);
}
-static void deflate_block(State *s, int blocklen) {
+static void deflate_block(State *s) {
int cfreq[Nclen];
uchar codes[Nlitlen + Ndist], extra[Nlitlen + Ndist];
uchar llen[Nlitlen], dlen[Ndist], clen[Nclen];
ushort lcode[Nlitlen], dcode[Ndist], ccode[Nclen];
int i, c, n, ncodes;
int nlit, ndist, nclen;
- int dynsize, fixsize, uncsize;
Runlen *r;
uchar *pc;
+ int dynsize, fixsize, uncsize;
+ int blocklen = s->pos - s->startpos;
int dyntree;
/* calc dynamic codes */
@@ -465,7 +466,6 @@ static void recordmatch(State *s, Match m) {
int n;
flushlit(s);
-/*fprintf(stderr, "len:%u dist:%u\n", m.len, m.dist);*/
n = bisect(lenbase, Nlen, m.len);
s->rend->n = n;
s->rend->bits = m.len - lenbase[n];
@@ -479,7 +479,6 @@ static void recordmatch(State *s, Match m) {
}
static void recordlit(State *s, int c) {
-/*fprintf(stderr, "lit:%c\n", c);*/
s->run++;
s->lfreq[c]++;
}
@@ -497,7 +496,7 @@ static ushort addtochain(State *s, ushort pos) {
h = gethash(s->win + pos);
i = s->head[h];
s->head[h] = pos;
- s->chain[pos % WinSize] = i;
+ s->chain[pos % MaxDist] = i;
return i;
}
@@ -532,7 +531,7 @@ static Match getmatch(State *s, ushort pos, ushort mpos) {
}
m.len = len;
}
- } while ((mpos = s->chain[mpos % WinSize]) > limit && --chainlen);
+ } while ((mpos = s->chain[mpos % MaxDist]) > limit && --chainlen);
if (m.len < MinMatch || (m.len == MinMatch && m.dist > BigDist))
m.len = 0;
return m;
@@ -549,27 +548,31 @@ static void newblock(State *s) {
}
static int fillwin(State *s) {
- int n, k;
+ int n;
+ int need, have;
- if (s->pos > WinSize + MaxDist) {
+ if (s->pos >= 2*MaxDist) {
/* shift win */
- memcpy(s->win, s->win + WinSize, WinSize);
+ memcpy(s->win, s->win + MaxDist, MaxDist + MaxMatch);
for (n = HashSize; n--;)
- s->head[n] = s->head[n] > WinSize ? s->head[n] - WinSize : 0;
- for (n = WinSize; n--;)
- s->chain[n] = s->chain[n] > WinSize ? s->chain[n] - WinSize : 0;
- s->startpos -= WinSize;
- s->pos -= WinSize;
+ s->head[n] = s->head[n] > MaxDist ? s->head[n] - MaxDist : 0;
+ for (n = MaxDist; n--;)
+ s->chain[n] = s->chain[n] > MaxDist ? s->chain[n] - MaxDist : 0;
+ s->startpos -= MaxDist;
+ s->pos -= MaxDist;
+ }
+ if (s->avail < MaxMatch) {
+ /* fill win */
+ need = WinSize - s->pos - s->avail;
+ have = s->srcend - s->src;
+ if (have > need)
+ have = need;
+ if (have == 0)
+ return FlateIn;
+ memcpy(s->win + s->pos + s->avail, s->src, have);
+ s->src += have;
+ s->avail += have;
}
- k = 2*WinSize - s->pos - s->avail;
- n = s->srcend - s->src;
- if (n > k)
- n = k;
- if (n == 0)
- return FlateIn;
- memcpy(s->win + s->pos + s->avail, s->src, n);
- s->src += n;
- s->avail += n;
return FlateOk;
}
@@ -577,9 +580,7 @@ static int deflate_state(State *s) {
Match m;
int head;
- /* messy.. */
- switch (s->state) {
- case FlateOut:
+ if (s->state == FlateOut) {
if (s->dstbegin < s->dst)
return FlateOut;
if (s->lastblock)
@@ -587,15 +588,12 @@ static int deflate_state(State *s) {
newblock(s);
if (s->prevm.len)
s->pos++;
- if (fillwin(s)) {
- s->state = FlateIn;
+ if (fillwin(s))
return FlateIn;
- }
- break;
- case FlateIn:
+ } else if (s->state == FlateIn)
fillwin(s);
- break;
- }
+ else
+ return s->state;
for (;;) {
head = addtochain(s, s->pos);
if (head >= s->pos || s->pos - head >= MaxDist)
@@ -619,30 +617,23 @@ static int deflate_state(State *s) {
recordlit(s, s->win[s->pos]);
s->pos++;
s->avail--;
-
- if (s->avail < MaxMatch || s->rend - s->rbuf >= RbufSize - 2) {
- if (s->avail == 0) {
- flushlit(s);
- s->lastblock = 1;
- s->state = FlateOut;
- deflate_block(s, s->pos - s->startpos);
- putbits(s, 0, 7);
- return FlateOut;
- }
- if (s->pos - s->startpos > MaxDist || s->rend - s->rbuf >= RbufSize - 2) {
- flushlit(s);
- if (s->prevm.len)
- s->pos--;
-fprintf(stderr, "avail %d pos %d srcavail %d\n", s->avail, s->pos, s->srcend - s->src);
- deflate_block(s, s->pos - s->startpos);
- s->state = FlateOut;
- return FlateOut;
- }
- if (fillwin(s)) {
- s->state = FlateIn;
- return FlateIn;
- }
+ if (s->avail == 0) {
+ s->lastblock = 1;
+ flushlit(s);
+ deflate_block(s);
+ putbits(s, 0, 7);
+ return FlateOut;
}
+ if (s->pos - s->startpos >= MaxDist || s->rend - s->rbuf >= RbufSize - 2) {
+fprintf(stderr, "start %d pos %d avail %d srcavail %d rlen %d\n", s->startpos, s->pos, s->avail, s->srcend - s->src, s->rend - s->rbuf);
+ flushlit(s);
+ if (s->prevm.len)
+ s->pos--;
+ deflate_block(s);
+ return FlateOut;
+ }
+ if (fillwin(s))
+ return FlateIn;
}
}
@@ -667,9 +658,8 @@ static State *alloc_state(void) {
fixdlen[i] = 5;
huffcodes(fixlcode, fixllen, Nlitlen);
huffcodes(fixdcode, fixdlen, Ndist);
-
s->dst = s->dstbegin = s->dstbuf;
- s->pos = s->startpos = WinSize;
+ s->pos = s->startpos = MaxDist;
s->avail = 0;
return s;
}
@@ -694,7 +684,7 @@ int deflate(FlateStream *stream) {
s->srcend = s->src + stream->nin;
stream->nin = 0;
}
- n = deflate_state(s);
+ n = s->state = deflate_state(s);
if (n == FlateOut) {
k = s->dst - s->dstbegin;
if (k < stream->nout)