IO::StreamBuffer class

Implements a smart buffer around a random-access stream.

This buffering is significantly smarter than the file buffering you get with the C or C++ standard libaries, and it gives the user some configurability options as well.

Base classes

class IStream

Public static variables

static const uint32_t kType
static const size_type kBufferSizeReadDefault
static const size_type kBufferSizeWriteDefault
This is the default write buffer size.
static const size_type kBufferSizeUseDefault
This is the default write buffer size.
static const size_type kBufferSizeUnspecified
This means that the buffer is used with the default size.

Constructors, destructors, conversion operators

StreamBuffer(size_type nReadBufferSize = kBufferSizeUnspecified, size_type nWriteBufferSize = kBufferSizeUnspecified, IStream* pStream = NULL)
This means that the user means to leave the given buffer as-is.
~StreamBuffer()

Public functions

auto GetStream() const -> IStream*
auto SetStream(IStream* pStream) -> bool
auto GetBufferSizes(size_type& nReadBufferSize, size_type& nWriteBufferSize) const -> void
auto SetBufferSizes(size_type nReadBufferSize, size_type nWriteBufferSize) -> bool
auto AddRef() -> int override
auto Release() -> int override
auto GetType() const -> uint32_t override
Returns the type of the stream, which is different for each Stream subclass.
auto GetAccessFlags() const -> AccessFlags override
Returns one of enum AccessFlags.
auto GetState() const -> FileError override
Returns the error state of the stream.
auto Close() -> bool override
Closes the stream and releases resouces associated with it.
auto GetSize() const -> size_type override
Returns the size of the stream, which is not the same as the size of bytes remaining to be read from the stream.
auto SetSize(size_type size) -> bool override
Sets the size of the stream, if possible.
auto GetPosition(PositionType positionType = PositionType::Begin) const -> int override
Gets the current read/write position within the stream.
auto SetPosition(int distance, PositionType positionType = PositionType::Begin) -> bool override
Sets the read/write position of the stream.
auto GetAvailable() const -> int override
Returns the number of bytes available for reading.
auto Read(void* pData, size_t nSize) -> int override
Reads bytes from the stream given by the input count 'nSize'.
auto Flush() -> bool override
Flush any non-empty stream write buffers.
auto Write(const void* pData, size_t nSize) -> int override
Writes bytes to the stream.

Protected functions

auto FillWriteBuffer(const char* pData, size_type nSize) -> bool
auto FlushWriteBuffer() -> bool

Protected variables

IStreamPtr mpStream
int mnRefCount
The stream that we are buffering.
size_type mnPositionExternal
The reference count, which may or may not be used.
size_type mnPositionInternal
This is the position of the the file pointer as the the user sees it. It is where the next byte read or write will come from or go to.
char* mpReadBuffer
This is the position of the the file pointer as the owned stream sees it.
size_type mnReadBufferSize
Pointer to buffer data.
size_type mnReadBufferStartPosition
This is the size of the read buffer available for our usage.
size_type mnReadBufferUsed
This is where in the file the beginning the read buffer corresponds to.
char* mpWriteBuffer
This is the count of bytes in the read buffer that are valid.
size_type mnWriteBufferSize
Pointer to buffer data.
size_type mnWriteBufferStartPosition
This is the size of the write buffer available for our usage.
size_type mnWriteBufferUsed
This is where in the file the beginning the write buffer corresponds to.

Function documentation

uint32_t IO::StreamBuffer::GetType() const override

Returns the type of the stream, which is different for each Stream subclass.

This function can be used for run-time type identification. A type of zero means the type is unknown or invalid.

AccessFlags IO::StreamBuffer::GetAccessFlags() const override

Returns one of enum AccessFlags.

This function also tells you if the stream is open, as a return value of zero means the stream is not open. It is not allowed that a stream
be open with no type of access.

FileError IO::StreamBuffer::GetState() const override

Returns the error state of the stream.

Returns FileError::Success if OK, else an error code. This function is similar to 'errno' or a 'get last error' facility.

bool IO::StreamBuffer::Close() override

Closes the stream and releases resouces associated with it.

Returns true upon success, else false. If the return value is false, GetState will give the error code. If an IStream encounters an error during operations on an open stream, it is guaranteed that you can safely call the Close function on the stream.

size_type IO::StreamBuffer::GetSize() const override

Returns the size of the stream, which is not the same as the size of bytes remaining to be read from the stream.

Returns (size_type)-2 if the stream is of indeterminate size. Returns (size_type)-1 (a.k.a. kSizeTypeError) upon error.

bool IO::StreamBuffer::SetSize(size_type size) override

Sets the size of the stream, if possible.

Parameters
size

It is debatable whether this function should be present in IStream or only in suclasses of StreamBase which are writable. For consistency with GetSize, we put the function here. But also consider that a SetSize function is not necessarily a data writing function, depending on the stream implementation.

int IO::StreamBuffer::GetPosition(PositionType positionType = PositionType::Begin) const override

Gets the current read/write position within the stream.

Parameters
positionType

The read and write positions of a stream must be the same value; you cannot have a read position that is different from a write position. However, a Stream subclass can provide such functionality if needed. Returns -1 upon error.

bool IO::StreamBuffer::SetPosition(int distance, PositionType positionType = PositionType::Begin) override

Sets the read/write position of the stream.

Parameters
distance
positionType

If the specified position is beyond the size of a fixed stream, the position is set to the end of the stream. A writable stream subclass may provide a policy whereby setting the position beyond the end of the stream results in an increase in the stream size.

int IO::StreamBuffer::GetAvailable() const override

Returns the number of bytes available for reading.

Returns (size_type)-1 (a.k.a. kSizeTypeError) upon error. This function is non-blocking; it should return immediately.

int IO::StreamBuffer::Read(void* pData, size_t nSize) override

Reads bytes from the stream given by the input count 'nSize'.

Parameters
pData
nSize

If less then nSize bytes are available, then those bytes will be read. Returns the number of bytes read. A return value of zero means that there were no bytes to be read or no bytes were requested to be read. A return value of zero means the end of file was reached. A return value > 0 but < 'nSize' is possible, and it does not necessarily mean that the end of the file was reached. Returns (size_type)-1 (a.k.a. kSizeTypeError) if there was an error. You can use this return value or IStream::GetState to determine the error. Input size values equal to (size_type)-1 (a.k.a. kSizeTypeError) are not valid input. Upon error, the stream pointer is at the position it was upon the error occurrence.

bool IO::StreamBuffer::Flush() override

Flush any non-empty stream write buffers.

If the return value is false, GetState will give the error code. This function implements the flushing as per the underlying file system. The behavior of the Flush function varies with the underlying platform.

A common use of Flush is write a file to disk immediately in order to prevent the file from being corrupted if the application crashes before the file is closed. However, on desktop platforms such as Windows this strategy is unnecesary, as the Windows OS file flush doesn't write the file to disk as might be expected. This actually is not a problem, because the Windows OS manages files outside the process and if your process crashes the OS will take care of safely closing the files. Only if the machine power is lost or if certain kinds of kernel-level crashes occur may you lose file data.

int IO::StreamBuffer::Write(const void* pData, size_t nSize) override

Writes bytes to the stream.

Parameters
pData
nSize

If false is returned, you can use IStream::GetState to determine the error. Upon error, the stream pointer is at the position it was upon the error occurrence.