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