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