From 06b2428c2afaa36997a9d341bd497d42aa0fef89 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Tue, 20 Jun 2017 18:22:00 +0300 Subject: utils: refactor command-line arguments parsing + update usage messages. --- utils/block_cmd_parser.hpp | 203 ++++++++++++++++++--------------------------- 1 file changed, 82 insertions(+), 121 deletions(-) (limited to 'utils/block_cmd_parser.hpp') diff --git a/utils/block_cmd_parser.hpp b/utils/block_cmd_parser.hpp index 9c9d61c..58f86d8 100644 --- a/utils/block_cmd_parser.hpp +++ b/utils/block_cmd_parser.hpp @@ -7,157 +7,118 @@ #include "block_input.hpp" #include "data_parsers.hpp" +#include "helpers/command_line.hpp" #include -#include #include #include #include -#include #include #include #include -namespace +class BlockSettings : public command_line::SettingsParser { - class CommandLineParser; +public: + aes::Algorithm algorithm = AES_AES128; + aes::Mode mode = AES_ECB; - class Settings - { - public: - aes::Algorithm algorithm = AES_AES128; - aes::Mode mode = AES_ECB; - - bool use_boxes = false; - bool verbose = false; - - private: - Settings() = default; + bool use_boxes = false; + bool verbose = false; - friend class CommandLineParser; - }; + std::vector inputs; - class CommandLineParser + explicit BlockSettings(const std::string& argv0) + : SettingsParser{argv0} { - public: - explicit CommandLineParser(const std::string& argv0) - : prog_name{boost::filesystem::path{argv0}.filename().string()} - , options{"Options"} - { } - - Settings parse(int argc, char** argv, std::vector& inputs) - { - Settings settings; - - namespace po = boost::program_options; - - options.add_options() - ("help,h", "show this message and exit") - ("use-boxes,b", po::bool_switch(&settings.use_boxes)->default_value(false), "use the \"boxes\" interface") - ("mode,m", po::value(&settings.mode)->required(), "set mode of operation") - ("algorithm,a", po::value(&settings.algorithm)->required(), "set algorithm") - ("verbose,v", po::bool_switch(&settings.verbose)->default_value(false), "enable verbose output"); + visible.add_options() + ("verbose,v", + boost::program_options::bool_switch(&verbose), + "enable verbose output") + ("algorithm,a", + boost::program_options::value(&algorithm) + ->required() + ->value_name("NAME"), + "set algorithm") + ("mode,m", + boost::program_options::value(&mode) + ->required() + ->value_name("MODE"), + "set mode of operation") + ("use-boxes,b", + boost::program_options::bool_switch(&use_boxes), + "use the \"boxes\" interface"); + hidden.add_options() + ("args", + boost::program_options::value>(&args), + "shouldn't be visible"); + positional.add("args", -1); + } - std::vector args; + const char* get_short_description() const override + { + return "[-h|--help] [-v|--verbose] [-a|--algorithm NAME] [-m|--mode MODE]" + " [-- KEY [IV] [BLOCK]...]..."; + } - po::options_description hidden_options; - hidden_options.add_options() - ("positional", po::value>(&args)); + void parse(int argc, char* argv[]) override + { + SettingsParser::parse(argc, argv); + parse_inputs(std::deque{ + std::make_move_iterator(args.begin()), + std::make_move_iterator(args.end())}); + } - po::options_description all_options; - all_options.add(options).add(hidden_options); +private: + void parse_inputs(std::deque&& src) + { + while (!src.empty()) + inputs.emplace_back(parse_input(src)); + } - po::positional_options_description positional_options; - positional_options.add("positional", -1); + Input parse_input(std::deque& src) const + { + std::string key{std::move(src.front())}; + src.pop_front(); - po::variables_map vm; - po::store(po::command_line_parser(argc, argv) - .options(all_options) - .positional(positional_options) - .run(), vm); + std::string iv; - if (vm.count("help")) + if (aes::mode_requires_init_vector(mode)) + { + if (src.empty()) { - help_flag = true; - return settings; + throw boost::program_options::error{ + "an initialization vector is required for the selected mode of operation"}; } - - po::notify(vm); - - inputs = parse_inputs(settings, std::deque{ - std::make_move_iterator(args.begin()), - std::make_move_iterator(args.end())}); - - return settings; - } - - bool exit_with_usage() const { return help_flag; } - - private: - static std::vector parse_inputs( - const Settings& settings, - std::deque&& args) - { - std::vector inputs; - while (!args.empty()) - inputs.emplace_back(parse_input(settings, args)); - return inputs; + iv = std::move(src.front()); + src.pop_front(); } - static Input parse_input( - const Settings& settings, - std::deque& args) - { - std::string key{std::move(args.front())}; - args.pop_front(); - - std::string iv; + auto blocks = parse_blocks(src); - if (aes::mode_requires_init_vector(settings.mode)) - { - if (args.empty()) - throw boost::program_options::error{"an initialization vector is required for the selected mode of operation"}; - iv = std::move(args.front()); - args.pop_front(); - } - - auto blocks = parse_blocks(args); + if (aes::mode_requires_init_vector(mode)) + return {key, iv, std::move(blocks)}; + else + return {key, std::move(blocks)}; + } - if (aes::mode_requires_init_vector(settings.mode)) - return {key, iv, std::move(blocks)}; - else - return {key, std::move(blocks)}; - } + static std::vector parse_blocks(std::deque& src) + { + std::vector blocks; - static std::vector parse_blocks(std::deque& args) + while (!src.empty()) { - std::vector blocks; - - while (!args.empty()) - { - std::string block{std::move(args.front())}; - args.pop_front(); - if (block == "--") - break; - blocks.emplace_back(std::move(block)); - } - - return blocks; + std::string block{std::move(src.front())}; + src.pop_front(); + if (block == "--") + break; + blocks.emplace_back(std::move(block)); } - const std::string prog_name; - boost::program_options::options_description options; - - bool help_flag = false; - - friend std::ostream& operator<<(std::ostream&, const CommandLineParser&); - }; - - std::ostream& operator<<(std::ostream& os, const CommandLineParser& cmd_parser) - { - return os << "Usage: " << cmd_parser.prog_name << " [OPTIONS...] [-- KEY [IV] [BLOCK...]...]\n" - << cmd_parser.options << "\n"; + return blocks; } -} + + std::vector args; +}; -- cgit v1.2.3