diff options
-rw-r--r-- | .clang_complete | 1 | ||||
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | example.cpp | 8 | ||||
-rw-r--r-- | getoptpp.hpp | 47 |
4 files changed, 34 insertions, 23 deletions
diff --git a/.clang_complete b/.clang_complete new file mode 100644 index 0000000..c24e3b5 --- /dev/null +++ b/.clang_complete @@ -0,0 +1 @@ +-std=c++11 @@ -1 +1,2 @@ getoptpp.geany +example diff --git a/example.cpp b/example.cpp index f4ca943..73988aa 100644 --- a/example.cpp +++ b/example.cpp @@ -4,7 +4,7 @@ int main(int argc, char* argv[]) { int verbose_flag; - + dg::Options opt; opt.add("verbose", no_argument, &verbose_flag, 1, [&]() { std::cout << "verbose: " << verbose_flag << "\n"; @@ -30,6 +30,10 @@ int main(int argc, char* argv[]) { opt.add("help", no_argument, '?', [&]() { std::cout << "usage stuff\n"; }); - + opt.process(argc, argv); + for(auto const &arg : opt.arguments()) + { + std::cout << arg << std::endl; + } } diff --git a/getoptpp.hpp b/getoptpp.hpp index ccefe9a..0eafe3f 100644 --- a/getoptpp.hpp +++ b/getoptpp.hpp @@ -1,8 +1,10 @@ #pragma once +#include <iostream> #include <cassert> #include <functional> #include <vector> #include <unordered_map> +#include <string> #include <getopt.h> namespace dg { @@ -12,25 +14,27 @@ using Handle = std::function<void()>; class Options { public: Options(); - + /// @param name name of the option /// @param has_arg kind of arguments that are used (no_argument, required_argument, optional_argument) /// @param val identifies the option (see getopt documentation) /// @param handle lambda that is invoked when the option occures void add(std::string const & name, int has_arg, int val, Handle handle); - + /// @param name name of the option /// @param has_arg kind of arguments that are used (no_argument, required_argument, optional_argument) /// @param flag pointer that is set after the option occured /// @param val value for the flag to be set /// @param handle lambda that is invoked when the option occures void add(std::string const & name, int has_arg, int* flag, int val, Handle handle); - - void process(int argc, char* argv[]); - + + bool process(int argc, char* argv[]); + const std::vector<std::string> arguments() const { return args; } + private: std::size_t num_flags; std::vector<option> options; + std::vector<std::string> args; std::unordered_map<int, Handle> handles; }; @@ -45,15 +49,8 @@ void Options::add(std::string const & name, int has_arg, int val, Handle handle) } void Options::add(std::string const & name, int has_arg, int* flag, int val, Handle handle) { - // create a new option from the args - options.emplace_back(); - auto& option = options.back(); - option.name = name.c_str(); - option.has_arg = has_arg; - option.flag = flag; - option.val = val; - int index = val; // let val be the option's unique identifier + options.push_back({name.data(), has_arg, flag, val}); if (flag != nullptr) { // flag is not null, so the val is not used as identifier // so pick another one @@ -63,14 +60,14 @@ void Options::add(std::string const & name, int has_arg, int* flag, int val, Han handles[index] = handle; } -void Options::process(int argc, char* argv[]) { +bool Options::process(int argc, char* argv[]) { std::string shortopts; for (auto const & option: options) { if (option.flag != nullptr) { continue; } shortopts += static_cast<char>(option.val); - + switch (option.has_arg) { case no_argument: break; @@ -82,17 +79,21 @@ void Options::process(int argc, char* argv[]) { break; } } - + // add termination option options.push_back({0, 0, 0, 0}); - + // handle arguments while (true) { - int index{0}; - int key = getopt_long(argc, argv, shortopts.c_str(), options.data(), &index); - + int index = 0; + int key = getopt_long(argc, argv, shortopts.data(), options.data(), &index); + if (key == -1) { break; + } else if (key == '?') { + return false; + } else if (key == ':') { + return false; } else if (key == 0) { // call flag's handle handles.at(index)(); @@ -101,10 +102,14 @@ void Options::process(int argc, char* argv[]) { handles.at(key)(); } } - + for (int i = optind; i < argc; ++i) { + args.push_back(argv[i]); + } + // remove terminating option options.pop_back(); assert(options.size() == handles.size()); + return true; } } |