2017-02-27 23:11:43 +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-03-02 21:52:51 +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-03-02 21:52:51 +01:00
|
|
|
#include "llvm/Support/BinaryStream.h"
|
|
|
|
#include "llvm/Support/BinaryStreamError.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-27 23:11:43 +01:00
|
|
|
template <typename T> struct BinaryItemTraits {
|
2017-02-25 18:04:23 +01:00
|
|
|
static size_t length(const T &Item) = delete;
|
|
|
|
static ArrayRef<uint8_t> bytes(const T &Item) = delete;
|
2016-09-09 19:46:17 +02:00
|
|
|
};
|
|
|
|
|
2017-02-27 23:11:43 +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 Traits = BinaryItemTraits<T>>
|
|
|
|
class BinaryItemStream : public BinaryStream {
|
2016-09-09 19:46:17 +02:00
|
|
|
public:
|
2017-02-28 01:04:07 +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-27 23:11:43 +01:00
|
|
|
ArrayRef<uint8_t> &Buffer) override {
|
2017-02-25 18:04:23 +01:00
|
|
|
auto ExpectedIndex = translateOffsetIndex(Offset);
|
|
|
|
if (!ExpectedIndex)
|
|
|
|
return ExpectedIndex.takeError();
|
|
|
|
const auto &Item = Items[*ExpectedIndex];
|
2017-02-28 18:49:34 +01:00
|
|
|
if (auto EC = checkOffset(Offset, Size))
|
|
|
|
return EC;
|
2017-02-25 18:04:23 +01:00
|
|
|
if (Size > Traits::length(Item))
|
2017-02-28 18:49:34 +01:00
|
|
|
return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
|
2017-02-25 18:04:23 +01:00
|
|
|
Buffer = Traits::bytes(Item).take_front(Size);
|
2016-09-09 19:46:17 +02:00
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
|
|
|
Error readLongestContiguousChunk(uint32_t Offset,
|
2017-02-27 23:11:43 +01:00
|
|
|
ArrayRef<uint8_t> &Buffer) override {
|
2017-02-25 18:04:23 +01:00
|
|
|
auto ExpectedIndex = translateOffsetIndex(Offset);
|
|
|
|
if (!ExpectedIndex)
|
|
|
|
return ExpectedIndex.takeError();
|
|
|
|
Buffer = Traits::bytes(Items[*ExpectedIndex]);
|
2016-09-09 19:46:17 +02:00
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
|
|
|
void setItems(ArrayRef<T> ItemArray) { Items = ItemArray; }
|
|
|
|
|
2017-02-27 23:11:43 +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 18:04:23 +01:00
|
|
|
Size += Traits::length(Item);
|
2016-09-09 19:46:17 +02:00
|
|
|
return Size;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2017-02-25 18:04:23 +01:00
|
|
|
Expected<uint32_t> translateOffsetIndex(uint32_t Offset) const {
|
2016-09-09 19:46:17 +02:00
|
|
|
uint32_t CurrentOffset = 0;
|
2017-02-25 18:04:23 +01:00
|
|
|
uint32_t CurrentIndex = 0;
|
|
|
|
for (const auto &Item : Items) {
|
|
|
|
if (CurrentOffset >= Offset)
|
|
|
|
break;
|
|
|
|
CurrentOffset += Traits::length(Item);
|
|
|
|
++CurrentIndex;
|
2016-09-09 19:46:17 +02:00
|
|
|
}
|
2017-02-25 18:04:23 +01:00
|
|
|
if (CurrentOffset != Offset)
|
2017-02-28 18:49:34 +01:00
|
|
|
return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
|
2017-02-25 18:04:23 +01:00
|
|
|
return CurrentIndex;
|
2016-09-09 19:46:17 +02:00
|
|
|
}
|
2016-11-18 19:00:19 +01:00
|
|
|
|
2017-02-28 01:04:07 +01:00
|
|
|
llvm::support::endianness Endian;
|
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-03-02 21:52:51 +01:00
|
|
|
#endif // LLVM_SUPPORT_BINARYITEMSTREAM_H
|