Path: blob/main/contrib/llvm-project/llvm/lib/Support/BinaryStreamReader.cpp
35232 views
//===- BinaryStreamReader.cpp - Reads objects from a binary stream --------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/Support/BinaryStreamReader.h"910#include "llvm/Support/BinaryStreamError.h"11#include "llvm/Support/BinaryStreamRef.h"12#include "llvm/Support/LEB128.h"1314using namespace llvm;1516BinaryStreamReader::BinaryStreamReader(BinaryStreamRef Ref) : Stream(Ref) {}1718BinaryStreamReader::BinaryStreamReader(BinaryStream &Stream) : Stream(Stream) {}1920BinaryStreamReader::BinaryStreamReader(ArrayRef<uint8_t> Data,21endianness Endian)22: Stream(Data, Endian) {}2324BinaryStreamReader::BinaryStreamReader(StringRef Data, endianness Endian)25: Stream(Data, Endian) {}2627Error BinaryStreamReader::readLongestContiguousChunk(28ArrayRef<uint8_t> &Buffer) {29if (auto EC = Stream.readLongestContiguousChunk(Offset, Buffer))30return EC;31Offset += Buffer.size();32return Error::success();33}3435Error BinaryStreamReader::readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size) {36if (auto EC = Stream.readBytes(Offset, Size, Buffer))37return EC;38Offset += Size;39return Error::success();40}4142Error BinaryStreamReader::readULEB128(uint64_t &Dest) {43SmallVector<uint8_t, 10> EncodedBytes;44ArrayRef<uint8_t> NextByte;4546// Copy the encoded ULEB into the buffer.47do {48if (auto Err = readBytes(NextByte, 1))49return Err;50EncodedBytes.push_back(NextByte[0]);51} while (NextByte[0] & 0x80);5253Dest = decodeULEB128(EncodedBytes.begin(), nullptr, EncodedBytes.end());54return Error::success();55}5657Error BinaryStreamReader::readSLEB128(int64_t &Dest) {58SmallVector<uint8_t, 10> EncodedBytes;59ArrayRef<uint8_t> NextByte;6061// Copy the encoded ULEB into the buffer.62do {63if (auto Err = readBytes(NextByte, 1))64return Err;65EncodedBytes.push_back(NextByte[0]);66} while (NextByte[0] & 0x80);6768Dest = decodeSLEB128(EncodedBytes.begin(), nullptr, EncodedBytes.end());69return Error::success();70}7172Error BinaryStreamReader::readCString(StringRef &Dest) {73uint64_t OriginalOffset = getOffset();74uint64_t FoundOffset = 0;75while (true) {76uint64_t ThisOffset = getOffset();77ArrayRef<uint8_t> Buffer;78if (auto EC = readLongestContiguousChunk(Buffer))79return EC;80StringRef S(reinterpret_cast<const char *>(Buffer.begin()), Buffer.size());81size_t Pos = S.find_first_of('\0');82if (LLVM_LIKELY(Pos != StringRef::npos)) {83FoundOffset = Pos + ThisOffset;84break;85}86}87assert(FoundOffset >= OriginalOffset);8889setOffset(OriginalOffset);90size_t Length = FoundOffset - OriginalOffset;9192if (auto EC = readFixedString(Dest, Length))93return EC;9495// Now set the offset back to after the null terminator.96setOffset(FoundOffset + 1);97return Error::success();98}99100Error BinaryStreamReader::readWideString(ArrayRef<UTF16> &Dest) {101uint64_t Length = 0;102uint64_t OriginalOffset = getOffset();103const UTF16 *C;104while (true) {105if (auto EC = readObject(C))106return EC;107if (*C == 0x0000)108break;109++Length;110}111uint64_t NewOffset = getOffset();112setOffset(OriginalOffset);113114if (auto EC = readArray(Dest, Length))115return EC;116setOffset(NewOffset);117return Error::success();118}119120Error BinaryStreamReader::readFixedString(StringRef &Dest, uint32_t Length) {121ArrayRef<uint8_t> Bytes;122if (auto EC = readBytes(Bytes, Length))123return EC;124Dest = StringRef(reinterpret_cast<const char *>(Bytes.begin()), Bytes.size());125return Error::success();126}127128Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref) {129return readStreamRef(Ref, bytesRemaining());130}131132Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref, uint32_t Length) {133if (bytesRemaining() < Length)134return make_error<BinaryStreamError>(stream_error_code::stream_too_short);135Ref = Stream.slice(Offset, Length);136Offset += Length;137return Error::success();138}139140Error BinaryStreamReader::readSubstream(BinarySubstreamRef &Ref,141uint32_t Length) {142Ref.Offset = getOffset();143return readStreamRef(Ref.StreamData, Length);144}145146Error BinaryStreamReader::skip(uint64_t Amount) {147if (Amount > bytesRemaining())148return make_error<BinaryStreamError>(stream_error_code::stream_too_short);149Offset += Amount;150return Error::success();151}152153Error BinaryStreamReader::padToAlignment(uint32_t Align) {154uint32_t NewOffset = alignTo(Offset, Align);155return skip(NewOffset - Offset);156}157158uint8_t BinaryStreamReader::peek() const {159ArrayRef<uint8_t> Buffer;160auto EC = Stream.readBytes(Offset, 1, Buffer);161assert(!EC && "Cannot peek an empty buffer!");162llvm::consumeError(std::move(EC));163return Buffer[0];164}165166std::pair<BinaryStreamReader, BinaryStreamReader>167BinaryStreamReader::split(uint64_t Off) const {168assert(getLength() >= Off);169170BinaryStreamRef First = Stream.drop_front(Offset);171172BinaryStreamRef Second = First.drop_front(Off);173First = First.keep_front(Off);174BinaryStreamReader W1{First};175BinaryStreamReader W2{Second};176return std::make_pair(W1, W2);177}178179180