surfaces-unies/src/main.c
2018-11-27 23:59:04 +01:00

151 lines
5.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* \file main.c
* \brief Fichier principal du programme
*
* Ce fichier contient les fonctions principales du logiciel qui ne sont pas
* directement liées à la logique et au traitement des données du logiciel,
* mais plutôt au traitement des arguments passés au processus et au lancement
* des fonctions cœures du programme.
*/
#include "compress.h"
#include "uncompress.h"
#include <getopt.h>
#include <string.h>
/**
* \brief Affiche un message d'aide
*
* Affiche un message d'aide pour le logiciel ainsi que son utilisation, puis
* termine le processus avec le code de sortie indiqué par l'argument de la
* fonction.
*
* \param[in] t_exit_code Code de sortie du processus
*/
void help(int t_exit_code) {
puts("Usage:\n"
"surfaces-unies -i path [-o path] [--options] [-t 0-100]\n\n"
"The default action is to compress the mandatory input image to a .su\n"
"file saved in the current directory.\n"
"The input image MUST be saved in the ppm format.\n"
"Options available:\n"
"-h --help\n\tDisplay the current message\n"
"-i --input\n\tPath to the input file (MANDATORY)\n"
"-o --output\n"
"\tPath to the output file (if the file already exists, it will be\n"
"\toverwritten)\n"
"-t --tolerance\n"
"\tColor tolerance for lossy compression. By default at 0 for lossless\n"
"\tcompression, at 100 will consider every color to be the same.\n"
"-c --compress\n\tCompress the input file\n"
"-u --uncompress\n\tUncompresses the input file to the output file.");
exit(t_exit_code);
}
/**
* \struct Argres
* \brief Résultats du traitement des arguments du processus
*
* Cette structure est utilisée pour consolider ensemble les résultats du
* traitement des arguments et les renvoyer en une fois au lieu d'avoir à
* utiliser des variables globales ou des pointeurs en arguments
* supplémentaires aux fonctions.
*/
struct Argres {
char *input; /*!< Nom du fichier d'entrée */
char *output; /*!< Nom du fichier de sortie */
char compress; /*!< Le fichier d'entrée doit-il être compressé ? */
int32_t tolerance; /*!< Tolérance en pourcentage des différences de couleur */
};
typedef struct Argres Argres;
/**
* \brief Processes independently the arguments of the process
*
* Each option and switch will be processed here and will modify appropriately
* the parameter `args`
*
* \param[out] t_args Result of the arguments processing
* \param[in] t_c Switch or option passed
*/
void get_args(Argres *t_args, const int *const t_c) {
switch (*t_c) {
case 0: break;
case 'h': help(NOERROR); break;
case 'i': (*t_args).input = optarg; break;
case 'o': (*t_args).output = optarg; break;
case 'c': (*t_args).compress = 1; break;
case 'u': (*t_args).compress = 0; break;
case 't':
(*t_args).tolerance = atoi(optarg);
if(t_args->tolerance < 0 || t_args->tolerance > 100) {
help(ARGERROR);
}
break;
case '?':
default: help(ARGERROR);
}
}
/**
* \brief Traite les arguments passés au processus
*
* Les arguments passés au processus seront traités ici. Les arguments passés
* dans cette fonction ne subiront aucune modification. La fonction renvoie une
* structure \ref Argres contenant le nom de fichier dentrée et de sortie
* ainsi quun booléen indiquant si le fichier dentrée doit être compressé ou
* décompressé.
*
* \param[in] t_argc Nombre darguments reçus
* \param[in] t_argv Arguments reçus par le processus
* \return structure \ref Argres
*/
Argres process_args(const int t_argc, char *t_argv[]) {
Argres res;
res.input = NULL;
res.compress = 1;
res.output = NULL;
res.tolerance = 0;
while (1) {
int option_index = 0;
static struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"input", required_argument, NULL, 'i'},
{"output", required_argument, NULL, 'o'},
{"tolerance", required_argument, NULL, 't'},
{"compress", no_argument, NULL, 'c'},
{"uncompress", no_argument, NULL, 'u'},
{NULL, 0, NULL, 0}};
int c = getopt_long(t_argc, t_argv, "hi:o:t:cu", long_options, &option_index);
if (c == -1)
break;
get_args(&res, &c);
}
return res;
}
/**
* \brief Fonction `main` lancée avec le processus
*
* This function is launched with the process. It will analyze the arguments it
* received, and depending on them will either compress or uncompress the input
* file, or will throw an error and stop in case of incorrect arguments.
*
* \param[in] argc Nombre darguments reçus par le processus
* \param[in] argv Tableau des arguments reçus par le processus
* \return Code de status du processus
*/
int main(int argc, char **argv) {
Argres argresults = process_args(argc, argv);
if (NULL == argresults.input) {
fprintf(stderr, "ERROR: no input file.");
help(ARGERROR);
}
if (argresults.compress) {
compress(argresults.input, argresults.output, argresults.tolerance);
} else {
uncompress(argresults.input, argresults.output);
}
return 0;
}