xref: /freebsd/contrib/llvm-project/llvm/lib/Support/BinaryStreamReader.cpp (revision c0f13232410cf881475d6e4dbd0ec28ab3476c59)
1  //===- BinaryStreamReader.cpp - Reads objects from a binary stream --------===//
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/BinaryStreamReader.h"
10  
11  #include "llvm/Support/BinaryStreamError.h"
12  #include "llvm/Support/BinaryStreamRef.h"
13  #include "llvm/Support/LEB128.h"
14  
15  using namespace llvm;
16  
17  BinaryStreamReader::BinaryStreamReader(BinaryStreamRef Ref) : Stream(Ref) {}
18  
19  BinaryStreamReader::BinaryStreamReader(BinaryStream &Stream) : Stream(Stream) {}
20  
21  BinaryStreamReader::BinaryStreamReader(ArrayRef<uint8_t> Data,
22                                         endianness Endian)
23      : Stream(Data, Endian) {}
24  
25  BinaryStreamReader::BinaryStreamReader(StringRef Data, endianness Endian)
26      : Stream(Data, Endian) {}
27  
28  Error BinaryStreamReader::readLongestContiguousChunk(
29      ArrayRef<uint8_t> &Buffer) {
30    if (auto EC = Stream.readLongestContiguousChunk(Offset, Buffer))
31      return EC;
32    Offset += Buffer.size();
33    return Error::success();
34  }
35  
36  Error BinaryStreamReader::readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size) {
37    if (auto EC = Stream.readBytes(Offset, Size, Buffer))
38      return EC;
39    Offset += Size;
40    return Error::success();
41  }
42  
43  Error BinaryStreamReader::readULEB128(uint64_t &Dest) {
44    SmallVector<uint8_t, 10> EncodedBytes;
45    ArrayRef<uint8_t> NextByte;
46  
47    // Copy the encoded ULEB into the buffer.
48    do {
49      if (auto Err = readBytes(NextByte, 1))
50        return Err;
51      EncodedBytes.push_back(NextByte[0]);
52    } while (NextByte[0] & 0x80);
53  
54    Dest = decodeULEB128(EncodedBytes.begin(), nullptr, EncodedBytes.end());
55    return Error::success();
56  }
57  
58  Error BinaryStreamReader::readSLEB128(int64_t &Dest) {
59    SmallVector<uint8_t, 10> EncodedBytes;
60    ArrayRef<uint8_t> NextByte;
61  
62    // Copy the encoded ULEB into the buffer.
63    do {
64      if (auto Err = readBytes(NextByte, 1))
65        return Err;
66      EncodedBytes.push_back(NextByte[0]);
67    } while (NextByte[0] & 0x80);
68  
69    Dest = decodeSLEB128(EncodedBytes.begin(), nullptr, EncodedBytes.end());
70    return Error::success();
71  }
72  
73  Error BinaryStreamReader::readCString(StringRef &Dest) {
74    uint64_t OriginalOffset = getOffset();
75    uint64_t FoundOffset = 0;
76    while (true) {
77      uint64_t ThisOffset = getOffset();
78      ArrayRef<uint8_t> Buffer;
79      if (auto EC = readLongestContiguousChunk(Buffer))
80        return EC;
81      StringRef S(reinterpret_cast<const char *>(Buffer.begin()), Buffer.size());
82      size_t Pos = S.find_first_of('\0');
83      if (LLVM_LIKELY(Pos != StringRef::npos)) {
84        FoundOffset = Pos + ThisOffset;
85        break;
86      }
87    }
88    assert(FoundOffset >= OriginalOffset);
89  
90    setOffset(OriginalOffset);
91    size_t Length = FoundOffset - OriginalOffset;
92  
93    if (auto EC = readFixedString(Dest, Length))
94      return EC;
95  
96    // Now set the offset back to after the null terminator.
97    setOffset(FoundOffset + 1);
98    return Error::success();
99  }
100  
101  Error BinaryStreamReader::readWideString(ArrayRef<UTF16> &Dest) {
102    uint64_t Length = 0;
103    uint64_t OriginalOffset = getOffset();
104    const UTF16 *C;
105    while (true) {
106      if (auto EC = readObject(C))
107        return EC;
108      if (*C == 0x0000)
109        break;
110      ++Length;
111    }
112    uint64_t NewOffset = getOffset();
113    setOffset(OriginalOffset);
114  
115    if (auto EC = readArray(Dest, Length))
116      return EC;
117    setOffset(NewOffset);
118    return Error::success();
119  }
120  
121  Error BinaryStreamReader::readFixedString(StringRef &Dest, uint32_t Length) {
122    ArrayRef<uint8_t> Bytes;
123    if (auto EC = readBytes(Bytes, Length))
124      return EC;
125    Dest = StringRef(reinterpret_cast<const char *>(Bytes.begin()), Bytes.size());
126    return Error::success();
127  }
128  
129  Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref) {
130    return readStreamRef(Ref, bytesRemaining());
131  }
132  
133  Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref, uint32_t Length) {
134    if (bytesRemaining() < Length)
135      return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
136    Ref = Stream.slice(Offset, Length);
137    Offset += Length;
138    return Error::success();
139  }
140  
141  Error BinaryStreamReader::readSubstream(BinarySubstreamRef &Ref,
142                                          uint32_t Length) {
143    Ref.Offset = getOffset();
144    return readStreamRef(Ref.StreamData, Length);
145  }
146  
147  Error BinaryStreamReader::skip(uint64_t Amount) {
148    if (Amount > bytesRemaining())
149      return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
150    Offset += Amount;
151    return Error::success();
152  }
153  
154  Error BinaryStreamReader::padToAlignment(uint32_t Align) {
155    uint32_t NewOffset = alignTo(Offset, Align);
156    return skip(NewOffset - Offset);
157  }
158  
159  uint8_t BinaryStreamReader::peek() const {
160    ArrayRef<uint8_t> Buffer;
161    auto EC = Stream.readBytes(Offset, 1, Buffer);
162    assert(!EC && "Cannot peek an empty buffer!");
163    llvm::consumeError(std::move(EC));
164    return Buffer[0];
165  }
166  
167  std::pair<BinaryStreamReader, BinaryStreamReader>
168  BinaryStreamReader::split(uint64_t Off) const {
169    assert(getLength() >= Off);
170  
171    BinaryStreamRef First = Stream.drop_front(Offset);
172  
173    BinaryStreamRef Second = First.drop_front(Off);
174    First = First.keep_front(Off);
175    BinaryStreamReader W1{First};
176    BinaryStreamReader W2{Second};
177    return std::make_pair(W1, W2);
178  }
179