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