forked from OSchip/llvm-project
320 lines
7.7 KiB
C++
320 lines
7.7 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_
|