491 lines
10 KiB
C
491 lines
10 KiB
C
|
//===-- 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_
|