macutils/macunpack/de_huffman.c

159 lines
2.5 KiB
C

#include "de_huffman.h"
#include "macunpack.h"
#ifdef JDW
#define DEHUFFMAN
#endif /* JDW */
#ifdef STF
#define DEHUFFMAN
#endif /* STF */
#ifdef PIT
#define DEHUFFMAN
#endif /* PIT */
#ifdef SIT
#define DEHUFFMAN
#endif /* SIT */
#ifdef CPT
#define DEHUFFMAN
#endif /* CPT */
#ifdef DEHUFFMAN
#include "globals.h"
#include "../util/masks.h"
#include "../fileio/wrfile.h"
#include "huffman.h"
#include "../util/util.h"
int (*get_bit)(void);
int bytesread;
/* 515 because StuffIt Classic needs more than the needed 511 */
struct node nodelist[515];
static int getbit_be(void);
static int getbit_le(void);
static int getdecodebyte(void);
static node *nodeptr, *read_sub_tree(void);
static int bit;
void de_huffman(uint32_t obytes)
{
while(obytes != 0) {
*out_ptr++ = gethuffbyte(nodelist);
obytes--;
}
return;
}
void de_huffman_end(unsigned int term)
{
int c;
while((c = gethuffbyte(nodelist)) != term) {
*out_ptr++ = c;
}
}
void set_huffman(int endian)
{
if(endian == HUFF_LE) {
get_bit = getbit_le;
} else if(endian == HUFF_BE) {
get_bit = getbit_be;
}
}
void
read_tree (void)
{
nodeptr = nodelist;
bit = 0; /* put us on a boundary */
(void)read_sub_tree();
}
/* This routine recursively reads the Huffman encoding table and builds
a decoding tree. */
static node *read_sub_tree(void)
{
node *np;
np = nodeptr++;
if((*get_bit)() == 1) {
np->flag = 1;
np->byte = getdecodebyte();
} 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_be (void)
{
static int b;
if(bit == 0) {
b = getb(infp) & BYTEMASK;
bit = 8;
bytesread++;
}
bit--;
return (b >> bit) & 1;
}
/* This routine returns the next bit in the input stream (LSB first) */
static int
getbit_le (void)
{
static int b;
if(bit == 0) {
b = getb(infp) & BYTEMASK;
bit = 8;
bytesread++;
}
bit--;
return (b >> (7 - bit)) & 1;
}
void
clrhuff (void)
{
bit = 0;
}
int gethuffbyte(node *l_nodelist)
{
register node *np;
np = l_nodelist;
while(np->flag == 0) {
np = (*get_bit)() ? np->one : np->zero;
}
return np->byte;
}
int
getihuffbyte (void)
{
return gethuffbyte(nodelist);
}
static int
getdecodebyte (void)
{
register int i, b;
b = 0;
for(i = 8; i > 0; i--) {
b = (b << 1) + (*get_bit)();
}
return b;
}
#else /* DEHUFFMAN */
int dehuffman; /* keep lint and some compilers happy */
#endif /* DEHUFFMAN */