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"
15 using endianness
= llvm::support::endianness
;
17 BinaryStreamReader::BinaryStreamReader(BinaryStreamRef Ref
) : Stream(Ref
) {}
19 BinaryStreamReader::BinaryStreamReader(BinaryStream
&Stream
) : Stream(Stream
) {}
21 BinaryStreamReader::BinaryStreamReader(ArrayRef
<uint8_t> Data
,
23 : Stream(Data
, Endian
) {}
25 BinaryStreamReader::BinaryStreamReader(StringRef Data
, endianness Endian
)
26 : Stream(Data
, Endian
) {}
28 Error
BinaryStreamReader::readLongestContiguousChunk(
29 ArrayRef
<uint8_t> &Buffer
) {
30 if (auto EC
= Stream
.readLongestContiguousChunk(Offset
, Buffer
))
32 Offset
+= Buffer
.size();
33 return Error::success();
36 Error
BinaryStreamReader::readBytes(ArrayRef
<uint8_t> &Buffer
, uint32_t Size
) {
37 if (auto EC
= Stream
.readBytes(Offset
, Size
, Buffer
))
40 return Error::success();
43 Error
BinaryStreamReader::readCString(StringRef
&Dest
) {
44 uint32_t OriginalOffset
= getOffset();
45 uint32_t FoundOffset
= 0;
47 uint32_t ThisOffset
= getOffset();
48 ArrayRef
<uint8_t> Buffer
;
49 if (auto EC
= readLongestContiguousChunk(Buffer
))
51 StringRef
S(reinterpret_cast<const char *>(Buffer
.begin()), Buffer
.size());
52 size_t Pos
= S
.find_first_of('\0');
53 if (LLVM_LIKELY(Pos
!= StringRef::npos
)) {
54 FoundOffset
= Pos
+ ThisOffset
;
58 assert(FoundOffset
>= OriginalOffset
);
60 setOffset(OriginalOffset
);
61 size_t Length
= FoundOffset
- OriginalOffset
;
63 if (auto EC
= readFixedString(Dest
, Length
))
66 // Now set the offset back to after the null terminator.
67 setOffset(FoundOffset
+ 1);
68 return Error::success();
71 Error
BinaryStreamReader::readWideString(ArrayRef
<UTF16
> &Dest
) {
73 uint32_t OriginalOffset
= getOffset();
76 if (auto EC
= readObject(C
))
82 uint32_t NewOffset
= getOffset();
83 setOffset(OriginalOffset
);
85 if (auto EC
= readArray(Dest
, Length
))
88 return Error::success();
91 Error
BinaryStreamReader::readFixedString(StringRef
&Dest
, uint32_t Length
) {
92 ArrayRef
<uint8_t> Bytes
;
93 if (auto EC
= readBytes(Bytes
, Length
))
95 Dest
= StringRef(reinterpret_cast<const char *>(Bytes
.begin()), Bytes
.size());
96 return Error::success();
99 Error
BinaryStreamReader::readStreamRef(BinaryStreamRef
&Ref
) {
100 return readStreamRef(Ref
, bytesRemaining());
103 Error
BinaryStreamReader::readStreamRef(BinaryStreamRef
&Ref
, uint32_t Length
) {
104 if (bytesRemaining() < Length
)
105 return make_error
<BinaryStreamError
>(stream_error_code::stream_too_short
);
106 Ref
= Stream
.slice(Offset
, Length
);
108 return Error::success();
111 Error
BinaryStreamReader::readSubstream(BinarySubstreamRef
&Stream
,
113 Stream
.Offset
= getOffset();
114 return readStreamRef(Stream
.StreamData
, Size
);
117 Error
BinaryStreamReader::skip(uint32_t Amount
) {
118 if (Amount
> bytesRemaining())
119 return make_error
<BinaryStreamError
>(stream_error_code::stream_too_short
);
121 return Error::success();
124 Error
BinaryStreamReader::padToAlignment(uint32_t Align
) {
125 uint32_t NewOffset
= alignTo(Offset
, Align
);
126 return skip(NewOffset
- Offset
);
129 uint8_t BinaryStreamReader::peek() const {
130 ArrayRef
<uint8_t> Buffer
;
131 auto EC
= Stream
.readBytes(Offset
, 1, Buffer
);
132 assert(!EC
&& "Cannot peek an empty buffer!");
133 llvm::consumeError(std::move(EC
));
137 std::pair
<BinaryStreamReader
, BinaryStreamReader
>
138 BinaryStreamReader::split(uint32_t Off
) const {
139 assert(getLength() >= Off
);
141 BinaryStreamRef First
= Stream
.drop_front(Offset
);
143 BinaryStreamRef Second
= First
.drop_front(Off
);
144 First
= First
.keep_front(Off
);
145 BinaryStreamReader W1
{First
};
146 BinaryStreamReader W2
{Second
};
147 return std::make_pair(W1
, W2
);