presence: Replace Argument class with CLI11

Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: Idd6e49c7206ce0b71990cc4999659bd51768f691
diff --git a/argument.hpp b/argument.hpp
deleted file mode 100644
index 7917b8a..0000000
--- a/argument.hpp
+++ /dev/null
@@ -1,65 +0,0 @@
-#pragma once
-
-#include <getopt.h>
-
-#include <map>
-#include <string>
-
-namespace phosphor
-{
-namespace gpio
-{
-/** @brief Class - Encapsulates parsing command line options and
- *                 populating arguments
- */
-class ArgumentParser
-{
-  public:
-    ArgumentParser() = delete;
-    ~ArgumentParser() = default;
-    ArgumentParser(const ArgumentParser&) = delete;
-    ArgumentParser& operator=(const ArgumentParser&) = delete;
-    ArgumentParser(ArgumentParser&&) = default;
-    ArgumentParser& operator=(ArgumentParser&&) = default;
-
-    /** @brief Constructs Argument object
-     *
-     *  @param argc - the main function's argc passed as is
-     *  @param argv - the main function's argv passed as is
-     *  @return Object constructed
-     */
-    ArgumentParser(int argc, char** argv);
-
-    /** @brief Given an option, returns its argument(optarg)
-     *
-     *  @param opt - command line option string
-     *
-     *  @return argument which is a standard optarg
-     */
-    const std::string& operator[](const std::string& opt);
-
-    /** @brief Displays usage
-     *
-     *  @param argv - the main function's argv passed as is
-     */
-    static void usage(char** argv);
-
-    /** @brief Set to 'true' when an option is passed */
-    static const std::string trueString;
-
-    /** @brief Set to '' when an option is not passed */
-    static const std::string emptyString;
-
-  private:
-    /** @brief Option to argument mapping */
-    std::map<const std::string, std::string> arguments;
-
-    /** @brief Array of struct options as needed by getopt_long */
-    static const option options[];
-
-    /** @brief optstring as needed by getopt_long */
-    static const char* optionStr;
-};
-
-} // namespace gpio
-} // namespace phosphor
diff --git a/presence/argument.cpp b/presence/argument.cpp
deleted file mode 100644
index c0d0ee3..0000000
--- a/presence/argument.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/**
- * Copyright © 2017 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 <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:n:i:d:e:?h";
-const option ArgumentParser::options[] = {
-    {"path", required_argument, nullptr, 'p'},
-    {"key", required_argument, nullptr, 'k'},
-    {"name", required_argument, nullptr, 'n'},
-    {"inventory", required_argument, nullptr, 'i'},
-    {"drivers", required_argument, nullptr, 'd'},
-    {"extra-ifaces", required_argument, nullptr, 'e'},
-    {"help", no_argument, nullptr, 'h'},
-    {0, 0, 0, 0},
-};
-
-ArgumentParser::ArgumentParser(int argc, char** argv)
-{
-    auto 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)
-        {
-            arguments[i->name] = (i->has_arg ? optarg : 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 << "  --inventory=<inventory> Object path under inventory"
-                 " that will be created\n";
-    std::cerr << "  --path=<path>           Path of device to read for GPIO pin"
-                 " state to determine presence of inventory item\n";
-    std::cerr << "  --key=<key>             Input GPIO key number\n";
-    std::cerr << "  --name=<name>           Pretty name of the inventory"
-                 " item\n";
-    std::cerr << "  --drivers=<drivers>     List of drivers to bind when card"
-                 " is added and unbind when card is removed\n";
-    std::cerr << "                          Format is a space separated list"
-                 " of path,device pairs.  For example:\n";
-    std::cerr << "                          "
-                 "/sys/bus/i2c/drivers/some-driver,3-0068\n";
-    std::cerr << "  --extra-ifaces=<ifaces> List of interfaces to associate to"
-                 " inventory item\n";
-    std::cerr << "                          Format is a comma separated list"
-                 " of interfaces.         For example:\n";
-    std::cerr << "                          "
-                 "/xyz/openbmc_project/.../1,/xyz/openbmc_project/.../2\n";
-    std::cerr << std::flush;
-    exit(-1);
-}
-} // namespace gpio
-} // namespace phosphor
diff --git a/presence/main.cpp b/presence/main.cpp
index cb573fc..aa1eb24 100644
--- a/presence/main.cpp
+++ b/presence/main.cpp
@@ -1,8 +1,8 @@
-#include "argument.hpp"
 #include "gpio_presence.hpp"
 
 #include <systemd/sd-event.h>
 
+#include <CLI/CLI.hpp>
 #include <phosphor-logging/lg2.hpp>
 
 #include <iostream>
@@ -57,54 +57,66 @@
     return 0;
 }
 
-int main(int argc, char* argv[])
+int main(int argc, char** argv)
 {
-    auto options = ArgumentParser(argc, argv);
+    CLI::App app{"Monitor gpio presence status"};
 
-    auto inventory = options["inventory"];
-    auto key = options["key"];
-    auto path = options["path"];
-    auto drivers = options["drivers"];
-    auto ifaces = options["extra-ifaces"];
-    if (argc < 4)
+    std::string path{};
+    std::string key{};
+    std::string name{};
+    std::string inventory{};
+    std::string drivers{};
+    std::string ifaces{};
+
+    /* Add an input option */
+    app.add_option(
+           "-p,--path", path,
+           " Path of device to read for GPIO pin state to determine presence of inventory item")
+        ->required();
+    app.add_option("-k,--key", key, "Input GPIO key number")->required();
+    app.add_option("-n,--name", name, "Pretty name of the inventory item")
+        ->required();
+    app.add_option("-i,--inventory", inventory,
+                   "Object path under inventory that will be created")
+        ->required();
+    app.add_option(
+        "-d,--drivers", drivers,
+        "List of drivers to bind when card is added and unbind when card is removed\n"
+        "Format is a space separated list of path,device pairs.\n"
+        "For example: /sys/bus/i2c/drivers/some-driver,3-0068");
+    app.add_option(
+        "-e,--extra-ifaces", ifaces,
+        "List of interfaces to associate to inventory item\n"
+        "Format is a comma separated list of interfaces.\n"
+        "For example: /xyz/openbmc_project/.../1,/xyz/openbmc_project/.../2");
+
+    /* Parse input parameter */
+    try
     {
-        std::cerr << "Too few arguments\n";
-        options.usage(argv);
+        app.parse(argc, argv);
     }
-
-    if (inventory == ArgumentParser::emptyString)
+    catch (const CLI::Error& e)
     {
-        std::cerr << "Inventory argument required\n";
-        options.usage(argv);
-    }
-
-    if (key == ArgumentParser::emptyString)
-    {
-        std::cerr << "GPIO key argument required\n";
-        options.usage(argv);
-    }
-
-    if (path == ArgumentParser::emptyString)
-    {
-        std::cerr << "Device path argument required\n";
-        options.usage(argv);
+        return app.exit(e);
     }
 
     std::vector<Driver> driverList;
 
     // Driver list is optional
-    if (drivers != ArgumentParser::emptyString)
+    if (!drivers.empty())
     {
         if (getDrivers(drivers, driverList) < 0)
         {
-            options.usage(argv);
+            lg2::error("Failed to parser drivers: {DRIVERS}", "DRIVERS",
+                       drivers);
+            return -1;
         }
     }
 
     std::vector<Interface> ifaceList;
 
     // Extra interfaces list is optional
-    if (ifaces != ArgumentParser::emptyString)
+    if (!ifaces.empty())
     {
         std::stringstream ss(ifaces);
         Interface iface;
@@ -126,7 +138,6 @@
     EventPtr eventP{event};
     event = nullptr;
 
-    auto name = options["name"];
     Presence presence(bus, inventory, path, std::stoul(key), name, eventP,
                       driverList, ifaceList);
 
diff --git a/presence/meson.build b/presence/meson.build
index c46f844..9c7828b 100644
--- a/presence/meson.build
+++ b/presence/meson.build
@@ -1,6 +1,5 @@
 executable(
     'phosphor-gpio-presence',
-    'argument.cpp',
     'main.cpp',
     'gpio_presence.cpp',
     dependencies: [