tool: Refactor base type Commands

Each command will be implemented as a CLI subcommand
command handers registration process:

    CLI::App app;
    auto base = app.add_subcommand("base");
    auto GetPLDMVersion = base->add_subcommand("GetPLDMVersion");
    /* register callback for GetPLDMVersion Command */
    GetPLDMVersion->callback(exec());
    CLI11_PARSER();

Each command will be implemented as a class. To avoid duplicate,
An interface class is abstracted as the base class for commands.

CommandInterface
{
	CommandInterface(CLI::App* app){
		app->callback([&](){exec();}) //register exec() to CLI11
	}
	virtual createRequestMsg();
	virtual parseResponseMsg();
	exec(){
		createRequestMsg();
		send_recv();
		parseResponseMsg();
	}
};

GetPLDMVersion : public CommandInterface
{
	GetPLDMVersion(CLI::App *app){
		app->add_option();  // add options for this command
	}
	...
}

Then, the main is like below:

int main()
{
	CLI::App app{"PLDM requester tool for OpenBMC"};
	auto base = app.add_subcommand("base");
	auto version = base->add_subcommand("GetPLDMVersion");
	GetPLDMVersion getPLDMVersion(version);
	CLI11_PARSE(app, argc, argv);
}

Tested:

root@fp5280g2:~# pldmtool base GetPLDMTypes
Encode request successfully
Request Message:
08 01 80 00 04
Success in creating the socket : RC = 3
Success in connecting to socket : RC = 0
Success in sending message type as pldm to mctp : RC = 0
Write to socket successful : RC = 5
Total length:5
Loopback response message:
08 01 80 00 04
On first recv(),response == request : RC = 0
Total length: 14
Shutdown Socket successful :  RC = 0
Response Message:
08 01 00 00 04 00 0d 00 00 00 00 00 00 00
Supported types: 0(base) 2(platform) 3(bios)

root@fp5280g2:~# pldmtool base GetPLDMVersion -t platform
Encode request successfully
Request Message:
08 01 80 00 03 00 00 00 00 01 02
Success in creating the socket : RC = 3
Success in connecting to socket : RC = 0
Success in sending message type as pldm to mctp : RC = 0
Write to socket successful : RC = 11
Total length:11
Loopback response message:
08 01 80 00 03 00 00 00 00 01 02
On first recv(),response == request : RC = 0
Total length: 15
Shutdown Socket successful :  RC = 0
Response Message:
08 01 00 00 03 00 00 00 00 00 05 f1 f1 f1 00
Type 2(platform): 1.1.1

root@fp5280g2:~# pldmtool raw -d 0x80 0x00 0x04
Encode request successfully
Request Message:
08 01 80 00 04
Success in creating the socket : RC = 3
Success in connecting to socket : RC = 0
Success in sending message type as pldm to mctp : RC = 0
Write to socket successful : RC = 5
Total length:5
Loopback response message:
08 01 80 00 04
On first recv(),response == request : RC = 0
Total length: 14
Shutdown Socket successful :  RC = 0
Response Message:
08 01 00 00 04 00 0d 00 00 00 00 00 00 00

Signed-off-by: John Wang <wangzqbj@inspur.com>
Change-Id: I658b2c8094e9e5d972d786b26f9f8d52bc011981
diff --git a/tool/pldmtool.cpp b/tool/pldmtool.cpp
index 54287d5..7244e47 100644
--- a/tool/pldmtool.cpp
+++ b/tool/pldmtool.cpp
@@ -1,108 +1,72 @@
-#include "handler.hpp"
+#include "pldm_base_cmd.hpp"
+#include "pldm_cmd_helper.hpp"
 
 #include <CLI/CLI.hpp>
 
+namespace pldmtool
+{
+
+namespace raw
+{
+
+using namespace pldmtool::helper;
+
+namespace
+{
+std::vector<std::unique_ptr<CommandInterface>> commands;
+}
+
+class RawOp : public CommandInterface
+{
+  public:
+    ~RawOp() = default;
+    RawOp() = delete;
+    RawOp(const RawOp&) = delete;
+    RawOp(RawOp&&) = default;
+    RawOp& operator=(const RawOp&) = delete;
+    RawOp& operator=(RawOp&&) = default;
+
+    explicit RawOp(const char* type, const char* name, CLI::App* app) :
+        CommandInterface(type, name, app)
+    {
+        app->add_option("-d,--data", rawData, "raw data")
+            ->required()
+            ->expected(-3);
+    }
+    std::pair<int, std::vector<uint8_t>> createRequestMsg() override
+
+    {
+        return {PLDM_SUCCESS, rawData};
+    }
+
+    void parseResponseMsg(pldm_msg* /* responsePtr */,
+                          size_t /* payloadLength */) override
+    {
+    }
+
+  private:
+    std::vector<uint8_t> rawData;
+};
+
+void registerCommand(CLI::App& app)
+{
+    auto raw =
+        app.add_subcommand("raw", "send a raw request and print response");
+    commands.push_back(std::make_unique<RawOp>("raw", "raw", raw));
+}
+
+} // namespace raw
+} // namespace pldmtool
+
 int main(int argc, char** argv)
 {
 
     CLI::App app{"PLDM requester tool for OpenBMC"};
+    app.require_subcommand(1)->ignore_case();
 
-    // TODO: To enable it later
-    // bool verbose_flag = false;
-    // app.add_flag("-v, --verbose", verbose_flag, "Output debug logs ");
-    std::vector<std::string> rawCmd{};
-    app.add_option("-r, --raw", rawCmd,
-                   "Send a RAW PLDM request and print response");
-
-    auto base = app.add_subcommand("BASE", "PLDM Command Type = BASE");
-    std::vector<std::string> args{};
-    base->add_option("-c, --command", args,
-                     "PLDM request command \n"
-                     "[GetPLDMTypes] Get PLDM Type \n"
-                     "[GetPLDMVersion] Get PLDM Version");
-
-    auto bios = app.add_subcommand("BIOS", "PLDM Command Type = BIOS");
-    bios->add_option("-c, --command", args, "PLDM request command");
-
-    auto oem = app.add_subcommand("OEM", "PLDM Command Type = OEM");
-    oem->add_option("-c, --command", args, "PLDM request command");
+    pldmtool::raw::registerCommand(app);
+    pldmtool::base::registerCommand(app);
 
     CLI11_PARSE(app, argc, argv);
-
-    std::string cmdName;
-    int rc = 0;
-
-    if (argc < 2)
-    {
-        std::cerr << "Run pldmtool --help for more information" << std::endl;
-        return -1;
-    }
-
-    if (memcmp(argv[1], "--raw", strlen(argv[1])) != 0 &&
-        memcmp(argv[1], "-r", strlen(argv[1])) != 0)
-    {
-        // Parse args to program
-        if (args.size() == 0)
-        {
-            std::cerr << "Run pldmtool --help for more information"
-                      << std::endl;
-            return -1;
-        }
-        cmdName = args[0];
-    }
-    else
-    {
-        if (rawCmd.size() == 0)
-        {
-            std::cerr << "Run pldmtool --help for more information"
-                      << std::endl;
-            return -1;
-        }
-
-        // loop through the remaining argument list
-        for (auto&& item : rawCmd)
-        {
-
-            if (item[0] == '0' && (item[1] == 'x' || item[1] == 'X'))
-            {
-
-                // Erase 0x from input
-                item.erase(0, 2);
-
-                // Check for hex input value validity
-                if (std::all_of(item.begin(), item.end(), ::isxdigit))
-                {
-
-                    // Parse args to program
-                    cmdName = "HandleRawOp";
-                }
-                else
-                {
-                    std::cerr << item << " contains non hex digits. Re-enter"
-                              << std::endl;
-                    return -1;
-                }
-            }
-            else
-            {
-                std::cerr << item << " Input hex value starting with 0x "
-                          << std::endl;
-                return -1;
-            }
-        }
-        args = rawCmd;
-    }
-
-    Handler handler;
-    try
-    {
-        handler.dispatcher.at(cmdName)(std::move(args));
-    }
-    catch (const std::out_of_range& e)
-    {
-        std::cerr << cmdName << " is not supported!" << std::endl;
-        return -1;
-    }
-
-    return rc;
+    return 0;
 }