ftp.nice.ch/pub/next/tools/archiver/Opener.3.4b.Utils.s.tar.gz#/Opener.3.4a.Utils.s/lha/src/huf.c

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.