blob: eee62f4533279b35c8e91850e9c4d1881230c2f9 [file] [log] [blame]
Todd Fiala75930012016-08-19 04:21:48 +00001//===---------------------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
Pavel Labath72090c22016-09-12 16:13:05 +000013#include "StdStringExtractor.h"
Todd Fiala75930012016-08-19 04:21:48 +000014
15// C includes
16#include <inttypes.h>
17#include <stdint.h>
18
19// C++ includes
20#include <map>
21#include <memory>
22#include <ostream>
23#include <string>
24#include <vector>
25
Kate Stoneb9c1b512016-09-06 20:57:50 +000026class JSONValue {
Todd Fiala75930012016-08-19 04:21:48 +000027public:
Kate Stoneb9c1b512016-09-06 20:57:50 +000028 virtual void Write(std::ostream &s) = 0;
Todd Fiala75930012016-08-19 04:21:48 +000029
Kate Stoneb9c1b512016-09-06 20:57:50 +000030 typedef std::shared_ptr<JSONValue> SP;
Todd Fiala75930012016-08-19 04:21:48 +000031
Kate Stoneb9c1b512016-09-06 20:57:50 +000032 enum class Kind { String, Number, True, False, Null, Object, Array };
Todd Fiala75930012016-08-19 04:21:48 +000033
Kate Stoneb9c1b512016-09-06 20:57:50 +000034 JSONValue(Kind k) : m_kind(k) {}
Todd Fiala75930012016-08-19 04:21:48 +000035
Kate Stoneb9c1b512016-09-06 20:57:50 +000036 Kind GetKind() const { return m_kind; }
Todd Fiala75930012016-08-19 04:21:48 +000037
Kate Stoneb9c1b512016-09-06 20:57:50 +000038 virtual ~JSONValue() = default;
Todd Fiala75930012016-08-19 04:21:48 +000039
40private:
Kate Stoneb9c1b512016-09-06 20:57:50 +000041 const Kind m_kind;
Todd Fiala75930012016-08-19 04:21:48 +000042};
43
Kate Stoneb9c1b512016-09-06 20:57:50 +000044class JSONString : public JSONValue {
Todd Fiala75930012016-08-19 04:21:48 +000045public:
Kate Stoneb9c1b512016-09-06 20:57:50 +000046 JSONString();
47 JSONString(const char *s);
48 JSONString(const std::string &s);
Todd Fiala75930012016-08-19 04:21:48 +000049
Kate Stoneb9c1b512016-09-06 20:57:50 +000050 JSONString(const JSONString &s) = delete;
51 JSONString &operator=(const JSONString &s) = delete;
Todd Fiala75930012016-08-19 04:21:48 +000052
Kate Stoneb9c1b512016-09-06 20:57:50 +000053 void Write(std::ostream &s) override;
Todd Fiala75930012016-08-19 04:21:48 +000054
Kate Stoneb9c1b512016-09-06 20:57:50 +000055 typedef std::shared_ptr<JSONString> SP;
Todd Fiala75930012016-08-19 04:21:48 +000056
Kate Stoneb9c1b512016-09-06 20:57:50 +000057 std::string GetData() { return m_data; }
Todd Fiala75930012016-08-19 04:21:48 +000058
Kate Stoneb9c1b512016-09-06 20:57:50 +000059 static bool classof(const JSONValue *V) {
60 return V->GetKind() == JSONValue::Kind::String;
61 }
Todd Fiala75930012016-08-19 04:21:48 +000062
Kate Stoneb9c1b512016-09-06 20:57:50 +000063 ~JSONString() override = default;
Todd Fiala75930012016-08-19 04:21:48 +000064
Todd Fiala75930012016-08-19 04:21:48 +000065private:
Kate Stoneb9c1b512016-09-06 20:57:50 +000066 static std::string json_string_quote_metachars(const std::string &);
67
68 std::string m_data;
Todd Fiala75930012016-08-19 04:21:48 +000069};
70
Kate Stoneb9c1b512016-09-06 20:57:50 +000071class JSONNumber : public JSONValue {
Todd Fiala75930012016-08-19 04:21:48 +000072public:
Kate Stoneb9c1b512016-09-06 20:57:50 +000073 typedef std::shared_ptr<JSONNumber> SP;
74
75 // We cretae a constructor for all integer and floating point type with using
76 // templates and
77 // SFINAE to avoid having ambiguous overloads because of the implicit type
78 // promotion. If we
79 // would have constructors only with int64_t, uint64_t and double types then
80 // constructing a
81 // JSONNumber from an int32_t (or any other similar type) would fail to
82 // compile.
83
84 template <typename T, typename std::enable_if<
85 std::is_integral<T>::value &&
86 std::is_unsigned<T>::value>::type * = nullptr>
87 explicit JSONNumber(T u)
88 : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Unsigned) {
89 m_data.m_unsigned = u;
90 }
91
92 template <typename T,
93 typename std::enable_if<std::is_integral<T>::value &&
94 std::is_signed<T>::value>::type * = nullptr>
95 explicit JSONNumber(T s)
96 : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Signed) {
97 m_data.m_signed = s;
98 }
99
100 template <typename T, typename std::enable_if<
101 std::is_floating_point<T>::value>::type * = nullptr>
102 explicit JSONNumber(T d)
103 : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Double) {
104 m_data.m_double = d;
105 }
106
107 ~JSONNumber() override = default;
108
109 JSONNumber(const JSONNumber &s) = delete;
110 JSONNumber &operator=(const JSONNumber &s) = delete;
111
112 void Write(std::ostream &s) override;
113
114 uint64_t GetAsUnsigned() const;
115
116 int64_t GetAsSigned() const;
117
118 double GetAsDouble() const;
119
120 static bool classof(const JSONValue *V) {
121 return V->GetKind() == JSONValue::Kind::Number;
122 }
123
Todd Fiala75930012016-08-19 04:21:48 +0000124private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000125 enum class DataType : uint8_t { Unsigned, Signed, Double } m_data_type;
Todd Fiala75930012016-08-19 04:21:48 +0000126
Kate Stoneb9c1b512016-09-06 20:57:50 +0000127 union {
128 uint64_t m_unsigned;
129 int64_t m_signed;
130 double m_double;
131 } m_data;
Todd Fiala75930012016-08-19 04:21:48 +0000132};
133
Kate Stoneb9c1b512016-09-06 20:57:50 +0000134class JSONTrue : public JSONValue {
Todd Fiala75930012016-08-19 04:21:48 +0000135public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000136 JSONTrue();
Todd Fiala75930012016-08-19 04:21:48 +0000137
Kate Stoneb9c1b512016-09-06 20:57:50 +0000138 JSONTrue(const JSONTrue &s) = delete;
139 JSONTrue &operator=(const JSONTrue &s) = delete;
Todd Fiala75930012016-08-19 04:21:48 +0000140
Kate Stoneb9c1b512016-09-06 20:57:50 +0000141 void Write(std::ostream &s) override;
Todd Fiala75930012016-08-19 04:21:48 +0000142
Kate Stoneb9c1b512016-09-06 20:57:50 +0000143 typedef std::shared_ptr<JSONTrue> SP;
Todd Fiala75930012016-08-19 04:21:48 +0000144
Kate Stoneb9c1b512016-09-06 20:57:50 +0000145 static bool classof(const JSONValue *V) {
146 return V->GetKind() == JSONValue::Kind::True;
147 }
148
149 ~JSONTrue() override = default;
150};
151
152class JSONFalse : public JSONValue {
153public:
154 JSONFalse();
155
156 JSONFalse(const JSONFalse &s) = delete;
157 JSONFalse &operator=(const JSONFalse &s) = delete;
158
159 void Write(std::ostream &s) override;
160
161 typedef std::shared_ptr<JSONFalse> SP;
162
163 static bool classof(const JSONValue *V) {
164 return V->GetKind() == JSONValue::Kind::False;
165 }
166
167 ~JSONFalse() override = default;
168};
169
170class JSONNull : public JSONValue {
171public:
172 JSONNull();
173
174 JSONNull(const JSONNull &s) = delete;
175 JSONNull &operator=(const JSONNull &s) = delete;
176
177 void Write(std::ostream &s) override;
178
179 typedef std::shared_ptr<JSONNull> SP;
180
181 static bool classof(const JSONValue *V) {
182 return V->GetKind() == JSONValue::Kind::Null;
183 }
184
185 ~JSONNull() override = default;
186};
187
188class JSONObject : public JSONValue {
189public:
190 JSONObject();
191
192 JSONObject(const JSONObject &s) = delete;
193 JSONObject &operator=(const JSONObject &s) = delete;
194
195 void Write(std::ostream &s) override;
196
197 typedef std::shared_ptr<JSONObject> SP;
198
199 static bool classof(const JSONValue *V) {
200 return V->GetKind() == JSONValue::Kind::Object;
201 }
202
203 bool SetObject(const std::string &key, JSONValue::SP value);
204
205 JSONValue::SP GetObject(const std::string &key) const;
206
207 // -------------------------------------------------------------------------
208 /// Return keyed value as bool
209 ///
210 /// @param[in] key
211 /// The value of the key to lookup
212 ///
213 /// @param[out] value
214 /// The value of the key as a bool. Undefined if the key doesn't
215 /// exist or if the key is not either true or false.
216 ///
217 /// @return
218 /// true if the key existed as was a bool value; false otherwise.
219 /// Note the return value is *not* the value of the bool, use
220 /// \b value for that.
221 // -------------------------------------------------------------------------
222 bool GetObjectAsBool(const std::string &key, bool &value) const;
223
224 bool GetObjectAsString(const std::string &key, std::string &value) const;
225
226 ~JSONObject() override = default;
227
228private:
229 typedef std::map<std::string, JSONValue::SP> Map;
230 typedef Map::iterator Iterator;
231 Map m_elements;
232};
233
234class JSONArray : public JSONValue {
235public:
236 JSONArray();
237
238 JSONArray(const JSONArray &s) = delete;
239 JSONArray &operator=(const JSONArray &s) = delete;
240
241 void Write(std::ostream &s) override;
242
243 typedef std::shared_ptr<JSONArray> SP;
244
245 static bool classof(const JSONValue *V) {
246 return V->GetKind() == JSONValue::Kind::Array;
247 }
248
249private:
250 typedef std::vector<JSONValue::SP> Vector;
251 typedef Vector::iterator Iterator;
252 typedef Vector::size_type Index;
253 typedef Vector::size_type Size;
254
255public:
256 bool SetObject(Index i, JSONValue::SP value);
257
258 bool AppendObject(JSONValue::SP value);
259
260 JSONValue::SP GetObject(Index i);
261
262 Size GetNumElements();
263
264 ~JSONArray() override = default;
265
266 Vector m_elements;
267};
268
269class JSONParser : public StdStringExtractor {
270public:
271 enum Token {
272 Invalid,
273 Error,
274 ObjectStart,
275 ObjectEnd,
276 ArrayStart,
277 ArrayEnd,
278 Comma,
279 Colon,
280 String,
281 Integer,
282 Float,
283 True,
284 False,
285 Null,
286 EndOfFile
287 };
288
289 JSONParser(const char *cstr);
290
291 int GetEscapedChar(bool &was_escaped);
292
293 Token GetToken(std::string &value);
294
295 JSONValue::SP ParseJSONValue();
Todd Fiala75930012016-08-19 04:21:48 +0000296
297protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000298 JSONValue::SP ParseJSONObject();
Todd Fiala75930012016-08-19 04:21:48 +0000299
Kate Stoneb9c1b512016-09-06 20:57:50 +0000300 JSONValue::SP ParseJSONArray();
Todd Fiala75930012016-08-19 04:21:48 +0000301};
302
303#endif // utility_JSON_h_