Line data Source code
1 : //===- StreamReader.h - Reads bytes and objects from a stream ---*- C++ -*-===//
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 : #ifndef LLVM_DEBUGINFO_MSF_STREAMREADER_H
11 : #define LLVM_DEBUGINFO_MSF_STREAMREADER_H
12 :
13 : #include "llvm/ADT/ArrayRef.h"
14 : #include "llvm/DebugInfo/MSF/MSFError.h"
15 : #include "llvm/DebugInfo/MSF/StreamArray.h"
16 : #include "llvm/DebugInfo/MSF/StreamInterface.h"
17 : #include "llvm/DebugInfo/MSF/StreamRef.h"
18 : #include "llvm/Support/Endian.h"
19 : #include "llvm/Support/Error.h"
20 : #include "llvm/Support/type_traits.h"
21 :
22 : #include <string>
23 : #include <type_traits>
24 :
25 : namespace llvm {
26 : namespace msf {
27 :
28 : class StreamReader {
29 : public:
30 : StreamReader(ReadableStreamRef Stream);
31 :
32 : Error readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer);
33 : Error readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size);
34 :
35 : template <typename T>
36 44664 : Error readInteger(T &Dest,
37 : llvm::support::endianness Endian = llvm::support::native) {
38 : static_assert(std::is_integral<T>::value,
39 : "Cannot call readInteger with non-integral value!");
40 :
41 44664 : ArrayRef<uint8_t> Bytes;
42 133992 : if (auto EC = readBytes(Bytes, sizeof(T)))
43 0 : return EC;
44 :
45 46112 : Dest = llvm::support::endian::read<T, llvm::support::unaligned>(
46 44664 : Bytes.data(), Endian);
47 133992 : return Error::success();
48 : }
49 :
50 : Error readZeroString(StringRef &Dest);
51 : Error readFixedString(StringRef &Dest, uint32_t Length);
52 : Error readStreamRef(ReadableStreamRef &Ref);
53 : Error readStreamRef(ReadableStreamRef &Ref, uint32_t Length);
54 :
55 : template <typename T>
56 7594 : Error readEnum(T &Dest,
57 : llvm::support::endianness Endian = llvm::support::native) {
58 : static_assert(std::is_enum<T>::value,
59 : "Cannot call readEnum with non-enum value!");
60 : typename std::underlying_type<T>::type N;
61 22782 : if (auto EC = readInteger(N, Endian))
62 0 : return EC;
63 7594 : Dest = static_cast<T>(N);
64 22782 : return Error::success();
65 : }
66 :
67 697230 : template <typename T> Error readObject(const T *&Dest) {
68 697230 : ArrayRef<uint8_t> Buffer;
69 2091687 : if (auto EC = readBytes(Buffer, sizeof(T)))
70 6 : return EC;
71 697227 : Dest = reinterpret_cast<const T *>(Buffer.data());
72 2091681 : return Error::success();
73 : }
74 :
75 : template <typename T>
76 376 : Error readArray(ArrayRef<T> &Array, uint32_t NumElements) {
77 376 : ArrayRef<uint8_t> Bytes;
78 376 : if (NumElements == 0) {
79 45 : Array = ArrayRef<T>();
80 135 : return Error::success();
81 : }
82 :
83 330 : if (NumElements > UINT32_MAX / sizeof(T))
84 0 : return make_error<MSFError>(msf_error_code::insufficient_buffer);
85 :
86 993 : if (auto EC = readBytes(Bytes, NumElements * sizeof(T)))
87 0 : return EC;
88 331 : Array = ArrayRef<T>(reinterpret_cast<const T *>(Bytes.data()), NumElements);
89 993 : return Error::success();
90 : }
91 :
92 : template <typename T, typename U>
93 533 : Error readArray(VarStreamArray<T, U> &Array, uint32_t Size) {
94 533 : ReadableStreamRef S;
95 1599 : if (auto EC = readStreamRef(S, Size))
96 0 : return EC;
97 535 : Array = VarStreamArray<T, U>(S, Array.getExtractor());
98 1599 : return Error::success();
99 : }
100 :
101 : template <typename T>
102 135 : Error readArray(FixedStreamArray<T> &Array, uint32_t NumItems) {
103 135 : if (NumItems == 0) {
104 8 : Array = FixedStreamArray<T>();
105 12 : return Error::success();
106 : }
107 131 : uint32_t Length = NumItems * sizeof(T);
108 131 : if (Length / sizeof(T) != NumItems)
109 0 : return make_error<MSFError>(msf_error_code::invalid_format);
110 131 : if (Offset + Length > Stream.getLength())
111 0 : return make_error<MSFError>(msf_error_code::insufficient_buffer);
112 131 : ReadableStreamRef View = Stream.slice(Offset, Length);
113 131 : Array = FixedStreamArray<T>(View);
114 131 : Offset += Length;
115 393 : return Error::success();
116 : }
117 :
118 8818 : bool empty() const { return bytesRemaining() == 0; }
119 35634 : void setOffset(uint32_t Off) { Offset = Off; }
120 : uint32_t getOffset() const { return Offset; }
121 23742 : uint32_t getLength() const { return Stream.getLength(); }
122 23254 : uint32_t bytesRemaining() const { return getLength() - getOffset(); }
123 :
124 : Error skip(uint32_t Amount);
125 :
126 : uint8_t peek() const;
127 :
128 : private:
129 : ReadableStreamRef Stream;
130 : uint32_t Offset;
131 : };
132 : } // namespace msf
133 : } // namespace llvm
134 :
135 : #endif // LLVM_DEBUGINFO_MSF_STREAMREADER_H
|