//===---------------------JSON.h --------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLDB_TOOLS_DEBUGSERVER_SOURCE_JSON_H #define LLDB_TOOLS_DEBUGSERVER_SOURCE_JSON_H #include "StdStringExtractor.h" // C includes #include #include // C++ includes #include #include #include #include #include class JSONValue { public: virtual void Write(std::ostream &s) = 0; typedef std::shared_ptr SP; enum class Kind { String, Number, True, False, Null, Object, Array }; JSONValue(Kind k) : m_kind(k) {} Kind GetKind() const { return m_kind; } virtual ~JSONValue() = default; private: const Kind m_kind; }; class JSONString : public JSONValue { public: JSONString(); JSONString(const char *s); JSONString(const std::string &s); JSONString(const JSONString &s) = delete; JSONString &operator=(const JSONString &s) = delete; void Write(std::ostream &s) override; typedef std::shared_ptr SP; std::string GetData() { return m_data; } static bool classof(const JSONValue *V) { return V->GetKind() == JSONValue::Kind::String; } ~JSONString() override = default; private: static std::string json_string_quote_metachars(const std::string &); std::string m_data; }; class JSONNumber : public JSONValue { public: typedef std::shared_ptr SP; // We cretae a constructor for all integer and floating point type with using // templates and // SFINAE to avoid having ambiguous overloads because of the implicit type // promotion. If we // would have constructors only with int64_t, uint64_t and double types then // constructing a // JSONNumber from an int32_t (or any other similar type) would fail to // compile. template ::value && std::is_unsigned::value>::type * = nullptr> explicit JSONNumber(T u) : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Unsigned) { m_data.m_unsigned = u; } template ::value && std::is_signed::value>::type * = nullptr> explicit JSONNumber(T s) : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Signed) { m_data.m_signed = s; } template ::value>::type * = nullptr> explicit JSONNumber(T d) : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Double) { m_data.m_double = d; } ~JSONNumber() override = default; JSONNumber(const JSONNumber &s) = delete; JSONNumber &operator=(const JSONNumber &s) = delete; void Write(std::ostream &s) override; uint64_t GetAsUnsigned() const; int64_t GetAsSigned() const; double GetAsDouble() const; static bool classof(const JSONValue *V) { return V->GetKind() == JSONValue::Kind::Number; } private: enum class DataType : uint8_t { Unsigned, Signed, Double } m_data_type; union { uint64_t m_unsigned; int64_t m_signed; double m_double; } m_data; }; class JSONTrue : public JSONValue { public: JSONTrue(); JSONTrue(const JSONTrue &s) = delete; JSONTrue &operator=(const JSONTrue &s) = delete; void Write(std::ostream &s) override; typedef std::shared_ptr SP; static bool classof(const JSONValue *V) { return V->GetKind() == JSONValue::Kind::True; } ~JSONTrue() override = default; }; class JSONFalse : public JSONValue { public: JSONFalse(); JSONFalse(const JSONFalse &s) = delete; JSONFalse &operator=(const JSONFalse &s) = delete; void Write(std::ostream &s) override; typedef std::shared_ptr SP; static bool classof(const JSONValue *V) { return V->GetKind() == JSONValue::Kind::False; } ~JSONFalse() override = default; }; class JSONNull : public JSONValue { public: JSONNull(); JSONNull(const JSONNull &s) = delete; JSONNull &operator=(const JSONNull &s) = delete; void Write(std::ostream &s) override; typedef std::shared_ptr SP; static bool classof(const JSONValue *V) { return V->GetKind() == JSONValue::Kind::Null; } ~JSONNull() override = default; }; class JSONObject : public JSONValue { public: JSONObject(); JSONObject(const JSONObject &s) = delete; JSONObject &operator=(const JSONObject &s) = delete; void Write(std::ostream &s) override; typedef std::shared_ptr SP; static bool classof(const JSONValue *V) { return V->GetKind() == JSONValue::Kind::Object; } bool SetObject(const std::string &key, JSONValue::SP value); JSONValue::SP GetObject(const std::string &key) const; /// Return keyed value as bool /// /// \param[in] key /// The value of the key to lookup /// /// \param[out] value /// The value of the key as a bool. Undefined if the key doesn't /// exist or if the key is not either true or false. /// /// \return /// true if the key existed as was a bool value; false otherwise. /// Note the return value is *not* the value of the bool, use /// \b value for that. bool GetObjectAsBool(const std::string &key, bool &value) const; bool GetObjectAsString(const std::string &key, std::string &value) const; ~JSONObject() override = default; private: typedef std::map Map; typedef Map::iterator Iterator; Map m_elements; }; class JSONArray : public JSONValue { public: JSONArray(); JSONArray(const JSONArray &s) = delete; JSONArray &operator=(const JSONArray &s) = delete; void Write(std::ostream &s) override; typedef std::shared_ptr SP; static bool classof(const JSONValue *V) { return V->GetKind() == JSONValue::Kind::Array; } private: typedef std::vector Vector; typedef Vector::iterator Iterator; typedef Vector::size_type Index; typedef Vector::size_type Size; public: bool SetObject(Index i, JSONValue::SP value); bool AppendObject(JSONValue::SP value); JSONValue::SP GetObject(Index i); Size GetNumElements(); ~JSONArray() override = default; Vector m_elements; }; class JSONParser : public StdStringExtractor { public: enum Token { Invalid, Status, ObjectStart, ObjectEnd, ArrayStart, ArrayEnd, Comma, Colon, String, Integer, Float, True, False, Null, EndOfFile }; JSONParser(const char *cstr); int GetEscapedChar(bool &was_escaped); Token GetToken(std::string &value); JSONValue::SP ParseJSONValue(); protected: JSONValue::SP ParseJSONValue(const std::string &value, const Token &token); JSONValue::SP ParseJSONObject(); JSONValue::SP ParseJSONArray(); }; #endif // LLDB_TOOLS_DEBUGSERVER_SOURCE_JSON_H