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