Logo Search packages:      
Sourcecode: macutils version File versions  Download package

de_compress.c

#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 */


Generated by  Doxygen 1.6.0   Back to index