From deb22164d4bc55f0ff09661cde5895ccec219604 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matt=C3=A9o=20Delabre=20=E2=9C=8F?= Date: Sun, 20 Nov 2016 01:49:11 +0100 Subject: [PATCH] =?UTF-8?q?Support=20de=20la=20d=C3=A9compression?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 4 +++- inc/decompress.h | 8 +++++++ src/decompress.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ src/main.c | 15 ++++++-------- 4 files changed, 71 insertions(+), 10 deletions(-) create mode 100644 inc/decompress.h create mode 100644 src/decompress.c diff --git a/Makefile b/Makefile index ea96ee8..7cf4ea7 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ OUT=out/ # Configuration du compilateur CC=gcc -CFLAGS=-Wall -std=c99 -I$(INC) +CFLAGS=-Wall -std=c99 -I$(INC) -g # Objets et exécutables à construire PROG=huffman @@ -29,6 +29,8 @@ $(OUT)$(PROG): $(OBJECTS) $(OUT)buffer.o: $(SRC)buffer.c $(INC)buffer.h $(OUT)compress.o: $(SRC)compress.c $(INC)compress.h $(INC)common.h \ $(INC)display.h +$(OUT)decompress.o: $(SRC)decompress.c $(INC)decompress.h $(INC)buffer.h \ + $(INC)display.h $(INC)huftree.h $(OUT)display.o: $(SRC)display.c $(INC)display.h $(INC)common.h $(OUT)huftree.o: $(SRC)huftree.c $(INC)huftree.h $(INC)common.h $(OUT)main.o: $(SRC)main.c $(INC)compress.h $(INC)common.h diff --git a/inc/decompress.h b/inc/decompress.h new file mode 100644 index 0000000..c3fb056 --- /dev/null +++ b/inc/decompress.h @@ -0,0 +1,8 @@ +#ifndef __IN303_DECOMPRESS_H__ +#define __IN303_DECOMPRESS_H__ + +#include + +void decompress(FILE* source, FILE* dest); + +#endif diff --git a/src/decompress.c b/src/decompress.c new file mode 100644 index 0000000..4a818fe --- /dev/null +++ b/src/decompress.c @@ -0,0 +1,54 @@ +#include "huftree.h" +#include "buffer.h" +#include "display.h" +#include "decompress.h" + +void decompress(FILE* source, FILE* dest) { + // ÉTAPE 1 : lecture du nombre de caractères originel. Cela permet + // d'ignorer les bits d'alignement en fin de fichier + size_t original_count = 0; + fread(&original_count, sizeof(size_t), 1, source); + printVerbose("Lecture du nombre de caractères : %d.\n", original_count); + + // ÉTAPE 2 : reconstruction de l'arbre à partir des données linéarisées + printVerbose("Reconstruction de l'arbre de Huffman.\n"); + ReadBuffer input = createReadBuffer(source); + HufTree tree = readTree(&input); + + if (isVerbose()) { + printTree(tree); + } + + // ÉTAPE 3 : lecture des données compressées et interprétation grâce + // à l'arbre de Huffman reconstitué + printVerbose("\nLecture et interprétation des données compressées.\n"); + char next_bit = getBuffer(&input); + size_t wrote_count = 0; + + while (next_bit != -1 && wrote_count < original_count) { + HufTree current = tree; + + // Descente dans l'arbre, allant à gauche si un '0' est rencontré + // ou à droite si un '1' est rencontré. Arrêt dès l'arrivée sur + // une feuille + while ( + next_bit != -1 && + current->child_l != NULL && current->child_r != NULL + ) { + if (next_bit == 0) { + current = current->child_l; + } else { + current = current->child_r; + } + + next_bit = getBuffer(&input); + } + + // La valeur de la feuille trouvée est le caractère compressé : + // on l'écrit dans le fichier + fputc(current->name, dest); + wrote_count++; + } + + freeTree(tree); +} diff --git a/src/main.c b/src/main.c index dc166c6..4dd541f 100644 --- a/src/main.c +++ b/src/main.c @@ -1,6 +1,7 @@ #include "common.h" #include "display.h" #include "compress.h" +#include "decompress.h" #include #include @@ -72,10 +73,7 @@ static error_t parse_opt(int key, char* arg, struct argp_state* state) { case ARGP_KEY_END: if (state->arg_num < 1) { - argp_error( - state, "Fichier d'entrée manquant (le premier argument " - " est obligatoire)" - ); + argp_error(state, "Fichier d'entrée manquant"); } break; @@ -102,7 +100,7 @@ static struct argp_option options[] = { { .name = "decompress", .key = 'd', - .doc = "Décompresse SOURCE vers DEST" + .doc = "Décompresse SOURCE vers DEST au lieu de compresser" }, { .name = "verbose", @@ -116,8 +114,8 @@ static struct argp argp = { .options = options, .parser = parse_opt, .args_doc = "SOURCE [DEST]", - .doc = "Compresse ou décompresse SOURCE vers DEST en utilisant " - "l'algorithme de Huffman (par défaut, compresse SOURCE vers DEST)." + .doc = "Compresse SOURCE vers DEST (par défaut, vers la sortie standard) " + "en utilisant l'algorithme de Huffman" }; int main(int argc, char** argv) { @@ -147,8 +145,7 @@ int main(int argc, char** argv) { if (args.compress) { compress(args.source, args.dest); } else { - fprintf(stderr, "Décompression non-implémentée.\n"); - return EXIT_FAILURE; + decompress(args.source, args.dest); } // Fermeture des flux et sortie