Home | History | Annotate | Download | only in Support
      1 //===- BinaryStream.h - Base interface for a stream of data -----*- 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 //===----------------------------------------------------------------------===//
      9 
     10 #ifndef LLVM_SUPPORT_BINARYSTREAM_H
     11 #define LLVM_SUPPORT_BINARYSTREAM_H
     12 
     13 #include "llvm/ADT/ArrayRef.h"
     14 #include "llvm/ADT/BitmaskEnum.h"
     15 #include "llvm/Support/BinaryStreamError.h"
     16 #include "llvm/Support/Endian.h"
     17 #include "llvm/Support/Error.h"
     18 #include <cstdint>
     19 
     20 namespace llvm {
     21 
     22 enum BinaryStreamFlags {
     23   BSF_None = 0,
     24   BSF_Write = 1,  // Stream supports writing.
     25   BSF_Append = 2, // Writing can occur at offset == length.
     26   LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ BSF_Append)
     27 };
     28 
     29 /// An interface for accessing data in a stream-like format, but which
     30 /// discourages copying.  Instead of specifying a buffer in which to copy
     31 /// data on a read, the API returns an ArrayRef to data owned by the stream's
     32 /// implementation.  Since implementations may not necessarily store data in a
     33 /// single contiguous buffer (or even in memory at all), in such cases a it may
     34 /// be necessary for an implementation to cache such a buffer so that it can
     35 /// return it.
     36 class BinaryStream {
     37 public:
     38   virtual ~BinaryStream() = default;
     39 
     40   virtual llvm::support::endianness getEndian() const = 0;
     41 
     42   /// Given an offset into the stream and a number of bytes, attempt to
     43   /// read the bytes and set the output ArrayRef to point to data owned by the
     44   /// stream.
     45   virtual Error readBytes(uint32_t Offset, uint32_t Size,
     46                           ArrayRef<uint8_t> &Buffer) = 0;
     47 
     48   /// Given an offset into the stream, read as much as possible without
     49   /// copying any data.
     50   virtual Error readLongestContiguousChunk(uint32_t Offset,
     51                                            ArrayRef<uint8_t> &Buffer) = 0;
     52 
     53   /// Return the number of bytes of data in this stream.
     54   virtual uint32_t getLength() = 0;
     55 
     56   /// Return the properties of this stream.
     57   virtual BinaryStreamFlags getFlags() const { return BSF_None; }
     58 
     59 protected:
     60   Error checkOffsetForRead(uint32_t Offset, uint32_t DataSize) {
     61     if (Offset > getLength())
     62       return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
     63     if (getLength() < DataSize + Offset)
     64       return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
     65     return Error::success();
     66   }
     67 };
     68 
     69 /// A BinaryStream which can be read from as well as written to.  Note
     70 /// that writing to a BinaryStream always necessitates copying from the input
     71 /// buffer to the stream's backing store.  Streams are assumed to be buffered
     72 /// so that to be portable it is necessary to call commit() on the stream when
     73 /// all data has been written.
     74 class WritableBinaryStream : public BinaryStream {
     75 public:
     76   ~WritableBinaryStream() override = default;
     77 
     78   /// Attempt to write the given bytes into the stream at the desired
     79   /// offset. This will always necessitate a copy.  Cannot shrink or grow the
     80   /// stream, only writes into existing allocated space.
     81   virtual Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) = 0;
     82 
     83   /// For buffered streams, commits changes to the backing store.
     84   virtual Error commit() = 0;
     85 
     86   /// Return the properties of this stream.
     87   BinaryStreamFlags getFlags() const override { return BSF_Write; }
     88 
     89 protected:
     90   Error checkOffsetForWrite(uint32_t Offset, uint32_t DataSize) {
     91     if (!(getFlags() & BSF_Append))
     92       return checkOffsetForRead(Offset, DataSize);
     93 
     94     if (Offset > getLength())
     95       return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
     96     return Error::success();
     97   }
     98 };
     99 
    100 } // end namespace llvm
    101 
    102 #endif // LLVM_SUPPORT_BINARYSTREAM_H
    103