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 {
34 public:
35 
36     class Object;
37     class Array;
38     class Integer;
39     class Float;
40     class Boolean;
41     class String;
42     class Dictionary;
43     class Generic;
44 
45     typedef std::shared_ptr<Object> ObjectSP;
46     typedef std::shared_ptr<Array> ArraySP;
47     typedef std::shared_ptr<Integer> IntegerSP;
48     typedef std::shared_ptr<Float> FloatSP;
49     typedef std::shared_ptr<Boolean> BooleanSP;
50     typedef std::shared_ptr<String> StringSP;
51     typedef std::shared_ptr<Dictionary> DictionarySP;
52     typedef std::shared_ptr<Generic> GenericSP;
53 
54     enum class Type
55     {
56         eTypeInvalid = -1,
57         eTypeNull = 0,
58         eTypeGeneric,
59         eTypeArray,
60         eTypeInteger,
61         eTypeFloat,
62         eTypeBoolean,
63         eTypeString,
64         eTypeDictionary
65     };
66 
67     class Object :
68         public std::enable_shared_from_this<Object>
69     {
70     public:
71 
72         Object (Type t = Type::eTypeInvalid) :
73             m_type (t)
74         {
75         }
76 
77         virtual ~Object ()
78         {
79         }
80 
81         virtual bool
82         IsValid() const
83         {
84             return true;
85         }
86 
87         virtual void
88         Clear ()
89         {
90             m_type = Type::eTypeInvalid;
91         }
92 
93         Type
94         GetType () const
95         {
96             return m_type;
97         }
98 
99         void
100         SetType (Type t)
101         {
102             m_type = t;
103         }
104 
105         Array *
106         GetAsArray ()
107         {
108             if (m_type == Type::eTypeArray)
109                 return (Array *)this;
110             return NULL;
111         }
112 
113         Dictionary *
114         GetAsDictionary ()
115         {
116             if (m_type == Type::eTypeDictionary)
117                 return (Dictionary *)this;
118             return NULL;
119         }
120 
121         Integer *
122         GetAsInteger ()
123         {
124             if (m_type == Type::eTypeInteger)
125                 return (Integer *)this;
126             return NULL;
127         }
128 
129         Float *
130         GetAsFloat ()
131         {
132             if (m_type == Type::eTypeFloat)
133                 return (Float *)this;
134             return NULL;
135         }
136 
137         Boolean *
138         GetAsBoolean ()
139         {
140             if (m_type == Type::eTypeBoolean)
141                 return (Boolean *)this;
142             return NULL;
143         }
144 
145         String *
146         GetAsString ()
147         {
148             if (m_type == Type::eTypeString)
149                 return (String *)this;
150             return NULL;
151         }
152 
153         Generic *
154         GetAsGeneric()
155         {
156             if (m_type == Type::eTypeGeneric)
157                 return (Generic *)this;
158             return NULL;
159         }
160 
161         virtual void
162         Dump (std::ostream &s) const = 0;
163 
164     private:
165         Type m_type;
166     };
167 
168     class Array : public Object
169     {
170     public:
171         Array () :
172             Object (Type::eTypeArray)
173         {
174         }
175 
176         virtual
177         ~Array()
178         {
179         }
180 
181         void
182         AddItem(ObjectSP item)
183         {
184             m_items.push_back(item);
185         }
186 
187         void Dump(std::ostream &s) const override
188         {
189             s << "[";
190             const size_t arrsize = m_items.size();
191             for (size_t i = 0; i < arrsize; ++i)
192             {
193                 m_items[i]->Dump(s);
194                 if (i + 1 < arrsize)
195                     s << ",";
196             }
197             s << "]";
198         }
199 
200     protected:
201         typedef std::vector<ObjectSP> collection;
202         collection m_items;
203     };
204 
205 
206     class Integer  : public Object
207     {
208     public:
209         Integer (uint64_t value = 0) :
210             Object (Type::eTypeInteger),
211             m_value (value)
212         {
213         }
214 
215         virtual ~Integer()
216         {
217         }
218 
219         void
220         SetValue (uint64_t value)
221         {
222             m_value = value;
223         }
224 
225         void Dump(std::ostream &s) const override
226         {
227             s << m_value;
228         }
229 
230     protected:
231         uint64_t m_value;
232     };
233 
234     class Float  : public Object
235     {
236     public:
237         Float (double d = 0.0) :
238             Object (Type::eTypeFloat),
239             m_value (d)
240         {
241         }
242 
243         virtual ~Float()
244         {
245         }
246 
247         void
248         SetValue (double value)
249         {
250             m_value = value;
251         }
252 
253         void Dump(std::ostream &s) const override
254         {
255             s << m_value;
256         }
257 
258     protected:
259         double m_value;
260     };
261 
262     class Boolean  : public Object
263     {
264     public:
265         Boolean (bool b = false) :
266             Object (Type::eTypeBoolean),
267             m_value (b)
268         {
269         }
270 
271         virtual ~Boolean()
272         {
273         }
274 
275         void
276         SetValue (bool value)
277         {
278             m_value = value;
279         }
280 
281         void Dump(std::ostream &s) const override
282         {
283             if (m_value == true)
284                 s << "true";
285             else
286                 s << "false";
287         }
288 
289     protected:
290         bool m_value;
291     };
292 
293 
294 
295     class String  : public Object
296     {
297     public:
298         String () :
299             Object (Type::eTypeString),
300             m_value ()
301         {
302         }
303 
304         String (const std::string &s) :
305             Object (Type::eTypeString),
306             m_value (s)
307         {
308         }
309 
310         String (const std::string &&s) :
311             Object (Type::eTypeString),
312             m_value (s)
313         {
314         }
315 
316         void
317         SetValue (const std::string &string)
318         {
319             m_value = string;
320         }
321 
322         void Dump(std::ostream &s) const override
323         {
324             std::string quoted;
325             const size_t strsize = m_value.size();
326             for (size_t i = 0; i < strsize ; ++i)
327             {
328                 char ch = m_value[i];
329                 if (ch == '"')
330                     quoted.push_back ('\\');
331                 quoted.push_back (ch);
332             }
333             s << '"' << quoted.c_str() << '"';
334         }
335 
336     protected:
337         std::string m_value;
338     };
339 
340     class Dictionary : public Object
341     {
342     public:
343         Dictionary () :
344             Object (Type::eTypeDictionary),
345             m_dict ()
346         {
347         }
348 
349         virtual ~Dictionary()
350         {
351         }
352 
353         void
354         AddItem (std::string key, ObjectSP value)
355         {
356             m_dict.push_back(Pair(key, value));
357         }
358 
359         void
360         AddIntegerItem (std::string key, uint64_t value)
361         {
362             AddItem (key, ObjectSP (new Integer(value)));
363         }
364 
365         void
366         AddFloatItem (std::string key, double value)
367         {
368             AddItem (key, ObjectSP (new Float(value)));
369         }
370 
371         void
372         AddStringItem (std::string key, std::string value)
373         {
374             AddItem (key, ObjectSP (new String(std::move(value))));
375         }
376 
377         void
378         AddBytesAsHexASCIIString (std::string key, const uint8_t *src, size_t src_len)
379         {
380             if (src && src_len)
381             {
382                 std::ostringstream strm;
383                 for (size_t i = 0; i < src_len; i++)
384                     strm << std::setfill('0') << std::hex << std::right << std::setw(2) << ((uint32_t)(src[i]));
385                 AddItem (key, ObjectSP (new String(std::move(strm.str()))));
386             }
387             else
388             {
389                 AddItem (key, ObjectSP (new String()));
390             }
391         }
392 
393         void
394         AddBooleanItem (std::string key, bool value)
395         {
396             AddItem (key, ObjectSP (new Boolean(value)));
397         }
398 
399         void Dump(std::ostream &s) const override
400         {
401             bool have_printed_one_elem = false;
402             s << "{";
403             for (collection::const_iterator iter = m_dict.begin(); iter != m_dict.end(); ++iter)
404             {
405                 if (have_printed_one_elem == false)
406                 {
407                     have_printed_one_elem = true;
408                 }
409                 else
410                 {
411                     s << ",";
412                 }
413                 s << "\"" << iter->first.c_str() << "\":";
414                 iter->second->Dump(s);
415             }
416             s << "}";
417         }
418 
419     protected:
420         // Keep the dictionary as a vector so the dictionary doesn't reorder itself when you dump it
421         // We aren't accessing keys by name, so this won't affect performance
422         typedef std::pair<std::string, ObjectSP> Pair;
423         typedef std::vector<Pair> collection;
424         collection m_dict;
425     };
426 
427     class Null : public Object
428     {
429     public:
430         Null () :
431             Object (Type::eTypeNull)
432         {
433         }
434 
435         virtual ~Null()
436         {
437         }
438 
439         bool
440         IsValid() const override
441         {
442             return false;
443         }
444 
445         void Dump(std::ostream &s) const override
446         {
447             s << "null";
448         }
449 
450     protected:
451     };
452 
453     class Generic : public Object
454     {
455       public:
456         explicit Generic(void *object = nullptr)
457             : Object(Type::eTypeGeneric)
458             , m_object(object)
459         {
460         }
461 
462         void
463         SetValue(void *value)
464         {
465             m_object = value;
466         }
467 
468         void *
469         GetValue() const
470         {
471             return m_object;
472         }
473 
474         bool
475         IsValid() const override
476         {
477             return m_object != nullptr;
478         }
479 
480         void Dump(std::ostream &s) const override;
481 
482       private:
483         void *m_object;
484     };
485 
486 };  // class JSONGenerator
487 
488 
489 
490 #endif  // __JSONGenerator_h_
491