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