17 Buffer-oriented streams [buffer.stream]

17.1 Requirements [buffer.stream.reqmts]

17.1.1 Buffer-oriented synchronous read stream requirements [buffer.stream.reqmts.syncreadstream]

A type X meets the SyncReadStream requirements if it satisfies the requirements listed in Table [tab:buffer.stream.reqmts.syncreadstream.requirements].

An orderly shutdown is the procedure for shutting down a stream after all work in progress has been completed, without loss of data.

In Table [tab:buffer.stream.reqmts.syncreadstream.requirements], a denotes a value of type X, mb denotes a (possibly const) value of a type satisfying the MutableBufferSequence ([buffer.reqmts.mutablebuffersequence]) requirements, and ec denotes an object of type error_code.

Table 16 — SyncReadStream requirements
operationtypesemantics, pre/post-conditions
a.read_some(mb) a.read_some(mb,ec) size_t Meets the requirements for a read operation ([buffer.reqmts.read.write]).
If buffer_size(mb) > 0, reads one or more bytes of data from the stream a into the buffer sequence mb. If successful, sets ec such that !ec is true, and returns the number of bytes read. If an error occurred, sets ec such that !!ec is true, and returns 0. If all data has been read from the stream, and the stream performed an orderly shutdown, sets ec to stream_errc::eof and returns 0. If buffer_size(mb) == 0, the operation shall not block. Sets ec such that !ec is true, and returns 0.

17.1.2 Buffer-oriented asynchronous read stream requirements [buffer.stream.reqmts.asyncreadstream]

A type X meets the AsyncReadStream requirements if it satisfies the requirements listed below.

In the table below, a denotes a value of type X, mb denotes a (possibly const) value of a type satisfying the MutableBufferSequence ([buffer.reqmts.mutablebuffersequence]) requirements, and t is a completion token.

Table 17 — AsyncReadStream requirements
operationtypesemantics, pre/post-conditions
a.get_executor() A type satisfying the Executor requirements ([async.reqmts.executor]). Returns the associated I/O executor.
a.async_read_some(mb,t) The return type is determined according to the requirements for an asynchronous operation ([async.reqmts.async]). Meets the requirements for a read operation ([buffer.reqmts.read.write]) and an asynchronous operation ([async.reqmts.async]) with completion signature void(error_code ec, size_t n).
If buffer_size(mb) > 0, initiates an asynchronous operation to read one or more bytes of data from the stream a into the buffer sequence mb. If successful, ec is set such that !ec is true, and n is the number of bytes read. If an error occurred, ec is set such that !!ec is true, and n is 0. If all data has been read from the stream, and the stream performed an orderly shutdown, ec is stream_errc::eof and n is 0. If buffer_size(mb) == 0, the operation completes immediately. ec is set such that !ec is true, and n is 0.

17.1.3 Buffer-oriented synchronous write stream requirements [buffer.stream.reqmts.syncwritestream]

A type X meets the SyncWriteStream requirements if it satisfies the requirements listed below.

In the table below, a denotes a value of type X, cb denotes a (possibly const) value of a type satisfying the ConstBufferSequence ([buffer.reqmts.constbuffersequence]) requirements, and ec denotes an object of type error_code.

Table 18 — SyncWriteStream requirements
operationtypesemantics, pre/post-conditions
a.write_some(cb) a.write_some(cb,ec) size_t Meets the requirements for a write operation ([buffer.reqmts.read.write]).
If buffer_size(cb) > 0, writes one or more bytes of data to the stream a from the buffer sequence cb. If successful, sets ec such that !ec is true, and returns the number of bytes written. If an error occurred, sets ec such that !!ec is true, and returns 0. If buffer_size(cb) == 0, the operation shall not block. Sets ec such that !ec is true, and returns 0.

17.1.4 Buffer-oriented asynchronous write stream requirements [buffer.stream.reqmts.asyncwritestream]

A type X meets the AsyncWriteStream requirements if it satisfies the requirements listed below.

In the table below, a denotes a value of type X, cb denotes a (possibly const) value of a type satisfying the ConstBufferSequence ([buffer.reqmts.constbuffersequence]) requirements, and t is a completion token.

Table 19 — AsyncWriteStream requirements
operationtypesemantics, pre/post-conditions
a.get_executor() A type satisfying the Executor requirements ([async.reqmts.executor]). Returns the associated I/O executor.
a.async_write_some(cb,t) The return type is determined according to the requirements for an asynchronous operation ([async.reqmts.async]). Meets the requirements for a write operation ([buffer.reqmts.read.write]) and an asynchronous operation ([async.reqmts.async]) with completion signature void(error_code ec, size_t n).
If buffer_size(cb) > 0, initiates an asynchronous operation to write one or more bytes of data to the stream a from the buffer sequence cb. If successful, ec is set such that !ec is true, and n is the number of bytes written. If an error occurred, ec is set such that !!ec is true, and n is 0. If buffer_size(cb) == 0, the operation completes immediately. ec is set such that !ec is true, and n is 0.

17.1.5 Completion condition requirements [buffer.stream.reqmts.completioncondition]

A completion condition is a function object that is used with the algorithms read ([buffer.read]), async_read ([buffer.async.read]), write ([buffer.write]), and async_write ([buffer.async.write]) to determine when the algorithm has completed transferring data.

A type X meets the CompletionCondition requirements if it satisfies the requirements of Destructible (C++ 2014 [destructible]) and CopyConstructible (C++ 2014 [copyconstructible]), as well as the additional requirements listed below.

In the table below, x denotes a value of type X, ec denotes a (possibly const) value of type error_code, and n denotes a (possibly const) value of type size_t.

Table 20 — CompletionCondition requirements
expressionreturn typeassertion/note pre/post-condition
x(ec, n) size_t Let n be the total number of bytes transferred by the read or write algorithm so far.
Returns the maximum number of bytes to be transferred on the next read_some, async_read_some, write_some, or async_write_some operation performed by the algorithm. Returns 0 to indicate that the algorithm is complete.

17.2 Class transfer_all [buffer.stream.transfer.all]

The class transfer_all is a completion condition that is used to specify that a read or write operation should continue until all of the data has been transferred, or until an error occurs.

namespace std {
namespace experimental {
namespace net {
inline namespace v1 {

  class transfer_all
  {
  public:
    size_t operator()(const error_code& ec, size_t) const;
  };

} // inline namespace v1
} // namespace net
} // namespace experimental
} // namespace std

The class transfer_all satisfies the CompletionCondition ([buffer.stream.reqmts.completioncondition]) requirements.

size_t operator()(const error_code& ec, size_t) const;

Returns: If !ec, an unspecified non-zero value. Otherwise 0.

17.3 Class transfer_at_least [buffer.stream.transfer.at.least]

The class transfer_at_least is a completion condition that is used to specify that a read or write operation should continue until a minimum number of bytes has been transferred, or until an error occurs.

namespace std {
namespace experimental {
namespace net {
inline namespace v1 {

  class transfer_at_least
  {
  public:
    explicit transfer_at_least(size_t m);
    size_t operator()(const error_code& ec, size_t n) const;
  private:
    size_t minimum_; // exposition only
  };

} // inline namespace v1
} // namespace net
} // namespace experimental
} // namespace std

The class transfer_at_least satisfies the CompletionCondition ([buffer.stream.reqmts.completioncondition]) requirements.

explicit transfer_at_least(size_t m);

Postconditions: minimum_ == m.

size_t operator()(const error_code& ec, size_t n) const;

Returns: If !ec && n < minimum_, an unspecified non-zero value. Otherwise 0.

17.4 Class transfer_exactly [buffer.stream.transfer.exactly]

The class transfer_exactly is a completion condition that is used to specify that a read or write operation should continue until an exact number of bytes has been transferred, or until an error occurs.

namespace std {
namespace experimental {
namespace net {
inline namespace v1 {

  class transfer_exactly
  {
  public:
    explicit transfer_exactly(size_t e);
    size_t operator()(const error_code& ec, size_t n) const;
  private:
    size_t exact_; // exposition only
  };

} // inline namespace v1
} // namespace net
} // namespace experimental
} // namespace std

The class transfer_exactly satisfies the CompletionCondition ([buffer.stream.reqmts.completioncondition]) requirements.

explicit transfer_exactly(size_t e);

Postconditions: exact_ == e.

size_t operator()(const error_code& ec, size_t n) const;

Returns: If !ec && n < exact_, the result of min(exact_ - n, N), where N is an unspecified non-zero value. Otherwise 0.

17.5 Synchronous read operations [buffer.read]

template<class SyncReadStream, class MutableBufferSequence> size_t read(SyncReadStream& stream, const MutableBufferSequence& buffers); template<class SyncReadStream, class MutableBufferSequence> size_t read(SyncReadStream& stream, const MutableBufferSequence& buffers, error_code& ec); template<class SyncReadStream, class MutableBufferSequence, class CompletionCondition> size_t read(SyncReadStream& stream, const MutableBufferSequence& buffers, CompletionCondition completion_condition); template<class SyncReadStream, class MutableBufferSequence, class CompletionCondition> size_t read(SyncReadStream& stream, const MutableBufferSequence& buffers, CompletionCondition completion_condition, error_code& ec);

A read operation ([buffer.reqmts.read.write]).

Effects: Clears ec, then reads data from the buffer-oriented synchronous read stream ([buffer.stream.reqmts.syncreadstream]) object stream by performing zero or more calls to the stream's read_some member function.

The completion_condition parameter specifies a completion condition to be called prior to each call to the stream's read_some member function. The completion condition is passed the error_code value from the most recent read_some call, and the total number of bytes transferred in the synchronous read operation so far. The completion condition return value specifies the maximum number of bytes to be read on the subsequent read_some call. Overloads where a completion condition is not specified behave as if called with an object of class transfer_all.

The synchronous read operation continues until:

  • the total number of bytes transferred is equal to buffer_size(buffers); or

  • the completion condition returns 0.

On return, ec contains the error_code value from the most recent read_some call.

Returns: The total number of bytes transferred in the synchronous read operation.

Remarks: This function shall not participate in overload resolution unless is_mutable_buffer_sequence_v<MutableBufferSequence> is true.

template<class SyncReadStream, class DynamicBuffer> size_t read(SyncReadStream& stream, DynamicBuffer&& b); template<class SyncReadStream, class DynamicBuffer> size_t read(SyncReadStream& stream, DynamicBuffer&& b, error_code& ec); template<class SyncReadStream, class DynamicBuffer, class CompletionCondition> size_t read(SyncReadStream& stream, DynamicBuffer&& b, CompletionCondition completion_condition); template<class SyncReadStream, class DynamicBuffer, class CompletionCondition> size_t read(SyncReadStream& stream, DynamicBuffer&& b, CompletionCondition completion_condition, error_code& ec);

Effects: Clears ec, then reads data from the synchronous read stream ([buffer.stream.reqmts.syncreadstream]) object stream by performing zero or more calls to the stream's read_some member function.

Data is placed into the dynamic buffer ([buffer.reqmts.dynamicbuffer]) object b. A mutable buffer sequence ([buffer.reqmts.mutablebuffersequence]) is obtained prior to each read_some call using b.prepare(N), where N is an unspecified value less than or equal to b.max_size() - b.size(). [ Note: Implementations can use b.capacity() when determining N, to minimize the number of read_some calls performed on the stream.  — end note ] After each read_some call, the implementation performs b.commit(n), where n is the return value from read_some.

The completion_condition parameter specifies a completion condition to be called prior to each call to the stream's read_some member function. The completion condition is passed the error_code value from the most recent read_some call, and the total number of bytes transferred in the synchronous read operation so far. The completion condition return value specifies the maximum number of bytes to be read on the subsequent read_some call. Overloads where a completion condition is not specified behave as if called with an object of class transfer_all.

The synchronous read operation continues until:

  • b.size() == b.max_size(); or

  • the completion condition returns 0.

On return, ec contains the error_code value from the most recent read_some call.

Returns: The total number of bytes transferred in the synchronous read operation.

Remarks: This function shall not participate in overload resolution unless is_dynamic_buffer_v<DynamicBuffer> is true.

17.6 Asynchronous read operations [buffer.async.read]

template<class AsyncReadStream, class MutableBufferSequence, class CompletionToken> DEDUCED async_read(AsyncReadStream& stream, const MutableBufferSequence& buffers, CompletionToken&& token); template<class AsyncReadStream, class MutableBufferSequence, class CompletionCondition, class CompletionToken> DEDUCED async_read(AsyncReadStream& stream, const MutableBufferSequence& buffers, CompletionCondition completion_condition, CompletionToken&& token);

A composed asynchronous read operation ([async.reqmts.async.composed], [buffer.reqmts.read.write]).

Completion signature: void(error_code ec, size_t n).

Effects: Reads data from the buffer-oriented asynchronous read stream ([buffer.stream.reqmts.asyncreadstream]) object stream by invoking the stream's async_read_some member function (henceforth referred to as asynchronous read_some operations) zero or more times.

The completion_condition parameter specifies a completion condition to be called prior to each asynchronous read_some operation. The completion condition is passed the error_code value from the most recent asynchronous read_some operation, and the total number of bytes transferred in the asynchronous read operation so far. The completion condition return value specifies the maximum number of bytes to be read on the subsequent asynchronous read_some operation. Overloads where a completion condition is not specified behave as if called with an object of class transfer_all.

This asynchronous read operation is outstanding until:

  • the total number of bytes transferred is equal to buffer_size(buffers); or

  • the completion condition returns 0.

The program shall ensure the AsyncReadStream object stream is valid until the completion handler for the asynchronous operation is invoked.

On completion of the asynchronous operation, ec is the error_code value from the most recent asynchronous read_some operation, and n is the total number of bytes transferred.

Remarks: This function shall not participate in overload resolution unless is_mutable_buffer_sequence_v<MutableBufferSequence> is true.

template<class AsyncReadStream, class DynamicBuffer, class CompletionToken> DEDUCED async_read(AsyncReadStream& stream, DynamicBuffer&& b, CompletionToken&& token); template<class AsyncReadStream, class DynamicBuffer, class CompletionCondition, class CompletionToken> DEDUCED async_read(AsyncReadStream& stream, DynamicBuffer&& b, CompletionCondition completion_condition, CompletionToken&& token);

Completion signature: void(error_code ec, size_t n).

Effects: Initiates an asynchronous operation to read data from the buffer-oriented asynchronous read stream ([buffer.stream.reqmts.asyncreadstream]) object stream by performing one or more asynchronous read_some operations on the stream.

Data is placed into the dynamic buffer ([buffer.reqmts.dynamicbuffer]) object b. A mutable buffer sequence ([buffer.reqmts.mutablebuffersequence]) is obtained prior to each async_read_some call using b.prepare(N), where N is an unspecified value such that N is less than or equal to b.max_size() - b.size(). [ Note: Implementations can use b.capacity() when determining N, to minimize the number of asynchronous read_some operations performed on the stream.  — end note ] After the completion of each asynchronous read_some operation, the implementation performs b.commit(n), where n is the value passed to the asynchronous read_some operation's completion handler.

The completion_condition parameter specifies a completion condition to be called prior to each asynchronous read_some operation. The completion condition is passed the error_code value from the most recent asynchronous read_some operation, and the total number of bytes transferred in the asynchronous read operation so far. The completion condition return value specifies the maximum number of bytes to be read on the subsequent asynchronous read_some operation. Overloads where a completion condition is not specified behave as if called with an object of class transfer_all.

The asynchronous read operation is outstanding until:

  • b.size() == b.max_size(); or

  • the completion condition returns 0.

The program shall ensure the AsyncReadStream object stream is valid until the completion handler for the asynchronous operation is invoked.

On completion of the asynchronous operation, ec is the error_code value from the most recent asynchronous read_some operation, and n is the total number of bytes transferred.

Remarks: This function shall not participate in overload resolution unless is_dynamic_buffer_v<DynamicBuffer> is true.

17.7 Synchronous write operations [buffer.write]

template<class SyncWriteStream, class ConstBufferSequence> size_t write(SyncWriteStream& stream, const ConstBufferSequence& buffers); template<class SyncWriteStream, class ConstBufferSequence> size_t write(SyncWriteStream& stream, const ConstBufferSequence& buffers, error_code& ec); template<class SyncWriteStream, class ConstBufferSequence, class CompletionCondition> size_t write(SyncWriteStream& stream, const ConstBufferSequence& buffers, CompletionCondition completion_condition); template<class SyncWriteStream, class ConstBufferSequence, class CompletionCondition> size_t write(SyncWriteStream& stream, const ConstBufferSequence& buffers, CompletionCondition completion_condition, error_code& ec);

A write operation ([buffer.reqmts.read.write]).

Effects: Writes data to the buffer-oriented synchronous write stream ([buffer.stream.reqmts.syncwritestream]) object stream by performing zero or more calls to the stream's write_some member function.

The completion_condition parameter specifies a completion condition to be called prior to each call to the stream's write_some member function. The completion condition is passed the error_code value from the most recent write_some call, and the total number of bytes transferred in the synchronous write operation so far. The completion condition return value specifies the maximum number of bytes to be written on the subsequent write_some call. Overloads where a completion condition is not specified behave as if called with an object of class transfer_all.

The synchronous write operation continues until:

  • the total number of bytes transferred is equal to buffer_size(buffers); or

  • the completion condition returns 0.

On return, ec contains the error_code value from the most recent write_some call.

Returns: The total number of bytes transferred in the synchronous write operation.

Remarks: This function shall not participate in overload resolution unless is_const_buffer_sequence<ConstBufferSequence>::value is true.

template<class SyncWriteStream, class DynamicBuffer> size_t write(SyncWriteStream& stream, DynamicBuffer&& b); template<class SyncWriteStream, class DynamicBuffer> size_t write(SyncWriteStream& stream, DynamicBuffer&& b, error_code& ec); template<class SyncWriteStream, class DynamicBuffer, class CompletionCondition> size_t write(SyncWriteStream& stream, DynamicBuffer&& b, CompletionCondition completion_condition); template<class SyncWriteStream, class DynamicBuffer, class CompletionCondition> size_t write(SyncWriteStream& stream, DynamicBuffer&& b, CompletionCondition completion_condition, error_code& ec);

Effects: Writes data to the synchronous write stream ([buffer.stream.reqmts.syncwritestream]) object stream by performing zero or more calls to the stream's write_some member function.

Data is written from the dynamic buffer ([buffer.reqmts.dynamicbuffer]) object b. A constant buffer sequence ([buffer.reqmts.constbuffersequence]) is obtained using b.data(). After the data has been written to the stream, the implementation performs b.consume(n), where n is the number of bytes successfully written.

The completion_condition parameter specifies a completion condition to be called after each call to the stream's write_some member function. The completion condition is passed the error_code value from the most recent write_some call, and the total number of bytes transferred in the synchronous write operation so far. The completion condition return value specifies the maximum number of bytes to be written on the subsequent write_some call. Overloads where a completion condition is not specified behave as if called with an object of class transfer_all.

The synchronous write operation continues until:

  • b.size() == 0; or

  • the completion condition returns 0.

On return, ec contains the error_code value from the most recent write_some call.

Returns: The total number of bytes transferred in the synchronous write operation.

Remarks: This function shall not participate in overload resolution unless is_dynamic_buffer_v<DynamicBuffer> is true.

17.8 Asynchronous write operations [buffer.async.write]

template<class AsyncWriteStream, class ConstBufferSequence, class CompletionToken> DEDUCED async_write(AsyncWriteStream& stream, const ConstBufferSequence& buffers, CompletionToken&& token); template<class AsyncWriteStream, class ConstBufferSequence, class CompletionCondition, class CompletionToken> DEDUCED async_write(AsyncWriteStream& stream, const ConstBufferSequence& buffers, CompletionCondition completion_condition, CompletionToken&& token);

A composed asynchronous write operation ([async.reqmts.async.composed], [buffer.reqmts.read.write]).

Completion signature: void(error_code ec, size_t n).

Effects: Initiates an asynchronous operation to write data to the buffer-oriented asynchronous write stream ([buffer.stream.reqmts.asyncwritestream]) object stream by performing zero or more asynchronous operations on the stream using the stream's async_write_some member function (henceforth referred to as asynchronous write_some operations).

The completion_condition parameter specifies a completion condition to be called prior to each asynchronous write_some operation. The completion condition is passed the error_code value from the most recent asynchronous write_some operation, and the total number of bytes transferred in the asynchronous write operation so far. The completion condition return value specifies the maximum number of bytes to be written on the subsequent asynchronous write_some operation. Overloads where a completion condition is not specified behave as if called with an object of class transfer_all.

The asynchronous write operation continues until:

  • the total number of bytes transferred is equal to buffer_size(buffers); or

  • the completion condition returns 0.

The program shall ensure the AsyncWriteStream object stream is valid until the completion handler for the asynchronous operation is invoked.

On completion of the asynchronous operation, ec is the error_code value from the most recent asynchronous write_some operation, and n is the total number of bytes transferred.

Remarks: This function shall not participate in overload resolution unless is_const_buffer_sequence<ConstBufferSequence>::value is true.

template<class AsyncWriteStream, class DynamicBuffer, class CompletionToken> DEDUCED async_write(AsyncWriteStream& stream, DynamicBuffer&& b, CompletionToken&& token); template<class AsyncWriteStream, class DynamicBuffer, class CompletionCondition, class CompletionToken> DEDUCED async_write(AsyncWriteStream& stream, DynamicBuffer&& b, CompletionCondition completion_condition, CompletionToken&& token);

Completion signature: void(error_code ec, size_t n).

Effects: Initiates an asynchronous operation to write data to the buffer-oriented asynchronous write stream ([buffer.stream.reqmts.asyncwritestream]) object stream by performing zero or more asynchronous write_some operations on the stream.

Data is written from the dynamic buffer ([buffer.reqmts.dynamicbuffer]) object b. A constant buffer sequence ([buffer.reqmts.constbuffersequence]) is obtained using b.data(). After the data has been written to the stream, the implementation performs b.consume(n), where n is the number of bytes successfully written.

The completion_condition parameter specifies a completion condition to be called prior to each asynchronous write_some operation. The completion condition is passed the error_code value from the most recent asynchronous write_some operation, and the total number of bytes transferred in the asynchronous write operation so far. The completion condition return value specifies the maximum number of bytes to be written on the subsequent asynchronous write_some operation. Overloads where a completion condition is not specified behave as if called with an object of class transfer_all.

The asynchronous write operation continues until:

  • b.size() == 0; or

  • the completion condition returns 0.

The program shall ensure both the AsyncWriteStream object stream and the memory associated with the dynamic buffer b are valid until the completion handler for the asynchronous operation is invoked.

On completion of the asynchronous operation, ec is the error_code value from the most recent asynchronous write_some operation, and n is the total number of bytes transferred.

Remarks: This function shall not participate in overload resolution unless is_dynamic_buffer_v<DynamicBuffer> is true.

17.9 Synchronous delimited read operations [buffer.read.until]

template<class SyncReadStream, class DynamicBuffer> size_t read_until(SyncReadStream& s, DynamicBuffer&& b, char delim); template<class SyncReadStream, class DynamicBuffer> size_t read_until(SyncReadStream& s, DynamicBuffer&& b, char delim, error_code& ec); template<class SyncReadStream, class DynamicBuffer> size_t read_until(SyncReadStream& s, DynamicBuffer&& b, string_view delim); template<class SyncReadStream, class DynamicBuffer> size_t read_until(SyncReadStream& s, DynamicBuffer&& b, string_view delim, error_code& ec);

Effects: Reads data from the buffer-oriented synchronous read stream ([buffer.stream.reqmts.syncreadstream]) object stream by performing zero or more calls to the stream's read_some member function, until the readable bytes of the dynamic buffer ([buffer.reqmts.dynamicbuffer]) object b contains the specified delimiter delim.

Data is placed into the dynamic buffer object b. A mutable buffer sequence ([buffer.reqmts.mutablebuffersequence]) is obtained prior to each read_some call using b.prepare(N), where N is an unspecified value such that N <= max_size() - size(). [ Note: Implementations can use b.capacity() when determining N, to minimize the number of read_some calls performed on the stream.  — end note ] After each read_some call, the implementation performs b.commit(n), where n is the return value from read_some.

The synchronous read_until operation continues until:

  • the readable bytes of b contains the delimiter delim; or

  • b.size() == b.max_size(); or

  • an asynchronous read_some operation fails.

On exit, if the readable bytes of b contains the delimiter, ec is set such that !ec is true. Otherwise, if b.size() == b.max_size(), ec is set such that ec == stream_errc::not_found. If b.size() < b.max_size(), ec contains the error_code from the most recent read_some call.

Returns: The number of bytes in the readable bytes of b up to and including the delimiter, if present. [ Note: On completion, the buffer can contain additional bytes following the delimiter.  — end note ] Otherwise returns 0.

17.10 Asynchronous delimited read operations [buffer.async.read.until]

template<class AsyncReadStream, class DynamicBuffer, class CompletionToken> DEDUCED async_read_until(AsyncReadStream& s, DynamicBuffer&& b, char delim, CompletionToken&& token); template<class AsyncReadStream, class DynamicBuffer, class CompletionToken> DEDUCED async_read_until(AsyncReadStream& s, DynamicBuffer&& b, string_view delim, CompletionToken&& token);

A composed asynchronous operation ([async.reqmts.async.composed]).

Completion signature: void(error_code ec, size_t n).

Effects: Initiates an asynchronous operation to read data from the buffer-oriented asynchronous read stream ([buffer.stream.reqmts.asyncreadstream]) object stream by performing zero or more asynchronous read_some operations on the stream, until the readable bytes of the dynamic buffer ([buffer.reqmts.dynamicbuffer]) object b contain the specified delimiter delim.

Data is placed into the dynamic buffer object b. A mutable buffer sequence ([buffer.reqmts.mutablebuffersequence]) is obtained prior to each async_read_some call using b.prepare(N), where N is an unspecified value such that N <= max_size() - size(). [ Note: Implementations can use b.capacity() when determining N, to minimize the number of asynchronous read_some operations performed on the stream.  — end note ] After the completion of each asynchronous read_some operation, the implementation performs b.commit(n), where n is the value passed to the asynchronous read_some operation's completion handler.

The asynchronous read_until operation continues until:

  • the readable bytes of b contain the delimiter delim; or

  • b.size() == b.max_size(); or

  • an asynchronous read_some operation fails.

The program shall ensure the AsyncReadStream object stream is valid until the completion handler for the asynchronous operation is invoked.

If delim is of type string_view, the implementation copies the underlying sequence of characters prior to initiating an asynchronous read_some operation on the stream. [ Note: This means that the caller is not required to guarantee the validity of the delimiter string after the call to async_read_until returns.  — end note ]

On completion of the asynchronous operation, if the readable bytes of b contain the delimiter, ec is set such that !ec is true. Otherwise, if b.size() == b.max_size(), ec is set such that ec == stream_errc::not_found. If b.size() < b.max_size(), ec is the error_code from the most recent asynchronous read_some operation. n is the number of readable bytes in b up to and including the delimiter, if present, otherwise 0.