1 //===- BinaryStreamReader.cpp - Reads objects from a binary stream --------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Support/BinaryStreamReader.h"
11 #include "llvm/Support/BinaryStreamError.h"
12 #include "llvm/Support/BinaryStreamRef.h"
13 #include "llvm/Support/LEB128.h"
16 using endianness
= llvm::support::endianness
;
18 BinaryStreamReader::BinaryStreamReader(BinaryStreamRef Ref
) : Stream(Ref
) {}
20 BinaryStreamReader::BinaryStreamReader(BinaryStream
&Stream
) : Stream(Stream
) {}
22 BinaryStreamReader::BinaryStreamReader(ArrayRef
<uint8_t> Data
,
24 : Stream(Data
, Endian
) {}
26 BinaryStreamReader::BinaryStreamReader(StringRef Data
, endianness Endian
)
27 : Stream(Data
, Endian
) {}
29 Error
BinaryStreamReader::readLongestContiguousChunk(
30 ArrayRef
<uint8_t> &Buffer
) {
31 if (auto EC
= Stream
.readLongestContiguousChunk(Offset
, Buffer
))
33 Offset
+= Buffer
.size();
34 return Error::success();
37 Error
BinaryStreamReader::readBytes(ArrayRef
<uint8_t> &Buffer
, uint32_t Size
) {
38 if (auto EC
= Stream
.readBytes(Offset
, Size
, Buffer
))
41 return Error::success();
44 Error
BinaryStreamReader::readULEB128(uint64_t &Dest
) {
45 SmallVector
<uint8_t, 10> EncodedBytes
;
46 ArrayRef
<uint8_t> NextByte
;
48 // Copy the encoded ULEB into the buffer.
50 if (auto Err
= readBytes(NextByte
, 1))
52 EncodedBytes
.push_back(NextByte
[0]);
53 } while (NextByte
[0] & 0x80);
55 Dest
= decodeULEB128(EncodedBytes
.begin(), nullptr, EncodedBytes
.end());
56 return Error::success();
59 Error
BinaryStreamReader::readSLEB128(int64_t &Dest
) {
60 SmallVector
<uint8_t, 10> EncodedBytes
;
61 ArrayRef
<uint8_t> NextByte
;
63 // Copy the encoded ULEB into the buffer.
65 if (auto Err
= readBytes(NextByte
, 1))
67 EncodedBytes
.push_back(NextByte
[0]);
68 } while (NextByte
[0] & 0x80);
70 Dest
= decodeSLEB128(EncodedBytes
.begin(), nullptr, EncodedBytes
.end());
71 return Error::success();
74 Error
BinaryStreamReader::readCString(StringRef
&Dest
) {
75 uint32_t OriginalOffset
= getOffset();
76 uint32_t FoundOffset
= 0;
78 uint32_t ThisOffset
= getOffset();
79 ArrayRef
<uint8_t> Buffer
;
80 if (auto EC
= readLongestContiguousChunk(Buffer
))
82 StringRef
S(reinterpret_cast<const char *>(Buffer
.begin()), Buffer
.size());
83 size_t Pos
= S
.find_first_of('\0');
84 if (LLVM_LIKELY(Pos
!= StringRef::npos
)) {
85 FoundOffset
= Pos
+ ThisOffset
;
89 assert(FoundOffset
>= OriginalOffset
);
91 setOffset(OriginalOffset
);
92 size_t Length
= FoundOffset
- OriginalOffset
;
94 if (auto EC
= readFixedString(Dest
, Length
))
97 // Now set the offset back to after the null terminator.
98 setOffset(FoundOffset
+ 1);
99 return Error::success();
102 Error
BinaryStreamReader::readWideString(ArrayRef
<UTF16
> &Dest
) {
104 uint32_t OriginalOffset
= getOffset();
107 if (auto EC
= readObject(C
))
113 uint32_t NewOffset
= getOffset();
114 setOffset(OriginalOffset
);
116 if (auto EC
= readArray(Dest
, Length
))
118 setOffset(NewOffset
);
119 return Error::success();
122 Error
BinaryStreamReader::readFixedString(StringRef
&Dest
, uint32_t Length
) {
123 ArrayRef
<uint8_t> Bytes
;
124 if (auto EC
= readBytes(Bytes
, Length
))
126 Dest
= StringRef(reinterpret_cast<const char *>(Bytes
.begin()), Bytes
.size());
127 return Error::success();
130 Error
BinaryStreamReader::readStreamRef(BinaryStreamRef
&Ref
) {
131 return readStreamRef(Ref
, bytesRemaining());
134 Error
BinaryStreamReader::readStreamRef(BinaryStreamRef
&Ref
, uint32_t Length
) {
135 if (bytesRemaining() < Length
)
136 return make_error
<BinaryStreamError
>(stream_error_code::stream_too_short
);
137 Ref
= Stream
.slice(Offset
, Length
);
139 return Error::success();
142 Error
BinaryStreamReader::readSubstream(BinarySubstreamRef
&Stream
,
144 Stream
.Offset
= getOffset();
145 return readStreamRef(Stream
.StreamData
, Size
);
148 Error
BinaryStreamReader::skip(uint32_t Amount
) {
149 if (Amount
> bytesRemaining())
150 return make_error
<BinaryStreamError
>(stream_error_code::stream_too_short
);
152 return Error::success();
155 Error
BinaryStreamReader::padToAlignment(uint32_t Align
) {
156 uint32_t NewOffset
= alignTo(Offset
, Align
);
157 return skip(NewOffset
- Offset
);
160 uint8_t BinaryStreamReader::peek() const {
161 ArrayRef
<uint8_t> Buffer
;
162 auto EC
= Stream
.readBytes(Offset
, 1, Buffer
);
163 assert(!EC
&& "Cannot peek an empty buffer!");
164 llvm::consumeError(std::move(EC
));
168 std::pair
<BinaryStreamReader
, BinaryStreamReader
>
169 BinaryStreamReader::split(uint32_t Off
) const {
170 assert(getLength() >= Off
);
172 BinaryStreamRef First
= Stream
.drop_front(Offset
);
174 BinaryStreamRef Second
= First
.drop_front(Off
);
175 First
= First
.keep_front(Off
);
176 BinaryStreamReader W1
{First
};
177 BinaryStreamReader W2
{Second
};
178 return std::make_pair(W1
, W2
);