CXStream
From cxwiki
The CXStream class hierarchy provides support for readable and writeable streams, ranging from file streams and network sockets to adaptors such as data codecs. The underlying functionality is virtual, but non-virtual caching operations are provided transparently to avoid exessive virtual call overhead. As much as is possible, CXStream-derived classes provide completely generic behaviour, and CXStream-utilising functions accept a base CXStream* rather than specifying a more specialised derived type. This allows an application to create a CXStream of any type (potentially even creating something new) and pass it to an existing function or system.
This page documents the usage of CXStream (and its derived classes). For guidance on creating new CXStream-derived classes, see CXStream Development.
Any given CXStream-derived object may be used on any thread, or passed between threads, but is NOT reentrant, except where specifically noted.
It is expected that CXStream implementations will closely follow the expected behaviour detailed in this document. In scenarios where customised behaviour may be preferrable, that behaviour should either be exposed through additional APIs which do not affect the behaviour of the standard APIs, or via additional capabilities flags which should be explicitly enabled.
Read / Write
// Read from the current read cursor position in this stream. If the
// size is greater than zero, the output buffer must be non-null. The
// return value is the number of bytes successfully read.
// This function will normally block until the requested number of
// bytes have been read or until an error condition has resulted
// (eg. end-of-file, i/o error, disconnected, etc.) A non-blocking
// stream (which is not the default behaviour) will instead return
// after any non-zero number of bytes has been read, without
// raising an error status.
StreamSize Read(void* __nullable o_buffer, StreamSize size);
// Writes to the current write cursor position in this stream. If
// the size is gerater than zero, the input buffer must be non-null.
// The return value is the number of bytes succesfully written.
// This function will normally block until the requested number of
// bytes have been written, or until an error condition has resulted
// (eg. end-of-file, i/o error, disconnected, etc.) A non-blocking
// stream (which is not the default behaviour) will instead return
// after any non-zero number of bytes has been written, without
// raising an error status.
StreamSize Write(const void* __nullable buffer, StreamSize size);
// Semantically equivalent to calling Read() with the specified
// size and then discarding the buffer. This may be more
// performant in some implementations.
CXStream::StreamSize ReadDiscard(CXStream::StreamSize a_size);
// Semantically equivalent to calling Write(), however the
// implementation is free to write alternative data (including
// but not limited to all zeroes) or simply seek over the
// specified number of bytes. This may be used where an empty
// space is being left in the stream that is expected to be
// filled at a later time. The stream size and cursor are
// affected in the same manner as if this was a regular Write().
CXStream::StreamSize WriteDiscard(const void* __nonnull a_buffer, StreamSize a_size);
// Flush any cached or asychronous writes to the backing store.
// Since i/o error conditions (etc.) are not detectable until the
// actual output operation is attempted, it is necessary to call
// Flush() before GetStreamResult() if an accurate outcome is
// required.
void Flush(FlushFlags flags = FLUSH_FLAGS_BLOCK);
Cursor
//
StreamPos Seek(StreamPos a_pos, uint a_mode = STREAM_SEEK_START);
//
StreamPos Tell(void) const;
//
StreamSize GetSize(void) const;
//
void SetSize(StreamSize size);
//
void Truncate(void)
//
StreamSize GetRemain(void) const;
//
bool GetRemain(StreamSize& o_remain) const;
// End-of-File detection
bool IsEOF(void) const;
Capabilities Flags
enum
{
CAPS_READ = 1, // stream is readable
CAPS_WRITE = 2, // stream is writable
CAPS_SIZE = 4, // stream provider supports GetSize() and STREAM_SEEK_END
CAPS_SEEK = 8, // stream provider supports Seek() -- usually you actually want CAPS_TELL
CAPS_TELL = 16, // stream provider supports Tell()
CAPS_UNIFIED_CURSOR = 32, // stream has unified read / write cursor -- ie. Tell() is affected by both Read() and Write()
CAPS_NO_REWIND = 64, // stream cannot seek backwards, and GetSize() returns the number of bytes after the current position
CAPS_SEEK_IN_WRITE_CACHE = 128, // since the original implementation did not support this, we have to flag if we support the technique.
// "flag" caps
CAPS_OPEN = 256, // stream is open
CAPS_EOF = 512, // stream is known to be at the EOF position
//
CAPS_NON_BLOCKING = 1024, // stream is in non-blocking mode
};
// Get the capabilities flags for this stream. These are defined
// by the implementation to describe how this stream functions in
// general terms.
Flags32 GetCaps(void) const;
// Request a change of capabilities for this stream. Any
// capabilities flags included in 'mask' are to be updated. Any
// capabilities flags also included in 'caps' are to be enabled,
// the remainder are to be disabled. The implementation is free
// to partially or fully ignore this request.
void SetCaps(const Flags32& caps, const Flags32& mask);
// Request the specified capabilites to be enabled. The
// implementation is free to partially or fully ignore this
// request.
void SetCaps(const Flags32& caps);
// Request the specified capabilities to be disabled. The
// implementation is free to partially or fully ignore this
// request.
void ClearCaps(const Flags32& caps);
// Provide a hint to the implementation. The 'hintEnum' is a
// four-char-code identifying the specific attribute to affect.
// The 'hintValue' is a hint-specific parameter to adjust.
// The implementation is free to ignore this request. This
// mechanism is provided as a way to offer generic hints that
// may be applicable across a broad range of implementations,
// without the application having to be aware of the specifics
// of the CXStream object on which the hint is being set.
// Because they may be ignored, hints should generally change
// performance characteristics and other similar behaviours,
// rather than changing the semantics of any APIs.
void SetHint(uint32 hintEnum, uint32 hintValue);
Status
// Returns the most recent CXResultCode that was raised against
// this stream. The implementation will never clear this result
// short of a complete close/reopen of the stream, or an explicit
// call to ClearStreamResult(), so this function does not need to
// be called after every stream operation.'
// Stream operations such as Write() may result only in cache
// activity with the actual i/o operation delayed until the cache
// is flushed. In this scenario, certain classes of result code
// may not be available until the flush is performed. If a
// guaranteed final result is required, the application should
// call Flush() prior to calling GetStreamResult().
CXResultCode GetStreamResult(void) const;
// Explicitly clears the stream's CXResultCode.
void ClearStreamResult(void);
// Explicitly sets the stream's CXResultCode to the specified
// value. An attempt to set the stream to CXResultCode::OK is
// ignored, leaving the previous result code intact.
void SetStreamResult(CXResultCode result) const;
// If the stream already has a result code flagged, this call
// is ignored. Otherwise, the stream's result code is
// explicitly set to the specified value.
void ConcatenateResult(CXResultCode result) const;
// Requests the implementation to shut down this stream, ready
// for another call to Open(). This mechanism is not implemented
// in the default implementation, but it is considered a generic
// enough requirement that an generic API is provided. The
// matching Open() functionality is not considered generic and
// an implementation-specific API must be used.
void Close(void);
// Returns true if this stream is open.
bool IsOpen(void) const;
// Returns true if this stream is closed.
bool IsClosed(void) const;
Events
//
CXGenericEventRef GetStreamEvent(EventType eventType) const;