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