Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/include/llvm/Support/BinaryByteStream.h
Line
Count
Source (jump to first uncovered line)
1
//===- BinaryByteStream.h ---------------------------------------*- 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
// A BinaryStream which stores data in a single continguous memory buffer.
8
//===----------------------------------------------------------------------===//
9
10
#ifndef LLVM_SUPPORT_BINARYBYTESTREAM_H
11
#define LLVM_SUPPORT_BINARYBYTESTREAM_H
12
13
#include "llvm/ADT/ArrayRef.h"
14
#include "llvm/ADT/StringRef.h"
15
#include "llvm/Support/BinaryStream.h"
16
#include "llvm/Support/BinaryStreamError.h"
17
#include "llvm/Support/Error.h"
18
#include "llvm/Support/FileOutputBuffer.h"
19
#include "llvm/Support/MemoryBuffer.h"
20
#include <algorithm>
21
#include <cstdint>
22
#include <cstring>
23
#include <memory>
24
25
namespace llvm {
26
27
/// An implementation of BinaryStream which holds its entire data set
28
/// in a single contiguous buffer.  BinaryByteStream guarantees that no read
29
/// operation will ever incur a copy.  Note that BinaryByteStream does not
30
/// own the underlying buffer.
31
class BinaryByteStream : public BinaryStream {
32
public:
33
822
  BinaryByteStream() = default;
34
  BinaryByteStream(ArrayRef<uint8_t> Data, llvm::support::endianness Endian)
35
42.0k
      : Endian(Endian), Data(Data) {}
36
  BinaryByteStream(StringRef Data, llvm::support::endianness Endian)
37
218
      : Endian(Endian), Data(Data.bytes_begin(), Data.bytes_end()) {}
38
39
247k
  llvm::support::endianness getEndian() const override { return Endian; }
40
41
  Error readBytes(uint32_t Offset, uint32_t Size,
42
524k
                  ArrayRef<uint8_t> &Buffer) override {
43
524k
    if (auto EC = checkOffsetForRead(Offset, Size))
44
3
      return EC;
45
524k
    Buffer = Data.slice(Offset, Size);
46
524k
    return Error::success();
47
524k
  }
48
49
  Error readLongestContiguousChunk(uint32_t Offset,
50
57.1k
                                   ArrayRef<uint8_t> &Buffer) override {
51
57.1k
    if (auto EC = checkOffsetForRead(Offset, 1))
52
0
      return EC;
53
57.1k
    Buffer = Data.slice(Offset);
54
57.1k
    return Error::success();
55
57.1k
  }
56
57
1.34M
  uint32_t getLength() override { return Data.size(); }
58
59
0
  ArrayRef<uint8_t> data() const { return Data; }
60
61
0
  StringRef str() const {
62
0
    const char *CharData = reinterpret_cast<const char *>(Data.data());
63
0
    return StringRef(CharData, Data.size());
64
0
  }
65
66
protected:
67
  llvm::support::endianness Endian;
68
  ArrayRef<uint8_t> Data;
69
};
70
71
/// An implementation of BinaryStream whose data is backed by an llvm
72
/// MemoryBuffer object.  MemoryBufferByteStream owns the MemoryBuffer in
73
/// question.  As with BinaryByteStream, reading from a MemoryBufferByteStream
74
/// will never cause a copy.
75
class MemoryBufferByteStream : public BinaryByteStream {
76
public:
77
  MemoryBufferByteStream(std::unique_ptr<MemoryBuffer> Buffer,
78
                         llvm::support::endianness Endian)
79
      : BinaryByteStream(Buffer->getBuffer(), Endian),
80
157
        MemBuffer(std::move(Buffer)) {}
81
82
  std::unique_ptr<MemoryBuffer> MemBuffer;
83
};
84
85
/// An implementation of BinaryStream which holds its entire data set
86
/// in a single contiguous buffer.  As with BinaryByteStream, the mutable
87
/// version also guarantees that no read operation will ever incur a copy,
88
/// and similarly it does not own the underlying buffer.
89
class MutableBinaryByteStream : public WritableBinaryStream {
90
public:
91
137
  MutableBinaryByteStream() = default;
92
  MutableBinaryByteStream(MutableArrayRef<uint8_t> Data,
93
                          llvm::support::endianness Endian)
94
6.80k
      : Data(Data), ImmutableStream(Data, Endian) {}
95
96
31.1k
  llvm::support::endianness getEndian() const override {
97
31.1k
    return ImmutableStream.getEndian();
98
31.1k
  }
99
100
  Error readBytes(uint32_t Offset, uint32_t Size,
101
74
                  ArrayRef<uint8_t> &Buffer) override {
102
74
    return ImmutableStream.readBytes(Offset, Size, Buffer);
103
74
  }
104
105
  Error readLongestContiguousChunk(uint32_t Offset,
106
132
                                   ArrayRef<uint8_t> &Buffer) override {
107
132
    return ImmutableStream.readLongestContiguousChunk(Offset, Buffer);
108
132
  }
109
110
144k
  uint32_t getLength() override { return ImmutableStream.getLength(); }
111
112
70.6k
  Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) override {
113
70.6k
    if (Buffer.empty())
114
119
      return Error::success();
115
70.5k
116
70.5k
    if (auto EC = checkOffsetForWrite(Offset, Buffer.size()))
117
3
      return EC;
118
70.5k
119
70.5k
    uint8_t *DataPtr = const_cast<uint8_t *>(Data.data());
120
70.5k
    ::memcpy(DataPtr + Offset, Buffer.data(), Buffer.size());
121
70.5k
    return Error::success();
122
70.5k
  }
123
124
0
  Error commit() override { return Error::success(); }
125
126
0
  MutableArrayRef<uint8_t> data() const { return Data; }
127
128
private:
129
  MutableArrayRef<uint8_t> Data;
130
  BinaryByteStream ImmutableStream;
131
};
132
133
/// An implementation of WritableBinaryStream which can write at its end
134
/// causing the underlying data to grow.  This class owns the underlying data.
135
class AppendingBinaryByteStream : public WritableBinaryStream {
136
  std::vector<uint8_t> Data;
137
  llvm::support::endianness Endian = llvm::support::little;
138
139
public:
140
403
  AppendingBinaryByteStream() = default;
141
  AppendingBinaryByteStream(llvm::support::endianness Endian)
142
      : Endian(Endian) {}
143
144
374
  void clear() { Data.clear(); }
145
146
42.0k
  llvm::support::endianness getEndian() const override { return Endian; }
147
148
  Error readBytes(uint32_t Offset, uint32_t Size,
149
6
                  ArrayRef<uint8_t> &Buffer) override {
150
6
    if (auto EC = checkOffsetForWrite(Offset, Buffer.size()))
151
0
      return EC;
152
6
153
6
    Buffer = makeArrayRef(Data).slice(Offset, Size);
154
6
    return Error::success();
155
6
  }
156
157
8
  void insert(uint32_t Offset, ArrayRef<uint8_t> Bytes) {
158
8
    Data.insert(Data.begin() + Offset, Bytes.begin(), Bytes.end());
159
8
  }
160
161
  Error readLongestContiguousChunk(uint32_t Offset,
162
5
                                   ArrayRef<uint8_t> &Buffer) override {
163
5
    if (auto EC = checkOffsetForWrite(Offset, 1))
164
0
      return EC;
165
5
166
5
    Buffer = makeArrayRef(Data).slice(Offset);
167
5
    return Error::success();
168
5
  }
169
170
134k
  uint32_t getLength() override { return Data.size(); }
171
172
67.3k
  Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) override {
173
67.3k
    if (Buffer.empty())
174
6
      return Error::success();
175
67.3k
176
67.3k
    // This is well-defined for any case except where offset is strictly
177
67.3k
    // greater than the current length.  If offset is equal to the current
178
67.3k
    // length, we can still grow.  If offset is beyond the current length, we
179
67.3k
    // would have to decide how to deal with the intermediate uninitialized
180
67.3k
    // bytes.  So we punt on that case for simplicity and just say it's an
181
67.3k
    // error.
182
67.3k
    if (Offset > getLength())
183
1
      return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
184
67.3k
185
67.3k
    uint32_t RequiredSize = Offset + Buffer.size();
186
67.3k
    if (RequiredSize > Data.size())
187
67.3k
      Data.resize(RequiredSize);
188
67.3k
189
67.3k
    ::memcpy(Data.data() + Offset, Buffer.data(), Buffer.size());
190
67.3k
    return Error::success();
191
67.3k
  }
192
193
0
  Error commit() override { return Error::success(); }
194
195
  /// Return the properties of this stream.
196
67.8k
  virtual BinaryStreamFlags getFlags() const override {
197
67.8k
    return BSF_Write | BSF_Append;
198
67.8k
  }
199
200
382
  MutableArrayRef<uint8_t> data() { return Data; }
201
};
202
203
/// An implementation of WritableBinaryStream backed by an llvm
204
/// FileOutputBuffer.
205
class FileBufferByteStream : public WritableBinaryStream {
206
private:
207
  class StreamImpl : public MutableBinaryByteStream {
208
  public:
209
    StreamImpl(std::unique_ptr<FileOutputBuffer> Buffer,
210
               llvm::support::endianness Endian)
211
        : MutableBinaryByteStream(
212
              MutableArrayRef<uint8_t>(Buffer->getBufferStart(),
213
                                       Buffer->getBufferEnd()),
214
              Endian),
215
135
          FileBuffer(std::move(Buffer)) {}
216
217
135
    Error commit() override {
218
135
      if (FileBuffer->commit())
219
0
        return make_error<BinaryStreamError>(
220
0
            stream_error_code::filesystem_error);
221
135
      return Error::success();
222
135
    }
223
224
    /// Returns a pointer to the start of the buffer.
225
244
    uint8_t *getBufferStart() const { return FileBuffer->getBufferStart(); }
226
227
    /// Returns a pointer to the end of the buffer.
228
110
    uint8_t *getBufferEnd() const { return FileBuffer->getBufferEnd(); }
229
230
  private:
231
    std::unique_ptr<FileOutputBuffer> FileBuffer;
232
  };
233
234
public:
235
  FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer,
236
                       llvm::support::endianness Endian)
237
135
      : Impl(std::move(Buffer), Endian) {}
238
239
0
  llvm::support::endianness getEndian() const override {
240
0
    return Impl.getEndian();
241
0
  }
242
243
  Error readBytes(uint32_t Offset, uint32_t Size,
244
0
                  ArrayRef<uint8_t> &Buffer) override {
245
0
    return Impl.readBytes(Offset, Size, Buffer);
246
0
  }
247
248
  Error readLongestContiguousChunk(uint32_t Offset,
249
0
                                   ArrayRef<uint8_t> &Buffer) override {
250
0
    return Impl.readLongestContiguousChunk(Offset, Buffer);
251
0
  }
252
253
1.31k
  uint32_t getLength() override { return Impl.getLength(); }
254
255
20.6k
  Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) override {
256
20.6k
    return Impl.writeBytes(Offset, Data);
257
20.6k
  }
258
259
135
  Error commit() override { return Impl.commit(); }
260
261
  /// Returns a pointer to the start of the buffer.
262
244
  uint8_t *getBufferStart() const { return Impl.getBufferStart(); }
263
264
  /// Returns a pointer to the end of the buffer.
265
110
  uint8_t *getBufferEnd() const { return Impl.getBufferEnd(); }
266
267
private:
268
  StreamImpl Impl;
269
};
270
271
} // end namespace llvm
272
273
#endif // LLVM_SUPPORT_BYTESTREAM_H