Windows2000/private/inet/urlmon/compress/gzip/maketbl.c
2020-09-30 17:12:32 +02:00

169 lines
4.3 KiB
C

// maketbl.c
// Creates Huffman decoding tables
#include <windows.h>
#include <crtdbg.h>
#include "common.h"
#include "maketbl.h"
// Reverse the bits, len > 0
static unsigned int bitReverse(unsigned int code, int len)
{
unsigned int new_code = 0;
_ASSERT(len > 0);
do
{
new_code |= (code & 1);
new_code <<= 1;
code >>= 1;
} while (--len > 0);
return new_code >> 1;
}
BOOL makeTable(
int num_elements,
int table_bits,
const byte * code_length,
short * table,
short * left,
short * right
)
{
int bl_count[17];
unsigned int next_code[17];
unsigned int code[MAX_LITERAL_TREE_ELEMENTS];
int temp_code;
int avail;
int i, bits, ch;
int table_size, table_mask;
table_size = 1 << table_bits;
table_mask = table_size - 1;
for (i = 0; i <= 16; i++)
bl_count[i] = 0;
for (i = 0; i < num_elements; i++)
bl_count[code_length[i]]++;
// If there are any codes larger than table_bits in length, then we will have to clear the table for our left/right spillover code to work correctly.
// If there aren't any codes that large, then all table entries will be written over without being read, so we don't need to initialise them
for (i = table_bits; i <= 16; i++)
{
if (bl_count[i] > 0)
{
int j;
// found a code larger than table_bits
for (j = 0; j < table_size; j++)
table[j] = 0;
break;
}
}
temp_code = 0;
bl_count[0] = 0;
for (bits = 1; bits <= 16; bits++)
{
temp_code = (temp_code + bl_count[bits - 1]) << 1;
next_code[bits] = temp_code;
}
for (i = 0; i < num_elements; i++)
{
int len = code_length[i];
if (len > 0)
{
code[i] = bitReverse(next_code[len], len);
next_code[len]++;
}
}
avail = num_elements;
for (ch = 0; ch < num_elements; ch++)
{
int start_at, len;
len = code_length[ch];// length of this code
start_at = code[ch];// start value (bit reversed)
if (len > 0)
{
if (len <= table_bits)
{
int locs = 1 << (table_bits - len);
int increment = 1 << len;
int j;
// Make sure that in the loop below, start_at is always less than table_size.
// On last iteration we store at array index:
// initial_start_at + (locs-1)*increment
// = initial_start_at + locs*increment - increment
// = initial_start_at + (1 << table_bits) - increment
// = initial_start_at + table_size - increment
// Therefore we must ensure:
// initial_start_at + table_size - increment < table_size
// or: initial_start_at < increment
if (start_at >= increment)
return FALSE; // invalid table!
for (j = 0; j < locs; j++)
{
table[start_at] = (short) ch;
start_at += increment;
}
}
else
{
int overflow_bits;
int code_bit_mask;
short * p;
overflow_bits = len - table_bits;
code_bit_mask = 1 << table_bits;
p = &table[start_at & table_mask];
do
{
short value;
value = *p;
if (value == 0)
{
left[avail] = 0;
right[avail] = 0;
*p = -avail;
value = -avail;
avail++;
}
if ((start_at & code_bit_mask) == 0)
p = &left[-value];
else
p = &right[-value];
code_bit_mask <<= 1;
overflow_bits--;
} while (overflow_bits != 0);
*p = (short) ch;
}
}
}
return TRUE;
}