hanchenye-llvm-project/lldb/tools/debugserver/source/JSONGenerator.h

491 lines
10 KiB
C
Raw Normal View History

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