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