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