Streams

Output Streams/Buffer

#include <dplx/dp/streams/output_buffer.hpp>
namespace dplx::dp {}
class output_buffer

The (soon to be) universal way encoders interact with output streams. It is an abstract base class managing the memory being written to by the encoder and forwards the content to the underlying stream via do_grow and do_bulk_write.

output_buffer models a contiguous_range of bytes which can be directly written. If an encoder needs more space than currently available it may call ensure_size which asks the underlying stream for the next buffer (and fails with errc::end_of_stream if it runs out of space).

Type Aliases

using element_type = std::byte
using value_type = std::byte
using pointer = std::byte*
using iterator = std::byte*
using size_type = std::size_t
using difference_type = std::ptrdiff_t

Special Member Functions

protected ~output_buffer() noexcept = default

The destructor is trivial but protected to prevent accidental deletion of the base instead of the derived object.

protected output_buffer() noexcept

Initializes the output_buffer to an empty range/buffer.

output_buffer(output_buffer const&) noexcept = default

The copy constructor is trivial but protected to prevent accidental slicing.

auto operator=(output_buffer const&) noexcept -> output_buffer& = default

The copy assignment operator is trivial but protected to prevent accidental slicing.

protected output_buffer(std::byte *buffer, std::size_t bufferSize) noexcept

Initializes the instance with the given buffer. This should be used to avoid a do_grow call on the first write if possible.

Member Functions

void commit_written(size_type numBytes)

Informs the buffer that numBytes have been written. The buffer will remove these bytes from the beginning of the output_range and therefore shrink by numBytes.

auto ensure_size(size_type requestedSize) noexcept -> result<void>

Tries to get a buffer from the underlying stream which is at least requestedSize bytes big. May invalidate all iterators and pointers.

If the current buffer doesn’t satisfy the new size requirement do_grow will be called which may fail if no more space is available.

Warning

Data written to the current buffer which has not been committed by calling commit_written() is not guaranteed to survive and might be lost.

private virtual auto do_grow(size_type requestedSize) noexcept -> result<void> = 0

Asks the derived class to reset() this instance with a buffer at least as big as requestedSize. The implementation is responsible for actually outputting the committed area of the current buffer (which _might_ be a no-op if streaming to memory).

protected void reset() noexcept

Resets this output range to an empty state.

protected void reset(std::byte *buffer, std::size_t bufferSize)

Resets this output range to [buffer, buffer + bufferSize).

auto bulk_write(std::byte const *bytes, std::size_t bytesSize) noexcept -> result<void>

Fills the current buffer starting at begin() with the data pointed at by bytes and commits these bytes as if calling commit_written() afterwards. If more bytes are being written than can fit into the current buffer, the remainder gets forwarded to do_bulk_write().

private auto do_bulk_write(std::byte const *bytes, std::size_t bytesSize) noexcept -> result<void> = 0

Asks the derived class to output the current buffer and append the given data to the stream. The current buffer is guaranteed to be full i.e. empty() returns true. The implementation is encouraged to reset() this instance to a (not necessarily) new buffer to avoid a do_grow() call.

Contiguous Output Range Functions

[[nodiscard]] auto begin() noexcept -> iterator
[[nodiscard]] auto end() noexcept -> iterator
[[nodiscard]] auto data() noexcept -> pointer
[[nodiscard]] auto size() const noexcept -> size_type
[[nodiscard]] auto empty() const noexcept -> bool