rendered paste body#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
// copyright of capisce
uint32_t read_uint32(FILE *fp)
{
int32_t value;
fread(&value, 4, 1, fp);
return ntohl(value);
}
uint16_t read_uint16(FILE *fp)
{
uint16_t value;
fread(&value, 2, 1, fp);
return ntohs(value);
}
typedef int (*max_heap_less_than_func)(void *a, void *b);
typedef struct max_heap
{
void **data;
int size;
max_heap_less_than_func less_than;
} max_heap;
void max_heap_init(max_heap *heap, void **storage, max_heap_less_than_func less_than)
{
heap->data = storage;
heap->size = 0;
heap->less_than = less_than;
}
void max_heap_swap(void **a, void **b)
{
void *temp = *a;
*a = *b;
*b = temp;
}
void max_heap_insert(max_heap *heap, void *node)
{
heap->size++;
int index = heap->size - 1;
heap->data[index] = node;
while (index > 0) {
int parent = ((index+1) / 2) - 1;
if (!heap->less_than(heap->data[parent], heap->data[index]))
break;
max_heap_swap(&heap->data[parent], &heap->data[index]);
index = parent;
}
}
void max_heapify(max_heap *heap, int index)
{
int right_child = (index + 1) * 2;
int left_child = right_child - 1;
int largest = index;
if (left_child < heap->size && heap->less_than(heap->data[largest], heap->data[left_child]))
largest = left_child;
if (right_child < heap->size && heap->less_than(heap->data[largest], heap->data[right_child]))
largest = right_child;
if (largest != index) {
max_heap_swap(&heap->data[index], &heap->data[largest]);
max_heapify(heap, largest);
}
}
void *max_heap_remove(max_heap *heap)
{
if (heap->size == 0)
return 0;
void *node = heap->data[0];
heap->size--;
heap->data[0] = heap->data[heap->size];
if (heap->size > 1)
max_heapify(heap, 0);
return node;
}
typedef struct huffman_node
{
uint8_t value;
uint32_t frequency;
struct huffman_node *child[2];
} huffman_node;
int huffman_node_less_than(void *a, void *b)
{
huffman_node *ha = (huffman_node *)a;
huffman_node *hb = (huffman_node *)b;
if (ha->frequency == hb->frequency)
return ha->value > hb->value;
return ha->frequency > hb->frequency;
}
huffman_node *huffman_node_init(huffman_node *node, uint8_t value, uint32_t frequency)
{
node->value = value;
node->frequency = frequency;
node->child[0] = 0;
node->child[1] = 0;
return node;
}
huffman_node *huffman_node_combine(huffman_node *node, huffman_node *a, huffman_node *b)
{
node->frequency = a->frequency + b->frequency;
int index = huffman_node_less_than((void *)a, (void *)b);
node->child[index] = a;
node->child[!index] = b;
node->value = node->child[node->child[0]->value > node->child[1]->value]->value;
return node;
}
typedef struct bit_input_stream
{
FILE *fp;
int remaining;
uint8_t current;
} bit_input_stream;
void bit_input_stream_init(bit_input_stream *stream, FILE *fp)
{
stream->fp = fp;
stream->remaining = 0;
stream->current = 0;
}
int bit_input_stream_next(bit_input_stream *stream)
{
if (stream->remaining == 0) {
fread(&stream->current, 1, 1, stream->fp);
stream->remaining = 8;
}
stream->remaining--;
return (stream->current >> stream->remaining) & 1;
}
char decode_next(huffman_node *tree, bit_input_stream *stream)
{
while (tree->child[0] != 0)
tree = tree->child[bit_input_stream_next(stream)];
return tree->value;
}
void huffman_decode(huffman_node *tree, uint32_t decoded_length, FILE *fp)
{
bit_input_stream stream;
bit_input_stream_init(&stream, fp);
while (decoded_length--)
printf("%c", decode_next(tree, &stream));
}
huffman_node *huffman_build(huffman_node *tree_store, FILE *fp)
{
huffman_node *heap_store[256];
max_heap heap;
max_heap_init(&heap, (void **)heap_store, huffman_node_less_than);
int i;
for (i = 0; i < 256; ++i)
max_heap_insert(&heap, huffman_node_init(&tree_store[i], i, read_uint16(fp)));
huffman_node *tree;
for (;;) {
tree = max_heap_remove(&heap);
huffman_node *next = max_heap_remove(&heap);
if (next == 0)
break;
max_heap_insert(&heap, huffman_node_combine(&tree_store[i++], tree, next));
}
return tree;
}
int main(int argc, char **argv)
{
if (argc < 2) {
fprintf(stderr, "Usage: %s filename\n", argv[0]);
return -1;
}
FILE *fp = fopen(argv[1], "r");
if (!fp) {
fprintf(stderr, "Couldn't open %s, aborting\n", argv[1]);
return -1;
}
uint32_t decoded_length = read_uint32(fp);
huffman_node tree_nodes[511];
huffman_decode(huffman_build(tree_nodes, fp), decoded_length, fp);
fclose(fp);
return 0;
}