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 utility_JSON_h_
10 #define utility_JSON_h_
11 
12 #include "StdStringExtractor.h"
13 
14 // C includes
15 #include <inttypes.h>
16 #include <stdint.h>
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 
33   JSONValue(Kind k) : m_kind(k) {}
34 
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 
56   std::string GetData() { return m_data; }
57 
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>
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>
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>
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 
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 
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 
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 
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 
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   // -------------------------------------------------------------------------
207   /// Return keyed value as bool
208   ///
209   /// @param[in] key
210   ///     The value of the key to lookup
211   ///
212   /// @param[out] value
213   ///     The value of the key as a bool.  Undefined if the key doesn't
214   ///     exist or if the key is not either true or false.
215   ///
216   /// @return
217   ///     true if the key existed as was a bool value; false otherwise.
218   ///     Note the return value is *not* the value of the bool, use
219   ///     \b value for that.
220   // -------------------------------------------------------------------------
221   bool GetObjectAsBool(const std::string &key, bool &value) const;
222 
223   bool GetObjectAsString(const std::string &key, std::string &value) const;
224 
225   ~JSONObject() override = default;
226 
227 private:
228   typedef std::map<std::string, JSONValue::SP> Map;
229   typedef Map::iterator Iterator;
230   Map m_elements;
231 };
232 
233 class JSONArray : public JSONValue {
234 public:
235   JSONArray();
236 
237   JSONArray(const JSONArray &s) = delete;
238   JSONArray &operator=(const JSONArray &s) = delete;
239 
240   void Write(std::ostream &s) override;
241 
242   typedef std::shared_ptr<JSONArray> SP;
243 
244   static bool classof(const JSONValue *V) {
245     return V->GetKind() == JSONValue::Kind::Array;
246   }
247 
248 private:
249   typedef std::vector<JSONValue::SP> Vector;
250   typedef Vector::iterator Iterator;
251   typedef Vector::size_type Index;
252   typedef Vector::size_type Size;
253 
254 public:
255   bool SetObject(Index i, JSONValue::SP value);
256 
257   bool AppendObject(JSONValue::SP value);
258 
259   JSONValue::SP GetObject(Index i);
260 
261   Size GetNumElements();
262 
263   ~JSONArray() override = default;
264 
265   Vector m_elements;
266 };
267 
268 class JSONParser : public StdStringExtractor {
269 public:
270   enum Token {
271     Invalid,
272     Status,
273     ObjectStart,
274     ObjectEnd,
275     ArrayStart,
276     ArrayEnd,
277     Comma,
278     Colon,
279     String,
280     Integer,
281     Float,
282     True,
283     False,
284     Null,
285     EndOfFile
286   };
287 
288   JSONParser(const char *cstr);
289 
290   int GetEscapedChar(bool &was_escaped);
291 
292   Token GetToken(std::string &value);
293 
294   JSONValue::SP ParseJSONValue();
295 
296 protected:
297   JSONValue::SP ParseJSONObject();
298 
299   JSONValue::SP ParseJSONArray();
300 };
301 
302 #endif // utility_JSON_h_
303