10b57cec5SDimitry Andric //===- BinaryStreamReader.cpp - Reads objects from a binary stream --------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "llvm/Support/BinaryStreamReader.h"
100b57cec5SDimitry Andric
110b57cec5SDimitry Andric #include "llvm/Support/BinaryStreamError.h"
120b57cec5SDimitry Andric #include "llvm/Support/BinaryStreamRef.h"
130b57cec5SDimitry Andric #include "llvm/Support/LEB128.h"
140b57cec5SDimitry Andric
150b57cec5SDimitry Andric using namespace llvm;
160b57cec5SDimitry Andric
BinaryStreamReader(BinaryStreamRef Ref)170b57cec5SDimitry Andric BinaryStreamReader::BinaryStreamReader(BinaryStreamRef Ref) : Stream(Ref) {}
180b57cec5SDimitry Andric
BinaryStreamReader(BinaryStream & Stream)190b57cec5SDimitry Andric BinaryStreamReader::BinaryStreamReader(BinaryStream &Stream) : Stream(Stream) {}
200b57cec5SDimitry Andric
BinaryStreamReader(ArrayRef<uint8_t> Data,endianness Endian)210b57cec5SDimitry Andric BinaryStreamReader::BinaryStreamReader(ArrayRef<uint8_t> Data,
220b57cec5SDimitry Andric endianness Endian)
230b57cec5SDimitry Andric : Stream(Data, Endian) {}
240b57cec5SDimitry Andric
BinaryStreamReader(StringRef Data,endianness Endian)250b57cec5SDimitry Andric BinaryStreamReader::BinaryStreamReader(StringRef Data, endianness Endian)
260b57cec5SDimitry Andric : Stream(Data, Endian) {}
270b57cec5SDimitry Andric
readLongestContiguousChunk(ArrayRef<uint8_t> & Buffer)280b57cec5SDimitry Andric Error BinaryStreamReader::readLongestContiguousChunk(
290b57cec5SDimitry Andric ArrayRef<uint8_t> &Buffer) {
300b57cec5SDimitry Andric if (auto EC = Stream.readLongestContiguousChunk(Offset, Buffer))
310b57cec5SDimitry Andric return EC;
320b57cec5SDimitry Andric Offset += Buffer.size();
330b57cec5SDimitry Andric return Error::success();
340b57cec5SDimitry Andric }
350b57cec5SDimitry Andric
readBytes(ArrayRef<uint8_t> & Buffer,uint32_t Size)360b57cec5SDimitry Andric Error BinaryStreamReader::readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size) {
370b57cec5SDimitry Andric if (auto EC = Stream.readBytes(Offset, Size, Buffer))
380b57cec5SDimitry Andric return EC;
390b57cec5SDimitry Andric Offset += Size;
400b57cec5SDimitry Andric return Error::success();
410b57cec5SDimitry Andric }
420b57cec5SDimitry Andric
readULEB128(uint64_t & Dest)430b57cec5SDimitry Andric Error BinaryStreamReader::readULEB128(uint64_t &Dest) {
440b57cec5SDimitry Andric SmallVector<uint8_t, 10> EncodedBytes;
450b57cec5SDimitry Andric ArrayRef<uint8_t> NextByte;
460b57cec5SDimitry Andric
470b57cec5SDimitry Andric // Copy the encoded ULEB into the buffer.
480b57cec5SDimitry Andric do {
490b57cec5SDimitry Andric if (auto Err = readBytes(NextByte, 1))
500b57cec5SDimitry Andric return Err;
510b57cec5SDimitry Andric EncodedBytes.push_back(NextByte[0]);
520b57cec5SDimitry Andric } while (NextByte[0] & 0x80);
530b57cec5SDimitry Andric
540b57cec5SDimitry Andric Dest = decodeULEB128(EncodedBytes.begin(), nullptr, EncodedBytes.end());
550b57cec5SDimitry Andric return Error::success();
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric
readSLEB128(int64_t & Dest)580b57cec5SDimitry Andric Error BinaryStreamReader::readSLEB128(int64_t &Dest) {
590b57cec5SDimitry Andric SmallVector<uint8_t, 10> EncodedBytes;
600b57cec5SDimitry Andric ArrayRef<uint8_t> NextByte;
610b57cec5SDimitry Andric
620b57cec5SDimitry Andric // Copy the encoded ULEB into the buffer.
630b57cec5SDimitry Andric do {
640b57cec5SDimitry Andric if (auto Err = readBytes(NextByte, 1))
650b57cec5SDimitry Andric return Err;
660b57cec5SDimitry Andric EncodedBytes.push_back(NextByte[0]);
670b57cec5SDimitry Andric } while (NextByte[0] & 0x80);
680b57cec5SDimitry Andric
690b57cec5SDimitry Andric Dest = decodeSLEB128(EncodedBytes.begin(), nullptr, EncodedBytes.end());
700b57cec5SDimitry Andric return Error::success();
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric
readCString(StringRef & Dest)730b57cec5SDimitry Andric Error BinaryStreamReader::readCString(StringRef &Dest) {
74*349cc55cSDimitry Andric uint64_t OriginalOffset = getOffset();
75*349cc55cSDimitry Andric uint64_t FoundOffset = 0;
760b57cec5SDimitry Andric while (true) {
77*349cc55cSDimitry Andric uint64_t ThisOffset = getOffset();
780b57cec5SDimitry Andric ArrayRef<uint8_t> Buffer;
790b57cec5SDimitry Andric if (auto EC = readLongestContiguousChunk(Buffer))
800b57cec5SDimitry Andric return EC;
810b57cec5SDimitry Andric StringRef S(reinterpret_cast<const char *>(Buffer.begin()), Buffer.size());
820b57cec5SDimitry Andric size_t Pos = S.find_first_of('\0');
830b57cec5SDimitry Andric if (LLVM_LIKELY(Pos != StringRef::npos)) {
840b57cec5SDimitry Andric FoundOffset = Pos + ThisOffset;
850b57cec5SDimitry Andric break;
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric assert(FoundOffset >= OriginalOffset);
890b57cec5SDimitry Andric
900b57cec5SDimitry Andric setOffset(OriginalOffset);
910b57cec5SDimitry Andric size_t Length = FoundOffset - OriginalOffset;
920b57cec5SDimitry Andric
930b57cec5SDimitry Andric if (auto EC = readFixedString(Dest, Length))
940b57cec5SDimitry Andric return EC;
950b57cec5SDimitry Andric
960b57cec5SDimitry Andric // Now set the offset back to after the null terminator.
970b57cec5SDimitry Andric setOffset(FoundOffset + 1);
980b57cec5SDimitry Andric return Error::success();
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric
readWideString(ArrayRef<UTF16> & Dest)1010b57cec5SDimitry Andric Error BinaryStreamReader::readWideString(ArrayRef<UTF16> &Dest) {
102*349cc55cSDimitry Andric uint64_t Length = 0;
103*349cc55cSDimitry Andric uint64_t OriginalOffset = getOffset();
1040b57cec5SDimitry Andric const UTF16 *C;
1050b57cec5SDimitry Andric while (true) {
1060b57cec5SDimitry Andric if (auto EC = readObject(C))
1070b57cec5SDimitry Andric return EC;
1080b57cec5SDimitry Andric if (*C == 0x0000)
1090b57cec5SDimitry Andric break;
1100b57cec5SDimitry Andric ++Length;
1110b57cec5SDimitry Andric }
112*349cc55cSDimitry Andric uint64_t NewOffset = getOffset();
1130b57cec5SDimitry Andric setOffset(OriginalOffset);
1140b57cec5SDimitry Andric
1150b57cec5SDimitry Andric if (auto EC = readArray(Dest, Length))
1160b57cec5SDimitry Andric return EC;
1170b57cec5SDimitry Andric setOffset(NewOffset);
1180b57cec5SDimitry Andric return Error::success();
1190b57cec5SDimitry Andric }
1200b57cec5SDimitry Andric
readFixedString(StringRef & Dest,uint32_t Length)1210b57cec5SDimitry Andric Error BinaryStreamReader::readFixedString(StringRef &Dest, uint32_t Length) {
1220b57cec5SDimitry Andric ArrayRef<uint8_t> Bytes;
1230b57cec5SDimitry Andric if (auto EC = readBytes(Bytes, Length))
1240b57cec5SDimitry Andric return EC;
1250b57cec5SDimitry Andric Dest = StringRef(reinterpret_cast<const char *>(Bytes.begin()), Bytes.size());
1260b57cec5SDimitry Andric return Error::success();
1270b57cec5SDimitry Andric }
1280b57cec5SDimitry Andric
readStreamRef(BinaryStreamRef & Ref)1290b57cec5SDimitry Andric Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref) {
1300b57cec5SDimitry Andric return readStreamRef(Ref, bytesRemaining());
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric
readStreamRef(BinaryStreamRef & Ref,uint32_t Length)1330b57cec5SDimitry Andric Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref, uint32_t Length) {
1340b57cec5SDimitry Andric if (bytesRemaining() < Length)
1350b57cec5SDimitry Andric return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
1360b57cec5SDimitry Andric Ref = Stream.slice(Offset, Length);
1370b57cec5SDimitry Andric Offset += Length;
1380b57cec5SDimitry Andric return Error::success();
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric
readSubstream(BinarySubstreamRef & Ref,uint32_t Length)141480093f4SDimitry Andric Error BinaryStreamReader::readSubstream(BinarySubstreamRef &Ref,
142480093f4SDimitry Andric uint32_t Length) {
143480093f4SDimitry Andric Ref.Offset = getOffset();
144480093f4SDimitry Andric return readStreamRef(Ref.StreamData, Length);
1450b57cec5SDimitry Andric }
1460b57cec5SDimitry Andric
skip(uint64_t Amount)147*349cc55cSDimitry Andric Error BinaryStreamReader::skip(uint64_t Amount) {
1480b57cec5SDimitry Andric if (Amount > bytesRemaining())
1490b57cec5SDimitry Andric return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
1500b57cec5SDimitry Andric Offset += Amount;
1510b57cec5SDimitry Andric return Error::success();
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric
padToAlignment(uint32_t Align)1540b57cec5SDimitry Andric Error BinaryStreamReader::padToAlignment(uint32_t Align) {
1550b57cec5SDimitry Andric uint32_t NewOffset = alignTo(Offset, Align);
1560b57cec5SDimitry Andric return skip(NewOffset - Offset);
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric
peek() const1590b57cec5SDimitry Andric uint8_t BinaryStreamReader::peek() const {
1600b57cec5SDimitry Andric ArrayRef<uint8_t> Buffer;
1610b57cec5SDimitry Andric auto EC = Stream.readBytes(Offset, 1, Buffer);
1620b57cec5SDimitry Andric assert(!EC && "Cannot peek an empty buffer!");
1630b57cec5SDimitry Andric llvm::consumeError(std::move(EC));
1640b57cec5SDimitry Andric return Buffer[0];
1650b57cec5SDimitry Andric }
1660b57cec5SDimitry Andric
1670b57cec5SDimitry Andric std::pair<BinaryStreamReader, BinaryStreamReader>
split(uint64_t Off) const168*349cc55cSDimitry Andric BinaryStreamReader::split(uint64_t Off) const {
1690b57cec5SDimitry Andric assert(getLength() >= Off);
1700b57cec5SDimitry Andric
1710b57cec5SDimitry Andric BinaryStreamRef First = Stream.drop_front(Offset);
1720b57cec5SDimitry Andric
1730b57cec5SDimitry Andric BinaryStreamRef Second = First.drop_front(Off);
1740b57cec5SDimitry Andric First = First.keep_front(Off);
1750b57cec5SDimitry Andric BinaryStreamReader W1{First};
1760b57cec5SDimitry Andric BinaryStreamReader W2{Second};
1770b57cec5SDimitry Andric return std::make_pair(W1, W2);
1780b57cec5SDimitry Andric }
179