vpd-tool:UTF-8 encoding support on hardware read

Keyword values when in unreadable format may need to be converted
to Hex. This code converts data from HW to readable format.

Test:
root@bonn003:~# tmp/vpd-tool -r -H -O "/sys/bus/i2c/drivers/at24/8-0050/eeprom" -R VINI -K SN
{
    "/sys/bus/i2c/drivers/at24/8-0050/eeprom": {
        "SN": "YF30UF31C007"
    }
}
root@bonn003:~# tmp/vpd-tool -r -H -O "/sys/bus/i2c/drivers/at24/8-0050/eeprom" -R VINI -K HW
{
    "/sys/bus/i2c/drivers/at24/8-0050/eeprom": {
        "HW": "0x8001"
    }
}

Change-Id: I28d9189d95202a565bcba81299f2e548cb4cb83a
Signed-off-by: Giridhari Krishna <giridharikrishnan@gmail.com>
diff --git a/ibm_vpd_utils.cpp b/ibm_vpd_utils.cpp
index 8d93606..f717c13 100644
--- a/ibm_vpd_utils.cpp
+++ b/ibm_vpd_utils.cpp
@@ -676,47 +676,57 @@
     return kwVal;
 }
 
-std::string byteArrayToHexString(const Binary& vec)
+std::string hexString(const std::variant<Binary, std::string>& kw)
 {
-    std::stringstream ss;
-    std::string hexRep = "0x";
-    ss << hexRep;
-    std::string str = ss.str();
-
-    // convert Decimal to Hex string
-    for (auto& v : vec)
-    {
-        ss << std::setfill('0') << std::setw(2) << std::hex << (int)v;
-        str = ss.str();
-    }
-    return str;
+    std::string hexString;
+    std::visit(
+        [&hexString](auto&& kw) {
+            for (auto& kwVal : kw)
+            {
+                std::stringstream ss;
+                std::string hexRep = "0x";
+                ss << hexRep;
+                ss << std::setfill('0') << std::setw(2) << std::hex
+                   << static_cast<int>(kwVal);
+                hexString = ss.str();
+            }
+        },
+        kw);
+    return hexString;
 }
 
-std::string getPrintableValue(const Binary& vec)
+std::string getPrintableValue(const std::variant<Binary, std::string>& kwVal)
 {
-    std::string str{};
-
-    // find for a non printable value in the vector
-    const auto it = std::find_if(vec.begin(), vec.end(),
-                                 [](const auto& ele) { return !isprint(ele); });
-
-    if (it != vec.end()) // if the given vector has any non printable value
-    {
-        for (auto itr = it; itr != vec.end(); itr++)
-        {
-            if (*itr != 0x00)
+    std::string kwString{};
+    std::visit(
+        [&kwString](auto&& kwVal) {
+            const auto it =
+                std::find_if(kwVal.begin(), kwVal.end(),
+                             [](const auto& kw) { return !isprint(kw); });
+            if (it != kwVal.end())
             {
-                str = byteArrayToHexString(vec);
-                return str;
+                bool printable = true;
+                for (auto itr = it; itr != kwVal.end(); itr++)
+                {
+                    if (*itr != 0x00)
+                    {
+                        kwString = hexString(kwVal);
+                        printable = false;
+                        break;
+                    }
+                }
+                if (printable)
+                {
+                    kwString = std::string(kwVal.begin(), it);
+                }
             }
-        }
-        str = std::string(vec.begin(), it);
-    }
-    else
-    {
-        str = std::string(vec.begin(), vec.end());
-    }
-    return str;
+            else
+            {
+                kwString = std::string(kwVal.begin(), kwVal.end());
+            }
+        },
+        kwVal);
+    return kwString;
 }
 
 void executePostFailAction(const nlohmann::json& json, const std::string& file)
@@ -1043,4 +1053,4 @@
     return vpdVector;
 }
 } // namespace vpd
-} // namespace openpower
+} // namespace openpower
\ No newline at end of file
diff --git a/ibm_vpd_utils.hpp b/ibm_vpd_utils.hpp
index 18ee819..46a707a 100644
--- a/ibm_vpd_utils.hpp
+++ b/ibm_vpd_utils.hpp
@@ -7,6 +7,7 @@
 #include <iostream>
 #include <nlohmann/json.hpp>
 #include <optional>
+#include <variant>
 
 namespace openpower
 {
@@ -354,21 +355,21 @@
 /**
  * @brief Get Printable Value
  *
- * Checks if the vector value has non printable characters.
+ * Checks if the value has non printable characters.
  * Returns hex value if non printable char is found else
  * returns ascii value.
  *
- * @param[in] vector - Reference of the Binary vector
+ * @param[in] kwVal - Reference of the input data, Keyword value
  * @return printable value - either in hex or in ascii.
  */
-std::string getPrintableValue(const Binary& vec);
+std::string getPrintableValue(const std::variant<Binary, std::string>& kwVal);
 
 /**
- * @brief Convert byte array to hex string.
- * @param[in] vec - byte array
+ * @brief Convert array to hex string.
+ * @param[in] kwVal - input data, Keyword value
  * @return hexadecimal string of bytes.
  */
-std::string byteArrayToHexString(const Binary& vec);
+std::string hexString(const std::variant<Binary, std::string>& kwVal);
 
 /**
  * @brief Return presence of the FRU.
diff --git a/vpd_tool_impl.cpp b/vpd_tool_impl.cpp
index 0fc8755..93c4d40 100644
--- a/vpd_tool_impl.cpp
+++ b/vpd_tool_impl.cpp
@@ -431,8 +431,8 @@
     }
     catch (const json::exception& e)
     {
-        json output = json::object({});
-        json kwVal = json::object({});
+        std::cout << "Keyword Value: " << keyword << std::endl;
+        std::cout << e.what() << std::endl;
     }
 }
 
@@ -562,7 +562,7 @@
     {
         json output = json::object({});
         json kwVal = json::object({});
-        kwVal.emplace(keyword, keywordVal);
+        kwVal.emplace(keyword, getPrintableValue(keywordVal));
 
         output.emplace(fruPath, kwVal);
 
@@ -712,7 +712,7 @@
                 }
             }
 
-            if (keyword != "SE")
+            if (keyword != "SE") // SE to display in Hex string only
             {
                 ostringstream hwValStream;
                 hwValStream << "0x";
@@ -726,7 +726,7 @@
 
                 if (const auto value = get_if<Binary>(&kwValue))
                 {
-                    busStr = byteArrayToHexString(*value);
+                    busStr = hexString(*value);
                 }
                 if (busStr != hwValStr)
                 {