diff options
Diffstat (limited to 'include/llvm/DebugInfo/MSF/ByteStream.h')
| -rw-r--r-- | include/llvm/DebugInfo/MSF/ByteStream.h | 169 |
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 |
