ftp.nice.ch/pub/next/tools/archiver/Opener.3.4b.Utils.s.tar.gz#/Opener.3.4a.Utils.s/macutils/macunpack/de_compress.c

This is de_compress.c in view mode; [Download] [Up]

#include "macunpack.h"
#ifdef SIT
#define DECOMPRESS
#endif /* SIT */
#ifdef LZC
#define DECOMPRESS
#endif /* LZC */
#ifdef DECOMPRESS
#include "globals.h"
#include "../fileio/wrfile.h"

/* Written to allow for bits to be upto 16, MacCompress can use 16 bits */

#define	BITS	16
#define HSIZE	69001		/* 95% occupancy */

#define INIT_BITS 9			/* initial number of bits/code */

static int n_bits;				/* number of bits/code */
static int maxbits;			/* user settable max # bits/code */
static long maxcode;			/* maximum code, given n_bits */
static long maxmaxcode;			/* should NEVER generate this code */
# define MAXCODE(n_bits)	((1 << (n_bits)) - 1)

static long htab [HSIZE];
static unsigned short codetab [HSIZE];

#define tab_prefixof(i) codetab[i]
#define tab_suffixof(i)	((unsigned char *)(htab))[i]
#define de_stack	((unsigned char *)&tab_suffixof(1<<BITS))

static long free_ent = 0;			/* first unused entry */

static long getcode();

static int clear_flg = 0;

/*
 * the next two codes should not be changed lightly, as they must not
 * lie within the contiguous general code space.
 */
#define FIRST	257	/* first free entry */
#define	CLEAR	256	/* table clear output code */

static int toread;

void de_compress(ibytes, mb)
unsigned long ibytes;
int mb;
{
    register unsigned char *stackp;
    register int finchar;
    register long code, oldcode, incode;

    toread = ibytes;
    maxbits = mb;
    maxmaxcode = 1 << maxbits;
    maxcode = MAXCODE(n_bits = INIT_BITS);
    for(code = 255; code >= 0; code--) {
	tab_prefixof(code) = 0;
	tab_suffixof(code) = (unsigned char)code;
    }
    free_ent = FIRST;
    finchar = oldcode = getcode();
    if(oldcode == -1) {	/* EOF already? */
	return;			/* Get out of here */
    }
    /* first code must be 8 bits = char */
    *out_ptr++ = (char)finchar;
    stackp = de_stack;
    while((code = getcode()) > -1) {
	if(code == CLEAR) {
	    for(code = 255; code >= 0; code--) {
		tab_prefixof(code) = 0;
	    }
	    clear_flg = 1;
	    free_ent = FIRST - 1;
	    if((code = getcode()) == -1) {	/* O, untimely death! */
		break;
	    }
	}
	incode = code;
	/*
	 * Special case for KwKwK string.
	 */
	if(code >= free_ent) {
	    *stackp++ = finchar;
	    code = oldcode;
	}
	/*
	 * Generate output characters in reverse order
	 */
	while(code >= 256) {
	    *stackp++ = tab_suffixof(code);
	    code = tab_prefixof(code);
	}
	*stackp++ = finchar = tab_suffixof(code);
	/*
	 * And put them out in forward order
	 */
	do {
	    *out_ptr++ = (char)*--stackp;
	} while(stackp > de_stack);
	/*
	 * Generate the new entry.
	 */
	if((code=free_ent) < maxmaxcode) {
	    tab_prefixof(code) = (unsigned short)oldcode;
	    tab_suffixof(code) = finchar;
	    free_ent = code+1;
	}
	/*
	 * Remember previous code.
	 */
	oldcode = incode;
    }
    return;
}

static unsigned char rmask[9] =
    {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};

static int get_core_bytes;
static char *core_ptr;
static int file_bytes();
static int core_bytes();

static long getcode()
{
    register long code;
    static int offset = 0, size = 0;
    static unsigned char buf[BITS];
    register int r_off, bits;
    register unsigned char *bp = buf;

    if(clear_flg > 0 || offset >= size || free_ent > maxcode) {
	/*
	 * If the next entry will be too big for the current code
	 * size, then we must increase the size.  This implies reading
	 * a new buffer full, too.
	 */
	if(free_ent > maxcode) {
	    n_bits++;
	    if(n_bits == maxbits) {
		maxcode = maxmaxcode;	/* won't get any bigger now */
	    } else {
		maxcode = MAXCODE(n_bits);
	    }
	}
	if(clear_flg > 0) {
	    maxcode = MAXCODE (n_bits = INIT_BITS);
	    clear_flg = 0;
	}
	if(toread == 0) {
	    return -1;
	}
	if(get_core_bytes) {
	    size = core_bytes((char *)buf, (n_bits < toread ? n_bits : toread));
	} else {
	    size = file_bytes((char *)buf, (n_bits < toread ? n_bits : toread));
	}
	toread -= size;
	if(size <= 0) {
	    (void)fprintf(stderr, "Premature EOF\n");
#ifdef SCAN
	    do_error("macunpack: Premature EOF");
#endif /* SCAN */
	    exit(1);
	}
	offset = 0;
	/* Round size down to integral number of codes */
	size = (size << 3) - (n_bits - 1);
    }
    r_off = offset;
    bits = n_bits;
    /*
     * Get to the first byte.
     */
    bp += (r_off >> 3);
    r_off &= 7;
    /* Get first part (low order bits) */
    code = (*bp++ >> r_off);
    bits -= (8 - r_off);
    r_off = 8 - r_off;		/* now, offset into code word */
    /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
    if(bits >= 8) {
	code |= *bp++ << r_off;
	r_off += 8;
	bits -= 8;
    }
    /* high order bits. */
    code |= (*bp & rmask[bits]) << r_off;
    offset += n_bits;
    return code;
}

static int file_bytes(buf, length)
char *buf;
int length;
{
    return fread(buf, 1, length, infp);
}

static int core_bytes(buf, length)
char *buf;
int length;
{
    int i;

    for(i = 0; i < length; i++) {
	*buf++ = *core_ptr++;
    }
    return length;
}

void core_compress(ptr)
char *ptr;
{
    core_ptr = ptr;
    get_core_bytes = ptr != NULL;
}
#else /* DECOMPRESS */
int decompress; /* keep lint and some compilers happy */
#endif /* DECOMPRESS */

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.