//===-- JSONGenerator.h ----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef __JSONGenerator_h_ #define __JSONGenerator_h_ // C Includes // C++ Includes #include #include #include #include #include //---------------------------------------------------------------------- /// @class JSONGenerator JSONGenerator.h /// @brief A class which can construct structured data for the sole purpose /// of printing it in JSON format. /// /// A stripped down version of lldb's StructuredData objects which are much /// general purpose. This variant is intended only for assembling information /// and printing it as a JSON string. //---------------------------------------------------------------------- class JSONGenerator { public: class Object; class Array; class Integer; class Float; class Boolean; class String; class Dictionary; class Generic; typedef std::shared_ptr ObjectSP; typedef std::shared_ptr ArraySP; typedef std::shared_ptr IntegerSP; typedef std::shared_ptr FloatSP; typedef std::shared_ptr BooleanSP; typedef std::shared_ptr StringSP; typedef std::shared_ptr DictionarySP; typedef std::shared_ptr GenericSP; enum class Type { eTypeInvalid = -1, eTypeNull = 0, eTypeGeneric, eTypeArray, eTypeInteger, eTypeFloat, eTypeBoolean, eTypeString, eTypeDictionary }; class Object : public std::enable_shared_from_this { public: Object (Type t = Type::eTypeInvalid) : m_type (t) { } virtual ~Object () { } virtual bool IsValid() const { return true; } virtual void Clear () { m_type = Type::eTypeInvalid; } Type GetType () const { return m_type; } void SetType (Type t) { m_type = t; } Array * GetAsArray () { if (m_type == Type::eTypeArray) return (Array *)this; return NULL; } Dictionary * GetAsDictionary () { if (m_type == Type::eTypeDictionary) return (Dictionary *)this; return NULL; } Integer * GetAsInteger () { if (m_type == Type::eTypeInteger) return (Integer *)this; return NULL; } Float * GetAsFloat () { if (m_type == Type::eTypeFloat) return (Float *)this; return NULL; } Boolean * GetAsBoolean () { if (m_type == Type::eTypeBoolean) return (Boolean *)this; return NULL; } String * GetAsString () { if (m_type == Type::eTypeString) return (String *)this; return NULL; } Generic * GetAsGeneric() { if (m_type == Type::eTypeGeneric) return (Generic *)this; return NULL; } virtual void Dump (std::ostream &s) const = 0; private: Type m_type; }; class Array : public Object { public: Array () : Object (Type::eTypeArray) { } virtual ~Array() { } void AddItem(ObjectSP item) { m_items.push_back(item); } void Dump(std::ostream &s) const override { s << "["; const size_t arrsize = m_items.size(); for (size_t i = 0; i < arrsize; ++i) { m_items[i]->Dump(s); if (i + 1 < arrsize) s << ","; } s << "]"; } protected: typedef std::vector collection; collection m_items; }; class Integer : public Object { public: Integer (uint64_t value = 0) : Object (Type::eTypeInteger), m_value (value) { } virtual ~Integer() { } void SetValue (uint64_t value) { m_value = value; } void Dump(std::ostream &s) const override { s << m_value; } protected: uint64_t m_value; }; class Float : public Object { public: Float (double d = 0.0) : Object (Type::eTypeFloat), m_value (d) { } virtual ~Float() { } void SetValue (double value) { m_value = value; } void Dump(std::ostream &s) const override { s << m_value; } protected: double m_value; }; class Boolean : public Object { public: Boolean (bool b = false) : Object (Type::eTypeBoolean), m_value (b) { } virtual ~Boolean() { } void SetValue (bool value) { m_value = value; } void Dump(std::ostream &s) const override { if (m_value == true) s << "true"; else s << "false"; } protected: bool m_value; }; class String : public Object { public: String () : Object (Type::eTypeString), m_value () { } String (const std::string &s) : Object (Type::eTypeString), m_value (s) { } String (const std::string &&s) : Object (Type::eTypeString), m_value (s) { } void SetValue (const std::string &string) { m_value = string; } void Dump(std::ostream &s) const override { std::string quoted; const size_t strsize = m_value.size(); for (size_t i = 0; i < strsize ; ++i) { char ch = m_value[i]; if (ch == '"') quoted.push_back ('\\'); quoted.push_back (ch); } s << '"' << quoted.c_str() << '"'; } protected: std::string m_value; }; class Dictionary : public Object { public: Dictionary () : Object (Type::eTypeDictionary), m_dict () { } virtual ~Dictionary() { } void AddItem (std::string key, ObjectSP value) { m_dict.push_back(Pair(key, value)); } void AddIntegerItem (std::string key, uint64_t value) { AddItem (key, ObjectSP (new Integer(value))); } void AddFloatItem (std::string key, double value) { AddItem (key, ObjectSP (new Float(value))); } void AddStringItem (std::string key, std::string value) { AddItem (key, ObjectSP (new String(std::move(value)))); } void AddBytesAsHexASCIIString (std::string key, const uint8_t *src, size_t src_len) { if (src && src_len) { std::ostringstream strm; for (size_t i = 0; i < src_len; i++) strm << std::setfill('0') << std::hex << std::right << std::setw(2) << ((uint32_t)(src[i])); AddItem (key, ObjectSP (new String(std::move(strm.str())))); } else { AddItem (key, ObjectSP (new String())); } } void AddBooleanItem (std::string key, bool value) { AddItem (key, ObjectSP (new Boolean(value))); } void Dump(std::ostream &s) const override { bool have_printed_one_elem = false; s << "{"; for (collection::const_iterator iter = m_dict.begin(); iter != m_dict.end(); ++iter) { if (have_printed_one_elem == false) { have_printed_one_elem = true; } else { s << ","; } s << "\"" << iter->first.c_str() << "\":"; iter->second->Dump(s); } s << "}"; } protected: // Keep the dictionary as a vector so the dictionary doesn't reorder itself when you dump it // We aren't accessing keys by name, so this won't affect performance typedef std::pair Pair; typedef std::vector collection; collection m_dict; }; class Null : public Object { public: Null () : Object (Type::eTypeNull) { } virtual ~Null() { } bool IsValid() const override { return false; } void Dump(std::ostream &s) const override { s << "null"; } protected: }; class Generic : public Object { public: explicit Generic(void *object = nullptr) : Object(Type::eTypeGeneric) , m_object(object) { } void SetValue(void *value) { m_object = value; } void * GetValue() const { return m_object; } bool IsValid() const override { return m_object != nullptr; } void Dump(std::ostream &s) const override; private: void *m_object; }; }; // class JSONGenerator #endif // __JSONGenerator_h_