huffman/src/main.c

157 lines
3.7 KiB
C
Raw Normal View History

2016-10-25 04:51:07 +00:00
#include "common.h"
2016-10-28 14:44:05 +00:00
#include "display.h"
2016-10-25 04:51:07 +00:00
#include "compress.h"
2016-11-20 00:49:11 +00:00
#include "decompress.h"
2016-10-28 14:44:05 +00:00
#include <stdlib.h>
2016-10-22 00:56:35 +00:00
#include <argp.h>
#include <libintl.h>
2016-10-22 00:56:35 +00:00
#include <locale.h>
2016-10-27 16:20:18 +00:00
#include <string.h>
2016-10-22 00:56:35 +00:00
/**
* 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;
2016-10-22 00:56:35 +00:00
} Args;
2016-10-22 00:56:35 +00:00
/**
* 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;
2016-10-22 00:56:35 +00:00
switch (key) {
case 'v':
args->verbose = TRUE;
break;
2016-10-22 00:56:35 +00:00
case 'd':
args->compress = FALSE;
break;
2016-10-22 00:56:35 +00:00
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;
2016-10-22 00:56:35 +00:00
default:
argp_error(
state, "trop d'arguments (l'argument %s, numéro %d "
"est superflu)", arg, state->arg_num + 1
);
}
break;
case ARGP_KEY_END:
if (state->arg_num < 1) {
argp_error(state, "fichier d'entrée manquant");
}
break;
default:
return ARGP_ERR_UNKNOWN;
2016-10-22 00:56:35 +00:00
}
return 0;
}
2016-10-22 00:56:35 +00:00
/**
* Nom, version du programme et adresse pour les bugs
* (ces informations sont affichées dans l'aide)
*/
const char *argp_program_version = "huffman 0.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"
},
{
.name = "verbose",
.key = 'v',
.doc = "Affiche des informations de débogage"
},
{0}
};
2016-10-22 00:56:35 +00:00
static struct argp argp = {
.options = options,
.parser = parse_opt,
.args_doc = "SOURCE [DEST]",
2016-11-20 00:49:11 +00:00
.doc = "Compresse SOURCE vers DEST (par défaut, vers la sortie standard) "
"en utilisant l'algorithme de Huffman"
};
2016-10-22 00:56:35 +00:00
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;
}
2016-10-22 00:56:35 +00:00
// 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 {
2016-11-20 00:49:11 +00:00
decompress(args.source, args.dest);
2016-10-22 00:56:35 +00:00
}
2016-10-27 16:20:18 +00:00
// Fermeture des flux et sortie
fclose(args.source);
fclose(args.dest);
2016-10-27 16:20:18 +00:00
return EXIT_SUCCESS;
2016-10-22 00:56:35 +00:00
}