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