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