blob: ba5fd213c59d926e57a154e045c57e09d18105e5 [file] [log] [blame]
Zachary Turneraf299ea2017-02-25 00:44:30 +00001//===- BinaryStreamReader.cpp - Reads objects from a binary stream --------===//
Zachary Turner6ba65de2016-04-29 17:22:58 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Zachary Turnerd2684b72017-02-25 00:33:34 +000010#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
Zachary Turnerd5d37dc2016-05-25 20:37:03 +000011
Zachary Turnerd2684b72017-02-25 00:33:34 +000012#include "llvm/DebugInfo/MSF/BinaryStreamRef.h"
Zachary Turner6ba65de2016-04-29 17:22:58 +000013
14using namespace llvm;
Zachary Turner6ba65de2016-04-29 17:22:58 +000015
Zachary Turneraf299ea2017-02-25 00:44:30 +000016BinaryStreamReader::BinaryStreamReader(BinaryStreamRef S)
17 : Stream(S), Offset(0) {}
Zachary Turner6ba65de2016-04-29 17:22:58 +000018
Zachary Turneraf299ea2017-02-25 00:44:30 +000019Error BinaryStreamReader::readLongestContiguousChunk(
20 ArrayRef<uint8_t> &Buffer) {
Zachary Turner5acb4ac2016-06-10 05:09:12 +000021 if (auto EC = Stream.readLongestContiguousChunk(Offset, Buffer))
22 return EC;
23 Offset += Buffer.size();
24 return Error::success();
25}
26
Zachary Turneraf299ea2017-02-25 00:44:30 +000027Error BinaryStreamReader::readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size) {
Zachary Turner8dbe3622016-05-27 01:54:44 +000028 if (auto EC = Stream.readBytes(Offset, Size, Buffer))
29 return EC;
30 Offset += Size;
31 return Error::success();
32}
33
Zachary Turneraf299ea2017-02-25 00:44:30 +000034Error BinaryStreamReader::readInteger(uint64_t &Dest, uint32_t ByteSize) {
35 assert(ByteSize == 1 || ByteSize == 2 || ByteSize == 4 || ByteSize == 8);
36 ArrayRef<uint8_t> Bytes;
37
38 if (auto EC = readBytes(Bytes, ByteSize))
39 return EC;
40 switch (ByteSize) {
41 case 1:
42 Dest = Bytes[0];
43 return Error::success();
44 case 2:
45 Dest = llvm::support::endian::read16(Bytes.data(), Stream.getEndian());
46 return Error::success();
47 case 4:
48 Dest = llvm::support::endian::read32(Bytes.data(), Stream.getEndian());
49 return Error::success();
50 case 8:
51 Dest = llvm::support::endian::read64(Bytes.data(), Stream.getEndian());
52 return Error::success();
53 }
54 llvm_unreachable("Unreachable!");
55 return Error::success();
56}
57
58Error BinaryStreamReader::readCString(StringRef &Dest) {
59 // TODO: This could be made more efficient by using readLongestContiguousChunk
60 // and searching for null terminators in the resulting buffer.
61
Zachary Turner8dbe3622016-05-27 01:54:44 +000062 uint32_t Length = 0;
63 // First compute the length of the string by reading 1 byte at a time.
64 uint32_t OriginalOffset = getOffset();
65 const char *C;
Zachary Turneraf299ea2017-02-25 00:44:30 +000066 while (true) {
Zachary Turner8dbe3622016-05-27 01:54:44 +000067 if (auto EC = readObject(C))
Zachary Turner819e77d2016-05-06 20:51:57 +000068 return EC;
Zachary Turneraf299ea2017-02-25 00:44:30 +000069 if (*C == '\0')
70 break;
71 ++Length;
72 }
Zachary Turner8dbe3622016-05-27 01:54:44 +000073 // Now go back and request a reference for that many bytes.
74 uint32_t NewOffset = getOffset();
75 setOffset(OriginalOffset);
76
Zachary Turneraf299ea2017-02-25 00:44:30 +000077 if (auto EC = readFixedString(Dest, Length))
Zachary Turner8dbe3622016-05-27 01:54:44 +000078 return EC;
Zachary Turner8dbe3622016-05-27 01:54:44 +000079
80 // Now set the offset back to where it was after we calculated the length.
81 setOffset(NewOffset);
Zachary Turner819e77d2016-05-06 20:51:57 +000082 return Error::success();
Zachary Turner6ba65de2016-04-29 17:22:58 +000083}
Zachary Turnerf5c59652016-05-03 00:28:21 +000084
Zachary Turneraf299ea2017-02-25 00:44:30 +000085Error BinaryStreamReader::readFixedString(StringRef &Dest, uint32_t Length) {
Zachary Turner8dbe3622016-05-27 01:54:44 +000086 ArrayRef<uint8_t> Bytes;
Zachary Turner0d43c1c2016-05-28 05:21:57 +000087 if (auto EC = readBytes(Bytes, Length))
Zachary Turnerf5c59652016-05-03 00:28:21 +000088 return EC;
Zachary Turner8dbe3622016-05-27 01:54:44 +000089 Dest = StringRef(reinterpret_cast<const char *>(Bytes.begin()), Bytes.size());
90 return Error::success();
91}
92
Zachary Turneraf299ea2017-02-25 00:44:30 +000093Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref) {
Zachary Turner8dbe3622016-05-27 01:54:44 +000094 return readStreamRef(Ref, bytesRemaining());
95}
96
Zachary Turneraf299ea2017-02-25 00:44:30 +000097Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref, uint32_t Length) {
Zachary Turner8dbe3622016-05-27 01:54:44 +000098 if (bytesRemaining() < Length)
Zachary Turneraf299ea2017-02-25 00:44:30 +000099 return errorCodeToError(make_error_code(std::errc::no_buffer_space));
Zachary Turnerf4e9c9a2016-06-02 19:51:48 +0000100 Ref = Stream.slice(Offset, Length);
Zachary Turnerf5c59652016-05-03 00:28:21 +0000101 Offset += Length;
Zachary Turner819e77d2016-05-06 20:51:57 +0000102 return Error::success();
Zachary Turnerf5c59652016-05-03 00:28:21 +0000103}
Zachary Turner4d49eb92016-10-20 18:31:19 +0000104
Zachary Turneraf299ea2017-02-25 00:44:30 +0000105Error BinaryStreamReader::skip(uint32_t Amount) {
Zachary Turner4d49eb92016-10-20 18:31:19 +0000106 if (Amount > bytesRemaining())
Zachary Turneraf299ea2017-02-25 00:44:30 +0000107 return errorCodeToError(make_error_code(std::errc::no_buffer_space));
Zachary Turner4d49eb92016-10-20 18:31:19 +0000108 Offset += Amount;
109 return Error::success();
110}
111
Zachary Turneraf299ea2017-02-25 00:44:30 +0000112uint8_t BinaryStreamReader::peek() const {
Zachary Turner4d49eb92016-10-20 18:31:19 +0000113 ArrayRef<uint8_t> Buffer;
114 auto EC = Stream.readBytes(Offset, 1, Buffer);
115 assert(!EC && "Cannot peek an empty buffer!");
116 llvm::consumeError(std::move(EC));
117 return Buffer[0];
118}