summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGoran Mekić <meka@tilda.center>2017-05-08 10:00:27 (GMT)
committerGoran Mekić <meka@tilda.center>2017-05-14 11:08:45 (GMT)
commit5f0849ef45459647661fabd402c2642146eb4d59 (patch)
treec79f1a270dc02ab78fe8c6638cededaeaa4f97a3
parent981d9012b461258b115aa2d1ad70d91fee555035 (diff)
Parse arguments without optionsrefs/pull/1/head
-rw-r--r--.clang_complete1
-rw-r--r--.gitignore1
-rw-r--r--example.cpp8
-rw-r--r--getoptpp.hpp47
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
diff --git a/.gitignore b/.gitignore
index bc98fd3..93ed025 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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;
}
}