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