Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/include/llvm/Support/BinaryStreamWriter.h
Line
Count
Source
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"
15
#include "llvm/Support/BinaryStreamArray.h"
16
#include "llvm/Support/BinaryStreamError.h"
17
#include "llvm/Support/BinaryStreamRef.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.
31
class BinaryStreamWriter {
32
public:
33
  BinaryStreamWriter() = default;
34
  explicit BinaryStreamWriter(WritableBinaryStreamRef Ref);
35
  explicit BinaryStreamWriter(WritableBinaryStream &Stream);
36
  explicit BinaryStreamWriter(MutableArrayRef<uint8_t> Data,
37
                              llvm::support::endianness Endian);
38
39
  BinaryStreamWriter(const BinaryStreamWriter &Other)
40
2.12k
      : Stream(Other.Stream), Offset(Other.Offset) {}
41
42
  BinaryStreamWriter &operator=(const BinaryStreamWriter &Other) {
43
    Stream = Other.Stream;
44
    Offset = Other.Offset;
45
    return *this;
46
  }
47
48
13.8k
  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.
56
  Error writeBytes(ArrayRef<uint8_t> Buffer);
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
77.1k
  template <typename T> Error writeInteger(T Value) {
65
77.1k
    static_assert(std::is_integral<T>::value,
66
77.1k
                  "Cannot call writeInteger with non-integral value!");
67
77.1k
    uint8_t Buffer[sizeof(T)];
68
77.1k
    llvm::support::endian::write<T, llvm::support::unaligned>(
69
77.1k
        Buffer, Value, Stream.getEndian());
70
77.1k
    return writeBytes(Buffer);
71
77.1k
  }
llvm::Error llvm::BinaryStreamWriter::writeInteger<char>(char)
Line
Count
Source
64
2.52k
  template <typename T> Error writeInteger(T Value) {
65
2.52k
    static_assert(std::is_integral<T>::value,
66
2.52k
                  "Cannot call writeInteger with non-integral value!");
67
2.52k
    uint8_t Buffer[sizeof(T)];
68
2.52k
    llvm::support::endian::write<T, llvm::support::unaligned>(
69
2.52k
        Buffer, Value, Stream.getEndian());
70
2.52k
    return writeBytes(Buffer);
71
2.52k
  }
llvm::Error llvm::BinaryStreamWriter::writeInteger<unsigned int>(unsigned int)
Line
Count
Source
64
17.3k
  template <typename T> Error writeInteger(T Value) {
65
17.3k
    static_assert(std::is_integral<T>::value,
66
17.3k
                  "Cannot call writeInteger with non-integral value!");
67
17.3k
    uint8_t Buffer[sizeof(T)];
68
17.3k
    llvm::support::endian::write<T, llvm::support::unaligned>(
69
17.3k
        Buffer, Value, Stream.getEndian());
70
17.3k
    return writeBytes(Buffer);
71
17.3k
  }
llvm::Error llvm::BinaryStreamWriter::writeInteger<unsigned char>(unsigned char)
Line
Count
Source
64
9.49k
  template <typename T> Error writeInteger(T Value) {
65
9.49k
    static_assert(std::is_integral<T>::value,
66
9.49k
                  "Cannot call writeInteger with non-integral value!");
67
9.49k
    uint8_t Buffer[sizeof(T)];
68
9.49k
    llvm::support::endian::write<T, llvm::support::unaligned>(
69
9.49k
        Buffer, Value, Stream.getEndian());
70
9.49k
    return writeBytes(Buffer);
71
9.49k
  }
llvm::Error llvm::BinaryStreamWriter::writeInteger<unsigned short>(unsigned short)
Line
Count
Source
64
47.2k
  template <typename T> Error writeInteger(T Value) {
65
47.2k
    static_assert(std::is_integral<T>::value,
66
47.2k
                  "Cannot call writeInteger with non-integral value!");
67
47.2k
    uint8_t Buffer[sizeof(T)];
68
47.2k
    llvm::support::endian::write<T, llvm::support::unaligned>(
69
47.2k
        Buffer, Value, Stream.getEndian());
70
47.2k
    return writeBytes(Buffer);
71
47.2k
  }
Unexecuted instantiation: llvm::Error llvm::BinaryStreamWriter::writeInteger<signed char>(signed char)
llvm::Error llvm::BinaryStreamWriter::writeInteger<short>(short)
Line
Count
Source
64
6
  template <typename T> Error writeInteger(T Value) {
65
6
    static_assert(std::is_integral<T>::value,
66
6
                  "Cannot call writeInteger with non-integral value!");
67
6
    uint8_t Buffer[sizeof(T)];
68
6
    llvm::support::endian::write<T, llvm::support::unaligned>(
69
6
        Buffer, Value, Stream.getEndian());
70
6
    return writeBytes(Buffer);
71
6
  }
llvm::Error llvm::BinaryStreamWriter::writeInteger<int>(int)
Line
Count
Source
64
517
  template <typename T> Error writeInteger(T Value) {
65
517
    static_assert(std::is_integral<T>::value,
66
517
                  "Cannot call writeInteger with non-integral value!");
67
517
    uint8_t Buffer[sizeof(T)];
68
517
    llvm::support::endian::write<T, llvm::support::unaligned>(
69
517
        Buffer, Value, Stream.getEndian());
70
517
    return writeBytes(Buffer);
71
517
  }
llvm::Error llvm::BinaryStreamWriter::writeInteger<long long>(long long)
Line
Count
Source
64
18
  template <typename T> Error writeInteger(T Value) {
65
18
    static_assert(std::is_integral<T>::value,
66
18
                  "Cannot call writeInteger with non-integral value!");
67
18
    uint8_t Buffer[sizeof(T)];
68
18
    llvm::support::endian::write<T, llvm::support::unaligned>(
69
18
        Buffer, Value, Stream.getEndian());
70
18
    return writeBytes(Buffer);
71
18
  }
llvm::Error llvm::BinaryStreamWriter::writeInteger<unsigned long long>(unsigned long long)
Line
Count
Source
64
5
  template <typename T> Error writeInteger(T Value) {
65
5
    static_assert(std::is_integral<T>::value,
66
5
                  "Cannot call writeInteger with non-integral value!");
67
5
    uint8_t Buffer[sizeof(T)];
68
5
    llvm::support::endian::write<T, llvm::support::unaligned>(
69
5
        Buffer, Value, Stream.getEndian());
70
5
    return writeBytes(Buffer);
71
5
  }
72
73
  /// Similar to writeInteger
74
12.5k
  template <typename T> Error writeEnum(T Num) {
75
12.5k
    static_assert(std::is_enum<T>::value,
76
12.5k
                  "Cannot call writeEnum with non-Enum type");
77
12.5k
78
12.5k
    using U = typename std::underlying_type<T>::type;
79
12.5k
    return writeInteger<U>(static_cast<U>(Num));
80
12.5k
  }
81
82
  /// Write the unsigned integer Value to the underlying stream using ULEB128
83
  /// encoding.
84
  ///
85
  /// \returns a success error code if the data was successfully written,
86
  /// otherwise returns an appropriate error code.
87
  Error writeULEB128(uint64_t Value);
88
89
  /// Write the unsigned integer Value to the underlying stream using ULEB128
90
  /// encoding.
91
  ///
92
  /// \returns a success error code if the data was successfully written,
93
  /// otherwise returns an appropriate error code.
94
  Error writeSLEB128(int64_t Value);
95
96
  /// Write the string \p Str to the underlying stream followed by a null
97
  /// terminator.  On success, updates the offset so that subsequent writes
98
  /// occur at the next unwritten position.  \p Str need not be null terminated
99
  /// on input.
100
  ///
101
  /// \returns a success error code if the data was successfully written,
102
  /// otherwise returns an appropriate error code.
103
  Error writeCString(StringRef Str);
104
105
  /// Write the string \p Str to the underlying stream without a null
106
  /// terminator.  On success, updates the offset so that subsequent writes
107
  /// occur at the next unwritten position.
108
  ///
109
  /// \returns a success error code if the data was successfully written,
110
  /// otherwise returns an appropriate error code.
111
  Error writeFixedString(StringRef Str);
112
113
  /// Efficiently reads all data from \p Ref, and writes it to this stream.
114
  /// This operation will not invoke any copies of the source data, regardless
115
  /// of the source stream's implementation.
116
  ///
117
  /// \returns a success error code if the data was successfully written,
118
  /// otherwise returns an appropriate error code.
119
  Error writeStreamRef(BinaryStreamRef Ref);
120
121
  /// Efficiently reads \p Size bytes from \p Ref, and writes it to this stream.
122
  /// This operation will not invoke any copies of the source data, regardless
123
  /// of the source stream's implementation.
124
  ///
125
  /// \returns a success error code if the data was successfully written,
126
  /// otherwise returns an appropriate error code.
127
  Error writeStreamRef(BinaryStreamRef Ref, uint32_t Size);
128
129
  /// Writes the object \p Obj to the underlying stream, as if by using memcpy.
130
  /// It is up to the caller to ensure that type of \p Obj can be safely copied
131
  /// in this fashion, as no checks are made to ensure that this is safe.
132
  ///
133
  /// \returns a success error code if the data was successfully written,
134
  /// otherwise returns an appropriate error code.
135
25.9k
  template <typename T> Error writeObject(const T &Obj) {
136
25.9k
    static_assert(!std::is_pointer<T>::value,
137
25.9k
                  "writeObject should not be used with pointers, to write "
138
25.9k
                  "the pointed-to value dereference the pointer before calling "
139
25.9k
                  "writeObject");
140
25.9k
    return writeBytes(
141
25.9k
        ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&Obj), sizeof(T)));
142
25.9k
  }
llvm::Error llvm::BinaryStreamWriter::writeObject<char>(char const&)
Line
Count
Source
135
18.9k
  template <typename T> Error writeObject(const T &Obj) {
136
18.9k
    static_assert(!std::is_pointer<T>::value,
137
18.9k
                  "writeObject should not be used with pointers, to write "
138
18.9k
                  "the pointed-to value dereference the pointer before calling "
139
18.9k
                  "writeObject");
140
18.9k
    return writeBytes(
141
18.9k
        ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&Obj), sizeof(T)));
142
18.9k
  }
llvm::Error llvm::BinaryStreamWriter::writeObject<llvm::codeview::RecordPrefix>(llvm::codeview::RecordPrefix const&)
Line
Count
Source
135
6.76k
  template <typename T> Error writeObject(const T &Obj) {
136
6.76k
    static_assert(!std::is_pointer<T>::value,
137
6.76k
                  "writeObject should not be used with pointers, to write "
138
6.76k
                  "the pointed-to value dereference the pointer before calling "
139
6.76k
                  "writeObject");
140
6.76k
    return writeBytes(
141
6.76k
        ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&Obj), sizeof(T)));
142
6.76k
  }
llvm::Error llvm::BinaryStreamWriter::writeObject<llvm::support::detail::packed_endian_specific_integral<unsigned short, (llvm::support::endianness)1, 1ul> >(llvm::support::detail::packed_endian_specific_integral<unsigned short, (llvm::support::endianness)1, 1ul> const&)
Line
Count
Source
135
26
  template <typename T> Error writeObject(const T &Obj) {
136
26
    static_assert(!std::is_pointer<T>::value,
137
26
                  "writeObject should not be used with pointers, to write "
138
26
                  "the pointed-to value dereference the pointer before calling "
139
26
                  "writeObject");
140
26
    return writeBytes(
141
26
        ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&Obj), sizeof(T)));
142
26
  }
llvm::Error llvm::BinaryStreamWriter::writeObject<llvm::support::detail::packed_endian_specific_integral<int, (llvm::support::endianness)1, 1ul> >(llvm::support::detail::packed_endian_specific_integral<int, (llvm::support::endianness)1, 1ul> const&)
Line
Count
Source
135
4
  template <typename T> Error writeObject(const T &Obj) {
136
4
    static_assert(!std::is_pointer<T>::value,
137
4
                  "writeObject should not be used with pointers, to write "
138
4
                  "the pointed-to value dereference the pointer before calling "
139
4
                  "writeObject");
140
4
    return writeBytes(
141
4
        ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&Obj), sizeof(T)));
142
4
  }
llvm::Error llvm::BinaryStreamWriter::writeObject<llvm::support::detail::packed_endian_specific_integral<unsigned int, (llvm::support::endianness)1, 1ul> >(llvm::support::detail::packed_endian_specific_integral<unsigned int, (llvm::support::endianness)1, 1ul> const&)
Line
Count
Source
135
268
  template <typename T> Error writeObject(const T &Obj) {
136
268
    static_assert(!std::is_pointer<T>::value,
137
268
                  "writeObject should not be used with pointers, to write "
138
268
                  "the pointed-to value dereference the pointer before calling "
139
268
                  "writeObject");
140
268
    return writeBytes(
141
268
        ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&Obj), sizeof(T)));
142
268
  }
143
144
  /// Writes an array of objects of type T to the underlying stream, as if by
145
  /// using memcpy.  It is up to the caller to ensure that type of \p Obj can
146
  /// be safely copied in this fashion, as no checks are made to ensure that
147
  /// this is safe.
148
  ///
149
  /// \returns a success error code if the data was successfully written,
150
  /// otherwise returns an appropriate error code.
151
  template <typename T> Error writeArray(ArrayRef<T> Array) {
152
    if (Array.empty())
153
      return Error::success();
154
    if (Array.size() > UINT32_MAX / sizeof(T))
155
      return make_error<BinaryStreamError>(
156
          stream_error_code::invalid_array_size);
157
158
    return writeBytes(
159
        ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Array.data()),
160
                          Array.size() * sizeof(T)));
161
  }
162
163
  /// Writes all data from the array \p Array to the underlying stream.
164
  ///
165
  /// \returns a success error code if the data was successfully written,
166
  /// otherwise returns an appropriate error code.
167
  template <typename T, typename U>
168
  Error writeArray(VarStreamArray<T, U> Array) {
169
    return writeStreamRef(Array.getUnderlyingStream());
170
  }
171
172
  /// Writes all elements from the array \p Array to the underlying stream.
173
  ///
174
  /// \returns a success error code if the data was successfully written,
175
  /// otherwise returns an appropriate error code.
176
  template <typename T> Error writeArray(FixedStreamArray<T> Array) {
177
    return writeStreamRef(Array.getUnderlyingStream());
178
  }
179
180
  /// Splits the Writer into two Writers at a given offset.
181
  std::pair<BinaryStreamWriter, BinaryStreamWriter> split(uint32_t Off) const;
182
183
4.63k
  void setOffset(uint32_t Off) { Offset = Off; }
184
95.8k
  uint32_t getOffset() const { return Offset; }
185
3.90k
  uint32_t getLength() const { return Stream.getLength(); }
186
  uint32_t bytesRemaining() const { return getLength() - getOffset(); }
187
  Error padToAlignment(uint32_t Align);
188
189
protected:
190
  WritableBinaryStreamRef Stream;
191
  uint32_t Offset = 0;
192
};
193
194
} // end namespace llvm
195
196
#endif // LLVM_SUPPORT_BINARYSTREAMWRITER_H