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