diff --git a/.gitignore b/.gitignore index 822895d828941cf6cc60f68aaac31b7dfd40462b..5e7833aef76bb4f56b5e7c1e6513f374d3581dee 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ myzip0 myunzip0 +inflate +huffman \ No newline at end of file diff --git a/Makefile b/Makefile index f1e3ca95a2c8efeeceae703a15d25fb8fef20608..026c9f2dcc8e15242d1b59b253eac0615a2e04de 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,10 @@ -all : myzip0 myunzip0 +all : myzip0 myunzip0 huffman myzip0 : myzip0.c cc myzip0.c -o myzip0 myunzip0 : myunzip0.c - cc myunzip0.c -o myunzip0 \ No newline at end of file + cc myunzip0.c -o myunzip0 + +huffman : huffman.c + cc huffman.c -o huffman \ No newline at end of file diff --git a/example.bin b/example.bin new file mode 100644 index 0000000000000000000000000000000000000000..d90011ece84dbdabf09793470f1a9869757aa9cb --- /dev/null +++ b/example.bin @@ -0,0 +1 @@ +"3DUfwˆ™ª»ÌÝîÿ \ No newline at end of file diff --git a/huffman.c b/huffman.c new file mode 100644 index 0000000000000000000000000000000000000000..527f74177b08cff9c30b2609b1f57d27f14ca7a0 --- /dev/null +++ b/huffman.c @@ -0,0 +1,115 @@ +#include <stdlib.h> +#include <stdio.h> +#include <stdbool.h> +#include <stdint.h> +#include <string.h> +#include <assert.h> + +/* A struct for writing to files as + streams of individual bits */ + +typedef struct __bit_writer +{ + FILE *file; + uint8_t byte; + int mod; +} bit_writer; + +bit_writer *bit_writer_init(FILE *file) +{ + bit_writer *bw = malloc(sizeof(bit_writer)); + assert(bw); + bw->file = file; + bw->byte = 0; + bw->mod = 0; + return bw; +} + +void bit_writer_free(bit_writer *bw) +{ + free(bw); +} + +void bit_writer_write_bit(bit_writer *bw, bool bit) +{ + bw->byte |= (bit > 0) << (bw->mod++); + + if (bw->mod == 8) + { + fwrite(&bw->byte, 1, 1, bw->file); + bw->byte = 0; + bw->mod = 0; + } +} + +void bit_writer_flush(bit_writer *bw) +{ + while (bw->mod != 0) bit_writer_write_bit(bw, 0); +} + +void write_byte(bit_writer *bw, uint8_t byte) +{ + + if (byte <= 143) /* 8 bit encoding */ + { + uint32_t to_encode = 0x30 + (uint32_t) byte; + for (int b = 8 - 1; b >= 0; b--) + bit_writer_write_bit(bw, to_encode & (1 << b)); + } else /* 9 bit encoding */ + { + uint32_t to_encode = 0x100 + (uint32_t) byte; + for (int b = 9 - 1; b >= 0; b--) + { + // bool to_write = () != 0; + // printf("Writing %d\n", to_write); + bit_writer_write_bit(bw, to_encode & (1 << b)); + } + } +} + +int main(int argc, char *argv[]) +{ + if (argc != 2) + { + printf("Usage: %s <input file>\n", argv[0]); + exit(1); + } + + char *input_file_name = argv[1]; + char *output_file_name = malloc(sizeof(char) * + (strlen(input_file_name) + strlen(".deflate") + 1)); + sprintf(output_file_name, "%s.deflate", input_file_name); + + FILE *input_file = fopen(input_file_name, "r"); + FILE *output_file = fopen(output_file_name, "w"); + free(output_file_name); + bit_writer *bw = bit_writer_init(output_file); + + + + bit_writer_write_bit(bw, 1); /* BFINAL */ + + bit_writer_write_bit(bw, 1); /* BTYPE */ + bit_writer_write_bit(bw, 0); + + // write_byte(bw, 144); + + char c; + while (fread(&c, 1, 1, input_file)) + { + // printf("Writing %d\n", (int) c); + write_byte(bw, c); + } + + for (int i = 0; i < 7; i++) + bit_writer_write_bit(bw, 0); + + bit_writer_flush(bw); + bit_writer_free(bw); + fclose(output_file); + fclose(input_file); + + + + return 0; +} \ No newline at end of file