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