diff --git a/sk1/program.c b/sk1/program.c new file mode 100644 index 0000000..1b6a172 --- /dev/null +++ b/sk1/program.c @@ -0,0 +1,178 @@ +#include +#include + +struct node{ + struct node* children[256]; + unsigned char size; + unsigned char character; + unsigned char pos; + + //Not used in encoding + struct node* parent; +}; + +typedef struct node* node; + +void compress(FILE* in, FILE* out); +void decompress(FILE* in, FILE* out); + +int main(int argc, char* argv[]){ + if(argc < 4){ + printf("Choose option and files!\n"); + printf("Options:\n\tc for compress\n\td for decompress\n"); + return 0; + } + + FILE* in = fopen(argv[2], "r"); + FILE* out = fopen(argv[3], "w"); + + if(argv[1][0] == 'c'){ + compress(in, out); + } + else{ + decompress(in, out); + } + + fclose(in); + fclose(out); +} + + +node create_node(unsigned char character, unsigned char pos){ + node new = malloc(sizeof(struct node)); + new->character = character; + new->pos = pos; + new->size = 0; + return new; +} + + +node find_parent_enc(node root, unsigned char character){ + for(int i = 0; i < root->size; i++){ + if(root->children[i]->character == character){ + return root->children[i]; + } + } + return NULL; +} + + +void recursive_free(node tree){ + if(tree != NULL){ + for(int i = 0; i < tree->size; i++){ + recursive_free(tree->children[i]); + } + free(tree); + } +} + +void free_tree(node tree){ + for(int i = 0; i < tree->size; i++){ + recursive_free(tree->children[i]); + } + tree->size = 0; +} + + +void enc_write(unsigned char pos, char character, FILE* out){ + fputc(pos, out); + fputc(character, out); +} + + +void compress(FILE* in, FILE* out){ + node root = create_node(0, 0); + + unsigned char pos = 1; + unsigned char character; + + node parent = root; + + + while(fread(&character, 1, 1, in) > 0){ + node parent_copy = parent; + parent = find_parent_enc(parent_copy, character); + if(parent == NULL){ + node new = create_node(character, pos); + parent_copy->children[parent_copy->size] = new; + enc_write(parent_copy->pos, parent_copy->children[parent_copy->size]->character, out); + parent_copy->size += 1; + pos++; + if(pos >= 255){ + pos = 1; + free_tree(root); + } + parent = root; + } + } + + if(parent != root){ + fputc(parent->pos, out); + } + + free_tree(root); + free(root); +} + + +node find_parent_dec(unsigned char pos, node tree){ + if(pos == 0 || tree == NULL){ + return NULL; + } + else if(tree->pos == pos){ + return tree; + } + + for(int i = 0; i < tree->size; i++){ + node child = find_parent_dec(pos, tree->children[i]); + if(child != NULL){ + return child; + } + } + return NULL; +} + +void dec_write(node element, FILE* out){ + if(element->parent != NULL){ + dec_write(element->parent, out); + fputc(element->character, out); + } +} +void decompress(FILE* in, FILE* out){ + int res = 0; + node root = create_node(0, 0); + + unsigned short pos = 1; + unsigned char character; + unsigned char parent_pos; + + while(fread(&parent_pos, 1, 1, in) > 0 && fread(&character, 1, 1, in) > 0){ + node parent = find_parent_dec(parent_pos, root); + if(parent == NULL){ + parent = root; + } + + node new = create_node(character, pos); + pos++; + + new->parent = parent; + parent->children[parent->size] = new; + parent->size += 1; + parent_pos = 0; + + dec_write(new, out); + if(pos >= 255){ + free_tree(root); + res++; + pos = 1; + } + } + + if(parent_pos != 0){ + node last = find_parent_dec(parent_pos, root); + dec_write(last, out); + } + + free_tree(root); + free(root); +} \ No newline at end of file