2017-02-25 01:44:30 +01:00
|
|
|
//===- BinaryItemStream.h ---------------------------------------*- C++ -*-===//
|
2016-09-09 19:46:17 +02:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-02-25 01:44:30 +01:00
|
|
|
#ifndef LLVM_SUPPORT_BINARYITEMSTREAM_H
|
|
|
|
#define LLVM_SUPPORT_BINARYITEMSTREAM_H
|
2016-09-09 19:46:17 +02:00
|
|
|
|
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
2017-02-25 01:33:34 +01:00
|
|
|
#include "llvm/DebugInfo/MSF/BinaryStream.h"
|
2016-09-09 19:46:17 +02:00
|
|
|
#include "llvm/Support/Error.h"
|
2016-11-18 19:00:19 +01:00
|
|
|
#include <cstddef>
|
2016-09-09 19:46:17 +02:00
|
|
|
#include <cstdint>
|
|
|
|
|
|
|
|
namespace llvm {
|
2016-11-18 19:00:19 +01:00
|
|
|
|
2017-02-25 01:44:30 +01:00
|
|
|
template <typename T> struct BinaryItemTraits {
|
|
|
|
size_t length(const T &Item) = delete;
|
|
|
|
ArrayRef<uint8_t> bytes(const T &Item) = delete;
|
2016-09-09 19:46:17 +02:00
|
|
|
};
|
|
|
|
|
2017-02-25 01:44:30 +01:00
|
|
|
/// BinaryItemStream represents a sequence of objects stored in some kind of
|
|
|
|
/// external container but for which it is useful to view as a stream of
|
|
|
|
/// contiguous bytes. An example of this might be if you have a collection of
|
|
|
|
/// records and you serialize each one into a buffer, and store these serialized
|
|
|
|
/// records in a container. The pointers themselves are not laid out
|
|
|
|
/// contiguously in memory, but we may wish to read from or write to these
|
|
|
|
/// records as if they were.
|
|
|
|
template <typename T, typename ItemTraits = BinaryItemTraits<T>>
|
|
|
|
class BinaryItemStream : public BinaryStream {
|
2016-09-09 19:46:17 +02:00
|
|
|
public:
|
2017-02-25 01:44:30 +01:00
|
|
|
explicit BinaryItemStream(llvm::support::endianness Endian)
|
|
|
|
: Endian(Endian) {}
|
|
|
|
|
|
|
|
llvm::support::endianness getEndian() const override { return Endian; }
|
2016-09-09 19:46:17 +02:00
|
|
|
|
|
|
|
Error readBytes(uint32_t Offset, uint32_t Size,
|
2017-02-25 01:44:30 +01:00
|
|
|
ArrayRef<uint8_t> &Buffer) override {
|
|
|
|
if (auto EC = readLongestContiguousChunk(Offset, Buffer))
|
|
|
|
return EC;
|
|
|
|
|
|
|
|
if (Size > Buffer.size())
|
|
|
|
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
|
|
|
|
|
|
|
Buffer = Buffer.take_front(Size);
|
2016-09-09 19:46:17 +02:00
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
|
|
|
Error readLongestContiguousChunk(uint32_t Offset,
|
2017-02-25 01:44:30 +01:00
|
|
|
ArrayRef<uint8_t> &Buffer) override {
|
|
|
|
uint32_t Index;
|
|
|
|
uint32_t ByteOffset;
|
|
|
|
if (auto EC = translateOffsetIndex(Offset, Index, ByteOffset))
|
|
|
|
return EC;
|
|
|
|
const auto &Item = Items[Index];
|
|
|
|
Buffer = Traits.bytes(Item).drop_front(ByteOffset);
|
2016-09-09 19:46:17 +02:00
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
|
|
|
void setItems(ArrayRef<T> ItemArray) { Items = ItemArray; }
|
|
|
|
|
2017-02-25 01:44:30 +01:00
|
|
|
uint32_t getLength() override {
|
2016-09-09 19:46:17 +02:00
|
|
|
uint32_t Size = 0;
|
|
|
|
for (const auto &Item : Items)
|
2017-02-25 01:44:30 +01:00
|
|
|
Size += Traits.length(Item);
|
2016-09-09 19:46:17 +02:00
|
|
|
return Size;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2017-02-25 01:44:30 +01:00
|
|
|
Error translateOffsetIndex(uint32_t Offset, uint32_t &ItemIndex,
|
|
|
|
uint32_t &ByteOffset) {
|
|
|
|
ItemIndex = 0;
|
|
|
|
ByteOffset = 0;
|
|
|
|
uint32_t PrevOffset = 0;
|
2016-09-09 19:46:17 +02:00
|
|
|
uint32_t CurrentOffset = 0;
|
2017-02-25 01:44:30 +01:00
|
|
|
if (Offset > 0) {
|
|
|
|
for (const auto &Item : Items) {
|
|
|
|
PrevOffset = CurrentOffset;
|
|
|
|
CurrentOffset += Traits.length(Item);
|
|
|
|
if (CurrentOffset > Offset)
|
|
|
|
break;
|
|
|
|
++ItemIndex;
|
|
|
|
}
|
2016-09-09 19:46:17 +02:00
|
|
|
}
|
2017-02-25 01:44:30 +01:00
|
|
|
if (CurrentOffset < Offset)
|
|
|
|
return errorCodeToError(make_error_code(std::errc::no_buffer_space));
|
|
|
|
ByteOffset = Offset - PrevOffset;
|
|
|
|
return Error::success();
|
2016-09-09 19:46:17 +02:00
|
|
|
}
|
2016-11-18 19:00:19 +01:00
|
|
|
|
2017-02-25 01:44:30 +01:00
|
|
|
llvm::support::endianness Endian;
|
|
|
|
ItemTraits Traits;
|
2016-09-09 19:46:17 +02:00
|
|
|
ArrayRef<T> Items;
|
|
|
|
};
|
2016-11-18 19:00:19 +01:00
|
|
|
|
2016-09-09 19:46:17 +02:00
|
|
|
} // end namespace llvm
|
|
|
|
|
2017-02-25 01:44:30 +01:00
|
|
|
#endif // LLVM_SUPPORT_BINARYITEMSTREAM_H
|