| //===-- 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_ |