diff --git a/libmineziper/CMakeLists.txt b/libmineziper/CMakeLists.txt index 350448e..c320497 100644 --- a/libmineziper/CMakeLists.txt +++ b/libmineziper/CMakeLists.txt @@ -5,12 +5,14 @@ set(libmineziper_STATIC_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/include) set(libmineziper_SRC ${libmineziper_STATIC_SRC}/libmineziper.c ${libmineziper_STATIC_SRC}/libmineziper_zip.c + ${libmineziper_STATIC_SRC}/libmineziper_huffman_tree.c ${libmineziper_STATIC_SRC}/libmineziper_bitstream.c ) set(libmineziper_INCLUDE ${libmineziper_STATIC_INCLUDE}/libmineziper.h ${libmineziper_STATIC_INCLUDE}/libmineziper_zip.h + ${libmineziper_STATIC_INCLUDE}/libmineziper_huffman_tree.h ${libmineziper_STATIC_INCLUDE}/libmineziper_bitstream.h ) diff --git a/libmineziper/include/libmineziper_huffman_tree.h b/libmineziper/include/libmineziper_huffman_tree.h new file mode 100644 index 0000000..7f58acb --- /dev/null +++ b/libmineziper/include/libmineziper_huffman_tree.h @@ -0,0 +1,25 @@ +#ifndef LIBMINEZIPER_HUFFMAN_TREE_H +#define LIBMINEZIPER_HUFFMAN_TREE_H + +#include "libmineziper_bitstream.h" + +typedef struct leaf +{ + int code; + short litteral; + char length; +} leaf; + +typedef struct tree +{ + leaf* leaves; + unsigned int size; + unsigned int min, max; +} tree; + +unsigned int* sort(unsigned char* ints, int size); +void print_huffman_tree(tree t); +tree build_tree(char* bit_lengths, int size); +tree build_default_tree(); + +#endif \ No newline at end of file diff --git a/libmineziper/src/libmineziper_huffman_tree.c b/libmineziper/src/libmineziper_huffman_tree.c new file mode 100644 index 0000000..c696721 --- /dev/null +++ b/libmineziper/src/libmineziper_huffman_tree.c @@ -0,0 +1,98 @@ +#include "libmineziper_huffman_tree.h" + +#include +#include +#include + +tree build_tree(char* bit_lenghts, int size) +{ + unsigned int* order_codes = sort(bit_lenghts, size); + + tree out; + out.size = size; + out.min = bit_lenghts[order_codes[0]]; + out.max = bit_lenghts[order_codes[size - 1]]; + out.leaves = malloc(sizeof(leaf) * size); + + int code = 0; + int code_incr = 0; + int last_bit_length = 0; + int i = 0; + int len_bit, j; + + while (i < size) + { + j = order_codes[i]; + len_bit = bit_lenghts[j]; + + code = code + code_incr; + if (len_bit != last_bit_length) + { + last_bit_length = len_bit; + code_incr = 1 << (16 - last_bit_length); + } + + out.leaves[j].code = reverse(code, 16); + out.leaves[j].length = len_bit; + out.leaves[j].litteral = j; + i++; + } + + free(order_codes); + return out; +} + +tree build_default_tree() +{ + char bit_lengths[288]; + + for (int i = 0; i < 288; i++) + { + if (i < 144 || i >= 280) + bit_lengths[i] = 8; + + else if (i >= 144 && i < 256) + bit_lengths[i] = 9; + + else + bit_lengths[i] = 7; + } + + return build_tree(bit_lengths, 288); +} + +unsigned int* sort(unsigned char* ints, int size) +{ + unsigned char MAX = 0xff; + + unsigned int* out = malloc(sizeof(int) * size); + unsigned char* buf = malloc(size); + memcpy(buf, ints, sizeof(char) * size); + + for (int k = 0; k < size; k++) + { + int min = 0; + for (int i = 0; i < size; i++) + { + if (buf[min] == MAX || buf[i] < ints[min]) + { + min = i; + } + } + buf[min] = MAX; + out[k] = min; + } + + free(buf); + return out; +} + +void print_huffman_tree(tree t) +{ + for (int i = 0; i < t.size; i++) + { + printf("Symbol 0x%x = Code ", t.leaves[i].litteral); + print_bits(t.leaves[i].code, t.leaves[i].length); + printf("\n"); + } +}