LCOV - code coverage report
Current view: top level - include/llvm/Support - BinaryByteStream.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 66 75 88.0 %
Date: 2018-06-17 00:07:59 Functions: 23 38 60.5 %
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        1026 : class BinaryByteStream : public BinaryStream {
      33             : public:
      34         582 :   BinaryByteStream() = default;
      35             :   BinaryByteStream(ArrayRef<uint8_t> Data, llvm::support::endianness Endian)
      36       20460 :       : Endian(Endian), Data(Data) {}
      37             :   BinaryByteStream(StringRef Data, llvm::support::endianness Endian)
      38         110 :       : Endian(Endian), Data(Data.bytes_begin(), Data.bytes_end()) {}
      39             : 
      40       96063 :   llvm::support::endianness getEndian() const override { return Endian; }
      41             : 
      42      162317 :   Error readBytes(uint32_t Offset, uint32_t Size,
      43             :                   ArrayRef<uint8_t> &Buffer) override {
      44      324634 :     if (auto EC = checkOffsetForRead(Offset, Size))
      45             :       return EC;
      46      324628 :     Buffer = Data.slice(Offset, Size);
      47             :     return Error::success();
      48             :   }
      49             : 
      50       18317 :   Error readLongestContiguousChunk(uint32_t Offset,
      51             :                                    ArrayRef<uint8_t> &Buffer) override {
      52       36634 :     if (auto EC = checkOffsetForRead(Offset, 1))
      53             :       return EC;
      54       36634 :     Buffer = Data.slice(Offset);
      55             :     return Error::success();
      56             :   }
      57             : 
      58      459538 :   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         204 : class MemoryBufferByteStream : public BinaryByteStream {
      77             : public:
      78             :   MemoryBufferByteStream(std::unique_ptr<MemoryBuffer> Buffer,
      79             :                          llvm::support::endianness Endian)
      80         104 :       : BinaryByteStream(Buffer->getBuffer(), Endian),
      81         104 :         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         208 : class MutableBinaryByteStream : public WritableBinaryStream {
      91             : public:
      92          93 :   MutableBinaryByteStream() = default;
      93             :   MutableBinaryByteStream(MutableArrayRef<uint8_t> Data,
      94             :                           llvm::support::endianness Endian)
      95        3717 :       : Data(Data), ImmutableStream(Data, Endian) {}
      96             : 
      97        6794 :   llvm::support::endianness getEndian() const override {
      98        6794 :     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          88 :   Error readLongestContiguousChunk(uint32_t Offset,
     107             :                                    ArrayRef<uint8_t> &Buffer) override {
     108          88 :     return ImmutableStream.readLongestContiguousChunk(Offset, Buffer);
     109             :   }
     110             : 
     111      158506 :   uint32_t getLength() override { return ImmutableStream.getLength(); }
     112             : 
     113       39041 :   Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) override {
     114       39041 :     if (Buffer.empty())
     115             :       return Error::success();
     116             : 
     117       77932 :     if (auto EC = checkOffsetForWrite(Offset, Buffer.size()))
     118             :       return EC;
     119             : 
     120             :     uint8_t *DataPtr = const_cast<uint8_t *>(Data.data());
     121       38963 :     ::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         509 : class AppendingBinaryByteStream : public WritableBinaryStream {
     137             :   std::vector<uint8_t> Data;
     138             :   llvm::support::endianness Endian = llvm::support::little;
     139             : 
     140             : public:
     141         510 :   AppendingBinaryByteStream() = default;
     142             :   AppendingBinaryByteStream(llvm::support::endianness Endian)
     143           6 :       : Endian(Endian) {}
     144             : 
     145             :   void clear() { Data.clear(); }
     146             : 
     147       22670 :   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      144438 :   uint32_t getLength() override { return Data.size(); }
     172             : 
     173       36084 :   Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) override {
     174       36084 :     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       36082 :     if (Offset > getLength())
     184           1 :       return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
     185             : 
     186       36081 :     uint32_t RequiredSize = Offset + Buffer.size();
     187       72162 :     if (RequiredSize > Data.size())
     188       36081 :       Data.resize(RequiredSize);
     189             : 
     190       36081 :     ::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       36352 :   virtual BinaryStreamFlags getFlags() const override {
     198       36352 :     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         180 : class FileBufferByteStream : public WritableBinaryStream {
     207             : private:
     208          90 :   class StreamImpl : public MutableBinaryByteStream {
     209             :   public:
     210          90 :     StreamImpl(std::unique_ptr<FileOutputBuffer> Buffer,
     211             :                llvm::support::endianness Endian)
     212          90 :         : MutableBinaryByteStream(
     213          90 :               MutableArrayRef<uint8_t>(Buffer->getBufferStart(),
     214          90 :                                        Buffer->getBufferEnd()),
     215             :               Endian),
     216         360 :           FileBuffer(std::move(Buffer)) {}
     217             : 
     218          90 :     Error commit() override {
     219         180 :       if (FileBuffer->commit())
     220             :         return make_error<BinaryStreamError>(
     221           0 :             stream_error_code::filesystem_error);
     222             :       return Error::success();
     223             :     }
     224             : 
     225             :   private:
     226             :     std::unique_ptr<FileOutputBuffer> FileBuffer;
     227             :   };
     228             : 
     229             : public:
     230          90 :   FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer,
     231             :                        llvm::support::endianness Endian)
     232         270 :       : Impl(std::move(Buffer), Endian) {}
     233             : 
     234           0 :   llvm::support::endianness getEndian() const override {
     235           0 :     return Impl.getEndian();
     236             :   }
     237             : 
     238           0 :   Error readBytes(uint32_t Offset, uint32_t Size,
     239             :                   ArrayRef<uint8_t> &Buffer) override {
     240           0 :     return Impl.readBytes(Offset, Size, Buffer);
     241             :   }
     242             : 
     243           0 :   Error readLongestContiguousChunk(uint32_t Offset,
     244             :                                    ArrayRef<uint8_t> &Buffer) override {
     245           0 :     return Impl.readLongestContiguousChunk(Offset, Buffer);
     246             :   }
     247             : 
     248        1752 :   uint32_t getLength() override { return Impl.getLength(); }
     249             : 
     250       10549 :   Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) override {
     251       10549 :     return Impl.writeBytes(Offset, Data);
     252             :   }
     253             : 
     254          90 :   Error commit() override { return Impl.commit(); }
     255             : 
     256             : private:
     257             :   StreamImpl Impl;
     258             : };
     259             : 
     260             : } // end namespace llvm
     261             : 
     262             : #endif // LLVM_SUPPORT_BYTESTREAM_H

Generated by: LCOV version 1.13