]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/Support/BinaryStreamWriter.h
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r303571, and update
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / Support / BinaryStreamWriter.h
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