lzw is not as complicated as everyone thinks

88 views
Skip to first unread message

dowu...@gmail.com

unread,
Aug 4, 2020, 10:24:47 PM8/4/20
to
/* unix uncompress */

#include <err.h>
#include <stdio.h>
#include <stdlib.h>

unsigned char *Character; /* character dictionary */
int charactersz;

void growcharacter(int n)
{
for(charactersz = 100000; charactersz <= n; charactersz = charactersz / 5 * 8);
if(Character = realloc(Character, charactersz * sizeof(*Character)), Character == 0) err(1, "character dictionary resize error");
}

int *String; /* string dictionary */
int stringsz;

void growstring(int n)
{
for(stringsz = 10000; stringsz <= n; stringsz = stringsz / 5 * 8);
if(String = realloc(String, stringsz * sizeof(*String)), String == 0) err(1, "string dictionary resize error");
}

int Buffer; /* bit stream */
int buffersz;

int readbits(int n)
{
while(buffersz < n) {
int a = getc(stdin); if(a == EOF) return EOF;
Buffer += a << buffersz;
buffersz += 8;
}
int b = Buffer;
Buffer >>= n;
buffersz -= n;
return b & ((1 << n) - 1);
}

int main(void)
{
if(!(getc(stdin) == 0x1f && getc(stdin) == 0x9d)) errx(1, "not a compressed file");

int maxbits = getc(stdin) & 0x1f;
if(!(maxbits >= 9 && maxbits <= 16)) errx(1, "dictionary bits error");

int characterp = 0; /* current position in character dictionary */
int stringp = 256; /* current position in string dictionary */
int bits = 9; /* current size of code in bits */

int code;
while(code = readbits(bits), code != EOF) {

if(!(code >= 0 && code <= stringp)) errx(1, "code bounds error -- invalid compressed data");

if(stringp >= stringsz) growstring(stringp);
String[stringp++] = characterp;

if(code < 256) { /* character */
if(characterp >= charactersz) growcharacter(characterp);
Character[characterp++] = code;

} else if(code > 256) { /* string */
int a = String[code - 1];
int b = String[code - 0];
while(a <= b) {
if(characterp >= charactersz) growcharacter(characterp);
Character[characterp++] = Character[a++];
}

} else { /* flush entire dictionary */
while(stringp % 8 != 0) { readbits(bits); stringp++; } /* what? */

if(fwrite(Character, characterp, 1, stdout) != 1) err(1, "write error");
characterp = 0; stringp = 256; bits = 9; /* initial state */
}

if(stringp == (1 << bits) && bits < maxbits) bits++; /* increase code size */
}
if(fwrite(Character, characterp, 1, stdout) != 1) err(1, "write error");
if(fflush(stdout) != 0) err(1, "flush error");

return 0;
}
Reply all
Reply to author
Forward
0 new messages