| //===---------------------JSON.h --------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef utility_JSON_h_ |
| #define utility_JSON_h_ |
| |
| // This cross-project usage is fine as StringExtractor.h is entirely |
| // self-contained. |
| #include "lldb/Utility/StringExtractor.h" |
| |
| // C includes |
| #include <inttypes.h> |
| #include <stdint.h> |
| |
| // C++ includes |
| #include <map> |
| #include <memory> |
| #include <ostream> |
| #include <string> |
| #include <vector> |
| |
| class JSONValue |
| { |
| public: |
| virtual void |
| Write (std::ostream& s) = 0; |
| |
| typedef std::shared_ptr<JSONValue> 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<JSONString> 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<JSONNumber> 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 <typename T, |
| typename std::enable_if<std::is_integral<T>::value && |
| std::is_unsigned<T>::value>::type* = nullptr> |
| explicit JSONNumber (T u) : |
| JSONValue(JSONValue::Kind::Number), |
| m_data_type(DataType::Unsigned) |
| { |
| m_data.m_unsigned = u; |
| } |
| |
| template <typename T, |
| typename std::enable_if<std::is_integral<T>::value && |
| std::is_signed<T>::value>::type* = nullptr> |
| explicit JSONNumber (T s) : |
| JSONValue(JSONValue::Kind::Number), |
| m_data_type(DataType::Signed) |
| { |
| m_data.m_signed = s; |
| } |
| |
| template <typename T, |
| typename std::enable_if<std::is_floating_point<T>::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<JSONTrue> 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<JSONFalse> 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<JSONNull> 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<JSONObject> 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<std::string, JSONValue::SP> 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<JSONArray> SP; |
| |
| static bool classof(const JSONValue *V) |
| { |
| return V->GetKind() == JSONValue::Kind::Array; |
| } |
| |
| private: |
| typedef std::vector<JSONValue::SP> 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 StringExtractor |
| { |
| public: |
| enum Token |
| { |
| Invalid, |
| Error, |
| 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 |
| ParseJSONObject (); |
| |
| JSONValue::SP |
| ParseJSONArray (); |
| }; |
| |
| #endif // utility_JSON_h_ |