133 lines
2.5 KiB
C
133 lines
2.5 KiB
C
#include "libmineziper_huffman_tree.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
tree build_tree(char* bit_lenghts, int size)
|
|
{
|
|
unsigned int* order_codes = sort(bit_lenghts, size);
|
|
|
|
tree out;
|
|
out.size = size;
|
|
out.min = bit_lenghts[order_codes[0]];
|
|
out.max = bit_lenghts[order_codes[size - 1]];
|
|
out.leaves = malloc(sizeof(leaf) * size);
|
|
|
|
int code = 0;
|
|
int code_incr = 0;
|
|
int last_bit_length = 0;
|
|
int i = 0;
|
|
int len_bit, j;
|
|
|
|
while (i < size)
|
|
{
|
|
j = order_codes[i];
|
|
len_bit = bit_lenghts[j];
|
|
|
|
code = code + code_incr;
|
|
if (len_bit != last_bit_length)
|
|
{
|
|
last_bit_length = len_bit;
|
|
code_incr = 1 << (16 - last_bit_length);
|
|
}
|
|
|
|
out.leaves[j].code = reverse(code, 16);
|
|
out.leaves[j].length = len_bit;
|
|
out.leaves[j].litteral = j;
|
|
i++;
|
|
}
|
|
|
|
free(order_codes);
|
|
return out;
|
|
}
|
|
|
|
tree build_default_tree()
|
|
{
|
|
char bit_lengths[DEFAULT_TREE_SIZE];
|
|
for (int i = 0; i < DEFAULT_TREE_SIZE; i++)
|
|
{
|
|
if (i < 144 || i >= 280)
|
|
bit_lengths[i] = 8;
|
|
|
|
else if (i >= 144 && i < 256)
|
|
bit_lengths[i] = 9;
|
|
|
|
else
|
|
bit_lengths[i] = 7;
|
|
}
|
|
|
|
return build_tree(bit_lengths, DEFAULT_TREE_SIZE);
|
|
}
|
|
|
|
tree build_default_dist_tree()
|
|
{
|
|
char bit_lengths[DEFAULT_DIST_TREE_SIZE];
|
|
for (int i = 0; i < DEFAULT_DIST_TREE_SIZE; i++)
|
|
{
|
|
bit_lengths[i] = 5;
|
|
}
|
|
|
|
return build_tree(bit_lengths, DEFAULT_DIST_TREE_SIZE);
|
|
}
|
|
|
|
unsigned int* sort(unsigned char* ints, int size)
|
|
{
|
|
unsigned char MAX = 0xff;
|
|
|
|
unsigned int* out = malloc(sizeof(int) * size);
|
|
unsigned char* buf = malloc(size);
|
|
memcpy(buf, ints, sizeof(char) * size);
|
|
|
|
for (int k = 0; k < size; k++)
|
|
{
|
|
int min = 0;
|
|
for (int i = 0; i < size; i++)
|
|
{
|
|
if (buf[min] == MAX || buf[i] < ints[min])
|
|
{
|
|
min = i;
|
|
}
|
|
}
|
|
buf[min] = MAX;
|
|
out[k] = min;
|
|
}
|
|
|
|
free(buf);
|
|
return out;
|
|
}
|
|
|
|
void print_huffman_tree(tree t)
|
|
{
|
|
for (int i = 0; i < t.size; i++)
|
|
{
|
|
printf("Symbol 0x%x = Code ", t.leaves[i].litteral);
|
|
print_bits(t.leaves[i].code, t.leaves[i].length);
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
int next_token(bitstream* bs, tree t)
|
|
{
|
|
// TODO handle if tmin is null elsewhere
|
|
int init = 0;
|
|
if (t.min > 0)
|
|
{
|
|
init = t.min - 1;
|
|
}
|
|
|
|
unsigned int base = get_bits(bs, init);
|
|
|
|
for (int k = t.min; k <= t.max; k++)
|
|
{
|
|
base += get_bits(bs, 1) << (k - 1);
|
|
|
|
for (int i = 0; i < t.size; i++)
|
|
{
|
|
if (t.leaves[i].length == k && t.leaves[i].code == base)
|
|
return t.leaves[i].litteral;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|