xref: /openbsd-src/gnu/llvm/llvm/lib/Support/BinaryStreamRef.cpp (revision 09467b48e8bc8b4905716062da846024139afbf2)
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