blob: b1c4a4c9db82ae93c7085cb9831f7ecd52ff69a3 [file] [log] [blame]
Todd Fiala75930012016-08-19 04:21:48 +00001//===---------------------JSON.h --------------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Todd Fiala75930012016-08-19 04:21:48 +00006//
7//===----------------------------------------------------------------------===//
8
9#ifndef utility_JSON_h_
10#define utility_JSON_h_
11
Pavel Labath72090c22016-09-12 16:13:05 +000012#include "StdStringExtractor.h"
Todd Fiala75930012016-08-19 04:21:48 +000013
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
Kate Stoneb9c1b512016-09-06 20:57:50 +000025class JSONValue {
Todd Fiala75930012016-08-19 04:21:48 +000026public:
Kate Stoneb9c1b512016-09-06 20:57:50 +000027 virtual void Write(std::ostream &s) = 0;
Todd Fiala75930012016-08-19 04:21:48 +000028
Kate Stoneb9c1b512016-09-06 20:57:50 +000029 typedef std::shared_ptr<JSONValue> SP;
Todd Fiala75930012016-08-19 04:21:48 +000030
Kate Stoneb9c1b512016-09-06 20:57:50 +000031 enum class Kind { String, Number, True, False, Null, Object, Array };
Todd Fiala75930012016-08-19 04:21:48 +000032
Kate Stoneb9c1b512016-09-06 20:57:50 +000033 JSONValue(Kind k) : m_kind(k) {}
Todd Fiala75930012016-08-19 04:21:48 +000034
Kate Stoneb9c1b512016-09-06 20:57:50 +000035 Kind GetKind() const { return m_kind; }
Todd Fiala75930012016-08-19 04:21:48 +000036
Kate Stoneb9c1b512016-09-06 20:57:50 +000037 virtual ~JSONValue() = default;
Todd Fiala75930012016-08-19 04:21:48 +000038
39private:
Kate Stoneb9c1b512016-09-06 20:57:50 +000040 const Kind m_kind;
Todd Fiala75930012016-08-19 04:21:48 +000041};
42
Kate Stoneb9c1b512016-09-06 20:57:50 +000043class JSONString : public JSONValue {
Todd Fiala75930012016-08-19 04:21:48 +000044public:
Kate Stoneb9c1b512016-09-06 20:57:50 +000045 JSONString();
46 JSONString(const char *s);
47 JSONString(const std::string &s);
Todd Fiala75930012016-08-19 04:21:48 +000048
Kate Stoneb9c1b512016-09-06 20:57:50 +000049 JSONString(const JSONString &s) = delete;
50 JSONString &operator=(const JSONString &s) = delete;
Todd Fiala75930012016-08-19 04:21:48 +000051
Kate Stoneb9c1b512016-09-06 20:57:50 +000052 void Write(std::ostream &s) override;
Todd Fiala75930012016-08-19 04:21:48 +000053
Kate Stoneb9c1b512016-09-06 20:57:50 +000054 typedef std::shared_ptr<JSONString> SP;
Todd Fiala75930012016-08-19 04:21:48 +000055
Kate Stoneb9c1b512016-09-06 20:57:50 +000056 std::string GetData() { return m_data; }
Todd Fiala75930012016-08-19 04:21:48 +000057
Kate Stoneb9c1b512016-09-06 20:57:50 +000058 static bool classof(const JSONValue *V) {
59 return V->GetKind() == JSONValue::Kind::String;
60 }
Todd Fiala75930012016-08-19 04:21:48 +000061
Kate Stoneb9c1b512016-09-06 20:57:50 +000062 ~JSONString() override = default;
Todd Fiala75930012016-08-19 04:21:48 +000063
Todd Fiala75930012016-08-19 04:21:48 +000064private:
Kate Stoneb9c1b512016-09-06 20:57:50 +000065 static std::string json_string_quote_metachars(const std::string &);
66
67 std::string m_data;
Todd Fiala75930012016-08-19 04:21:48 +000068};
69
Kate Stoneb9c1b512016-09-06 20:57:50 +000070class JSONNumber : public JSONValue {
Todd Fiala75930012016-08-19 04:21:48 +000071public:
Kate Stoneb9c1b512016-09-06 20:57:50 +000072 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
Todd Fiala75930012016-08-19 04:21:48 +0000123private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000124 enum class DataType : uint8_t { Unsigned, Signed, Double } m_data_type;
Todd Fiala75930012016-08-19 04:21:48 +0000125
Kate Stoneb9c1b512016-09-06 20:57:50 +0000126 union {
127 uint64_t m_unsigned;
128 int64_t m_signed;
129 double m_double;
130 } m_data;
Todd Fiala75930012016-08-19 04:21:48 +0000131};
132
Kate Stoneb9c1b512016-09-06 20:57:50 +0000133class JSONTrue : public JSONValue {
Todd Fiala75930012016-08-19 04:21:48 +0000134public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000135 JSONTrue();
Todd Fiala75930012016-08-19 04:21:48 +0000136
Kate Stoneb9c1b512016-09-06 20:57:50 +0000137 JSONTrue(const JSONTrue &s) = delete;
138 JSONTrue &operator=(const JSONTrue &s) = delete;
Todd Fiala75930012016-08-19 04:21:48 +0000139
Kate Stoneb9c1b512016-09-06 20:57:50 +0000140 void Write(std::ostream &s) override;
Todd Fiala75930012016-08-19 04:21:48 +0000141
Kate Stoneb9c1b512016-09-06 20:57:50 +0000142 typedef std::shared_ptr<JSONTrue> SP;
Todd Fiala75930012016-08-19 04:21:48 +0000143
Kate Stoneb9c1b512016-09-06 20:57:50 +0000144 static bool classof(const JSONValue *V) {
145 return V->GetKind() == JSONValue::Kind::True;
146 }
147
148 ~JSONTrue() override = default;
149};
150
151class JSONFalse : public JSONValue {
152public:
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
169class JSONNull : public JSONValue {
170public:
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
187class JSONObject : public JSONValue {
188public:
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
Kate Stoneb9c1b512016-09-06 20:57:50 +0000206 /// Return keyed value as bool
207 ///
Adrian Prantlf05b42e2019-03-11 17:09:29 +0000208 /// \param[in] key
Kate Stoneb9c1b512016-09-06 20:57:50 +0000209 /// The value of the key to lookup
210 ///
Adrian Prantlf05b42e2019-03-11 17:09:29 +0000211 /// \param[out] value
Kate Stoneb9c1b512016-09-06 20:57:50 +0000212 /// 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 ///
Adrian Prantlf05b42e2019-03-11 17:09:29 +0000215 /// \return
Kate Stoneb9c1b512016-09-06 20:57:50 +0000216 /// 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.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000219 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
225private:
226 typedef std::map<std::string, JSONValue::SP> Map;
227 typedef Map::iterator Iterator;
228 Map m_elements;
229};
230
231class JSONArray : public JSONValue {
232public:
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
242 static bool classof(const JSONValue *V) {
243 return V->GetKind() == JSONValue::Kind::Array;
244 }
245
246private:
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
252public:
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
266class JSONParser : public StdStringExtractor {
267public:
268 enum Token {
269 Invalid,
Zachary Turner97206d52017-05-12 04:51:55 +0000270 Status,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000271 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();
Todd Fiala75930012016-08-19 04:21:48 +0000293
294protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000295 JSONValue::SP ParseJSONObject();
Todd Fiala75930012016-08-19 04:21:48 +0000296
Kate Stoneb9c1b512016-09-06 20:57:50 +0000297 JSONValue::SP ParseJSONArray();
Todd Fiala75930012016-08-19 04:21:48 +0000298};
299
300#endif // utility_JSON_h_