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 }