157 lines
3.7 KiB
C
157 lines
3.7 KiB
C
#include "common.h"
|
|
#include "display.h"
|
|
#include "compress.h"
|
|
#include "decompress.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <argp.h>
|
|
#include <libintl.h>
|
|
#include <locale.h>
|
|
#include <string.h>
|
|
|
|
/**
|
|
* Contient les valeurs des arguments (options et opérandes)
|
|
* passées au programme et interprétées via Argp
|
|
*/
|
|
typedef struct Args {
|
|
int verbose;
|
|
int compress;
|
|
FILE* source;
|
|
FILE* dest;
|
|
} Args;
|
|
|
|
/**
|
|
* Fonction de rappel pour interpréter les arguments
|
|
* passés au programme
|
|
*/
|
|
static error_t parse_opt(int key, char* arg, struct argp_state* state) {
|
|
Args* args = state->input;
|
|
|
|
switch (key) {
|
|
case 'v':
|
|
args->verbose = TRUE;
|
|
break;
|
|
|
|
case 'd':
|
|
args->compress = FALSE;
|
|
break;
|
|
|
|
case ARGP_KEY_ARG:
|
|
switch (state->arg_num) {
|
|
case 0:
|
|
// Premier argument : fichier d'entrée
|
|
args->source = fopen(arg, "rb");
|
|
|
|
if (args->source == NULL) {
|
|
argp_error(
|
|
state, "%s: %s",
|
|
arg, strerror(errno)
|
|
);
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
// Second argument : fichier de sortie. Si omis,
|
|
// utilisation de la sortie standard
|
|
args->dest = fopen(arg, "wb");
|
|
|
|
if (args->dest == NULL) {
|
|
argp_error(
|
|
state, "%s: %s",
|
|
arg, strerror(errno)
|
|
);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
argp_error(
|
|
state, "Trop d'arguments (l'argument %s est superflu)",
|
|
arg
|
|
);
|
|
}
|
|
break;
|
|
|
|
case ARGP_KEY_END:
|
|
if (state->arg_num < 1) {
|
|
argp_error(state, "Fichier d'entrée manquant");
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return ARGP_ERR_UNKNOWN;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Nom, version du programme et adresse pour les bugs
|
|
* (ces informations sont affichées dans l'aide)
|
|
*/
|
|
const char *argp_program_version = "huffman v0.1";
|
|
const char *argp_program_bug_address =
|
|
"<matteo.delabre@etu.umontpellier.fr>";
|
|
|
|
/**
|
|
* Définition de la configuration de Argp, qui affichera
|
|
* ces informations dans la page d'aide entre autres
|
|
*/
|
|
static struct argp_option options[] = {
|
|
{
|
|
.name = "decompress",
|
|
.key = 'd',
|
|
.doc = "Décompresse SOURCE vers DEST au lieu de compresser"
|
|
},
|
|
{
|
|
.name = "verbose",
|
|
.key = 'v',
|
|
.doc = "Affiche des informations de débogage"
|
|
},
|
|
{0}
|
|
};
|
|
|
|
static struct argp argp = {
|
|
.options = options,
|
|
.parser = parse_opt,
|
|
.args_doc = "SOURCE [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) {
|
|
// Paramètres de langue. Utilisation de la locale de l'utilisateur,
|
|
// et des messages traduits dans libc (pour pallier à un bug de argp)
|
|
setlocale(LC_ALL, "");
|
|
textdomain("libc");
|
|
|
|
// Valeurs par défaut des arguments optionnels
|
|
Args args = {
|
|
.verbose = FALSE,
|
|
.compress = TRUE,
|
|
.source = NULL,
|
|
.dest = stdout
|
|
};
|
|
|
|
// Interprétation des arguments passés au programme, résultat
|
|
// dans `args`. Arrêt en cas d'erreur
|
|
if (argp_parse(&argp, argc, argv, 0, 0, &args)) {
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
// Passage en mode verbeux si demandé
|
|
setVerbose(args.verbose);
|
|
|
|
// Compression ou décompression du flux d'entrée vers le flux de sortie
|
|
if (args.compress) {
|
|
compress(args.source, args.dest);
|
|
} else {
|
|
decompress(args.source, args.dest);
|
|
}
|
|
|
|
// Fermeture des flux et sortie
|
|
fclose(args.source);
|
|
fclose(args.dest);
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|