blob: 7af6ae60c5f75eec292dbffdf42f655d84980832 [file] [log] [blame]
Greg Claytonc9a2f6e2015-06-25 22:34:08 +00001//===-- JSONGenerator.h ----------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef __JSONGenerator_h_
11#define __JSONGenerator_h_
12
13// C Includes
14// C++ Includes
15
16#include <iomanip>
17#include <sstream>
18#include <string>
19#include <utility>
20#include <vector>
21
22//----------------------------------------------------------------------
23/// @class JSONGenerator JSONGenerator.h
Adrian Prantld8f460e2018-05-02 16:55:16 +000024/// A class which can construct structured data for the sole purpose
Greg Claytonc9a2f6e2015-06-25 22:34:08 +000025/// of printing it in JSON format.
26///
27/// A stripped down version of lldb's StructuredData objects which are much
28/// general purpose. This variant is intended only for assembling information
29/// and printing it as a JSON string.
30//----------------------------------------------------------------------
31
Kate Stoneb9c1b512016-09-06 20:57:50 +000032class JSONGenerator {
Greg Claytonc9a2f6e2015-06-25 22:34:08 +000033public:
Kate Stoneb9c1b512016-09-06 20:57:50 +000034 class Object;
35 class Array;
36 class Integer;
37 class Float;
38 class Boolean;
39 class String;
40 class Dictionary;
41 class Generic;
Greg Claytonc9a2f6e2015-06-25 22:34:08 +000042
Kate Stoneb9c1b512016-09-06 20:57:50 +000043 typedef std::shared_ptr<Object> ObjectSP;
44 typedef std::shared_ptr<Array> ArraySP;
45 typedef std::shared_ptr<Integer> IntegerSP;
46 typedef std::shared_ptr<Float> FloatSP;
47 typedef std::shared_ptr<Boolean> BooleanSP;
48 typedef std::shared_ptr<String> StringSP;
49 typedef std::shared_ptr<Dictionary> DictionarySP;
50 typedef std::shared_ptr<Generic> GenericSP;
Greg Claytonc9a2f6e2015-06-25 22:34:08 +000051
Kate Stoneb9c1b512016-09-06 20:57:50 +000052 enum class Type {
53 eTypeInvalid = -1,
54 eTypeNull = 0,
55 eTypeGeneric,
56 eTypeArray,
57 eTypeInteger,
58 eTypeFloat,
59 eTypeBoolean,
60 eTypeString,
61 eTypeDictionary
62 };
Greg Claytonc9a2f6e2015-06-25 22:34:08 +000063
Kate Stoneb9c1b512016-09-06 20:57:50 +000064 class Object : public std::enable_shared_from_this<Object> {
65 public:
66 Object(Type t = Type::eTypeInvalid) : m_type(t) {}
Greg Claytonc9a2f6e2015-06-25 22:34:08 +000067
Kate Stoneb9c1b512016-09-06 20:57:50 +000068 virtual ~Object() {}
Greg Claytonc9a2f6e2015-06-25 22:34:08 +000069
Kate Stoneb9c1b512016-09-06 20:57:50 +000070 virtual bool IsValid() const { return true; }
71
72 virtual void Clear() { m_type = Type::eTypeInvalid; }
73
74 Type GetType() const { return m_type; }
75
76 void SetType(Type t) { m_type = t; }
77
78 Array *GetAsArray() {
79 if (m_type == Type::eTypeArray)
80 return (Array *)this;
81 return NULL;
82 }
83
84 Dictionary *GetAsDictionary() {
85 if (m_type == Type::eTypeDictionary)
86 return (Dictionary *)this;
87 return NULL;
88 }
89
90 Integer *GetAsInteger() {
91 if (m_type == Type::eTypeInteger)
92 return (Integer *)this;
93 return NULL;
94 }
95
96 Float *GetAsFloat() {
97 if (m_type == Type::eTypeFloat)
98 return (Float *)this;
99 return NULL;
100 }
101
102 Boolean *GetAsBoolean() {
103 if (m_type == Type::eTypeBoolean)
104 return (Boolean *)this;
105 return NULL;
106 }
107
108 String *GetAsString() {
109 if (m_type == Type::eTypeString)
110 return (String *)this;
111 return NULL;
112 }
113
114 Generic *GetAsGeneric() {
115 if (m_type == Type::eTypeGeneric)
116 return (Generic *)this;
117 return NULL;
118 }
119
120 virtual void Dump(std::ostream &s) const = 0;
121
122 private:
123 Type m_type;
124 };
125
126 class Array : public Object {
127 public:
128 Array() : Object(Type::eTypeArray) {}
129
130 virtual ~Array() {}
131
132 void AddItem(ObjectSP item) { m_items.push_back(item); }
133
134 void Dump(std::ostream &s) const override {
135 s << "[";
136 const size_t arrsize = m_items.size();
137 for (size_t i = 0; i < arrsize; ++i) {
138 m_items[i]->Dump(s);
139 if (i + 1 < arrsize)
140 s << ",";
141 }
142 s << "]";
143 }
144
145 protected:
146 typedef std::vector<ObjectSP> collection;
147 collection m_items;
148 };
149
150 class Integer : public Object {
151 public:
152 Integer(uint64_t value = 0) : Object(Type::eTypeInteger), m_value(value) {}
153
154 virtual ~Integer() {}
155
156 void SetValue(uint64_t value) { m_value = value; }
157
158 void Dump(std::ostream &s) const override { s << m_value; }
159
160 protected:
161 uint64_t m_value;
162 };
163
164 class Float : public Object {
165 public:
166 Float(double d = 0.0) : Object(Type::eTypeFloat), m_value(d) {}
167
168 virtual ~Float() {}
169
170 void SetValue(double value) { m_value = value; }
171
172 void Dump(std::ostream &s) const override { s << m_value; }
173
174 protected:
175 double m_value;
176 };
177
178 class Boolean : public Object {
179 public:
180 Boolean(bool b = false) : Object(Type::eTypeBoolean), m_value(b) {}
181
182 virtual ~Boolean() {}
183
184 void SetValue(bool value) { m_value = value; }
185
186 void Dump(std::ostream &s) const override {
187 if (m_value == true)
188 s << "true";
189 else
190 s << "false";
191 }
192
193 protected:
194 bool m_value;
195 };
196
197 class String : public Object {
198 public:
199 String() : Object(Type::eTypeString), m_value() {}
200
201 String(const std::string &s) : Object(Type::eTypeString), m_value(s) {}
202
203 String(const std::string &&s) : Object(Type::eTypeString), m_value(s) {}
204
205 void SetValue(const std::string &string) { m_value = string; }
206
207 void Dump(std::ostream &s) const override {
208 std::string quoted;
209 const size_t strsize = m_value.size();
210 for (size_t i = 0; i < strsize; ++i) {
211 char ch = m_value[i];
212 if (ch == '"')
213 quoted.push_back('\\');
214 quoted.push_back(ch);
215 }
216 s << '"' << quoted.c_str() << '"';
217 }
218
219 protected:
220 std::string m_value;
221 };
222
223 class Dictionary : public Object {
224 public:
225 Dictionary() : Object(Type::eTypeDictionary), m_dict() {}
226
227 virtual ~Dictionary() {}
228
229 void AddItem(std::string key, ObjectSP value) {
230 m_dict.push_back(Pair(key, value));
231 }
232
233 void AddIntegerItem(std::string key, uint64_t value) {
234 AddItem(key, ObjectSP(new Integer(value)));
235 }
236
237 void AddFloatItem(std::string key, double value) {
238 AddItem(key, ObjectSP(new Float(value)));
239 }
240
241 void AddStringItem(std::string key, std::string value) {
242 AddItem(key, ObjectSP(new String(std::move(value))));
243 }
244
245 void AddBytesAsHexASCIIString(std::string key, const uint8_t *src,
246 size_t src_len) {
247 if (src && src_len) {
248 std::ostringstream strm;
249 for (size_t i = 0; i < src_len; i++)
250 strm << std::setfill('0') << std::hex << std::right << std::setw(2)
251 << ((uint32_t)(src[i]));
252 AddItem(key, ObjectSP(new String(std::move(strm.str()))));
253 } else {
254 AddItem(key, ObjectSP(new String()));
255 }
256 }
257
258 void AddBooleanItem(std::string key, bool value) {
259 AddItem(key, ObjectSP(new Boolean(value)));
260 }
261
262 void Dump(std::ostream &s) const override {
263 bool have_printed_one_elem = false;
264 s << "{";
265 for (collection::const_iterator iter = m_dict.begin();
266 iter != m_dict.end(); ++iter) {
267 if (have_printed_one_elem == false) {
268 have_printed_one_elem = true;
269 } else {
270 s << ",";
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000271 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000272 s << "\"" << iter->first.c_str() << "\":";
273 iter->second->Dump(s);
274 }
275 s << "}";
276 }
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000277
Kate Stoneb9c1b512016-09-06 20:57:50 +0000278 protected:
279 // Keep the dictionary as a vector so the dictionary doesn't reorder itself
280 // when you dump it
281 // We aren't accessing keys by name, so this won't affect performance
282 typedef std::pair<std::string, ObjectSP> Pair;
283 typedef std::vector<Pair> collection;
284 collection m_dict;
285 };
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000286
Kate Stoneb9c1b512016-09-06 20:57:50 +0000287 class Null : public Object {
288 public:
289 Null() : Object(Type::eTypeNull) {}
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000290
Kate Stoneb9c1b512016-09-06 20:57:50 +0000291 virtual ~Null() {}
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000292
Kate Stoneb9c1b512016-09-06 20:57:50 +0000293 bool IsValid() const override { return false; }
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000294
Kate Stoneb9c1b512016-09-06 20:57:50 +0000295 void Dump(std::ostream &s) const override { s << "null"; }
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000296
Kate Stoneb9c1b512016-09-06 20:57:50 +0000297 protected:
298 };
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000299
Kate Stoneb9c1b512016-09-06 20:57:50 +0000300 class Generic : public Object {
301 public:
302 explicit Generic(void *object = nullptr)
303 : Object(Type::eTypeGeneric), m_object(object) {}
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000304
Kate Stoneb9c1b512016-09-06 20:57:50 +0000305 void SetValue(void *value) { m_object = value; }
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000306
Kate Stoneb9c1b512016-09-06 20:57:50 +0000307 void *GetValue() const { return m_object; }
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000308
Kate Stoneb9c1b512016-09-06 20:57:50 +0000309 bool IsValid() const override { return m_object != nullptr; }
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000310
Kate Stoneb9c1b512016-09-06 20:57:50 +0000311 void Dump(std::ostream &s) const override;
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000312
Kate Stoneb9c1b512016-09-06 20:57:50 +0000313 private:
314 void *m_object;
315 };
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000316
Kate Stoneb9c1b512016-09-06 20:57:50 +0000317}; // class JSONGenerator
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000318
Kate Stoneb9c1b512016-09-06 20:57:50 +0000319#endif // __JSONGenerator_h_