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