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, size_t indentCount, bool toJson) 71 { 72 const int symbolSize = 100; 73 std::string jsonIndent(indentLevel * indentCount, 0x20); 74 if (toJson) 75 { 76 jsonIndent.append("\""); 77 } 78 char* buffer = (char*)calloc(std::max(70, 10 * (int)size), sizeof(char)); 79 char* symbol = (char*)calloc(symbolSize, sizeof(char)); 80 char* byteCount = (char*)calloc(11, sizeof(char)); 81 char ascii[17]; 82 size_t i, j; 83 ascii[16] = '\0'; 84 for (i = 0; i < size; ++i) 85 { 86 if (i % 16 == 0) 87 { 88 if (!toJson) 89 { 90 snprintf(byteCount, 11, "%08X ", static_cast<uint32_t>(i)); 91 strcat(buffer, byteCount); 92 } 93 strcat(buffer, jsonIndent.c_str()); 94 } 95 snprintf(symbol, symbolSize, "%02X ", ((unsigned char*)data)[i]); 96 strcat(buffer, symbol); 97 memset(symbol, 0, strlen(symbol)); 98 if (((unsigned char*)data)[i] >= ' ' && 99 ((unsigned char*)data)[i] <= '~') 100 { 101 ascii[i % 16] = ((unsigned char*)data)[i]; 102 } 103 else 104 { 105 ascii[i % 16] = '.'; 106 } 107 if ((i + 1) % 8 == 0 || i + 1 == size) 108 { 109 std::string asciiString(ascii); 110 if (toJson) 111 { 112 asciiString = escapeJSON(asciiString); 113 } 114 strcat(buffer, " "); 115 if ((i + 1) % 16 == 0) 116 { 117 if (i + 1 != size && toJson) 118 { 119 snprintf(symbol, symbolSize, "| %s\",\n", 120 asciiString.c_str()); 121 } 122 else if (toJson) 123 { 124 snprintf(symbol, symbolSize, "| %s\"\n", 125 asciiString.c_str()); 126 } 127 else 128 { 129 snprintf(symbol, symbolSize, "| %s\n", 130 asciiString.c_str()); 131 } 132 strcat(buffer, symbol); 133 memset(symbol, 0, strlen(symbol)); 134 } 135 else if (i + 1 == size) 136 { 137 ascii[(i + 1) % 16] = '\0'; 138 if ((i + 1) % 16 <= 8) 139 { 140 strcat(buffer, " "); 141 } 142 for (j = (i + 1) % 16; j < 16; ++j) 143 { 144 strcat(buffer, " "); 145 } 146 std::string asciiString2(ascii); 147 if (toJson) 148 { 149 asciiString2 = escapeJSON(asciiString2); 150 snprintf(symbol, symbolSize, "| %s\"\n", 151 asciiString2.c_str()); 152 } 153 else 154 { 155 snprintf(symbol, symbolSize, "| %s\n", 156 asciiString2.c_str()); 157 } 158 159 strcat(buffer, symbol); 160 memset(symbol, 0, strlen(symbol)); 161 } 162 } 163 } 164 free(byteCount); 165 free(symbol); 166 return buffer; 167 } 168 169 void jsonInsert(std::string& jsonStr, const std::string& fieldName, 170 const std::string& fieldValue, uint8_t indentCount) 171 { 172 const int8_t spacesToAppend = colAlign - (indentCount * indentLevel) - 173 fieldName.length() - 3; 174 const std::string jsonIndent(indentCount * indentLevel, 0x20); 175 jsonStr.append(jsonIndent + "\"" + fieldName + "\":"); 176 if (spacesToAppend >= 0) 177 { 178 jsonStr.append(spacesToAppend, 0x20); 179 } 180 else 181 { 182 jsonStr.append(1, 0x20); 183 } 184 jsonStr.append("\"" + fieldValue + "\",\n"); 185 } 186 187 void jsonInsertArray(std::string& jsonStr, const std::string& fieldName, 188 const std::vector<std::string>& values, 189 uint8_t indentCount) 190 { 191 const std::string jsonIndent(indentCount * indentLevel, 0x20); 192 if (!values.empty()) 193 { 194 jsonStr.append(jsonIndent + "\"" + fieldName + "\": [\n"); 195 for (size_t i = 0; i < values.size(); i++) 196 { 197 jsonStr.append(colAlign, 0x20); 198 if (i == values.size() - 1) 199 { 200 jsonStr.append("\"" + values[i] + "\"\n"); 201 } 202 else 203 { 204 jsonStr.append("\"" + values[i] + "\",\n"); 205 } 206 } 207 jsonStr.append(jsonIndent + "],\n"); 208 } 209 else 210 { 211 const int8_t spacesToAppend = colAlign - (indentCount * indentLevel) - 212 fieldName.length() - 3; 213 jsonStr.append(jsonIndent + "\"" + fieldName + "\":"); 214 if (spacesToAppend > 0) 215 { 216 jsonStr.append(spacesToAppend, 0x20); 217 } 218 else 219 { 220 jsonStr.append(1, 0x20); 221 } 222 jsonStr.append("[],\n"); 223 } 224 } 225 226 std::string trimEnd(std::string s) 227 { 228 const char* t = " \t\n\r\f\v"; 229 if (s.find_last_not_of(t) != std::string::npos) 230 { 231 s.erase(s.find_last_not_of(t) + 1); 232 } 233 return s; 234 } 235 } // namespace pels 236 } // namespace openpower 237