summaryrefslogtreecommitdiff
path: root/include/llvm/Support/BinaryItemStream.h
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-04-16 16:01:22 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-04-16 16:01:22 +0000
commit71d5a2540a98c81f5bcaeb48805e0e2881f530ef (patch)
tree5343938942df402b49ec7300a1c25a2d4ccd5821 /include/llvm/Support/BinaryItemStream.h
parent31bbf64f3a4974a2d6c8b3b27ad2f519caf74057 (diff)
Notes
Diffstat (limited to 'include/llvm/Support/BinaryItemStream.h')
-rw-r--r--include/llvm/Support/BinaryItemStream.h95
1 files changed, 95 insertions, 0 deletions
diff --git a/include/llvm/Support/BinaryItemStream.h b/include/llvm/Support/BinaryItemStream.h
new file mode 100644
index 0000000000000..f4b319217819e
--- /dev/null
+++ b/include/llvm/Support/BinaryItemStream.h
@@ -0,0 +1,95 @@
+//===- BinaryItemStream.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_SUPPORT_BINARYITEMSTREAM_H
+#define LLVM_SUPPORT_BINARYITEMSTREAM_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/BinaryStream.h"
+#include "llvm/Support/BinaryStreamError.h"
+#include "llvm/Support/Error.h"
+#include <cstddef>
+#include <cstdint>
+
+namespace llvm {
+
+template <typename T> struct BinaryItemTraits {
+ static size_t length(const T &Item) = delete;
+ static ArrayRef<uint8_t> bytes(const T &Item) = delete;
+};
+
+/// 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 {
+public:
+ explicit BinaryItemStream(llvm::support::endianness Endian)
+ : Endian(Endian) {}
+
+ llvm::support::endianness getEndian() const override { return Endian; }
+
+ Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) override {
+ auto ExpectedIndex = translateOffsetIndex(Offset);
+ if (!ExpectedIndex)
+ return ExpectedIndex.takeError();
+ const auto &Item = Items[*ExpectedIndex];
+ if (auto EC = checkOffset(Offset, Size))
+ return EC;
+ if (Size > Traits::length(Item))
+ return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
+ Buffer = Traits::bytes(Item).take_front(Size);
+ return Error::success();
+ }
+
+ Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) override {
+ auto ExpectedIndex = translateOffsetIndex(Offset);
+ if (!ExpectedIndex)
+ return ExpectedIndex.takeError();
+ Buffer = Traits::bytes(Items[*ExpectedIndex]);
+ return Error::success();
+ }
+
+ void setItems(ArrayRef<T> ItemArray) { Items = ItemArray; }
+
+ uint32_t getLength() override {
+ uint32_t Size = 0;
+ for (const auto &Item : Items)
+ Size += Traits::length(Item);
+ return Size;
+ }
+
+private:
+ Expected<uint32_t> translateOffsetIndex(uint32_t Offset) const {
+ uint32_t CurrentOffset = 0;
+ uint32_t CurrentIndex = 0;
+ for (const auto &Item : Items) {
+ if (CurrentOffset >= Offset)
+ break;
+ CurrentOffset += Traits::length(Item);
+ ++CurrentIndex;
+ }
+ if (CurrentOffset != Offset)
+ return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
+ return CurrentIndex;
+ }
+
+ llvm::support::endianness Endian;
+ ArrayRef<T> Items;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_BINARYITEMSTREAM_H