10b57cec5SDimitry Andric //===- BinaryStreamRef.cpp - ----------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "llvm/Support/BinaryStreamRef.h"
100b57cec5SDimitry Andric #include "llvm/Support/BinaryByteStream.h"
110b57cec5SDimitry Andric
120b57cec5SDimitry Andric using namespace llvm;
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric namespace {
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric class ArrayRefImpl : public BinaryStream {
170b57cec5SDimitry Andric public:
ArrayRefImpl(ArrayRef<uint8_t> Data,endianness Endian)180b57cec5SDimitry Andric ArrayRefImpl(ArrayRef<uint8_t> Data, endianness Endian) : BBS(Data, Endian) {}
190b57cec5SDimitry Andric
getEndian() const20*5f757f3fSDimitry Andric llvm::endianness getEndian() const override { return BBS.getEndian(); }
readBytes(uint64_t Offset,uint64_t Size,ArrayRef<uint8_t> & Buffer)21349cc55cSDimitry Andric Error readBytes(uint64_t Offset, uint64_t Size,
220b57cec5SDimitry Andric ArrayRef<uint8_t> &Buffer) override {
230b57cec5SDimitry Andric return BBS.readBytes(Offset, Size, Buffer);
240b57cec5SDimitry Andric }
readLongestContiguousChunk(uint64_t Offset,ArrayRef<uint8_t> & Buffer)25349cc55cSDimitry Andric Error readLongestContiguousChunk(uint64_t Offset,
260b57cec5SDimitry Andric ArrayRef<uint8_t> &Buffer) override {
270b57cec5SDimitry Andric return BBS.readLongestContiguousChunk(Offset, Buffer);
280b57cec5SDimitry Andric }
getLength()29349cc55cSDimitry Andric uint64_t getLength() override { return BBS.getLength(); }
300b57cec5SDimitry Andric
310b57cec5SDimitry Andric private:
320b57cec5SDimitry Andric BinaryByteStream BBS;
330b57cec5SDimitry Andric };
340b57cec5SDimitry Andric
350b57cec5SDimitry Andric class MutableArrayRefImpl : public WritableBinaryStream {
360b57cec5SDimitry Andric public:
MutableArrayRefImpl(MutableArrayRef<uint8_t> Data,endianness Endian)370b57cec5SDimitry Andric MutableArrayRefImpl(MutableArrayRef<uint8_t> Data, endianness Endian)
380b57cec5SDimitry Andric : BBS(Data, Endian) {}
390b57cec5SDimitry Andric
400b57cec5SDimitry Andric // Inherited via WritableBinaryStream
getEndian() const41*5f757f3fSDimitry Andric llvm::endianness getEndian() const override { return BBS.getEndian(); }
readBytes(uint64_t Offset,uint64_t Size,ArrayRef<uint8_t> & Buffer)42349cc55cSDimitry Andric Error readBytes(uint64_t Offset, uint64_t Size,
430b57cec5SDimitry Andric ArrayRef<uint8_t> &Buffer) override {
440b57cec5SDimitry Andric return BBS.readBytes(Offset, Size, Buffer);
450b57cec5SDimitry Andric }
readLongestContiguousChunk(uint64_t Offset,ArrayRef<uint8_t> & Buffer)46349cc55cSDimitry Andric Error readLongestContiguousChunk(uint64_t Offset,
470b57cec5SDimitry Andric ArrayRef<uint8_t> &Buffer) override {
480b57cec5SDimitry Andric return BBS.readLongestContiguousChunk(Offset, Buffer);
490b57cec5SDimitry Andric }
getLength()50349cc55cSDimitry Andric uint64_t getLength() override { return BBS.getLength(); }
510b57cec5SDimitry Andric
writeBytes(uint64_t Offset,ArrayRef<uint8_t> Data)52349cc55cSDimitry Andric Error writeBytes(uint64_t Offset, ArrayRef<uint8_t> Data) override {
530b57cec5SDimitry Andric return BBS.writeBytes(Offset, Data);
540b57cec5SDimitry Andric }
commit()550b57cec5SDimitry Andric Error commit() override { return BBS.commit(); }
560b57cec5SDimitry Andric
570b57cec5SDimitry Andric private:
580b57cec5SDimitry Andric MutableBinaryByteStream BBS;
590b57cec5SDimitry Andric };
60fe6060f1SDimitry Andric } // namespace
610b57cec5SDimitry Andric
BinaryStreamRef(BinaryStream & Stream)620b57cec5SDimitry Andric BinaryStreamRef::BinaryStreamRef(BinaryStream &Stream)
630b57cec5SDimitry Andric : BinaryStreamRefBase(Stream) {}
BinaryStreamRef(BinaryStream & Stream,uint64_t Offset,std::optional<uint64_t> Length)64349cc55cSDimitry Andric BinaryStreamRef::BinaryStreamRef(BinaryStream &Stream, uint64_t Offset,
65bdd1243dSDimitry Andric std::optional<uint64_t> Length)
660b57cec5SDimitry Andric : BinaryStreamRefBase(Stream, Offset, Length) {}
BinaryStreamRef(ArrayRef<uint8_t> Data,endianness Endian)670b57cec5SDimitry Andric BinaryStreamRef::BinaryStreamRef(ArrayRef<uint8_t> Data, endianness Endian)
680b57cec5SDimitry Andric : BinaryStreamRefBase(std::make_shared<ArrayRefImpl>(Data, Endian), 0,
690b57cec5SDimitry Andric Data.size()) {}
BinaryStreamRef(StringRef Data,endianness Endian)700b57cec5SDimitry Andric BinaryStreamRef::BinaryStreamRef(StringRef Data, endianness Endian)
71bdd1243dSDimitry Andric : BinaryStreamRef(ArrayRef(Data.bytes_begin(), Data.bytes_end()), Endian) {}
720b57cec5SDimitry Andric
readBytes(uint64_t Offset,uint64_t Size,ArrayRef<uint8_t> & Buffer) const73349cc55cSDimitry Andric Error BinaryStreamRef::readBytes(uint64_t Offset, uint64_t Size,
740b57cec5SDimitry Andric ArrayRef<uint8_t> &Buffer) const {
750b57cec5SDimitry Andric if (auto EC = checkOffsetForRead(Offset, Size))
760b57cec5SDimitry Andric return EC;
770b57cec5SDimitry Andric return BorrowedImpl->readBytes(ViewOffset + Offset, Size, Buffer);
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric
readLongestContiguousChunk(uint64_t Offset,ArrayRef<uint8_t> & Buffer) const800b57cec5SDimitry Andric Error BinaryStreamRef::readLongestContiguousChunk(
81349cc55cSDimitry Andric uint64_t Offset, ArrayRef<uint8_t> &Buffer) const {
820b57cec5SDimitry Andric if (auto EC = checkOffsetForRead(Offset, 1))
830b57cec5SDimitry Andric return EC;
840b57cec5SDimitry Andric
850b57cec5SDimitry Andric if (auto EC =
860b57cec5SDimitry Andric BorrowedImpl->readLongestContiguousChunk(ViewOffset + Offset, Buffer))
870b57cec5SDimitry Andric return EC;
880b57cec5SDimitry Andric // This StreamRef might refer to a smaller window over a larger stream. In
890b57cec5SDimitry Andric // that case we will have read out more bytes than we should return, because
900b57cec5SDimitry Andric // we should not read past the end of the current view.
91349cc55cSDimitry Andric uint64_t MaxLength = getLength() - Offset;
920b57cec5SDimitry Andric if (Buffer.size() > MaxLength)
930b57cec5SDimitry Andric Buffer = Buffer.slice(0, MaxLength);
940b57cec5SDimitry Andric return Error::success();
950b57cec5SDimitry Andric }
960b57cec5SDimitry Andric
WritableBinaryStreamRef(WritableBinaryStream & Stream)970b57cec5SDimitry Andric WritableBinaryStreamRef::WritableBinaryStreamRef(WritableBinaryStream &Stream)
980b57cec5SDimitry Andric : BinaryStreamRefBase(Stream) {}
990b57cec5SDimitry Andric
WritableBinaryStreamRef(WritableBinaryStream & Stream,uint64_t Offset,std::optional<uint64_t> Length)1000b57cec5SDimitry Andric WritableBinaryStreamRef::WritableBinaryStreamRef(WritableBinaryStream &Stream,
101349cc55cSDimitry Andric uint64_t Offset,
102bdd1243dSDimitry Andric std::optional<uint64_t> Length)
1030b57cec5SDimitry Andric : BinaryStreamRefBase(Stream, Offset, Length) {}
1040b57cec5SDimitry Andric
WritableBinaryStreamRef(MutableArrayRef<uint8_t> Data,endianness Endian)1050b57cec5SDimitry Andric WritableBinaryStreamRef::WritableBinaryStreamRef(MutableArrayRef<uint8_t> Data,
1060b57cec5SDimitry Andric endianness Endian)
1070b57cec5SDimitry Andric : BinaryStreamRefBase(std::make_shared<MutableArrayRefImpl>(Data, Endian),
1080b57cec5SDimitry Andric 0, Data.size()) {}
1090b57cec5SDimitry Andric
writeBytes(uint64_t Offset,ArrayRef<uint8_t> Data) const110349cc55cSDimitry Andric Error WritableBinaryStreamRef::writeBytes(uint64_t Offset,
1110b57cec5SDimitry Andric ArrayRef<uint8_t> Data) const {
1120b57cec5SDimitry Andric if (auto EC = checkOffsetForWrite(Offset, Data.size()))
1130b57cec5SDimitry Andric return EC;
1140b57cec5SDimitry Andric
1150b57cec5SDimitry Andric return BorrowedImpl->writeBytes(ViewOffset + Offset, Data);
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric
operator BinaryStreamRef() const1180b57cec5SDimitry Andric WritableBinaryStreamRef::operator BinaryStreamRef() const {
1190b57cec5SDimitry Andric return BinaryStreamRef(*BorrowedImpl, ViewOffset, Length);
1200b57cec5SDimitry Andric }
1210b57cec5SDimitry Andric
1220b57cec5SDimitry Andric /// For buffered streams, commits changes to the backing store.
commit()1230b57cec5SDimitry Andric Error WritableBinaryStreamRef::commit() { return BorrowedImpl->commit(); }
124