xref: /openbsd-src/gnu/llvm/lldb/tools/debugserver/source/JSONGenerator.h (revision 46035553bfdd96e63c94e32da0210227ec2e3cf1)
1 //===-- JSONGenerator.h ----------------------------------------*- C++ -*-===//
2 //
3 // 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
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef __JSONGenerator_h_
10 #define __JSONGenerator_h_
11 
12 
13 #include <iomanip>
14 #include <sstream>
15 #include <string>
16 #include <utility>
17 #include <vector>
18 
19 /// \class JSONGenerator JSONGenerator.h
20 /// A class which can construct structured data for the sole purpose
21 /// 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.
26 
27 class JSONGenerator {
28 public:
29   class Object;
30   class Array;
31   class Integer;
32   class Float;
33   class Boolean;
34   class String;
35   class Dictionary;
36   class Generic;
37 
38   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;
46 
47   enum class Type {
48     eTypeInvalid = -1,
49     eTypeNull = 0,
50     eTypeGeneric,
51     eTypeArray,
52     eTypeInteger,
53     eTypeFloat,
54     eTypeBoolean,
55     eTypeString,
56     eTypeDictionary
57   };
58 
59   class Object : public std::enable_shared_from_this<Object> {
60   public:
61     Object(Type t = Type::eTypeInvalid) : m_type(t) {}
62 
63     virtual ~Object() {}
64 
65     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 {
182       if (m_value)
183         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) {
262         if (!have_printed_one_elem) {
263           have_printed_one_elem = true;
264         } else {
265           s << ",";
266         }
267         s << "\"" << iter->first.c_str() << "\":";
268         iter->second->Dump(s);
269       }
270       s << "}";
271     }
272 
273   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   };
281 
282   class Null : public Object {
283   public:
284     Null() : Object(Type::eTypeNull) {}
285 
286     virtual ~Null() {}
287 
288     bool IsValid() const override { return false; }
289 
290     void Dump(std::ostream &s) const override { s << "null"; }
291 
292   protected:
293   };
294 
295   class Generic : public Object {
296   public:
297     explicit Generic(void *object = nullptr)
298         : Object(Type::eTypeGeneric), m_object(object) {}
299 
300     void SetValue(void *value) { m_object = value; }
301 
302     void *GetValue() const { return m_object; }
303 
304     bool IsValid() const override { return m_object != nullptr; }
305 
306     void Dump(std::ostream &s) const override;
307 
308   private:
309     void *m_object;
310   };
311 
312 }; // class JSONGenerator
313 
314 #endif // __JSONGenerator_h_
315