// Copyright (c) 2015 Egor Tensin // This file is part of the "AES tools" project. // For details, see https://github.com/egor-tensin/aes-tools. // Distributed under the MIT License. #pragma once #include "cmd_parser.hpp" #include "data_parsers.hpp" #include #include #include #include #include #include #include #include #include class BlockSettings : public SettingsParser { public: class Input { public: Input( std::string_view key, std::optional&& iv, std::vector&& blocks ) : key{key}, iv{std::move(iv)}, blocks{std::move(blocks)} {} std::string get_key() const { return key; } std::optional get_iv() const { return iv; } std::vector get_blocks() const { return blocks; } private: std::string key; std::optional iv; std::vector blocks; }; explicit BlockSettings(std::string_view argv0) : SettingsParser{argv0} { namespace po = boost::program_options; visible.add_options()("verbose,v", po::bool_switch(&verbose), "enable verbose output"); visible.add_options()( "algorithm,a", po::value(&algorithm)->required()->value_name("NAME"), "set algorithm" ); visible.add_options()( "mode,m", po::value(&mode)->required()->value_name("MODE"), "set mode of operation" ); } const char* get_short_description() const override { return "[-h|--help] [-v|--verbose] [-a|--algorithm NAME] [-m|--mode MODE]" " [-- KEY [IV] [BLOCK]...]..."; } void parse(int argc, char* argv[]) override { std::vector args; hidden.add_options()("args", boost::program_options::value(&args), "shouldn't be visible"); positional.add("args", -1); SettingsParser::parse(argc, argv); if (exit_with_usage()) return; parse_inputs( std::deque{ std::make_move_iterator(args.begin()), std::make_move_iterator(args.end()) } ); } aes::Algorithm get_algorithm() const { return algorithm; } aes::Mode get_mode() const { return mode; } const std::vector& get_inputs() const { return inputs; } bool get_verbose() const { return verbose; } private: void parse_inputs(std::deque&& src) { while (!src.empty()) inputs.emplace_back(parse_input(src)); } Input parse_input(std::deque& src) const { std::string key{std::move(src.front())}; src.pop_front(); std::optional iv; if (aes_mode_requires_init_vector(mode)) { if (src.empty()) { throw boost::program_options::error{ "an initialization vector is required for the selected mode of operation" }; } iv = aes::Block::parse(src.front()); src.pop_front(); } return {key, std::move(iv), parse_blocks(src)}; } static std::vector parse_blocks(std::deque& src) { std::vector blocks; while (!src.empty()) { std::string block{std::move(src.front())}; src.pop_front(); if (block == "--") break; blocks.emplace_back(aes::Block::parse(block)); } return blocks; } aes::Algorithm algorithm; aes::Mode mode; std::vector inputs; bool verbose = false; };