1 //===- BinaryStream.h - Base interface for a stream of data -----*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef LLVM_SUPPORT_BINARYSTREAM_H 11 #define LLVM_SUPPORT_BINARYSTREAM_H 12 13 #include "llvm/ADT/ArrayRef.h" 14 #include "llvm/ADT/BitmaskEnum.h" 15 #include "llvm/Support/BinaryStreamError.h" 16 #include "llvm/Support/Endian.h" 17 #include "llvm/Support/Error.h" 18 #include <cstdint> 19 20 namespace llvm { 21 22 enum BinaryStreamFlags { 23 BSF_None = 0, 24 BSF_Write = 1, // Stream supports writing. 25 BSF_Append = 2, // Writing can occur at offset == length. 26 LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ BSF_Append) 27 }; 28 29 /// An interface for accessing data in a stream-like format, but which 30 /// discourages copying. Instead of specifying a buffer in which to copy 31 /// data on a read, the API returns an ArrayRef to data owned by the stream's 32 /// implementation. Since implementations may not necessarily store data in a 33 /// single contiguous buffer (or even in memory at all), in such cases a it may 34 /// be necessary for an implementation to cache such a buffer so that it can 35 /// return it. 36 class BinaryStream { 37 public: 38 virtual ~BinaryStream() = default; 39 40 virtual llvm::support::endianness getEndian() const = 0; 41 42 /// Given an offset into the stream and a number of bytes, attempt to 43 /// read the bytes and set the output ArrayRef to point to data owned by the 44 /// stream. 45 virtual Error readBytes(uint32_t Offset, uint32_t Size, 46 ArrayRef<uint8_t> &Buffer) = 0; 47 48 /// Given an offset into the stream, read as much as possible without 49 /// copying any data. 50 virtual Error readLongestContiguousChunk(uint32_t Offset, 51 ArrayRef<uint8_t> &Buffer) = 0; 52 53 /// Return the number of bytes of data in this stream. 54 virtual uint32_t getLength() = 0; 55 56 /// Return the properties of this stream. getFlags()57 virtual BinaryStreamFlags getFlags() const { return BSF_None; } 58 59 protected: checkOffsetForRead(uint32_t Offset,uint32_t DataSize)60 Error checkOffsetForRead(uint32_t Offset, uint32_t DataSize) { 61 if (Offset > getLength()) 62 return make_error<BinaryStreamError>(stream_error_code::invalid_offset); 63 if (getLength() < DataSize + Offset) 64 return make_error<BinaryStreamError>(stream_error_code::stream_too_short); 65 return Error::success(); 66 } 67 }; 68 69 /// A BinaryStream which can be read from as well as written to. Note 70 /// that writing to a BinaryStream always necessitates copying from the input 71 /// buffer to the stream's backing store. Streams are assumed to be buffered 72 /// so that to be portable it is necessary to call commit() on the stream when 73 /// all data has been written. 74 class WritableBinaryStream : public BinaryStream { 75 public: 76 ~WritableBinaryStream() override = default; 77 78 /// Attempt to write the given bytes into the stream at the desired 79 /// offset. This will always necessitate a copy. Cannot shrink or grow the 80 /// stream, only writes into existing allocated space. 81 virtual Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) = 0; 82 83 /// For buffered streams, commits changes to the backing store. 84 virtual Error commit() = 0; 85 86 /// Return the properties of this stream. getFlags()87 BinaryStreamFlags getFlags() const override { return BSF_Write; } 88 89 protected: checkOffsetForWrite(uint32_t Offset,uint32_t DataSize)90 Error checkOffsetForWrite(uint32_t Offset, uint32_t DataSize) { 91 if (!(getFlags() & BSF_Append)) 92 return checkOffsetForRead(Offset, DataSize); 93 94 if (Offset > getLength()) 95 return make_error<BinaryStreamError>(stream_error_code::invalid_offset); 96 return Error::success(); 97 } 98 }; 99 100 } // end namespace llvm 101 102 #endif // LLVM_SUPPORT_BINARYSTREAM_H 103