Get rid of IMsfStreamData class.

This was a pure virtual base class whose purpose was to abstract
away the notion of how you retrieve the layout of a discontiguous
stream of blocks in an Msf file.  This led to too many layers of
abstraction making it difficult to figure out what was going on
and extend things.  Ultimately, a stream's layout is decided by
its length and the array of block numbers that it lives on.  So
rather than have an abstract base class which can return this in
any number of ways, it's more straightforward to simply store them
as fields of a trivial struct, and also to give a more appropriate
name.

This patch does that.  It renames IMsfStreamData to MsfStreamLayout,
and deletes the 2 concrete implementations, DirectoryStreamData
and IndexedStreamData.  MsfStreamLayout is a trivial struct
with the necessary data.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@277018 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Zachary Turner 2016-07-28 19:11:09 +00:00
parent f79c57a412
commit 0c78d1d159
19 changed files with 177 additions and 261 deletions

View File

@ -1,39 +0,0 @@
//===- DirectoryStreamData.h ---------------------------------- *- C++ --*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_MSF_DIRECTORYSTREAMDATA_H
#define LLVM_DEBUGINFO_MSF_DIRECTORYSTREAMDATA_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/DebugInfo/Msf/IMsfFile.h"
#include "llvm/DebugInfo/Msf/IMsfStreamData.h"
#include "llvm/Support/Endian.h"
namespace llvm {
namespace msf {
class IMsfFile;
class DirectoryStreamData : public IMsfStreamData {
public:
DirectoryStreamData(uint32_t Length, ArrayRef<support::ulittle32_t> Blocks)
: Length(Length), Blocks(Blocks) {}
virtual uint32_t getLength() { return Length; }
virtual llvm::ArrayRef<llvm::support::ulittle32_t> getStreamBlocks() {
return Blocks;
}
private:
uint32_t Length;
ArrayRef<support::ulittle32_t> Blocks;
};
}
}
#endif

View File

@ -1,40 +0,0 @@
//===- IMsfStreamData.h - Base interface for Msf Stream Data ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_MSF_IMSFSTREAMDATA_H
#define LLVM_DEBUGINFO_MSF_IMSFSTREAMDATA_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Endian.h"
#include <cstdint>
namespace llvm {
namespace msf {
/// IMsfStream abstracts the notion of PDB stream data. Although we already
/// have another stream abstraction (namely in the form of StreamInterface
/// and MappedBlockStream), they assume that the stream data is referenced
/// the same way. Namely, by looking in the directory to get the list of
/// stream blocks, and by looking in the array of stream lengths to get the
/// length. This breaks down for the directory itself, however, since its
/// length and list of blocks are stored elsewhere. By abstracting the
/// notion of stream data further, we can use a MappedBlockStream to read
/// from the directory itself, or from an indexed stream which references
/// the directory.
class IMsfStreamData {
public:
virtual ~IMsfStreamData() {}
virtual uint32_t getLength() = 0;
virtual ArrayRef<support::ulittle32_t> getStreamBlocks() = 0;
};
} // namespace msf
} // namespace llvm
#endif // LLVM_DEBUGINFO_MSF_IMSFSTREAMDATA_H

View File

@ -1,34 +0,0 @@
//===- IndexedStreamData.h - Standard Msf Stream Data -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_MSF_INDEXEDSTREAMDATA_H
#define LLVM_DEBUGINFO_MSF_INDEXEDSTREAMDATA_H
#include "llvm/DebugInfo/Msf/IMsfStreamData.h"
namespace llvm {
namespace msf {
class IMsfFile;
class IndexedStreamData : public IMsfStreamData {
public:
IndexedStreamData(uint32_t StreamIdx, const IMsfFile &File);
virtual ~IndexedStreamData() {}
uint32_t getLength() override;
ArrayRef<support::ulittle32_t> getStreamBlocks() override;
private:
uint32_t StreamIdx;
const IMsfFile &File;
};
} // namespace msf
} // namespace llvm
#endif // LLVM_DEBUGINFO_MSF_INDEXEDSTREAMDATA_H

View File

@ -14,7 +14,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/DebugInfo/Msf/IMsfStreamData.h"
#include "llvm/DebugInfo/Msf/MsfStreamLayout.h"
#include "llvm/DebugInfo/Msf/StreamInterface.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Endian.h"
@ -59,14 +59,14 @@ public:
llvm::BumpPtrAllocator &getAllocator() { return Pool; }
protected:
MappedBlockStream(std::unique_ptr<IMsfStreamData> Data, const IMsfFile &File);
MappedBlockStream(const MsfStreamLayout &Layout, const IMsfFile &File);
Error readBytes(uint32_t Offset, MutableArrayRef<uint8_t> Buffer) const;
bool tryReadContiguously(uint32_t Offset, uint32_t Size,
ArrayRef<uint8_t> &Buffer) const;
const IMsfFile &Msf;
std::unique_ptr<IMsfStreamData> Data;
const MsfStreamLayout Layout;
typedef MutableArrayRef<uint8_t> CacheEntry;
mutable llvm::BumpPtrAllocator Pool;

View File

@ -0,0 +1,35 @@
//===- MsfStreamLayout.h - Describes the layout of a stream -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_MSF_MSFSTREAMLAYOUT_H
#define LLVM_DEBUGINFO_MSF_MSFSTREAMLAYOUT_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Endian.h"
#include <cstdint>
namespace llvm {
namespace msf {
/// \brief Describes the layout of a stream in an Msf layout. A "stream" here
/// is defined as any logical unit of data which may be arranged inside the Msf
/// file as a sequence of (possibly discontiguous) blocks. When we want to read
/// from a particular Msf Stream, we fill out a stream layout structure and the
/// reader uses it to determine which blocks in the underlying Msf file contain
/// the data, so that it can be pieced together in the right order.
class MsfStreamLayout {
public:
uint32_t Length;
ArrayRef<support::ulittle32_t> Blocks;
};
} // namespace msf
} // namespace llvm
#endif // LLVM_DEBUGINFO_MSF_MSFSTREAMLAYOUT_H

View File

@ -46,6 +46,8 @@ public:
build(std::unique_ptr<msf::StreamInterface> PdbFileBuffer);
private:
Expected<msf::Layout> finalizeMsfLayout() const;
BumpPtrAllocator &Allocator;
std::unique_ptr<msf::MsfBuilder> Msf;

View File

@ -1,6 +1,5 @@
add_llvm_library(LLVMDebugInfoMsf
ByteStream.cpp
IndexedStreamData.cpp
MappedBlockStream.cpp
MsfBuilder.cpp
MsfCommon.cpp

View File

@ -1,25 +0,0 @@
//===- IndexedStreamData.cpp - Standard PDB Stream Data ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/Msf/IndexedStreamData.h"
#include "llvm/DebugInfo/Msf/IMsfFile.h"
using namespace llvm;
using namespace llvm::msf;
IndexedStreamData::IndexedStreamData(uint32_t StreamIdx, const IMsfFile &File)
: StreamIdx(StreamIdx), File(File) {}
uint32_t IndexedStreamData::getLength() {
return File.getStreamByteSize(StreamIdx);
}
ArrayRef<support::ulittle32_t> IndexedStreamData::getStreamBlocks() {
return File.getStreamBlockList(StreamIdx);
}

View File

@ -8,10 +8,10 @@
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/Msf/MappedBlockStream.h"
#include "llvm/DebugInfo/Msf/DirectoryStreamData.h"
#include "llvm/DebugInfo/Msf/IMsfStreamData.h"
#include "llvm/DebugInfo/Msf/IndexedStreamData.h"
#include "llvm/DebugInfo/Msf/IMsfFile.h"
#include "llvm/DebugInfo/Msf/MsfError.h"
#include "llvm/DebugInfo/Msf/MsfStreamLayout.h"
using namespace llvm;
using namespace llvm::msf;
@ -22,9 +22,8 @@ namespace {
// protected, forcing users to go through the `create` interface.
class MappedBlockStreamImpl : public MappedBlockStream {
public:
MappedBlockStreamImpl(std::unique_ptr<IMsfStreamData> Data,
const IMsfFile &File)
: MappedBlockStream(std::move(Data), File) {}
MappedBlockStreamImpl(const MsfStreamLayout &Layout, const IMsfFile &File)
: MappedBlockStream(Layout, File) {}
};
}
@ -34,16 +33,16 @@ static Interval intersect(const Interval &I1, const Interval &I2) {
std::min(I1.second, I2.second));
}
MappedBlockStream::MappedBlockStream(std::unique_ptr<IMsfStreamData> Data,
MappedBlockStream::MappedBlockStream(const MsfStreamLayout &Layout,
const IMsfFile &File)
: Msf(File), Data(std::move(Data)) {}
: Msf(File), Layout(Layout) {}
Error MappedBlockStream::readBytes(uint32_t Offset, uint32_t Size,
ArrayRef<uint8_t> &Buffer) const {
// Make sure we aren't trying to read beyond the end of the stream.
if (Size > Data->getLength())
if (Size > Layout.Length)
return make_error<MsfError>(msf_error_code::insufficient_buffer);
if (Offset > Data->getLength() - Size)
if (Offset > Layout.Length - Size)
return make_error<MsfError>(msf_error_code::insufficient_buffer);
if (tryReadContiguously(Offset, Size, Buffer))
@ -121,14 +120,13 @@ Error MappedBlockStream::readBytes(uint32_t Offset, uint32_t Size,
Error MappedBlockStream::readLongestContiguousChunk(
uint32_t Offset, ArrayRef<uint8_t> &Buffer) const {
// Make sure we aren't trying to read beyond the end of the stream.
if (Offset >= Data->getLength())
if (Offset >= Layout.Length)
return make_error<MsfError>(msf_error_code::insufficient_buffer);
uint32_t First = Offset / Msf.getBlockSize();
uint32_t Last = First;
auto BlockList = Data->getStreamBlocks();
while (Last < Msf.getBlockCount() - 1) {
if (BlockList[Last] != BlockList[Last + 1] - 1)
if (Layout.Blocks[Last] != Layout.Blocks[Last + 1] - 1)
break;
++Last;
}
@ -138,7 +136,7 @@ Error MappedBlockStream::readLongestContiguousChunk(
uint32_t BlockSpan = Last - First + 1;
uint32_t ByteSpan =
BytesFromFirstBlock + (BlockSpan - 1) * Msf.getBlockSize();
auto Result = Msf.getBlockData(BlockList[First], Msf.getBlockSize());
auto Result = Msf.getBlockData(Layout.Blocks[First], Msf.getBlockSize());
if (!Result)
return Result.takeError();
Buffer = Result->drop_front(OffsetInFirstBlock);
@ -146,7 +144,7 @@ Error MappedBlockStream::readLongestContiguousChunk(
return Error::success();
}
uint32_t MappedBlockStream::getLength() const { return Data->getLength(); }
uint32_t MappedBlockStream::getLength() const { return Layout.Length; }
Error MappedBlockStream::commit() const { return Error::success(); }
@ -165,15 +163,14 @@ bool MappedBlockStream::tryReadContiguously(uint32_t Offset, uint32_t Size,
llvm::alignTo(Size - BytesFromFirstBlock, Msf.getBlockSize()) /
Msf.getBlockSize();
auto BlockList = Data->getStreamBlocks();
uint32_t RequiredContiguousBlocks = NumAdditionalBlocks + 1;
uint32_t E = BlockList[BlockNum];
uint32_t E = Layout.Blocks[BlockNum];
for (uint32_t I = 0; I < RequiredContiguousBlocks; ++I, ++E) {
if (BlockList[I + BlockNum] != E)
if (Layout.Blocks[I + BlockNum] != E)
return false;
}
uint32_t FirstBlockAddr = BlockList[BlockNum];
uint32_t FirstBlockAddr = Layout.Blocks[BlockNum];
auto Result = Msf.getBlockData(FirstBlockAddr, Msf.getBlockSize());
if (!Result) {
consumeError(Result.takeError());
@ -190,17 +187,16 @@ Error MappedBlockStream::readBytes(uint32_t Offset,
uint32_t OffsetInBlock = Offset % Msf.getBlockSize();
// Make sure we aren't trying to read beyond the end of the stream.
if (Buffer.size() > Data->getLength())
if (Buffer.size() > Layout.Length)
return make_error<MsfError>(msf_error_code::insufficient_buffer);
if (Offset > Data->getLength() - Buffer.size())
if (Offset > Layout.Length - Buffer.size())
return make_error<MsfError>(msf_error_code::insufficient_buffer);
uint32_t BytesLeft = Buffer.size();
uint32_t BytesWritten = 0;
uint8_t *WriteBuffer = Buffer.data();
auto BlockList = Data->getStreamBlocks();
while (BytesLeft > 0) {
uint32_t StreamBlockAddr = BlockList[BlockNum];
uint32_t StreamBlockAddr = Layout.Blocks[BlockNum];
auto Result = Msf.getBlockData(StreamBlockAddr, Msf.getBlockSize());
if (!Result)
@ -224,20 +220,19 @@ Error MappedBlockStream::readBytes(uint32_t Offset,
Error MappedBlockStream::writeBytes(uint32_t Offset,
ArrayRef<uint8_t> Buffer) const {
// Make sure we aren't trying to write beyond the end of the stream.
if (Buffer.size() > Data->getLength())
if (Buffer.size() > Layout.Length)
return make_error<MsfError>(msf_error_code::insufficient_buffer);
if (Offset > Data->getLength() - Buffer.size())
if (Offset > Layout.Length - Buffer.size())
return make_error<MsfError>(msf_error_code::insufficient_buffer);
uint32_t BlockNum = Offset / Msf.getBlockSize();
uint32_t OffsetInBlock = Offset % Msf.getBlockSize();
uint32_t BytesLeft = Buffer.size();
auto BlockList = Data->getStreamBlocks();
uint32_t BytesWritten = 0;
while (BytesLeft > 0) {
uint32_t StreamBlockAddr = BlockList[BlockNum];
uint32_t StreamBlockAddr = Layout.Blocks[BlockNum];
uint32_t BytesToWriteInChunk =
std::min(BytesLeft, Msf.getBlockSize() - OffsetInBlock);
@ -297,15 +292,19 @@ MappedBlockStream::createIndexedStream(uint32_t StreamIdx,
const IMsfFile &File) {
if (StreamIdx >= File.getNumStreams())
return make_error<MsfError>(msf_error_code::no_stream);
auto Data = llvm::make_unique<IndexedStreamData>(StreamIdx, File);
return llvm::make_unique<MappedBlockStreamImpl>(std::move(Data), File);
MsfStreamLayout L;
L.Blocks = File.getStreamBlockList(StreamIdx);
L.Length = File.getStreamByteSize(StreamIdx);
return llvm::make_unique<MappedBlockStreamImpl>(L, File);
}
Expected<std::unique_ptr<MappedBlockStream>>
MappedBlockStream::createDirectoryStream(uint32_t Length,
ArrayRef<support::ulittle32_t> Blocks,
const IMsfFile &File) {
auto Data = llvm::make_unique<DirectoryStreamData>(Length, Blocks);
return llvm::make_unique<MappedBlockStreamImpl>(std::move(Data), File);
MsfStreamLayout L;
L.Blocks = Blocks;
L.Length = Length;
return llvm::make_unique<MappedBlockStreamImpl>(L, File);
}

View File

@ -9,7 +9,6 @@
#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
#include "llvm/DebugInfo/Msf/IndexedStreamData.h"
#include "llvm/DebugInfo/Msf/StreamArray.h"
#include "llvm/DebugInfo/Msf/StreamReader.h"
#include "llvm/DebugInfo/Msf/StreamWriter.h"

View File

@ -10,7 +10,6 @@
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/DebugInfo/Msf/IndexedStreamData.h"
#include "llvm/DebugInfo/Msf/StreamReader.h"
#include "llvm/DebugInfo/Msf/StreamWriter.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"

View File

@ -9,7 +9,6 @@
#include "llvm/DebugInfo/PDB/Raw/ModStream.h"
#include "llvm/DebugInfo/Msf/IndexedStreamData.h"
#include "llvm/DebugInfo/Msf/StreamReader.h"
#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"

View File

@ -10,8 +10,6 @@
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/DebugInfo/Msf/DirectoryStreamData.h"
#include "llvm/DebugInfo/Msf/IndexedStreamData.h"
#include "llvm/DebugInfo/Msf/StreamArray.h"
#include "llvm/DebugInfo/Msf/StreamInterface.h"
#include "llvm/DebugInfo/Msf/StreamReader.h"

View File

@ -58,8 +58,7 @@ DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() {
return *Dbi;
}
Expected<std::unique_ptr<PDBFile>>
PDBFileBuilder::build(std::unique_ptr<msf::StreamInterface> PdbFileBuffer) {
Expected<msf::Layout> PDBFileBuilder::finalizeMsfLayout() const {
if (Info) {
uint32_t Length = Info->calculateSerializedLength();
if (auto EC = Msf->setStreamSize(StreamPDB, Length))
@ -71,7 +70,12 @@ PDBFileBuilder::build(std::unique_ptr<msf::StreamInterface> PdbFileBuffer) {
return std::move(EC);
}
auto ExpectedLayout = Msf->build();
return Msf->build();
}
Expected<std::unique_ptr<PDBFile>>
PDBFileBuilder::build(std::unique_ptr<msf::StreamInterface> PdbFileBuffer) {
auto ExpectedLayout = finalizeMsfLayout();
if (!ExpectedLayout)
return ExpectedLayout.takeError();

View File

@ -26,7 +26,6 @@
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/Msf/IndexedStreamData.h"
#include "llvm/DebugInfo/Msf/MappedBlockStream.h"
#include "llvm/DebugInfo/Msf/StreamReader.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"

View File

@ -11,7 +11,6 @@
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/Msf/IndexedStreamData.h"
#include "llvm/DebugInfo/Msf/MappedBlockStream.h"
#include "llvm/DebugInfo/Msf/StreamReader.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"

View File

@ -13,7 +13,6 @@
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/Msf/IndexedStreamData.h"
#include "llvm/DebugInfo/Msf/MappedBlockStream.h"
#include "llvm/DebugInfo/Msf/StreamReader.h"
#include "llvm/DebugInfo/PDB/Raw/Hash.h"

View File

@ -13,7 +13,6 @@
#include "llvm/DebugInfo/CodeView/EnumTables.h"
#include "llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h"
#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
#include "llvm/DebugInfo/Msf/IndexedStreamData.h"
#include "llvm/DebugInfo/Msf/MappedBlockStream.h"
#include "llvm/DebugInfo/Msf/StreamReader.h"
#include "llvm/DebugInfo/PDB/PDBExtras.h"

View File

@ -11,9 +11,8 @@
#include "llvm/DebugInfo/Msf/ByteStream.h"
#include "llvm/DebugInfo/Msf/IMsfFile.h"
#include "llvm/DebugInfo/Msf/IMsfStreamData.h"
#include "llvm/DebugInfo/Msf/IndexedStreamData.h"
#include "llvm/DebugInfo/Msf/MappedBlockStream.h"
#include "llvm/DebugInfo/Msf/MsfStreamLayout.h"
#include "llvm/DebugInfo/Msf/StreamReader.h"
#include "llvm/DebugInfo/Msf/StreamRef.h"
#include "llvm/DebugInfo/Msf/StreamWriter.h"
@ -66,19 +65,15 @@ private:
MutableArrayRef<uint8_t> Data;
};
class MappedBlockStreamImpl : public MappedBlockStream {
public:
MappedBlockStreamImpl(std::unique_ptr<IMsfStreamData> Data,
const IMsfFile &File)
: MappedBlockStream(std::move(Data), File) {}
};
// Tests that a read which is entirely contained within a single block works
// and does not allocate.
TEST(MappedBlockStreamTest, ReadBeyondEndOfStreamRef) {
DiscontiguousFile F(BlocksAry, DataAry);
MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
StreamReader R(S);
auto ExpectedS = MappedBlockStream::createIndexedStream(0, F);
EXPECT_EXPECTED(ExpectedS);
auto &S = *ExpectedS;
StreamReader R(*S);
StreamRef SR;
EXPECT_NO_ERROR(R.readStreamRef(SR, 0U));
ArrayRef<uint8_t> Buffer;
@ -91,12 +86,14 @@ TEST(MappedBlockStreamTest, ReadBeyondEndOfStreamRef) {
// does not fail due to the length of the output buffer.
TEST(MappedBlockStreamTest, ReadOntoNonEmptyBuffer) {
DiscontiguousFile F(BlocksAry, DataAry);
MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
StreamReader R(S);
auto ExpectedS = MappedBlockStream::createIndexedStream(0, F);
EXPECT_EXPECTED(ExpectedS);
auto &S = *ExpectedS;
StreamReader R(*S);
StringRef Str = "ZYXWVUTSRQPONMLKJIHGFEDCBA";
EXPECT_NO_ERROR(R.readFixedString(Str, 1));
EXPECT_EQ(Str, StringRef("A"));
EXPECT_EQ(0U, S.getNumBytesCopied());
EXPECT_EQ(0U, S->getNumBytesCopied());
}
// Tests that a read which crosses a block boundary, but where the subsequent
@ -104,17 +101,19 @@ TEST(MappedBlockStreamTest, ReadOntoNonEmptyBuffer) {
// not allocate memory.
TEST(MappedBlockStreamTest, ZeroCopyReadContiguousBreak) {
DiscontiguousFile F(BlocksAry, DataAry);
MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
StreamReader R(S);
auto ExpectedS = MappedBlockStream::createIndexedStream(0, F);
EXPECT_EXPECTED(ExpectedS);
auto &S = *ExpectedS;
StreamReader R(*S);
StringRef Str;
EXPECT_NO_ERROR(R.readFixedString(Str, 2));
EXPECT_EQ(Str, StringRef("AB"));
EXPECT_EQ(0U, S.getNumBytesCopied());
EXPECT_EQ(0U, S->getNumBytesCopied());
R.setOffset(6);
EXPECT_NO_ERROR(R.readFixedString(Str, 4));
EXPECT_EQ(Str, StringRef("GHIJ"));
EXPECT_EQ(0U, S.getNumBytesCopied());
EXPECT_EQ(0U, S->getNumBytesCopied());
}
// Tests that a read which crosses a block boundary and cannot be referenced
@ -122,62 +121,72 @@ TEST(MappedBlockStreamTest, ZeroCopyReadContiguousBreak) {
// requested.
TEST(MappedBlockStreamTest, CopyReadNonContiguousBreak) {
DiscontiguousFile F(BlocksAry, DataAry);
MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
StreamReader R(S);
auto ExpectedS = MappedBlockStream::createIndexedStream(0, F);
EXPECT_EXPECTED(ExpectedS);
auto &S = *ExpectedS;
StreamReader R(*S);
StringRef Str;
EXPECT_NO_ERROR(R.readFixedString(Str, 10));
EXPECT_EQ(Str, StringRef("ABCDEFGHIJ"));
EXPECT_EQ(10U, S.getNumBytesCopied());
EXPECT_EQ(10U, S->getNumBytesCopied());
}
// Test that an out of bounds read which doesn't cross a block boundary
// fails and allocates no memory.
TEST(MappedBlockStreamTest, InvalidReadSizeNoBreak) {
DiscontiguousFile F(BlocksAry, DataAry);
MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
StreamReader R(S);
auto ExpectedS = MappedBlockStream::createIndexedStream(0, F);
EXPECT_EXPECTED(ExpectedS);
auto &S = *ExpectedS;
StreamReader R(*S);
StringRef Str;
R.setOffset(10);
EXPECT_ERROR(R.readFixedString(Str, 1));
EXPECT_EQ(0U, S.getNumBytesCopied());
EXPECT_EQ(0U, S->getNumBytesCopied());
}
// Test that an out of bounds read which crosses a contiguous block boundary
// fails and allocates no memory.
TEST(MappedBlockStreamTest, InvalidReadSizeContiguousBreak) {
DiscontiguousFile F(BlocksAry, DataAry);
MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
StreamReader R(S);
auto ExpectedS = MappedBlockStream::createIndexedStream(0, F);
EXPECT_EXPECTED(ExpectedS);
auto &S = *ExpectedS;
StreamReader R(*S);
StringRef Str;
R.setOffset(6);
EXPECT_ERROR(R.readFixedString(Str, 5));
EXPECT_EQ(0U, S.getNumBytesCopied());
EXPECT_EQ(0U, S->getNumBytesCopied());
}
// Test that an out of bounds read which crosses a discontiguous block
// boundary fails and allocates no memory.
TEST(MappedBlockStreamTest, InvalidReadSizeNonContiguousBreak) {
DiscontiguousFile F(BlocksAry, DataAry);
MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
StreamReader R(S);
auto ExpectedS = MappedBlockStream::createIndexedStream(0, F);
EXPECT_EXPECTED(ExpectedS);
auto &S = *ExpectedS;
StreamReader R(*S);
StringRef Str;
EXPECT_ERROR(R.readFixedString(Str, 11));
EXPECT_EQ(0U, S.getNumBytesCopied());
EXPECT_EQ(0U, S->getNumBytesCopied());
}
// Tests that a read which is entirely contained within a single block but
// beyond the end of a StreamRef fails.
TEST(MappedBlockStreamTest, ZeroCopyReadNoBreak) {
DiscontiguousFile F(BlocksAry, DataAry);
MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
StreamReader R(S);
auto ExpectedS = MappedBlockStream::createIndexedStream(0, F);
EXPECT_EXPECTED(ExpectedS);
auto &S = *ExpectedS;
StreamReader R(*S);
StringRef Str;
EXPECT_NO_ERROR(R.readFixedString(Str, 1));
EXPECT_EQ(Str, StringRef("A"));
EXPECT_EQ(0U, S.getNumBytesCopied());
EXPECT_EQ(0U, S->getNumBytesCopied());
}
// Tests that a read which is not aligned on the same boundary as a previous
@ -185,19 +194,21 @@ TEST(MappedBlockStreamTest, ZeroCopyReadNoBreak) {
// previous allocation.
TEST(MappedBlockStreamTest, UnalignedOverlappingRead) {
DiscontiguousFile F(BlocksAry, DataAry);
MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
StreamReader R(S);
auto ExpectedS = MappedBlockStream::createIndexedStream(0, F);
EXPECT_EXPECTED(ExpectedS);
auto &S = *ExpectedS;
StreamReader R(*S);
StringRef Str1;
StringRef Str2;
EXPECT_NO_ERROR(R.readFixedString(Str1, 7));
EXPECT_EQ(Str1, StringRef("ABCDEFG"));
EXPECT_EQ(7U, S.getNumBytesCopied());
EXPECT_EQ(7U, S->getNumBytesCopied());
R.setOffset(2);
EXPECT_NO_ERROR(R.readFixedString(Str2, 3));
EXPECT_EQ(Str2, StringRef("CDE"));
EXPECT_EQ(Str1.data() + 2, Str2.data());
EXPECT_EQ(7U, S.getNumBytesCopied());
EXPECT_EQ(7U, S->getNumBytesCopied());
}
// Tests that a read which is not aligned on the same boundary as a previous
@ -205,18 +216,20 @@ TEST(MappedBlockStreamTest, UnalignedOverlappingRead) {
// still works correctly and allocates again from the shared pool.
TEST(MappedBlockStreamTest, UnalignedOverlappingReadFail) {
DiscontiguousFile F(BlocksAry, DataAry);
MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
StreamReader R(S);
auto ExpectedS = MappedBlockStream::createIndexedStream(0, F);
EXPECT_EXPECTED(ExpectedS);
auto &S = *ExpectedS;
StreamReader R(*S);
StringRef Str1;
StringRef Str2;
EXPECT_NO_ERROR(R.readFixedString(Str1, 6));
EXPECT_EQ(Str1, StringRef("ABCDEF"));
EXPECT_EQ(6U, S.getNumBytesCopied());
EXPECT_EQ(6U, S->getNumBytesCopied());
R.setOffset(4);
EXPECT_NO_ERROR(R.readFixedString(Str2, 4));
EXPECT_EQ(Str2, StringRef("EFGH"));
EXPECT_EQ(10U, S.getNumBytesCopied());
EXPECT_EQ(10U, S->getNumBytesCopied());
}
TEST(MappedBlockStreamTest, WriteBeyondEndOfStream) {
@ -228,40 +241,44 @@ TEST(MappedBlockStreamTest, WriteBeyondEndOfStream) {
"LargeBuffer is not big enough");
DiscontiguousFile F(BlocksAry, Data);
MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
auto ExpectedS = MappedBlockStream::createIndexedStream(0, F);
EXPECT_EXPECTED(ExpectedS);
auto &S = *ExpectedS;
ArrayRef<uint8_t> Buffer;
EXPECT_ERROR(S.writeBytes(0, ArrayRef<uint8_t>(LargeBuffer)));
EXPECT_NO_ERROR(S.writeBytes(0, ArrayRef<uint8_t>(SmallBuffer)));
EXPECT_NO_ERROR(S.writeBytes(7, ArrayRef<uint8_t>(SmallBuffer)));
EXPECT_ERROR(S.writeBytes(8, ArrayRef<uint8_t>(SmallBuffer)));
EXPECT_ERROR(S->writeBytes(0, ArrayRef<uint8_t>(LargeBuffer)));
EXPECT_NO_ERROR(S->writeBytes(0, ArrayRef<uint8_t>(SmallBuffer)));
EXPECT_NO_ERROR(S->writeBytes(7, ArrayRef<uint8_t>(SmallBuffer)));
EXPECT_ERROR(S->writeBytes(8, ArrayRef<uint8_t>(SmallBuffer)));
}
TEST(MappedBlockStreamTest, TestWriteBytesNoBreakBoundary) {
static uint8_t Data[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'};
DiscontiguousFile F(BlocksAry, Data);
MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
auto ExpectedS = MappedBlockStream::createIndexedStream(0, F);
EXPECT_EXPECTED(ExpectedS);
auto &S = *ExpectedS;
ArrayRef<uint8_t> Buffer;
EXPECT_NO_ERROR(S.readBytes(0, 1, Buffer));
EXPECT_NO_ERROR(S->readBytes(0, 1, Buffer));
EXPECT_EQ(Buffer, ArrayRef<uint8_t>('A'));
EXPECT_NO_ERROR(S.readBytes(9, 1, Buffer));
EXPECT_NO_ERROR(S->readBytes(9, 1, Buffer));
EXPECT_EQ(Buffer, ArrayRef<uint8_t>('J'));
EXPECT_NO_ERROR(S.writeBytes(0, ArrayRef<uint8_t>('J')));
EXPECT_NO_ERROR(S.writeBytes(9, ArrayRef<uint8_t>('A')));
EXPECT_NO_ERROR(S->writeBytes(0, ArrayRef<uint8_t>('J')));
EXPECT_NO_ERROR(S->writeBytes(9, ArrayRef<uint8_t>('A')));
EXPECT_NO_ERROR(S.readBytes(0, 1, Buffer));
EXPECT_NO_ERROR(S->readBytes(0, 1, Buffer));
EXPECT_EQ(Buffer, ArrayRef<uint8_t>('J'));
EXPECT_NO_ERROR(S.readBytes(9, 1, Buffer));
EXPECT_NO_ERROR(S->readBytes(9, 1, Buffer));
EXPECT_EQ(Buffer, ArrayRef<uint8_t>('A'));
EXPECT_NO_ERROR(S.writeBytes(0, ArrayRef<uint8_t>('A')));
EXPECT_NO_ERROR(S.writeBytes(9, ArrayRef<uint8_t>('J')));
EXPECT_NO_ERROR(S->writeBytes(0, ArrayRef<uint8_t>('A')));
EXPECT_NO_ERROR(S->writeBytes(9, ArrayRef<uint8_t>('J')));
EXPECT_NO_ERROR(S.readBytes(0, 1, Buffer));
EXPECT_NO_ERROR(S->readBytes(0, 1, Buffer));
EXPECT_EQ(Buffer, ArrayRef<uint8_t>('A'));
EXPECT_NO_ERROR(S.readBytes(9, 1, Buffer));
EXPECT_NO_ERROR(S->readBytes(9, 1, Buffer));
EXPECT_EQ(Buffer, ArrayRef<uint8_t>('J'));
}
@ -272,15 +289,17 @@ TEST(MappedBlockStreamTest, TestWriteBytesBreakBoundary) {
'T', 'G', '.', '0', '0'};
DiscontiguousFile F(BlocksAry, Data);
MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
auto ExpectedS = MappedBlockStream::createIndexedStream(0, F);
EXPECT_EXPECTED(ExpectedS);
auto &S = *ExpectedS;
ArrayRef<uint8_t> Buffer;
EXPECT_NO_ERROR(S.writeBytes(0, TestData));
EXPECT_NO_ERROR(S->writeBytes(0, TestData));
// First just compare the memory, then compare the result of reading the
// string out.
EXPECT_EQ(ArrayRef<uint8_t>(Data), ArrayRef<uint8_t>(Expected));
EXPECT_NO_ERROR(S.readBytes(0, 8, Buffer));
EXPECT_NO_ERROR(S->readBytes(0, 8, Buffer));
EXPECT_EQ(Buffer, ArrayRef<uint8_t>(TestData));
}
@ -290,7 +309,9 @@ TEST(MappedBlockStreamTest, TestWriteThenRead) {
const uint32_t Blocks[] = {2, 1, 0, 6, 3, 4, 5, 7, 9, 8};
DiscontiguousFile F(Blocks, Data);
MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
auto ExpectedS = MappedBlockStream::createIndexedStream(0, F);
EXPECT_EXPECTED(ExpectedS);
auto &S = *ExpectedS;
enum class MyEnum : uint32_t { Val1 = 2908234, Val2 = 120891234 };
using support::ulittle32_t;
@ -309,8 +330,8 @@ TEST(MappedBlockStreamTest, TestWriteThenRead) {
uint32_t intArr1[] = {890723408, 29082234};
ArrayRef<uint32_t> intArray[] = {intArr0, intArr1};
StreamReader Reader(S);
StreamWriter Writer(S);
StreamReader Reader(*S);
StreamWriter Writer(*S);
EXPECT_NO_ERROR(Writer.writeInteger(u16[0]));
EXPECT_NO_ERROR(Reader.readInteger(u16[1]));
EXPECT_EQ(u16[0], u16[1]);
@ -381,8 +402,9 @@ TEST(MappedBlockStreamTest, TestWriteContiguousStreamRef) {
MutableArrayRef<uint8_t> SrcData(SrcDataBytes);
DiscontiguousFile F(DestBlocks, DestData);
MappedBlockStreamImpl DestStream(llvm::make_unique<IndexedStreamData>(0, F),
F);
auto ExpectedS = MappedBlockStream::createIndexedStream(0, F);
EXPECT_EXPECTED(ExpectedS);
auto &DestStream = *ExpectedS;
// First write "Test Str" into the source stream.
ByteStream<true> SourceStream(SrcData);
@ -392,14 +414,14 @@ TEST(MappedBlockStreamTest, TestWriteContiguousStreamRef) {
{'T', 'e', 's', 't', ' ', 'S', 't', 'r', 0, 0}));
// Then write the source stream into the dest stream.
StreamWriter DestWriter(DestStream);
StreamWriter DestWriter(*DestStream);
EXPECT_NO_ERROR(DestWriter.writeStreamRef(SourceStream));
EXPECT_EQ(DestDataBytes, std::vector<uint8_t>(
{'s', 'e', 'T', ' ', 'S', 't', 't', 'r', 0, 0}));
// Then read the string back out of the dest stream.
StringRef Result;
StreamReader DestReader(DestStream);
StreamReader DestReader(*DestStream);
EXPECT_NO_ERROR(DestReader.readZeroString(Result));
EXPECT_EQ(Result, "Test Str");
}
@ -416,26 +438,28 @@ TEST(MappedBlockStreamTest, TestWriteDiscontiguousStreamRef) {
DiscontiguousFile DestFile(DestBlocks, DestData);
DiscontiguousFile SrcFile(SrcBlocks, SrcData);
MappedBlockStreamImpl DestStream(
llvm::make_unique<IndexedStreamData>(0, DestFile), DestFile);
MappedBlockStreamImpl SrcStream(
llvm::make_unique<IndexedStreamData>(0, SrcFile), SrcFile);
auto ExpectedDest = MappedBlockStream::createIndexedStream(0, DestFile);
auto ExpectedSrc = MappedBlockStream::createIndexedStream(0, SrcFile);
EXPECT_EXPECTED(ExpectedDest);
EXPECT_EXPECTED(ExpectedSrc);
auto &DestStream = *ExpectedDest;
auto &SrcStream = *ExpectedSrc;
// First write "Test Str" into the source stream.
StreamWriter SourceWriter(SrcStream);
StreamWriter SourceWriter(*SrcStream);
EXPECT_NO_ERROR(SourceWriter.writeZeroString("Test Str"));
EXPECT_EQ(SrcDataBytes, std::vector<uint8_t>(
{'e', 'T', 't', 't', ' ', 'S', 's', 'r', 0, 0}));
// Then write the source stream into the dest stream.
StreamWriter DestWriter(DestStream);
EXPECT_NO_ERROR(DestWriter.writeStreamRef(SrcStream));
StreamWriter DestWriter(*DestStream);
EXPECT_NO_ERROR(DestWriter.writeStreamRef(*SrcStream));
EXPECT_EQ(DestDataBytes, std::vector<uint8_t>(
{'s', 'e', 'T', ' ', 'S', 't', 't', 'r', 0, 0}));
// Then read the string back out of the dest stream.
StringRef Result;
StreamReader DestReader(DestStream);
StreamReader DestReader(*DestStream);
EXPECT_NO_ERROR(DestReader.readZeroString(Result));
EXPECT_EQ(Result, "Test Str");
}