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