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:
m_type(t)60     Object(Type t = Type::eTypeInvalid) : m_type(t) {}
61 
~Object()62     virtual ~Object() {}
63 
IsValid()64     virtual bool IsValid() const { return true; }
65 
Clear()66     virtual void Clear() { m_type = Type::eTypeInvalid; }
67 
GetType()68     Type GetType() const { return m_type; }
69 
SetType(Type t)70     void SetType(Type t) { m_type = t; }
71 
GetAsArray()72     Array *GetAsArray() {
73       if (m_type == Type::eTypeArray)
74         return (Array *)this;
75       return NULL;
76     }
77 
GetAsDictionary()78     Dictionary *GetAsDictionary() {
79       if (m_type == Type::eTypeDictionary)
80         return (Dictionary *)this;
81       return NULL;
82     }
83 
GetAsInteger()84     Integer *GetAsInteger() {
85       if (m_type == Type::eTypeInteger)
86         return (Integer *)this;
87       return NULL;
88     }
89 
GetAsFloat()90     Float *GetAsFloat() {
91       if (m_type == Type::eTypeFloat)
92         return (Float *)this;
93       return NULL;
94     }
95 
GetAsBoolean()96     Boolean *GetAsBoolean() {
97       if (m_type == Type::eTypeBoolean)
98         return (Boolean *)this;
99       return NULL;
100     }
101 
GetAsString()102     String *GetAsString() {
103       if (m_type == Type::eTypeString)
104         return (String *)this;
105       return NULL;
106     }
107 
GetAsGeneric()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:
Array()122     Array() : Object(Type::eTypeArray) {}
123 
~Array()124     virtual ~Array() {}
125 
AddItem(ObjectSP item)126     void AddItem(ObjectSP item) { m_items.push_back(item); }
127 
Dump(std::ostream & s)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:
Object(Type::eTypeInteger)146     Integer(uint64_t value = 0) : Object(Type::eTypeInteger), m_value(value) {}
147 
~Integer()148     virtual ~Integer() {}
149 
SetValue(uint64_t value)150     void SetValue(uint64_t value) { m_value = value; }
151 
Dump(std::ostream & s)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:
Object(Type::eTypeFloat)160     Float(double d = 0.0) : Object(Type::eTypeFloat), m_value(d) {}
161 
~Float()162     virtual ~Float() {}
163 
SetValue(double value)164     void SetValue(double value) { m_value = value; }
165 
Dump(std::ostream & s)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:
Object(Type::eTypeBoolean)174     Boolean(bool b = false) : Object(Type::eTypeBoolean), m_value(b) {}
175 
~Boolean()176     virtual ~Boolean() {}
177 
SetValue(bool value)178     void SetValue(bool value) { m_value = value; }
179 
Dump(std::ostream & s)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:
String()193     String() : Object(Type::eTypeString), m_value() {}
194 
String(const std::string & s)195     String(const std::string &s) : Object(Type::eTypeString), m_value(s) {}
196 
String(const std::string && s)197     String(const std::string &&s) : Object(Type::eTypeString), m_value(s) {}
198 
SetValue(const std::string & string)199     void SetValue(const std::string &string) { m_value = string; }
200 
Dump(std::ostream & s)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:
Dictionary()219     Dictionary() : Object(Type::eTypeDictionary), m_dict() {}
220 
~Dictionary()221     virtual ~Dictionary() {}
222 
AddItem(std::string key,ObjectSP value)223     void AddItem(std::string key, ObjectSP value) {
224       m_dict.push_back(Pair(key, value));
225     }
226 
AddIntegerItem(std::string key,uint64_t value)227     void AddIntegerItem(std::string key, uint64_t value) {
228       AddItem(key, ObjectSP(new Integer(value)));
229     }
230 
AddFloatItem(std::string key,double value)231     void AddFloatItem(std::string key, double value) {
232       AddItem(key, ObjectSP(new Float(value)));
233     }
234 
AddStringItem(std::string key,std::string value)235     void AddStringItem(std::string key, std::string value) {
236       AddItem(key, ObjectSP(new String(std::move(value))));
237     }
238 
AddBytesAsHexASCIIString(std::string key,const uint8_t * src,size_t src_len)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 
AddBooleanItem(std::string key,bool value)252     void AddBooleanItem(std::string key, bool value) {
253       AddItem(key, ObjectSP(new Boolean(value)));
254     }
255 
Dump(std::ostream & s)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:
Null()283     Null() : Object(Type::eTypeNull) {}
284 
~Null()285     virtual ~Null() {}
286 
IsValid()287     bool IsValid() const override { return false; }
288 
Dump(std::ostream & s)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)
Object(Type::eTypeGeneric)297         : Object(Type::eTypeGeneric), m_object(object) {}
298 
SetValue(void * value)299     void SetValue(void *value) { m_object = value; }
300 
GetValue()301     void *GetValue() const { return m_object; }
302 
IsValid()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