Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

278 lines
5.6 KiB

//
// deftree.c
//
// Tree creation for the compressor
//
#include "deflate.h"
#include <string.h>
#include <crtdbg.h>
//
// MAX_LITERAL_TREE elements is the largest number of elements that will ever be passed
// in to this routine
//
typedef struct
{
// Made left_right a single long array for performance reasons. We always access them
// one after the other, so there is no disadvantage.
// left[] in lower 16 bits, right[] in upper 16 bits
// short left[2*MAX_LITERAL_TREE_ELEMENTS];
// short right[2*MAX_LITERAL_TREE_ELEMENTS];
unsigned long left_right[2*MAX_LITERAL_TREE_ELEMENTS];
int heap[MAX_LITERAL_TREE_ELEMENTS+1];
int num_elements;
// Maximum allowable code length (7 for pre-tree, 15 for other trees)
int max_code_length;
unsigned short *freq; // passed in as parameter
unsigned short *code; // passed in as parameter
short * sortptr;
int depth;
int heapsize;
int len_cnt[17];
} t_tree_context;
static void countLen(t_tree_context *context, int i) /* call with i = root */
{
if (i < context->num_elements)
{
// check for max code length allowed
context->len_cnt[(context->depth < context->max_code_length) ? context->depth : context->max_code_length]++;
}
else
{
unsigned long lr_value = context->left_right[i];
context->depth++;
countLen(context, lr_value & 65535); // formerly left[i]
countLen(context, lr_value >> 16); // formerly right[i]
context->depth--;
}
}
static void makeLen(t_tree_context *context, int root, BYTE *len)
{
int k;
int cum;
int i;
for (i = 0; i <= 16; i++)
context->len_cnt[i] = 0;
countLen(context, root);
cum = 0;
for (i = context->max_code_length; i > 0; i--)
cum += (context->len_cnt[i] << (context->max_code_length - i));
while (cum != (1 << context->max_code_length))
{
context->len_cnt[context->max_code_length]--;
for (i = context->max_code_length-1; i > 0; i--)
{
if (context->len_cnt[i] != 0)
{
context->len_cnt[i]--;
context->len_cnt[i+1] += 2;
break;
}
}
cum--;
}
for (i = 16; i > 0; i--)
{
k = context->len_cnt[i];
while (--k >= 0)
len[ *context->sortptr++ ] = (byte) i;
}
}
/* priority queue; send i-th entry down heap */
static void downHeap(t_tree_context *context, int i)
{
int j, k;
k = context->heap[i];
while ((j = (i<<1)) <= context->heapsize)
{
if (j < context->heapsize &&
context->freq[context->heap[j]] > context->freq[context->heap[j + 1]])
j++;
if (context->freq[k] <= context->freq[context->heap[j]])
break;
context->heap[i] = context->heap[j];
i = j;
}
context->heap[i] = k;
}
//
// Reverse the bits, len > 0
//
static unsigned int bitReverse(unsigned int code, int len)
{
unsigned int new_code = 0;
do
{
new_code |= (code & 1);
new_code <<= 1;
code >>= 1;
} while (--len > 0);
return new_code >> 1;
}
void makeCode(int num_elements, const int *len_cnt, const BYTE *len, USHORT *code)
{
int start[18];
int i;
start[1] = 0;
for (i = 1; i <= 16; i++)
start[i + 1] = (start[i] + len_cnt[i]) << 1;
for (i = 0; i < num_elements; i++)
{
unsigned int unreversed_code;
unreversed_code = start[len[i]]++;
code[i] = (USHORT) bitReverse(unreversed_code, len[i]);
}
}
void makeTree(
int num_elements,
int max_code_length,
unsigned short * freq,
unsigned short * code,
byte * len
)
{
t_tree_context tree;
int k;
int avail;
int i;
_ASSERT(num_elements <= MAX_LITERAL_TREE_ELEMENTS);
// init tree context
tree.depth = 0;
tree.freq = freq;
tree.code = code;
tree.num_elements = num_elements;
tree.max_code_length = max_code_length;
avail = num_elements;
tree.heapsize = 0;
tree.heap[1] = 0;
for (i = 0; i < tree.num_elements; i++)
{
len[i] = 0;
if (tree.freq[i] != 0)
tree.heap[++tree.heapsize] = i;
}
//
// Less than 2 elements in the tree?
//
if (tree.heapsize < 2)
{
if (tree.heapsize == 0)
{
//
// No elements in the tree?
//
// Then insert two fake elements and retry.
//
tree.freq[0] = 1;
tree.freq[1] = 1;
}
else
{
//
// One element in the tree, so add a fake code
//
// If our only element is element #0 (heap[1] == 0), then
// make element #1 have a frequency of 1.
//
// Else make element #0 have a frequency of 1.
//
if (tree.heap[1] == 0)
tree.freq[1] = 1;
else
tree.freq[0] = 1;
}
//
// Retry with these new frequencies
//
makeTree(num_elements, max_code_length, freq, code, len);
return;
}
for (i = tree.heapsize >> 1; i >= 1; i--)
downHeap(&tree, i); /* make priority queue */
tree.sortptr = tree.code;
do
{
int i, j;
/* while queue has at least two entries */
i = tree.heap[1]; /* take out least-freq entry */
if (i < tree.num_elements)
*tree.sortptr++ = (short) i;
tree.heap[1] = tree.heap[tree.heapsize--];
downHeap(&tree, 1);
j = tree.heap[1]; /* next least-freq entry */
if (j < tree.num_elements)
*tree.sortptr++ = (short) j;
k = avail++; /* generate new node */
tree.freq[k] = tree.freq[i] + tree.freq[j];
tree.heap[1] = k;
downHeap(&tree, 1); /* put into queue */
// tree.left[k] = (short) i;
// tree.right[k] = (short) j;
tree.left_right[k] = (j << 16) | i;
} while (tree.heapsize > 1);
tree.sortptr = tree.code;
makeLen(&tree, k, len);
makeCode(num_elements, tree.len_cnt, len, code);
}