PEL: Print action flags into JSON aligned

"User Header": {
    "Section Version":          "1",
    "Sub-section type":         "0",
    "Log Committed by":         "0x4552",
    "Subsystem":                "System Hypervisor Firmware",
    "Event Scope":              "Entire Platform",
    "Event Severity":           "Informational Event",
    "Event Type":               "Miscellaneous, Informational Only",
    "Action Flags": [
                                "Report Externally"
    ]
}

Testing: Manually run peltool and verified output
Signed-off-by: Harisuddin Mohamed Isa <harisuddin@gmail.com>
Change-Id: Ie8376953b5f1baa093fc0aa9564d50cd4208564e
diff --git a/extensions/openpower-pels/json_utils.cpp b/extensions/openpower-pels/json_utils.cpp
new file mode 100644
index 0000000..c6ea9f6
--- /dev/null
+++ b/extensions/openpower-pels/json_utils.cpp
@@ -0,0 +1,197 @@
+/**
+ * Copyright © 2019 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 "json_utils.hpp"
+
+#include <stdio.h>
+
+#include <cstring>
+#include <sstream>
+#include <string>
+
+namespace openpower
+{
+namespace pels
+{
+
+std::string escapeJSON(const std::string& input)
+{
+    std::string output;
+    output.reserve(input.length());
+
+    for (const auto c : input)
+    {
+        switch (c)
+        {
+            case '"':
+                output += "\\\"";
+                break;
+            case '/':
+                output += "\\/";
+                break;
+            case '\b':
+                output += "\\b";
+                break;
+            case '\f':
+                output += "\\f";
+                break;
+            case '\n':
+                output += "\\n";
+                break;
+            case '\r':
+                output += "\\r";
+                break;
+            case '\t':
+                output += "\\t";
+                break;
+            case '\\':
+                output += "\\\\";
+                break;
+            default:
+                output += c;
+                break;
+        }
+    }
+
+    return output;
+}
+char* dumpHex(const void* data, size_t size)
+{
+    const int symbolSize = 100;
+    std::string jsonIndent(indentLevel, 0x20);
+    jsonIndent.append("\"");
+    char* buffer = (char*)calloc(10 * size, sizeof(char));
+    char* symbol = (char*)calloc(symbolSize, sizeof(char));
+    char ascii[17];
+    size_t i, j;
+    ascii[16] = '\0';
+    for (i = 0; i < size; ++i)
+    {
+        if (i % 16 == 0)
+        {
+            strcat(buffer, jsonIndent.c_str());
+        }
+        snprintf(symbol, symbolSize, "%02X ", ((unsigned char*)data)[i]);
+        strcat(buffer, symbol);
+        memset(symbol, 0, strlen(symbol));
+        if (((unsigned char*)data)[i] >= ' ' &&
+            ((unsigned char*)data)[i] <= '~')
+        {
+            ascii[i % 16] = ((unsigned char*)data)[i];
+        }
+        else
+        {
+            ascii[i % 16] = '.';
+        }
+        if ((i + 1) % 8 == 0 || i + 1 == size)
+        {
+            std::string asciiString(ascii);
+            asciiString = escapeJSON(asciiString);
+            const char* asciiToPrint = asciiString.c_str();
+            strcat(buffer, " ");
+            if ((i + 1) % 16 == 0)
+            {
+                if (i + 1 != size)
+                {
+                    snprintf(symbol, symbolSize, "|  %s\",\n", asciiToPrint);
+                }
+                else
+                {
+                    snprintf(symbol, symbolSize, "|  %s\"\n", asciiToPrint);
+                }
+                strcat(buffer, symbol);
+                memset(symbol, 0, strlen(symbol));
+            }
+            else if (i + 1 == size)
+            {
+                ascii[(i + 1) % 16] = '\0';
+                if ((i + 1) % 16 <= 8)
+                {
+                    strcat(buffer, " ");
+                }
+                for (j = (i + 1) % 16; j < 16; ++j)
+                {
+                    strcat(buffer, "   ");
+                }
+                std::string asciiString2(ascii);
+                asciiString2 = escapeJSON(asciiString2);
+                asciiToPrint = asciiString2.c_str();
+                snprintf(symbol, symbolSize, "|  %s\"\n", asciiToPrint);
+                strcat(buffer, symbol);
+                memset(symbol, 0, strlen(symbol));
+            }
+        }
+    }
+    free(symbol);
+    return buffer;
+}
+
+void jsonInsert(std::string& jsonStr, const std::string& fieldName,
+                std::string& fieldValue, uint8_t indentCount)
+{
+    const int8_t spacesToAppend =
+        colAlign - (indentCount * indentLevel) - fieldName.length() - 3;
+    const std::string jsonIndent(indentCount * indentLevel, 0x20);
+    jsonStr.append(jsonIndent + "\"" + fieldName + "\":");
+    if (spacesToAppend > 0)
+    {
+        jsonStr.append(spacesToAppend, 0x20);
+    }
+    else
+    {
+        jsonStr.append(1, 0x20);
+    }
+    jsonStr.append("\"" + fieldValue + "\",\n");
+}
+
+void jsonInsertArray(std::string& jsonStr, const std::string& fieldName,
+                     std::vector<std::string>& values, uint8_t indentCount)
+{
+    const std::string jsonIndent(indentCount * indentLevel, 0x20);
+    if (!values.empty())
+    {
+        jsonStr.append(jsonIndent + "\"" + fieldName + "\": [\n");
+        for (size_t i = 0; i < values.size(); i++)
+        {
+            jsonStr.append(colAlign, 0x20);
+            if (i == values.size() - 1)
+            {
+                jsonStr.append("\"" + values[i] + "\"\n");
+            }
+            else
+            {
+                jsonStr.append("\"" + values[i] + "\",\n");
+            }
+        }
+        jsonStr.append(jsonIndent + "],\n");
+    }
+    else
+    {
+        const int8_t spacesToAppend =
+            colAlign - (indentCount * indentLevel) - fieldName.length() - 3;
+        jsonStr.append(jsonIndent + "\"" + fieldName + "\":");
+        if (spacesToAppend > 0)
+        {
+            jsonStr.append(spacesToAppend, 0x20);
+        }
+        else
+        {
+            jsonStr.append(1, 0x20);
+        }
+        jsonStr.append("[],\n");
+    }
+}
+} // namespace pels
+} // namespace openpower