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

de_lzh.c

#include "macunpack.h"
#ifdef ZMA
#define DELZH
#endif /* ZMA */
#ifdef LZH
#define DELZH
#endif /* LZH */
#ifdef DELZH
#include "globals.h"
#include "../util/masks.h"
#include "../fileio/wrfile.h"
#include "bits_be.h"

/* This code is valid for bitsused upto 15. */
#define DICBIT    13    /* 12(-lh4-) or 13(-lh5-) */
#define UCHAR_MAX    255
#define THRESHOLD    3

static int decoded;
static int bitsused;
static unsigned int blocksize;
static unsigned int decode_c();
static unsigned int decode_p();
static void make_table();

/* lzh compression */
void de_lzh(ibytes, obytes, data, bits)
long ibytes;
long obytes;
char **data;
int bits;
{
    unsigned int i, r, c;
    int remains;

    bit_be_inbytes = ibytes;
    bit_be_filestart = *data;
    bitsused = bits;
    bit_be_init_getbits();
    blocksize = 0;
    decoded = 0;
    r = 0;
    for(;;) {
      c = decode_c();
      if(decoded) {
          *data = bit_be_filestart;
          return;
      }
      if(c <= UCHAR_MAX) {
          out_ptr[r++] = c;
          obytes--;
          if(obytes == 0) {
            *data = bit_be_filestart;
            return;
          }
      } else {
          remains = c - (UCHAR_MAX + 1 - THRESHOLD);
          i = (r - decode_p() - 1);
          while(--remains >= 0) {
            out_ptr[r++] = out_ptr[i++];
            obytes--;
            if(obytes == 0) {
                *data = bit_be_filestart;
                return;
            }
          }
      }
    }
}

#define MAXMATCH 256
#define NC (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD)
#define CBIT 9
#define CODE_BIT 16
#define NP (DICBIT + 1)
#define NT (CODE_BIT + 3)
#define PBIT 4  /* smallest integer such that (1U << PBIT) > NP */
#define TBIT 5  /* smallest integer such that (1U << TBIT) > NT */
#if NT > NP
# define NPT NT
#else
# define NPT NP
#endif

static unsigned int left[2 * NC - 1], right[2 * NC - 1];
static unsigned char c_len[NC], pt_len[NPT];
static unsigned int c_table[4096], pt_table[256];

static void read_pt_len(nn, nbit, i_special)
int nn;
int nbit;
int i_special;
{
    int i, c, n;
    unsigned int mask;

    n = bit_be_getbits(nbit);
    if (n == 0) {
      c = bit_be_getbits(nbit);
      for (i = 0; i < nn; i++) {
          pt_len[i] = 0;
      }
      for (i = 0; i < 256; i++) {
          pt_table[i] = c;
      }
    } else {
      i = 0;
      while (i < n) {
          c = bit_be_bitbuf >> (BITBUFSIZ - 3);
          if (c == 7) {
            mask = (unsigned) 1 << (BITBUFSIZ - 1 - 3);
            while (mask & bit_be_bitbuf) {
                mask >>= 1;
                c++;
            }
          }
          bit_be_fillbuf((c < 7) ? 3 : c - 3);
          pt_len[i++] = c;
          if (i == i_special) {
            c = bit_be_getbits(2);
            while (--c >= 0) {
                pt_len[i++] = 0;
            }
          }
      }
      while (i < nn) {
          pt_len[i++] = 0;
      }
      make_table(nn, pt_len, 8, pt_table);
    }
}

static void read_c_len()
{
    int i, c, n;
    unsigned int mask;

    n = bit_be_getbits(CBIT);
    if (n == 0) {
      c = bit_be_getbits(CBIT);
      for (i = 0; i < NC; i++) {
          c_len[i] = 0;
      }
      for (i = 0; i < 4096; i++) {
          c_table[i] = c;
      }
    } else {
      i = 0;
      while (i < n) {
          c = pt_table[bit_be_bitbuf >> (BITBUFSIZ - 8)];
          if (c >= NT) {
            mask = (unsigned) 1 << (BITBUFSIZ - 1 - 8);
            do {
                if (bit_be_bitbuf & mask) {
                  c = right[c];
                } else {
                  c = left [c];
                }
                mask >>= 1;
            } while (c >= NT);
          }
          bit_be_fillbuf((int)pt_len[c]);
          if (c <= 2) {
            if (c == 0) {
                c = 1;
            } else if (c == 1) {
                c = bit_be_getbits(4) + 3;
            } else {
                c = bit_be_getbits(CBIT) + 20;
            }
            while (--c >= 0) {
                c_len[i++] = 0;
            }
          } else {
            c_len[i++] = c - 2;
          }
      }
      while (i < NC) {
          c_len[i++] = 0;
      }
      make_table(NC, c_len, 12, c_table);
    }
}

static unsigned int decode_c()
{
    unsigned int j, mask;

    if (blocksize == 0) {
      blocksize = bit_be_getbits(16);
      if (blocksize == 0) {
          decoded = 1;
          return 0;
      }
      read_pt_len(NT, TBIT, 3);
      read_c_len();
      read_pt_len(bitsused + 1, PBIT, -1);
    }
    blocksize--;
    j = c_table[bit_be_bitbuf >> (BITBUFSIZ - 12)];
    if (j >= NC) {
      mask = (unsigned) 1 << (BITBUFSIZ - 1 - 12);
      do {
          if (bit_be_bitbuf & mask) {
            j = right[j];
          } else {
            j = left [j];
          }
          mask >>= 1;
      } while (j >= NC);
    }
    bit_be_fillbuf((int)c_len[j]);
    return j;
}

static unsigned int decode_p()
{
    unsigned int j, mask;

    j = pt_table[bit_be_bitbuf >> (BITBUFSIZ - 8)];
    if (j > bitsused) {
      mask = (unsigned) 1 << (BITBUFSIZ - 1 - 8);
      do {
          if (bit_be_bitbuf & mask) {
            j = right[j];
          } else {
            j = left [j];
          }
          mask >>= 1;
      } while (j > bitsused);
    }
    bit_be_fillbuf((int)pt_len[j]);
    if (j != 0) {
      j = ((unsigned) 1 << (j - 1)) + bit_be_getbits((int) (j - 1));
    }
    return j;
}

static void make_table(nchar, bitlen, tablebits, table)
int nchar;
unsigned char bitlen[];
int tablebits;
unsigned int table[];
{
    unsigned int count[17], weight[17], start[18], *p;
    unsigned int i, k, len, ch, jutbits, avail, nextcode, mask;

    for (i = 1; i <= 16; i++) {
      count[i] = 0;
    }
    for (i = 0; i < nchar; i++) {
      count[bitlen[i]]++;
    }

    start[1] = 0;
    for (i = 1; i <= 16; i++) {
      start[i + 1] = start[i] + (count[i] << (16 - i));
    }

    jutbits = 16 - tablebits;
    for (i = 1; i <= tablebits; i++) {
      start[i] >>= jutbits;
      weight[i] = (unsigned) 1 << (tablebits - i);
    }
    while (i <= 16) {
       weight[i] = (unsigned) 1 << (16 - i);
       i++;
    }

    i = start[tablebits + 1] >> jutbits;
    if (i != (unsigned int)((unsigned) 1 << 16)) {
      k = 1 << tablebits;
      while (i != k) {
          table[i++] = 0;
      }
    }

    avail = nchar;
    mask = (unsigned) 1 << (15 - tablebits);
    for (ch = 0; ch < nchar; ch++) {
      if ((len = bitlen[ch]) == 0) {
          continue;
      }
      nextcode = start[len] + weight[len];
      if (len <= tablebits) {
          for (i = start[len]; i < nextcode; i++) {
            table[i] = ch;
          }
      } else {
          k = start[len];
          p = &table[k >> jutbits];
          i = len - tablebits;
          while (i != 0) {
            if (*p == 0) {
                right[avail] = left[avail] = 0;
                *p = avail++;
            }
            if (k & mask) {
                p = &right[*p];
            } else {
                p = &left[*p];
            }
            k <<= 1;
            i--;
          }
          *p = ch;
      }
      start[len] = nextcode;
    }
}
#else /* DELZH */
int delzh; /* keep lint and some compilers happy */
#endif /* DELZH */


Generated by  Doxygen 1.6.0   Back to index