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