Add StructuredData plugin type; showcase with new DarwinLog feature
Take 2, with missing cmake line fixed. Build tested on
Ubuntu 14.04 with clang-3.6.
See docs/structured_data/StructuredDataPlugins.md for details.
differential review: https://reviews.llvm.org/D22976
reviewers: clayborg, jingham
llvm-svn: 279202
diff --git a/lldb/tools/debugserver/source/JSON.h b/lldb/tools/debugserver/source/JSON.h
new file mode 100644
index 0000000..d1723d8
--- /dev/null
+++ b/lldb/tools/debugserver/source/JSON.h
@@ -0,0 +1,382 @@
+//===---------------------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_