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>(Args: stream_error_code::invalid_offset); |
61 | if (getLength() < DataSize + Offset) |
62 | return make_error<BinaryStreamError>(Args: 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>(Args: stream_error_code::invalid_offset); |
94 | return Error::success(); |
95 | } |
96 | }; |
97 | |
98 | } // end namespace llvm |
99 | |
100 | #endif // LLVM_SUPPORT_BINARYSTREAM_H |
101 | |