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