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