1*0b57cec5SDimitry Andric //===- BinaryStreamRef.cpp - ----------------------------------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "llvm/Support/BinaryStreamRef.h" 10*0b57cec5SDimitry Andric #include "llvm/Support/BinaryByteStream.h" 11*0b57cec5SDimitry Andric 12*0b57cec5SDimitry Andric using namespace llvm; 13*0b57cec5SDimitry Andric using namespace llvm::support; 14*0b57cec5SDimitry Andric 15*0b57cec5SDimitry Andric namespace { 16*0b57cec5SDimitry Andric 17*0b57cec5SDimitry Andric class ArrayRefImpl : public BinaryStream { 18*0b57cec5SDimitry Andric public: 19*0b57cec5SDimitry Andric ArrayRefImpl(ArrayRef<uint8_t> Data, endianness Endian) : BBS(Data, Endian) {} 20*0b57cec5SDimitry Andric 21*0b57cec5SDimitry Andric llvm::support::endianness getEndian() const override { 22*0b57cec5SDimitry Andric return BBS.getEndian(); 23*0b57cec5SDimitry Andric } 24349cc55cSDimitry Andric Error readBytes(uint64_t Offset, uint64_t Size, 25*0b57cec5SDimitry Andric ArrayRef<uint8_t> &Buffer) override { 26*0b57cec5SDimitry Andric return BBS.readBytes(Offset, Size, Buffer); 27*0b57cec5SDimitry Andric } 28349cc55cSDimitry Andric Error readLongestContiguousChunk(uint64_t Offset, 29*0b57cec5SDimitry Andric ArrayRef<uint8_t> &Buffer) override { 30*0b57cec5SDimitry Andric return BBS.readLongestContiguousChunk(Offset, Buffer); 31*0b57cec5SDimitry Andric } 32349cc55cSDimitry Andric uint64_t getLength() override { return BBS.getLength(); } 33*0b57cec5SDimitry Andric 34*0b57cec5SDimitry Andric private: 35*0b57cec5SDimitry Andric BinaryByteStream BBS; 36*0b57cec5SDimitry Andric }; 37*0b57cec5SDimitry Andric 38*0b57cec5SDimitry Andric class MutableArrayRefImpl : public WritableBinaryStream { 39*0b57cec5SDimitry Andric public: 40*0b57cec5SDimitry Andric MutableArrayRefImpl(MutableArrayRef<uint8_t> Data, endianness Endian) 41*0b57cec5SDimitry Andric : BBS(Data, Endian) {} 42*0b57cec5SDimitry Andric 43*0b57cec5SDimitry Andric // Inherited via WritableBinaryStream 44*0b57cec5SDimitry Andric llvm::support::endianness getEndian() const override { 45*0b57cec5SDimitry Andric return BBS.getEndian(); 46*0b57cec5SDimitry Andric } 47349cc55cSDimitry Andric Error readBytes(uint64_t Offset, uint64_t Size, 48*0b57cec5SDimitry Andric ArrayRef<uint8_t> &Buffer) override { 49*0b57cec5SDimitry Andric return BBS.readBytes(Offset, Size, Buffer); 50*0b57cec5SDimitry Andric } 51349cc55cSDimitry Andric Error readLongestContiguousChunk(uint64_t Offset, 52*0b57cec5SDimitry Andric ArrayRef<uint8_t> &Buffer) override { 53*0b57cec5SDimitry Andric return BBS.readLongestContiguousChunk(Offset, Buffer); 54*0b57cec5SDimitry Andric } 55349cc55cSDimitry Andric uint64_t getLength() override { return BBS.getLength(); } 56*0b57cec5SDimitry Andric 57349cc55cSDimitry Andric Error writeBytes(uint64_t Offset, ArrayRef<uint8_t> Data) override { 58*0b57cec5SDimitry Andric return BBS.writeBytes(Offset, Data); 59*0b57cec5SDimitry Andric } 60*0b57cec5SDimitry Andric Error commit() override { return BBS.commit(); } 61*0b57cec5SDimitry Andric 62*0b57cec5SDimitry Andric private: 63*0b57cec5SDimitry Andric MutableBinaryByteStream BBS; 64*0b57cec5SDimitry Andric }; 65fe6060f1SDimitry Andric } // namespace 66*0b57cec5SDimitry Andric 67*0b57cec5SDimitry Andric BinaryStreamRef::BinaryStreamRef(BinaryStream &Stream) 68*0b57cec5SDimitry Andric : BinaryStreamRefBase(Stream) {} 69349cc55cSDimitry Andric BinaryStreamRef::BinaryStreamRef(BinaryStream &Stream, uint64_t Offset, 70349cc55cSDimitry Andric Optional<uint64_t> Length) 71*0b57cec5SDimitry Andric : BinaryStreamRefBase(Stream, Offset, Length) {} 72*0b57cec5SDimitry Andric BinaryStreamRef::BinaryStreamRef(ArrayRef<uint8_t> Data, endianness Endian) 73*0b57cec5SDimitry Andric : BinaryStreamRefBase(std::make_shared<ArrayRefImpl>(Data, Endian), 0, 74*0b57cec5SDimitry Andric Data.size()) {} 75*0b57cec5SDimitry Andric BinaryStreamRef::BinaryStreamRef(StringRef Data, endianness Endian) 76*0b57cec5SDimitry Andric : BinaryStreamRef(makeArrayRef(Data.bytes_begin(), Data.bytes_end()), 77*0b57cec5SDimitry Andric Endian) {} 78*0b57cec5SDimitry Andric 79349cc55cSDimitry Andric Error BinaryStreamRef::readBytes(uint64_t Offset, uint64_t Size, 80*0b57cec5SDimitry Andric ArrayRef<uint8_t> &Buffer) const { 81*0b57cec5SDimitry Andric if (auto EC = checkOffsetForRead(Offset, Size)) 82*0b57cec5SDimitry Andric return EC; 83*0b57cec5SDimitry Andric return BorrowedImpl->readBytes(ViewOffset + Offset, Size, Buffer); 84*0b57cec5SDimitry Andric } 85*0b57cec5SDimitry Andric 86*0b57cec5SDimitry Andric Error BinaryStreamRef::readLongestContiguousChunk( 87349cc55cSDimitry Andric uint64_t Offset, ArrayRef<uint8_t> &Buffer) const { 88*0b57cec5SDimitry Andric if (auto EC = checkOffsetForRead(Offset, 1)) 89*0b57cec5SDimitry Andric return EC; 90*0b57cec5SDimitry Andric 91*0b57cec5SDimitry Andric if (auto EC = 92*0b57cec5SDimitry Andric BorrowedImpl->readLongestContiguousChunk(ViewOffset + Offset, Buffer)) 93*0b57cec5SDimitry Andric return EC; 94*0b57cec5SDimitry Andric // This StreamRef might refer to a smaller window over a larger stream. In 95*0b57cec5SDimitry Andric // that case we will have read out more bytes than we should return, because 96*0b57cec5SDimitry Andric // we should not read past the end of the current view. 97349cc55cSDimitry Andric uint64_t MaxLength = getLength() - Offset; 98*0b57cec5SDimitry Andric if (Buffer.size() > MaxLength) 99*0b57cec5SDimitry Andric Buffer = Buffer.slice(0, MaxLength); 100*0b57cec5SDimitry Andric return Error::success(); 101*0b57cec5SDimitry Andric } 102*0b57cec5SDimitry Andric 103*0b57cec5SDimitry Andric WritableBinaryStreamRef::WritableBinaryStreamRef(WritableBinaryStream &Stream) 104*0b57cec5SDimitry Andric : BinaryStreamRefBase(Stream) {} 105*0b57cec5SDimitry Andric 106*0b57cec5SDimitry Andric WritableBinaryStreamRef::WritableBinaryStreamRef(WritableBinaryStream &Stream, 107349cc55cSDimitry Andric uint64_t Offset, 108349cc55cSDimitry Andric Optional<uint64_t> Length) 109*0b57cec5SDimitry Andric : BinaryStreamRefBase(Stream, Offset, Length) {} 110*0b57cec5SDimitry Andric 111*0b57cec5SDimitry Andric WritableBinaryStreamRef::WritableBinaryStreamRef(MutableArrayRef<uint8_t> Data, 112*0b57cec5SDimitry Andric endianness Endian) 113*0b57cec5SDimitry Andric : BinaryStreamRefBase(std::make_shared<MutableArrayRefImpl>(Data, Endian), 114*0b57cec5SDimitry Andric 0, Data.size()) {} 115*0b57cec5SDimitry Andric 116349cc55cSDimitry Andric Error WritableBinaryStreamRef::writeBytes(uint64_t Offset, 117*0b57cec5SDimitry Andric ArrayRef<uint8_t> Data) const { 118*0b57cec5SDimitry Andric if (auto EC = checkOffsetForWrite(Offset, Data.size())) 119*0b57cec5SDimitry Andric return EC; 120*0b57cec5SDimitry Andric 121*0b57cec5SDimitry Andric return BorrowedImpl->writeBytes(ViewOffset + Offset, Data); 122*0b57cec5SDimitry Andric } 123*0b57cec5SDimitry Andric 124*0b57cec5SDimitry Andric WritableBinaryStreamRef::operator BinaryStreamRef() const { 125*0b57cec5SDimitry Andric return BinaryStreamRef(*BorrowedImpl, ViewOffset, Length); 126*0b57cec5SDimitry Andric } 127*0b57cec5SDimitry Andric 128*0b57cec5SDimitry Andric /// For buffered streams, commits changes to the backing store. 129*0b57cec5SDimitry Andric Error WritableBinaryStreamRef::commit() { return BorrowedImpl->commit(); } 130