diff options
| author | Jan Sucan <jan@jansucan.com> | 2024-12-28 11:52:13 +0100 |
|---|---|---|
| committer | Ján Sučan <jan@jansucan.com> | 2024-12-31 08:26:48 +0100 |
| commit | e34296bbaa3b80a9c5c1bf6dba3ada28016f03de (patch) | |
| tree | 88c4302c93ee9c0ef8946a0fc305774c4d7d22be /src | |
| parent | 9280ff2c747a5a59f0a6e0cc6335b24de62cacc9 (diff) | |
Use options instead of positional arguments for file paths
Diffstat (limited to 'src')
| -rw-r--r-- | src/options.cpp | 184 |
1 files changed, 123 insertions, 61 deletions
diff --git a/src/options.cpp b/src/options.cpp index 280d5c6..66a8c69 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -86,11 +86,12 @@ OptionsRestore::getOutFilePath() const void OptionParser::printUsage() { - std::cout << "Usage: " << PROGRAM_NAME_STR << " backup [-s SECTOR_SIZE]"; - std::cout << " [-b BUFFER_SIZE] INFILE BASEFILE OUTFILE" << std::endl; + std::cout << "Usage: " << PROGRAM_NAME_STR << " backup [-S SECTOR_SIZE]"; + std::cout << " [-B BUFFER_SIZE] -i INFILE -b BASEFILE -o OUTFILE" + << std::endl; - std::cout << " Or: " << PROGRAM_NAME_STR << " restore [-s SECTOR_SIZE]"; - std::cout << "[-b BUFFER_SIZE] DIFFFILE OUTFILE" << std::endl; + std::cout << " Or: " << PROGRAM_NAME_STR << " restore [-S SECTOR_SIZE]"; + std::cout << "[-B BUFFER_SIZE] -d DIFFFILE -o OUTFILE" << std::endl; std::cout << " Or: " << PROGRAM_NAME_STR << " help" << std::endl; } @@ -118,82 +119,118 @@ OptionParser::parseBackup(int argc, char **argv) { OptionsBackup opts; - parse_common(&argc, &argv, opts); + // Skip the executable name. Do not skip the operation name. getopt expects + // to start at an argument immediately preceding the possible options. + argc -= 1; + argv += 1; - if (argc < 3) { - throw OptionError("missing arguments"); - } else if (argc > 3) { - throw OptionError("too many arguments"); - } else { - opts.in_file_path = next_arg(&argv); - opts.base_file_path = next_arg(&argv); - opts.out_file_path = next_arg(&argv); - } + int ch; + const char *arg_sector_size = NULL; + const char *arg_buffer_size = NULL; + const char *arg_input_file = NULL; + const char *arg_base_file = NULL; + const char *arg_output_file = NULL; - return opts; -} + while ((ch = getopt(argc, argv, ":B:S:i:b:o:")) != -1) { + switch (ch) { + case 'B': + arg_buffer_size = optarg; + break; -OptionsRestore -OptionParser::parseRestore(int argc, char **argv) -{ - OptionsRestore opts; + case 'S': + arg_sector_size = optarg; + break; - parse_common(&argc, &argv, opts); + case 'i': + arg_input_file = optarg; + break; - if (argc < 2) { - throw OptionError("missing arguments"); - } else if (argc > 2) { - throw OptionError("too many arguments"); - } else { - opts.diff_file_path = next_arg(&argv); - opts.out_file_path = next_arg(&argv); - } + case 'b': + arg_base_file = optarg; + break; - return opts; -} + case 'o': + arg_output_file = optarg; + break; -bool -OptionParser::isOperation(int argc, char **argv, std::string_view operationName) -{ - return ((argc >= 2) && - (strncmp(argv[1], operationName.data(), - OptionParser::MAX_OPERATION_NAME_LENGTH) == 0)); -} + case ':': + throw OptionError("missing argument for option '-" + + std::string(1, optopt) + "'"); + default: + throw OptionError("unknown option '-" + std::string(1, optopt) + + "'"); + } + } -int -OptionParser::parse_unsigned(const char *const arg, uint32_t *const value) -{ - char *end; + argc -= optind; + argv += optind; - errno = 0; + /* Convert numbers in the arguments */ + if ((arg_sector_size != NULL) && + parse_unsigned(arg_sector_size, &(opts.sector_size))) { + throw OptionError("incorrect sector size"); + } else if ((arg_buffer_size != NULL) && + parse_unsigned(arg_buffer_size, &(opts.buffer_size))) { + throw OptionError("incorrect buffer size"); + } else if (opts.sector_size == 0) { + throw OptionError("sector size cannot be 0"); + } else if (opts.buffer_size == 0) { + throw OptionError("buffer size cannot be 0"); + } else if (opts.sector_size > opts.buffer_size) { + throw OptionError("sector size cannot larger than buffer size"); + } else if ((opts.buffer_size % opts.sector_size) != 0) { + throw OptionError("buffer size is not multiple of sector size"); + } - *value = strtoul(arg, &end, 0); + if (arg_input_file == NULL) { + throw OptionError("missing input file"); + } else if (arg_base_file == NULL) { + throw OptionError("missing base file"); + } else if (arg_output_file == NULL) { + throw OptionError("missing output file"); + } else if (argc != 0) { + throw OptionError("too many arguments"); + } - return ((*end != '\0') || (errno != 0)) ? -1 : 0; + opts.in_file_path = arg_input_file; + opts.base_file_path = arg_base_file; + opts.out_file_path = arg_output_file; + + return opts; } -void -OptionParser::parse_common(int *const argc, char ***const argv, Options &opts) +OptionsRestore +OptionParser::parseRestore(int argc, char **argv) { - // Skip the executable name. Do not skip the operation name. getopt expects - // to start at an argument immediately preceding the possible options. - *argc -= 1; - *argv += 1; + OptionsRestore opts; + + argc -= 1; + argv += 1; int ch; const char *arg_sector_size = NULL; const char *arg_buffer_size = NULL; + const char *arg_diff_file = NULL; + const char *arg_output_file = NULL; - while ((ch = getopt(*argc, *argv, ":b:s:")) != -1) { + while ((ch = getopt(argc, argv, ":B:S:d:o:")) != -1) { switch (ch) { - case 'b': + case 'B': arg_buffer_size = optarg; break; - case 's': + case 'S': arg_sector_size = optarg; break; + case 'd': + arg_diff_file = optarg; + break; + + case 'o': + arg_output_file = optarg; + break; + case ':': throw OptionError("missing argument for option '-" + std::string(1, optopt) + "'"); @@ -203,8 +240,8 @@ OptionParser::parse_common(int *const argc, char ***const argv, Options &opts) } } - *argc -= optind; - *argv += optind; + argc -= optind; + argv += optind; /* Convert numbers in the arguments */ if ((arg_sector_size != NULL) && @@ -222,12 +259,37 @@ OptionParser::parse_common(int *const argc, char ***const argv, Options &opts) } else if ((opts.buffer_size % opts.sector_size) != 0) { throw OptionError("buffer size is not multiple of sector size"); } + + if (arg_diff_file == NULL) { + throw OptionError("missing diff file"); + } else if (arg_output_file == NULL) { + throw OptionError("missing output file"); + } else if (argc != 0) { + throw OptionError("too many arguments"); + } + + opts.diff_file_path = arg_diff_file; + opts.out_file_path = arg_output_file; + + return opts; } -const char * -OptionParser::next_arg(char ***const argv) +bool +OptionParser::isOperation(int argc, char **argv, std::string_view operationName) { - const char *arg = **argv; - ++(*argv); - return arg; + return ((argc >= 2) && + (strncmp(argv[1], operationName.data(), + OptionParser::MAX_OPERATION_NAME_LENGTH) == 0)); +} + +int +OptionParser::parse_unsigned(const char *const arg, uint32_t *const value) +{ + char *end; + + errno = 0; + + *value = strtoul(arg, &end, 0); + + return ((*end != '\0') || (errno != 0)) ? -1 : 0; } |
