From 53414fe78b29b1957ab8b29fde05a90e179092d7 Mon Sep 17 00:00:00 2001 From: lloyd Date: Wed, 9 Aug 2006 08:27:03 +0000 Subject: Add a simple option parser to the check utility; it makes for much saner code in check.cpp, and now the order of options on the command line should not change what heppens. The options taken have changed slightly. All options that take values are now --arg=value instead of "--arg value", and the various --bench-(blah) options have been turned into a new option --bench-type that takes an argument specifying the type of algorithm to benchmark. --- checks/check.cpp | 126 +++++++++++++++++++++++------------------------------- checks/getopt.cpp | 79 ++++++++++++++++++++++++++++++++++ checks/getopt.h | 38 ++++++++++++++++ 3 files changed, 171 insertions(+), 72 deletions(-) create mode 100644 checks/getopt.cpp create mode 100644 checks/getopt.h (limited to 'checks') diff --git a/checks/check.cpp b/checks/check.cpp index 81bb92220..c67dbd953 100644 --- a/checks/check.cpp +++ b/checks/check.cpp @@ -15,11 +15,10 @@ #include #include -/* Flag to use engine(s) for PK operations, if available */ -#define USE_ENGINES 0 - using namespace Botan_types; +#include "getopt.h" + /* Not on by default as many compilers (including egcs and gcc 2.95.x) * do not have the C++ header. * @@ -43,88 +42,72 @@ void benchmark(const std::string&, bool html, double seconds); void bench_pk(const std::string&, bool html, double seconds); u32bit bench_algo(const std::string&); int validate(); -void print_help(double); +void print_help(); int main(int argc, char* argv[]) { - try { + try + { + if(argc <= 1) + { print_help(); return 1; } -#if 0 - // Make sure we can repeatedly init/shutdown without problems - for(u32bit j = 0; j != 3; j++) - { - Botan::Init::initialize(); - Botan::Init::deinitialize(); - } -#endif + OptionParser opts("help|html|init=|validate|" + "benchmark|bench-type=|bench-algo=|seconds="); + opts.parse(argv); - std::string init_flags = ""; - if(USE_ENGINES) - init_flags += " use_engines"; + if(opts.is_set("help")) + { print_help(); return 1; } - Botan::LibraryInitializer init(init_flags); - bool html = false; // default to text output - double seconds = 1.5; + std::string init_flags = (opts.is_set("init") ? opts.value("init") : ""); - std::vector args; - for(int j = 1; j != argc; j++) - args.push_back(argv[j]); + Botan::InitializerOptions init_options(init_flags); + Botan::LibraryInitializer init(init_options); - if(!args.size()) { print_help(seconds); return 2; } + if(opts.is_set("validate")) + return validate(); - for(u32bit j = 0; j != args.size(); j++) + double seconds = 1.5; + + if(opts.is_set("seconds")) { - if(args[j] == "--help") { print_help(seconds); return 1; } - if(args[j] == "--html") html = true; - if(args[j] == "--bench-algo") - { - if(j != args.size() - 1) - { - u32bit found = bench_algo(args[j+1]); - if(!found) // maybe it's a PK algorithm - bench_pk(args[j+1], false, seconds); - } - else - { - std::cout << "Option --bench-algo needs an argument\n"; - return 2; - } - } - if(args[j] == "--seconds") + seconds = std::atof(opts.value("seconds").c_str()); + if((seconds < 0.1 || seconds > 30) && seconds != 0) { - if(j != args.size() - 1) // another arg remains - { - seconds = std::atof(args[j+1].c_str()); - // sanity check; we allow zero for testing porpoises - if((seconds < 0.1 || seconds > 30) && seconds != 0) - { - std::cout << "Invalid argument to --seconds\n"; - return 2; - } - } - else - { - std::cout << "Option --seconds needs an argument\n"; - return 2; - } + std::cout << "Invalid argument to --seconds\n"; + return 2; } } - for(u32bit j = 0; j != args.size(); j++) + if(opts.is_set("bench-algo")) + { + const std::string alg = opts.value("bench-algo"); + u32bit found = bench_algo(alg); + if(!found) // maybe it's a PK algorithm + bench_pk(alg, false, seconds); + } + + const bool html = opts.is_set("html"); + + if(opts.is_set("benchmark")) + benchmark("All", html, seconds); + else if(opts.is_set("bench-type")) { - if(args[j] == "--validate") return validate(); - if(args[j] == "--benchmark") benchmark("All", html, seconds); - if(args[j] == "--bench-all") benchmark("All", html, seconds); - if(args[j] == "--bench-block") + const std::string type = opts.value("bench-type"); + + if(type == "all") + benchmark("All", html, seconds); + else if(type == "block") benchmark("Block Cipher", html, seconds); - if(args[j] == "--bench-mode") - benchmark("Cipher Mode", html, seconds); - if(args[j] == "--bench-stream") + else if(type == "stream") benchmark("Stream Cipher", html, seconds); - if(args[j] == "--bench-hash") benchmark("Hash", html, seconds); - if(args[j] == "--bench-mac") benchmark("MAC", html, seconds); - if(args[j] == "--bench-rng") benchmark("RNG", html, seconds); - if(args[j] == "--bench-pk") bench_pk("All", html, seconds); + else if(type == "hash") + benchmark("Hash", html, seconds); + else if(type == "mac") + benchmark("MAC", html, seconds); + else if(type == "rng") + benchmark("RNG", html, seconds); + else if(type == "pk") + bench_pk("All", html, seconds); } } catch(Botan::Exception& e) @@ -147,17 +130,16 @@ int main(int argc, char* argv[]) return 0; } -void print_help(double seconds) +void print_help() { std::cout << Botan::version_string() << " test driver" << std::endl << "Usage:\n" << " --validate: Check test vectors\n" << " --benchmark: Benchmark everything\n" - << " --bench-{block,mode,stream,hash,mac,rng,pk}:\n" + << " --bench-type={block,mode,stream,hash,mac,rng,pk}:\n" << " Benchmark only algorithms of a particular type\n" << " --html: Produce HTML output for benchmarks\n" - << " --seconds n: Benchmark for n seconds (default is " - << seconds << ")\n" + << " --seconds=n: Benchmark for n seconds\n" << " --help: Print this message\n"; } diff --git a/checks/getopt.cpp b/checks/getopt.cpp new file mode 100644 index 000000000..a30134ff9 --- /dev/null +++ b/checks/getopt.cpp @@ -0,0 +1,79 @@ + +#include "getopt.h" + +#include +#include + +OptionParser::OptionParser(const std::string& opt_string) + { + std::vector opts = Botan::split_on(opt_string, '|'); + + for(size_t j = 0; j != opts.size(); j++) + flags.push_back(OptionFlag(opts[j])); + } + +OptionParser::OptionFlag OptionParser::find_option(const std::string& name) const + { + for(size_t j = 0; j != flags.size(); j++) + if(flags[j].name() == name) + return flags[j]; + throw Botan::Exception("Unknown option " + name); + } + +bool OptionParser::is_set(const std::string& key) const + { + return (options.find(key) != options.end()); + } + +std::string OptionParser::value(const std::string& key) const + { + std::map::const_iterator i = options.find(key); + if(i == options.end()) + throw Botan::Exception("Option " + key + " not found"); + return i->second; + } + +void OptionParser::parse(char* argv[]) + { + std::vector args; + for(int j = 1; argv[j]; j++) + args.push_back(argv[j]); + + for(size_t j = 0; j != args.size(); j++) + { + std::string arg = args[j]; + + if(arg.size() > 2 && arg[0] == '-' && arg[1] == '-') + { + const std::string opt_name = arg.substr(0, arg.find('=')); + + arg = arg.substr(2); + + std::string::size_type mark = arg.find('='); + + OptionFlag opt = find_option(arg.substr(0, mark)); + + if(opt.takes_arg()) + { + if(mark == std::string::npos) + throw Botan::Exception("Option " + opt_name + + " requires an argument"); + + std::string name = arg.substr(0, mark); + std::string value = arg.substr(mark+1); + + options[name] = value; + } + else + { + if(mark != std::string::npos) + throw Botan::Exception("Option " + opt_name + + " does not take an argument"); + + options[arg] = ""; + } + } + else + leftover.push_back(arg); + } + } diff --git a/checks/getopt.h b/checks/getopt.h new file mode 100644 index 000000000..5796f7ae7 --- /dev/null +++ b/checks/getopt.h @@ -0,0 +1,38 @@ + +#include +#include +#include + +class OptionParser + { + public: + std::vector leftovers() const { return leftover; } + bool is_set(const std::string&) const; + std::string value(const std::string&) const; + + void parse(char*[]); + OptionParser(const std::string&); + private: + class OptionFlag + { + public: + std::string name() const { return opt_name; } + bool takes_arg() const { return opt_takes_arg; } + + OptionFlag(const std::string& opt_string) + { + std::string::size_type mark = opt_string.find('='); + opt_name = opt_string.substr(0, mark); + opt_takes_arg = (mark != std::string::npos); + } + private: + std::string opt_name; + bool opt_takes_arg; + }; + + OptionFlag find_option(const std::string&) const; + + std::vector flags; + std::map options; + std::vector leftover; + }; -- cgit v1.2.3