Skip to content

Commit

Permalink
[JSON] Use LLVM's library for encoding JSON in StructuredData
Browse files Browse the repository at this point in the history
This patch replaces the hand-rolled JSON emission in StructuredData with
LLVM's JSON library.

Differential revision: https://reviews.llvm.org/D68248

llvm-svn: 373359
  • Loading branch information
JDevlieghere committed Oct 1, 2019
1 parent 9292983 commit 2783d81
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 102 deletions.
3 changes: 2 additions & 1 deletion lldb/include/lldb/Core/StructuredDataImpl.h
Expand Up @@ -54,7 +54,8 @@ class StructuredDataImpl {
return error;
}

m_data_sp->Dump(stream);
llvm::json::OStream s(stream.AsRawOstream());
m_data_sp->Serialize(s);
return error;
}

Expand Down
26 changes: 16 additions & 10 deletions lldb/include/lldb/Utility/StructuredData.h
Expand Up @@ -10,9 +10,11 @@
#define liblldb_StructuredData_h_

#include "llvm/ADT/StringRef.h"
#include "llvm/Support/JSON.h"

#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Stream.h"
#include "lldb/lldb-enumerations.h"

#include <cassert>
Expand All @@ -28,7 +30,6 @@

namespace lldb_private {
class Status;
class Stream;
}

namespace lldb_private {
Expand Down Expand Up @@ -150,7 +151,12 @@ class StructuredData {

void DumpToStdout(bool pretty_print = true) const;

virtual void Dump(Stream &s, bool pretty_print = true) const = 0;
virtual void Serialize(llvm::json::OStream &s) const = 0;

void Dump(lldb_private::Stream &s, bool pretty_print = true) const {
llvm::json::OStream jso(s.AsRawOstream(), pretty_print ? 2 : 0);
Serialize(jso);
}

private:
lldb::StructuredDataType m_type;
Expand Down Expand Up @@ -269,7 +275,7 @@ class StructuredData {

void AddItem(ObjectSP item) { m_items.push_back(item); }

void Dump(Stream &s, bool pretty_print = true) const override;
void Serialize(llvm::json::OStream &s) const override;

protected:
typedef std::vector<ObjectSP> collection;
Expand All @@ -287,7 +293,7 @@ class StructuredData {

uint64_t GetValue() { return m_value; }

void Dump(Stream &s, bool pretty_print = true) const override;
void Serialize(llvm::json::OStream &s) const override;

protected:
uint64_t m_value;
Expand All @@ -304,7 +310,7 @@ class StructuredData {

double GetValue() { return m_value; }

void Dump(Stream &s, bool pretty_print = true) const override;
void Serialize(llvm::json::OStream &s) const override;

protected:
double m_value;
Expand All @@ -321,7 +327,7 @@ class StructuredData {

bool GetValue() { return m_value; }

void Dump(Stream &s, bool pretty_print = true) const override;
void Serialize(llvm::json::OStream &s) const override;

protected:
bool m_value;
Expand All @@ -337,7 +343,7 @@ class StructuredData {

llvm::StringRef GetValue() { return m_value; }

void Dump(Stream &s, bool pretty_print = true) const override;
void Serialize(llvm::json::OStream &s) const override;

protected:
std::string m_value;
Expand Down Expand Up @@ -506,7 +512,7 @@ class StructuredData {
AddItem(key, std::make_shared<Boolean>(value));
}

void Dump(Stream &s, bool pretty_print = true) const override;
void Serialize(llvm::json::OStream &s) const override;

protected:
typedef std::map<ConstString, ObjectSP> collection;
Expand All @@ -521,7 +527,7 @@ class StructuredData {

bool IsValid() const override { return false; }

void Dump(Stream &s, bool pretty_print = true) const override;
void Serialize(llvm::json::OStream &s) const override;
};

class Generic : public Object {
Expand All @@ -535,7 +541,7 @@ class StructuredData {

bool IsValid() const override { return m_object != nullptr; }

void Dump(Stream &s, bool pretty_print = true) const override;
void Serialize(llvm::json::OStream &s) const override;

private:
void *m_object;
Expand Down
Expand Up @@ -5089,7 +5089,7 @@ ParseStructuredDataPacket(llvm::StringRef packet) {
if (log) {
if (json_sp) {
StreamString json_str;
json_sp->Dump(json_str);
json_sp->Dump(json_str, true);
json_str.Flush();
LLDB_LOGF(log,
"ProcessGDBRemote::%s() "
Expand Down
Expand Up @@ -29,8 +29,8 @@
using namespace lldb_private;
using namespace lldb;

void StructuredPythonObject::Dump(Stream &s, bool pretty_print) const {
s << "Python Obj: 0x" << GetValue();
void StructuredPythonObject::Serialize(llvm::json::OStream &s) const {
s.value(llvm::formatv("Python Obj: {0:X}", GetValue()).str());
}

// PythonObject
Expand Down
Expand Up @@ -43,7 +43,7 @@ class StructuredPythonObject : public StructuredData::Generic {

bool IsValid() const override { return GetValue() && GetValue() != Py_None; }

void Dump(Stream &s, bool pretty_print = true) const override;
void Serialize(llvm::json::OStream &s) const override;

private:
DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject);
Expand Down
100 changes: 25 additions & 75 deletions lldb/source/Utility/StructuredData.cpp
Expand Up @@ -11,7 +11,6 @@
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/JSON.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/MemoryBuffer.h"
Expand All @@ -21,6 +20,7 @@
#include <limits>

using namespace lldb_private;
using namespace llvm;

// Functions that use a JSONParser to parse JSON into StructuredData
static StructuredData::ObjectSP ParseJSONValue(JSONParser &json_parser);
Expand Down Expand Up @@ -181,98 +181,48 @@ StructuredData::Object::GetObjectForDotSeparatedPath(llvm::StringRef path) {
}

void StructuredData::Object::DumpToStdout(bool pretty_print) const {
StreamString stream;
Dump(stream, pretty_print);
llvm::outs() << stream.GetString();
json::OStream stream(llvm::outs(), pretty_print ? 2 : 0);
Serialize(stream);
}

void StructuredData::Array::Dump(Stream &s, bool pretty_print) const {
bool first = true;
s << "[";
if (pretty_print) {
s << "\n";
s.IndentMore();
}
void StructuredData::Array::Serialize(json::OStream &s) const {
s.arrayBegin();
for (const auto &item_sp : m_items) {
if (first) {
first = false;
} else {
s << ",";
if (pretty_print)
s << "\n";
}

if (pretty_print)
s.Indent();
item_sp->Dump(s, pretty_print);
}
if (pretty_print) {
s.IndentLess();
s.EOL();
s.Indent();
item_sp->Serialize(s);
}
s << "]";
s.arrayEnd();
}

void StructuredData::Integer::Dump(Stream &s, bool pretty_print) const {
s.Printf("%" PRIu64, m_value);
void StructuredData::Integer::Serialize(json::OStream &s) const {
s.value(static_cast<int64_t>(m_value));
}

void StructuredData::Float::Dump(Stream &s, bool pretty_print) const {
s.Printf("%lg", m_value);
void StructuredData::Float::Serialize(json::OStream &s) const {
s.value(m_value);
}

void StructuredData::Boolean::Dump(Stream &s, bool pretty_print) const {
if (m_value)
s.PutCString("true");
else
s.PutCString("false");
void StructuredData::Boolean::Serialize(json::OStream &s) const {
s.value(m_value);
}

void StructuredData::String::Dump(Stream &s, bool pretty_print) const {
std::string quoted;
const size_t strsize = m_value.size();
for (size_t i = 0; i < strsize; ++i) {
char ch = m_value[i];
if (ch == '"' || ch == '\\')
quoted.push_back('\\');
quoted.push_back(ch);
}
s.Printf("\"%s\"", quoted.c_str());
void StructuredData::String::Serialize(json::OStream &s) const {
s.value(m_value);
}

void StructuredData::Dictionary::Dump(Stream &s, bool pretty_print) const {
bool first = true;
s << "{";
if (pretty_print) {
s << "\n";
s.IndentMore();
}
void StructuredData::Dictionary::Serialize(json::OStream &s) const {
s.objectBegin();
for (const auto &pair : m_dict) {
if (first)
first = false;
else {
s << ",";
if (pretty_print)
s << "\n";
}
if (pretty_print)
s.Indent();
s << "\"" << pair.first.AsCString() << "\" : ";
pair.second->Dump(s, pretty_print);
}
if (pretty_print) {
s.IndentLess();
s.EOL();
s.Indent();
s.attributeBegin(pair.first.AsCString());
pair.second->Serialize(s);
s.attributeEnd();
}
s << "}";
s.objectEnd();
}

void StructuredData::Null::Dump(Stream &s, bool pretty_print) const {
s << "null";
void StructuredData::Null::Serialize(json::OStream &s) const {
s.value(nullptr);
}

void StructuredData::Generic::Dump(Stream &s, bool pretty_print) const {
s << "0x" << m_object;
void StructuredData::Generic::Serialize(json::OStream &s) const {
s.value(llvm::formatv("{0:X}", m_object));
}
Expand Up @@ -384,9 +384,9 @@ TEST_F(GDBRemoteCommunicationClientTest, SendStartTracePacket) {

// Since the line is exceeding 80 characters.
std::string expected_packet1 =
R"(jTraceStart:{"buffersize" : 8192,"metabuffersize" : 8192,"params" :)";
R"(jTraceStart:{"buffersize":8192,"metabuffersize":8192,"params":)";
std::string expected_packet2 =
R"( {"psb" : 1,"tracetech" : "intel-pt"},"threadid" : 35,"type" : 1})";
R"({"psb":1,"tracetech":"intel-pt"},"threadid":35,"type":1})";
HandlePacket(server, (expected_packet1 + expected_packet2), "1");
ASSERT_TRUE(error.Success());
ASSERT_EQ(result.get(), 1u);
Expand All @@ -409,8 +409,7 @@ TEST_F(GDBRemoteCommunicationClientTest, SendStopTracePacket) {
return client.SendStopTracePacket(trace_id, thread_id);
});

const char *expected_packet =
R"(jTraceStop:{"threadid" : 35,"traceid" : 3})";
const char *expected_packet = R"(jTraceStop:{"threadid":35,"traceid":3})";
HandlePacket(server, expected_packet, "OK");
ASSERT_TRUE(result.get().Success());

Expand All @@ -435,8 +434,8 @@ TEST_F(GDBRemoteCommunicationClientTest, SendGetDataPacket) {
});

std::string expected_packet1 =
R"(jTraceBufferRead:{"buffersize" : 32,"offset" : 0,"threadid" : 35,)";
std::string expected_packet2 = R"("traceid" : 3})";
R"(jTraceBufferRead:{"buffersize":32,"offset":0,"threadid":35,)";
std::string expected_packet2 = R"("traceid":3})";
HandlePacket(server, expected_packet1+expected_packet2, "123456");
ASSERT_TRUE(result.get().Success());
ASSERT_EQ(buffer.size(), 3u);
Expand Down Expand Up @@ -467,8 +466,8 @@ TEST_F(GDBRemoteCommunicationClientTest, SendGetMetaDataPacket) {
});

std::string expected_packet1 =
R"(jTraceMetaRead:{"buffersize" : 32,"offset" : 0,"threadid" : 35,)";
std::string expected_packet2 = R"("traceid" : 3})";
R"(jTraceMetaRead:{"buffersize":32,"offset":0,"threadid":35,)";
std::string expected_packet2 = R"("traceid":3})";
HandlePacket(server, expected_packet1+expected_packet2, "123456");
ASSERT_TRUE(result.get().Success());
ASSERT_EQ(buffer.size(), 3u);
Expand Down Expand Up @@ -497,11 +496,10 @@ TEST_F(GDBRemoteCommunicationClientTest, SendGetTraceConfigPacket) {
});

const char *expected_packet =
R"(jTraceConfigRead:{"threadid" : 35,"traceid" : 3})";
R"(jTraceConfigRead:{"threadid":35,"traceid":3})";
std::string response1 =
R"({"buffersize" : 8192,"params" : {"psb" : 1,"tracetech" : "intel-pt"})";
std::string response2 =
R"(],"metabuffersize" : 8192,"threadid" : 35,"type" : 1}])";
R"({"buffersize":8192,"params":{"psb":1,"tracetech":"intel-pt"})";
std::string response2 = R"(],"metabuffersize":8192,"threadid":35,"type":1}])";
HandlePacket(server, expected_packet, response1+response2);
ASSERT_TRUE(result.get().Success());
ASSERT_EQ(options.getTraceBufferSize(), 8192u);
Expand Down

0 comments on commit 2783d81

Please sign in to comment.