Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

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