1 //===-- JSONGenerator.h ----------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef __JSONGenerator_h_ 10 #define __JSONGenerator_h_ 11 12 13 #include <iomanip> 14 #include <sstream> 15 #include <string> 16 #include <utility> 17 #include <vector> 18 19 //---------------------------------------------------------------------- 20 /// \class JSONGenerator JSONGenerator.h 21 /// A class which can construct structured data for the sole purpose 22 /// of printing it in JSON format. 23 /// 24 /// A stripped down version of lldb's StructuredData objects which are much 25 /// general purpose. This variant is intended only for assembling information 26 /// and printing it as a JSON string. 27 //---------------------------------------------------------------------- 28 29 class JSONGenerator { 30 public: 31 class Object; 32 class Array; 33 class Integer; 34 class Float; 35 class Boolean; 36 class String; 37 class Dictionary; 38 class Generic; 39 40 typedef std::shared_ptr<Object> ObjectSP; 41 typedef std::shared_ptr<Array> ArraySP; 42 typedef std::shared_ptr<Integer> IntegerSP; 43 typedef std::shared_ptr<Float> FloatSP; 44 typedef std::shared_ptr<Boolean> BooleanSP; 45 typedef std::shared_ptr<String> StringSP; 46 typedef std::shared_ptr<Dictionary> DictionarySP; 47 typedef std::shared_ptr<Generic> GenericSP; 48 49 enum class Type { 50 eTypeInvalid = -1, 51 eTypeNull = 0, 52 eTypeGeneric, 53 eTypeArray, 54 eTypeInteger, 55 eTypeFloat, 56 eTypeBoolean, 57 eTypeString, 58 eTypeDictionary 59 }; 60 61 class Object : public std::enable_shared_from_this<Object> { 62 public: 63 Object(Type t = Type::eTypeInvalid) : m_type(t) {} 64 65 virtual ~Object() {} 66 67 virtual bool IsValid() const { return true; } 68 69 virtual void Clear() { m_type = Type::eTypeInvalid; } 70 71 Type GetType() const { return m_type; } 72 73 void SetType(Type t) { m_type = t; } 74 75 Array *GetAsArray() { 76 if (m_type == Type::eTypeArray) 77 return (Array *)this; 78 return NULL; 79 } 80 81 Dictionary *GetAsDictionary() { 82 if (m_type == Type::eTypeDictionary) 83 return (Dictionary *)this; 84 return NULL; 85 } 86 87 Integer *GetAsInteger() { 88 if (m_type == Type::eTypeInteger) 89 return (Integer *)this; 90 return NULL; 91 } 92 93 Float *GetAsFloat() { 94 if (m_type == Type::eTypeFloat) 95 return (Float *)this; 96 return NULL; 97 } 98 99 Boolean *GetAsBoolean() { 100 if (m_type == Type::eTypeBoolean) 101 return (Boolean *)this; 102 return NULL; 103 } 104 105 String *GetAsString() { 106 if (m_type == Type::eTypeString) 107 return (String *)this; 108 return NULL; 109 } 110 111 Generic *GetAsGeneric() { 112 if (m_type == Type::eTypeGeneric) 113 return (Generic *)this; 114 return NULL; 115 } 116 117 virtual void Dump(std::ostream &s) const = 0; 118 119 private: 120 Type m_type; 121 }; 122 123 class Array : public Object { 124 public: 125 Array() : Object(Type::eTypeArray) {} 126 127 virtual ~Array() {} 128 129 void AddItem(ObjectSP item) { m_items.push_back(item); } 130 131 void Dump(std::ostream &s) const override { 132 s << "["; 133 const size_t arrsize = m_items.size(); 134 for (size_t i = 0; i < arrsize; ++i) { 135 m_items[i]->Dump(s); 136 if (i + 1 < arrsize) 137 s << ","; 138 } 139 s << "]"; 140 } 141 142 protected: 143 typedef std::vector<ObjectSP> collection; 144 collection m_items; 145 }; 146 147 class Integer : public Object { 148 public: 149 Integer(uint64_t value = 0) : Object(Type::eTypeInteger), m_value(value) {} 150 151 virtual ~Integer() {} 152 153 void SetValue(uint64_t value) { m_value = value; } 154 155 void Dump(std::ostream &s) const override { s << m_value; } 156 157 protected: 158 uint64_t m_value; 159 }; 160 161 class Float : public Object { 162 public: 163 Float(double d = 0.0) : Object(Type::eTypeFloat), m_value(d) {} 164 165 virtual ~Float() {} 166 167 void SetValue(double value) { m_value = value; } 168 169 void Dump(std::ostream &s) const override { s << m_value; } 170 171 protected: 172 double m_value; 173 }; 174 175 class Boolean : public Object { 176 public: 177 Boolean(bool b = false) : Object(Type::eTypeBoolean), m_value(b) {} 178 179 virtual ~Boolean() {} 180 181 void SetValue(bool value) { m_value = value; } 182 183 void Dump(std::ostream &s) const override { 184 if (m_value) 185 s << "true"; 186 else 187 s << "false"; 188 } 189 190 protected: 191 bool m_value; 192 }; 193 194 class String : public Object { 195 public: 196 String() : Object(Type::eTypeString), m_value() {} 197 198 String(const std::string &s) : Object(Type::eTypeString), m_value(s) {} 199 200 String(const std::string &&s) : Object(Type::eTypeString), m_value(s) {} 201 202 void SetValue(const std::string &string) { m_value = string; } 203 204 void Dump(std::ostream &s) const override { 205 std::string quoted; 206 const size_t strsize = m_value.size(); 207 for (size_t i = 0; i < strsize; ++i) { 208 char ch = m_value[i]; 209 if (ch == '"') 210 quoted.push_back('\\'); 211 quoted.push_back(ch); 212 } 213 s << '"' << quoted.c_str() << '"'; 214 } 215 216 protected: 217 std::string m_value; 218 }; 219 220 class Dictionary : public Object { 221 public: 222 Dictionary() : Object(Type::eTypeDictionary), m_dict() {} 223 224 virtual ~Dictionary() {} 225 226 void AddItem(std::string key, ObjectSP value) { 227 m_dict.push_back(Pair(key, value)); 228 } 229 230 void AddIntegerItem(std::string key, uint64_t value) { 231 AddItem(key, ObjectSP(new Integer(value))); 232 } 233 234 void AddFloatItem(std::string key, double value) { 235 AddItem(key, ObjectSP(new Float(value))); 236 } 237 238 void AddStringItem(std::string key, std::string value) { 239 AddItem(key, ObjectSP(new String(std::move(value)))); 240 } 241 242 void AddBytesAsHexASCIIString(std::string key, const uint8_t *src, 243 size_t src_len) { 244 if (src && src_len) { 245 std::ostringstream strm; 246 for (size_t i = 0; i < src_len; i++) 247 strm << std::setfill('0') << std::hex << std::right << std::setw(2) 248 << ((uint32_t)(src[i])); 249 AddItem(key, ObjectSP(new String(std::move(strm.str())))); 250 } else { 251 AddItem(key, ObjectSP(new String())); 252 } 253 } 254 255 void AddBooleanItem(std::string key, bool value) { 256 AddItem(key, ObjectSP(new Boolean(value))); 257 } 258 259 void Dump(std::ostream &s) const override { 260 bool have_printed_one_elem = false; 261 s << "{"; 262 for (collection::const_iterator iter = m_dict.begin(); 263 iter != m_dict.end(); ++iter) { 264 if (!have_printed_one_elem) { 265 have_printed_one_elem = true; 266 } else { 267 s << ","; 268 } 269 s << "\"" << iter->first.c_str() << "\":"; 270 iter->second->Dump(s); 271 } 272 s << "}"; 273 } 274 275 protected: 276 // Keep the dictionary as a vector so the dictionary doesn't reorder itself 277 // when you dump it 278 // We aren't accessing keys by name, so this won't affect performance 279 typedef std::pair<std::string, ObjectSP> Pair; 280 typedef std::vector<Pair> collection; 281 collection m_dict; 282 }; 283 284 class Null : public Object { 285 public: 286 Null() : Object(Type::eTypeNull) {} 287 288 virtual ~Null() {} 289 290 bool IsValid() const override { return false; } 291 292 void Dump(std::ostream &s) const override { s << "null"; } 293 294 protected: 295 }; 296 297 class Generic : public Object { 298 public: 299 explicit Generic(void *object = nullptr) 300 : Object(Type::eTypeGeneric), m_object(object) {} 301 302 void SetValue(void *value) { m_object = value; } 303 304 void *GetValue() const { return m_object; } 305 306 bool IsValid() const override { return m_object != nullptr; } 307 308 void Dump(std::ostream &s) const override; 309 310 private: 311 void *m_object; 312 }; 313 314 }; // class JSONGenerator 315 316 #endif // __JSONGenerator_h_ 317