1 //===- BinaryStreamReader.cpp - Reads objects from a binary stream --------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/Support/BinaryStreamReader.h"
12 #include "llvm/Support/BinaryStreamError.h"
13 #include "llvm/Support/BinaryStreamRef.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::readCString(StringRef &Dest) {
45 // TODO: This could be made more efficient by using readLongestContiguousChunk
46 // and searching for null terminators in the resulting buffer.
49 // First compute the length of the string by reading 1 byte at a time.
50 uint32_t OriginalOffset = getOffset();
53 if (auto EC = readObject(C))
59 // Now go back and request a reference for that many bytes.
60 uint32_t NewOffset = getOffset();
61 setOffset(OriginalOffset);
63 if (auto EC = readFixedString(Dest, Length))
66 // Now set the offset back to where it was after we calculated the length.
68 return Error::success();
71 Error BinaryStreamReader::readFixedString(StringRef &Dest, uint32_t Length) {
72 ArrayRef<uint8_t> Bytes;
73 if (auto EC = readBytes(Bytes, Length))
75 Dest = StringRef(reinterpret_cast<const char *>(Bytes.begin()), Bytes.size());
76 return Error::success();
79 Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref) {
80 return readStreamRef(Ref, bytesRemaining());
83 Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref, uint32_t Length) {
84 if (bytesRemaining() < Length)
85 return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
86 Ref = Stream.slice(Offset, Length);
88 return Error::success();
91 Error BinaryStreamReader::skip(uint32_t Amount) {
92 if (Amount > bytesRemaining())
93 return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
95 return Error::success();
98 Error BinaryStreamReader::padToAlignment(uint32_t Align) {
99 uint32_t NewOffset = alignTo(Offset, Align);
100 return skip(NewOffset - Offset);
103 uint8_t BinaryStreamReader::peek() const {
104 ArrayRef<uint8_t> Buffer;
105 auto EC = Stream.readBytes(Offset, 1, Buffer);
106 assert(!EC && "Cannot peek an empty buffer!");
107 llvm::consumeError(std::move(EC));
111 std::pair<BinaryStreamReader, BinaryStreamReader>
112 BinaryStreamReader::split(uint32_t Off) const {
113 assert(getLength() >= Off);
115 BinaryStreamRef First = Stream.drop_front(Offset);
117 BinaryStreamRef Second = First.drop_front(Off);
118 First = First.keep_front(Off);
119 BinaryStreamReader W1{First};
120 BinaryStreamReader W2{Second};
121 return std::make_pair(W1, W2);