aboutsummaryrefslogtreecommitdiffstats
path: root/lzss.h
blob: 5753ba9cf5644a830e55dadfb5d3aff2522b7f01 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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;
}