ftp.nice.ch/pub/next/unix/archiver/freeze.2.3.N.bs.tar.gz#/freeze/huf.c

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

#include "freeze.h"
#include "huf.h"
#include "bitio.h"

/*----------------------------------------------------------------------*/
/*									*/
/*		HUFFMAN ENCODING					*/
/*									*/
/*----------------------------------------------------------------------*/

/* TABLES OF ENCODE/DECODE for upper 6 bits position information */

/* The contents of `Table' are used for freezing only, so we use
 * it freely when melting.
 */

uchar Table2[9] = { 0, 0, 1, 1, 1, 4, 10, 27, 18 };

uchar p_len[64];        /* These arrays are built accordingly to values */
uchar d_len[256];       /* of `Table' above which are default, from the */
			/* command line or from the header of frozen file */

uchar code[256];

u_short freq[T2 + 1];           /* frequency table */
short   son[T2];                /* points to son node (son[i],son[i+1]) */
short   prnt[T2 + N_CHAR2];     /* points to parent node */

static  short t, r, chars;

/* notes :
   prnt[Tx .. Tx + N_CHARx - 1] used by
   indicates leaf position that corresponding to code.
*/

/* Initializes Huffman tree, bit I/O variables, etc.
   Static array is initialized with `table', dynamic Huffman tree
   has `n_char' leaves.
*/

void StartHuff (n_char)
	int n_char;
{
	register short i, j;
	t = n_char * 2 - 1;
	r = t - 1;
	chars = n_char;

/* A priori frequences are 1 */

	for (i = 0; i < n_char; i++) {
		freq[i] = 1;
		son[i] = i + t;
		prnt[i + t] = i;
	}
	i = 0; j = n_char;

/* Building the balanced tree */

	while (j <= r) {
		freq[j] = freq[i] + freq[i + 1];
		son[j] = i;
		prnt[i] = prnt[i + 1] = j;
		i += 2; j++;
	}
	freq[t] = 0xffff;
	prnt[r] = 0;
	in_count = 1;
	bytes_out = 5;
#ifdef DEBUG
	symbols_out = refers_out = 0;
#endif
}

/* Reconstructs tree with `chars' leaves */

void reconst ()
{
	register u_short i, j, k;
	register u_short f;

#ifdef DEBUG
	if (quiet < 0)
	  fprintf(stderr,
	    "Reconstructing Huffman tree: symbols: %ld, references: %ld\n",
	    symbols_out, refers_out);
#endif

/* correct leaf node into of first half,
   and set these freqency to (freq+1)/2
*/
	j = 0;
	for (i = 0; i < t; i++) {
		if (son[i] >= t) {
			freq[j] = (freq[i] + 1) / 2;
			son[j] = son[i];
			j++;
		}
	}
/* Build tree.  Link sons first */

	for (i = 0, j = chars; j < t; i += 2, j++) {
		k = i + 1;
		f = freq[j] = freq[i] + freq[k];
		for (k = j - 1; f < freq[k]; k--);
		k++;
		{       register u_short *p, *e;
			for (p = &freq[j], e = &freq[k]; p > e; p--)
				p[0] = p[-1];
			freq[k] = f;
		}
		{       register short *p, *e;
			for (p = &son[j], e = &son[k]; p > e; p--)
				p[0] = p[-1];
			son[k] = i;
		}
	}

/* Link parents */
	for (i = 0; i < t; i++) {
		if ((k = son[i]) >= t) {
			prnt[k] = i;
		} else {
			prnt[k] = prnt[k + 1] = i;
		}
	}
}


/* Updates given code's frequency, and updates tree */

void update (c)
	u_short c;
{
	register u_short *p;
	register u_short i, j, k, l;

	if (freq[r] == MAX_FREQ) {
		reconst();
	}
	c = prnt[c + t];
	do {
		k = ++freq[c];

		/* swap nodes when become wrong frequency order. */
		if (k > freq[l = c + 1]) {
			for (p = freq+l+1; k > *p++; ) ;
			l = p - freq - 2;
			freq[c] = p[-2];
			p[-2] = k;

			i = son[c];
			prnt[i] = l;
			if (i < t) prnt[i + 1] = l;

			j = son[l];
			son[l] = i;

			prnt[j] = c;
			if (j < t) prnt[j + 1] = c;
			son[c] = j;

			c = l;
		}
	} while ((c = prnt[c]) != 0);	/* loop until reach to root */
}

/* Encodes the literal or the length information */

void EncodeChar (c)
	u_short c;
{
	unsigned long i;
	register u_short j, k;

	i = 0;
	j = 0;
	k = prnt[c + t];

/* trace links from leaf node to root */

	do {
		i >>= 1;

/* if node index is odd, trace larger of sons */
		if (k & 1) i += 0x80000000;

		j++;
	} while ((k = prnt[k]) != r) ;

/* `j' never reaches the value of 32 ! */

	if (j > 16) {
		Putcode(16, (u_short)(i >> 16));
		Putcode(j - 16, (u_short)i);
	} else {
		Putcode(j, (u_short)(i >> 16));
	}
	update(c);
}

/* Encodes the position information */

void EncodePosition (c)
	register u_short c;
{
	register u_short i;

	/* output upper 6 bit from table */
	i = c >> 7;
	Putcode((u_short)(p_len[i]), (u_short)(code[i]) << 8);

	/* output lower 7 bit */
	Putcode(7, (u_short)(c & 0x7f) << 9);
}


/* Decodes the literal or length info and returns its value.
	Returns ENDOF, if the file is corrupt.
*/

short DecodeChar ()
{
	register u_short c;
	c = son[r];

	/* trace from root to leaf,
	   got bit is 0 to small(son[]), 1 to large (son[]+1) son node */

	while (c < t) {
		c += GetBit();
		c = son[c];
	}
	c -= t;
	update(c);
	if (crpt_flag) {
		crpt_message();
		return ENDOF;
	}
	crpt_flag = feof(stdin);
	return c;
}

/* Decodes the position info and returns it */

short DecodePosition ()
{
	register u_short i, j, c;

	/* decode upper 6 bits from the table */

	i = GetByte();
	crpt_flag = feof(stdin);

	c = (u_short)code[i] << 7;
	j = d_len[i] - 1;

	/* get lower 7 bits literally */

	return c | (((i << j) | GetNBits (j)) & 0x7f);
}


/* Initializes static Huffman arrays */

void init(table) uchar * table; {
	short i, j, k, num;
	num = 0;

/* There are `table[i]' `i'-bits Huffman codes */

	for(i = 1, j = 0; i <= 8; i++) {
		num += table[i] << (8 - i);
		for(k = table[i]; k; j++, k--)
			p_len[j] = i;
	}
	if (num != 256) {
		fprintf(stderr, "Invalid position table\n");
		exit(1);
	}
	num = j;
	if (do_melt == 0)

/* Freezing: building the table for encoding */

		for(i = j = 0;;) {
			code[j] = i << (8 - p_len[j]);
			i++;
			j++;
			if (j == num) break;
			i <<= p_len[j] - p_len[j-1];
		}
	else {

/* Melting: building the table for decoding */

		for(k = j = 0; j < num; j ++)
			for(i = 1 << (8 - p_len[j]); i--;)
				code[k++] = j;

		for(k = j = 0; j < num; j ++)
			for(i = 1 << (8 - p_len[j]); i--;)
				d_len[k++] =  p_len[j];
	}
}

/* Writes a 3-byte header into the frozen form of file; Table[7] and
	Table[8] aren't necessary, see `read_header'.
*/

void write_header() {
	u_short i;

	i = Table2[5] & 0x1F; i <<= 4;
	i |= Table2[4] & 0xF; i <<= 3;
	i |= Table2[3] & 7;   i <<= 2;
	i |= Table2[2] & 3;   i <<= 1;
	i |= Table2[1] & 1;

	putchar((int)(i & 0xFF));
	putchar((int)((i >> 8)));
	putchar((int)(Table2[6] & 0x3F));
	if (ferror(stdout))
		writeerr();
}

/* Reconstructs `Table' from the header of the frozen file and checks
	its correctness. Returns 0 if OK, EOF otherwise.
*/

int read_header() {
	short i, j;
	i = getchar() & 0xFF;
	i |= (getchar() & 0xFF) << 8;
	Table2[1] = i & 1; i >>= 1;
	Table2[2] = i & 3; i >>= 2;
	Table2[3] = i & 7; i >>= 3;
	Table2[4] = i & 0xF; i >>= 4;
	Table2[5] = i & 0x1F; i >>= 5;

	if (i & 1 || (i = getchar()) & 0xC0) {
		fprintf(stderr, "Unknown header format.\n");
		crpt_message();
		return EOF;
	}

	Table2[6] = i & 0x3F;

	i = Table2[1] + Table2[2] + Table2[3] + Table2[4] +
	Table2[5] + Table2[6];

	i = 62 - i;     /* free variable length codes for 7 & 8 bits */

	j = 128 * Table2[1] + 64 * Table2[2] + 32 * Table2[3] +
	16 * Table2[4] + 8 * Table2[5] + 4 * Table2[6];

	j = 256 - j;    /* free byte images for these codes */

/*      Equation:
	    Table[7] + Table[8] = i
	2 * Table[7] + Table[8] = j
*/
	j -= i;
	if (j < 0 || i < j) {
		crpt_message();
		return EOF;
	}
	Table2[7] = j;
	Table2[8] = i - j;

#ifdef DEBUG
	fprintf(stderr, "Codes: %d %d %d %d %d %d %d %d\n",
		Table2[1], Table2[2], Table2[3], Table2[4],
		Table2[5], Table2[6], Table2[7], Table2[8]);
#endif
	return 0;
}

#ifdef COMPAT

uchar Table1[9] = { 0, 0, 0, 1, 3, 8, 12, 24, 16 };

/* Old version of a routine above for handling files made by
	the 1st version of Freeze.
*/

short DecodePOld ()
{
	register u_short i, j, c;

	i = GetByte();
	crpt_flag = feof(stdin);

	c = (u_short)code[i] << 6;
	j = d_len[i] - 2;

	return c | (((i << j) | GetNBits (j)) & 0x3f);
}
#endif

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