1 | //===- BinaryStreamRef.cpp - ----------------------------------------------===// |
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 | #include "llvm/Support/BinaryStreamRef.h" |
10 | #include "llvm/Support/BinaryByteStream.h" |
11 | |
12 | using namespace llvm; |
13 | |
14 | namespace { |
15 | |
16 | class ArrayRefImpl : public BinaryStream { |
17 | public: |
18 | ArrayRefImpl(ArrayRef<uint8_t> Data, endianness Endian) : BBS(Data, Endian) {} |
19 | |
20 | llvm::endianness getEndian() const override { return BBS.getEndian(); } |
21 | Error readBytes(uint64_t Offset, uint64_t Size, |
22 | ArrayRef<uint8_t> &Buffer) override { |
23 | return BBS.readBytes(Offset, Size, Buffer); |
24 | } |
25 | Error readLongestContiguousChunk(uint64_t Offset, |
26 | ArrayRef<uint8_t> &Buffer) override { |
27 | return BBS.readLongestContiguousChunk(Offset, Buffer); |
28 | } |
29 | uint64_t getLength() override { return BBS.getLength(); } |
30 | |
31 | private: |
32 | BinaryByteStream BBS; |
33 | }; |
34 | |
35 | class MutableArrayRefImpl : public WritableBinaryStream { |
36 | public: |
37 | MutableArrayRefImpl(MutableArrayRef<uint8_t> Data, endianness Endian) |
38 | : BBS(Data, Endian) {} |
39 | |
40 | // Inherited via WritableBinaryStream |
41 | llvm::endianness getEndian() const override { return BBS.getEndian(); } |
42 | Error readBytes(uint64_t Offset, uint64_t Size, |
43 | ArrayRef<uint8_t> &Buffer) override { |
44 | return BBS.readBytes(Offset, Size, Buffer); |
45 | } |
46 | Error readLongestContiguousChunk(uint64_t Offset, |
47 | ArrayRef<uint8_t> &Buffer) override { |
48 | return BBS.readLongestContiguousChunk(Offset, Buffer); |
49 | } |
50 | uint64_t getLength() override { return BBS.getLength(); } |
51 | |
52 | Error writeBytes(uint64_t Offset, ArrayRef<uint8_t> Data) override { |
53 | return BBS.writeBytes(Offset, Buffer: Data); |
54 | } |
55 | Error commit() override { return BBS.commit(); } |
56 | |
57 | private: |
58 | MutableBinaryByteStream BBS; |
59 | }; |
60 | } // namespace |
61 | |
62 | BinaryStreamRef::BinaryStreamRef(BinaryStream &Stream) |
63 | : BinaryStreamRefBase(Stream) {} |
64 | BinaryStreamRef::BinaryStreamRef(BinaryStream &Stream, uint64_t Offset, |
65 | std::optional<uint64_t> Length) |
66 | : BinaryStreamRefBase(Stream, Offset, Length) {} |
67 | BinaryStreamRef::BinaryStreamRef(ArrayRef<uint8_t> Data, endianness Endian) |
68 | : BinaryStreamRefBase(std::make_shared<ArrayRefImpl>(args&: Data, args&: Endian), 0, |
69 | Data.size()) {} |
70 | BinaryStreamRef::BinaryStreamRef(StringRef Data, endianness Endian) |
71 | : BinaryStreamRef(ArrayRef(Data.bytes_begin(), Data.bytes_end()), Endian) {} |
72 | |
73 | Error BinaryStreamRef::readBytes(uint64_t Offset, uint64_t Size, |
74 | ArrayRef<uint8_t> &Buffer) const { |
75 | if (auto EC = checkOffsetForRead(Offset, DataSize: Size)) |
76 | return EC; |
77 | return BorrowedImpl->readBytes(Offset: ViewOffset + Offset, Size, Buffer); |
78 | } |
79 | |
80 | Error BinaryStreamRef::readLongestContiguousChunk( |
81 | uint64_t Offset, ArrayRef<uint8_t> &Buffer) const { |
82 | if (auto EC = checkOffsetForRead(Offset, DataSize: 1)) |
83 | return EC; |
84 | |
85 | if (auto EC = |
86 | BorrowedImpl->readLongestContiguousChunk(Offset: ViewOffset + Offset, Buffer)) |
87 | return EC; |
88 | // This StreamRef might refer to a smaller window over a larger stream. In |
89 | // that case we will have read out more bytes than we should return, because |
90 | // we should not read past the end of the current view. |
91 | uint64_t MaxLength = getLength() - Offset; |
92 | if (Buffer.size() > MaxLength) |
93 | Buffer = Buffer.slice(N: 0, M: MaxLength); |
94 | return Error::success(); |
95 | } |
96 | |
97 | WritableBinaryStreamRef::WritableBinaryStreamRef(WritableBinaryStream &Stream) |
98 | : BinaryStreamRefBase(Stream) {} |
99 | |
100 | WritableBinaryStreamRef::WritableBinaryStreamRef(WritableBinaryStream &Stream, |
101 | uint64_t Offset, |
102 | std::optional<uint64_t> Length) |
103 | : BinaryStreamRefBase(Stream, Offset, Length) {} |
104 | |
105 | WritableBinaryStreamRef::WritableBinaryStreamRef(MutableArrayRef<uint8_t> Data, |
106 | endianness Endian) |
107 | : BinaryStreamRefBase(std::make_shared<MutableArrayRefImpl>(args&: Data, args&: Endian), |
108 | 0, Data.size()) {} |
109 | |
110 | Error WritableBinaryStreamRef::writeBytes(uint64_t Offset, |
111 | ArrayRef<uint8_t> Data) const { |
112 | if (auto EC = checkOffsetForWrite(Offset, DataSize: Data.size())) |
113 | return EC; |
114 | |
115 | return BorrowedImpl->writeBytes(Offset: ViewOffset + Offset, Data); |
116 | } |
117 | |
118 | WritableBinaryStreamRef::operator BinaryStreamRef() const { |
119 | return BinaryStreamRef(*BorrowedImpl, ViewOffset, Length); |
120 | } |
121 | |
122 | /// For buffered streams, commits changes to the backing store. |
123 | Error WritableBinaryStreamRef::commit() { return BorrowedImpl->commit(); } |
124 | |