175930019STodd Fiala //===---------------------JSON.h --------------------------------*- C++ -*-===//
275930019STodd Fiala //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
675930019STodd Fiala //
775930019STodd Fiala //===----------------------------------------------------------------------===//
875930019STodd Fiala 
9cdc514e4SJonas Devlieghere #ifndef LLDB_TOOLS_DEBUGSERVER_SOURCE_JSON_H
10cdc514e4SJonas Devlieghere #define LLDB_TOOLS_DEBUGSERVER_SOURCE_JSON_H
1175930019STodd Fiala 
1272090c21SPavel Labath #include "StdStringExtractor.h"
1375930019STodd Fiala 
1475930019STodd Fiala // C includes
15*76e47d48SRaphael Isemann #include <cinttypes>
16*76e47d48SRaphael Isemann #include <cstdint>
1775930019STodd Fiala 
1875930019STodd Fiala // C++ includes
1975930019STodd Fiala #include <map>
2075930019STodd Fiala #include <memory>
2175930019STodd Fiala #include <ostream>
2275930019STodd Fiala #include <string>
2375930019STodd Fiala #include <vector>
2475930019STodd Fiala 
25b9c1b51eSKate Stone class JSONValue {
2675930019STodd Fiala public:
27b9c1b51eSKate Stone   virtual void Write(std::ostream &s) = 0;
2875930019STodd Fiala 
2975930019STodd Fiala   typedef std::shared_ptr<JSONValue> SP;
3075930019STodd Fiala 
31b9c1b51eSKate Stone   enum class Kind { String, Number, True, False, Null, Object, Array };
3275930019STodd Fiala 
JSONValue(Kind k)33b9c1b51eSKate Stone   JSONValue(Kind k) : m_kind(k) {}
3475930019STodd Fiala 
GetKind()35b9c1b51eSKate Stone   Kind GetKind() const { return m_kind; }
3675930019STodd Fiala 
37b9c1b51eSKate Stone   virtual ~JSONValue() = default;
3875930019STodd Fiala 
3975930019STodd Fiala private:
4075930019STodd Fiala   const Kind m_kind;
4175930019STodd Fiala };
4275930019STodd Fiala 
43b9c1b51eSKate Stone class JSONString : public JSONValue {
4475930019STodd Fiala public:
4575930019STodd Fiala   JSONString();
4675930019STodd Fiala   JSONString(const char *s);
4775930019STodd Fiala   JSONString(const std::string &s);
4875930019STodd Fiala 
4975930019STodd Fiala   JSONString(const JSONString &s) = delete;
50b9c1b51eSKate Stone   JSONString &operator=(const JSONString &s) = delete;
5175930019STodd Fiala 
52b9c1b51eSKate Stone   void Write(std::ostream &s) override;
5375930019STodd Fiala 
5475930019STodd Fiala   typedef std::shared_ptr<JSONString> SP;
5575930019STodd Fiala 
GetData()56b9c1b51eSKate Stone   std::string GetData() { return m_data; }
5775930019STodd Fiala 
classof(const JSONValue * V)58b9c1b51eSKate Stone   static bool classof(const JSONValue *V) {
5975930019STodd Fiala     return V->GetKind() == JSONValue::Kind::String;
6075930019STodd Fiala   }
6175930019STodd Fiala 
6275930019STodd Fiala   ~JSONString() override = default;
6375930019STodd Fiala 
6475930019STodd Fiala private:
65b9c1b51eSKate Stone   static std::string json_string_quote_metachars(const std::string &);
6675930019STodd Fiala 
6775930019STodd Fiala   std::string m_data;
6875930019STodd Fiala };
6975930019STodd Fiala 
70b9c1b51eSKate Stone class JSONNumber : public JSONValue {
7175930019STodd Fiala public:
7275930019STodd Fiala   typedef std::shared_ptr<JSONNumber> SP;
7375930019STodd Fiala 
74b9c1b51eSKate Stone   // We cretae a constructor for all integer and floating point type with using
75b9c1b51eSKate Stone   // templates and
76b9c1b51eSKate Stone   // SFINAE to avoid having ambiguous overloads because of the implicit type
77b9c1b51eSKate Stone   // promotion. If we
78b9c1b51eSKate Stone   // would have constructors only with int64_t, uint64_t and double types then
79b9c1b51eSKate Stone   // constructing a
80b9c1b51eSKate Stone   // JSONNumber from an int32_t (or any other similar type) would fail to
81b9c1b51eSKate Stone   // compile.
8275930019STodd Fiala 
83b9c1b51eSKate Stone   template <typename T, typename std::enable_if<
84b9c1b51eSKate Stone                             std::is_integral<T>::value &&
8575930019STodd Fiala                             std::is_unsigned<T>::value>::type * = nullptr>
JSONNumber(T u)86b9c1b51eSKate Stone   explicit JSONNumber(T u)
87b9c1b51eSKate Stone       : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Unsigned) {
8875930019STodd Fiala     m_data.m_unsigned = u;
8975930019STodd Fiala   }
9075930019STodd Fiala 
9175930019STodd Fiala   template <typename T,
9275930019STodd Fiala             typename std::enable_if<std::is_integral<T>::value &&
9375930019STodd Fiala                                     std::is_signed<T>::value>::type * = nullptr>
JSONNumber(T s)94b9c1b51eSKate Stone   explicit JSONNumber(T s)
95b9c1b51eSKate Stone       : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Signed) {
9675930019STodd Fiala     m_data.m_signed = s;
9775930019STodd Fiala   }
9875930019STodd Fiala 
99b9c1b51eSKate Stone   template <typename T, typename std::enable_if<
100b9c1b51eSKate Stone                             std::is_floating_point<T>::value>::type * = nullptr>
JSONNumber(T d)101b9c1b51eSKate Stone   explicit JSONNumber(T d)
102b9c1b51eSKate Stone       : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Double) {
10375930019STodd Fiala     m_data.m_double = d;
10475930019STodd Fiala   }
10575930019STodd Fiala 
10675930019STodd Fiala   ~JSONNumber() override = default;
10775930019STodd Fiala 
10875930019STodd Fiala   JSONNumber(const JSONNumber &s) = delete;
109b9c1b51eSKate Stone   JSONNumber &operator=(const JSONNumber &s) = delete;
11075930019STodd Fiala 
111b9c1b51eSKate Stone   void Write(std::ostream &s) override;
11275930019STodd Fiala 
113b9c1b51eSKate Stone   uint64_t GetAsUnsigned() const;
11475930019STodd Fiala 
115b9c1b51eSKate Stone   int64_t GetAsSigned() const;
11675930019STodd Fiala 
117b9c1b51eSKate Stone   double GetAsDouble() const;
11875930019STodd Fiala 
classof(const JSONValue * V)119b9c1b51eSKate Stone   static bool classof(const JSONValue *V) {
12075930019STodd Fiala     return V->GetKind() == JSONValue::Kind::Number;
12175930019STodd Fiala   }
12275930019STodd Fiala 
12375930019STodd Fiala private:
124b9c1b51eSKate Stone   enum class DataType : uint8_t { Unsigned, Signed, Double } m_data_type;
12575930019STodd Fiala 
126b9c1b51eSKate Stone   union {
12775930019STodd Fiala     uint64_t m_unsigned;
12875930019STodd Fiala     int64_t m_signed;
12975930019STodd Fiala     double m_double;
13075930019STodd Fiala   } m_data;
13175930019STodd Fiala };
13275930019STodd Fiala 
133b9c1b51eSKate Stone class JSONTrue : public JSONValue {
13475930019STodd Fiala public:
13575930019STodd Fiala   JSONTrue();
13675930019STodd Fiala 
13775930019STodd Fiala   JSONTrue(const JSONTrue &s) = delete;
138b9c1b51eSKate Stone   JSONTrue &operator=(const JSONTrue &s) = delete;
13975930019STodd Fiala 
140b9c1b51eSKate Stone   void Write(std::ostream &s) override;
14175930019STodd Fiala 
14275930019STodd Fiala   typedef std::shared_ptr<JSONTrue> SP;
14375930019STodd Fiala 
classof(const JSONValue * V)144b9c1b51eSKate Stone   static bool classof(const JSONValue *V) {
14575930019STodd Fiala     return V->GetKind() == JSONValue::Kind::True;
14675930019STodd Fiala   }
14775930019STodd Fiala 
14875930019STodd Fiala   ~JSONTrue() override = default;
14975930019STodd Fiala };
15075930019STodd Fiala 
151b9c1b51eSKate Stone class JSONFalse : public JSONValue {
15275930019STodd Fiala public:
15375930019STodd Fiala   JSONFalse();
15475930019STodd Fiala 
15575930019STodd Fiala   JSONFalse(const JSONFalse &s) = delete;
156b9c1b51eSKate Stone   JSONFalse &operator=(const JSONFalse &s) = delete;
15775930019STodd Fiala 
158b9c1b51eSKate Stone   void Write(std::ostream &s) override;
15975930019STodd Fiala 
16075930019STodd Fiala   typedef std::shared_ptr<JSONFalse> SP;
16175930019STodd Fiala 
classof(const JSONValue * V)162b9c1b51eSKate Stone   static bool classof(const JSONValue *V) {
16375930019STodd Fiala     return V->GetKind() == JSONValue::Kind::False;
16475930019STodd Fiala   }
16575930019STodd Fiala 
16675930019STodd Fiala   ~JSONFalse() override = default;
16775930019STodd Fiala };
16875930019STodd Fiala 
169b9c1b51eSKate Stone class JSONNull : public JSONValue {
17075930019STodd Fiala public:
17175930019STodd Fiala   JSONNull();
17275930019STodd Fiala 
17375930019STodd Fiala   JSONNull(const JSONNull &s) = delete;
174b9c1b51eSKate Stone   JSONNull &operator=(const JSONNull &s) = delete;
17575930019STodd Fiala 
176b9c1b51eSKate Stone   void Write(std::ostream &s) override;
17775930019STodd Fiala 
17875930019STodd Fiala   typedef std::shared_ptr<JSONNull> SP;
17975930019STodd Fiala 
classof(const JSONValue * V)180b9c1b51eSKate Stone   static bool classof(const JSONValue *V) {
18175930019STodd Fiala     return V->GetKind() == JSONValue::Kind::Null;
18275930019STodd Fiala   }
18375930019STodd Fiala 
18475930019STodd Fiala   ~JSONNull() override = default;
18575930019STodd Fiala };
18675930019STodd Fiala 
187b9c1b51eSKate Stone class JSONObject : public JSONValue {
18875930019STodd Fiala public:
18975930019STodd Fiala   JSONObject();
19075930019STodd Fiala 
19175930019STodd Fiala   JSONObject(const JSONObject &s) = delete;
192b9c1b51eSKate Stone   JSONObject &operator=(const JSONObject &s) = delete;
19375930019STodd Fiala 
194b9c1b51eSKate Stone   void Write(std::ostream &s) override;
19575930019STodd Fiala 
19675930019STodd Fiala   typedef std::shared_ptr<JSONObject> SP;
19775930019STodd Fiala 
classof(const JSONValue * V)198b9c1b51eSKate Stone   static bool classof(const JSONValue *V) {
19975930019STodd Fiala     return V->GetKind() == JSONValue::Kind::Object;
20075930019STodd Fiala   }
20175930019STodd Fiala 
202b9c1b51eSKate Stone   bool SetObject(const std::string &key, JSONValue::SP value);
20375930019STodd Fiala 
204b9c1b51eSKate Stone   JSONValue::SP GetObject(const std::string &key) const;
20575930019STodd Fiala 
20675930019STodd Fiala   /// Return keyed value as bool
20775930019STodd Fiala   ///
208f05b42e9SAdrian Prantl   /// \param[in] key
20975930019STodd Fiala   ///     The value of the key to lookup
21075930019STodd Fiala   ///
211f05b42e9SAdrian Prantl   /// \param[out] value
21275930019STodd Fiala   ///     The value of the key as a bool.  Undefined if the key doesn't
21375930019STodd Fiala   ///     exist or if the key is not either true or false.
21475930019STodd Fiala   ///
215f05b42e9SAdrian Prantl   /// \return
21675930019STodd Fiala   ///     true if the key existed as was a bool value; false otherwise.
21775930019STodd Fiala   ///     Note the return value is *not* the value of the bool, use
21875930019STodd Fiala   ///     \b value for that.
219b9c1b51eSKate Stone   bool GetObjectAsBool(const std::string &key, bool &value) const;
22075930019STodd Fiala 
221b9c1b51eSKate Stone   bool GetObjectAsString(const std::string &key, std::string &value) const;
22275930019STodd Fiala 
22375930019STodd Fiala   ~JSONObject() override = default;
22475930019STodd Fiala 
22575930019STodd Fiala private:
22675930019STodd Fiala   typedef std::map<std::string, JSONValue::SP> Map;
22775930019STodd Fiala   typedef Map::iterator Iterator;
22875930019STodd Fiala   Map m_elements;
22975930019STodd Fiala };
23075930019STodd Fiala 
231b9c1b51eSKate Stone class JSONArray : public JSONValue {
23275930019STodd Fiala public:
23375930019STodd Fiala   JSONArray();
23475930019STodd Fiala 
23575930019STodd Fiala   JSONArray(const JSONArray &s) = delete;
236b9c1b51eSKate Stone   JSONArray &operator=(const JSONArray &s) = delete;
23775930019STodd Fiala 
238b9c1b51eSKate Stone   void Write(std::ostream &s) override;
23975930019STodd Fiala 
24075930019STodd Fiala   typedef std::shared_ptr<JSONArray> SP;
24175930019STodd Fiala 
classof(const JSONValue * V)242b9c1b51eSKate Stone   static bool classof(const JSONValue *V) {
24375930019STodd Fiala     return V->GetKind() == JSONValue::Kind::Array;
24475930019STodd Fiala   }
24575930019STodd Fiala 
24675930019STodd Fiala private:
24775930019STodd Fiala   typedef std::vector<JSONValue::SP> Vector;
24875930019STodd Fiala   typedef Vector::iterator Iterator;
24975930019STodd Fiala   typedef Vector::size_type Index;
25075930019STodd Fiala   typedef Vector::size_type Size;
25175930019STodd Fiala 
25275930019STodd Fiala public:
253b9c1b51eSKate Stone   bool SetObject(Index i, JSONValue::SP value);
25475930019STodd Fiala 
255b9c1b51eSKate Stone   bool AppendObject(JSONValue::SP value);
25675930019STodd Fiala 
257b9c1b51eSKate Stone   JSONValue::SP GetObject(Index i);
25875930019STodd Fiala 
259b9c1b51eSKate Stone   Size GetNumElements();
26075930019STodd Fiala 
26175930019STodd Fiala   ~JSONArray() override = default;
26275930019STodd Fiala 
26375930019STodd Fiala   Vector m_elements;
26475930019STodd Fiala };
26575930019STodd Fiala 
266b9c1b51eSKate Stone class JSONParser : public StdStringExtractor {
26775930019STodd Fiala public:
268b9c1b51eSKate Stone   enum Token {
26975930019STodd Fiala     Invalid,
27097206d57SZachary Turner     Status,
27175930019STodd Fiala     ObjectStart,
27275930019STodd Fiala     ObjectEnd,
27375930019STodd Fiala     ArrayStart,
27475930019STodd Fiala     ArrayEnd,
27575930019STodd Fiala     Comma,
27675930019STodd Fiala     Colon,
27775930019STodd Fiala     String,
27875930019STodd Fiala     Integer,
27975930019STodd Fiala     Float,
28075930019STodd Fiala     True,
28175930019STodd Fiala     False,
28275930019STodd Fiala     Null,
28375930019STodd Fiala     EndOfFile
28475930019STodd Fiala   };
28575930019STodd Fiala 
28675930019STodd Fiala   JSONParser(const char *cstr);
28775930019STodd Fiala 
288b9c1b51eSKate Stone   int GetEscapedChar(bool &was_escaped);
28975930019STodd Fiala 
290b9c1b51eSKate Stone   Token GetToken(std::string &value);
29175930019STodd Fiala 
292b9c1b51eSKate Stone   JSONValue::SP ParseJSONValue();
29375930019STodd Fiala 
29475930019STodd Fiala protected:
29510b85143SAlex Cameron   JSONValue::SP ParseJSONValue(const std::string &value, const Token &token);
29610b85143SAlex Cameron 
297b9c1b51eSKate Stone   JSONValue::SP ParseJSONObject();
29875930019STodd Fiala 
299b9c1b51eSKate Stone   JSONValue::SP ParseJSONArray();
30075930019STodd Fiala };
30175930019STodd Fiala 
302cdc514e4SJonas Devlieghere #endif // LLDB_TOOLS_DEBUGSERVER_SOURCE_JSON_H
303