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
25class JSONValue {
26public:
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
39private:
40  const Kind m_kind;
41};
42
43class JSONString : public JSONValue {
44public:
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
64private:
65  static std::string json_string_quote_metachars(const std::string &);
66
67  std::string m_data;
68};
69
70class JSONNumber : public JSONValue {
71public:
72  typedef std::shared_ptr<JSONNumber> SP;
73
74  // We create 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
123private:
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
133class JSONTrue : public JSONValue {
134public:
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
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
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
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,
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
294protected:
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