This is huf.c in view mode; [Download] [Up]
/* ------------------------------------------------------------------------ */
/* LHa for UNIX */
/* huf.c -- new static Huffman */
/* */
/* Modified Nobutaka Watazaki */
/* */
/* Ver. 1.14 Source All chagned 1995.01.14 N.Watazaki */
/* ------------------------------------------------------------------------ */
#include "lha.h"
#ifdef sony_news
#include <sys/param.h>
#endif
#if defined(__STDC__) || defined(NEWSOS)
#include <stdlib.h>
#endif
/* ------------------------------------------------------------------------ */
unsigned short left[2 * NC - 1], right[2 * NC - 1];
unsigned char c_len[NC], pt_len[NPT];
unsigned short c_freq[2 * NC - 1], c_table[4096], c_code[NC], p_freq[2 * NP - 1],
pt_table[256], pt_code[NPT], t_freq[2 * NT - 1];
static unsigned char *buf;
static unsigned short bufsiz;
static unsigned short blocksize;
static unsigned short output_pos, output_mask;
static int pbit;
static int np;
/* ------------------------------------------------------------------------ */
/* Encording */
/* ------------------------------------------------------------------------ */
static void
count_t_freq(/*void*/)
{
short i, k, n, count;
for (i = 0; i < NT; i++)
t_freq[i] = 0;
n = NC;
while (n > 0 && c_len[n - 1] == 0)
n--;
i = 0;
while (i < n) {
k = c_len[i++];
if (k == 0) {
count = 1;
while (i < n && c_len[i] == 0) {
i++;
count++;
}
if (count <= 2)
t_freq[0] += count;
else if (count <= 18)
t_freq[1]++;
else if (count == 19) {
t_freq[0]++;
t_freq[1]++;
}
else
t_freq[2]++;
} else
t_freq[k + 2]++;
}
}
/* ------------------------------------------------------------------------ */
static void
write_pt_len(n, nbit, i_special)
short n;
short nbit;
short i_special;
{
short i, k;
while (n > 0 && pt_len[n - 1] == 0)
n--;
putbits(nbit, n);
i = 0;
while (i < n) {
k = pt_len[i++];
if (k <= 6)
putbits(3, k);
else
putbits(k - 3, USHRT_MAX << 1);
if (i == i_special) {
while (i < 6 && pt_len[i] == 0)
i++;
putbits(2, i - 3);
}
}
}
/* ------------------------------------------------------------------------ */
static void
write_c_len(/*void*/)
{
short i, k, n, count;
n = NC;
while (n > 0 && c_len[n - 1] == 0)
n--;
putbits(CBIT, n);
i = 0;
while (i < n) {
k = c_len[i++];
if (k == 0) {
count = 1;
while (i < n && c_len[i] == 0) {
i++;
count++;
}
if (count <= 2) {
for (k = 0; k < count; k++)
putcode(pt_len[0], pt_code[0]);
}
else if (count <= 18) {
putcode(pt_len[1], pt_code[1]);
putbits(4, count - 3);
}
else if (count == 19) {
putcode(pt_len[0], pt_code[0]);
putcode(pt_len[1], pt_code[1]);
putbits(4, 15);
}
else {
putcode(pt_len[2], pt_code[2]);
putbits(CBIT, count - 20);
}
}
else
putcode(pt_len[k + 2], pt_code[k + 2]);
}
}
/* ------------------------------------------------------------------------ */
static void
encode_c(c)
short c;
{
putcode(c_len[c], c_code[c]);
}
/* ------------------------------------------------------------------------ */
static void
encode_p(p)
unsigned short p;
{
unsigned short c, q;
c = 0;
q = p;
while (q) {
q >>= 1;
c++;
}
putcode(pt_len[c], pt_code[c]);
if (c > 1)
putbits(c - 1, p);
}
/* ------------------------------------------------------------------------ */
static void
send_block( /* void */ )
{
unsigned char flags;
unsigned short i, k, root, pos, size;
root = make_tree(NC, c_freq, c_len, c_code);
size = c_freq[root];
putbits(16, size);
if (root >= NC) {
count_t_freq();
root = make_tree(NT, t_freq, pt_len, pt_code);
if (root >= NT) {
write_pt_len(NT, TBIT, 3);
} else {
putbits(TBIT, 0);
putbits(TBIT, root);
}
write_c_len();
} else {
putbits(TBIT, 0);
putbits(TBIT, 0);
putbits(CBIT, 0);
putbits(CBIT, root);
}
root = make_tree(np, p_freq, pt_len, pt_code);
if (root >= np) {
write_pt_len(np, pbit, -1);
}
else {
putbits(pbit, 0);
putbits(pbit, root);
}
pos = 0;
for (i = 0; i < size; i++) {
if (i % CHAR_BIT == 0)
flags = buf[pos++];
else
flags <<= 1;
if (flags & (1 << (CHAR_BIT - 1))) {
encode_c(buf[pos++] + (1 << CHAR_BIT));
k = buf[pos++] << CHAR_BIT;
k += buf[pos++];
encode_p(k);
} else
encode_c(buf[pos++]);
if (unpackable)
return;
}
for (i = 0; i < NC; i++)
c_freq[i] = 0;
for (i = 0; i < np; i++)
p_freq[i] = 0;
}
/* ------------------------------------------------------------------------ */
void
output_st1(c, p)
unsigned short c;
unsigned short p;
{
static unsigned short cpos;
output_mask >>= 1;
if (output_mask == 0) {
output_mask = 1 << (CHAR_BIT - 1);
if (output_pos >= bufsiz - 3 * CHAR_BIT) {
send_block();
if (unpackable)
return;
output_pos = 0;
}
cpos = output_pos++;
buf[cpos] = 0;
}
buf[output_pos++] = (unsigned char) c;
c_freq[c]++;
if (c >= (1 << CHAR_BIT)) {
buf[cpos] |= output_mask;
buf[output_pos++] = (unsigned char) (p >> CHAR_BIT);
buf[output_pos++] = (unsigned char) p;
c = 0;
while (p) {
p >>= 1;
c++;
}
p_freq[c]++;
}
}
/* ------------------------------------------------------------------------ */
unsigned char *
alloc_buf( /* void */ )
{
bufsiz = 16 * 1024 *2; /* 65408U; */ /* t.okamoto */
while ((buf = (unsigned char *) malloc(bufsiz)) == NULL) {
bufsiz = (bufsiz / 10) * 9;
if (bufsiz < 4 * 1024)
break;
}
return buf;
}
/* ------------------------------------------------------------------------ */
void
encode_start_st1( /* void */ )
{
int i;
if (dicbit <= (MAX_DICBIT - 2)) {
pbit = 4; /* lh4,5 etc. */
np = 14;
} else {
pbit = 5; /* lh6 */
np = 16;
}
for (i = 0; i < NC; i++)
c_freq[i] = 0;
for (i = 0; i < np; i++)
p_freq[i] = 0;
output_pos = output_mask = 0;
init_putbits();
buf[0] = 0;
}
/* ------------------------------------------------------------------------ */
void
encode_end_st1( /* void */ )
{
if (!unpackable) {
send_block();
putbits(CHAR_BIT - 1, 0); /* flush remaining bits */
}
}
/* ------------------------------------------------------------------------ */
/* decoding */
/* ------------------------------------------------------------------------ */
static void
read_pt_len(nn, nbit, i_special)
short nn;
short nbit;
short i_special;
{
short i, c, n;
n = getbits(nbit);
if (n == 0) {
c = 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 = bitbuf >> (16 - 3);
if (c == 7) {
unsigned short mask = 1 << (16 - 4);
while (mask & bitbuf) {
mask >>= 1;
c++;
}
}
fillbuf((c < 7) ? 3 : c - 3);
pt_len[i++] = c;
if (i == i_special) {
c = 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( /* void */ )
{
short i, c, n;
n = getbits(CBIT);
if (n == 0) {
c = 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[bitbuf >> (16 - 8)];
if (c >= NT) {
unsigned short mask = 1 << (16 - 9);
do {
if (bitbuf & mask)
c = right[c];
else
c = left[c];
mask >>= 1;
} while (c >= NT);
}
fillbuf(pt_len[c]);
if (c <= 2) {
if (c == 0)
c = 1;
else if (c == 1)
c = getbits(4) + 3;
else
c = 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);
}
}
/* ------------------------------------------------------------------------ */
unsigned short
decode_c_st1( /*void*/ )
{
unsigned short j, mask;
if (blocksize == 0) {
blocksize = getbits(16);
read_pt_len(NT, TBIT, 3);
read_c_len();
read_pt_len(np, pbit, -1);
}
blocksize--;
j = c_table[bitbuf >> 4];
if (j < NC)
fillbuf(c_len[j]);
else {
fillbuf(12);
mask = 1 << (16 - 1);
do {
if (bitbuf & mask)
j = right[j];
else
j = left[j];
mask >>= 1;
} while (j >= NC);
fillbuf(c_len[j] - 12);
}
return j;
}
/* ------------------------------------------------------------------------ */
unsigned short
decode_p_st1( /* void */ )
{
unsigned short j, mask;
j = pt_table[bitbuf >> (16 - 8)];
if (j < np)
fillbuf(pt_len[j]);
else {
fillbuf(8);
mask = 1 << (16 - 1);
do {
if (bitbuf & mask)
j = right[j];
else
j = left[j];
mask >>= 1;
} while (j >= np);
fillbuf(pt_len[j] - 8);
}
if (j != 0)
j = (1 << (j - 1)) + getbits(j - 1);
return j;
}
/* ------------------------------------------------------------------------ */
void
decode_start_st1( /* void */ )
{
if (dicbit <= (MAX_DICBIT - 2)) { /* 13 ... Changed N.Watazaki */
np = 14;
pbit = 4;
} else {
np = 16;
pbit = 5;
}
init_getbits();
blocksize = 0;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.