LLVM  9.0.0svn
BinaryStreamWriter.h
Go to the documentation of this file.
1 //===- BinaryStreamWriter.h - Writes objects to a BinaryStream ---*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_SUPPORT_BINARYSTREAMWRITER_H
10 #define LLVM_SUPPORT_BINARYSTREAMWRITER_H
11 
12 #include "llvm/ADT/ArrayRef.h"
13 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/ADT/StringRef.h"
18 #include "llvm/Support/Endian.h"
19 #include "llvm/Support/Error.h"
20 #include <cstdint>
21 #include <type_traits>
22 #include <utility>
23 
24 namespace llvm {
25 
26 /// Provides write only access to a subclass of `WritableBinaryStream`.
27 /// Provides bounds checking and helpers for writing certain common data types
28 /// such as null-terminated strings, integers in various flavors of endianness,
29 /// etc. Can be subclassed to provide reading and writing of custom datatypes,
30 /// although no methods are overridable.
32 public:
33  BinaryStreamWriter() = default;
38 
40  : Stream(Other.Stream), Offset(Other.Offset) {}
41 
43  Stream = Other.Stream;
44  Offset = Other.Offset;
45  return *this;
46  }
47 
48  virtual ~BinaryStreamWriter() {}
49 
50  /// Write the bytes specified in \p Buffer to the underlying stream.
51  /// On success, updates the offset so that subsequent writes will occur
52  /// at the next unwritten position.
53  ///
54  /// \returns a success error code if the data was successfully written,
55  /// otherwise returns an appropriate error code.
57 
58  /// Write the integer \p Value to the underlying stream in the
59  /// specified endianness. On success, updates the offset so that
60  /// subsequent writes occur at the next unwritten position.
61  ///
62  /// \returns a success error code if the data was successfully written,
63  /// otherwise returns an appropriate error code.
64  template <typename T> Error writeInteger(T Value) {
65  static_assert(std::is_integral<T>::value,
66  "Cannot call writeInteger with non-integral value!");
67  uint8_t Buffer[sizeof(T)];
68  llvm::support::endian::write<T, llvm::support::unaligned>(
69  Buffer, Value, Stream.getEndian());
70  return writeBytes(Buffer);
71  }
72 
73  /// Similar to writeInteger
74  template <typename T> Error writeEnum(T Num) {
75  static_assert(std::is_enum<T>::value,
76  "Cannot call writeEnum with non-Enum type");
77 
78  using U = typename std::underlying_type<T>::type;
79  return writeInteger<U>(static_cast<U>(Num));
80  }
81 
82  /// Write the string \p Str to the underlying stream followed by a null
83  /// terminator. On success, updates the offset so that subsequent writes
84  /// occur at the next unwritten position. \p Str need not be null terminated
85  /// on input.
86  ///
87  /// \returns a success error code if the data was successfully written,
88  /// otherwise returns an appropriate error code.
90 
91  /// Write the string \p Str to the underlying stream without a null
92  /// terminator. On success, updates the offset so that subsequent writes
93  /// occur at the next unwritten position.
94  ///
95  /// \returns a success error code if the data was successfully written,
96  /// otherwise returns an appropriate error code.
98 
99  /// Efficiently reads all data from \p Ref, and writes it to this stream.
100  /// This operation will not invoke any copies of the source data, regardless
101  /// of the source stream's implementation.
102  ///
103  /// \returns a success error code if the data was successfully written,
104  /// otherwise returns an appropriate error code.
106 
107  /// Efficiently reads \p Size bytes from \p Ref, and writes it to this stream.
108  /// This operation will not invoke any copies of the source data, regardless
109  /// of the source stream's implementation.
110  ///
111  /// \returns a success error code if the data was successfully written,
112  /// otherwise returns an appropriate error code.
114 
115  /// Writes the object \p Obj to the underlying stream, as if by using memcpy.
116  /// It is up to the caller to ensure that type of \p Obj can be safely copied
117  /// in this fashion, as no checks are made to ensure that this is safe.
118  ///
119  /// \returns a success error code if the data was successfully written,
120  /// otherwise returns an appropriate error code.
121  template <typename T> Error writeObject(const T &Obj) {
122  static_assert(!std::is_pointer<T>::value,
123  "writeObject should not be used with pointers, to write "
124  "the pointed-to value dereference the pointer before calling "
125  "writeObject");
126  return writeBytes(
127  ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&Obj), sizeof(T)));
128  }
129 
130  /// Writes an array of objects of type T to the underlying stream, as if by
131  /// using memcpy. It is up to the caller to ensure that type of \p Obj can
132  /// be safely copied in this fashion, as no checks are made to ensure that
133  /// this is safe.
134  ///
135  /// \returns a success error code if the data was successfully written,
136  /// otherwise returns an appropriate error code.
137  template <typename T> Error writeArray(ArrayRef<T> Array) {
138  if (Array.empty())
139  return Error::success();
140  if (Array.size() > UINT32_MAX / sizeof(T))
141  return make_error<BinaryStreamError>(
143 
144  return writeBytes(
145  ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Array.data()),
146  Array.size() * sizeof(T)));
147  }
148 
149  /// Writes all data from the array \p Array to the underlying stream.
150  ///
151  /// \returns a success error code if the data was successfully written,
152  /// otherwise returns an appropriate error code.
153  template <typename T, typename U>
155  return writeStreamRef(Array.getUnderlyingStream());
156  }
157 
158  /// Writes all elements from the array \p Array to the underlying stream.
159  ///
160  /// \returns a success error code if the data was successfully written,
161  /// otherwise returns an appropriate error code.
162  template <typename T> Error writeArray(FixedStreamArray<T> Array) {
163  return writeStreamRef(Array.getUnderlyingStream());
164  }
165 
166  /// Splits the Writer into two Writers at a given offset.
167  std::pair<BinaryStreamWriter, BinaryStreamWriter> split(uint32_t Off) const;
168 
169  void setOffset(uint32_t Off) { Offset = Off; }
170  uint32_t getOffset() const { return Offset; }
171  uint32_t getLength() const { return Stream.getLength(); }
172  uint32_t bytesRemaining() const { return getLength() - getOffset(); }
174 
175 protected:
178 };
179 
180 } // end namespace llvm
181 
182 #endif // LLVM_SUPPORT_BINARYSTREAMWRITER_H
Error writeObject(const T &Obj)
Writes the object Obj to the underlying stream, as if by using memcpy.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
Error writeBytes(ArrayRef< uint8_t > Buffer)
Write the bytes specified in Buffer to the underlying stream.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
BinaryStreamWriter(const BinaryStreamWriter &Other)
BinaryStreamWriter & operator=(const BinaryStreamWriter &Other)
BinaryStreamRef getUnderlyingStream() const
FixedStreamArray is similar to VarStreamArray, except with each record having a fixed-length.
The access may reference the value stored in memory.
Error writeArray(VarStreamArray< T, U > Array)
Writes all data from the array Array to the underlying stream.
Error writeFixedString(StringRef Str)
Write the string Str to the underlying stream without a null terminator.
virtual uint32_t getLength()=0
Return the number of bytes of data in this stream.
#define T
Error writeArray(ArrayRef< T > Array)
Writes an array of objects of type T to the underlying stream, as if by using memcpy.
virtual llvm::support::endianness getEndian() const =0
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:148
Error writeArray(FixedStreamArray< T > Array)
Writes all elements from the array Array to the underlying stream.
Error writeStreamRef(BinaryStreamRef Ref)
Efficiently reads all data from Ref, and writes it to this stream.
WritableBinaryStreamRef Stream
Provides write only access to a subclass of WritableBinaryStream.
Error writeInteger(T Value)
Write the integer Value to the underlying stream in the specified endianness.
const T * data() const
Definition: ArrayRef.h:145
uint32_t bytesRemaining() const
Error writeCString(StringRef Str)
Write the string Str to the underlying stream followed by a null terminator.
static ErrorSuccess success()
Create a success value.
Definition: Error.h:326
BinaryStreamRef is to BinaryStream what ArrayRef is to an Array.
std::pair< BinaryStreamWriter, BinaryStreamWriter > split(uint32_t Off) const
Splits the Writer into two Writers at a given offset.
Error writeEnum(T Num)
Similar to writeInteger.
void setOffset(uint32_t Off)
BinaryStreamRef getUnderlyingStream() const
Error padToAlignment(uint32_t Align)
uint32_t Size
Definition: Profile.cpp:46
LLVM Value Representation.
Definition: Value.h:72
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:143
A BinaryStream which can be read from as well as written to.
Definition: BinaryStream.h:73