Add simple command line option parser and a tester for it
authorJyri Sarha <jsarha@ti.com>
Tue, 20 Oct 2015 13:55:13 +0000 (16:55 +0300)
committerJyri Sarha <jsarha@ti.com>
Tue, 20 Oct 2015 19:41:21 +0000 (22:41 +0300)
tests/CMakeLists.txt
tests/cmdoptions.h [new file with mode: 0644]
tests/optiontester.cpp [new file with mode: 0644]

index 10b269f4575deb9b0ab382f60cc5c41aa43f7615..11eadc053c263a8606c2d5042afd7504f207b5e7 100644 (file)
@@ -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 (file)
index 0000000..843e65a
--- /dev/null
@@ -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 (file)
index 0000000..ccb9579
--- /dev/null
@@ -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;
+}