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_