xref: /openbsd-src/gnu/llvm/lldb/tools/debugserver/source/JSONGenerator.h (revision 4e1ee0786f11cc571bd0be17d38e46f635c719fc)
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 LLDB_TOOLS_DEBUGSERVER_SOURCE_JSONGENERATOR_H
10 #define LLDB_TOOLS_DEBUGSERVER_SOURCE_JSONGENERATOR_H
11 
12 #include <iomanip>
13 #include <sstream>
14 #include <string>
15 #include <utility>
16 #include <vector>
17 
18 /// \class JSONGenerator JSONGenerator.h
19 /// A class which can construct structured data for the sole purpose
20 /// of printing it in JSON format.
21 ///
22 /// A stripped down version of lldb's StructuredData objects which are much
23 /// general purpose.  This variant is intended only for assembling information
24 /// and printing it as a JSON string.
25 
26 class JSONGenerator {
27 public:
28   class Object;
29   class Array;
30   class Integer;
31   class Float;
32   class Boolean;
33   class String;
34   class Dictionary;
35   class Generic;
36 
37   typedef std::shared_ptr<Object> ObjectSP;
38   typedef std::shared_ptr<Array> ArraySP;
39   typedef std::shared_ptr<Integer> IntegerSP;
40   typedef std::shared_ptr<Float> FloatSP;
41   typedef std::shared_ptr<Boolean> BooleanSP;
42   typedef std::shared_ptr<String> StringSP;
43   typedef std::shared_ptr<Dictionary> DictionarySP;
44   typedef std::shared_ptr<Generic> GenericSP;
45 
46   enum class Type {
47     eTypeInvalid = -1,
48     eTypeNull = 0,
49     eTypeGeneric,
50     eTypeArray,
51     eTypeInteger,
52     eTypeFloat,
53     eTypeBoolean,
54     eTypeString,
55     eTypeDictionary
56   };
57 
58   class Object : public std::enable_shared_from_this<Object> {
59   public:
60     Object(Type t = Type::eTypeInvalid) : m_type(t) {}
61 
62     virtual ~Object() {}
63 
64     virtual bool IsValid() const { return true; }
65 
66     virtual void Clear() { m_type = Type::eTypeInvalid; }
67 
68     Type GetType() const { return m_type; }
69 
70     void SetType(Type t) { m_type = t; }
71 
72     Array *GetAsArray() {
73       if (m_type == Type::eTypeArray)
74         return (Array *)this;
75       return NULL;
76     }
77 
78     Dictionary *GetAsDictionary() {
79       if (m_type == Type::eTypeDictionary)
80         return (Dictionary *)this;
81       return NULL;
82     }
83 
84     Integer *GetAsInteger() {
85       if (m_type == Type::eTypeInteger)
86         return (Integer *)this;
87       return NULL;
88     }
89 
90     Float *GetAsFloat() {
91       if (m_type == Type::eTypeFloat)
92         return (Float *)this;
93       return NULL;
94     }
95 
96     Boolean *GetAsBoolean() {
97       if (m_type == Type::eTypeBoolean)
98         return (Boolean *)this;
99       return NULL;
100     }
101 
102     String *GetAsString() {
103       if (m_type == Type::eTypeString)
104         return (String *)this;
105       return NULL;
106     }
107 
108     Generic *GetAsGeneric() {
109       if (m_type == Type::eTypeGeneric)
110         return (Generic *)this;
111       return NULL;
112     }
113 
114     virtual void Dump(std::ostream &s) const = 0;
115 
116   private:
117     Type m_type;
118   };
119 
120   class Array : public Object {
121   public:
122     Array() : Object(Type::eTypeArray) {}
123 
124     virtual ~Array() {}
125 
126     void AddItem(ObjectSP item) { m_items.push_back(item); }
127 
128     void Dump(std::ostream &s) const override {
129       s << "[";
130       const size_t arrsize = m_items.size();
131       for (size_t i = 0; i < arrsize; ++i) {
132         m_items[i]->Dump(s);
133         if (i + 1 < arrsize)
134           s << ",";
135       }
136       s << "]";
137     }
138 
139   protected:
140     typedef std::vector<ObjectSP> collection;
141     collection m_items;
142   };
143 
144   class Integer : public Object {
145   public:
146     Integer(uint64_t value = 0) : Object(Type::eTypeInteger), m_value(value) {}
147 
148     virtual ~Integer() {}
149 
150     void SetValue(uint64_t value) { m_value = value; }
151 
152     void Dump(std::ostream &s) const override { s << m_value; }
153 
154   protected:
155     uint64_t m_value;
156   };
157 
158   class Float : public Object {
159   public:
160     Float(double d = 0.0) : Object(Type::eTypeFloat), m_value(d) {}
161 
162     virtual ~Float() {}
163 
164     void SetValue(double value) { m_value = value; }
165 
166     void Dump(std::ostream &s) const override { s << m_value; }
167 
168   protected:
169     double m_value;
170   };
171 
172   class Boolean : public Object {
173   public:
174     Boolean(bool b = false) : Object(Type::eTypeBoolean), m_value(b) {}
175 
176     virtual ~Boolean() {}
177 
178     void SetValue(bool value) { m_value = value; }
179 
180     void Dump(std::ostream &s) const override {
181       if (m_value)
182         s << "true";
183       else
184         s << "false";
185     }
186 
187   protected:
188     bool m_value;
189   };
190 
191   class String : public Object {
192   public:
193     String() : Object(Type::eTypeString), m_value() {}
194 
195     String(const std::string &s) : Object(Type::eTypeString), m_value(s) {}
196 
197     String(const std::string &&s) : Object(Type::eTypeString), m_value(s) {}
198 
199     void SetValue(const std::string &string) { m_value = string; }
200 
201     void Dump(std::ostream &s) const override {
202       std::string quoted;
203       const size_t strsize = m_value.size();
204       for (size_t i = 0; i < strsize; ++i) {
205         char ch = m_value[i];
206         if (ch == '"')
207           quoted.push_back('\\');
208         quoted.push_back(ch);
209       }
210       s << '"' << quoted.c_str() << '"';
211     }
212 
213   protected:
214     std::string m_value;
215   };
216 
217   class Dictionary : public Object {
218   public:
219     Dictionary() : Object(Type::eTypeDictionary), m_dict() {}
220 
221     virtual ~Dictionary() {}
222 
223     void AddItem(std::string key, ObjectSP value) {
224       m_dict.push_back(Pair(key, value));
225     }
226 
227     void AddIntegerItem(std::string key, uint64_t value) {
228       AddItem(key, ObjectSP(new Integer(value)));
229     }
230 
231     void AddFloatItem(std::string key, double value) {
232       AddItem(key, ObjectSP(new Float(value)));
233     }
234 
235     void AddStringItem(std::string key, std::string value) {
236       AddItem(key, ObjectSP(new String(std::move(value))));
237     }
238 
239     void AddBytesAsHexASCIIString(std::string key, const uint8_t *src,
240                                   size_t src_len) {
241       if (src && src_len) {
242         std::ostringstream strm;
243         for (size_t i = 0; i < src_len; i++)
244           strm << std::setfill('0') << std::hex << std::right << std::setw(2)
245                << ((uint32_t)(src[i]));
246         AddItem(key, ObjectSP(new String(std::move(strm.str()))));
247       } else {
248         AddItem(key, ObjectSP(new String()));
249       }
250     }
251 
252     void AddBooleanItem(std::string key, bool value) {
253       AddItem(key, ObjectSP(new Boolean(value)));
254     }
255 
256     void Dump(std::ostream &s) const override {
257       bool have_printed_one_elem = false;
258       s << "{";
259       for (collection::const_iterator iter = m_dict.begin();
260            iter != m_dict.end(); ++iter) {
261         if (!have_printed_one_elem) {
262           have_printed_one_elem = true;
263         } else {
264           s << ",";
265         }
266         s << "\"" << iter->first.c_str() << "\":";
267         iter->second->Dump(s);
268       }
269       s << "}";
270     }
271 
272   protected:
273     // Keep the dictionary as a vector so the dictionary doesn't reorder itself
274     // when you dump it
275     // We aren't accessing keys by name, so this won't affect performance
276     typedef std::pair<std::string, ObjectSP> Pair;
277     typedef std::vector<Pair> collection;
278     collection m_dict;
279   };
280 
281   class Null : public Object {
282   public:
283     Null() : Object(Type::eTypeNull) {}
284 
285     virtual ~Null() {}
286 
287     bool IsValid() const override { return false; }
288 
289     void Dump(std::ostream &s) const override { s << "null"; }
290 
291   protected:
292   };
293 
294   class Generic : public Object {
295   public:
296     explicit Generic(void *object = nullptr)
297         : Object(Type::eTypeGeneric), m_object(object) {}
298 
299     void SetValue(void *value) { m_object = value; }
300 
301     void *GetValue() const { return m_object; }
302 
303     bool IsValid() const override { return m_object != nullptr; }
304 
305     void Dump(std::ostream &s) const override;
306 
307   private:
308     void *m_object;
309   };
310 
311 }; // class JSONGenerator
312 
313 #endif // LLDB_TOOLS_DEBUGSERVER_SOURCE_JSONGENERATOR_H
314