178 lines
3.7 KiB
C
178 lines
3.7 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
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);
|
|
} |