phosphor-gpio-monitor: Replace Argument class with CLI11

Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: Id750beb9f8b8f8ec0c611c58b9a0ef86d92750f4
diff --git a/argument.cpp b/argument.cpp
deleted file mode 100644
index 74bdda2..0000000
--- a/argument.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/**
- * Copyright © 2016 IBM Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "argument.hpp"
-
-#include <algorithm>
-#include <cassert>
-#include <iostream>
-#include <iterator>
-
-namespace phosphor
-{
-namespace gpio
-{
-
-using namespace std::string_literals;
-
-const std::string ArgumentParser::trueString = "true"s;
-const std::string ArgumentParser::emptyString = ""s;
-
-const char* ArgumentParser::optionStr = "p:k:r:t:?h";
-const option ArgumentParser::options[] = {
-    {"path", required_argument, nullptr, 'p'},
-    {"key", required_argument, nullptr, 'k'},
-    {"polarity", required_argument, nullptr, 'r'},
-    {"target", required_argument, nullptr, 't'},
-    {"continue", no_argument, nullptr, 'c'},
-    {"help", no_argument, nullptr, 'h'},
-    {0, 0, 0, 0},
-};
-
-ArgumentParser::ArgumentParser(int argc, char** argv)
-{
-    int option = 0;
-    while (-1 !=
-           (option = getopt_long(argc, argv, optionStr, options, nullptr)))
-    {
-        if ((option == '?') || (option == 'h'))
-        {
-            usage(argv);
-            exit(-1);
-        }
-
-        auto i = &options[0];
-        while ((i->val != option) && (i->val != 0))
-        {
-            ++i;
-        }
-
-        if (i->val)
-        {
-            // optional argument may get nullptr for optarg
-            // make it empty string in such case
-            auto arg = (optarg == nullptr ? "" : optarg);
-            arguments[i->name] = (i->has_arg ? arg : trueString);
-        }
-    }
-}
-
-const std::string& ArgumentParser::operator[](const std::string& opt)
-{
-    auto i = arguments.find(opt);
-    if (i == arguments.end())
-    {
-        return emptyString;
-    }
-    else
-    {
-        return i->second;
-    }
-}
-
-void ArgumentParser::usage(char** argv)
-{
-    std::cerr << "Usage: " << argv[0] << " [options]\n";
-    std::cerr << "Options:\n";
-    std::cerr << "  --help                  Print this menu\n";
-    std::cerr << "  --path=<path>           Path of input device."
-                 " Ex: /dev/input/event2\n";
-    std::cerr << "  --key=<key>             Input GPIO key number\n";
-    std::cerr << "  --polarity=<polarity>   Asertion polarity to look for."
-                 " This is 0 / 1 \n";
-    std::cerr << "  --target=<systemd unit> Systemd unit to be called on GPIO"
-                 " state change\n";
-    std::cerr << "  [--continue]            Whether or not to continue"
-                 " after key pressed\n";
-}
-} // namespace gpio
-} // namespace phosphor
diff --git a/mainapp.cpp b/mainapp.cpp
index 7a3300f..2496a89 100644
--- a/mainapp.cpp
+++ b/mainapp.cpp
@@ -14,59 +14,51 @@
  * limitations under the License.
  */
 
-#include "argument.hpp"
 #include "monitor.hpp"
 
 #include <systemd/sd-event.h>
 
+#include <CLI/CLI.hpp>
 #include <phosphor-logging/lg2.hpp>
 
 #include <iostream>
 #include <string>
 
-static void exitWithError(const char* err, char** argv)
-{
-    phosphor::gpio::ArgumentParser::usage(argv);
-    std::cerr << "ERROR: " << err << "\n";
-    exit(EXIT_FAILURE);
-}
-
 int main(int argc, char** argv)
 {
+    CLI::App app{"Monitor GPIO line for requested state change"};
+
     // Read arguments.
-    auto options = phosphor::gpio::ArgumentParser(argc, argv);
+    std::string path{};
+    std::string key{};
+    std::string polarity{};
+    std::string target{};
+    bool continueRun = false;
 
-    // Parse out path argument.
-    auto path = (options)["path"];
-    if (path == phosphor::gpio::ArgumentParser::emptyString)
+    /* Add an input option */
+    app.add_option("-p,--path", path,
+                   "Path of input device. Ex: /dev/input/event2")
+        ->required();
+    app.add_option("-k,--key", key, "Input GPIO key number")->required();
+    app.add_option("-r,--polarity", polarity,
+                   "Asertion polarity to look for. This is 0 / 1")
+        ->required();
+    app.add_option("-t,--target", target,
+                   "Systemd unit to be called on GPIO state change")
+        ->required();
+    app.add_option("-c,--continue", continueRun,
+                   "PWhether or not to continue after key pressed");
+
+    /* Parse input parameter */
+    try
     {
-        exitWithError("path not specified.", argv);
+        app.parse(argc, argv);
     }
-
-    // Parse out key number that we are interested in
-    // Its integer mapping to the GPIO key configured by the kernel
-    auto key = (options)["key"];
-    if (key == phosphor::gpio::ArgumentParser::emptyString)
+    catch (const CLI::Error& e)
     {
-        exitWithError("Key not specified.", argv);
+        return app.exit(e);
     }
 
-    // Parse out assertion polarity interested in
-    // Its either 1 or 0 for press / release
-    auto polarity = (options)["polarity"];
-    if (polarity == phosphor::gpio::ArgumentParser::emptyString)
-    {
-        exitWithError("Polarity not specified.", argv);
-    }
-
-    // Parse out target argument. It is fine if the caller does not
-    // pass this if they are not interested in calling into any target
-    // on meeting a condition.
-    auto target = (options)["target"];
-
-    bool continueRun =
-        (options["continue"] == phosphor::gpio::ArgumentParser::trueString);
-
     sd_event* event = nullptr;
     auto r = sd_event_default(&event);
     if (r < 0)
@@ -90,7 +82,7 @@
         if (r < 0)
         {
             lg2::error("Failure in processing request: {RC}", "RC", r);
-            break;
+            return r;
         }
     }
 
diff --git a/meson.build b/meson.build
index a3f3bad..ffb3442 100644
--- a/meson.build
+++ b/meson.build
@@ -126,7 +126,6 @@
 
 phosphor_gpio_monitor = executable(
     'phosphor-gpio-monitor',
-    'argument.cpp',
     'mainapp.cpp',
     dependencies: [
         libevdev,