221 lines
3.8 KiB
C
221 lines
3.8 KiB
C
/*
|
|
* Table-building routines
|
|
*
|
|
* make_table() is based on ** Public Domain ** source "AR001.ZIP".
|
|
*/
|
|
#include "decoder.h"
|
|
|
|
|
|
/*
|
|
* Make a decoding table for decoding nchar possible Huffman elements
|
|
* with bit lengths given by bitlen.
|
|
*
|
|
* Output the main lookup table into table[] and use leftright[] for
|
|
* supplementary information (for bitlengths > tablebits).
|
|
*
|
|
* The size of table[] is tablebits elements.
|
|
*/
|
|
#ifndef ASM_MAKE_TABLE
|
|
bool NEAR make_table(
|
|
t_decoder_context *context,
|
|
int nchar,
|
|
const byte *bitlen,
|
|
byte tablebits,
|
|
short *table,
|
|
short *leftright
|
|
)
|
|
{
|
|
uint i;
|
|
int ch;
|
|
short * p;
|
|
uint count[17], weight[17], start[18];
|
|
int avail;
|
|
uint nextcode;
|
|
uint k;
|
|
byte len;
|
|
byte jutbits;
|
|
|
|
for (i = 1; i <= 16; i++)
|
|
count[i] = 0;
|
|
|
|
/* count the number of elements of each bit length */
|
|
for (i = 0; i < (uint) nchar; i++)
|
|
count[bitlen[i]]++;
|
|
|
|
start[1] = 0;
|
|
|
|
for (i = 1; i <= 16; i++)
|
|
start[i + 1] = start[i] + (count[i] << (16 - i));
|
|
|
|
#ifdef BIT16
|
|
if (start[17])
|
|
{
|
|
return false; /* bad table */
|
|
}
|
|
#else
|
|
if (start[17] != 65536)
|
|
{
|
|
if (start[17] == 0)
|
|
{
|
|
/*
|
|
* All elements are length zero
|
|
*/
|
|
memset(table, 0, sizeof(ushort)*(1 << tablebits));
|
|
return true; /* success */
|
|
}
|
|
else
|
|
{
|
|
return false; /* bad table */
|
|
}
|
|
}
|
|
#endif
|
|
|
|
jutbits = 16 - tablebits;
|
|
|
|
for (i = 1; i <= tablebits; i++)
|
|
{
|
|
start[i] >>= jutbits;
|
|
weight[i] = 1 << (tablebits - i);
|
|
}
|
|
|
|
while (i <= 16)
|
|
{
|
|
weight[i] = 1 << (16 - i);
|
|
i++;
|
|
}
|
|
|
|
i = start[tablebits+1] >> jutbits;
|
|
|
|
#ifdef BIT16
|
|
if (i)
|
|
#else
|
|
if (i != 65536)
|
|
#endif
|
|
{
|
|
memset(
|
|
&table[i],
|
|
0,
|
|
sizeof(ushort)*((1 << tablebits)-i)
|
|
);
|
|
}
|
|
|
|
avail = nchar;
|
|
|
|
for (ch = 0; ch < nchar; ch++)
|
|
{
|
|
if ((len = bitlen[ch]) == 0)
|
|
continue;
|
|
|
|
nextcode = start[len] + weight[len];
|
|
|
|
if (len <= tablebits)
|
|
{
|
|
if (nextcode > (uint) (1 << tablebits))
|
|
return false; /* bad table */
|
|
|
|
for (i = start[len]; i < nextcode; i++)
|
|
table[i] = (short) ch;
|
|
|
|
start[len] = nextcode;
|
|
}
|
|
else
|
|
{
|
|
byte i;
|
|
|
|
k = start[len];
|
|
start[len] = nextcode;
|
|
p = &table[k >> jutbits];
|
|
|
|
i = len - tablebits;
|
|
k <<= tablebits;
|
|
|
|
do
|
|
{
|
|
if (*p == 0)
|
|
{
|
|
leftright[avail*2] = leftright[avail*2+1] = 0;
|
|
*p = (short) -avail;
|
|
avail++;
|
|
}
|
|
|
|
if ((signed short) k < 0) // if (k & 32768)
|
|
p = &leftright[-(*p)*2+1];
|
|
else
|
|
p = &leftright[-(*p)*2];
|
|
|
|
k <<= 1;
|
|
i--;
|
|
} while (i);
|
|
|
|
*p = (short) ch;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
* Specialised make table routine where it is known that there are
|
|
* only 8 elements (nchar=8) and tablebits=7 (128 byte lookup table).
|
|
*
|
|
* Since there can be no overflow, this will be a direct lookup.
|
|
*
|
|
* Important difference; the lookup table returns a byte, not a ushort.
|
|
*/
|
|
bool NEAR make_table_8bit(t_decoder_context *context, byte bitlen[], byte table[])
|
|
{
|
|
ushort count[17], weight[17], start[18];
|
|
ushort i;
|
|
ushort nextcode;
|
|
byte len;
|
|
byte ch;
|
|
|
|
for (i = 1; i <= 16; i++)
|
|
count[i] = 0;
|
|
|
|
for (i = 0; i < 8; i++)
|
|
count[bitlen[i]]++;
|
|
|
|
start[1] = 0;
|
|
|
|
for (i = 1; i <= 16; i++)
|
|
start[i + 1] = start[i] + (count[i] << (16 - i));
|
|
|
|
if (start[17] != 0)
|
|
return false; /* bad table */
|
|
|
|
for (i = 1; i <= 7; i++)
|
|
{
|
|
start[i] >>= 9;
|
|
weight[i] = 1 << (7 - i);
|
|
}
|
|
|
|
while (i <= 16)
|
|
{
|
|
weight[i] = 1 << (16 - i);
|
|
i++;
|
|
}
|
|
|
|
memset(table, 0, 1<<7);
|
|
|
|
for (ch = 0; ch < 8; ch++)
|
|
{
|
|
if ((len = bitlen[ch]) == 0)
|
|
continue;
|
|
|
|
nextcode = start[len] + weight[len];
|
|
|
|
if (nextcode > (1 << 7))
|
|
return false; /* bad table */
|
|
|
|
for (i = start[len]; i < nextcode; i++)
|
|
table[i] = ch;
|
|
|
|
start[len] = nextcode;
|
|
}
|
|
|
|
return true;
|
|
}
|