|  | //===-- 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 <iomanip> | 
|  | #include <sstream> | 
|  | #include <string> | 
|  | #include <utility> | 
|  | #include <vector> | 
|  |  | 
|  | //---------------------------------------------------------------------- | 
|  | /// @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<Object> ObjectSP; | 
|  | typedef std::shared_ptr<Array> ArraySP; | 
|  | typedef std::shared_ptr<Integer> IntegerSP; | 
|  | typedef std::shared_ptr<Float> FloatSP; | 
|  | typedef std::shared_ptr<Boolean> BooleanSP; | 
|  | typedef std::shared_ptr<String> StringSP; | 
|  | typedef std::shared_ptr<Dictionary> DictionarySP; | 
|  | typedef std::shared_ptr<Generic> GenericSP; | 
|  |  | 
|  | enum class Type | 
|  | { | 
|  | eTypeInvalid = -1, | 
|  | eTypeNull = 0, | 
|  | eTypeGeneric, | 
|  | eTypeArray, | 
|  | eTypeInteger, | 
|  | eTypeFloat, | 
|  | eTypeBoolean, | 
|  | eTypeString, | 
|  | eTypeDictionary | 
|  | }; | 
|  |  | 
|  | class Object : | 
|  | public std::enable_shared_from_this<Object> | 
|  | { | 
|  | 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<ObjectSP> 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<std::string, ObjectSP> Pair; | 
|  | typedef std::vector<Pair> 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_ |