comparison include/llvm/Support/BinaryStreamWriter.h @ 121:803732b1fca8

LLVM 5.0
author kono
date Fri, 27 Oct 2017 17:07:41 +0900
parents
children 3a76565eade5
comparison
equal deleted inserted replaced
120:1172e4bd9c6f 121:803732b1fca8
1 //===- BinaryStreamWriter.h - Writes objects to a BinaryStream ---*- 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_SUPPORT_BINARYSTREAMWRITER_H
11 #define LLVM_SUPPORT_BINARYSTREAMWRITER_H
12
13 #include "llvm/ADT/ArrayRef.h"
14 #include "llvm/ADT/STLExtras.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/Support/BinaryStreamArray.h"
17 #include "llvm/Support/BinaryStreamError.h"
18 #include "llvm/Support/BinaryStreamRef.h"
19 #include "llvm/Support/Endian.h"
20 #include "llvm/Support/Error.h"
21 #include <cstdint>
22 #include <type_traits>
23 #include <utility>
24
25 namespace llvm {
26
27 /// \brief Provides write only access to a subclass of `WritableBinaryStream`.
28 /// Provides bounds checking and helpers for writing certain common data types
29 /// such as null-terminated strings, integers in various flavors of endianness,
30 /// etc. Can be subclassed to provide reading and writing of custom datatypes,
31 /// although no methods are overridable.
32 class BinaryStreamWriter {
33 public:
34 BinaryStreamWriter() = default;
35 explicit BinaryStreamWriter(WritableBinaryStreamRef Ref);
36 explicit BinaryStreamWriter(WritableBinaryStream &Stream);
37 explicit BinaryStreamWriter(MutableArrayRef<uint8_t> Data,
38 llvm::support::endianness Endian);
39
40 BinaryStreamWriter(const BinaryStreamWriter &Other)
41 : Stream(Other.Stream), Offset(Other.Offset) {}
42
43 BinaryStreamWriter &operator=(const BinaryStreamWriter &Other) {
44 Stream = Other.Stream;
45 Offset = Other.Offset;
46 return *this;
47 }
48
49 virtual ~BinaryStreamWriter() {}
50
51 /// Write the bytes specified in \p Buffer to the underlying stream.
52 /// On success, updates the offset so that subsequent writes will occur
53 /// at the next unwritten position.
54 ///
55 /// \returns a success error code if the data was successfully written,
56 /// otherwise returns an appropriate error code.
57 Error writeBytes(ArrayRef<uint8_t> Buffer);
58
59 /// Write the the integer \p Value to the underlying stream in the
60 /// specified endianness. On success, updates the offset so that
61 /// subsequent writes occur at the next unwritten position.
62 ///
63 /// \returns a success error code if the data was successfully written,
64 /// otherwise returns an appropriate error code.
65 template <typename T> Error writeInteger(T Value) {
66 static_assert(std::is_integral<T>::value,
67 "Cannot call writeInteger with non-integral value!");
68 uint8_t Buffer[sizeof(T)];
69 llvm::support::endian::write<T, llvm::support::unaligned>(
70 Buffer, Value, Stream.getEndian());
71 return writeBytes(Buffer);
72 }
73
74 /// Similar to writeInteger
75 template <typename T> Error writeEnum(T Num) {
76 static_assert(std::is_enum<T>::value,
77 "Cannot call writeEnum with non-Enum type");
78
79 using U = typename std::underlying_type<T>::type;
80 return writeInteger<U>(static_cast<U>(Num));
81 }
82
83 /// Write the the string \p Str to the underlying stream followed by a null
84 /// terminator. On success, updates the offset so that subsequent writes
85 /// occur at the next unwritten position. \p Str need not be null terminated
86 /// on input.
87 ///
88 /// \returns a success error code if the data was successfully written,
89 /// otherwise returns an appropriate error code.
90 Error writeCString(StringRef Str);
91
92 /// Write the the string \p Str to the underlying stream without a null
93 /// terminator. On success, updates the offset so that subsequent writes
94 /// occur at the next unwritten position.
95 ///
96 /// \returns a success error code if the data was successfully written,
97 /// otherwise returns an appropriate error code.
98 Error writeFixedString(StringRef Str);
99
100 /// Efficiently reads all data from \p Ref, and writes it to this stream.
101 /// This operation will not invoke any copies of the source data, regardless
102 /// of the source stream's implementation.
103 ///
104 /// \returns a success error code if the data was successfully written,
105 /// otherwise returns an appropriate error code.
106 Error writeStreamRef(BinaryStreamRef Ref);
107
108 /// Efficiently reads \p Size bytes from \p Ref, and writes it to this stream.
109 /// This operation will not invoke any copies of the source data, regardless
110 /// of the source stream's implementation.
111 ///
112 /// \returns a success error code if the data was successfully written,
113 /// otherwise returns an appropriate error code.
114 Error writeStreamRef(BinaryStreamRef Ref, uint32_t Size);
115
116 /// Writes the object \p Obj to the underlying stream, as if by using memcpy.
117 /// It is up to the caller to ensure that type of \p Obj can be safely copied
118 /// in this fashion, as no checks are made to ensure that this is safe.
119 ///
120 /// \returns a success error code if the data was successfully written,
121 /// otherwise returns an appropriate error code.
122 template <typename T> Error writeObject(const T &Obj) {
123 static_assert(!std::is_pointer<T>::value,
124 "writeObject should not be used with pointers, to write "
125 "the pointed-to value dereference the pointer before calling "
126 "writeObject");
127 return writeBytes(
128 ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&Obj), sizeof(T)));
129 }
130
131 /// Writes an array of objects of type T to the underlying stream, as if by
132 /// using memcpy. It is up to the caller to ensure that type of \p Obj can
133 /// be safely copied in this fashion, as no checks are made to ensure that
134 /// this is safe.
135 ///
136 /// \returns a success error code if the data was successfully written,
137 /// otherwise returns an appropriate error code.
138 template <typename T> Error writeArray(ArrayRef<T> Array) {
139 if (Array.empty())
140 return Error::success();
141 if (Array.size() > UINT32_MAX / sizeof(T))
142 return make_error<BinaryStreamError>(
143 stream_error_code::invalid_array_size);
144
145 return writeBytes(
146 ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Array.data()),
147 Array.size() * sizeof(T)));
148 }
149
150 /// Writes all data from the array \p Array to the underlying stream.
151 ///
152 /// \returns a success error code if the data was successfully written,
153 /// otherwise returns an appropriate error code.
154 template <typename T, typename U>
155 Error writeArray(VarStreamArray<T, U> Array) {
156 return writeStreamRef(Array.getUnderlyingStream());
157 }
158
159 /// Writes all elements from the array \p Array to the underlying stream.
160 ///
161 /// \returns a success error code if the data was successfully written,
162 /// otherwise returns an appropriate error code.
163 template <typename T> Error writeArray(FixedStreamArray<T> Array) {
164 return writeStreamRef(Array.getUnderlyingStream());
165 }
166
167 /// Splits the Writer into two Writers at a given offset.
168 std::pair<BinaryStreamWriter, BinaryStreamWriter> split(uint32_t Off) const;
169
170 void setOffset(uint32_t Off) { Offset = Off; }
171 uint32_t getOffset() const { return Offset; }
172 uint32_t getLength() const { return Stream.getLength(); }
173 uint32_t bytesRemaining() const { return getLength() - getOffset(); }
174 Error padToAlignment(uint32_t Align);
175
176 protected:
177 WritableBinaryStreamRef Stream;
178 uint32_t Offset = 0;
179 };
180
181 } // end namespace llvm
182
183 #endif // LLVM_SUPPORT_BINARYSTREAMWRITER_H