Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:27

0001 //===- BinaryByteStream.h ---------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //===----------------------------------------------------------------------===//
0007 // A BinaryStream which stores data in a single continguous memory buffer.
0008 //===----------------------------------------------------------------------===//
0009 
0010 #ifndef LLVM_SUPPORT_BINARYBYTESTREAM_H
0011 #define LLVM_SUPPORT_BINARYBYTESTREAM_H
0012 
0013 #include "llvm/ADT/ArrayRef.h"
0014 #include "llvm/ADT/StringRef.h"
0015 #include "llvm/Support/BinaryStream.h"
0016 #include "llvm/Support/BinaryStreamError.h"
0017 #include "llvm/Support/Error.h"
0018 #include "llvm/Support/FileOutputBuffer.h"
0019 #include "llvm/Support/MemoryBuffer.h"
0020 #include <cstdint>
0021 #include <cstring>
0022 #include <memory>
0023 
0024 namespace llvm {
0025 
0026 /// An implementation of BinaryStream which holds its entire data set
0027 /// in a single contiguous buffer.  BinaryByteStream guarantees that no read
0028 /// operation will ever incur a copy.  Note that BinaryByteStream does not
0029 /// own the underlying buffer.
0030 class BinaryByteStream : public BinaryStream {
0031 public:
0032   BinaryByteStream() = default;
0033   BinaryByteStream(ArrayRef<uint8_t> Data, llvm::endianness Endian)
0034       : Endian(Endian), Data(Data) {}
0035   BinaryByteStream(StringRef Data, llvm::endianness Endian)
0036       : Endian(Endian), Data(Data.bytes_begin(), Data.bytes_end()) {}
0037 
0038   llvm::endianness getEndian() const override { return Endian; }
0039 
0040   Error readBytes(uint64_t Offset, uint64_t Size,
0041                   ArrayRef<uint8_t> &Buffer) override {
0042     if (auto EC = checkOffsetForRead(Offset, Size))
0043       return EC;
0044     Buffer = Data.slice(Offset, Size);
0045     return Error::success();
0046   }
0047 
0048   Error readLongestContiguousChunk(uint64_t Offset,
0049                                    ArrayRef<uint8_t> &Buffer) override {
0050     if (auto EC = checkOffsetForRead(Offset, 1))
0051       return EC;
0052     Buffer = Data.slice(Offset);
0053     return Error::success();
0054   }
0055 
0056   uint64_t getLength() override { return Data.size(); }
0057 
0058   ArrayRef<uint8_t> data() const { return Data; }
0059 
0060   StringRef str() const {
0061     const char *CharData = reinterpret_cast<const char *>(Data.data());
0062     return StringRef(CharData, Data.size());
0063   }
0064 
0065 protected:
0066   llvm::endianness Endian;
0067   ArrayRef<uint8_t> Data;
0068 };
0069 
0070 /// An implementation of BinaryStream whose data is backed by an llvm
0071 /// MemoryBuffer object.  MemoryBufferByteStream owns the MemoryBuffer in
0072 /// question.  As with BinaryByteStream, reading from a MemoryBufferByteStream
0073 /// will never cause a copy.
0074 class MemoryBufferByteStream : public BinaryByteStream {
0075 public:
0076   MemoryBufferByteStream(std::unique_ptr<MemoryBuffer> Buffer,
0077                          llvm::endianness Endian)
0078       : BinaryByteStream(Buffer->getBuffer(), Endian),
0079         MemBuffer(std::move(Buffer)) {}
0080 
0081   std::unique_ptr<MemoryBuffer> MemBuffer;
0082 };
0083 
0084 /// An implementation of BinaryStream which holds its entire data set
0085 /// in a single contiguous buffer.  As with BinaryByteStream, the mutable
0086 /// version also guarantees that no read operation will ever incur a copy,
0087 /// and similarly it does not own the underlying buffer.
0088 class MutableBinaryByteStream : public WritableBinaryStream {
0089 public:
0090   MutableBinaryByteStream() = default;
0091   MutableBinaryByteStream(MutableArrayRef<uint8_t> Data,
0092                           llvm::endianness Endian)
0093       : Data(Data), ImmutableStream(Data, Endian) {}
0094 
0095   llvm::endianness getEndian() const override {
0096     return ImmutableStream.getEndian();
0097   }
0098 
0099   Error readBytes(uint64_t Offset, uint64_t Size,
0100                   ArrayRef<uint8_t> &Buffer) override {
0101     return ImmutableStream.readBytes(Offset, Size, Buffer);
0102   }
0103 
0104   Error readLongestContiguousChunk(uint64_t Offset,
0105                                    ArrayRef<uint8_t> &Buffer) override {
0106     return ImmutableStream.readLongestContiguousChunk(Offset, Buffer);
0107   }
0108 
0109   uint64_t getLength() override { return ImmutableStream.getLength(); }
0110 
0111   Error writeBytes(uint64_t Offset, ArrayRef<uint8_t> Buffer) override {
0112     if (Buffer.empty())
0113       return Error::success();
0114 
0115     if (auto EC = checkOffsetForWrite(Offset, Buffer.size()))
0116       return EC;
0117 
0118     uint8_t *DataPtr = const_cast<uint8_t *>(Data.data());
0119     ::memcpy(DataPtr + Offset, Buffer.data(), Buffer.size());
0120     return Error::success();
0121   }
0122 
0123   Error commit() override { return Error::success(); }
0124 
0125   MutableArrayRef<uint8_t> data() const { return Data; }
0126 
0127 private:
0128   MutableArrayRef<uint8_t> Data;
0129   BinaryByteStream ImmutableStream;
0130 };
0131 
0132 /// An implementation of WritableBinaryStream which can write at its end
0133 /// causing the underlying data to grow.  This class owns the underlying data.
0134 class AppendingBinaryByteStream : public WritableBinaryStream {
0135   std::vector<uint8_t> Data;
0136   llvm::endianness Endian = llvm::endianness::little;
0137 
0138 public:
0139   AppendingBinaryByteStream() = default;
0140   AppendingBinaryByteStream(llvm::endianness Endian) : Endian(Endian) {}
0141 
0142   void clear() { Data.clear(); }
0143 
0144   llvm::endianness getEndian() const override { return Endian; }
0145 
0146   Error readBytes(uint64_t Offset, uint64_t Size,
0147                   ArrayRef<uint8_t> &Buffer) override {
0148     if (auto EC = checkOffsetForWrite(Offset, Buffer.size()))
0149       return EC;
0150 
0151     Buffer = ArrayRef(Data).slice(Offset, Size);
0152     return Error::success();
0153   }
0154 
0155   void insert(uint64_t Offset, ArrayRef<uint8_t> Bytes) {
0156     Data.insert(Data.begin() + Offset, Bytes.begin(), Bytes.end());
0157   }
0158 
0159   Error readLongestContiguousChunk(uint64_t Offset,
0160                                    ArrayRef<uint8_t> &Buffer) override {
0161     if (auto EC = checkOffsetForWrite(Offset, 1))
0162       return EC;
0163 
0164     Buffer = ArrayRef(Data).slice(Offset);
0165     return Error::success();
0166   }
0167 
0168   uint64_t getLength() override { return Data.size(); }
0169 
0170   Error writeBytes(uint64_t Offset, ArrayRef<uint8_t> Buffer) override {
0171     if (Buffer.empty())
0172       return Error::success();
0173 
0174     // This is well-defined for any case except where offset is strictly
0175     // greater than the current length.  If offset is equal to the current
0176     // length, we can still grow.  If offset is beyond the current length, we
0177     // would have to decide how to deal with the intermediate uninitialized
0178     // bytes.  So we punt on that case for simplicity and just say it's an
0179     // error.
0180     if (Offset > getLength())
0181       return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
0182 
0183     uint64_t RequiredSize = Offset + Buffer.size();
0184     if (RequiredSize > Data.size())
0185       Data.resize(RequiredSize);
0186 
0187     ::memcpy(Data.data() + Offset, Buffer.data(), Buffer.size());
0188     return Error::success();
0189   }
0190 
0191   Error commit() override { return Error::success(); }
0192 
0193   /// Return the properties of this stream.
0194   BinaryStreamFlags getFlags() const override { return BSF_Write | BSF_Append; }
0195 
0196   MutableArrayRef<uint8_t> data() { return Data; }
0197 };
0198 
0199 /// An implementation of WritableBinaryStream backed by an llvm
0200 /// FileOutputBuffer.
0201 class FileBufferByteStream : public WritableBinaryStream {
0202 private:
0203   class StreamImpl : public MutableBinaryByteStream {
0204   public:
0205     StreamImpl(std::unique_ptr<FileOutputBuffer> Buffer,
0206                llvm::endianness Endian)
0207         : MutableBinaryByteStream(
0208               MutableArrayRef<uint8_t>(Buffer->getBufferStart(),
0209                                        Buffer->getBufferEnd()),
0210               Endian),
0211           FileBuffer(std::move(Buffer)) {}
0212 
0213     Error commit() override {
0214       if (FileBuffer->commit())
0215         return make_error<BinaryStreamError>(
0216             stream_error_code::filesystem_error);
0217       return Error::success();
0218     }
0219 
0220     /// Returns a pointer to the start of the buffer.
0221     uint8_t *getBufferStart() const { return FileBuffer->getBufferStart(); }
0222 
0223     /// Returns a pointer to the end of the buffer.
0224     uint8_t *getBufferEnd() const { return FileBuffer->getBufferEnd(); }
0225 
0226   private:
0227     std::unique_ptr<FileOutputBuffer> FileBuffer;
0228   };
0229 
0230 public:
0231   FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer,
0232                        llvm::endianness Endian)
0233       : Impl(std::move(Buffer), Endian) {}
0234 
0235   llvm::endianness getEndian() const override { return Impl.getEndian(); }
0236 
0237   Error readBytes(uint64_t Offset, uint64_t Size,
0238                   ArrayRef<uint8_t> &Buffer) override {
0239     return Impl.readBytes(Offset, Size, Buffer);
0240   }
0241 
0242   Error readLongestContiguousChunk(uint64_t Offset,
0243                                    ArrayRef<uint8_t> &Buffer) override {
0244     return Impl.readLongestContiguousChunk(Offset, Buffer);
0245   }
0246 
0247   uint64_t getLength() override { return Impl.getLength(); }
0248 
0249   Error writeBytes(uint64_t Offset, ArrayRef<uint8_t> Data) override {
0250     return Impl.writeBytes(Offset, Data);
0251   }
0252 
0253   Error commit() override { return Impl.commit(); }
0254 
0255   /// Returns a pointer to the start of the buffer.
0256   uint8_t *getBufferStart() const { return Impl.getBufferStart(); }
0257 
0258   /// Returns a pointer to the end of the buffer.
0259   uint8_t *getBufferEnd() const { return Impl.getBufferEnd(); }
0260 
0261 private:
0262   StreamImpl Impl;
0263 };
0264 
0265 } // end namespace llvm
0266 
0267 #endif // LLVM_SUPPORT_BINARYBYTESTREAM_H