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