17a7e6055SDimitry Andric //===- BinaryStreamReader.cpp - Reads objects from a binary stream --------===//
27a7e6055SDimitry Andric //
37a7e6055SDimitry Andric // The LLVM Compiler Infrastructure
47a7e6055SDimitry Andric //
57a7e6055SDimitry Andric // This file is distributed under the University of Illinois Open Source
67a7e6055SDimitry Andric // License. See LICENSE.TXT for details.
77a7e6055SDimitry Andric //
87a7e6055SDimitry Andric //===----------------------------------------------------------------------===//
97a7e6055SDimitry Andric
107a7e6055SDimitry Andric #include "llvm/Support/BinaryStreamReader.h"
117a7e6055SDimitry Andric
127a7e6055SDimitry Andric #include "llvm/Support/BinaryStreamError.h"
137a7e6055SDimitry Andric #include "llvm/Support/BinaryStreamRef.h"
147a7e6055SDimitry Andric
157a7e6055SDimitry Andric using namespace llvm;
16d8866befSDimitry Andric using endianness = llvm::support::endianness;
177a7e6055SDimitry Andric
BinaryStreamReader(BinaryStreamRef Ref)18d8866befSDimitry Andric BinaryStreamReader::BinaryStreamReader(BinaryStreamRef Ref) : Stream(Ref) {}
19d8866befSDimitry Andric
BinaryStreamReader(BinaryStream & Stream)20d8866befSDimitry Andric BinaryStreamReader::BinaryStreamReader(BinaryStream &Stream) : Stream(Stream) {}
21d8866befSDimitry Andric
BinaryStreamReader(ArrayRef<uint8_t> Data,endianness Endian)22d8866befSDimitry Andric BinaryStreamReader::BinaryStreamReader(ArrayRef<uint8_t> Data,
23d8866befSDimitry Andric endianness Endian)
24d8866befSDimitry Andric : Stream(Data, Endian) {}
25d8866befSDimitry Andric
BinaryStreamReader(StringRef Data,endianness Endian)26d8866befSDimitry Andric BinaryStreamReader::BinaryStreamReader(StringRef Data, endianness Endian)
27d8866befSDimitry Andric : Stream(Data, Endian) {}
287a7e6055SDimitry Andric
readLongestContiguousChunk(ArrayRef<uint8_t> & Buffer)297a7e6055SDimitry Andric Error BinaryStreamReader::readLongestContiguousChunk(
307a7e6055SDimitry Andric ArrayRef<uint8_t> &Buffer) {
317a7e6055SDimitry Andric if (auto EC = Stream.readLongestContiguousChunk(Offset, Buffer))
327a7e6055SDimitry Andric return EC;
337a7e6055SDimitry Andric Offset += Buffer.size();
347a7e6055SDimitry Andric return Error::success();
357a7e6055SDimitry Andric }
367a7e6055SDimitry Andric
readBytes(ArrayRef<uint8_t> & Buffer,uint32_t Size)377a7e6055SDimitry Andric Error BinaryStreamReader::readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size) {
387a7e6055SDimitry Andric if (auto EC = Stream.readBytes(Offset, Size, Buffer))
397a7e6055SDimitry Andric return EC;
407a7e6055SDimitry Andric Offset += Size;
417a7e6055SDimitry Andric return Error::success();
427a7e6055SDimitry Andric }
437a7e6055SDimitry Andric
readCString(StringRef & Dest)447a7e6055SDimitry Andric Error BinaryStreamReader::readCString(StringRef &Dest) {
457a7e6055SDimitry Andric uint32_t OriginalOffset = getOffset();
46302affcbSDimitry Andric uint32_t FoundOffset = 0;
477a7e6055SDimitry Andric while (true) {
48302affcbSDimitry Andric uint32_t ThisOffset = getOffset();
49302affcbSDimitry Andric ArrayRef<uint8_t> Buffer;
50302affcbSDimitry Andric if (auto EC = readLongestContiguousChunk(Buffer))
517a7e6055SDimitry Andric return EC;
52302affcbSDimitry Andric StringRef S(reinterpret_cast<const char *>(Buffer.begin()), Buffer.size());
53302affcbSDimitry Andric size_t Pos = S.find_first_of('\0');
54302affcbSDimitry Andric if (LLVM_LIKELY(Pos != StringRef::npos)) {
55302affcbSDimitry Andric FoundOffset = Pos + ThisOffset;
567a7e6055SDimitry Andric break;
577a7e6055SDimitry Andric }
58302affcbSDimitry Andric }
59302affcbSDimitry Andric assert(FoundOffset >= OriginalOffset);
60302affcbSDimitry Andric
617a7e6055SDimitry Andric setOffset(OriginalOffset);
62302affcbSDimitry Andric size_t Length = FoundOffset - OriginalOffset;
637a7e6055SDimitry Andric
647a7e6055SDimitry Andric if (auto EC = readFixedString(Dest, Length))
657a7e6055SDimitry Andric return EC;
667a7e6055SDimitry Andric
67302affcbSDimitry Andric // Now set the offset back to after the null terminator.
68302affcbSDimitry Andric setOffset(FoundOffset + 1);
697a7e6055SDimitry Andric return Error::success();
707a7e6055SDimitry Andric }
717a7e6055SDimitry Andric
readWideString(ArrayRef<UTF16> & Dest)72f9448bf3SDimitry Andric Error BinaryStreamReader::readWideString(ArrayRef<UTF16> &Dest) {
73f9448bf3SDimitry Andric uint32_t Length = 0;
74f9448bf3SDimitry Andric uint32_t OriginalOffset = getOffset();
75f9448bf3SDimitry Andric const UTF16 *C;
76f9448bf3SDimitry Andric while (true) {
77f9448bf3SDimitry Andric if (auto EC = readObject(C))
78f9448bf3SDimitry Andric return EC;
79f9448bf3SDimitry Andric if (*C == 0x0000)
80f9448bf3SDimitry Andric break;
81f9448bf3SDimitry Andric ++Length;
82f9448bf3SDimitry Andric }
83f9448bf3SDimitry Andric uint32_t NewOffset = getOffset();
84f9448bf3SDimitry Andric setOffset(OriginalOffset);
85f9448bf3SDimitry Andric
86f9448bf3SDimitry Andric if (auto EC = readArray(Dest, Length))
87f9448bf3SDimitry Andric return EC;
88f9448bf3SDimitry Andric setOffset(NewOffset);
89f9448bf3SDimitry Andric return Error::success();
90f9448bf3SDimitry Andric }
91f9448bf3SDimitry Andric
readFixedString(StringRef & Dest,uint32_t Length)927a7e6055SDimitry Andric Error BinaryStreamReader::readFixedString(StringRef &Dest, uint32_t Length) {
937a7e6055SDimitry Andric ArrayRef<uint8_t> Bytes;
947a7e6055SDimitry Andric if (auto EC = readBytes(Bytes, Length))
957a7e6055SDimitry Andric return EC;
967a7e6055SDimitry Andric Dest = StringRef(reinterpret_cast<const char *>(Bytes.begin()), Bytes.size());
977a7e6055SDimitry Andric return Error::success();
987a7e6055SDimitry Andric }
997a7e6055SDimitry Andric
readStreamRef(BinaryStreamRef & Ref)1007a7e6055SDimitry Andric Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref) {
1017a7e6055SDimitry Andric return readStreamRef(Ref, bytesRemaining());
1027a7e6055SDimitry Andric }
1037a7e6055SDimitry Andric
readStreamRef(BinaryStreamRef & Ref,uint32_t Length)1047a7e6055SDimitry Andric Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref, uint32_t Length) {
1057a7e6055SDimitry Andric if (bytesRemaining() < Length)
1067a7e6055SDimitry Andric return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
1077a7e6055SDimitry Andric Ref = Stream.slice(Offset, Length);
1087a7e6055SDimitry Andric Offset += Length;
1097a7e6055SDimitry Andric return Error::success();
1107a7e6055SDimitry Andric }
1117a7e6055SDimitry Andric
readSubstream(BinarySubstreamRef & Stream,uint32_t Size)112*edd7eaddSDimitry Andric Error BinaryStreamReader::readSubstream(BinarySubstreamRef &Stream,
113*edd7eaddSDimitry Andric uint32_t Size) {
114*edd7eaddSDimitry Andric Stream.Offset = getOffset();
115*edd7eaddSDimitry Andric return readStreamRef(Stream.StreamData, Size);
116*edd7eaddSDimitry Andric }
117*edd7eaddSDimitry Andric
skip(uint32_t Amount)1187a7e6055SDimitry Andric Error BinaryStreamReader::skip(uint32_t Amount) {
1197a7e6055SDimitry Andric if (Amount > bytesRemaining())
1207a7e6055SDimitry Andric return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
1217a7e6055SDimitry Andric Offset += Amount;
1227a7e6055SDimitry Andric return Error::success();
1237a7e6055SDimitry Andric }
1247a7e6055SDimitry Andric
padToAlignment(uint32_t Align)125d8866befSDimitry Andric Error BinaryStreamReader::padToAlignment(uint32_t Align) {
126d8866befSDimitry Andric uint32_t NewOffset = alignTo(Offset, Align);
127d8866befSDimitry Andric return skip(NewOffset - Offset);
128d8866befSDimitry Andric }
129d8866befSDimitry Andric
peek() const1307a7e6055SDimitry Andric uint8_t BinaryStreamReader::peek() const {
1317a7e6055SDimitry Andric ArrayRef<uint8_t> Buffer;
1327a7e6055SDimitry Andric auto EC = Stream.readBytes(Offset, 1, Buffer);
1337a7e6055SDimitry Andric assert(!EC && "Cannot peek an empty buffer!");
1347a7e6055SDimitry Andric llvm::consumeError(std::move(EC));
1357a7e6055SDimitry Andric return Buffer[0];
1367a7e6055SDimitry Andric }
137f37b6182SDimitry Andric
138f37b6182SDimitry Andric std::pair<BinaryStreamReader, BinaryStreamReader>
split(uint32_t Off) const139f37b6182SDimitry Andric BinaryStreamReader::split(uint32_t Off) const {
140f37b6182SDimitry Andric assert(getLength() >= Off);
141f37b6182SDimitry Andric
142f37b6182SDimitry Andric BinaryStreamRef First = Stream.drop_front(Offset);
143f37b6182SDimitry Andric
144f37b6182SDimitry Andric BinaryStreamRef Second = First.drop_front(Off);
145f37b6182SDimitry Andric First = First.keep_front(Off);
146f37b6182SDimitry Andric BinaryStreamReader W1{First};
147f37b6182SDimitry Andric BinaryStreamReader W2{Second};
148f37b6182SDimitry Andric return std::make_pair(W1, W2);
149f37b6182SDimitry Andric }