#include #include #include // 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_swap(void **a, void **b) { void *temp = *a; *a = *b; *b = temp; } 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; 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]; heap->data = realloc(heap->data, heap->size * sizeof(void *)); 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_create(uint8_t value, uint32_t frequency) { huffman_node *node = (huffman_node *)malloc(sizeof(huffman_node)); node->value = value; node->frequency = frequency; node->child[0] = 0; node->child[1] = 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; 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; } 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; }