16 Buffers [buffer]

16.1 Header <experimental/buffer> synopsis [buffer.synop]

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

  enum class stream_errc {
    eof = an implementation-defined non-zero value,
    not_found = an implementation-defined non-zero value
  };

  const error_category& stream_category() noexcept;

  error_code make_error_code(stream_errc e) noexcept;
  error_condition make_error_condition(stream_errc e) noexcept;

  class mutable_buffer;
  class const_buffer;

  // [buffer.traits], buffer type traits:

  template<class T> struct is_mutable_buffer_sequence;
  template<class T> struct is_const_buffer_sequence;
  template<class T> struct is_dynamic_buffer;

  template<class T>
    constexpr bool is_mutable_buffer_sequence_v = is_mutable_buffer_sequence<T>::value;
  template<class T>
    constexpr bool is_const_buffer_sequence_v = is_const_buffer_sequence<T>::value;
  template<class T>
    constexpr bool is_dynamic_buffer_v = is_dynamic_buffer<T>::value;

  // [buffer.seq.access], buffer sequence access:

  const mutable_buffer* buffer_sequence_begin(const mutable_buffer& b) noexcept;
  const const_buffer* buffer_sequence_begin(const const_buffer& b) noexcept;
  const mutable_buffer* buffer_sequence_end(const mutable_buffer& b) noexcept;
  const const_buffer* buffer_sequence_end(const const_buffer& b) noexcept;
  template<class C> auto buffer_sequence_begin(C& c) noexcept -> decltype(c.begin());
  template<class C> auto buffer_sequence_begin(const C& c) noexcept -> decltype(c.begin());
  template<class C> auto buffer_sequence_end(C& c) noexcept -> decltype(c.end());
  template<class C> auto buffer_sequence_end(const C& c) noexcept -> decltype(c.end());

  // [buffer.size], buffer size:

  template<class ConstBufferSequence>
    size_t buffer_size(const ConstBufferSequence& buffers) noexcept;

  // [buffer.copy], buffer copy:

  template<class MutableBufferSequence, class ConstBufferSequence>
    size_t buffer_copy(const MutableBufferSequence& dest,
                       const ConstBufferSequence& source) noexcept;
  template<class MutableBufferSequence, class ConstBufferSequence>
    size_t buffer_copy(const MutableBufferSequence& dest,
                       const ConstBufferSequence& source,
                       size_t max_size) noexcept;

  // [buffer.arithmetic], buffer arithmetic:

  mutable_buffer operator+(const mutable_buffer& b, size_t n) noexcept;
  mutable_buffer operator+(size_t n, const mutable_buffer& b) noexcept;
  const_buffer operator+(const const_buffer&, size_t n) noexcept;
  const_buffer operator+(size_t, const const_buffer&) noexcept;

  // [buffer.creation], buffer creation:

  mutable_buffer buffer(void* p, size_t n) noexcept;
  const_buffer buffer(const void* p, size_t n) noexcept;

  mutable_buffer buffer(const mutable_buffer& b) noexcept;
  mutable_buffer buffer(const mutable_buffer& b, size_t n) noexcept;
  const_buffer buffer(const const_buffer& b) noexcept;
  const_buffer buffer(const const_buffer& b, size_t n) noexcept;

  template<class T, size_t N>
    mutable_buffer buffer(T (&data)[N]) noexcept;
  template<class T, size_t N>
    const_buffer buffer(const T (&data)[N]) noexcept;
  template<class T, size_t N>
    mutable_buffer buffer(array<T, N>& data) noexcept;
  template<class T, size_t N>
    const_buffer buffer(array<const T, N>& data) noexcept;
  template<class T, size_t N>
    const_buffer buffer(const array<T, N>& data) noexcept;
  template<class T, class Allocator>
    mutable_buffer buffer(vector<T, Allocator>& data) noexcept;
  template<class T, class Allocator>
    const_buffer buffer(const vector<T, Allocator>& data) noexcept;
  template<class CharT, class Traits, class Allocator>
    mutable_buffer buffer(basic_string<CharT, Traits, Allocator>& data) noexcept;
  template<class CharT, class Traits, class Allocator>
    const_buffer buffer(const basic_string<CharT, Traits, Allocator>& data) noexcept;
  template<class CharT, class Traits>
    const_buffer buffer(basic_string_view<CharT, Traits> data) noexcept;

  template<class T, size_t N>
    mutable_buffer buffer(T (&data)[N], size_t n) noexcept;
  template<class T, size_t N>
    const_buffer buffer(const T (&data)[N], size_t n) noexcept;
  template<class T, size_t N>
    mutable_buffer buffer(array<T, N>& data, size_t n) noexcept;
  template<class T, size_t N>
    const_buffer buffer(array<const T, N>& data, size_t n) noexcept;
  template<class T, size_t N>
    const_buffer buffer(const array<T, N>& data, size_t n) noexcept;
  template<class T, class Allocator>
    mutable_buffer buffer(vector<T, Allocator>& data, size_t n) noexcept;
  template<class T, class Allocator>
    const_buffer buffer(const vector<T, Allocator>& data, size_t n) noexcept;
  template<class CharT, class Traits, class Allocator>
    mutable_buffer buffer(basic_string<CharT, Traits, Allocator>& data,
                          size_t n) noexcept;
  template<class CharT, class Traits, class Allocator>
    const_buffer buffer(const basic_string<CharT, Traits, Allocator>& data,
                        size_t n) noexcept;
  template<class CharT, class Traits>
    const_buffer buffer(basic_string_view<CharT, Traits> data,
                        size_t n) noexcept;

  template<class T, class Allocator>
    class dynamic_vector_buffer;

  template<class CharT, class Traits, class Allocator>
    class dynamic_string_buffer;

  // [buffer.dynamic.creation], dynamic buffer creation:

  template<class T, class Allocator>
    dynamic_vector_buffer<T, Allocator>
    dynamic_buffer(vector<T, Allocator>& vec) noexcept;
  template<class T, class Allocator>
    dynamic_vector_buffer<T, Allocator>
    dynamic_buffer(vector<T, Allocator>& vec, size_t n) noexcept;

  template<class CharT, class Traits, class Allocator>
    dynamic_string_buffer<CharT, Traits, Allocator>
    dynamic_buffer(basic_string<CharT, Traits, Allocator>& str) noexcept;
  template<class CharT, class Traits, class Allocator>
    dynamic_string_buffer<CharT, Traits, Allocator>
    dynamic_buffer(basic_string<CharT, Traits, Allocator>& str, size_t n) noexcept;

  class transfer_all;
  class transfer_at_least;
  class transfer_exactly;

  // [buffer.read], synchronous read operations:

  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);

  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);

  // [buffer.async.read], asynchronous read operations:

  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);

  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);

  // [buffer.write], synchronous write operations:

  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);

  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);

  // [buffer.async.write], asynchronous write operations:

  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);

  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);

  // [buffer.read.until], synchronous delimited read operations:

  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);

  // [buffer.async.read.until], asynchronous delimited read operations:

  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);

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

  template<> struct is_error_code_enum<experimental::net::v1::stream_errc>
    : public true_type {};

} // namespace std

16.2 Requirements [buffer.reqmts]

16.2.1 Mutable buffer sequence requirements [buffer.reqmts.mutablebuffersequence]

A mutable buffer sequence represents a set of memory regions that may be used to receive the output of an operation, such as the receive operation of a socket.

A type X meets the MutableBufferSequence requirements if it satisfies the requirements of Destructible (C++ 2014 [destructible]) and CopyConstructible (C++ 2014 [copyconstructible]), as well as the additional requirements listed in Table [tab:buffer.reqmts.mutablebuffersequence.requirements].

In Table [tab:buffer.reqmts.mutablebuffersequence.requirements], x denotes a (possibly const) value of type X, and u denotes an identifier.

Table 12 — MutableBufferSequence requirements
expressionreturn typeassertion/note
pre/post-condition
net::buffer_sequence_begin(x)
net::buffer_sequence_end(x)
An iterator type whose reference type is convertible to mutable_buffer, and which satisfies all the requirements for bidirectional iterators (C++ 2014 [bidirectional.iterators]) except that:
  • there is no requirement that operator-> is provided, and

  • there is no requirement that reference be a reference type.

For a dereferenceable iterator, no increment, decrement, or dereference operation, or conversion of the reference type to mutable_buffer, shall exit via an exception.
X u(x); post:
equal(
  net::buffer_sequence_begin(x),
  net::buffer_sequence_end(x),
  net::buffer_sequence_begin(u),
  net::buffer_sequence_end(u),
  [](const mutable_buffer& b1,
     const mutable_buffer& b2)
   {
     return b1.data() == b2.data()
         && b1.size() == b2.size();
   })

16.2.2 Constant buffer sequence requirements [buffer.reqmts.constbuffersequence]

A constant buffer sequence represents a set of memory regions that may be used as input to an operation, such as the send operation of a socket.

A type X meets the ConstBufferSequence requirements if it satisfies the requirements of Destructible (C++ 2014 [destructible]) and CopyConstructible (C++ 2014 [copyconstructible]), as well as the additional requirements listed in Table [tab:buffer.reqmts.constbuffersequence.requirements].

In Table [tab:buffer.reqmts.constbuffersequence.requirements], x denotes a (possibly const) value of type X, and u denotes an identifier.

Table 13 — ConstBufferSequence requirements
expressionreturn typeassertion/note
pre/post-condition
net::buffer_sequence_begin(x)
net::buffer_sequence_end(x)
An iterator type whose reference type is convertible to const_buffer, and which satisfies all the requirements for bidirectional iterators (C++ 2014 [bidirectional.iterators]) except that:
  • there is no requirement that operator-> is provided, and

  • there is no requirement that reference be a reference type.

For a dereferenceable iterator, no increment, decrement, or dereference operation, or conversion of the reference type to const_buffer, shall exit via an exception.
X u(x); post:
equal(
  net::buffer_sequence_begin(x),
  net::buffer_sequence_end(x),
  net::buffer_sequence_begin(u),
  net::buffer_sequence_end(u),
  [](const const_buffer& b1,
     const const_buffer& b2)
   {
     return b1.data() == b2.data()
         && b1.size() == b2.size();
   })

16.2.3 Buffer size [buffer.reqmts.size]

Several places in this document make unqualified calls to buffer_size. The context in which these calls are evaluated shall ensure that a unary non-member function named buffer_size is selected via overload resolution (C++ 2014 [over.match]) on a candidate set that includes:

  • the buffer_size function template defined in <experimental/buffer> ([buffer.synop]) and

  • the lookup set produced by argument-dependent lookup (C++ 2014 [basic.lookup.argdep]).

16.2.4 Dynamic buffer requirements [buffer.reqmts.dynamicbuffer]

A dynamic buffer encapsulates memory storage that may be automatically resized as required, where the memory is divided into two regions: readable bytes followed by writable bytes. These memory regions are internal to the dynamic buffer, but direct access to the elements is provided to permit them to be efficiently used with I/O operations. [ Note: Such as the send or receive operations of a socket. The readable bytes would be used as the constant buffer sequence for send, and the writable bytes used as the mutable buffer sequence for receive.  — end note ] Data written to the writable bytes of a dynamic buffer object is appended to the readable bytes of the same object.

A type X meets the DynamicBuffer requirements if it satisfies the requirements of Destructible (C++ 2014 [destructible]) and MoveConstructible (C++ 2014 [moveconstructible]), as well as the additional requirements listed in Table [tab:buffer.reqmts.dynamicbuffer.requirements].

In Table [tab:buffer.reqmts.dynamicbuffer.requirements], x denotes a value of type X, x1 denotes a (possibly const) value of type X, and n denotes a (possibly const) value of type size_t.

Table 14 — DynamicBuffer requirements
expressiontypeassertion/note pre/post-conditions
X::const_buffers_type type meeting ConstBufferSequence ([buffer.reqmts.constbuffersequence]) requirements. This type represents the memory associated with the readable bytes.
X::mutable_buffers_type type meeting MutableBufferSequence ([buffer.reqmts.constbuffersequence]) requirements. This type represents the memory associated with the writable bytes.
x1.size() size_t Returns the number of readable bytes.
x1.max_size() size_t Returns the maximum number of bytes, both readable and writable, that can be held by x1.
x1.capacity() size_t Returns the maximum number of bytes, both readable and writable, that can be held by x1 without requiring reallocation.
x1.data() X::const_buffers_type Returns a constant buffer sequence u that represents the readable bytes, and where buffer_size(u) == size().
x.prepare(n) X::mutable_buffers_type Returns a mutable buffer sequence u representing the writable bytes, and where buffer_size(u) == n. The dynamic buffer reallocates memory as required. All constant or mutable buffer sequences previously obtained using data() or prepare() are invalidated.
Throws: length_error if size() + n exceeds max_size().
x.commit(n) Appends n bytes from the start of the writable bytes to the end of the readable bytes. The remainder of the writable bytes are discarded. If n is greater than the number of writable bytes, all writable bytes are appended to the readable bytes. All constant or mutable buffer sequences previously obtained using data() or prepare() are invalidated.
x.consume(n) Removes n bytes from beginning of the readable bytes. If n is greater than the number of readable bytes, all readable bytes are removed. All constant or mutable buffer sequences previously obtained using data() or prepare() are invalidated.

16.2.5 Requirements on read and write operations [buffer.reqmts.read.write]

A read operation is an operation that reads data into a mutable buffer sequence argument of a type meeting MutableBufferSequence ([buffer.reqmts.mutablebuffersequence]) requirements. The mutable buffer sequence specifies memory where the data should be placed. A read operation shall always fill a buffer in the sequence completely before proceeding to the next.

A write operation is an operation that writes data from a constant buffer sequence argument of a type meeting ConstBufferSequence ([buffer.reqmts.constbuffersequence]) requirements. The constant buffer sequence specifies memory where the data to be written is located. A write operation shall always write a buffer in the sequence completely before proceeding to the next.

If a read or write operation is also an asynchronous operation ([async.reqmts.async]), the operation shall maintain one or more copies of the buffer sequence until such time as the operation no longer requires access to the memory specified by the buffers in the sequence. The program shall ensure the memory remains valid until:

  • the last copy of the buffer sequence is destroyed, or

  • the completion handler for the asynchronous operation is invoked,

whichever comes first.

16.3 Error codes [buffer.err]

const error_category& stream_category() noexcept;

Returns: A reference to an object of a type derived from class error_category. All calls to this function return references to the same object.

The object's default_error_condition and equivalent virtual functions behave as specified for the class error_category. The object's name virtual function returns a pointer to the string "stream".

error_code make_error_code(stream_errc e) noexcept;

Returns: error_code(static_cast<int>(e), stream_category()).

error_condition make_error_condition(stream_errc e) noexcept;

Returns: error_condition(static_cast<int>(e), stream_category()).

16.4 Class mutable_buffer [buffer.mutable]

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

  class mutable_buffer
  {
  public:
    // constructors:
    mutable_buffer() noexcept;
    mutable_buffer(void* p, size_t n) noexcept;

    // members:
    void* data() const noexcept;
    size_t size() const noexcept;
    mutable_buffer& operator+=(size_t n) noexcept;

  private:
    void* data_; // exposition only
    size_t size_; // exposition only
  };

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

The mutable_buffer class satisfies the requirements of MutableBufferSequence ([buffer.reqmts.mutablebuffersequence]), DefaultConstructible (C++ 2014 [defaultconstructible]), and CopyAssignable (C++ 2014 [copyassignable]).

mutable_buffer() noexcept;

Postconditions: data_ == nullptr and size_ == 0.

mutable_buffer(void* p, size_t n) noexcept;

Postconditions: data_ == p and size_ == n.

void* data() const noexcept;

Returns: data_.

size_t size() const noexcept;

Returns: size_.

mutable_buffer& operator+=(size_t n) noexcept;

Effects: Sets data_ to static_cast<char*>(data_) + min(n, size_), and then size_ to size_ - min(n, size_).

Returns: *this.

16.5 Class const_buffer [buffer.const]

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

  class const_buffer
  {
  public:
    // constructors:
    const_buffer() noexcept;
    const_buffer(const void* p, size_t n) noexcept;
    const_buffer(const mutable_buffer& b) noexcept;

    // members:
    const void* data() const noexcept;
    size_t size() const noexcept;
    const_buffer& operator+=(size_t n) noexcept;

  private:
    const void* data_; // exposition only
    size_t size_; // exposition only
  };

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

The const_buffer class satisfies requirements of ConstBufferSequence ([buffer.reqmts.constbuffersequence]), DefaultConstructible (C++ 2014 [defaultconstructible]), and CopyAssignable (C++ 2014 [copyassignable]).

const_buffer() noexcept;

Postconditions: data_ == nullptr and size_ == 0.

const_buffer(const void* p, size_t n) noexcept;

Postconditions: data_ == p and size_ == n.

const_buffer(const mutable_buffer& b);

Postconditions: data_ == b.data() and size_ == b.size().

const void* data() const noexcept;

Returns: data_.

size_t size() const noexcept;

Returns: size_.

const_buffer& operator+=(size_t n) noexcept;

Effects: Sets data_ to static_cast<const char*>(data_) + min(n, size_), and then size_ to size_ - min(n, size_).

Returns: *this.

16.6 Buffer type traits [buffer.traits]

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

  template<class T> struct is_mutable_buffer_sequence;
  template<class T> struct is_const_buffer_sequence;
  template<class T> struct is_dynamic_buffer;

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

This subclause contains templates that may be used to query the properties of a type at compile time. Each of these templates is a UnaryTypeTrait (C++ 2014 [meta.rqmts]) with a BaseCharacteristic of true_type if the corresponding condition is true, otherwise false_type.

Table 15 — Buffer type traits
TemplateConditionPreconditions
template<class T>
struct is_mutable_buffer_sequence
T meets the syntactic requirements for mutable buffer sequence ([buffer.reqmts.mutablebuffersequence]). T is a complete type.
template<class T>
struct is_const_buffer_sequence
T meets the syntactic requirements for constant buffer sequence ([buffer.reqmts.constbuffersequence]). T is a complete type.
template<class T>
struct is_dynamic_buffer
T meets the syntactic requirements for dynamic buffer ([buffer.reqmts.dynamicbuffer]). T is a complete type.

16.7 Buffer sequence access [buffer.seq.access]

const mutable_buffer* buffer_sequence_begin(const mutable_buffer& b) noexcept; const const_buffer* buffer_sequence_begin(const const_buffer& b) noexcept;

Returns: std::addressof(b).

const mutable_buffer* buffer_sequence_end(const mutable_buffer& b) noexcept; const const_buffer* buffer_sequence_end(const const_buffer& b) noexcept;

Returns: std::addressof(b) + 1.

template<class C> auto buffer_sequence_begin(C& c) noexcept -> decltype(c.begin()); template<class C> auto buffer_sequence_begin(const C& c) noexcept -> decltype(c.begin());

Returns: c.begin().

template<class C> auto buffer_sequence_end(C& c) noexcept -> decltype(c.end()); template<class C> auto buffer_sequence_end(const C& c) noexcept -> decltype(c.end());

Returns: c.end().

16.8 Function buffer_size [buffer.size]

template<class ConstBufferSequence> size_t buffer_size(const ConstBufferSequence& buffers) noexcept;

Returns: The total size of all buffers in the sequence, as if computed as follows:

size_t total_size = 0;
auto i = std::experimental::net::buffer_sequence_begin(buffers);
auto end = std::experimental::net::buffer_sequence_end(buffers);
for (; i != end; ++i){
  const_buffer b(*i);
  total_size += b.size();
}
return total_size;

16.9 Function buffer_copy [buffer.copy]

template<class MutableBufferSequence, class ConstBufferSequence> size_t buffer_copy(const MutableBufferSequence& dest, const ConstBufferSequence& source) noexcept; template<class MutableBufferSequence, class ConstBufferSequence> size_t buffer_copy(const MutableBufferSequence& dest, const ConstBufferSequence& source, size_t max_size) noexcept;

Effects: Copies bytes from the buffer sequence source to the buffer sequence dest, as if by calls to memcpy.

The number of bytes copied is the lesser of:

  • buffer_size(dest);

  • buffer_size(source); and

  • max_size, if specified.

The mutable buffer sequence dest specifies memory where the data should be placed. The operation always fills a buffer in the sequence completely before proceeding to the next.

The constant buffer sequence source specifies memory where the data to be written is located. The operation always copies a buffer in the sequence completely before proceeding to the next.

Returns: The number of bytes copied from source to dest.

16.10 Buffer arithmetic [buffer.arithmetic]

mutable_buffer operator+(const mutable_buffer& b, size_t n) noexcept; mutable_buffer operator+(size_t n, const mutable_buffer& b) noexcept;

Returns: A mutable_buffer equivalent to

mutable_buffer(
  static_cast<char*>(b.data()) + min(n, b.size()),
  b.size() - min(n, b.size()));

const_buffer operator+(const const_buffer& b, size_t n) noexcept; const_buffer operator+(size_t n, const const_buffer& b) noexcept;

Returns: A const_buffer equivalent to

const_buffer(
  static_cast<const char*>(b.data()) + min(n, b.size()),
  b.size() - min(n, b.size()));

16.11 Buffer creation functions [buffer.creation]

In the functions below, T shall be a trivially copyable or standard-layout type (C++ 2014 [basic.types]).

For the function overloads below that accept an argument of type vector<>, the buffer objects returned are invalidated by any vector operation that also invalidates all references, pointers and iterators referring to the elements in the sequence (C++ 2014 [vector]).

For the function overloads below that accept an argument of type basic_string<>, the buffer objects returned are invalidated according to the rules defined for invalidation of references, pointers and iterators referring to elements of the sequence (C++ 2014 [string.require]).

mutable_buffer buffer(void* p, size_t n) noexcept;

Returns: mutable_buffer(p, n).

const_buffer buffer(const void* p, size_t n) noexcept;

Returns: const_buffer(p, n).

mutable_buffer buffer(const mutable_buffer& b) noexcept;

Returns: b.

mutable_buffer buffer(const mutable_buffer& b, size_t n) noexcept;

Returns: mutable_buffer(b.data(), min(b.size(), n)).

const_buffer buffer(const const_buffer& b) noexcept;

Returns: b.

const_buffer buffer(const const_buffer& b, size_t n) noexcept;

Returns: const_buffer(b.data(), min(b.size(), n)).

template<class T, size_t N> mutable_buffer buffer(T (&data)[N]) noexcept; template<class T, size_t N> const_buffer buffer(const T (&data)[N]) noexcept; template<class T, size_t N> mutable_buffer buffer(array<T, N>& data) noexcept; template<class T, size_t N> const_buffer buffer(array<const T, N>& data) noexcept; template<class T, size_t N> const_buffer buffer(const array<T, N>& data) noexcept; template<class T, class Allocator> mutable_buffer buffer(vector<T, Allocator>& data) noexcept; template<class T, class Allocator> const_buffer buffer(const vector<T, Allocator>& data) noexcept; template<class CharT, class Traits, class Allocator> mutable_buffer buffer(basic_string<CharT, Traits, Allocator>& data) noexcept; template<class CharT, class Traits, class Allocator> const_buffer buffer(const basic_string<CharT, Traits, Allocator>& data) noexcept; template<class CharT, class Traits> const_buffer buffer(basic_string_view<CharT, Traits> data) noexcept;

Returns:

buffer(
  begin(data) != end(data) ? std::addressof(*begin(data)) : nullptr,
  (end(data) - begin(data)) * sizeof(*begin(data)));

template<class T, size_t N> mutable_buffer buffer(T (&data)[N], size_t n) noexcept; template<class T, size_t N> const_buffer buffer(const T (&data)[N], size_t n) noexcept; template<class T, size_t N> mutable_buffer buffer(array<T, N>& data, size_t n) noexcept; template<class T, size_t N> const_buffer buffer(array<const T, N>& data, size_t n) noexcept; template<class T, size_t N> const_buffer buffer(const array<T, N>& data, size_t n) noexcept; template<class T, class Allocator> mutable_buffer buffer(vector<T, Allocator>& data, size_t n) noexcept; template<class T, class Allocator> const_buffer buffer(const vector<T, Allocator>& data, size_t n) noexcept; template<class CharT, class Traits, class Allocator> mutable_buffer buffer(basic_string<CharT, Traits, Allocator>& data, size_t n) noexcept; template<class CharT, class Traits, class Allocator> const_buffer buffer(const basic_string<CharT, Traits, Allocator>& data, size_t n) noexcept; template<class CharT, class Traits> const_buffer buffer(basic_string_view<CharT, Traits> data, size_t n) noexcept;

Returns: buffer(buffer(data), n).

16.12 Class template dynamic_vector_buffer [buffer.dynamic.vector]

Class template dynamic_vector_buffer is an adaptor used to automatically grow or shrink a vector object, to reflect the data successfully transferred in an I/O operation.

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

  template<class T, class Allocator>
  class dynamic_vector_buffer
  {
  public:
    // types:
    using const_buffers_type = const_buffer;
    using mutable_buffers_type = mutable_buffer;

    // constructors:
    explicit dynamic_vector_buffer(vector<T, Allocator>& vec) noexcept;
    dynamic_vector_buffer(vector<T, Allocator>& vec,
                          size_t maximum_size) noexcept;
    dynamic_vector_buffer(dynamic_vector_buffer&&) = default;

    // members:
    size_t size() const noexcept;
    size_t max_size() const noexcept;
    size_t capacity() const noexcept;
    const_buffers_type data() const noexcept;
    mutable_buffers_type prepare(size_t n);
    void commit(size_t n);
    void consume(size_t n);

  private:
    vector<T, Allocator>& vec_; // exposition only
    size_t size_; // exposition only
    const size_t max_size_; // exposition only
  };

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

The dynamic_vector_buffer class template meets the requirements of DynamicBuffer ([buffer.reqmts.dynamicbuffer]).

The dynamic_vector_buffer class template requires that T is a trivially copyable or standard-layout type (C++ 2014 [basic.types]) and that sizeof(T) == 1.

explicit dynamic_vector_buffer(vector<T, Allocator>& vec) noexcept;

Effects: Initializes vec_ with vec, size_ with vec.size(), and max_size_ with vec.max_size().

dynamic_vector_buffer(vector<T, Allocator>& vec, size_t maximum_size) noexcept;

Requires: vec.size() <= maximum_size.

Effects: Initializes vec_ with vec, size_ with vec.size(), and max_size_ with maximum_size.

size_t size() const noexcept;

Returns: size_.

size_t max_size() const noexcept;

Returns: max_size_.

size_t capacity() const noexcept;

Returns: vec_.capacity().

const_buffers_type data() const noexcept;

Returns: buffer(vec_, size_).

mutable_buffers_type prepare(size_t n);

Effects: Performs vec_.resize(size_ + n).

Returns: buffer(buffer(vec_) + size_, n).

Remarks: length_error if size() + n exceeds max_size().

void commit(size_t n);

Effects: Performs:

size_ += min(n, vec_.size() - size_);
vec_.resize(size_);

void consume(size_t n);

Effects: Performs:

size_t m = min(n, size_);
vec_.erase(vec_.begin(), vec_.begin() + m);
size_ -= m;

16.13 Class template dynamic_string_buffer [buffer.dynamic.string]

Class template dynamic_string_buffer is an adaptor used to automatically grow or shrink a basic_string object, to reflect the data successfully transferred in an I/O operation.

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

  template<class CharT, class Traits, class Allocator>
  class dynamic_string_buffer
  {
  public:
    // types:
    using const_buffers_type = const_buffer;
    using mutable_buffers_type = mutable_buffer;

    // constructors:
    explicit dynamic_string_buffer(basic_string<CharT, Traits, Allocator>& str) noexcept;
    dynamic_string_buffer(basic_string<CharT, Traits, Allocator>& str,
                          size_t maximum_size) noexcept;
    dynamic_string_buffer(dynamic_string_buffer&&) = default;

    // members:
    size_t size() const noexcept;
    size_t max_size() const noexcept;
    size_t capacity() const noexcept;
    const_buffers_type data() const noexcept;
    mutable_buffers_type prepare(size_t n);
    void commit(size_t n) noexcept;
    void consume(size_t n);

  private:
    basic_string<CharT, Traits, Allocator>& str_; // exposition only
    size_t size_; // exposition only
    const size_t max_size_; // exposition only
  };

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

The dynamic_string_buffer class template meets the requirements of DynamicBuffer ([buffer.reqmts.dynamicbuffer]).

The dynamic_string_buffer class template requires that sizeof(CharT) == 1.

explicit dynamic_string_buffer(basic_string<CharT, Traits, Allocator>& str) noexcept;

Effects: Initializes str_ with str, size_ with str.size(), and max_size_ with str.max_size().

dynamic_string_buffer(basic_string<CharT, Traits, Allocator>& str, size_t maximum_size) noexcept;

Requires: str.size() <= maximum_size.

Effects: Initializes str_ with str, size_ with str.size(), and max_size_ with maximum_size.

size_t size() const noexcept;

Returns: size_.

size_t max_size() const noexcept;

Returns: max_size_.

size_t capacity() const noexcept;

Returns: str_.capacity().

const_buffers_type data() const noexcept;

Returns: buffer(str_, size_).

mutable_buffers_type prepare(size_t n);

Effects: Performs str_.resize(size_ + n).

Returns: buffer(buffer(str_) + size_, n).

Remarks: length_error if size() + n exceeds max_size().

void commit(size_t n) noexcept;

Effects: Performs:

size_ += min(n, str_.size() - size_);
str_.resize(size_);

void consume(size_t n);

Effects: Performs:

size_t m = min(n, size_);
str_.erase(0, m);
size_ -= m;

16.14 Dynamic buffer creation functions [buffer.dynamic.creation]

template<class T, class Allocator> dynamic_vector_buffer<T, Allocator> dynamic_buffer(vector<T, Allocator>& vec) noexcept;

Returns: dynamic_vector_buffer<T, Allocator>(vec).

template<class T, class Allocator> dynamic_vector_buffer<T, Allocator> dynamic_buffer(vector<T, Allocator>& vec, size_t n) noexcept;

Returns: dynamic_vector_buffer<T, Allocator>(vec, n).

template<class CharT, class Traits, class Allocator> dynamic_string_buffer<CharT, Traits, Allocator> dynamic_buffer(basic_string<CharT, Traits, Allocator>& str) noexcept;

Returns: dynamic_string_buffer<CharT, Traits, Allocator>(str).

template<class CharT, class Traits, class Allocator> dynamic_string_buffer<CharT, Traits, Allocator> dynamic_buffer(basic_string<CharT, Traits, Allocator>& str, size_t n) noexcept;

Returns: dynamic_string_buffer<CharT, Traits, Allocator>(str, n).