aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/DebugInfo/MSF/ByteStream.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/DebugInfo/MSF/ByteStream.h')
-rw-r--r--include/llvm/DebugInfo/MSF/ByteStream.h169
1 files changed, 169 insertions, 0 deletions
diff --git a/include/llvm/DebugInfo/MSF/ByteStream.h b/include/llvm/DebugInfo/MSF/ByteStream.h
new file mode 100644
index 0000000000000..547844be5e5d4
--- /dev/null
+++ b/include/llvm/DebugInfo/MSF/ByteStream.h
@@ -0,0 +1,169 @@
+//===- ByteStream.h - Reads stream data from a byte sequence ----*- 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_BYTESTREAM_H
+#define LLVM_DEBUGINFO_MSF_BYTESTREAM_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/MSF/MSFError.h"
+#include "llvm/DebugInfo/MSF/StreamInterface.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FileOutputBuffer.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <algorithm>
+#include <cstdint>
+#include <cstring>
+#include <memory>
+
+namespace llvm {
+namespace msf {
+
+class ByteStream : public ReadableStream {
+public:
+ ByteStream() = default;
+ explicit ByteStream(ArrayRef<uint8_t> Data) : Data(Data) {}
+ explicit ByteStream(StringRef Data)
+ : Data(Data.bytes_begin(), Data.bytes_end()) {}
+
+ Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) const override {
+ if (Offset > Data.size())
+ return make_error<MSFError>(msf_error_code::insufficient_buffer);
+ if (Data.size() < Size + Offset)
+ return make_error<MSFError>(msf_error_code::insufficient_buffer);
+ Buffer = Data.slice(Offset, Size);
+ return Error::success();
+ }
+
+ Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) const override {
+ if (Offset >= Data.size())
+ return make_error<MSFError>(msf_error_code::insufficient_buffer);
+ Buffer = Data.slice(Offset);
+ return Error::success();
+ }
+
+ uint32_t getLength() const override { return Data.size(); }
+
+ ArrayRef<uint8_t> data() const { return Data; }
+
+ StringRef str() const {
+ const char *CharData = reinterpret_cast<const char *>(Data.data());
+ return StringRef(CharData, Data.size());
+ }
+
+protected:
+ ArrayRef<uint8_t> Data;
+};
+
+// MemoryBufferByteStream behaves like a read-only ByteStream, but has its data
+// backed by an llvm::MemoryBuffer. It also owns the underlying MemoryBuffer.
+class MemoryBufferByteStream : public ByteStream {
+public:
+ explicit MemoryBufferByteStream(std::unique_ptr<MemoryBuffer> Buffer)
+ : ByteStream(ArrayRef<uint8_t>(Buffer->getBuffer().bytes_begin(),
+ Buffer->getBuffer().bytes_end())),
+ MemBuffer(std::move(Buffer)) {}
+
+ std::unique_ptr<MemoryBuffer> MemBuffer;
+};
+
+class MutableByteStream : public WritableStream {
+public:
+ MutableByteStream() = default;
+ explicit MutableByteStream(MutableArrayRef<uint8_t> Data)
+ : Data(Data), ImmutableStream(Data) {}
+
+ Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) const override {
+ return ImmutableStream.readBytes(Offset, Size, Buffer);
+ }
+
+ Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) const override {
+ return ImmutableStream.readLongestContiguousChunk(Offset, Buffer);
+ }
+
+ uint32_t getLength() const override { return ImmutableStream.getLength(); }
+
+ Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) const override {
+ if (Buffer.empty())
+ return Error::success();
+
+ if (Data.size() < Buffer.size())
+ return make_error<MSFError>(msf_error_code::insufficient_buffer);
+ if (Offset > Buffer.size() - Data.size())
+ return make_error<MSFError>(msf_error_code::insufficient_buffer);
+
+ uint8_t *DataPtr = const_cast<uint8_t *>(Data.data());
+ ::memcpy(DataPtr + Offset, Buffer.data(), Buffer.size());
+ return Error::success();
+ }
+
+ Error commit() const override { return Error::success(); }
+
+ MutableArrayRef<uint8_t> data() const { return Data; }
+
+private:
+ MutableArrayRef<uint8_t> Data;
+ ByteStream ImmutableStream;
+};
+
+// A simple adapter that acts like a ByteStream but holds ownership over
+// and underlying FileOutputBuffer.
+class FileBufferByteStream : public WritableStream {
+private:
+ class StreamImpl : public MutableByteStream {
+ public:
+ StreamImpl(std::unique_ptr<FileOutputBuffer> Buffer)
+ : MutableByteStream(MutableArrayRef<uint8_t>(Buffer->getBufferStart(),
+ Buffer->getBufferEnd())),
+ FileBuffer(std::move(Buffer)) {}
+
+ Error commit() const override {
+ if (FileBuffer->commit())
+ return llvm::make_error<MSFError>(msf_error_code::not_writable);
+ return Error::success();
+ }
+
+ private:
+ std::unique_ptr<FileOutputBuffer> FileBuffer;
+ };
+
+public:
+ explicit FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer)
+ : Impl(std::move(Buffer)) {}
+
+ Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) const override {
+ return Impl.readBytes(Offset, Size, Buffer);
+ }
+
+ Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) const override {
+ return Impl.readLongestContiguousChunk(Offset, Buffer);
+ }
+
+ uint32_t getLength() const override { return Impl.getLength(); }
+
+ Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const override {
+ return Impl.writeBytes(Offset, Data);
+ }
+
+ Error commit() const override { return Impl.commit(); }
+
+private:
+ StreamImpl Impl;
+};
+
+} // end namespace msf
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_MSF_BYTESTREAM_H