]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Support/BinaryStreamReader.cpp
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r303571, and update
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Support / BinaryStreamReader.cpp
1 //===- BinaryStreamReader.cpp - Reads objects from a binary stream --------===//
2 //
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
10 #include "llvm/Support/BinaryStreamReader.h"
11
12 #include "llvm/Support/BinaryStreamError.h"
13 #include "llvm/Support/BinaryStreamRef.h"
14
15 using namespace llvm;
16 using endianness = llvm::support::endianness;
17
18 BinaryStreamReader::BinaryStreamReader(BinaryStreamRef Ref) : Stream(Ref) {}
19
20 BinaryStreamReader::BinaryStreamReader(BinaryStream &Stream) : Stream(Stream) {}
21
22 BinaryStreamReader::BinaryStreamReader(ArrayRef<uint8_t> Data,
23                                        endianness Endian)
24     : Stream(Data, Endian) {}
25
26 BinaryStreamReader::BinaryStreamReader(StringRef Data, endianness Endian)
27     : Stream(Data, Endian) {}
28
29 Error BinaryStreamReader::readLongestContiguousChunk(
30     ArrayRef<uint8_t> &Buffer) {
31   if (auto EC = Stream.readLongestContiguousChunk(Offset, Buffer))
32     return EC;
33   Offset += Buffer.size();
34   return Error::success();
35 }
36
37 Error BinaryStreamReader::readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size) {
38   if (auto EC = Stream.readBytes(Offset, Size, Buffer))
39     return EC;
40   Offset += Size;
41   return Error::success();
42 }
43
44 Error BinaryStreamReader::readCString(StringRef &Dest) {
45   // TODO: This could be made more efficient by using readLongestContiguousChunk
46   // and searching for null terminators in the resulting buffer.
47
48   uint32_t Length = 0;
49   // First compute the length of the string by reading 1 byte at a time.
50   uint32_t OriginalOffset = getOffset();
51   const char *C;
52   while (true) {
53     if (auto EC = readObject(C))
54       return EC;
55     if (*C == '\0')
56       break;
57     ++Length;
58   }
59   // Now go back and request a reference for that many bytes.
60   uint32_t NewOffset = getOffset();
61   setOffset(OriginalOffset);
62
63   if (auto EC = readFixedString(Dest, Length))
64     return EC;
65
66   // Now set the offset back to where it was after we calculated the length.
67   setOffset(NewOffset);
68   return Error::success();
69 }
70
71 Error BinaryStreamReader::readFixedString(StringRef &Dest, uint32_t Length) {
72   ArrayRef<uint8_t> Bytes;
73   if (auto EC = readBytes(Bytes, Length))
74     return EC;
75   Dest = StringRef(reinterpret_cast<const char *>(Bytes.begin()), Bytes.size());
76   return Error::success();
77 }
78
79 Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref) {
80   return readStreamRef(Ref, bytesRemaining());
81 }
82
83 Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref, uint32_t Length) {
84   if (bytesRemaining() < Length)
85     return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
86   Ref = Stream.slice(Offset, Length);
87   Offset += Length;
88   return Error::success();
89 }
90
91 Error BinaryStreamReader::skip(uint32_t Amount) {
92   if (Amount > bytesRemaining())
93     return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
94   Offset += Amount;
95   return Error::success();
96 }
97
98 Error BinaryStreamReader::padToAlignment(uint32_t Align) {
99   uint32_t NewOffset = alignTo(Offset, Align);
100   return skip(NewOffset - Offset);
101 }
102
103 uint8_t BinaryStreamReader::peek() const {
104   ArrayRef<uint8_t> Buffer;
105   auto EC = Stream.readBytes(Offset, 1, Buffer);
106   assert(!EC && "Cannot peek an empty buffer!");
107   llvm::consumeError(std::move(EC));
108   return Buffer[0];
109 }
110
111 std::pair<BinaryStreamReader, BinaryStreamReader>
112 BinaryStreamReader::split(uint32_t Off) const {
113   assert(getLength() >= Off);
114
115   BinaryStreamRef First = Stream.drop_front(Offset);
116
117   BinaryStreamRef Second = First.drop_front(Off);
118   First = First.keep_front(Off);
119   BinaryStreamReader W1{First};
120   BinaryStreamReader W2{Second};
121   return std::make_pair(W1, W2);
122 }