From 1db94ae5d2201edb5f9421c2c30be049efc678f6 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Sun, 27 Dec 2015 12:56:13 +0300 Subject: utils: refactor command line parsing --- utils/block_cmd_parser.hpp | 143 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 128 insertions(+), 15 deletions(-) (limited to 'utils/block_cmd_parser.hpp') diff --git a/utils/block_cmd_parser.hpp b/utils/block_cmd_parser.hpp index 3468d58..988ef52 100644 --- a/utils/block_cmd_parser.hpp +++ b/utils/block_cmd_parser.hpp @@ -16,8 +16,11 @@ #include #include +#include +#include #include #include +#include #include namespace @@ -40,26 +43,87 @@ namespace "the selected mode of operation is not implemented"); } + class CommandLineParser; + + class Input + { + public: + Input( + std::string&& key_string, + std::string&& iv_string, + std::vector&& input_block_strings) + : key_string(std::move(key_string)) + , iv_string(std::make_pair(true, std::move(iv_string))) + , input_block_strings(input_block_strings) + { } + + Input( + std::string&& key_string, + std::vector&& input_block_strings) + : key_string(std::move(key_string)) + , iv_string(std::make_pair(false, std::string())) + , input_block_strings(std::move(input_block_strings)) + { } + + const std::string& get_key_string() const { return key_string; } + + const std::string& get_iv_string() const + { + if (!iv_string.first) + throw_iv_required(); + return iv_string.second; + } + + const std::vector& get_input_block_strings() const + { + return input_block_strings; + } + + private: + const std::string key_string; + const std::pair iv_string; + const std::vector input_block_strings; + }; + + class Settings + { + public: + aesni::Algorithm get_algorithm() const { return algorithm; } + aesni::Mode get_mode() const { return mode; } + + bool use_boxes() const { return use_boxes_flag; } + bool verbose() const { return verbose_flag; } + + private: + aesni::Algorithm algorithm; + aesni::Mode mode; + + bool use_boxes_flag = false; + bool verbose_flag = false; + + friend class CommandLineParser; + }; + class CommandLineParser { public: CommandLineParser(const std::string& argv0) : prog_name(boost::filesystem::path(argv0).filename().string()) , options("Options") + { } + + void parse(Settings& settings, int argc, char** argv, std::vector& inputs) { namespace po = boost::program_options; options.add_options() ("help,h", "show this message and exit") - ("box,b", po::bool_switch(&use_boxes)->default_value(false), "use the \"boxes\" interface") - ("mode,m", po::value(&mode)->required(), "set mode of operation") - ("algorithm,a", po::value(&algorithm)->required(), "set algorithm") - ("verbose,v", po::bool_switch(&verbose)->default_value(false), "enable verbose output"); - } + ("box,b", po::bool_switch(&settings.use_boxes_flag)->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_flag)->default_value(false), "enable verbose output"); - void parse(int argc, char** argv) - { - namespace po = boost::program_options; + std::vector args; po::options_description hidden_options; hidden_options.add_options() @@ -84,17 +148,66 @@ namespace } po::notify(vm); + + parse_inputs(settings, inputs, std::deque( + std::make_move_iterator(args.begin()), + std::make_move_iterator(args.end()) + )); } - bool requested_help() const { return help_flag; } - - aesni::Mode mode; - aesni::Algorithm algorithm; - bool use_boxes; - std::vector args; - bool verbose; + bool exit_with_usage() const { return help_flag; } private: + static void parse_inputs( + const Settings& settings, + std::vector& inputs, + std::deque&& args) + { + while (!args.empty()) + { + auto key_string = std::move(args.front()); + args.pop_front(); + + std::string iv_string; + + if (aesni::mode_requires_initialization_vector(settings.get_mode())) + { + if (args.empty()) + throw_iv_required(); + iv_string = std::move(args.front()); + args.pop_front(); + } + + std::vector input_block_strings; + + while (!args.empty()) + { + if (args.front() == "--") + { + args.pop_front(); + break; + } + + input_block_strings.emplace_back(std::move(args.front())); + args.pop_front(); + } + + if (aesni::mode_requires_initialization_vector(settings.get_mode())) + { + inputs.emplace_back( + std::move(key_string), + std::move(iv_string), + std::move(input_block_strings)); + } + else + { + inputs.emplace_back( + std::move(key_string), + std::move(input_block_strings)); + } + } + } + const std::string prog_name; boost::program_options::options_description options; -- cgit v1.2.3