aboutsummaryrefslogtreecommitdiffstats
path: root/lzss.h
diff options
context:
space:
mode:
Diffstat (limited to 'lzss.h')
-rw-r--r--lzss.h74
1 files changed, 74 insertions, 0 deletions
diff --git a/lzss.h b/lzss.h
new file mode 100644
index 0000000..5753ba9
--- /dev/null
+++ b/lzss.h
@@ -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;
+}
+