flate

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

commit 28997f8a140bb3ee75efd89425898f94e3968492
parent bb4c48aacfd66adfdcf9996a01d4c483c34b2eed
Author: nsz@tpx <unknown>
Date:   Thu,  6 Aug 2009 20:30:38 +0200

shorter return value enum, flate.h
Diffstat:
deflate.c | 34+++++++++++++++++-----------------
deflate.h | 31+------------------------------
deflate_example.c | 13+++++++------
inflate.c | 105++++++++++++++++++++++++++++++++++++++-----------------------------------------
inflate.h | 31+------------------------------
inflate_example.c | 13+++++++------
6 files changed, 84 insertions(+), 143 deletions(-)

diff --git a/deflate.c b/deflate.c @@ -1,6 +1,7 @@ #include <stdlib.h> #include <string.h> #include <stdio.h> +#include "flate.h" #include "deflate.h" /* @@ -571,14 +572,13 @@ static int fillwin(State *s) { if (n > k) n = k; if (n == 0) - return FlateNeedInput; + return FlateIn; memcpy(s->win + s->pos + s->avail, s->src, n); s->src += n; s->avail += n; return FlateOk; } -/* TODO: pos overflow */ static int deflate_state(State *s) { Match m; Match prevm = {0, 0}; @@ -592,10 +592,10 @@ static int deflate_state(State *s) { if (s->avail == 0) { flushlit(s); s->lastblock = 1; - s->state = FlateHasOutput; + s->state = FlateOut; deflate_block(s, pos - s->blockstart); putbits(s, 0, 7); - return FlateHasOutput; + return FlateOut; } if (pos - s->blockstart > MaxDist || s->rend - s->rbuf >= RbufSize - 2) { flushlit(s); @@ -608,11 +608,11 @@ fprintf(stderr, "avail %d pos %d lastpos %d srcavail %d\n", s->avail, pos, s->po deflate_block(s, pos - s->blockstart); s->pos = pos; s->prevm = prevm; - s->state = FlateHasOutput; - return FlateHasOutput; - case FlateHasOutput: + s->state = FlateOut; + return FlateOut; + case FlateOut: if (s->dstbegin < s->dst) - return FlateHasOutput; + return FlateOut; if (s->lastblock) return FlateOk; newblock(s); @@ -622,9 +622,9 @@ fprintf(stderr, "avail %d pos %d lastpos %d srcavail %d\n", s->avail, pos, s->po s->pos = pos; if (fillwin(s)) { s->prevm = prevm; - s->state = FlateNeedInput; - return FlateNeedInput; - case FlateNeedInput: + s->state = FlateIn; + return FlateIn; + case FlateIn: fillwin(s); prevm = s->prevm; } @@ -654,7 +654,7 @@ fprintf(stderr, "avail %d pos %d srcavail %d\n", s->avail, s->pos, s->srcend - s s->avail--; } /* for(;;) */ } /* switch */ - return FlateError; + return FlateErr; } static State *alloc_state(void) { @@ -692,13 +692,13 @@ int deflate(FlateStream *stream) { if (stream->err) { free(s); stream->state = 0; - return FlateError; + return FlateErr; } if (!s) { s = stream->state = alloc_state(); if (!s) - return stream->err = "no mem.", FlateError; - s->state = FlateHasOutput; + return stream->err = "no mem.", FlateErr; + s->state = FlateOut; } if (stream->nin) { s->src = stream->in; @@ -706,14 +706,14 @@ int deflate(FlateStream *stream) { stream->nin = 0; } n = deflate_state(s); - if (n == FlateHasOutput) { + if (n == FlateOut) { k = s->dst - s->dstbegin; if (k < stream->nout) stream->nout = k; memcpy(stream->out, s->dstbegin, stream->nout); s->dstbegin += stream->nout; } - if (n == FlateOk || n == FlateError) { + if (n == FlateOk || n == FlateErr) { free(s); stream->state = 0; } diff --git a/deflate.h b/deflate.h @@ -1,32 +1,3 @@ -typedef unsigned char uchar; -typedef unsigned short ushort; -typedef unsigned int uint; - -/* TODO: - flatein flateout flateerr - inflate_reset, inflate_free? - */ - -/* return values */ -enum { - FlateOk = 0, - FlateError = -1, - FlateNeedInput = -2, - FlateHasOutput = -3 -}; - -typedef struct { - uchar *in; - int nin; - uchar *out; - int nout; - char *err; - void *state; -} FlateStream; - -/* state and err should be initialized to 0, to free internal state call s->err = ""; inflate(s) */ -/* decode from in to out, return if input is needed or output is available */ +/* TODO: deflete_reset deflate_free */ int deflate(FlateStream *s); - -/* callback interface: r(buf, n, rdata) reads at most n bytes into buf */ int deflate_callback(int (*r)(void *, int, void *), void *rdata, int (*w)(void *, int, void *), void *wdata); diff --git a/deflate_example.c b/deflate_example.c @@ -1,5 +1,6 @@ #include <stdlib.h> #include <stdio.h> +#include "flate.h" #include "deflate.h" int compress_stream(FILE *in, FILE *out) { @@ -14,19 +15,19 @@ int compress_stream(FILE *in, FILE *out) { s.state = 0; nin = nout = 0; - for (n = FlateNeedInput; ; n = deflate(&s)) + for (n = FlateIn; ; n = deflate(&s)) switch (n) { case FlateOk: - case FlateError: + case FlateErr: fprintf(stderr, "in: %d out: %d err: %s\n", nin, nout, s.err); free(s.in); free(s.out); return n; - case FlateNeedInput: + case FlateIn: s.nin = fread(s.in, 1, Nin, in); nin += s.nin; break; - case FlateHasOutput: + case FlateOut: if (s.nout != fwrite(s.out, 1, s.nout, out)) s.err = "write error."; nout += s.nout; @@ -46,14 +47,14 @@ int compress_mem(void *src, int srclen, void *dst, int dstlen) { s.err = 0; s.state = 0; - while ((n = deflate(&s)) == FlateHasOutput) { + while ((n = deflate(&s)) == FlateOut) { dstlen -= s.nout; s.out += s.nout; s.nout = dstlen; if (dstlen < 0) s.err = "not enough output space."; } - if (n == FlateNeedInput) { + if (n == FlateIn) { s.err = "input is not terminated."; n = deflate(&s); } diff --git a/inflate.c b/inflate.c @@ -1,5 +1,6 @@ #include <stdlib.h> #include <string.h> +#include "flate.h" #include "inflate.h" enum { @@ -263,7 +264,7 @@ static uint decode_symbol_long(State *s, Huff *huff, uint bits, uint nbits, int for (;;) { if (!nbits--) { if (s->src == s->srcend) - return FlateNeedInput; + return FlateIn; bits = *s->src++; nbits = 7; } @@ -276,7 +277,7 @@ static uint decode_symbol_long(State *s, Huff *huff, uint bits, uint nbits, int cur <<= 1; count++; if (count == huff->count + CodeBits) - return s->err = "symbol decoding failed.", FlateError; + return s->err = "symbol decoding failed.", FlateErr; } s->bits = bits; s->nbits = nbits; @@ -315,7 +316,7 @@ static uint decode_symbol(State *s, Huff *huff) { } s->bits = bits; s->nbits = nbits; - return FlateNeedInput; + return FlateIn; } bits |= *s->src++ << nbits; nbits += 8; @@ -328,7 +329,7 @@ static uint decode_symbol(State *s, Huff *huff) { s->nbits = nbits - entry.len; return entry.sym; } else if (entry.len == 0) - return s->err = "symbol decoding failed.", FlateError; + return s->err = "symbol decoding failed.", FlateErr; return decode_symbol_long(s, huff, bits, nbits, entry.sym); } @@ -349,42 +350,42 @@ static int decode_block(State *s, Huff *lhuff, Huff *dhuff) { if (pos == WinSize) { s->pos = WinSize; s->state = DecodeBlock; - return FlateHasOutput; + return FlateOut; } } else if (sym > 256) { sym -= 257; if (sym >= Nlen) { s->pos = pos; s->state = DecodeBlock; - if (sym + 257 == (uint)FlateNeedInput) - return FlateNeedInput; - return FlateError; + if (sym + 257 == (uint)FlateIn) + return FlateIn; + return FlateErr; } case DecodeBlockLenBits: if (!fillbits_fast(&s->src, s->srcend, &s->bits, &s->nbits, lenbits[sym])) { s->nclen = sym; /* using nclen to store sym */ s->pos = pos; s->state = DecodeBlockLenBits; - return FlateNeedInput; + return FlateIn; } len = lenbase[sym] + getbits_fast(&s->bits, &s->nbits, lenbits[sym]); case DecodeBlockDist: sym = decode_symbol(s, dhuff); - if (sym == (uint)FlateNeedInput) { + if (sym == (uint)FlateIn) { s->pos = pos; s->lenpos = len; s->state = DecodeBlockDist; - return FlateNeedInput; + return FlateIn; } if (sym >= Ndist) - return FlateError; + return FlateErr; case DecodeBlockDistBits: if (!fillbits_fast(&s->src, s->srcend, &s->bits, &s->nbits, distbits[sym])) { s->nclen = sym; /* using nclen to store sym */ s->pos = pos; s->lenpos = len; s->state = DecodeBlockDistBits; - return FlateNeedInput; + return FlateIn; } dist = distbase[sym] + getbits_fast(&s->bits, &s->nbits, distbits[sym]); /* copy match, loop unroll in common case */ @@ -417,7 +418,7 @@ static int decode_block(State *s, Huff *lhuff, Huff *dhuff) { s->lenpos = len; s->nclen = dist; /* using nclen to store dist */ s->state = DecodeBlockCopy; - return FlateHasOutput; + return FlateOut; } } } @@ -427,7 +428,7 @@ static int decode_block(State *s, Huff *lhuff, Huff *dhuff) { } } /* for (;;) */ } /* switch () */ - return s->err = "corrupted state.", FlateError; + return s->err = "corrupted state.", FlateErr; } /* inflate state machine (decodes s->src into s->win) */ @@ -435,18 +436,18 @@ static int inflate_state(State *s) { int n; if (s->posout) - return FlateHasOutput; + return FlateOut; for (;;) { switch (s->state) { case BlockHead: if (s->final) { if (s->pos) - return FlateHasOutput; + return FlateOut; else return FlateOk; } if (!fillbits(s, 3)) - return FlateNeedInput; + return FlateIn; s->final = getbits(s, 1); n = getbits(s, 2); if (n == 0) @@ -456,29 +457,29 @@ static int inflate_state(State *s) { else if (n == 2) s->state = DynamicHuff; else - return s->err = "corrupt block header.", FlateError; + return s->err = "corrupt block header.", FlateErr; break; case UncompressedBlock: /* start block on a byte boundary */ s->bits >>= s->nbits & 7; s->nbits &= ~7; if (!fillbits(s, 32)) - return FlateNeedInput; + return FlateIn; s->lenpos = getbits(s, 16); n = getbits(s, 16); if (s->lenpos != (~n & 0xffff)) - return s->err = "corrupt uncompressed length.", FlateError; + return s->err = "corrupt uncompressed length.", FlateErr; s->state = CopyUncompressed; case CopyUncompressed: /* TODO: untested, slow, memcpy etc */ /* s->nbits should be 0 here */ while (s->lenpos) { if (s->src == s->srcend) - return FlateNeedInput; + return FlateIn; s->lenpos--; s->win[s->pos++] = *s->src++; if (s->pos == WinSize) - return FlateHasOutput; + return FlateOut; } s->state = BlockHead; break; @@ -489,12 +490,12 @@ static int inflate_state(State *s) { case DynamicHuff: /* decode dynamic huffman code trees */ if (!fillbits(s, 14)) - return FlateNeedInput; + return FlateIn; s->nlit = 257 + getbits(s, 5); s->ndist = 1 + getbits(s, 5); s->nclen = 4 + getbits(s, 4); if (s->nlit > Nlitlen || s->ndist > Ndist) - return s->err = "corrupt code tree.", FlateError; + return s->err = "corrupt code tree.", FlateErr; /* build code length tree */ for (n = 0; n < Nclen; n++) s->lens[n] = 0; @@ -507,11 +508,11 @@ static int inflate_state(State *s) { s->lens[clenorder[n]] = getbits(s, 3); } else { s->lenpos = n; - return FlateNeedInput; + return FlateIn; } /* using lhuff for code length huff code */ if (build_huff(&s->lhuff, s->lens, Nclen, ClenTableBits) < 0) - return s->err = "building clen tree failed.", FlateError; + return s->err = "building clen tree failed.", FlateErr; s->state = DynamicHuffLitlenDist; s->lenpos = 0; case DynamicHuffLitlenDist: @@ -524,9 +525,9 @@ static int inflate_state(State *s) { if (sym < 16) { s->lens[n++] = sym; continue; - } else if (sym == (uint)FlateNeedInput) { + } else if (sym == (uint)FlateIn) { s->lenpos = n; - return FlateNeedInput; + return FlateIn; case DynamicHuffContinue: n = s->lenpos; sym = s->nclen; @@ -534,12 +535,12 @@ static int inflate_state(State *s) { } if (!fillbits(s, 7)) { /* TODO: 7 is too much when an almost empty block is at the end */ - if (sym == (uint)FlateError) - return FlateError; + if (sym == (uint)FlateErr) + return FlateErr; s->nclen = sym; s->lenpos = n; s->state = DynamicHuffContinue; - return FlateNeedInput; + return FlateIn; } /* TODO: bound check s->lens */ if (sym == 16) { @@ -556,13 +557,13 @@ static int inflate_state(State *s) { for (len = 11 + getbits(s, 7); len; len--) s->lens[n++] = 0; } else - return s->err = "corrupt code tree.", FlateError; + return s->err = "corrupt code tree.", FlateErr; } /* build dynamic huffman code trees */ if (build_huff(&s->lhuff, s->lens, s->nlit, LitlenTableBits) < 0) - return s->err = "building litlen tree failed.", FlateError; + return s->err = "building litlen tree failed.", FlateErr; if (build_huff(&s->dhuff, s->lens + s->nlit, s->ndist, DistTableBits) < 0) - return s->err = "building dist tree failed.", FlateError; + return s->err = "building dist tree failed.", FlateErr; s->state = DecodeBlock; case DecodeBlock: case DecodeBlockLenBits: @@ -570,16 +571,12 @@ static int inflate_state(State *s) { case DecodeBlockDistBits: case DecodeBlockCopy: n = decode_block(s, s->fixed ? &lhuff : &s->lhuff, s->fixed ? &dhuff : &s->dhuff); - if (n == FlateNeedInput) - return FlateNeedInput; - if (n == FlateHasOutput) - return FlateHasOutput; - if (n == FlateError) - return FlateError; + if (n != FlateOk) + return n; s->state = BlockHead; break; default: - return s->err = "corrupt state.", FlateError; + return s->err = "corrupt state.", FlateErr; } } } @@ -611,12 +608,12 @@ int inflate(FlateStream *stream) { free(s); stream->state = 0; } - return FlateError; + return FlateErr; } if (!s) { s = stream->state = alloc_state(); if (!s) - return stream->err = "no mem.", FlateError; + return stream->err = "no mem.", FlateErr; } if (stream->nin) { s->src = stream->in; @@ -624,7 +621,7 @@ int inflate(FlateStream *stream) { stream->nin = 0; } n = inflate_state(s); - if (n == FlateHasOutput) { + if (n == FlateOut) { if (s->pos < stream->nout) stream->nout = s->pos; memcpy(stream->out, s->win + s->posout, stream->nout); @@ -634,7 +631,7 @@ int inflate(FlateStream *stream) { else s->posout = 0; } - if (n == FlateOk || n == FlateError) { + if (n == FlateOk || n == FlateErr) { stream->err = s->err; free(s); stream->state = 0; @@ -650,33 +647,33 @@ int inflate_callback(int (*r)(void *, int, void *), void *rdata, int (*w)(void * s = alloc_state(); if (!s) - return FlateError; + return FlateErr; s->src = s->srcend = src = malloc(SrcSize); if (!src) { free(s); - return FlateError; + return FlateErr; } - n = FlateNeedInput; + n = FlateIn; for (;;) switch (n) { - case FlateNeedInput: + case FlateIn: len = r(src, SrcSize, rdata); if (len > 0) { s->srcend = src + len; n = inflate_state(s); } else - n = FlateError; + n = FlateErr; break; - case FlateHasOutput: + case FlateOut: len = w(s->win, s->pos, wdata); if (len == s->pos) { s->pos = 0; n = inflate_state(s); } else - n = FlateError; + n = FlateErr; break; case FlateOk: - case FlateError: + case FlateErr: free(src); free(s); return n; diff --git a/inflate.h b/inflate.h @@ -1,32 +1,3 @@ -typedef unsigned char uchar; -typedef unsigned short ushort; -typedef unsigned int uint; - -/* TODO: - flatein flateout flateerr - inflate_reset, inflate_free? - */ - -/* return values */ -enum { - FlateOk = 0, - FlateError = -1, - FlateNeedInput = -2, - FlateHasOutput = -3 -}; - -typedef struct { - uchar *in; - int nin; - uchar *out; - int nout; - char *err; - void *state; -} FlateStream; - -/* state and err should be initialized to 0, to free internal state call s->err = ""; inflate(s) */ -/* decode from in to out, return if input is needed or output is available */ +/* TODO: inflate_reset, inflate_free */ int inflate(FlateStream *s); - -/* callback interface: r(buf, n, rdata) reads at most n bytes into buf */ int inflate_callback(int (*r)(void *, int, void *), void *rdata, int (*w)(void *, int, void *), void *wdata); diff --git a/inflate_example.c b/inflate_example.c @@ -1,5 +1,6 @@ #include <stdlib.h> #include <stdio.h> +#include "flate.h" #include "inflate.h" int decompress_stream(FILE *in, FILE *out) { @@ -14,21 +15,21 @@ int decompress_stream(FILE *in, FILE *out) { s.state = 0; nin = nout = 0; - for (n = FlateNeedInput; ; n = inflate(&s)) + for (n = FlateIn; ; n = inflate(&s)) switch (n) { case FlateOk: - case FlateError: + case FlateErr: fprintf(stderr, "in: %d out: %d err: %s\n", nin, nout, s.err); free(s.in); free(s.out); return n; - case FlateNeedInput: + case FlateIn: s.nin = fread(s.in, 1, Nin, in); if (s.nin == 0) s.err = "read error."; nin += s.nin; break; - case FlateHasOutput: + case FlateOut: if (s.nout != fwrite(s.out, 1, s.nout, out)) s.err = "write error."; nout += s.nout; @@ -48,14 +49,14 @@ int decompress_mem(void *src, int srclen, void *dst, int dstlen) { s.err = 0; s.state = 0; - while ((n = inflate(&s)) == FlateHasOutput) { + while ((n = inflate(&s)) == FlateOut) { dstlen -= s.nout; s.out += s.nout; s.nout = dstlen; if (dstlen < 0) s.err = "not enough output space."; } - if (n == FlateNeedInput) { + if (n == FlateIn) { s.err = "input is not terminated."; n = inflate(&s); }