All pastes #2051027 Raw Edit

Mine

public text v1 · immutable
#2051027 ·published 2011-04-26 22:48 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, max_heap_less_than_func less_than)
{
    heap->data = malloc(0);
    heap->size = 0;
    heap->less_than = less_than;
}

void max_heap_destroy(max_heap *heap)
{
    free(heap->data);
    heap->data = 0;
    heap->size = 0;
}

void max_heap_insert(max_heap *heap, void *node)
{
    heap->size++;
    heap->data = realloc(heap->data, heap->size * sizeof(void *));

    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;

        void *temp = heap->data[parent];
        heap->data[parent] = heap->data[index];
        heap->data[index] = temp;

        index = parent;
    }
}

void max_heap_swap(void **a, void **b)
{
    void *temp = *a;
    *a = *b;
    *b = temp;
}

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];
    heap->data = realloc(heap->data, heap->size * sizeof(void *));

    void max_heapify(max_heap *heap, int index)
    {
        int left_child = (index + 1) * 2 - 1;
        int right_child = (index + 1) * 2;

        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);
        }
    }

    if (heap->size > 1)
        max_heapify(heap, 0);

    return node;
}

typedef struct huffman_node
{
    uint8_t value;
    uint32_t frequency;

    struct huffman_node *left;
    struct huffman_node *right;
} 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_create(uint8_t value, uint32_t frequency)
{
    huffman_node *node = (huffman_node *)malloc(sizeof(huffman_node));
    node->value = value;
    node->frequency = frequency;
    node->left = 0;
    node->right = 0;
    return node;
}

huffman_node *huffman_node_combine(huffman_node *a, huffman_node *b)
{
    huffman_node *node = (huffman_node *)malloc(sizeof(huffman_node));
    node->frequency = a->frequency + b->frequency;
    if (huffman_node_less_than((void *)a, (void *)b)) {
        node->left = b;
        node->right = a;
    } else {
        node->left = a;
        node->right = b;
    }
    node->value = node->left->value < node->right->value ? node->left->value : node->right->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)
{
    if (tree->left == 0 && tree->right == 0)
        return tree->value;

    huffman_node *next = bit_input_stream_next(stream) ? tree->right : tree->left;
    return decode_next(next, stream);
}

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);

    max_heap heap;
    max_heap_init(&heap, huffman_node_less_than);

    for (int i = 0; i < 256; ++i)
        max_heap_insert(&heap, huffman_node_create(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, next));
    }

    max_heap_destroy(&heap);

    bit_input_stream stream;
    bit_input_stream_init(&stream, fp);

    char *result = malloc(decoded_length + 1);

    for (int i = 0; i < decoded_length; ++i)
        result[i] = decode_next(tree, &stream);

    result[decoded_length] = '\0';

    printf("%s", result);

    free(result);

    fclose(fp);

    return 0;
}