Streams

Stream and memory-buffer abstractions used by the codecs.

ua::FileStream

class

A seekable byte stream backed by a file on the local filesystem.

Wraps a C FILE* handle and implements the Stream contract over it. The stream owns its handle: the file is opened by open_for_read or open_for_write and closed by close or the destructor. Move transfers ownership of the handle and leaves the moved-from stream closed; the type is non-copyable.

Operations throw UaException carrying an ErrorDetail on failure (e.g. the file is not open, the underlying C stdio call fails, or an argument is out of range). Positions and lengths are byte offsets. Instances are not thread-safe; serialise access externally if shared across threads.

Stream

Functions

FileStream(std::filesystem::path filePath)

Constructs a closed stream bound to the given filesystem path.

  • filePath (std::filesystem::path) - Path to the target file. Must not be empty.
~FileStream() override

Closes the underlying file if it is still open.

FileStream(FileStream &&other) noexcept

Move-constructs from other, transferring ownership of its file handle.

  • other (FileStream &&) - Source stream; left closed after the move.
FileStream & operator=(FileStream &&other) noexcept

Move-assigns from other, closing any handle currently held first.

  • other (FileStream &&) - Source stream; left closed after the move.

Returns: Reference to this stream.

StatusCode open_for_read()

Opens the file for reading at the start of its contents.

Returns: Status::Good on success, or a Bad status if the file cannot be opened.

StatusCode open_for_write(bool eraseExisting, bool append)

Opens the file for reading and writing.

  • eraseExisting (bool) - If true, truncates any existing contents to zero length; if false, preserves them.
  • append (bool) - If true, positions the stream at the end of the file after opening so writes append.

Returns: Status::Good on success, or a Bad status if the file cannot be opened.

bool can_read() const override

Returns true; a file stream always supports reading.

Returns: true; a file stream always supports reading.

bool can_write() const override

Returns true only when the stream was opened via open_for_write.

Returns: true if the stream was opened for writing; otherwise false.

bool can_seek() const override

Returns true; a file stream always supports seeking.

Returns: true; a file stream always supports seeking.

bool is_empty() const override

Returns true when the file is currently zero bytes long.

Returns: true if the file is currently zero bytes long.

size_t get_capacity() const override

Not supported for file streams.

Returns: Never returns; this operation is unsupported for file streams.

size_t get_length() const override

Returns the total length of the file in bytes.

Returns: File length in bytes.

size_t get_position() const override

Returns the current read/write position as a byte offset from the start.

Returns: Current position in bytes.

void flush() override

Flushes buffered writes to the underlying file.

void close() override

Closes the underlying file and releases its handle.

void read_all(span< byte > dest) const override

Reads exactly dest.size() bytes into dest, starting at the current position.

  • dest (span< byte >) - Destination buffer to fill; its size sets the byte count.
size_t read(span< byte > dest) const override

Reads up to dest.size() bytes into dest, starting at the current position.

  • dest (span< byte >) - Destination buffer; its size bounds the byte count.

Returns: Number of bytes actually read.

void write_all(span< const byte > source) override

Writes all of source to the file at the current position.

  • source (span< const byte >) - Bytes to write.
size_t write(span< const byte > source) override

Writes up to source.size() bytes to the file at the current position.

  • source (span< const byte >) - Bytes to write.

Returns: Number of bytes actually written.

void seek(int offset) const override

Moves the current position by offset bytes relative to its present value.

  • offset (int) - Signed byte delta; negative seeks toward the start.
void seek_from_start(size_t offset) const override

Moves the current position to offset bytes from the start of the file.

  • offset (size_t) - Absolute byte offset from the start.
void seek_from_end(int offset) const override

Moves the current position to offset bytes relative to the end of file.

  • offset (int) - Signed byte delta from end of file; negative seeks back into the file, zero positions at end of file.

ua::memory_stream_device::Dynamic

class

A growable, owning in-memory buffer.

Backs a writable MemoryStream with a std::vector<byte> that the device owns and grows on demand up to a fixed capacity. Writes past the current length extend the buffer; the capacity is the hard upper bound and is set at construction. Lengths and capacities are byte counts.

MemoryStream, ExternalWritable, ExternalReadOnly

Static functions

bool can_write()

Returns true; a dynamic buffer is always writable.

Returns: true; a dynamic buffer is always writable.

Functions

Dynamic()

Constructs a device whose capacity is the maximum 32-bit value and that reserves no storage up front.

Dynamic(size_t capacity, bool reserve)

Constructs a device with a fixed maximum capacity.

  • capacity (size_t) - Maximum number of bytes the buffer may grow to, in bytes; must be non-zero.
  • reserve (bool) - When true, reserves capacity bytes of storage immediately so growth does not reallocate.
bool is_empty() const

Returns true when no bytes have been written yet.

Returns: true when no bytes have been written yet; false otherwise.

size_t get_capacity() const

Returns the maximum number of bytes the buffer may grow to, in bytes.

Returns: The maximum number of bytes the buffer may grow to, in bytes.

span< const byte > get_data() const

Returns a view over the bytes written so far.

Returns: A view over the bytes written so far.

std::vector< byte > move_storage_out()

Moves the underlying storage out of the device.

Returns: The owning byte vector. The device is left empty afterwards.

void write(span< const byte > source, size_t offset)

Writes source into the buffer at offset, growing it if needed.

  • source (span< const byte >) - Bytes to copy in.
  • offset (size_t) - Byte offset at which to place source. offset plus the size of source must not exceed the capacity.

Static attributes

constexpr bool sPersistentExternalStorage

Not externally-owned persistent storage: the buffer is device-owned and may grow/reallocate, so its bytes must never be borrowed past a write or the device's lifetime.

ua::memory_stream_device::ExternalWritable

class

A writable, non-owning view over caller-provided storage.

Backs a writable MemoryStream with externally owned memory. The device does not own the buffer: the caller must keep the underlying storage alive for the lifetime of the device and any stream wrapping it. Capacity is the size of the storage span and is fixed; content length tracks how far the buffer has been filled. Lengths and capacities are byte counts.

MemoryStream, Dynamic, ExternalReadOnly

Static functions

bool can_write()

Returns true; external writable storage is always writable.

Returns: true; external writable storage is always writable.

Functions

ExternalWritable(span< byte > storage, size_t contentLength=0)

Wraps externally owned writable storage.

  • storage (span< byte >) - Caller-owned buffer the device writes into; must outlive the device.
  • contentLength (size_t) - Number of leading bytes already populated, in bytes; must not exceed the size of storage.
bool is_empty() const

Returns true when the populated content length is zero.

Returns: true when the populated content length is zero; false otherwise.

size_t get_capacity() const

Returns the size of the backing storage, in bytes.

Returns: The size of the backing storage, in bytes.

span< const byte > get_data() const

Returns a view over the populated bytes.

Returns: A view over the populated bytes.

void write(span< const byte > source, size_t offset)

Writes source into the storage at offset, extending the content length if needed.

  • source (span< const byte >) - Bytes to copy in.
  • offset (size_t) - Byte offset at which to place source. offset plus the size of source must not exceed the storage size.

Static attributes

constexpr bool sPersistentExternalStorage

Not eligible for a borrowed contiguous view: although the storage is caller-owned, it is writable (hence not immutable) and exposes only the populated content, which may not be NUL-terminated.

ua::memory_stream_device::ExternalReadOnly

class

A read-only, non-owning view over caller-provided storage.

Backs a non-writable MemoryStream with externally owned immutable memory. The device does not own the buffer: the caller must keep the underlying storage alive for the lifetime of the device and any stream wrapping it. Any write attempt fails. Lengths and capacities are byte counts.

MemoryStream, Dynamic, ExternalWritable

Static functions

bool can_write()

Returns false; read-only storage cannot be written.

Returns: false; read-only storage cannot be written.

void write(span< const byte > source, size_t offset)

Always fails; read-only storage cannot be written.

  • source (span< const byte >) - Bytes that would be written; ignored, as this device never accepts writes.
  • offset (size_t) - Byte offset that would be written to; ignored.

Functions

ExternalReadOnly(span< const byte > storage)

Wraps externally owned read-only storage.

  • storage (span< const byte >) - Caller-owned immutable buffer the device reads from; must outlive the device.
bool is_empty() const

Returns true when the backing storage is empty.

Returns: true when the backing storage is empty; false otherwise.

size_t get_capacity() const

Returns the size of the backing storage, in bytes.

Returns: The size of the backing storage, in bytes.

span< const byte > get_data() const

Returns a view over the backing storage.

Returns: A view over the backing storage.

Static attributes

constexpr bool sPersistentExternalStorage

Externally-owned immutable storage: the buffer belongs to the caller (who must keep it alive), is never written, and get_data exposes it whole.

ua::MemoryStream

class

A seekable byte Stream backed by an in-memory buffer.

Implements the Stream contract over a storage device from memory_stream_device, selected as the Device template argument. The stream holds a non-owning reference to the device: the device (and any external buffer it refers to) must outlive the stream. Reads, writes and seeks move a single byte position; positions and lengths are byte offsets. Whether the stream is writable is delegated to the device.

Operations throw UaException carrying an ErrorDetail on failure (e.g. seeking past the end of the data, a null buffer argument, exceeding device capacity, or writing to a read-only device). Instances are not thread-safe; serialise access externally if shared across threads.

Device Storage backend from memory_stream_device (memory_stream_device::Dynamic, memory_stream_device::ExternalWritable, or memory_stream_device::ExternalReadOnly). Stream

Functions

MemoryStream(Device &device)

Wraps device, positioned at the start of its data.

  • device (Device &) - Storage backend the stream reads from and writes to; must outlive the stream.
bool can_read() const override

Returns true; a memory stream is always readable.

Returns: true; a memory stream is always readable.

bool can_write() const override

Returns true when the backing device is writable.

Returns: true when the backing device is writable; false otherwise.

bool can_seek() const override

Returns true; a memory stream is always seekable.

Returns: true; a memory stream is always seekable.

bool is_empty() const override

Returns true when the backing device holds no data.

Returns: true when the backing device holds no data; false otherwise.

size_t get_capacity() const override

Returns the maximum number of bytes the stream can hold, in bytes.

Returns: The maximum number of bytes the stream can hold, in bytes.

size_t get_length() const override

Returns the number of bytes currently stored, in bytes.

Returns: The number of bytes currently stored, in bytes.

size_t get_position() const override

Returns the current byte position within the stream.

Returns: The current byte position within the stream.

void flush() override

No-op; an in-memory stream has nothing to flush.

void close() override

No-op; an in-memory stream holds no resource to close.

void read_all(span< byte > dest) const override

Reads exactly dest.size() bytes into dest, advancing the position.

  • dest (span< byte >) - Buffer to fill; its size sets the number of bytes read.
size_t read(span< byte > dest) const override

Reads up to dest.size() bytes into dest, advancing the position.

  • dest (span< byte >) - Buffer to fill; its size sets the maximum bytes read.

Returns: The number of bytes read, which may be fewer than requested.

void write_all(span< const byte > source) override

Writes all of source into the stream, advancing the position.

  • source (span< const byte >) - Bytes to write.
size_t write(span< const byte > source) override

Writes up to the remaining capacity from source, advancing the position.

  • source (span< const byte >) - Bytes to write.

Returns: The number of bytes written, which may be fewer than source.size().

void seek(int offset) const override

Moves the current position by offset bytes, relative to the current position.

  • offset (int) - Signed byte displacement; negative values seek backwards.
void seek_from_start(size_t offset) const override

Sets the current position to offset bytes from the start.

  • offset (size_t) - Absolute byte position from the start of the data.
void seek_from_end(int offset) const override

Moves the current position by offset bytes, relative to the current position.

  • offset (int) - Signed byte displacement; negative values seek backwards.
optional< span< const byte > > contiguous_view() const override

Returns a view over the backing buffer when Device is externally-owned immutable storage (memory_stream_device::ExternalReadOnly); std::nullopt for owning/writable devices.

Returns: A view over the backing buffer, or std::nullopt for owning or writable devices.

ua::NullStream

class

A bottomless sink stream: writes are discarded and reads are unsupported.

Implements the Stream contract as a write-only "null device". Every byte written is discarded but still counted, so get_position advances by the number of bytes written; capacity is effectively unbounded. The stream is not readable and not seekable, and it has no defined length.

Read operations (read, read_all) and get_length throw UaException carrying a Status::BadNotSupported ErrorDetail. Positions are byte offsets. Instances are not thread-safe; serialise access externally if shared across threads.

Stream, FileStream

Functions

NullStream()=default
~NullStream()
bool can_read() const override

Returns false: a null stream is never readable.

Returns: false: a null stream is never readable.

bool can_write() const override

Returns true: writes are always accepted (and discarded).

Returns: true: writes are always accepted (and discarded).

bool can_seek() const override

Returns false: a null stream cannot seek.

Returns: false: a null stream cannot seek.

bool is_empty() const override

Returns false: a null stream is never considered empty.

Returns: false: a null stream is never considered empty.

size_t get_capacity() const override

Returns the effectively unbounded capacity (SIZE_MAX bytes).

Returns: The effectively unbounded capacity (SIZE_MAX bytes).

size_t get_length() const override

Not supported by a null stream.

Returns: Never returns; a null stream has no defined length.

size_t get_position() const override

Returns the current write position in bytes.

Returns: The current write position, in bytes.

void flush() override

Does nothing: there is no buffered data to flush.

void close() override

Does nothing: a null stream holds no resources to release.

void read_all(span< byte > dest) const override

Not supported by a null stream.

  • dest (span< byte >) - Destination buffer; left untouched.
size_t read(span< byte > dest) const override

Not supported by a null stream.

  • dest (span< byte >) - Destination buffer; left untouched.

Returns: Never returns; a null stream cannot be read.

void write_all(span< const byte > source) override

Discards all of source, advancing the position by its size.

  • source (span< const byte >) - Bytes to discard; their contents are ignored.
size_t write(span< const byte > source) override

Discards all of source, advancing the position by its size.

  • source (span< const byte >) - Bytes to discard; their contents are ignored.

Returns: The number of bytes accepted, always equal to source.size().

void seek(int offset) const override

Does nothing: a null stream cannot seek.

  • offset (int) - Ignored.
void seek_from_start(size_t offset) const override

Does nothing: a null stream cannot seek.

  • offset (size_t) - Ignored.
void seek_from_end(int offset) const override

Does nothing: a null stream cannot seek.

  • offset (int) - Ignored.

ua::Stream

class

Abstract interface for a seekable byte stream.

Models a stream of bytes that concrete devices (files, in-memory buffers, the null sink) implement. Reads and writes operate on raw std::byte spans and act at the stream's current position, which advances by the number of bytes transferred. All positions, lengths, and capacities are byte counts.

Operations are synchronous and blocking. On failure an implementation throws UaException carrying an ErrorDetail (e.g. the stream is closed, an argument is out of range, or the underlying device fails); a capability not offered by a device throws Status::BadNotSupported. Implementations are not thread-safe - serialise access externally if a stream is shared across threads.

FileStream, MemoryStream, NullStream

Functions

Stream()=default

Default-constructs the abstract base; only derived streams are instantiable.

~Stream()=default

Destroys the stream, releasing any underlying device or handle.

Stream(const Stream &)=default

Copy-constructs the base subobject; a no-op as Stream holds no state (see note above).

Stream & operator=(const Stream &)=default

Copy-assigns the base subobject; a no-op as Stream holds no state (see note above).

Returns: A reference to this stream.

Stream(Stream &&)=default

Move-constructs the base subobject; a no-op as Stream holds no state (see note above).

Stream & operator=(Stream &&)=default

Move-assigns the base subobject; a no-op as Stream holds no state (see note above).

Returns: A reference to this stream.

bool can_read() const =0

Returns whether the stream supports reading.

Returns: true if the stream supports reading; false otherwise.

bool can_write() const =0

Returns whether the stream supports writing.

Returns: true if the stream supports writing; false otherwise.

bool can_seek() const =0

Returns whether the stream supports seeking to an arbitrary position.

Returns: true if the stream supports seeking to an arbitrary position; false otherwise.

bool is_empty() const =0

Returns whether the stream currently holds no bytes (length is zero).

Returns: true if the stream currently holds no bytes; false otherwise.

size_t get_capacity() const =0

Returns the total number of bytes the stream can hold, in bytes.

Returns: The capacity in bytes.

size_t get_length() const =0

Returns the number of bytes currently stored, in bytes.

Returns: The length in bytes.

size_t get_position() const =0

Returns the current read/write position, in bytes from the start.

Returns: The position in bytes.

void flush()=0

Flushes any buffered output to the underlying device.

void close()=0

Closes the stream and releases the underlying device or handle.

void read_all(span< byte > dest) const =0

Reads exactly dest.size() bytes from the current position into dest.

  • dest (span< byte >) - Buffer to fill; its full size is read.
size_t read(span< byte > dest) const =0

Reads up to dest.size() bytes from the current position into dest.

  • dest (span< byte >) - Buffer to fill.

Returns: The number of bytes actually read, in the range [0, dest.size()].

void write_all(span< const byte > source)=0

Writes all bytes of source at the current position.

  • source (span< const byte >) - Bytes to write in full.
size_t write(span< const byte > source)=0

Writes up to source.size() bytes at the current position.

  • source (span< const byte >) - Bytes to write.

Returns: The number of bytes actually written, in the range [0, source.size()].

void seek(int offset) const =0

Moves the current position by offset bytes, relative to the current position.

  • offset (int) - Signed byte displacement; negative seeks backward.
void seek_from_start(size_t offset) const =0

Moves the current position to offset bytes from the start of the stream.

  • offset (size_t) - Absolute byte offset from the start.
void seek_from_end(int offset) const =0

Moves the current position by offset bytes, relative to the end of the stream.

  • offset (int) - Signed byte displacement from the end; negative seeks backward into the stream and zero positions at the end.
optional< span< const byte > > contiguous_view() const

Optional capability: a view over the stream's entire content when that content lives in externally-owned, immutable, contiguous storage that outlives the stream.

Returns: A view over the full content, or std::nullopt if the stream cannot make this guarantee.

Was this page helpful?