// <experimental/buffer> -*- C++ -*-
// Copyright (C) 2015-2020 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
/** @file experimental/buffer
* This is a TS C++ Library header.
* @ingroup networking-ts
*/
#ifndef _GLIBCXX_EXPERIMENTAL_BUFFER
#define _GLIBCXX_EXPERIMENTAL_BUFFER 1
#pragma GCC system_header
#if __cplusplus >= 201402L
#include <array>
#include <string>
#include <system_error>
#include <vector>
#include <cstring>
#include <experimental/string_view>
#include <experimental/bits/net.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
namespace experimental
{
namespace net
{
inline namespace v1
{
/** @addtogroup networking-ts
* @{
*/
enum class stream_errc { // TODO decide values
eof = 1,
not_found = 2
};
const error_category& stream_category() noexcept // TODO not inline
{
struct __cat : error_category
{
const char* name() const noexcept { return "stream"; }
std::string message(int __e) const
{
if (__e == (int)stream_errc::eof)
return "EOF";
else if (__e == (int)stream_errc::not_found)
return "not found";
return "stream";
}
virtual void __message(int) { } // TODO dual ABI XXX
};
static __cat __c;
return __c;
}
inline error_code
make_error_code(stream_errc __e) noexcept
{ return error_code(static_cast<int>(__e), stream_category()); }
inline error_condition
make_error_condition(stream_errc __e) noexcept
{ return error_condition(static_cast<int>(__e), stream_category()); }
class mutable_buffer
{
public:
// constructors:
mutable_buffer() noexcept : _M_data(), _M_size() { }
mutable_buffer(void* __p, size_t __n) noexcept
: _M_data(__p), _M_size(__n) { }
// members:
void* data() const noexcept { return _M_data; }
size_t size() const noexcept { return _M_size; }
private:
void* _M_data;
size_t _M_size;
};
class const_buffer
{
public:
// constructors:
const_buffer() noexcept : _M_data(), _M_size() { }
const_buffer(const void* __p, size_t __n) noexcept
: _M_data(__p), _M_size(__n) { }
const_buffer(const mutable_buffer& __b) noexcept
: _M_data(__b.data()), _M_size(__b.size()) { }
// members:
const void* data() const noexcept { return _M_data; }
size_t size() const noexcept { return _M_size; }
private:
const void* _M_data;
size_t _M_size;
};
/** @brief buffer sequence access
*
* Uniform access to types that meet the BufferSequence requirements.
* @{
*/
inline const mutable_buffer*
buffer_sequence_begin(const mutable_buffer& __b)
{ return std::addressof(__b); }
inline const const_buffer*
buffer_sequence_begin(const const_buffer& __b)
{ return std::addressof(__b); }
inline const mutable_buffer*
buffer_sequence_end(const mutable_buffer& __b)
{ return std::addressof(__b) + 1; }
inline const const_buffer*
buffer_sequence_end(const const_buffer& __b)
{ return std::addressof(__b) + 1; }
template<typename _Cont>
auto
buffer_sequence_begin(_Cont& __c) -> decltype(__c.begin())
{ return __c.begin(); }
template<typename _Cont>
auto
buffer_sequence_begin(const _Cont& __c) -> decltype(__c.begin())
{ return __c.begin(); }
template<typename _Cont>
auto
buffer_sequence_end(_Cont& __c) -> decltype(__c.end())
{ return __c.end(); }
template<typename _Cont>
auto
buffer_sequence_end(const _Cont& __c) -> decltype(__c.end())
{ return __c.end(); }
/// @}
/** @brief buffer type traits
*
* @{
*/
template<typename _Tp, typename _Buffer,
typename _Begin
= decltype(net::buffer_sequence_begin(std::declval<_Tp&>())),
typename _End
= decltype(net::buffer_sequence_end(std::declval<_Tp&>()))>
using __buffer_sequence = enable_if_t<__and_<
__is_value_constructible<_Tp>, is_same<_Begin, _End>,
is_convertible<typename iterator_traits<_Begin>::value_type, _Buffer>
>::value>;
template<typename _Tp, typename _Buffer, typename = void>
struct __is_buffer_sequence : false_type
{ };
template<typename _Tp, typename _Buffer>
struct __is_buffer_sequence<_Tp, _Buffer, __buffer_sequence<_Tp, _Buffer>>
: true_type
{ };
template<typename _Tp>
struct is_mutable_buffer_sequence
: __is_buffer_sequence<_Tp, mutable_buffer>::type
{ };
template<typename _Tp>
struct is_const_buffer_sequence
: __is_buffer_sequence<_Tp, const_buffer>::type
{ };
template<typename _Tp>
constexpr bool is_mutable_buffer_sequence_v
= is_mutable_buffer_sequence<_Tp>::value;
template<typename _Tp>
constexpr bool is_const_buffer_sequence_v
= is_const_buffer_sequence<_Tp>::value;
template<typename _Tp, typename = void>
struct __is_dynamic_buffer_impl : false_type
{ };
// Check DynamicBuffer requirements.
template<typename _Tp, typename _Up = remove_const_t<_Tp>>
auto
__dynamic_buffer_reqs(_Up* __x = 0, const _Up* __x1 = 0, size_t __n = 0)
-> enable_if_t<__and_<
is_move_constructible<_Up>,
is_const_buffer_sequence<typename _Tp::const_buffers_type>,
is_mutable_buffer_sequence<typename _Tp::mutable_buffers_type>,
is_same<decltype(__x1->size()), size_t>,
is_same<decltype(__x1->max_size()), size_t>,
is_same<decltype(__x1->capacity()), size_t>,
is_same<decltype(__x1->data()), typename _Tp::const_buffers_type>,
is_same<decltype(__x->prepare(__n)), typename _Tp::mutable_buffers_type>,
is_void<decltype(__x->commit(__n), __x->consume(__n), void())>
>::value>;
template<typename _Tp>
struct __is_dynamic_buffer_impl<_Tp,
decltype(__dynamic_buffer_reqs<_Tp>())>
: true_type
{ };
template<typename _Tp>
struct is_dynamic_buffer : __is_dynamic_buffer_impl<_Tp>::type
{ };
template<typename _Tp>
constexpr bool is_dynamic_buffer_v = is_dynamic_buffer<_Tp>::value;
/// @}
/// buffer size
template<typename _ConstBufferSequence>
size_t
buffer_size(const _ConstBufferSequence& __buffers) noexcept
{
size_t __total_size = 0;
auto __i = net::buffer_sequence_begin(__buffers);
const auto __end = net::buffer_sequence_end(__buffers);
for (; __i != __end; ++__i)
__total_size += const_buffer(*__i).size();
return __total_size;
}
template<typename _ConstBufferSequence>
bool
__buffer_empty(const _ConstBufferSequence& __buffers) noexcept
{
auto __i = net::buffer_sequence_begin(__buffers);
const auto __end = net::buffer_sequence_end(__buffers);
for (; __i != __end; ++__i)
if (const_buffer(*__i).size() != 0)
return false;
return true;
}
// buffer copy:
template<typename _MutableBufferSequence, typename _ConstBufferSequence>
size_t
buffer_copy(const _MutableBufferSequence& __dest,
const _ConstBufferSequence& __source,
size_t __max_size) noexcept
{
size_t __total_size = 0;
auto __to_i = net::buffer_sequence_begin(__dest);
const auto __to_end = net::buffer_sequence_end(__dest);
auto __from_i = net::buffer_sequence_begin(__source);
const auto __from_end = net::buffer_sequence_end(__source);
mutable_buffer __to;
const_buffer __from;
while (((__from_i != __from_end && __to_i != __to_end)
|| (__from.size() && __to.size()))
&& __total_size < __max_size)
{
if (__from.size() == 0)
__from = const_buffer{*__from_i++};
if (__to.size() == 0)
__to = mutable_buffer{*__to_i++};
size_t __n = std::min(__from.size(), __to.size());
__n = std::min(__n, __max_size - __total_size);
std::memcpy(__to.data(), __from.data(), __n);
__from = { (const char*)__from.data() + __n, __from.size() - __n };
__to = { (char*)__to.data() + __n, __to.size() - __n };
__total_size += __n;
}
return __total_size;
}
template<typename _MutableBufferSequence, typename _ConstBufferSequence>
inline size_t
buffer_copy(const _MutableBufferSequence& __dest,
const _ConstBufferSequence& __source) noexcept
{ return net::buffer_copy(__dest, __source, size_t{-1}); }
// buffer arithmetic:
inline mutable_buffer
operator+(const mutable_buffer& __b, size_t __n) noexcept
{
if (__n > __b.size())
__n = __b.size();
return { static_cast<char*>(__b.data()) + __n, __b.size() - __n };
}
inline mutable_buffer
operator+(size_t __n, const mutable_buffer& __b) noexcept
{ return __b + __n; }
inline const_buffer
operator+(const const_buffer& __b, size_t __n) noexcept
{
if (__n > __b.size())
__n = __b.size();
return { static_cast<const char*>(__b.data()) + __n, __b.size() - __n };
}
inline const_buffer
operator+(size_t __n, const const_buffer& __b) noexcept
{ return __b + __n; }
// buffer creation:
inline mutable_buffer
buffer(void* __p, size_t __n) noexcept
{ return { __p, __n }; }
inline const_buffer
buffer(const void* __p, size_t __n) noexcept
{ return { __p, __n }; }
inline mutable_buffer
buffer(const mutable_buffer& __b) noexcept
{ return __b; }
inline mutable_buffer
buffer(const mutable_buffer& __b, size_t __n) noexcept
{ return { __b.data(), std::min(__b.size(), __n) }; }
inline const_buffer
buffer(const const_buffer& __b) noexcept
{ return __b; }
inline const_buffer
buffer(const const_buffer& __b, size_t __n) noexcept
{ return { __b.data(), std::min(__b.size(), __n) }; }
template<typename _Tp>
inline mutable_buffer
__to_mbuf(_Tp* __data, size_t __n)
{ return { __n ? __data : nullptr, __n * sizeof(_Tp) }; }
template<typename _Tp>
inline const_buffer
__to_cbuf(const _Tp* __data, size_t __n)
{ return { __n ? __data : nullptr, __n * sizeof(_Tp) }; }
template<typename _Tp, size_t _Nm>
inline mutable_buffer
buffer(_Tp (&__data)[_Nm]) noexcept
{ return net::__to_mbuf(__data, _Nm); }
template<typename _Tp, size_t _Nm>
inline const_buffer
buffer(const _Tp (&__data)[_Nm]) noexcept
{ return net::__to_cbuf(__data, _Nm); }
template<typename _Tp, size_t _Nm>
inline mutable_buffer
buffer(array<_Tp, _Nm>& __data) noexcept
{ return net::__to_mbuf(__data.data(), _Nm); }
template<typename _Tp, size_t _Nm>
inline const_buffer
buffer(array<const _Tp, _Nm>& __data) noexcept
{ return net::__to_cbuf(__data.data(), __data.size()); }
template<typename _Tp, size_t _Nm>
inline const_buffer
buffer(const array<_Tp, _Nm>& __data) noexcept
{ return net::__to_cbuf(__data.data(), __data.size()); }
template<typename _Tp, typename _Allocator>
inline mutable_buffer
buffer(vector<_Tp, _Allocator>& __data) noexcept
{ return net::__to_mbuf(__data.data(), __data.size()); }
template<typename _Tp, typename _Allocator>
inline const_buffer
buffer(const vector<_Tp, _Allocator>& __data) noexcept
{ return net::__to_cbuf(__data.data(), __data.size()); }
template<typename _CharT, typename _Traits, typename _Allocator>
inline mutable_buffer
buffer(basic_string<_CharT, _Traits, _Allocator>& __data) noexcept
{ return net::__to_mbuf(&__data.front(), __data.size()); }
template<typename _CharT, typename _Traits, typename _Allocator>
inline const_buffer
buffer(const basic_string<_CharT, _Traits, _Allocator>& __data) noexcept
{ return net::__to_cbuf(&__data.front(), __data.size()); }
template<typename _CharT, typename _Traits>
inline const_buffer
buffer(basic_string_view<_CharT, _Traits> __data) noexcept
{ return net::__to_cbuf(__data.data(), __data.size()); }
template<typename _Tp, size_t _Nm>
inline mutable_buffer
buffer(_Tp (&__data)[_Nm], size_t __n) noexcept
{ return buffer(net::buffer(__data), __n * sizeof(_Tp)); }
template<typename _Tp, size_t _Nm>
inline const_buffer
buffer(const _Tp (&__data)[_Nm], size_t __n) noexcept
{ return buffer(net::buffer(__data), __n * sizeof(_Tp)); }
template<typename _Tp, size_t _Nm>
inline mutable_buffer
buffer(array<_Tp, _Nm>& __data, size_t __n) noexcept
{ return buffer(net::buffer(__data), __n * sizeof(_Tp)); }
template<typename _Tp, size_t _Nm>
inline const_buffer
buffer(array<const _Tp, _Nm>& __data, size_t __n) noexcept
{ return buffer(net::buffer(__data), __n * sizeof(_Tp)); }
template<typename _Tp, size_t _Nm>
inline const_buffer
buffer(const array<_Tp, _Nm>& __data, size_t __n) noexcept
{ return buffer(net::buffer(__data), __n * sizeof(_Tp)); }
template<typename _Tp, typename _Allocator>
inline mutable_buffer
buffer(vector<_Tp, _Allocator>& __data, size_t __n) noexcept
{ return buffer(net::buffer(__data), __n * sizeof(_Tp)); }
template<typename _Tp, typename _Allocator>
inline const_buffer
buffer(const vector<_Tp, _Allocator>& __data, size_t __n) noexcept
{ return buffer(net::buffer(__data), __n * sizeof(_Tp)); }
template<typename _CharT, typename _Traits, typename _Allocator>
inline mutable_buffer
buffer(basic_string<_CharT, _Traits, _Allocator>& __data,
size_t __n) noexcept
{ return buffer(net::buffer(__data), __n * sizeof(_CharT)); }
template<typename _CharT, typename _Traits, typename _Allocator>
inline const_buffer
buffer(const basic_string<_CharT, _Traits, _Allocator>& __data,
size_t __n) noexcept
{ return buffer(net::buffer(__data), __n * sizeof(_CharT)); }
template<typename _CharT, typename _Traits>
inline const_buffer
buffer(basic_string_view<_CharT, _Traits> __data, size_t __n) noexcept
{ return buffer(net::buffer(__data), __n * sizeof(_CharT)); }
template<typename _Sequence>
class __dynamic_buffer_base
{
public:
// types:
typedef const_buffer const_buffers_type;
typedef mutable_buffer mutable_buffers_type;
// constructors:
explicit
__dynamic_buffer_base(_Sequence& __seq) noexcept
: _M_seq(__seq), _M_size(__seq.size()), _M_max_size(__seq.max_size())
{ }
__dynamic_buffer_base(_Sequence& __seq, size_t __maximum_size) noexcept
: _M_seq(__seq), _M_size(__seq.size()), _M_max_size(__maximum_size)
{ __glibcxx_assert(__seq.size() <= __maximum_size); }
__dynamic_buffer_base(__dynamic_buffer_base&&) = default;
// members:
size_t size() const noexcept { return _M_size; }
size_t max_size() const noexcept { return _M_max_size; }
size_t capacity() const noexcept { return _M_seq.capacity(); }
const_buffers_type
data() const noexcept
{ return net::buffer(_M_seq, _M_size); }
mutable_buffers_type
prepare(size_t __n)
{
if ((_M_size + __n) > _M_max_size)
__throw_length_error("dynamic_vector_buffer::prepare");
_M_seq.resize(_M_size + __n);
return buffer(net::buffer(_M_seq) + _M_size, __n);
}
void
commit(size_t __n)
{
_M_size += std::min(__n, _M_seq.size() - _M_size);
_M_seq.resize(_M_size);
}
void
consume(size_t __n)
{
size_t __m = std::min(__n, _M_size);
_M_seq.erase(_M_seq.begin(), _M_seq.begin() + __m);
_M_size -= __m;
}
private:
_Sequence& _M_seq;
size_t _M_size;
const size_t _M_max_size;
};
template<typename _Tp, typename _Allocator>
class dynamic_vector_buffer
: public __dynamic_buffer_base<vector<_Tp, _Allocator>>
{
public:
using __dynamic_buffer_base<vector<_Tp, _Allocator>>::__dynamic_buffer_base;
};
template<typename _CharT, typename _Traits, typename _Allocator>
class dynamic_string_buffer
: public __dynamic_buffer_base<basic_string<_CharT, _Traits, _Allocator>>
{
public:
using __dynamic_buffer_base<basic_string<_CharT, _Traits, _Allocator>>::
__dynamic_buffer_base;
};
// dynamic buffer creation:
template<typename _Tp, typename _Allocator>
inline dynamic_vector_buffer<_Tp, _Allocator>
dynamic_buffer(vector<_Tp, _Allocator>& __vec) noexcept
{ return dynamic_vector_buffer<_Tp, _Allocator>{__vec}; }
template<typename _Tp, typename _Allocator>
inline dynamic_vector_buffer<_Tp, _Allocator>
dynamic_buffer(vector<_Tp, _Allocator>& __vec, size_t __n) noexcept
{ return {__vec, __n}; }
template<typename _CharT, typename _Traits, typename _Allocator>
inline dynamic_string_buffer<_CharT, _Traits, _Allocator>
dynamic_buffer(basic_string<_CharT, _Traits, _Allocator>& __str) noexcept
{ return dynamic_string_buffer<_CharT, _Traits, _Allocator>{__str}; }
template<typename _CharT, typename _Traits, typename _Allocator>
inline dynamic_string_buffer<_CharT, _Traits, _Allocator>
dynamic_buffer(basic_string<_CharT, _Traits, _Allocator>& __str,
size_t __n) noexcept
{ return {__str, __n}; }
class transfer_all
{
public:
size_t operator()(const error_code& __ec, size_t) const
{ return !__ec ? 1500 : 0; }
};
class transfer_at_least
{
public:
explicit transfer_at_least(size_t __m) : _M_minimum(__m) { }
size_t operator()(const error_code& __ec, size_t __n) const
{ return !__ec && __n < _M_minimum ? _M_minimum - __n : 0; }
private:
size_t _M_minimum;
};
class transfer_exactly
{
public:
explicit transfer_exactly(size_t __e) : _M_exact(__e) { }
size_t operator()(const error_code& __ec, size_t __n) const
{
size_t _Nm = -1;
return !__ec && __n < _M_exact ? std::min(_M_exact - __n, _Nm) : 0;
}
private:
size_t _M_exact;
};
/** @brief synchronous read operations
* @{
*/
template<typename _SyncReadStream, typename _MutableBufferSequence,
typename _CompletionCondition>
enable_if_t<is_mutable_buffer_sequence<_MutableBufferSequence>::value,
size_t>
read(_SyncReadStream& __stream, const _MutableBufferSequence& __buffers,
_CompletionCondition __completion_condition, error_code& __ec)
{
__ec.clear();
auto __i = net::buffer_sequence_begin(__buffers);
auto __end = net::buffer_sequence_end(__buffers);
mutable_buffer __to;
size_t __total = 0;
size_t __n;
while ((__n = __completion_condition(__ec, __total))
&& (__i != __end || __to.size()))
{
if (__to.size() == 0)
__to = mutable_buffer(*__i++);
__n = __stream.read_some(buffer(__to, __n), __ec);
__to = __to + __n;
__total += __n;
}
return __total;
}
template<typename _SyncReadStream, typename _MutableBufferSequence>
inline
enable_if_t<is_mutable_buffer_sequence<_MutableBufferSequence>::value,
size_t>
read(_SyncReadStream& __stream, const _MutableBufferSequence& __buffers)
{
error_code __ec;
return net::read(__stream, __buffers, transfer_all{}, __ec);
}
template<typename _SyncReadStream, typename _MutableBufferSequence>
inline
enable_if_t<is_mutable_buffer_sequence<_MutableBufferSequence>::value,
size_t>
read(_SyncReadStream& __stream, const _MutableBufferSequence& __buffers,
error_code& __ec)
{ return net::read(__stream, __buffers, transfer_all{}, __ec); }
template<typename _SyncReadStream, typename _MutableBufferSequence,
typename _CompletionCondition>
inline
enable_if_t<is_mutable_buffer_sequence<_MutableBufferSequence>::value,
size_t>
read(_SyncReadStream& __stream, const _MutableBufferSequence& __buffers,
_CompletionCondition __completion_condition)
{
error_code __ec;
return net::read(__stream, __buffers, __completion_condition, __ec);
}
template<typename _SyncReadStream, typename _DynamicBuffer,
typename _CompletionCondition>
enable_if_t<is_dynamic_buffer<decay_t<_DynamicBuffer>>::value, size_t>
read(_SyncReadStream& __stream, _DynamicBuffer&& __b,
_CompletionCondition __completion_condition, error_code& __ec)
{
const size_t __limit = 64;
__ec.clear();
size_t __cap = std::max(__b.capacity() - __b.size(), __limit);
size_t __total = 0;
size_t __n;
while ((__n = __completion_condition(__ec, __total))
&& __b.size() != __b.max_size())
{
__n = std::min(__n, __b.max_size() - __b.size());
size_t __cap = std::max(__b.capacity() - __b.size(), __limit);
mutable_buffer __to = __b.prepare(std::min(__cap, __n));
__n = __stream.read_some(__to, __ec);
__to = __to + __n;
__total += __n;
__b.commit(__n);
}
return __total;
}
template<typename _SyncReadStream, typename _DynamicBuffer>
inline enable_if_t<is_dynamic_buffer<_DynamicBuffer>::value, size_t>
read(_SyncReadStream& __stream, _DynamicBuffer&& __b)
{
error_code __ec;
return net::read(__stream, __b, transfer_all{}, __ec);
}
template<typename _SyncReadStream, typename _DynamicBuffer>
inline enable_if_t<is_dynamic_buffer<_DynamicBuffer>::value, size_t>
read(_SyncReadStream& __stream, _DynamicBuffer&& __b, error_code& __ec)
{
return net::read(__stream, __b, transfer_all{}, __ec);
}
template<typename _SyncReadStream, typename _DynamicBuffer,
typename _CompletionCondition>
inline enable_if_t<is_dynamic_buffer<_DynamicBuffer>::value, size_t>
read(_SyncReadStream& __stream, _DynamicBuffer&& __b,
_CompletionCondition __completion_condition)
{
error_code __ec;
return net::read(__stream, __b, __completion_condition, __ec);
}
/// @}
/** @brief asynchronous read operations
* @{
*/
template<typename _AsyncReadStream, typename _MutableBufferSequence,
typename _CompletionCondition, typename _CompletionToken>
__deduced_t<_CompletionToken, void(error_code, size_t)>
async_read(_AsyncReadStream& __stream,
const _MutableBufferSequence& __buffers,
_CompletionCondition __completion_condition,
_CompletionToken&& __token)
{
error_code __ec;
}
template<typename _AsyncReadStream, typename _MutableBufferSequence,
typename _CompletionToken>
inline __deduced_t<_CompletionToken, void(error_code, size_t)>
async_read(_AsyncReadStream& __stream,
const _MutableBufferSequence& __buffers,
_CompletionToken&& __token)
{
return net::async_read(__stream, __buffers, transfer_all{},
std::forward<_CompletionToken>(__token));
}
template<typename _AsyncReadStream, typename _DynamicBuffer,
typename _CompletionCondition, typename _CompletionToken>
__deduced_t<_CompletionToken, void(error_code, size_t)>
async_read(_AsyncReadStream& __stream, _DynamicBuffer&& __b,
_CompletionCondition __completion_condition,
_CompletionToken&& __token)
{
error_code __ec;
}
template<typename _AsyncReadStream, typename _DynamicBuffer,
typename _CompletionToken>
inline __deduced_t<_CompletionToken, void(error_code, size_t)>
async_read(_AsyncReadStream& __stream, _DynamicBuffer&& __b,
_CompletionToken&& __token)
{
return net::async_read(__stream, __b, transfer_all{},
std::forward<_CompletionToken>(__token));
}
/// @}
#if 0
/** @brief synchronous write operations:
* @{
*/
template<typename _SyncWriteStream, typename _ConstBufferSequence>
size_t write(_SyncWriteStream& __stream,
const _ConstBufferSequence& __buffers);
template<typename _SyncWriteStream, typename _ConstBufferSequence>
size_t write(_SyncWriteStream& __stream,
const _ConstBufferSequence& __buffers, error_code& __ec);
template<typename _SyncWriteStream, typename _ConstBufferSequence,
typename _CompletionCondition>
size_t write(_SyncWriteStream& __stream,
const _ConstBufferSequence& __buffers,
_CompletionCondition __completion_condition);
template<typename _SyncWriteStream, typename _ConstBufferSequence,
typename _CompletionCondition>
size_t write(_SyncWriteStream& __stream,
const _ConstBufferSequence& __buffers,
_CompletionCondition __completion_condition,
error_code& __ec);
template<typename _SyncWriteStream, typename _DynamicBuffer>
size_t write(_SyncWriteStream& __stream, _DynamicBuffer&& __b);
template<typename _SyncWriteStream, typename _DynamicBuffer>
size_t write(_SyncWriteStream& __stream, _DynamicBuffer&& __b, error_code& __ec);
template<typename _SyncWriteStream, typename _DynamicBuffer, typename _CompletionCondition>
size_t write(_SyncWriteStream& __stream, _DynamicBuffer&& __b,
_CompletionCondition __completion_condition);
template<typename _SyncWriteStream, typename _DynamicBuffer, typename _CompletionCondition>
size_t write(_SyncWriteStream& __stream, _DynamicBuffer&& __b,
_CompletionCondition __completion_condition, error_code& __ec);
/// @}
/** @brief asynchronous write operations
* @{
*/
template<typename _AsyncWriteStream, typename _ConstBufferSequence,
typename _CompletionToken>
DEDUCED async_write(_AsyncWriteStream& __stream,
const _ConstBufferSequence& __buffers,
_CompletionToken&& __token);
template<typename _AsyncWriteStream, typename _ConstBufferSequence,
typename _CompletionCondition, typename _CompletionToken>
DEDUCED async_write(_AsyncWriteStream& __stream,
const _ConstBufferSequence& __buffers,
_CompletionCondition __completion_condition,
_CompletionToken&& __token);
template<typename _AsyncWriteStream, typename _DynamicBuffer, typename _CompletionToken>
DEDUCED async_write(_AsyncWriteStream& __stream,
_DynamicBuffer&& __b, _CompletionToken&& __token);
template<typename _AsyncWriteStream, typename _DynamicBuffer,
typename _CompletionCondition, typename _CompletionToken>
DEDUCED async_write(_AsyncWriteStream& __stream,
_DynamicBuffer&& __b,
_CompletionCondition __completion_condition,
_CompletionToken&& __token);
/// @}
/** @brief synchronous delimited read operations
* @{
*/
template<typename _SyncReadStream, typename _DynamicBuffer>
size_t read_until(_SyncReadStream& __s, _DynamicBuffer&& __b, char __delim);
template<typename _SyncReadStream, typename _DynamicBuffer>
size_t read_until(_SyncReadStream& __s, _DynamicBuffer&& __b,
char __delim, error_code& __ec);
template<typename _SyncReadStream, typename _DynamicBuffer>
size_t read_until(_SyncReadStream& __s, _DynamicBuffer&& __b, string_view __delim);
template<typename _SyncReadStream, typename _DynamicBuffer>
size_t read_until(_SyncReadStream& __s, _DynamicBuffer&& __b,
string_view __delim, error_code& __ec);
/// @}
/** @brief asynchronous delimited read operations
* @{
*/
template<typename _AsyncReadStream, typename _DynamicBuffer, typename _CompletionToken>
DEDUCED async_read_until(_AsyncReadStream& __s,
_DynamicBuffer&& __b, char __delim,
_CompletionToken&& __token);
template<typename _AsyncReadStream, typename _DynamicBuffer, typename _CompletionToken>
DEDUCED async_read_until(_AsyncReadStream& __s,
_DynamicBuffer&& __b, string_view __delim,
_CompletionToken&& __token);
/// @}
#endif
/// @}
} // namespace v1
} // namespace net
} // namespace experimental
template<>
struct is_error_code_enum<experimental::net::v1::stream_errc>
: public true_type {};
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++14
#endif // _GLIBCXX_EXPERIMENTAL_BUFFER