#include "globals.h"
#include "masks.h"
#include "../fileio/fileglob.h"
#include "huffman.h"

unsigned char getb();
int (*get_bit)();
int getbit();

static node nodelist[512], *nodeptr, *read_sub_tree();

static int bit;

void dehuffman(obytes)
unsigned long obytes;
{
    get_bit = getbit;
    while(obytes != 0) {
	*out_ptr++ = gethuffbyte(nodelist);
	obytes--;
    }
    return;
}

void read_tree()
{
    nodeptr = nodelist;
    bit = 0;		/* put us on a byte boundary */
    (void)read_sub_tree();
}

/* This routine recursively reads the Huffman encoding table and builds
   a decoding tree. */
static node *read_sub_tree()
{
    node *np;

    np = nodeptr++;
    if(getbit() == 1) {
	np->flag = 1;
	np->byte = getdecodebyte((node *)NULL);
    } else {
	np->flag = 0;
	np->zero = read_sub_tree();
	np->one  = read_sub_tree();
    }
    return np;
}

/* This routine returns the next bit in the input stream (MSB first) */

static int getbit()
{
    static int b;

    if(bit == 0) {
	b = getb(infp) & BYTEMASK;
	bit = 8;
    }
    bit--;
    return (b >> bit) & 1;
}

int gethuffbyte(nodelist)
node *nodelist;
{
    register node *np;

    np = nodelist;
    while(np->flag == 0) {
	np = (*get_bit)() ? np->one : np->zero;
    }
    return np->byte;
}

int getdecodebyte(nodelist)
struct node *nodelist;
{
    register int i, b;

    if(bit == 0) {	/* on byte boundary? */
	b = getb(infp) & BYTEMASK;
    } else {		/* no, put a byte together */
	b = 0;
	for(i = 8; i > 0; i--) {
	    b = (b << 1) + getbit();
	}
    }
    return b;
}
