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