//===- BinaryStream.h - Base interface for a stream of data -----*- 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_BINARYSTREAM_H #define LLVM_SUPPORT_BINARYSTREAM_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitmaskEnum.h" #include "llvm/Support/BinaryStreamError.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include <cstdint> namespace llvm { enum BinaryStreamFlags { BSF_None = 0, BSF_Write = 1, // Stream supports writing. BSF_Append = 2, // Writing can occur at offset == length. LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ BSF_Append) }; /// An interface for accessing data in a stream-like format, but which /// discourages copying. Instead of specifying a buffer in which to copy /// data on a read, the API returns an ArrayRef to data owned by the stream's /// implementation. Since implementations may not necessarily store data in a /// single contiguous buffer (or even in memory at all), in such cases a it may /// be necessary for an implementation to cache such a buffer so that it can /// return it. class BinaryStream { public: virtual ~BinaryStream() = default; virtual llvm::support::endianness getEndian() const = 0; /// Given an offset into the stream and a number of bytes, attempt to /// read the bytes and set the output ArrayRef to point to data owned by the /// stream. virtual Error readBytes(uint32_t Offset, uint32_t Size, ArrayRef<uint8_t> &Buffer) = 0; /// Given an offset into the stream, read as much as possible without /// copying any data. virtual Error readLongestContiguousChunk(uint32_t Offset, ArrayRef<uint8_t> &Buffer) = 0; /// Return the number of bytes of data in this stream. virtual uint32_t getLength() = 0; /// Return the properties of this stream. virtual BinaryStreamFlags getFlags() const { return BSF_None; } protected: Error checkOffsetForRead(uint32_t Offset, uint32_t DataSize) { if (Offset > getLength()) return make_error<BinaryStreamError>(stream_error_code::invalid_offset); if (getLength() < DataSize + Offset) return make_error<BinaryStreamError>(stream_error_code::stream_too_short); return Error::success(); } }; /// A BinaryStream which can be read from as well as written to. Note /// that writing to a BinaryStream always necessitates copying from the input /// buffer to the stream's backing store. Streams are assumed to be buffered /// so that to be portable it is necessary to call commit() on the stream when /// all data has been written. class WritableBinaryStream : public BinaryStream { public: ~WritableBinaryStream() override = default; /// Attempt to write the given bytes into the stream at the desired /// offset. This will always necessitate a copy. Cannot shrink or grow the /// stream, only writes into existing allocated space. virtual Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) = 0; /// For buffered streams, commits changes to the backing store. virtual Error commit() = 0; /// Return the properties of this stream. BinaryStreamFlags getFlags() const override { return BSF_Write; } protected: Error checkOffsetForWrite(uint32_t Offset, uint32_t DataSize) { if (!(getFlags() & BSF_Append)) return checkOffsetForRead(Offset, DataSize); if (Offset > getLength()) return make_error<BinaryStreamError>(stream_error_code::invalid_offset); return Error::success(); } }; } // end namespace llvm #endif // LLVM_SUPPORT_BINARYSTREAM_H