diff options
Diffstat (limited to 'lzss.h')
-rw-r--r-- | lzss.h | 74 |
1 files changed, 74 insertions, 0 deletions
@@ -0,0 +1,74 @@ +/* LZSS encoder-decoder (Haruhiko Okumura; public domain) */ +/* Modified by Clyne Sullivan to focus on streamed decompression. */ + +#ifndef EOF +#define EOF (-1) +#endif + +#define EI 8 /* typically 10..13 */ +#define EJ 3 /* typically 4..5 */ +#define N (1 << EI) /* buffer size */ +#define F ((1 << EJ) + 1) /* lookahead buffer size */ + +static unsigned char buffer[N * 2]; +static const unsigned char *inbuffer; +static unsigned int insize, inidx; +static int buf, mask; + +/* Prepares decode() to decompress the given data. */ +void lzssinit(const unsigned char *inb, unsigned int ins) +{ + inbuffer = inb; + insize = ins; + inidx = 0; + buf = 0; + mask = 0; +} + +int getbit(int n) /* get n bits */ +{ + int i, x; + + x = 0; + for (i = 0; i < n; i++) { + if (mask == 0) { + if (inidx >= insize) + return EOF; + buf = inbuffer[inidx++]; + mask = 128; + } + x <<= 1; + if (buf & mask) x++; + mask >>= 1; + } + return x; +} + +/* handleoutput() receives each decompressed byte, return zero if want more. */ +int decode(int (*handleoutput)(int)) +{ + int i, j, k, r, c, ret; + + for (i = 0; i < N - F; i++) buffer[i] = ' '; + r = N - F; + while ((c = getbit(1)) != EOF) { + if (c) { + if ((c = getbit(8)) == EOF) break; + if ((ret = handleoutput(c))) + return ret; + buffer[r++] =(unsigned char) c; r &= (N - 1); + } else { + if ((i = getbit(EI)) == EOF) break; + if ((j = getbit(EJ)) == EOF) break; + for (k = 0; k <= j + 1; k++) { + c = buffer[(i + k) & (N - 1)]; + if ((ret = handleoutput(c))) + return ret; + buffer[r++] = (unsigned char)c; r &= (N - 1); + } + } + } + + return EOF; +} + |