From d40ae99422e118188a7f48055dc340c6aca022aa Mon Sep 17 00:00:00 2001 From: Kitty Draper Date: Sat, 5 Mar 2011 21:39:25 -0500 Subject: first commit --- source/unzip/unshrink.c | 177 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 source/unzip/unshrink.c (limited to 'source/unzip/unshrink.c') diff --git a/source/unzip/unshrink.c b/source/unzip/unshrink.c new file mode 100644 index 0000000..6deb4d4 --- /dev/null +++ b/source/unzip/unshrink.c @@ -0,0 +1,177 @@ +/*--------------------------------------------------------------------------- + + unshrink.c + + Shrinking is a Dynamic Lempel-Ziv-Welch compression algorithm with partial + clearing. + + ---------------------------------------------------------------------------*/ + + +#include "unz.h" +void flush_stack (int); + +/*************************************/ +/* UnShrink Defines, Globals, etc. */ +/*************************************/ + +/* MAX_BITS 13 (in unzip.h; defines size of global work area) */ +#define INIT_BITS 9 +#define FIRST_ENT 257 +#define CLEAR 256 +#define GetCode(dest) READBIT(codesize,dest) + +static void partial_clear (); + +int codesize, maxcode, maxcodemax, free_ent; + + + + +/*************************/ +/* Function unShrink() */ +/*************************/ + +void unShrink() +{ + register int code; + register int stackp; + int finchar; + int oldcode; + int incode; + + + /* decompress the file */ + codesize = INIT_BITS; + maxcode = (1 << codesize) - 1; + maxcodemax = HSIZE; /* (1 << MAX_BITS) */ + free_ent = FIRST_ENT; + + code = maxcodemax; + do { + prefix_of[code] = -1; + } while (--code > 255); +/* + OvdL: -Ox with SCO's 3.2.0 cc gives + a. warning: overflow in constant multiplication + b. segmentation fault (core dumped) when using the executable + for (code = maxcodemax; code > 255; code--) + prefix_of[code] = -1; + */ + + for (code = 255; code >= 0; code--) { + prefix_of[code] = 0; + suffix_of[code] = (byte) code; + } + + GetCode(oldcode); + if (zipeof) + return; + finchar = oldcode; + + stack[0] = finchar; + flush_stack (1); + + stackp = HSIZE; + + while (!zipeof) { + GetCode(code); + if (zipeof) + return; + + while (code == CLEAR) { + GetCode(code); + switch (code) { + case 1: + codesize++; + if (codesize == MAX_BITS) + maxcode = maxcodemax; + else + maxcode = (1 << codesize) - 1; + break; + + case 2: + partial_clear(); + break; + } + + GetCode(code); + if (zipeof) + return; + } + + + /* special case for KwKwK string */ + incode = code; + if (prefix_of[code] == -1) { + stack[--stackp] = (byte) finchar; + code = oldcode; + } + /* generate output characters in reverse order */ + while (code >= FIRST_ENT) { + if (prefix_of[code] == -1) { + stack[--stackp] = (byte) finchar; + code = oldcode; + } else { + stack[--stackp] = suffix_of[code]; + code = prefix_of[code]; + } + } + + finchar = suffix_of[code]; + stack[--stackp] = (byte) finchar; + + /* and put them out in forward order, block copy */ + flush_stack (HSIZE - stackp); + stackp = HSIZE; + + /* generate new entry */ + code = free_ent; + if (code < maxcodemax) { + prefix_of[code] = oldcode; + suffix_of[code] = (byte) finchar; + + do + code++; + while ((code < maxcodemax) && (prefix_of[code] != -1)); + + free_ent = code; + } + /* remember previous code */ + oldcode = incode; + } +} + + + +/******************************/ +/* Function partial_clear() */ +/******************************/ + +static void partial_clear() +{ + register int pr; + register int cd; + + /* mark all nodes as potentially unused */ + for (cd = FIRST_ENT; cd < free_ent; cd++) + prefix_of[cd] |= 0x8000; + + /* unmark those that are used by other nodes */ + for (cd = FIRST_ENT; cd < free_ent; cd++) { + pr = prefix_of[cd] & 0x7fff; /* reference to another node? */ + if (pr >= FIRST_ENT) /* flag node as referenced */ + prefix_of[pr] &= 0x7fff; + } + + /* clear the ones that are still marked */ + for (cd = FIRST_ENT; cd < free_ent; cd++) + if ((prefix_of[cd] & 0x8000) != 0) + prefix_of[cd] = -1; + + /* find first cleared node as next free_ent */ + cd = FIRST_ENT; + while ((cd < maxcodemax) && (prefix_of[cd] != -1)) + cd++; + free_ent = cd; +} -- cgit v1.2.3