blob: 70708f9a5acfe20b7e0adfc8d599642f8dcb99cb [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
Adrian Prantlf05b42e2019-03-11 17:09:29 +000019/// \class JSONGenerator JSONGenerator.h
Adrian Prantld8f460e2018-05-02 16:55:16 +000020/// A class which can construct structured data for the sole purpose
Greg Claytonc9a2f6e2015-06-25 22:34:08 +000021/// of printing it in JSON format.
22///
23/// A stripped down version of lldb's StructuredData objects which are much
24/// general purpose. This variant is intended only for assembling information
25/// and printing it as a JSON string.
Greg Claytonc9a2f6e2015-06-25 22:34:08 +000026
Kate Stoneb9c1b512016-09-06 20:57:50 +000027class JSONGenerator {
Greg Claytonc9a2f6e2015-06-25 22:34:08 +000028public:
Kate Stoneb9c1b512016-09-06 20:57:50 +000029 class Object;
30 class Array;
31 class Integer;
32 class Float;
33 class Boolean;
34 class String;
35 class Dictionary;
36 class Generic;
Greg Claytonc9a2f6e2015-06-25 22:34:08 +000037
Kate Stoneb9c1b512016-09-06 20:57:50 +000038 typedef std::shared_ptr<Object> ObjectSP;
39 typedef std::shared_ptr<Array> ArraySP;
40 typedef std::shared_ptr<Integer> IntegerSP;
41 typedef std::shared_ptr<Float> FloatSP;
42 typedef std::shared_ptr<Boolean> BooleanSP;
43 typedef std::shared_ptr<String> StringSP;
44 typedef std::shared_ptr<Dictionary> DictionarySP;
45 typedef std::shared_ptr<Generic> GenericSP;
Greg Claytonc9a2f6e2015-06-25 22:34:08 +000046
Kate Stoneb9c1b512016-09-06 20:57:50 +000047 enum class Type {
48 eTypeInvalid = -1,
49 eTypeNull = 0,
50 eTypeGeneric,
51 eTypeArray,
52 eTypeInteger,
53 eTypeFloat,
54 eTypeBoolean,
55 eTypeString,
56 eTypeDictionary
57 };
Greg Claytonc9a2f6e2015-06-25 22:34:08 +000058
Kate Stoneb9c1b512016-09-06 20:57:50 +000059 class Object : public std::enable_shared_from_this<Object> {
60 public:
61 Object(Type t = Type::eTypeInvalid) : m_type(t) {}
Greg Claytonc9a2f6e2015-06-25 22:34:08 +000062
Kate Stoneb9c1b512016-09-06 20:57:50 +000063 virtual ~Object() {}
Greg Claytonc9a2f6e2015-06-25 22:34:08 +000064
Kate Stoneb9c1b512016-09-06 20:57:50 +000065 virtual bool IsValid() const { return true; }
66
67 virtual void Clear() { m_type = Type::eTypeInvalid; }
68
69 Type GetType() const { return m_type; }
70
71 void SetType(Type t) { m_type = t; }
72
73 Array *GetAsArray() {
74 if (m_type == Type::eTypeArray)
75 return (Array *)this;
76 return NULL;
77 }
78
79 Dictionary *GetAsDictionary() {
80 if (m_type == Type::eTypeDictionary)
81 return (Dictionary *)this;
82 return NULL;
83 }
84
85 Integer *GetAsInteger() {
86 if (m_type == Type::eTypeInteger)
87 return (Integer *)this;
88 return NULL;
89 }
90
91 Float *GetAsFloat() {
92 if (m_type == Type::eTypeFloat)
93 return (Float *)this;
94 return NULL;
95 }
96
97 Boolean *GetAsBoolean() {
98 if (m_type == Type::eTypeBoolean)
99 return (Boolean *)this;
100 return NULL;
101 }
102
103 String *GetAsString() {
104 if (m_type == Type::eTypeString)
105 return (String *)this;
106 return NULL;
107 }
108
109 Generic *GetAsGeneric() {
110 if (m_type == Type::eTypeGeneric)
111 return (Generic *)this;
112 return NULL;
113 }
114
115 virtual void Dump(std::ostream &s) const = 0;
116
117 private:
118 Type m_type;
119 };
120
121 class Array : public Object {
122 public:
123 Array() : Object(Type::eTypeArray) {}
124
125 virtual ~Array() {}
126
127 void AddItem(ObjectSP item) { m_items.push_back(item); }
128
129 void Dump(std::ostream &s) const override {
130 s << "[";
131 const size_t arrsize = m_items.size();
132 for (size_t i = 0; i < arrsize; ++i) {
133 m_items[i]->Dump(s);
134 if (i + 1 < arrsize)
135 s << ",";
136 }
137 s << "]";
138 }
139
140 protected:
141 typedef std::vector<ObjectSP> collection;
142 collection m_items;
143 };
144
145 class Integer : public Object {
146 public:
147 Integer(uint64_t value = 0) : Object(Type::eTypeInteger), m_value(value) {}
148
149 virtual ~Integer() {}
150
151 void SetValue(uint64_t value) { m_value = value; }
152
153 void Dump(std::ostream &s) const override { s << m_value; }
154
155 protected:
156 uint64_t m_value;
157 };
158
159 class Float : public Object {
160 public:
161 Float(double d = 0.0) : Object(Type::eTypeFloat), m_value(d) {}
162
163 virtual ~Float() {}
164
165 void SetValue(double value) { m_value = value; }
166
167 void Dump(std::ostream &s) const override { s << m_value; }
168
169 protected:
170 double m_value;
171 };
172
173 class Boolean : public Object {
174 public:
175 Boolean(bool b = false) : Object(Type::eTypeBoolean), m_value(b) {}
176
177 virtual ~Boolean() {}
178
179 void SetValue(bool value) { m_value = value; }
180
181 void Dump(std::ostream &s) const override {
Jonas Devliegherea6682a42018-12-15 00:15:33 +0000182 if (m_value)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000183 s << "true";
184 else
185 s << "false";
186 }
187
188 protected:
189 bool m_value;
190 };
191
192 class String : public Object {
193 public:
194 String() : Object(Type::eTypeString), m_value() {}
195
196 String(const std::string &s) : Object(Type::eTypeString), m_value(s) {}
197
198 String(const std::string &&s) : Object(Type::eTypeString), m_value(s) {}
199
200 void SetValue(const std::string &string) { m_value = string; }
201
202 void Dump(std::ostream &s) const override {
203 std::string quoted;
204 const size_t strsize = m_value.size();
205 for (size_t i = 0; i < strsize; ++i) {
206 char ch = m_value[i];
207 if (ch == '"')
208 quoted.push_back('\\');
209 quoted.push_back(ch);
210 }
211 s << '"' << quoted.c_str() << '"';
212 }
213
214 protected:
215 std::string m_value;
216 };
217
218 class Dictionary : public Object {
219 public:
220 Dictionary() : Object(Type::eTypeDictionary), m_dict() {}
221
222 virtual ~Dictionary() {}
223
224 void AddItem(std::string key, ObjectSP value) {
225 m_dict.push_back(Pair(key, value));
226 }
227
228 void AddIntegerItem(std::string key, uint64_t value) {
229 AddItem(key, ObjectSP(new Integer(value)));
230 }
231
232 void AddFloatItem(std::string key, double value) {
233 AddItem(key, ObjectSP(new Float(value)));
234 }
235
236 void AddStringItem(std::string key, std::string value) {
237 AddItem(key, ObjectSP(new String(std::move(value))));
238 }
239
240 void AddBytesAsHexASCIIString(std::string key, const uint8_t *src,
241 size_t src_len) {
242 if (src && src_len) {
243 std::ostringstream strm;
244 for (size_t i = 0; i < src_len; i++)
245 strm << std::setfill('0') << std::hex << std::right << std::setw(2)
246 << ((uint32_t)(src[i]));
247 AddItem(key, ObjectSP(new String(std::move(strm.str()))));
248 } else {
249 AddItem(key, ObjectSP(new String()));
250 }
251 }
252
253 void AddBooleanItem(std::string key, bool value) {
254 AddItem(key, ObjectSP(new Boolean(value)));
255 }
256
257 void Dump(std::ostream &s) const override {
258 bool have_printed_one_elem = false;
259 s << "{";
260 for (collection::const_iterator iter = m_dict.begin();
261 iter != m_dict.end(); ++iter) {
Jonas Devliegherea6682a42018-12-15 00:15:33 +0000262 if (!have_printed_one_elem) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000263 have_printed_one_elem = true;
264 } else {
265 s << ",";
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000266 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000267 s << "\"" << iter->first.c_str() << "\":";
268 iter->second->Dump(s);
269 }
270 s << "}";
271 }
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000272
Kate Stoneb9c1b512016-09-06 20:57:50 +0000273 protected:
274 // Keep the dictionary as a vector so the dictionary doesn't reorder itself
275 // when you dump it
276 // We aren't accessing keys by name, so this won't affect performance
277 typedef std::pair<std::string, ObjectSP> Pair;
278 typedef std::vector<Pair> collection;
279 collection m_dict;
280 };
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000281
Kate Stoneb9c1b512016-09-06 20:57:50 +0000282 class Null : public Object {
283 public:
284 Null() : Object(Type::eTypeNull) {}
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000285
Kate Stoneb9c1b512016-09-06 20:57:50 +0000286 virtual ~Null() {}
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000287
Kate Stoneb9c1b512016-09-06 20:57:50 +0000288 bool IsValid() const override { return false; }
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000289
Kate Stoneb9c1b512016-09-06 20:57:50 +0000290 void Dump(std::ostream &s) const override { s << "null"; }
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000291
Kate Stoneb9c1b512016-09-06 20:57:50 +0000292 protected:
293 };
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000294
Kate Stoneb9c1b512016-09-06 20:57:50 +0000295 class Generic : public Object {
296 public:
297 explicit Generic(void *object = nullptr)
298 : Object(Type::eTypeGeneric), m_object(object) {}
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000299
Kate Stoneb9c1b512016-09-06 20:57:50 +0000300 void SetValue(void *value) { m_object = value; }
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000301
Kate Stoneb9c1b512016-09-06 20:57:50 +0000302 void *GetValue() const { return m_object; }
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000303
Kate Stoneb9c1b512016-09-06 20:57:50 +0000304 bool IsValid() const override { return m_object != nullptr; }
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000305
Kate Stoneb9c1b512016-09-06 20:57:50 +0000306 void Dump(std::ostream &s) const override;
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000307
Kate Stoneb9c1b512016-09-06 20:57:50 +0000308 private:
309 void *m_object;
310 };
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000311
Kate Stoneb9c1b512016-09-06 20:57:50 +0000312}; // class JSONGenerator
Greg Claytonc9a2f6e2015-06-25 22:34:08 +0000313
Kate Stoneb9c1b512016-09-06 20:57:50 +0000314#endif // __JSONGenerator_h_