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