You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
75 lines
1.8 KiB
C
75 lines
1.8 KiB
C
/* 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;
|
|
}
|
|
|