aboutsummaryrefslogtreecommitdiff
path: root/src/options.cpp
diff options
context:
space:
mode:
authorJan Sucan <jan@jansucan.com>2024-03-24 16:22:08 +0100
committerJán Sučan <jan@jansucan.com>2024-03-24 16:25:41 +0100
commite86c9c6135ba0462c5a352e6d8ea4b730aa9c370 (patch)
tree0c1aa521d865c4a17576d1048692922d895112c9 /src/options.cpp
parentdde03ff8796277f6ed0f8c8e8b18b83b801d6d27 (diff)
Rewrite the option code in object-oriented way
Diffstat (limited to 'src/options.cpp')
-rw-r--r--src/options.cpp294
1 files changed, 129 insertions, 165 deletions
diff --git a/src/options.cpp b/src/options.cpp
index ecb1026..545d11a 100644
--- a/src/options.cpp
+++ b/src/options.cpp
@@ -26,136 +26,160 @@
#include "options.h"
-#include "print.h"
+#include <iostream>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include <cstring>
#include <unistd.h>
/* This header file is automatically generated at build time from the Makefile
*/
#include "program_info.h"
-#define OPTIONS_MAX_OPERATION_NAME_LENGTH 8
-#define OPTIONS_DEFAULT_SECTOR_SIZE 512
-#define OPTIONS_DEFAULT_BUFFER_SIZE (4 * 1024 * 1024)
-
-struct common_options {
- uint32_t sector_size;
- uint32_t buffer_size;
-};
-
-static int options_parse_unsigned(const char *const arg, uint32_t *const value);
-static void options_parse_operation(const char *const argv,
- options_t *const opts);
-static bool options_parse_common(int *const argc, char ***const argv,
- struct common_options *const opts);
-static bool options_parse_backup(int *const argc, char ***const argv,
- options_t *const opts);
-static bool options_parse_restore(int *const argc, char ***const argv,
- options_t *const opts);
-static const char *next_arg(char ***const argv);
+Options::Options()
+ : sector_size{Options::DEFAULT_SECTOR_SIZE},
+ buffer_size{Options::DEFAULT_BUFFER_SIZE}
+{
+}
-bool
-options_parse(int argc, char **argv, options_t *const opts)
+uint32_t
+Options::getSectorSize() const
{
- // Skip the executable name
- --argc;
- ++argv;
+ return sector_size;
+}
- options_parse_operation(argv[0], opts);
+uint32_t
+Options::getBufferSize() const
+{
+ return buffer_size;
+}
- if (options_is_operation(opts, OPERATION_ID_UNKNOWN)) {
- return false;
- }
+std::filesystem::path
+OptionsBackup::getInFilePath() const
+{
+ return in_file_path;
+}
- if (options_is_operation(opts, OPERATION_ID_BACKUP)) {
- if (!options_parse_backup(&argc, &argv, opts)) {
- return false;
- }
- } else if (options_is_operation(opts, OPERATION_ID_RESTORE)) {
- if (!options_parse_restore(&argc, &argv, opts)) {
- return false;
- }
- }
- return true;
+std::filesystem::path
+OptionsBackup::getRefFilePath() const
+{
+ return ref_file_path;
+}
+
+std::filesystem::path
+OptionsBackup::getOutFilePath() const
+{
+ return out_file_path;
+}
+
+std::filesystem::path
+OptionsRestore::getInFilePath() const
+{
+ return in_file_path;
+}
+
+std::filesystem::path
+OptionsRestore::getOutFilePath() const
+{
+ return out_file_path;
}
void
-options_usage(int exit_code)
+OptionParser::printUsage()
{
- printf("Usage: %s backup [-s SECTOR_SIZE] [-b BUFFER_SIZE] INFILE REFFILE "
- "OUTFILE\n",
- PROGRAM_NAME_STR);
- printf(" Or: %s restore [-s SECTOR_SIZE] [-b BUFFER_SIZE] REFFILE "
- "OUTFILE\n",
- PROGRAM_NAME_STR);
- printf(" Or: %s help\n", PROGRAM_NAME_STR);
- exit(exit_code);
+ std::cout << "Usage: " << PROGRAM_NAME_STR << " backup [-s SECTOR_SIZE]";
+ std::cout << " [-b BUFFER_SIZE] INFILE REFFILE OUTFILE" << std::endl;
+
+ std::cout << " Or: " << PROGRAM_NAME_STR << " restore [-s SECTOR_SIZE]";
+ std::cout << "[-b BUFFER_SIZE] REFFILE OUTFILE" << std::endl;
+
+ std::cout << " Or: " << PROGRAM_NAME_STR << " help" << std::endl;
}
bool
-options_is_operation(const options_t *const opts, operation_id_t operation_id)
+OptionParser::isHelp(int argc, char **argv)
{
- return (opts->operation_id == operation_id);
+ return isOperation(argc, argv, "help");
}
-const options_backup_t *
-options_get_for_backup(const options_t *const opts)
+bool
+OptionParser::isBackup(int argc, char **argv)
{
- return &(opts->op.backup);
+ return isOperation(argc, argv, "backup");
}
-const options_restore_t *
-options_get_for_restore(const options_t *const opts)
+bool
+OptionParser::isRestore(int argc, char **argv)
{
- return &(opts->op.restore);
+ return isOperation(argc, argv, "restore");
}
-static int
-options_parse_unsigned(const char *const arg, uint32_t *const value)
+OptionsBackup
+OptionParser::parseBackup(int argc, char **argv)
{
- char *end;
+ OptionsBackup opts;
- errno = 0;
+ parse_common(&argc, &argv, opts);
- *value = strtoul(arg, &end, 0);
+ 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.ref_file_path = next_arg(&argv);
+ opts.out_file_path = next_arg(&argv);
+ }
- return ((*end != '\0') || (errno != 0)) ? -1 : 0;
+ return opts;
}
-static void
-options_parse_operation(const char *const op_name, options_t *const opts)
+OptionsRestore
+OptionParser::parseRestore(int argc, char **argv)
{
- if (op_name == NULL) {
- opts->operation_id = OPERATION_ID_UNKNOWN;
- } else if (strncmp(op_name, "help", OPTIONS_MAX_OPERATION_NAME_LENGTH) ==
- 0) {
- opts->operation_id = OPERATION_ID_HELP;
- } else if (strncmp(op_name, "backup", OPTIONS_MAX_OPERATION_NAME_LENGTH) ==
- 0) {
- opts->operation_id = OPERATION_ID_BACKUP;
- } else if (strncmp(op_name, "restore", OPTIONS_MAX_OPERATION_NAME_LENGTH) ==
- 0) {
- opts->operation_id = OPERATION_ID_RESTORE;
+ OptionsRestore opts;
+
+ parse_common(&argc, &argv, opts);
+
+ if (argc < 2) {
+ throw OptionError("missing arguments");
+ } else if (argc > 2) {
+ throw OptionError("too many arguments");
} else {
- opts->operation_id = OPERATION_ID_UNKNOWN;
+ opts.in_file_path = next_arg(&argv);
+ opts.out_file_path = next_arg(&argv);
}
+
+ return opts;
+}
+
+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));
}
-static void
-options_init_common(struct common_options *const opts)
+int
+OptionParser::parse_unsigned(const char *const arg, uint32_t *const value)
{
- opts->sector_size = OPTIONS_DEFAULT_SECTOR_SIZE;
- opts->buffer_size = OPTIONS_DEFAULT_BUFFER_SIZE;
+ char *end;
+
+ errno = 0;
+
+ *value = strtoul(arg, &end, 0);
+
+ return ((*end != '\0') || (errno != 0)) ? -1 : 0;
}
-static bool
-options_parse_common(int *const argc, char ***const argv,
- struct common_options *const opts)
+void
+OptionParser::parse_common(int *const argc, char ***const argv, Options &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;
+
int ch;
char *arg_sector_size = NULL;
char *arg_buffer_size = NULL;
@@ -171,11 +195,11 @@ options_parse_common(int *const argc, char ***const argv,
break;
case ':':
- print_error("missing argument for option '-%c'", optopt);
- return false;
+ throw OptionError("missing argument for option '-" +
+ std::string(1, optopt) + "'");
default:
- print_error("unknown option '-%c'", optopt);
- return false;
+ throw OptionError("unknown option '-" + std::string(1, optopt) +
+ "'");
}
}
@@ -184,84 +208,24 @@ options_parse_common(int *const argc, char ***const argv,
/* Convert numbers in the arguments */
if ((arg_sector_size != NULL) &&
- options_parse_unsigned(arg_sector_size, &(opts->sector_size))) {
- print_error("incorrect sector size");
- return false;
+ parse_unsigned(arg_sector_size, &(opts.sector_size))) {
+ throw OptionError("incorrect sector size");
} else if ((arg_buffer_size != NULL) &&
- options_parse_unsigned(arg_buffer_size, &(opts->buffer_size))) {
- print_error("incorrect buffer size");
- return false;
- } else if (opts->sector_size == 0) {
- print_error("sector size cannot be 0");
- return false;
- } else if (opts->buffer_size == 0) {
- print_error("buffer size cannot be 0");
- return false;
- } else if (opts->sector_size > opts->buffer_size) {
- print_error("sector size cannot larger than buffer size");
- return false;
- } else if ((opts->buffer_size % opts->sector_size) != 0) {
- print_error("buffer size is not multiple of sector size");
- return false;
- }
-
- return true;
-}
-
-static bool
-options_parse_backup(int *const argc, char ***const argv, options_t *const opts)
-{
- struct common_options common_opts;
- options_init_common(&common_opts);
- if (!options_parse_common(argc, argv, &common_opts)) {
- return false;
- }
-
- if (*argc < 3) {
- print_error("missing arguments");
- return false;
- } else if (*argc > 3) {
- print_error("too many arguments");
- return false;
- } else {
- opts->op.backup.sector_size = common_opts.sector_size;
- opts->op.backup.buffer_size = common_opts.buffer_size;
- opts->op.backup.in_file_path = next_arg(argv);
- opts->op.backup.ref_file_path = next_arg(argv);
- opts->op.backup.out_file_path = next_arg(argv);
- }
-
- return true;
-}
-
-static bool
-options_parse_restore(int *const argc, char ***const argv,
- options_t *const opts)
-{
- struct common_options common_opts;
- options_init_common(&common_opts);
- if (!options_parse_common(argc, argv, &common_opts)) {
- return false;
+ 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");
}
-
- if (*argc < 2) {
- print_error("missing arguments");
- return false;
- } else if (*argc > 2) {
- print_error("too many arguments");
- return false;
- } else {
- opts->op.restore.sector_size = common_opts.sector_size;
- opts->op.restore.buffer_size = common_opts.buffer_size;
- opts->op.restore.in_file_path = next_arg(argv);
- opts->op.restore.out_file_path = next_arg(argv);
- }
-
- return true;
}
-static const char *
-next_arg(char ***const argv)
+const char *
+OptionParser::next_arg(char ***const argv)
{
const char *arg = **argv;
++(*argv);