Add byte counting mechanism to LLDB's Stream class.

Summary:
This patch allows LLDB's Stream class to count the bytes it has written to so far.

There are two major motivations for this patch:

The first one is that this will allow us to get rid of all the handwritten byte counting code
we have in LLDB so far. Examples for this are pretty much all functions in LLDB that
take a Stream to write to and return a size_t, which usually represents the bytes written.

By moving to this centralized byte counting mechanism, we hopefully can avoid some
tricky errors that happen when some code forgets to count the written bytes while
writing something to a stream.

The second motivation is that this is needed for the migration away from LLDB's `Stream`
and towards LLVM's `raw_ostream`. My current plan is to start offering a fake raw_ostream
class that just forwards to a LLDB Stream.

However, for this raw_ostream wrapper we need to fulfill the raw_ostream interface with
LLDB's Stream, which currently lacks the ability to count the bytes written so far (which
raw_ostream exposes by it's `tell()` method). By adding this functionality it is trivial to start
rolling out our raw_ostream wrapper (and then eventually completely move to raw_ostream).

Also, once this fake raw_ostream is available, we can start replacing our own code writing
to LLDB's Stream by LLVM code writing to raw_ostream. The best example for this is the
LEB128 encoding we currently ship, which can be replaced with by LLVM's version which
accepts an raw_ostream.

From the point of view of the pure source changes this test does, we essentially just renamed
the Write implementation in Stream to `WriteImpl` while the `Write` method everyone is using
to write its raw bytes is now just forwarding and counting the written bytes.

Reviewers: labath, davide

Reviewed By: labath

Subscribers: JDevlieghere, lldb-commits

Differential Revision: https://reviews.llvm.org/D50159

llvm-svn: 338733
This commit is contained in:
Raphael Isemann 2018-08-02 16:38:34 +00:00
parent 98768e40fe
commit 92b16738a1
11 changed files with 168 additions and 39 deletions

View File

@ -30,7 +30,8 @@ public:
void Flush() override; void Flush() override;
size_t Write(const void *src, size_t src_len) override; protected:
size_t WriteImpl(const void *src, size_t src_len) override;
private: private:
Debugger &m_debugger; Debugger &m_debugger;

View File

@ -30,12 +30,6 @@ public:
// Nothing to do when flushing a buffer based stream... // Nothing to do when flushing a buffer based stream...
} }
virtual size_t Write(const void *s, size_t length) {
if (s && length)
m_packet.append((const char *)s, ((const char *)s) + length);
return length;
}
void Clear() { m_packet.clear(); } void Clear() { m_packet.clear(); }
// Beware, this might not be NULL terminated as you can expect from // Beware, this might not be NULL terminated as you can expect from
@ -48,6 +42,12 @@ public:
protected: protected:
llvm::SmallVector<char, N> m_packet; llvm::SmallVector<char, N> m_packet;
virtual size_t WriteImpl(const void *s, size_t length) {
if (s && length)
m_packet.append((const char *)s, ((const char *)s) + length);
return length;
}
}; };
} // namespace lldb_private } // namespace lldb_private

View File

@ -46,13 +46,13 @@ public:
void Flush() override; void Flush() override;
size_t Write(const void *s, size_t length) override;
protected: protected:
//------------------------------------------------------------------ //------------------------------------------------------------------
// Classes that inherit from StreamFile can see and modify these // Classes that inherit from StreamFile can see and modify these
//------------------------------------------------------------------ //------------------------------------------------------------------
File m_file; File m_file;
size_t WriteImpl(const void *s, size_t length) override;
private: private:
DISALLOW_COPY_AND_ASSIGN(StreamFile); DISALLOW_COPY_AND_ASSIGN(StreamFile);

View File

@ -83,7 +83,13 @@ public:
/// @return /// @return
/// The number of bytes that were appended to the stream. /// The number of bytes that were appended to the stream.
//------------------------------------------------------------------ //------------------------------------------------------------------
virtual size_t Write(const void *src, size_t src_len) = 0; size_t Write(const void *src, size_t src_len) {
size_t appended_byte_count = WriteImpl(src, src_len);
m_bytes_written += appended_byte_count;
return appended_byte_count;
}
size_t GetWrittenBytes() const { return m_bytes_written; }
//------------------------------------------------------------------ //------------------------------------------------------------------
// Member functions // Member functions
@ -523,8 +529,25 @@ protected:
lldb::ByteOrder lldb::ByteOrder
m_byte_order; ///< Byte order to use when encoding scalar types. m_byte_order; ///< Byte order to use when encoding scalar types.
int m_indent_level; ///< Indention level. int m_indent_level; ///< Indention level.
std::size_t m_bytes_written = 0; ///< Number of bytes written so far.
size_t _PutHex8(uint8_t uvalue, bool add_prefix); size_t _PutHex8(uint8_t uvalue, bool add_prefix);
//------------------------------------------------------------------
/// Output character bytes to the stream.
///
/// Appends \a src_len characters from the buffer \a src to the stream.
///
/// @param[in] src
/// A buffer containing at least \a src_len bytes of data.
///
/// @param[in] src_len
/// A number of bytes to append to the stream.
///
/// @return
/// The number of bytes that were appended to the stream.
//------------------------------------------------------------------
virtual size_t WriteImpl(const void *src, size_t src_len) = 0;
}; };
} // namespace lldb_private } // namespace lldb_private

View File

@ -31,8 +31,6 @@ public:
void Flush() override; void Flush() override;
size_t Write(const void *s, size_t length) override;
void Clear(); void Clear();
bool Empty() const; bool Empty() const;
@ -49,6 +47,7 @@ public:
protected: protected:
std::string m_packet; std::string m_packet;
size_t WriteImpl(const void *s, size_t length) override;
}; };
} // namespace lldb_private } // namespace lldb_private

View File

@ -70,29 +70,6 @@ public:
} }
} }
size_t Write(const void *s, size_t length) override {
std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
if (m_streams.empty())
return 0;
size_t min_bytes_written = SIZE_MAX;
collection::iterator pos, end;
for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) {
// Allow for our collection to contain NULL streams. This allows the
// StreamTee to be used with hard coded indexes for clients that might
// want N total streams with only a few that are set to valid values.
Stream *strm = pos->get();
if (strm) {
const size_t bytes_written = strm->Write(s, length);
if (min_bytes_written > bytes_written)
min_bytes_written = bytes_written;
}
}
if (min_bytes_written == SIZE_MAX)
return 0;
return min_bytes_written;
}
size_t AppendStream(const lldb::StreamSP &stream_sp) { size_t AppendStream(const lldb::StreamSP &stream_sp) {
size_t new_idx = m_streams.size(); size_t new_idx = m_streams.size();
std::lock_guard<std::recursive_mutex> guard(m_streams_mutex); std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
@ -131,6 +108,29 @@ protected:
typedef std::vector<lldb::StreamSP> collection; typedef std::vector<lldb::StreamSP> collection;
mutable std::recursive_mutex m_streams_mutex; mutable std::recursive_mutex m_streams_mutex;
collection m_streams; collection m_streams;
size_t WriteImpl(const void *s, size_t length) override {
std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
if (m_streams.empty())
return 0;
size_t min_bytes_written = SIZE_MAX;
collection::iterator pos, end;
for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) {
// Allow for our collection to contain NULL streams. This allows the
// StreamTee to be used with hard coded indexes for clients that might
// want N total streams with only a few that are set to valid values.
Stream *strm = pos->get();
if (strm) {
const size_t bytes_written = strm->Write(s, length);
if (min_bytes_written > bytes_written)
min_bytes_written = bytes_written;
}
}
if (min_bytes_written == SIZE_MAX)
return 0;
return min_bytes_written;
}
}; };
} // namespace lldb_private } // namespace lldb_private

View File

@ -31,7 +31,7 @@ void StreamAsynchronousIO::Flush() {
} }
} }
size_t StreamAsynchronousIO::Write(const void *s, size_t length) { size_t StreamAsynchronousIO::WriteImpl(const void *s, size_t length) {
m_data.append((const char *)s, length); m_data.append((const char *)s, length);
return length; return length;
} }

View File

@ -41,7 +41,7 @@ StreamFile::~StreamFile() {}
void StreamFile::Flush() { m_file.Flush(); } void StreamFile::Flush() { m_file.Flush(); }
size_t StreamFile::Write(const void *s, size_t length) { size_t StreamFile::WriteImpl(const void *s, size_t length) {
m_file.Write(s, length); m_file.Write(s, length);
return length; return length;
} }

View File

@ -24,12 +24,15 @@ void StreamString::Flush() {
// Nothing to do when flushing a buffer based stream... // Nothing to do when flushing a buffer based stream...
} }
size_t StreamString::Write(const void *s, size_t length) { size_t StreamString::WriteImpl(const void *s, size_t length) {
m_packet.append(reinterpret_cast<const char *>(s), length); m_packet.append(reinterpret_cast<const char *>(s), length);
return length; return length;
} }
void StreamString::Clear() { m_packet.clear(); } void StreamString::Clear() {
m_packet.clear();
m_bytes_written = 0;
}
bool StreamString::Empty() const { return GetSize() == 0; } bool StreamString::Empty() const { return GetSize() == 0; }

View File

@ -90,7 +90,9 @@ namespace {
void Flush() override { void Flush() override {
++m_flush_count; ++m_flush_count;
} }
size_t Write(const void *src, size_t src_len) override { return src_len; } size_t WriteImpl(const void *src, size_t src_len) override {
return src_len;
}
}; };
} }

View File

@ -44,149 +44,211 @@ TEST_F(StreamTest, ChangingByteOrder) {
TEST_F(StreamTest, PutChar) { TEST_F(StreamTest, PutChar) {
s.PutChar('a'); s.PutChar('a');
EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ("a", TakeValue()); EXPECT_EQ("a", TakeValue());
s.PutChar('1'); s.PutChar('1');
EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ("1", TakeValue()); EXPECT_EQ("1", TakeValue());
} }
TEST_F(StreamTest, PutCharWhitespace) { TEST_F(StreamTest, PutCharWhitespace) {
s.PutChar(' '); s.PutChar(' ');
EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ(" ", TakeValue()); EXPECT_EQ(" ", TakeValue());
s.PutChar('\n'); s.PutChar('\n');
EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ("\n", TakeValue()); EXPECT_EQ("\n", TakeValue());
s.PutChar('\r'); s.PutChar('\r');
EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ("\r", TakeValue()); EXPECT_EQ("\r", TakeValue());
s.PutChar('\t'); s.PutChar('\t');
EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ("\t", TakeValue()); EXPECT_EQ("\t", TakeValue());
} }
TEST_F(StreamTest, PutCString) { TEST_F(StreamTest, PutCString) {
s.PutCString(""); s.PutCString("");
EXPECT_EQ(0U, s.GetWrittenBytes());
EXPECT_EQ("", TakeValue()); EXPECT_EQ("", TakeValue());
s.PutCString("foobar"); s.PutCString("foobar");
EXPECT_EQ(6U, s.GetWrittenBytes());
EXPECT_EQ("foobar", TakeValue()); EXPECT_EQ("foobar", TakeValue());
s.PutCString(" "); s.PutCString(" ");
EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ(" ", TakeValue()); EXPECT_EQ(" ", TakeValue());
} }
TEST_F(StreamTest, PutCStringWithStringRef) { TEST_F(StreamTest, PutCStringWithStringRef) {
s.PutCString(llvm::StringRef("")); s.PutCString(llvm::StringRef(""));
EXPECT_EQ(0U, s.GetWrittenBytes());
EXPECT_EQ("", TakeValue()); EXPECT_EQ("", TakeValue());
s.PutCString(llvm::StringRef("foobar")); s.PutCString(llvm::StringRef("foobar"));
EXPECT_EQ(6U, s.GetWrittenBytes());
EXPECT_EQ("foobar", TakeValue()); EXPECT_EQ("foobar", TakeValue());
s.PutCString(llvm::StringRef(" ")); s.PutCString(llvm::StringRef(" "));
EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ(" ", TakeValue()); EXPECT_EQ(" ", TakeValue());
} }
TEST_F(StreamTest, QuotedCString) { TEST_F(StreamTest, QuotedCString) {
s.QuotedCString("foo"); s.QuotedCString("foo");
EXPECT_EQ(5U, s.GetWrittenBytes());
EXPECT_EQ(R"("foo")", TakeValue()); EXPECT_EQ(R"("foo")", TakeValue());
s.QuotedCString("ba r"); s.QuotedCString("ba r");
EXPECT_EQ(6U, s.GetWrittenBytes());
EXPECT_EQ(R"("ba r")", TakeValue()); EXPECT_EQ(R"("ba r")", TakeValue());
s.QuotedCString(" "); s.QuotedCString(" ");
EXPECT_EQ(3U, s.GetWrittenBytes());
EXPECT_EQ(R"(" ")", TakeValue()); EXPECT_EQ(R"(" ")", TakeValue());
} }
TEST_F(StreamTest, PutCharNull) { TEST_F(StreamTest, PutCharNull) {
s.PutChar('\0'); s.PutChar('\0');
EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ(std::string("\0", 1), TakeValue()); EXPECT_EQ(std::string("\0", 1), TakeValue());
s.PutChar('a'); s.PutChar('a');
EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ(std::string("a", 1), TakeValue()); EXPECT_EQ(std::string("a", 1), TakeValue());
} }
TEST_F(StreamTest, PutCStringAsRawHex8) { TEST_F(StreamTest, PutCStringAsRawHex8) {
s.PutCStringAsRawHex8(""); s.PutCStringAsRawHex8("");
EXPECT_EQ(0U, s.GetWrittenBytes());
EXPECT_EQ("", TakeValue()); EXPECT_EQ("", TakeValue());
s.PutCStringAsRawHex8("foobar"); s.PutCStringAsRawHex8("foobar");
EXPECT_EQ(12U, s.GetWrittenBytes());
EXPECT_EQ("666f6f626172", TakeValue()); EXPECT_EQ("666f6f626172", TakeValue());
s.PutCStringAsRawHex8(" "); s.PutCStringAsRawHex8(" ");
EXPECT_EQ(2U, s.GetWrittenBytes());
EXPECT_EQ("20", TakeValue()); EXPECT_EQ("20", TakeValue());
} }
TEST_F(StreamTest, PutHex8) { TEST_F(StreamTest, PutHex8) {
s.PutHex8((uint8_t)55); s.PutHex8((uint8_t)55);
EXPECT_EQ(2U, s.GetWrittenBytes());
EXPECT_EQ("37", TakeValue()); EXPECT_EQ("37", TakeValue());
s.PutHex8(std::numeric_limits<uint8_t>::max()); s.PutHex8(std::numeric_limits<uint8_t>::max());
EXPECT_EQ(2U, s.GetWrittenBytes());
EXPECT_EQ("ff", TakeValue()); EXPECT_EQ("ff", TakeValue());
s.PutHex8((uint8_t)0); s.PutHex8((uint8_t)0);
EXPECT_EQ(2U, s.GetWrittenBytes());
EXPECT_EQ("00", TakeValue()); EXPECT_EQ("00", TakeValue());
} }
TEST_F(StreamTest, PutNHex8) { TEST_F(StreamTest, PutNHex8) {
s.PutNHex8(0, (uint8_t)55); s.PutNHex8(0, (uint8_t)55);
EXPECT_EQ(0U, s.GetWrittenBytes());
EXPECT_EQ("", TakeValue()); EXPECT_EQ("", TakeValue());
s.PutNHex8(1, (uint8_t)55); s.PutNHex8(1, (uint8_t)55);
EXPECT_EQ(2U, s.GetWrittenBytes());
EXPECT_EQ("37", TakeValue()); EXPECT_EQ("37", TakeValue());
s.PutNHex8(2, (uint8_t)55); s.PutNHex8(2, (uint8_t)55);
EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("3737", TakeValue()); EXPECT_EQ("3737", TakeValue());
s.PutNHex8(1, (uint8_t)56); s.PutNHex8(1, (uint8_t)56);
EXPECT_EQ(2U, s.GetWrittenBytes());
EXPECT_EQ("38", TakeValue()); EXPECT_EQ("38", TakeValue());
} }
TEST_F(StreamTest, PutHex16ByteOrderLittle) { TEST_F(StreamTest, PutHex16ByteOrderLittle) {
s.PutHex16(0x1234U, lldb::eByteOrderLittle); s.PutHex16(0x1234U, lldb::eByteOrderLittle);
EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("3412", TakeValue()); EXPECT_EQ("3412", TakeValue());
s.PutHex16(std::numeric_limits<uint16_t>::max(), lldb::eByteOrderLittle); s.PutHex16(std::numeric_limits<uint16_t>::max(), lldb::eByteOrderLittle);
EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("ffff", TakeValue()); EXPECT_EQ("ffff", TakeValue());
s.PutHex16(0U, lldb::eByteOrderLittle); s.PutHex16(0U, lldb::eByteOrderLittle);
EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("0000", TakeValue()); EXPECT_EQ("0000", TakeValue());
} }
TEST_F(StreamTest, PutHex16ByteOrderBig) { TEST_F(StreamTest, PutHex16ByteOrderBig) {
s.PutHex16(0x1234U, lldb::eByteOrderBig); s.PutHex16(0x1234U, lldb::eByteOrderBig);
EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("1234", TakeValue()); EXPECT_EQ("1234", TakeValue());
s.PutHex16(std::numeric_limits<uint16_t>::max(), lldb::eByteOrderBig); s.PutHex16(std::numeric_limits<uint16_t>::max(), lldb::eByteOrderBig);
EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("ffff", TakeValue()); EXPECT_EQ("ffff", TakeValue());
s.PutHex16(0U, lldb::eByteOrderBig); s.PutHex16(0U, lldb::eByteOrderBig);
EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("0000", TakeValue()); EXPECT_EQ("0000", TakeValue());
} }
TEST_F(StreamTest, PutHex32ByteOrderLittle) { TEST_F(StreamTest, PutHex32ByteOrderLittle) {
s.PutHex32(0x12345678U, lldb::eByteOrderLittle); s.PutHex32(0x12345678U, lldb::eByteOrderLittle);
EXPECT_EQ(8U, s.GetWrittenBytes());
EXPECT_EQ("78563412", TakeValue()); EXPECT_EQ("78563412", TakeValue());
s.PutHex32(std::numeric_limits<uint32_t>::max(), lldb::eByteOrderLittle); s.PutHex32(std::numeric_limits<uint32_t>::max(), lldb::eByteOrderLittle);
EXPECT_EQ(8U, s.GetWrittenBytes());
EXPECT_EQ("ffffffff", TakeValue()); EXPECT_EQ("ffffffff", TakeValue());
s.PutHex32(0U, lldb::eByteOrderLittle); s.PutHex32(0U, lldb::eByteOrderLittle);
EXPECT_EQ(8U, s.GetWrittenBytes());
EXPECT_EQ("00000000", TakeValue()); EXPECT_EQ("00000000", TakeValue());
} }
TEST_F(StreamTest, PutHex32ByteOrderBig) { TEST_F(StreamTest, PutHex32ByteOrderBig) {
s.PutHex32(0x12345678U, lldb::eByteOrderBig); s.PutHex32(0x12345678U, lldb::eByteOrderBig);
EXPECT_EQ(8U, s.GetWrittenBytes());
EXPECT_EQ("12345678", TakeValue()); EXPECT_EQ("12345678", TakeValue());
s.PutHex32(std::numeric_limits<uint32_t>::max(), lldb::eByteOrderBig); s.PutHex32(std::numeric_limits<uint32_t>::max(), lldb::eByteOrderBig);
EXPECT_EQ(8U, s.GetWrittenBytes());
EXPECT_EQ("ffffffff", TakeValue()); EXPECT_EQ("ffffffff", TakeValue());
s.PutHex32(0U, lldb::eByteOrderBig); s.PutHex32(0U, lldb::eByteOrderBig);
EXPECT_EQ(8U, s.GetWrittenBytes());
EXPECT_EQ("00000000", TakeValue()); EXPECT_EQ("00000000", TakeValue());
} }
TEST_F(StreamTest, PutHex64ByteOrderLittle) { TEST_F(StreamTest, PutHex64ByteOrderLittle) {
s.PutHex64(0x1234567890ABCDEFU, lldb::eByteOrderLittle); s.PutHex64(0x1234567890ABCDEFU, lldb::eByteOrderLittle);
EXPECT_EQ(16U, s.GetWrittenBytes());
EXPECT_EQ("efcdab9078563412", TakeValue()); EXPECT_EQ("efcdab9078563412", TakeValue());
s.PutHex64(std::numeric_limits<uint64_t>::max(), lldb::eByteOrderLittle); s.PutHex64(std::numeric_limits<uint64_t>::max(), lldb::eByteOrderLittle);
EXPECT_EQ(16U, s.GetWrittenBytes());
EXPECT_EQ("ffffffffffffffff", TakeValue()); EXPECT_EQ("ffffffffffffffff", TakeValue());
s.PutHex64(0U, lldb::eByteOrderLittle); s.PutHex64(0U, lldb::eByteOrderLittle);
EXPECT_EQ(16U, s.GetWrittenBytes());
EXPECT_EQ("0000000000000000", TakeValue()); EXPECT_EQ("0000000000000000", TakeValue());
} }
TEST_F(StreamTest, PutHex64ByteOrderBig) { TEST_F(StreamTest, PutHex64ByteOrderBig) {
s.PutHex64(0x1234567890ABCDEFU, lldb::eByteOrderBig); s.PutHex64(0x1234567890ABCDEFU, lldb::eByteOrderBig);
EXPECT_EQ(16U, s.GetWrittenBytes());
EXPECT_EQ("1234567890abcdef", TakeValue()); EXPECT_EQ("1234567890abcdef", TakeValue());
s.PutHex64(std::numeric_limits<uint64_t>::max(), lldb::eByteOrderBig); s.PutHex64(std::numeric_limits<uint64_t>::max(), lldb::eByteOrderBig);
EXPECT_EQ(16U, s.GetWrittenBytes());
EXPECT_EQ("ffffffffffffffff", TakeValue()); EXPECT_EQ("ffffffffffffffff", TakeValue());
s.PutHex64(0U, lldb::eByteOrderBig); s.PutHex64(0U, lldb::eByteOrderBig);
EXPECT_EQ(16U, s.GetWrittenBytes());
EXPECT_EQ("0000000000000000", TakeValue()); EXPECT_EQ("0000000000000000", TakeValue());
} }
@ -200,6 +262,7 @@ TEST_F(StreamTest, PutMaxHex64ByteOrderBig) {
EXPECT_EQ(8U, bytes); EXPECT_EQ(8U, bytes);
bytes = s.PutMaxHex64(0x1234567890ABCDEFU, 8, lldb::eByteOrderBig); bytes = s.PutMaxHex64(0x1234567890ABCDEFU, 8, lldb::eByteOrderBig);
EXPECT_EQ(16U, bytes); EXPECT_EQ(16U, bytes);
EXPECT_EQ(30U, s.GetWrittenBytes());
EXPECT_EQ("121234123456781234567890abcdef", TakeValue()); EXPECT_EQ("121234123456781234567890abcdef", TakeValue());
} }
@ -213,6 +276,7 @@ TEST_F(StreamTest, PutMaxHex64ByteOrderLittle) {
EXPECT_EQ(8U, bytes); EXPECT_EQ(8U, bytes);
bytes = s.PutMaxHex64(0x1234567890ABCDEFU, 8, lldb::eByteOrderLittle); bytes = s.PutMaxHex64(0x1234567890ABCDEFU, 8, lldb::eByteOrderLittle);
EXPECT_EQ(16U, bytes); EXPECT_EQ(16U, bytes);
EXPECT_EQ(30U, s.GetWrittenBytes());
EXPECT_EQ("12341278563412efcdab9078563412", TakeValue()); EXPECT_EQ("12341278563412efcdab9078563412", TakeValue());
} }
@ -222,12 +286,15 @@ TEST_F(StreamTest, PutMaxHex64ByteOrderLittle) {
TEST_F(StreamTest, ShiftOperatorChars) { TEST_F(StreamTest, ShiftOperatorChars) {
s << 'a' << 'b'; s << 'a' << 'b';
EXPECT_EQ(2U, s.GetWrittenBytes());
EXPECT_EQ("ab", TakeValue()); EXPECT_EQ("ab", TakeValue());
} }
TEST_F(StreamTest, ShiftOperatorStrings) { TEST_F(StreamTest, ShiftOperatorStrings) {
s << "cstring\n"; s << "cstring\n";
EXPECT_EQ(8U, s.GetWrittenBytes());
s << llvm::StringRef("llvm::StringRef\n"); s << llvm::StringRef("llvm::StringRef\n");
EXPECT_EQ(24U, s.GetWrittenBytes());
EXPECT_EQ("cstring\nllvm::StringRef\n", TakeValue()); EXPECT_EQ("cstring\nllvm::StringRef\n", TakeValue());
} }
@ -236,6 +303,7 @@ TEST_F(StreamTest, ShiftOperatorInts) {
s << std::numeric_limits<int16_t>::max() << " "; s << std::numeric_limits<int16_t>::max() << " ";
s << std::numeric_limits<int32_t>::max() << " "; s << std::numeric_limits<int32_t>::max() << " ";
s << std::numeric_limits<int64_t>::max(); s << std::numeric_limits<int64_t>::max();
EXPECT_EQ(40U, s.GetWrittenBytes());
EXPECT_EQ("127 32767 2147483647 9223372036854775807", TakeValue()); EXPECT_EQ("127 32767 2147483647 9223372036854775807", TakeValue());
} }
@ -244,6 +312,7 @@ TEST_F(StreamTest, ShiftOperatorUInts) {
s << std::numeric_limits<uint16_t>::max() << " "; s << std::numeric_limits<uint16_t>::max() << " ";
s << std::numeric_limits<uint32_t>::max() << " "; s << std::numeric_limits<uint32_t>::max() << " ";
s << std::numeric_limits<uint64_t>::max(); s << std::numeric_limits<uint64_t>::max();
EXPECT_EQ(33U, s.GetWrittenBytes());
EXPECT_EQ("ff ffff ffffffff ffffffffffffffff", TakeValue()); EXPECT_EQ("ff ffff ffffffff ffffffffffffffff", TakeValue());
} }
@ -259,6 +328,7 @@ TEST_F(StreamTest, ShiftOperatorPtr) {
int *ptr = &i; int *ptr = &i;
s << ptr; s << ptr;
EXPECT_NE(0U, s.GetWrittenBytes());
EXPECT_TRUE(!TakeValue().empty()); EXPECT_TRUE(!TakeValue().empty());
} }
@ -268,6 +338,7 @@ TEST_F(StreamTest, PutPtr) {
int *ptr = &i; int *ptr = &i;
s.PutPointer(ptr); s.PutPointer(ptr);
EXPECT_NE(0U, s.GetWrittenBytes());
EXPECT_TRUE(!TakeValue().empty()); EXPECT_TRUE(!TakeValue().empty());
} }
@ -283,6 +354,7 @@ TEST_F(StreamTest, PutBytesAsRawHex8ToBigEndian) {
uint32_t value = 0x12345678; uint32_t value = 0x12345678;
s.PutBytesAsRawHex8(static_cast<void*>(&value), sizeof(value), s.PutBytesAsRawHex8(static_cast<void*>(&value), sizeof(value),
hostByteOrder, lldb::eByteOrderBig); hostByteOrder, lldb::eByteOrderBig);
EXPECT_EQ(8U, s.GetWrittenBytes());
EXPECT_EQ("78563412", TakeValue()); EXPECT_EQ("78563412", TakeValue());
} }
@ -290,6 +362,7 @@ TEST_F(StreamTest, PutRawBytesToBigEndian) {
uint32_t value = 0x12345678; uint32_t value = 0x12345678;
s.PutRawBytes(static_cast<void*>(&value), sizeof(value), s.PutRawBytes(static_cast<void*>(&value), sizeof(value),
hostByteOrder, lldb::eByteOrderBig); hostByteOrder, lldb::eByteOrderBig);
EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("\x78\x56\x34\x12", TakeValue()); EXPECT_EQ("\x78\x56\x34\x12", TakeValue());
} }
@ -297,6 +370,7 @@ TEST_F(StreamTest, PutBytesAsRawHex8ToLittleEndian) {
uint32_t value = 0x12345678; uint32_t value = 0x12345678;
s.PutBytesAsRawHex8(static_cast<void*>(&value), sizeof(value), s.PutBytesAsRawHex8(static_cast<void*>(&value), sizeof(value),
hostByteOrder, lldb::eByteOrderLittle); hostByteOrder, lldb::eByteOrderLittle);
EXPECT_EQ(8U, s.GetWrittenBytes());
EXPECT_EQ("12345678", TakeValue()); EXPECT_EQ("12345678", TakeValue());
} }
@ -304,6 +378,7 @@ TEST_F(StreamTest, PutRawBytesToLittleEndian) {
uint32_t value = 0x12345678; uint32_t value = 0x12345678;
s.PutRawBytes(static_cast<void*>(&value), sizeof(value), s.PutRawBytes(static_cast<void*>(&value), sizeof(value),
hostByteOrder, lldb::eByteOrderLittle); hostByteOrder, lldb::eByteOrderLittle);
EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("\x12\x34\x56\x78", TakeValue()); EXPECT_EQ("\x12\x34\x56\x78", TakeValue());
} }
@ -337,72 +412,84 @@ TEST_F(StreamTest, PutRawBytesToMixedEndian) {
TEST_F(BinaryStreamTest, PutULEB128OneByte) { TEST_F(BinaryStreamTest, PutULEB128OneByte) {
auto bytes = s.PutULEB128(0x74ULL); auto bytes = s.PutULEB128(0x74ULL);
EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ("\x74", TakeValue()); EXPECT_EQ("\x74", TakeValue());
EXPECT_EQ(1U, bytes); EXPECT_EQ(1U, bytes);
} }
TEST_F(BinaryStreamTest, PutULEB128TwoBytes) { TEST_F(BinaryStreamTest, PutULEB128TwoBytes) {
auto bytes = s.PutULEB128(0x1985ULL); auto bytes = s.PutULEB128(0x1985ULL);
EXPECT_EQ(2U, s.GetWrittenBytes());
EXPECT_EQ("\x85\x33", TakeValue()); EXPECT_EQ("\x85\x33", TakeValue());
EXPECT_EQ(2U, bytes); EXPECT_EQ(2U, bytes);
} }
TEST_F(BinaryStreamTest, PutULEB128ThreeBytes) { TEST_F(BinaryStreamTest, PutULEB128ThreeBytes) {
auto bytes = s.PutULEB128(0x5023ULL); auto bytes = s.PutULEB128(0x5023ULL);
EXPECT_EQ(3U, s.GetWrittenBytes());
EXPECT_EQ("\xA3\xA0\x1", TakeValue()); EXPECT_EQ("\xA3\xA0\x1", TakeValue());
EXPECT_EQ(3U, bytes); EXPECT_EQ(3U, bytes);
} }
TEST_F(BinaryStreamTest, PutULEB128FourBytes) { TEST_F(BinaryStreamTest, PutULEB128FourBytes) {
auto bytes = s.PutULEB128(0xA48032ULL); auto bytes = s.PutULEB128(0xA48032ULL);
EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("\xB2\x80\x92\x5", TakeValue()); EXPECT_EQ("\xB2\x80\x92\x5", TakeValue());
EXPECT_EQ(4U, bytes); EXPECT_EQ(4U, bytes);
} }
TEST_F(BinaryStreamTest, PutULEB128FiveBytes) { TEST_F(BinaryStreamTest, PutULEB128FiveBytes) {
auto bytes = s.PutULEB128(0x12345678ULL); auto bytes = s.PutULEB128(0x12345678ULL);
EXPECT_EQ(5U, s.GetWrittenBytes());
EXPECT_EQ("\xF8\xAC\xD1\x91\x1", TakeValue()); EXPECT_EQ("\xF8\xAC\xD1\x91\x1", TakeValue());
EXPECT_EQ(5U, bytes); EXPECT_EQ(5U, bytes);
} }
TEST_F(BinaryStreamTest, PutULEB128SixBytes) { TEST_F(BinaryStreamTest, PutULEB128SixBytes) {
auto bytes = s.PutULEB128(0xABFE3FAFDFULL); auto bytes = s.PutULEB128(0xABFE3FAFDFULL);
EXPECT_EQ(6U, s.GetWrittenBytes());
EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\x15", TakeValue()); EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\x15", TakeValue());
EXPECT_EQ(6U, bytes); EXPECT_EQ(6U, bytes);
} }
TEST_F(BinaryStreamTest, PutULEB128SevenBytes) { TEST_F(BinaryStreamTest, PutULEB128SevenBytes) {
auto bytes = s.PutULEB128(0xDABFE3FAFDFULL); auto bytes = s.PutULEB128(0xDABFE3FAFDFULL);
EXPECT_EQ(7U, s.GetWrittenBytes());
EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\xB5\x3", TakeValue()); EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\xB5\x3", TakeValue());
EXPECT_EQ(7U, bytes); EXPECT_EQ(7U, bytes);
} }
TEST_F(BinaryStreamTest, PutULEB128EightBytes) { TEST_F(BinaryStreamTest, PutULEB128EightBytes) {
auto bytes = s.PutULEB128(0x7CDABFE3FAFDFULL); auto bytes = s.PutULEB128(0x7CDABFE3FAFDFULL);
EXPECT_EQ(8U, s.GetWrittenBytes());
EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\xB5\xF3\x3", TakeValue()); EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\xB5\xF3\x3", TakeValue());
EXPECT_EQ(8U, bytes); EXPECT_EQ(8U, bytes);
} }
TEST_F(BinaryStreamTest, PutULEB128NineBytes) { TEST_F(BinaryStreamTest, PutULEB128NineBytes) {
auto bytes = s.PutULEB128(0x327CDABFE3FAFDFULL); auto bytes = s.PutULEB128(0x327CDABFE3FAFDFULL);
EXPECT_EQ(9U, s.GetWrittenBytes());
EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\xB5\xF3\x93\x3", TakeValue()); EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\xB5\xF3\x93\x3", TakeValue());
EXPECT_EQ(9U, bytes); EXPECT_EQ(9U, bytes);
} }
TEST_F(BinaryStreamTest, PutULEB128MaxValue) { TEST_F(BinaryStreamTest, PutULEB128MaxValue) {
auto bytes = s.PutULEB128(std::numeric_limits<uint64_t>::max()); auto bytes = s.PutULEB128(std::numeric_limits<uint64_t>::max());
EXPECT_EQ(10U, s.GetWrittenBytes());
EXPECT_EQ("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x1", TakeValue()); EXPECT_EQ("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x1", TakeValue());
EXPECT_EQ(10U, bytes); EXPECT_EQ(10U, bytes);
} }
TEST_F(BinaryStreamTest, PutULEB128Zero) { TEST_F(BinaryStreamTest, PutULEB128Zero) {
auto bytes = s.PutULEB128(0x0U); auto bytes = s.PutULEB128(0x0U);
EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ(std::string("\0", 1), TakeValue()); EXPECT_EQ(std::string("\0", 1), TakeValue());
EXPECT_EQ(1U, bytes); EXPECT_EQ(1U, bytes);
} }
TEST_F(BinaryStreamTest, PutULEB128One) { TEST_F(BinaryStreamTest, PutULEB128One) {
auto bytes = s.PutULEB128(0x1U); auto bytes = s.PutULEB128(0x1U);
EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ("\x1", TakeValue()); EXPECT_EQ("\x1", TakeValue());
EXPECT_EQ(1U, bytes); EXPECT_EQ(1U, bytes);
} }
@ -413,72 +500,84 @@ TEST_F(BinaryStreamTest, PutULEB128One) {
TEST_F(BinaryStreamTest, PutSLEB128OneByte) { TEST_F(BinaryStreamTest, PutSLEB128OneByte) {
auto bytes = s.PutSLEB128(0x74LL); auto bytes = s.PutSLEB128(0x74LL);
EXPECT_EQ(2U, s.GetWrittenBytes());
EXPECT_EQ(std::string("\xF4\0", 2), TakeValue()); EXPECT_EQ(std::string("\xF4\0", 2), TakeValue());
EXPECT_EQ(2U, bytes); EXPECT_EQ(2U, bytes);
} }
TEST_F(BinaryStreamTest, PutSLEB128TwoBytes) { TEST_F(BinaryStreamTest, PutSLEB128TwoBytes) {
auto bytes = s.PutSLEB128(0x1985LL); auto bytes = s.PutSLEB128(0x1985LL);
EXPECT_EQ(2U, s.GetWrittenBytes());
EXPECT_EQ("\x85\x33", TakeValue()); EXPECT_EQ("\x85\x33", TakeValue());
EXPECT_EQ(2U, bytes); EXPECT_EQ(2U, bytes);
} }
TEST_F(BinaryStreamTest, PutSLEB128ThreeBytes) { TEST_F(BinaryStreamTest, PutSLEB128ThreeBytes) {
auto bytes = s.PutSLEB128(0x5023LL); auto bytes = s.PutSLEB128(0x5023LL);
EXPECT_EQ(3U, s.GetWrittenBytes());
EXPECT_EQ("\xA3\xA0\x1", TakeValue()); EXPECT_EQ("\xA3\xA0\x1", TakeValue());
EXPECT_EQ(3U, bytes); EXPECT_EQ(3U, bytes);
} }
TEST_F(BinaryStreamTest, PutSLEB128FourBytes) { TEST_F(BinaryStreamTest, PutSLEB128FourBytes) {
auto bytes = s.PutSLEB128(0xA48032LL); auto bytes = s.PutSLEB128(0xA48032LL);
EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("\xB2\x80\x92\x5", TakeValue()); EXPECT_EQ("\xB2\x80\x92\x5", TakeValue());
EXPECT_EQ(4U, bytes); EXPECT_EQ(4U, bytes);
} }
TEST_F(BinaryStreamTest, PutSLEB128FiveBytes) { TEST_F(BinaryStreamTest, PutSLEB128FiveBytes) {
auto bytes = s.PutSLEB128(0x12345678LL); auto bytes = s.PutSLEB128(0x12345678LL);
EXPECT_EQ(5U, s.GetWrittenBytes());
EXPECT_EQ("\xF8\xAC\xD1\x91\x1", TakeValue()); EXPECT_EQ("\xF8\xAC\xD1\x91\x1", TakeValue());
EXPECT_EQ(5U, bytes); EXPECT_EQ(5U, bytes);
} }
TEST_F(BinaryStreamTest, PutSLEB128SixBytes) { TEST_F(BinaryStreamTest, PutSLEB128SixBytes) {
auto bytes = s.PutSLEB128(0xABFE3FAFDFLL); auto bytes = s.PutSLEB128(0xABFE3FAFDFLL);
EXPECT_EQ(6U, s.GetWrittenBytes());
EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\x15", TakeValue()); EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\x15", TakeValue());
EXPECT_EQ(6U, bytes); EXPECT_EQ(6U, bytes);
} }
TEST_F(BinaryStreamTest, PutSLEB128SevenBytes) { TEST_F(BinaryStreamTest, PutSLEB128SevenBytes) {
auto bytes = s.PutSLEB128(0xDABFE3FAFDFLL); auto bytes = s.PutSLEB128(0xDABFE3FAFDFLL);
EXPECT_EQ(7U, s.GetWrittenBytes());
EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\xB5\x3", TakeValue()); EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\xB5\x3", TakeValue());
EXPECT_EQ(7U, bytes); EXPECT_EQ(7U, bytes);
} }
TEST_F(BinaryStreamTest, PutSLEB128EightBytes) { TEST_F(BinaryStreamTest, PutSLEB128EightBytes) {
auto bytes = s.PutSLEB128(0x7CDABFE3FAFDFLL); auto bytes = s.PutSLEB128(0x7CDABFE3FAFDFLL);
EXPECT_EQ(8U, s.GetWrittenBytes());
EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\xB5\xF3\x3", TakeValue()); EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\xB5\xF3\x3", TakeValue());
EXPECT_EQ(8U, bytes); EXPECT_EQ(8U, bytes);
} }
TEST_F(BinaryStreamTest, PutSLEB128NineBytes) { TEST_F(BinaryStreamTest, PutSLEB128NineBytes) {
auto bytes = s.PutSLEB128(0x327CDABFE3FAFDFLL); auto bytes = s.PutSLEB128(0x327CDABFE3FAFDFLL);
EXPECT_EQ(9U, s.GetWrittenBytes());
EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\xB5\xF3\x93\x3", TakeValue()); EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\xB5\xF3\x93\x3", TakeValue());
EXPECT_EQ(9U, bytes); EXPECT_EQ(9U, bytes);
} }
TEST_F(BinaryStreamTest, PutSLEB128MaxValue) { TEST_F(BinaryStreamTest, PutSLEB128MaxValue) {
auto bytes = s.PutSLEB128(std::numeric_limits<int64_t>::max()); auto bytes = s.PutSLEB128(std::numeric_limits<int64_t>::max());
EXPECT_EQ(10U, s.GetWrittenBytes());
EXPECT_EQ(std::string("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0", 10), TakeValue()); EXPECT_EQ(std::string("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0", 10), TakeValue());
EXPECT_EQ(10U, bytes); EXPECT_EQ(10U, bytes);
} }
TEST_F(BinaryStreamTest, PutSLEB128Zero) { TEST_F(BinaryStreamTest, PutSLEB128Zero) {
auto bytes = s.PutSLEB128(0x0); auto bytes = s.PutSLEB128(0x0);
EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ(std::string("\0", 1), TakeValue()); EXPECT_EQ(std::string("\0", 1), TakeValue());
EXPECT_EQ(1U, bytes); EXPECT_EQ(1U, bytes);
} }
TEST_F(BinaryStreamTest, PutSLEB128One) { TEST_F(BinaryStreamTest, PutSLEB128One) {
auto bytes = s.PutSLEB128(0x1); auto bytes = s.PutSLEB128(0x1);
EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ(std::string("\x1", 1), TakeValue()); EXPECT_EQ(std::string("\x1", 1), TakeValue());
EXPECT_EQ(1U, bytes); EXPECT_EQ(1U, bytes);
} }
@ -492,12 +591,14 @@ TEST_F(BinaryStreamTest, PutSLEB128One) {
TEST_F(StreamTest, PutULEB128) { TEST_F(StreamTest, PutULEB128) {
auto bytes = s.PutULEB128(0x74ULL); auto bytes = s.PutULEB128(0x74ULL);
EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("0x74", TakeValue()); EXPECT_EQ("0x74", TakeValue());
EXPECT_EQ(4U, bytes); EXPECT_EQ(4U, bytes);
} }
TEST_F(StreamTest, PutSLEB128) { TEST_F(StreamTest, PutSLEB128) {
auto bytes = s.PutSLEB128(0x1985LL); auto bytes = s.PutSLEB128(0x1985LL);
EXPECT_EQ(6U, s.GetWrittenBytes());
EXPECT_EQ("0x6533", TakeValue()); EXPECT_EQ("0x6533", TakeValue());
EXPECT_EQ(6U, bytes); EXPECT_EQ(6U, bytes);
} }