All pastes #2051305 Raw Edit

Stuff

public text v1 · immutable
#2051305 ·published 2011-04-27 19:49 UTC
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;
}