blob: 0ac5e0bb768c1fbb18c07b5afee225b00b040a18 [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
Greg Claytonc9a2f6e2015-06-25 22:34:08 +000013
14#include <iomanip>
15#include <sstream>
16#include <string>
17#include <utility>
18#include <vector>
19
20//----------------------------------------------------------------------
21/// @class JSONGenerator JSONGenerator.h
Adrian Prantld8f460e2018-05-02 16:55:16 +000022/// A class which can construct structured data for the sole purpose
Greg Claytonc9a2f6e2015-06-25 22:34:08 +000023/// of printing it in JSON format.
24///
25/// A stripped down version of lldb's StructuredData objects which are much
26/// general purpose. This variant is intended only for assembling information
27/// and printing it as a JSON string.
28//----------------------------------------------------------------------
29
Kate Stoneb9c1b512016-09-06 20:57:50 +000030class JSONGenerator {
Greg Claytonc9a2f6e2015-06-25 22:34:08 +000031public:
Kate Stoneb9c1b512016-09-06 20:57:50 +000032 class Object;
33 class Array;
34 class Integer;
35 class Float;
36 class Boolean;
37 class String;
38 class Dictionary;
39 class Generic;
Greg Claytonc9a2f6e2015-06-25 22:34:08 +000040
Kate Stoneb9c1b512016-09-06 20:57:50 +000041 typedef std::shared_ptr<Object> ObjectSP;
42 typedef std::shared_ptr<Array> ArraySP;
43 typedef std::shared_ptr<Integer> IntegerSP;
44 typedef std::shared_ptr<Float> FloatSP;
45 typedef std::shared_ptr<Boolean> BooleanSP;
46 typedef std::shared_ptr<String> StringSP;
47 typedef std::shared_ptr<Dictionary> DictionarySP;
48 typedef std::shared_ptr<Generic> GenericSP;
Greg Claytonc9a2f6e2015-06-25 22:34:08 +000049
Kate Stoneb9c1b512016-09-06 20:57:50 +000050 enum class Type {
51 eTypeInvalid = -1,
52 eTypeNull = 0,
53 eTypeGeneric,
54 eTypeArray,
55 eTypeInteger,
56 eTypeFloat,
57 eTypeBoolean,
58 eTypeString,
59 eTypeDictionary
60 };
Greg Claytonc9a2f6e2015-06-25 22:34:08 +000061
Kate Stoneb9c1b512016-09-06 20:57:50 +000062 class Object : public std::enable_shared_from_this<Object> {
63 public:
64 Object(Type t = Type::eTypeInvalid) : m_type(t) {}
Greg Claytonc9a2f6e2015-06-25 22:34:08 +000065
Kate Stoneb9c1b512016-09-06 20:57:50 +000066 virtual ~Object() {}
Greg Claytonc9a2f6e2015-06-25 22:34:08 +000067
Kate Stoneb9c1b512016-09-06 20:57:50 +000068 virtual bool IsValid() const { return true; }
69
70 virtual void Clear() { m_type = Type::eTypeInvalid; }
71
72 Type GetType() const { return m_type; }
73
74 void SetType(Type t) { m_type = t; }
75
76 Array *GetAsArray() {
77 if (m_type == Type::eTypeArray)
78 return (Array *)this;
79 return NULL;
80 }
81
82 Dictionary *GetAsDictionary() {
83 if (m_type == Type::eTypeDictionary)
84 return (Dictionary *)this;
85 return NULL;
86 }
87
88 Integer *GetAsInteger() {
89 if (m_type == Type::eTypeInteger)
90 return (Integer *)this;
91 return NULL;
92 }
93
94 Float *GetAsFloat() {
95 if (m_type == Type::eTypeFloat)
96 return (Float *)this;
97 return NULL;
98 }
99
100 Boolean *GetAsBoolean() {
101 if (m_type == Type::eTypeBoolean)
102 return (Boolean *)this;
103 return NULL;
104 }
105
106 String *GetAsString() {
107 if (m_type == Type::eTypeString)
108 return (String *)this;
109 return NULL;
110 }
111
112 Generic *GetAsGeneric() {
113 if (m_type == Type::eTypeGeneric)
114 return (Generic *)this;
115 return NULL;
116 }
117
118 virtual void Dump(std::ostream &s) const = 0;
119
120 private:
121 Type m_type;
122 };
123
124 class Array : public Object {
125 public:
126 Array() : Object(Type::eTypeArray) {}
127
128 virtual ~Array() {}
129
130 void AddItem(ObjectSP item) { m_items.push_back(item); }
131
132 void Dump(std::ostream &s) const override {
133 s << "[";
134 const size_t arrsize = m_items.size();
135 for (size_t i = 0; i < arrsize; ++i) {
136 m_items[i]->Dump(s);
137 if (i + 1 < arrsize)
138 s << ",";
139 }
140 s << "]";
141 }
142
143 protected:
144 typedef std::vector<ObjectSP> collection;
145 collection m_items;
146 };
147
148 class Integer : public Object {
149 public:
150 Integer(uint64_t value = 0) : Object(Type::eTypeInteger), m_value(value) {}
151
152 virtual ~Integer() {}
153
154 void SetValue(uint64_t value) { m_value = value; }
155
156 void Dump(std::ostream &s) const override { s << m_value; }
157
158 protected:
159 uint64_t m_value;
160 };
161
162 class Float : public Object {
163 public:
164 Float(double d = 0.0) : Object(Type::eTypeFloat), m_value(d) {}
165
166 virtual ~Float() {}
167
168 void SetValue(double value) { m_value = value; }
169
170 void Dump(std::ostream &s) const override { s << m_value; }
171
172 protected:
173 double m_value;
174 };
175
176 class Boolean : public Object {
177 public:
178 Boolean(bool b = false) : Object(Type::eTypeBoolean), m_value(b) {}
179
180 virtual ~Boolean() {}
181
182 void SetValue(bool value) { m_value = value; }
183
184 void Dump(std::ostream &s) const override {
Jonas Devliegherea6682a42018-12-15 00:15:33 +0000185 if (m_value)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000186 s << "true";
187 else
188 s << "false";
189 }
190
191 protected:
192 bool m_value;
193 };
194
195 class String : public Object {
196 public:
197 String() : Object(Type::eTypeString), m_value() {}
198
199 String(const std::string &s) : Object(Type::eTypeString), m_value(s) {}
200
201 String(const std::string &&s) : Object(Type::eTypeString), m_value(s) {}
202
203 void SetValue(const std::string &string) { m_value = string; }
204
205 void Dump(std::ostream &s) const override {
206 std::string quoted;
207 const size_t strsize = m_value.size();
208 for (size_t i = 0; i < strsize; ++i) {
209 char ch = m_value[i];
210 if (ch == '"')
211 quoted.push_back('\\');
212 quoted.push_back(ch);
213 }
214 s << '"' << quoted.c_str() << '"';
215 }
216
217 protected:
218 std::string m_value;
219 };
220
221 class Dictionary : public Object {
222 public:
223 Dictionary() : Object(Type::eTypeDictionary), m_dict() {}
224
225 virtual ~Dictionary() {}
226
227 void AddItem(std::string key, ObjectSP value) {
228 m_dict.push_back(Pair(key, value));
229 }
230
231 void AddIntegerItem(std::string key, uint64_t value) {
232 AddItem(key, ObjectSP(new Integer(value)));
233 }
234
235 void AddFloatItem(std::string key, double value) {
236 AddItem(key, ObjectSP(new Float(value)));
237 }
238
239 void AddStringItem(std::string key, std::string value) {
240 AddItem(key, ObjectSP(new String(std::move(value))));
241 }
242
243 void AddBytesAsHexASCIIString(std::string key, const uint8_t *src,
244 size_t src_len) {
245 if (src && src_len) {
246 std::ostringstream strm;
247 for (size_t i = 0; i < src_len; i++)
248 strm << std::setfill('0') << std::hex << std::right << std::setw(2)
249 << ((uint32_t)(src[i]));
250 AddItem(key, ObjectSP(new String(std::move(strm.str()))));
251 } else {
252 AddItem(key, ObjectSP(new String()));
253 }
254 }
255
256 void AddBooleanItem(std::string key, bool value) {
257 AddItem(key, ObjectSP(new Boolean(value)));
258 }
259
260 void Dump(std::ostream &s) const override {
261 bool have_printed_one_elem = false;
262 s << "{";
263 for (collection::const_iterator iter = m_dict.begin();
264 iter != m_dict.end(); ++iter) {
Jonas Devliegherea6682a42018-12-15 00:15:33 +0000265 if (!have_printed_one_elem) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000266 have_printed_one_elem = true;
267 } else {
268 s << ",";
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000269 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000270 s << "\"" << iter->first.c_str() << "\":";
271 iter->second->Dump(s);
272 }
273 s << "}";
274 }
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000275
Kate Stoneb9c1b512016-09-06 20:57:50 +0000276 protected:
277 // Keep the dictionary as a vector so the dictionary doesn't reorder itself
278 // when you dump it
279 // We aren't accessing keys by name, so this won't affect performance
280 typedef std::pair<std::string, ObjectSP> Pair;
281 typedef std::vector<Pair> collection;
282 collection m_dict;
283 };
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000284
Kate Stoneb9c1b512016-09-06 20:57:50 +0000285 class Null : public Object {
286 public:
287 Null() : Object(Type::eTypeNull) {}
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000288
Kate Stoneb9c1b512016-09-06 20:57:50 +0000289 virtual ~Null() {}
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000290
Kate Stoneb9c1b512016-09-06 20:57:50 +0000291 bool IsValid() const override { return false; }
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000292
Kate Stoneb9c1b512016-09-06 20:57:50 +0000293 void Dump(std::ostream &s) const override { s << "null"; }
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000294
Kate Stoneb9c1b512016-09-06 20:57:50 +0000295 protected:
296 };
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000297
Kate Stoneb9c1b512016-09-06 20:57:50 +0000298 class Generic : public Object {
299 public:
300 explicit Generic(void *object = nullptr)
301 : Object(Type::eTypeGeneric), m_object(object) {}
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000302
Kate Stoneb9c1b512016-09-06 20:57:50 +0000303 void SetValue(void *value) { m_object = value; }
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000304
Kate Stoneb9c1b512016-09-06 20:57:50 +0000305 void *GetValue() const { return m_object; }
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000306
Kate Stoneb9c1b512016-09-06 20:57:50 +0000307 bool IsValid() const override { return m_object != nullptr; }
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000308
Kate Stoneb9c1b512016-09-06 20:57:50 +0000309 void Dump(std::ostream &s) const override;
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000310
Kate Stoneb9c1b512016-09-06 20:57:50 +0000311 private:
312 void *m_object;
313 };
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000314
Kate Stoneb9c1b512016-09-06 20:57:50 +0000315}; // class JSONGenerator
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000316
Kate Stoneb9c1b512016-09-06 20:57:50 +0000317#endif // __JSONGenerator_h_