1317017Sdim//===- BinaryStream.h - Base interface for a stream of data -----*- C++ -*-===// 2317017Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6317017Sdim// 7317017Sdim//===----------------------------------------------------------------------===// 8317017Sdim 9317017Sdim#ifndef LLVM_SUPPORT_BINARYSTREAM_H 10317017Sdim#define LLVM_SUPPORT_BINARYSTREAM_H 11317017Sdim 12317017Sdim#include "llvm/ADT/ArrayRef.h" 13327952Sdim#include "llvm/ADT/BitmaskEnum.h" 14317017Sdim#include "llvm/Support/BinaryStreamError.h" 15317017Sdim#include "llvm/Support/Endian.h" 16317017Sdim#include "llvm/Support/Error.h" 17317017Sdim#include <cstdint> 18317017Sdim 19317017Sdimnamespace llvm { 20317017Sdim 21327952Sdimenum BinaryStreamFlags { 22327952Sdim BSF_None = 0, 23327952Sdim BSF_Write = 1, // Stream supports writing. 24327952Sdim BSF_Append = 2, // Writing can occur at offset == length. 25327952Sdim LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ BSF_Append) 26327952Sdim}; 27327952Sdim 28341825Sdim/// An interface for accessing data in a stream-like format, but which 29317017Sdim/// discourages copying. Instead of specifying a buffer in which to copy 30317017Sdim/// data on a read, the API returns an ArrayRef to data owned by the stream's 31317017Sdim/// implementation. Since implementations may not necessarily store data in a 32317017Sdim/// single contiguous buffer (or even in memory at all), in such cases a it may 33317017Sdim/// be necessary for an implementation to cache such a buffer so that it can 34317017Sdim/// return it. 35317017Sdimclass BinaryStream { 36317017Sdimpublic: 37317017Sdim virtual ~BinaryStream() = default; 38317017Sdim 39317017Sdim virtual llvm::support::endianness getEndian() const = 0; 40317017Sdim 41341825Sdim /// Given an offset into the stream and a number of bytes, attempt to 42317017Sdim /// read the bytes and set the output ArrayRef to point to data owned by the 43317017Sdim /// stream. 44317017Sdim virtual Error readBytes(uint32_t Offset, uint32_t Size, 45317017Sdim ArrayRef<uint8_t> &Buffer) = 0; 46317017Sdim 47341825Sdim /// Given an offset into the stream, read as much as possible without 48317017Sdim /// copying any data. 49317017Sdim virtual Error readLongestContiguousChunk(uint32_t Offset, 50317017Sdim ArrayRef<uint8_t> &Buffer) = 0; 51317017Sdim 52341825Sdim /// Return the number of bytes of data in this stream. 53317017Sdim virtual uint32_t getLength() = 0; 54317017Sdim 55341825Sdim /// Return the properties of this stream. 56327952Sdim virtual BinaryStreamFlags getFlags() const { return BSF_None; } 57327952Sdim 58317017Sdimprotected: 59327952Sdim Error checkOffsetForRead(uint32_t Offset, uint32_t DataSize) { 60317017Sdim if (Offset > getLength()) 61317017Sdim return make_error<BinaryStreamError>(stream_error_code::invalid_offset); 62317017Sdim if (getLength() < DataSize + Offset) 63317017Sdim return make_error<BinaryStreamError>(stream_error_code::stream_too_short); 64317017Sdim return Error::success(); 65317017Sdim } 66317017Sdim}; 67317017Sdim 68341825Sdim/// A BinaryStream which can be read from as well as written to. Note 69317017Sdim/// that writing to a BinaryStream always necessitates copying from the input 70317017Sdim/// buffer to the stream's backing store. Streams are assumed to be buffered 71317017Sdim/// so that to be portable it is necessary to call commit() on the stream when 72317017Sdim/// all data has been written. 73317017Sdimclass WritableBinaryStream : public BinaryStream { 74317017Sdimpublic: 75317017Sdim ~WritableBinaryStream() override = default; 76317017Sdim 77341825Sdim /// Attempt to write the given bytes into the stream at the desired 78317017Sdim /// offset. This will always necessitate a copy. Cannot shrink or grow the 79317017Sdim /// stream, only writes into existing allocated space. 80317017Sdim virtual Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) = 0; 81317017Sdim 82341825Sdim /// For buffered streams, commits changes to the backing store. 83317017Sdim virtual Error commit() = 0; 84327952Sdim 85341825Sdim /// Return the properties of this stream. 86327952Sdim BinaryStreamFlags getFlags() const override { return BSF_Write; } 87327952Sdim 88327952Sdimprotected: 89327952Sdim Error checkOffsetForWrite(uint32_t Offset, uint32_t DataSize) { 90327952Sdim if (!(getFlags() & BSF_Append)) 91327952Sdim return checkOffsetForRead(Offset, DataSize); 92327952Sdim 93327952Sdim if (Offset > getLength()) 94327952Sdim return make_error<BinaryStreamError>(stream_error_code::invalid_offset); 95327952Sdim return Error::success(); 96327952Sdim } 97317017Sdim}; 98317017Sdim 99317017Sdim} // end namespace llvm 100317017Sdim 101317017Sdim#endif // LLVM_SUPPORT_BINARYSTREAM_H 102