1 /**
2  * Copyright © 2019 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "json_utils.hpp"
17 
18 #include <stdio.h>
19 
20 #include <cstring>
21 #include <sstream>
22 #include <string>
23 
24 namespace openpower
25 {
26 namespace pels
27 {
28 
29 std::string escapeJSON(const std::string& input)
30 {
31     std::string output;
32     output.reserve(input.length());
33 
34     for (const auto c : input)
35     {
36         switch (c)
37         {
38             case '"':
39                 output += "\\\"";
40                 break;
41             case '/':
42                 output += "\\/";
43                 break;
44             case '\b':
45                 output += "\\b";
46                 break;
47             case '\f':
48                 output += "\\f";
49                 break;
50             case '\n':
51                 output += "\\n";
52                 break;
53             case '\r':
54                 output += "\\r";
55                 break;
56             case '\t':
57                 output += "\\t";
58                 break;
59             case '\\':
60                 output += "\\\\";
61                 break;
62             default:
63                 output += c;
64                 break;
65         }
66     }
67 
68     return output;
69 }
70 char* dumpHex(const void* data, size_t size)
71 {
72     const int symbolSize = 100;
73     std::string jsonIndent(indentLevel, 0x20);
74     jsonIndent.append("\"");
75     char* buffer = (char*)calloc(10 * size, sizeof(char));
76     char* symbol = (char*)calloc(symbolSize, sizeof(char));
77     char ascii[17];
78     size_t i, j;
79     ascii[16] = '\0';
80     for (i = 0; i < size; ++i)
81     {
82         if (i % 16 == 0)
83         {
84             strcat(buffer, jsonIndent.c_str());
85         }
86         snprintf(symbol, symbolSize, "%02X ", ((unsigned char*)data)[i]);
87         strcat(buffer, symbol);
88         memset(symbol, 0, strlen(symbol));
89         if (((unsigned char*)data)[i] >= ' ' &&
90             ((unsigned char*)data)[i] <= '~')
91         {
92             ascii[i % 16] = ((unsigned char*)data)[i];
93         }
94         else
95         {
96             ascii[i % 16] = '.';
97         }
98         if ((i + 1) % 8 == 0 || i + 1 == size)
99         {
100             std::string asciiString(ascii);
101             asciiString = escapeJSON(asciiString);
102             const char* asciiToPrint = asciiString.c_str();
103             strcat(buffer, " ");
104             if ((i + 1) % 16 == 0)
105             {
106                 if (i + 1 != size)
107                 {
108                     snprintf(symbol, symbolSize, "|  %s\",\n", asciiToPrint);
109                 }
110                 else
111                 {
112                     snprintf(symbol, symbolSize, "|  %s\"\n", asciiToPrint);
113                 }
114                 strcat(buffer, symbol);
115                 memset(symbol, 0, strlen(symbol));
116             }
117             else if (i + 1 == size)
118             {
119                 ascii[(i + 1) % 16] = '\0';
120                 if ((i + 1) % 16 <= 8)
121                 {
122                     strcat(buffer, " ");
123                 }
124                 for (j = (i + 1) % 16; j < 16; ++j)
125                 {
126                     strcat(buffer, "   ");
127                 }
128                 std::string asciiString2(ascii);
129                 asciiString2 = escapeJSON(asciiString2);
130                 asciiToPrint = asciiString2.c_str();
131                 snprintf(symbol, symbolSize, "|  %s\"\n", asciiToPrint);
132                 strcat(buffer, symbol);
133                 memset(symbol, 0, strlen(symbol));
134             }
135         }
136     }
137     free(symbol);
138     return buffer;
139 }
140 
141 void jsonInsert(std::string& jsonStr, const std::string& fieldName,
142                 std::string fieldValue, uint8_t indentCount)
143 {
144     const int8_t spacesToAppend =
145         colAlign - (indentCount * indentLevel) - fieldName.length() - 3;
146     const std::string jsonIndent(indentCount * indentLevel, 0x20);
147     jsonStr.append(jsonIndent + "\"" + fieldName + "\":");
148     if (spacesToAppend >= 0)
149     {
150         jsonStr.append(spacesToAppend, 0x20);
151     }
152     else
153     {
154         jsonStr.append(1, 0x20);
155     }
156     jsonStr.append("\"" + fieldValue + "\",\n");
157 }
158 
159 void jsonInsertArray(std::string& jsonStr, const std::string& fieldName,
160                      std::vector<std::string>& values, uint8_t indentCount)
161 {
162     const std::string jsonIndent(indentCount * indentLevel, 0x20);
163     if (!values.empty())
164     {
165         jsonStr.append(jsonIndent + "\"" + fieldName + "\": [\n");
166         for (size_t i = 0; i < values.size(); i++)
167         {
168             jsonStr.append(colAlign, 0x20);
169             if (i == values.size() - 1)
170             {
171                 jsonStr.append("\"" + values[i] + "\"\n");
172             }
173             else
174             {
175                 jsonStr.append("\"" + values[i] + "\",\n");
176             }
177         }
178         jsonStr.append(jsonIndent + "],\n");
179     }
180     else
181     {
182         const int8_t spacesToAppend =
183             colAlign - (indentCount * indentLevel) - fieldName.length() - 3;
184         jsonStr.append(jsonIndent + "\"" + fieldName + "\":");
185         if (spacesToAppend > 0)
186         {
187             jsonStr.append(spacesToAppend, 0x20);
188         }
189         else
190         {
191             jsonStr.append(1, 0x20);
192         }
193         jsonStr.append("[],\n");
194     }
195 }
196 
197 std::string trimEnd(std::string s)
198 {
199     const char* t = " \t\n\r\f\v";
200     if (s.find_last_not_of(t) != std::string::npos)
201     {
202         s.erase(s.find_last_not_of(t) + 1);
203     }
204     return s;
205 }
206 } // namespace pels
207 } // namespace openpower
208