LCOV - code coverage report
Current view: top level - include/llvm/Support - BinaryByteStream.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 65 76 85.5 %
Date: 2018-10-20 13:21:21 Functions: 20 26 76.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13