summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJyri Sarha <jsarha@ti.com>2015-10-20 16:55:13 +0300
committerJyri Sarha <jsarha@ti.com>2015-10-20 22:41:21 +0300
commitf8f92d455c4a915a894111e00dd6f5ec1888bee5 (patch)
treeac85b9e440e93030e19525fd63cdf7100bc444fb
parent905eacc3b638e70f25958b7c25f09077b143e387 (diff)
Add simple command line option parser and a tester for it
-rw-r--r--tests/CMakeLists.txt2
-rw-r--r--tests/cmdoptions.h97
-rw-r--r--tests/optiontester.cpp29
3 files changed, 128 insertions, 0 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 10b269f..11eadc0 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -9,3 +9,5 @@ target_link_libraries(testpat kms++ kmstest ${LIBDRM_LIBRARIES})
add_executable (kmsview kmsview.cpp)
target_link_libraries(kmsview kms++ kmstest ${LIBDRM_LIBRARIES})
+
+add_executable (optiontester optiontester.cpp)
diff --git a/tests/cmdoptions.h b/tests/cmdoptions.h
new file mode 100644
index 0000000..843e65a
--- /dev/null
+++ b/tests/cmdoptions.h
@@ -0,0 +1,97 @@
+#pragma once
+
+#include <cstdio>
+#include <string>
+#include <vector>
+#include <map>
+
+using namespace std;
+
+#define NO_PARAM(h) (CmdOption(false, h))
+#define HAS_PARAM(h) (CmdOption(true, h))
+
+class CmdOption
+{
+public:
+ CmdOption(bool has_param, string help) :
+ m_has_param(has_param), m_help(help), m_is_set(false) { }
+ bool has_param() const { return m_has_param; }
+ const string& help() const { return m_help; }
+
+ void oset() { m_is_set = true; }
+ void pset(const string& p) { m_param = p; oset(); }
+ bool is_set() const { return m_is_set; }
+ const string& param() const { return m_param; }
+private:
+ bool m_has_param;
+ string m_help;
+
+ bool m_is_set;
+ string m_param;
+};
+
+class CmdOptions
+{
+public:
+ CmdOptions(int argc, char **argv, map<string, CmdOption>& opts) :
+ m_opts(opts), m_cmd(argv[0]) {
+ for (int i = 1; i < argc; i++) {
+ if (argv[i][0] == '-') {
+ auto ii = m_opts.find(&argv[i][1]);
+ if (ii == m_opts.end()) {
+ m_error += m_cmd + ": " +
+ string(argv[i]) +
+ ": unknown option\n";
+ continue;
+ }
+ if ((*ii).second.has_param()) {
+ if (++i == argc) {
+ m_error += m_cmd + ": -" +
+ (*ii).first +
+ ": parameter missing\n";
+ continue;
+ }
+ (*ii).second.pset(argv[i]);
+ } else {
+ (*ii).second.oset();
+ }
+ } else {
+ m_params.push_back(argv[i]);
+ }
+ }
+ }
+ const string& error() const { return m_error; }
+ const string& cmd() const { return m_cmd; }
+
+ bool is_set(const string& name) const {
+ return m_opts.at(name).is_set();
+ }
+ const string& opt_param(const string& name) const {
+ return m_opts.at(name).param();
+ }
+ const vector<string>& params() const { return m_params; }
+ CmdOption& get_option(const string& name) { return m_opts.at(name); }
+
+ int num_options() const {
+ int ret(0);
+ for (const auto& p : m_opts)
+ if (p.second.is_set())
+ ret++;
+ return ret;
+ }
+
+ const string usage() const {
+ string ret("usage:\n");
+ for (const auto& p : m_opts)
+ ret += "-" + p.first +
+ (p.second.has_param() ? " <>: " : ": ") +
+ p.second.help() + "\n";
+ return ret;
+ }
+
+private:
+ map<string, CmdOption>& m_opts;
+ string m_cmd;
+ vector<string> m_params;
+ string m_error;
+};
diff --git a/tests/optiontester.cpp b/tests/optiontester.cpp
new file mode 100644
index 0000000..ccb9579
--- /dev/null
+++ b/tests/optiontester.cpp
@@ -0,0 +1,29 @@
+#include <cstdio>
+#include <algorithm>
+#include <iostream>
+
+#include "cmdoptions.h"
+
+using namespace std;
+
+static map<string, CmdOption> options = {
+ { "test", NO_PARAM("test") },
+ { "test2", HAS_PARAM("test2") },
+};
+
+int main(int argc, char **argv)
+{
+ CmdOptions opts(argc, argv, options);
+
+ if (opts.error().length()) {
+ cerr << opts.error() << opts.usage();
+ return -1;
+ }
+
+ for (auto p : options)
+ printf("Option %s set %d param %s\n",
+ p.first.c_str(), opts.is_set(p.first),
+ opts.opt_param(p.first).c_str());;
+
+ return 0;
+}