1 //===---------------------JSON.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_JSON_H
10 #define LLDB_TOOLS_DEBUGSERVER_SOURCE_JSON_H
11 
12 #include "StdStringExtractor.h"
13 
14 // C includes
15 #include <cinttypes>
16 #include <cstdint>
17 
18 // C++ includes
19 #include <map>
20 #include <memory>
21 #include <ostream>
22 #include <string>
23 #include <vector>
24 
25 class JSONValue {
26 public:
27   virtual void Write(std::ostream &s) = 0;
28 
29   typedef std::shared_ptr<JSONValue> SP;
30 
31   enum class Kind { String, Number, True, False, Null, Object, Array };
32 
JSONValue(Kind k)33   JSONValue(Kind k) : m_kind(k) {}
34 
GetKind()35   Kind GetKind() const { return m_kind; }
36 
37   virtual ~JSONValue() = default;
38 
39 private:
40   const Kind m_kind;
41 };
42 
43 class JSONString : public JSONValue {
44 public:
45   JSONString();
46   JSONString(const char *s);
47   JSONString(const std::string &s);
48 
49   JSONString(const JSONString &s) = delete;
50   JSONString &operator=(const JSONString &s) = delete;
51 
52   void Write(std::ostream &s) override;
53 
54   typedef std::shared_ptr<JSONString> SP;
55 
GetData()56   std::string GetData() { return m_data; }
57 
classof(const JSONValue * V)58   static bool classof(const JSONValue *V) {
59     return V->GetKind() == JSONValue::Kind::String;
60   }
61 
62   ~JSONString() override = default;
63 
64 private:
65   static std::string json_string_quote_metachars(const std::string &);
66 
67   std::string m_data;
68 };
69 
70 class JSONNumber : public JSONValue {
71 public:
72   typedef std::shared_ptr<JSONNumber> SP;
73 
74   // We cretae a constructor for all integer and floating point type with using
75   // templates and
76   // SFINAE to avoid having ambiguous overloads because of the implicit type
77   // promotion. If we
78   // would have constructors only with int64_t, uint64_t and double types then
79   // constructing a
80   // JSONNumber from an int32_t (or any other similar type) would fail to
81   // compile.
82 
83   template <typename T, typename std::enable_if<
84                             std::is_integral<T>::value &&
85                             std::is_unsigned<T>::value>::type * = nullptr>
JSONNumber(T u)86   explicit JSONNumber(T u)
87       : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Unsigned) {
88     m_data.m_unsigned = u;
89   }
90 
91   template <typename T,
92             typename std::enable_if<std::is_integral<T>::value &&
93                                     std::is_signed<T>::value>::type * = nullptr>
JSONNumber(T s)94   explicit JSONNumber(T s)
95       : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Signed) {
96     m_data.m_signed = s;
97   }
98 
99   template <typename T, typename std::enable_if<
100                             std::is_floating_point<T>::value>::type * = nullptr>
JSONNumber(T d)101   explicit JSONNumber(T d)
102       : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Double) {
103     m_data.m_double = d;
104   }
105 
106   ~JSONNumber() override = default;
107 
108   JSONNumber(const JSONNumber &s) = delete;
109   JSONNumber &operator=(const JSONNumber &s) = delete;
110 
111   void Write(std::ostream &s) override;
112 
113   uint64_t GetAsUnsigned() const;
114 
115   int64_t GetAsSigned() const;
116 
117   double GetAsDouble() const;
118 
classof(const JSONValue * V)119   static bool classof(const JSONValue *V) {
120     return V->GetKind() == JSONValue::Kind::Number;
121   }
122 
123 private:
124   enum class DataType : uint8_t { Unsigned, Signed, Double } m_data_type;
125 
126   union {
127     uint64_t m_unsigned;
128     int64_t m_signed;
129     double m_double;
130   } m_data;
131 };
132 
133 class JSONTrue : public JSONValue {
134 public:
135   JSONTrue();
136 
137   JSONTrue(const JSONTrue &s) = delete;
138   JSONTrue &operator=(const JSONTrue &s) = delete;
139 
140   void Write(std::ostream &s) override;
141 
142   typedef std::shared_ptr<JSONTrue> SP;
143 
classof(const JSONValue * V)144   static bool classof(const JSONValue *V) {
145     return V->GetKind() == JSONValue::Kind::True;
146   }
147 
148   ~JSONTrue() override = default;
149 };
150 
151 class JSONFalse : public JSONValue {
152 public:
153   JSONFalse();
154 
155   JSONFalse(const JSONFalse &s) = delete;
156   JSONFalse &operator=(const JSONFalse &s) = delete;
157 
158   void Write(std::ostream &s) override;
159 
160   typedef std::shared_ptr<JSONFalse> SP;
161 
classof(const JSONValue * V)162   static bool classof(const JSONValue *V) {
163     return V->GetKind() == JSONValue::Kind::False;
164   }
165 
166   ~JSONFalse() override = default;
167 };
168 
169 class JSONNull : public JSONValue {
170 public:
171   JSONNull();
172 
173   JSONNull(const JSONNull &s) = delete;
174   JSONNull &operator=(const JSONNull &s) = delete;
175 
176   void Write(std::ostream &s) override;
177 
178   typedef std::shared_ptr<JSONNull> SP;
179 
classof(const JSONValue * V)180   static bool classof(const JSONValue *V) {
181     return V->GetKind() == JSONValue::Kind::Null;
182   }
183 
184   ~JSONNull() override = default;
185 };
186 
187 class JSONObject : public JSONValue {
188 public:
189   JSONObject();
190 
191   JSONObject(const JSONObject &s) = delete;
192   JSONObject &operator=(const JSONObject &s) = delete;
193 
194   void Write(std::ostream &s) override;
195 
196   typedef std::shared_ptr<JSONObject> SP;
197 
classof(const JSONValue * V)198   static bool classof(const JSONValue *V) {
199     return V->GetKind() == JSONValue::Kind::Object;
200   }
201 
202   bool SetObject(const std::string &key, JSONValue::SP value);
203 
204   JSONValue::SP GetObject(const std::string &key) const;
205 
206   /// Return keyed value as bool
207   ///
208   /// \param[in] key
209   ///     The value of the key to lookup
210   ///
211   /// \param[out] value
212   ///     The value of the key as a bool.  Undefined if the key doesn't
213   ///     exist or if the key is not either true or false.
214   ///
215   /// \return
216   ///     true if the key existed as was a bool value; false otherwise.
217   ///     Note the return value is *not* the value of the bool, use
218   ///     \b value for that.
219   bool GetObjectAsBool(const std::string &key, bool &value) const;
220 
221   bool GetObjectAsString(const std::string &key, std::string &value) const;
222 
223   ~JSONObject() override = default;
224 
225 private:
226   typedef std::map<std::string, JSONValue::SP> Map;
227   typedef Map::iterator Iterator;
228   Map m_elements;
229 };
230 
231 class JSONArray : public JSONValue {
232 public:
233   JSONArray();
234 
235   JSONArray(const JSONArray &s) = delete;
236   JSONArray &operator=(const JSONArray &s) = delete;
237 
238   void Write(std::ostream &s) override;
239 
240   typedef std::shared_ptr<JSONArray> SP;
241 
classof(const JSONValue * V)242   static bool classof(const JSONValue *V) {
243     return V->GetKind() == JSONValue::Kind::Array;
244   }
245 
246 private:
247   typedef std::vector<JSONValue::SP> Vector;
248   typedef Vector::iterator Iterator;
249   typedef Vector::size_type Index;
250   typedef Vector::size_type Size;
251 
252 public:
253   bool SetObject(Index i, JSONValue::SP value);
254 
255   bool AppendObject(JSONValue::SP value);
256 
257   JSONValue::SP GetObject(Index i);
258 
259   Size GetNumElements();
260 
261   ~JSONArray() override = default;
262 
263   Vector m_elements;
264 };
265 
266 class JSONParser : public StdStringExtractor {
267 public:
268   enum Token {
269     Invalid,
270     Status,
271     ObjectStart,
272     ObjectEnd,
273     ArrayStart,
274     ArrayEnd,
275     Comma,
276     Colon,
277     String,
278     Integer,
279     Float,
280     True,
281     False,
282     Null,
283     EndOfFile
284   };
285 
286   JSONParser(const char *cstr);
287 
288   int GetEscapedChar(bool &was_escaped);
289 
290   Token GetToken(std::string &value);
291 
292   JSONValue::SP ParseJSONValue();
293 
294 protected:
295   JSONValue::SP ParseJSONValue(const std::string &value, const Token &token);
296 
297   JSONValue::SP ParseJSONObject();
298 
299   JSONValue::SP ParseJSONArray();
300 };
301 
302 #endif // LLDB_TOOLS_DEBUGSERVER_SOURCE_JSON_H
303