181418a27Smrg// <experimental/buffer> -*- C++ -*- 281418a27Smrg 3*f0fbc68bSmrg// Copyright (C) 2015-2022 Free Software Foundation, Inc. 481418a27Smrg// 581418a27Smrg// This file is part of the GNU ISO C++ Library. This library is free 681418a27Smrg// software; you can redistribute it and/or modify it under the 781418a27Smrg// terms of the GNU General Public License as published by the 881418a27Smrg// Free Software Foundation; either version 3, or (at your option) 981418a27Smrg// any later version. 1081418a27Smrg 1181418a27Smrg// This library is distributed in the hope that it will be useful, 1281418a27Smrg// but WITHOUT ANY WARRANTY; without even the implied warranty of 1381418a27Smrg// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1481418a27Smrg// GNU General Public License for more details. 1581418a27Smrg 1681418a27Smrg// Under Section 7 of GPL version 3, you are granted additional 1781418a27Smrg// permissions described in the GCC Runtime Library Exception, version 1881418a27Smrg// 3.1, as published by the Free Software Foundation. 1981418a27Smrg 2081418a27Smrg// You should have received a copy of the GNU General Public License and 2181418a27Smrg// a copy of the GCC Runtime Library Exception along with this program; 2281418a27Smrg// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 2381418a27Smrg// <http://www.gnu.org/licenses/>. 2481418a27Smrg 2581418a27Smrg/** @file experimental/buffer 2681418a27Smrg * This is a TS C++ Library header. 278d286336Smrg * @ingroup networking-ts 2881418a27Smrg */ 2981418a27Smrg 3081418a27Smrg#ifndef _GLIBCXX_EXPERIMENTAL_BUFFER 3181418a27Smrg#define _GLIBCXX_EXPERIMENTAL_BUFFER 1 3281418a27Smrg 3381418a27Smrg#pragma GCC system_header 3481418a27Smrg 3581418a27Smrg#if __cplusplus >= 201402L 3681418a27Smrg 3781418a27Smrg#include <array> 3881418a27Smrg#include <string> 3981418a27Smrg#include <system_error> 4081418a27Smrg#include <vector> 4181418a27Smrg#include <cstring> 4281418a27Smrg#include <experimental/string_view> 4381418a27Smrg#include <experimental/bits/net.h> 4481418a27Smrg 4581418a27Smrgnamespace std _GLIBCXX_VISIBILITY(default) 4681418a27Smrg{ 4781418a27Smrg_GLIBCXX_BEGIN_NAMESPACE_VERSION 4881418a27Smrgnamespace experimental 4981418a27Smrg{ 5081418a27Smrgnamespace net 5181418a27Smrg{ 5281418a27Smrginline namespace v1 5381418a27Smrg{ 5481418a27Smrg 558d286336Smrg /** @addtogroup networking-ts 5681418a27Smrg * @{ 5781418a27Smrg */ 5881418a27Smrg 5981418a27Smrg enum class stream_errc { // TODO decide values 6081418a27Smrg eof = 1, 6181418a27Smrg not_found = 2 6281418a27Smrg }; 6381418a27Smrg 6481418a27Smrg const error_category& stream_category() noexcept // TODO not inline 6581418a27Smrg { 6681418a27Smrg struct __cat : error_category 6781418a27Smrg { 6881418a27Smrg const char* name() const noexcept { return "stream"; } 6981418a27Smrg 7081418a27Smrg std::string message(int __e) const 7181418a27Smrg { 7281418a27Smrg if (__e == (int)stream_errc::eof) 7381418a27Smrg return "EOF"; 7481418a27Smrg else if (__e == (int)stream_errc::not_found) 7581418a27Smrg return "not found"; 7681418a27Smrg return "stream"; 7781418a27Smrg } 7881418a27Smrg 7981418a27Smrg virtual void __message(int) { } // TODO dual ABI XXX 8081418a27Smrg }; 8181418a27Smrg static __cat __c; 8281418a27Smrg return __c; 8381418a27Smrg } 8481418a27Smrg 8581418a27Smrg inline error_code 8681418a27Smrg make_error_code(stream_errc __e) noexcept 8781418a27Smrg { return error_code(static_cast<int>(__e), stream_category()); } 8881418a27Smrg 8981418a27Smrg inline error_condition 9081418a27Smrg make_error_condition(stream_errc __e) noexcept 9181418a27Smrg { return error_condition(static_cast<int>(__e), stream_category()); } 9281418a27Smrg 9381418a27Smrg class mutable_buffer 9481418a27Smrg { 9581418a27Smrg public: 9681418a27Smrg // constructors: 9781418a27Smrg mutable_buffer() noexcept : _M_data(), _M_size() { } 9881418a27Smrg 9981418a27Smrg mutable_buffer(void* __p, size_t __n) noexcept 10081418a27Smrg : _M_data(__p), _M_size(__n) { } 10181418a27Smrg 10281418a27Smrg // members: 10381418a27Smrg void* data() const noexcept { return _M_data; } 10481418a27Smrg size_t size() const noexcept { return _M_size; } 10581418a27Smrg 10681418a27Smrg private: 10781418a27Smrg void* _M_data; 10881418a27Smrg size_t _M_size; 10981418a27Smrg }; 11081418a27Smrg 11181418a27Smrg class const_buffer 11281418a27Smrg { 11381418a27Smrg public: 11481418a27Smrg // constructors: 11581418a27Smrg const_buffer() noexcept : _M_data(), _M_size() { } 11681418a27Smrg 11781418a27Smrg const_buffer(const void* __p, size_t __n) noexcept 11881418a27Smrg : _M_data(__p), _M_size(__n) { } 11981418a27Smrg 12081418a27Smrg const_buffer(const mutable_buffer& __b) noexcept 12181418a27Smrg : _M_data(__b.data()), _M_size(__b.size()) { } 12281418a27Smrg 12381418a27Smrg // members: 12481418a27Smrg const void* data() const noexcept { return _M_data; } 12581418a27Smrg size_t size() const noexcept { return _M_size; } 12681418a27Smrg 12781418a27Smrg private: 12881418a27Smrg const void* _M_data; 12981418a27Smrg size_t _M_size; 13081418a27Smrg }; 13181418a27Smrg 13281418a27Smrg 13381418a27Smrg /** @brief buffer sequence access 13481418a27Smrg * 13581418a27Smrg * Uniform access to types that meet the BufferSequence requirements. 13681418a27Smrg * @{ 13781418a27Smrg */ 13881418a27Smrg 13981418a27Smrg inline const mutable_buffer* 14081418a27Smrg buffer_sequence_begin(const mutable_buffer& __b) 14181418a27Smrg { return std::addressof(__b); } 14281418a27Smrg 14381418a27Smrg inline const const_buffer* 14481418a27Smrg buffer_sequence_begin(const const_buffer& __b) 14581418a27Smrg { return std::addressof(__b); } 14681418a27Smrg 14781418a27Smrg inline const mutable_buffer* 14881418a27Smrg buffer_sequence_end(const mutable_buffer& __b) 14981418a27Smrg { return std::addressof(__b) + 1; } 15081418a27Smrg 15181418a27Smrg inline const const_buffer* 15281418a27Smrg buffer_sequence_end(const const_buffer& __b) 15381418a27Smrg { return std::addressof(__b) + 1; } 15481418a27Smrg 15581418a27Smrg template<typename _Cont> 15681418a27Smrg auto 15781418a27Smrg buffer_sequence_begin(_Cont& __c) -> decltype(__c.begin()) 15881418a27Smrg { return __c.begin(); } 15981418a27Smrg 16081418a27Smrg template<typename _Cont> 16181418a27Smrg auto 16281418a27Smrg buffer_sequence_begin(const _Cont& __c) -> decltype(__c.begin()) 16381418a27Smrg { return __c.begin(); } 16481418a27Smrg 16581418a27Smrg template<typename _Cont> 16681418a27Smrg auto 16781418a27Smrg buffer_sequence_end(_Cont& __c) -> decltype(__c.end()) 16881418a27Smrg { return __c.end(); } 16981418a27Smrg 17081418a27Smrg template<typename _Cont> 17181418a27Smrg auto 17281418a27Smrg buffer_sequence_end(const _Cont& __c) -> decltype(__c.end()) 17381418a27Smrg { return __c.end(); } 17481418a27Smrg 1757327edafSmrg /// @} 17681418a27Smrg 17781418a27Smrg 17881418a27Smrg /** @brief buffer type traits 17981418a27Smrg * 18081418a27Smrg * @{ 18181418a27Smrg */ 18281418a27Smrg 18381418a27Smrg template<typename _Tp, typename _Buffer, 18481418a27Smrg typename _Begin 18581418a27Smrg = decltype(net::buffer_sequence_begin(std::declval<_Tp&>())), 18681418a27Smrg typename _End 18781418a27Smrg = decltype(net::buffer_sequence_end(std::declval<_Tp&>()))> 18881418a27Smrg using __buffer_sequence = enable_if_t<__and_< 18981418a27Smrg __is_value_constructible<_Tp>, is_same<_Begin, _End>, 19081418a27Smrg is_convertible<typename iterator_traits<_Begin>::value_type, _Buffer> 19181418a27Smrg >::value>; 19281418a27Smrg 19381418a27Smrg template<typename _Tp, typename _Buffer, typename = void> 19481418a27Smrg struct __is_buffer_sequence : false_type 19581418a27Smrg { }; 19681418a27Smrg 19781418a27Smrg template<typename _Tp, typename _Buffer> 19881418a27Smrg struct __is_buffer_sequence<_Tp, _Buffer, __buffer_sequence<_Tp, _Buffer>> 19981418a27Smrg : true_type 20081418a27Smrg { }; 20181418a27Smrg 20281418a27Smrg template<typename _Tp> 20381418a27Smrg struct is_mutable_buffer_sequence 20481418a27Smrg : __is_buffer_sequence<_Tp, mutable_buffer>::type 20581418a27Smrg { }; 20681418a27Smrg 20781418a27Smrg template<typename _Tp> 20881418a27Smrg struct is_const_buffer_sequence 20981418a27Smrg : __is_buffer_sequence<_Tp, const_buffer>::type 21081418a27Smrg { }; 21181418a27Smrg 21281418a27Smrg template<typename _Tp> 21381418a27Smrg constexpr bool is_mutable_buffer_sequence_v 21481418a27Smrg = is_mutable_buffer_sequence<_Tp>::value; 21581418a27Smrg 21681418a27Smrg template<typename _Tp> 21781418a27Smrg constexpr bool is_const_buffer_sequence_v 21881418a27Smrg = is_const_buffer_sequence<_Tp>::value; 21981418a27Smrg 22081418a27Smrg template<typename _Tp, typename = void> 22181418a27Smrg struct __is_dynamic_buffer_impl : false_type 22281418a27Smrg { }; 22381418a27Smrg 22481418a27Smrg // Check DynamicBuffer requirements. 22581418a27Smrg template<typename _Tp, typename _Up = remove_const_t<_Tp>> 22681418a27Smrg auto 22781418a27Smrg __dynamic_buffer_reqs(_Up* __x = 0, const _Up* __x1 = 0, size_t __n = 0) 22881418a27Smrg -> enable_if_t<__and_< 22981418a27Smrg is_move_constructible<_Up>, 23081418a27Smrg is_const_buffer_sequence<typename _Tp::const_buffers_type>, 23181418a27Smrg is_mutable_buffer_sequence<typename _Tp::mutable_buffers_type>, 23281418a27Smrg is_same<decltype(__x1->size()), size_t>, 23381418a27Smrg is_same<decltype(__x1->max_size()), size_t>, 23481418a27Smrg is_same<decltype(__x1->capacity()), size_t>, 23581418a27Smrg is_same<decltype(__x1->data()), typename _Tp::const_buffers_type>, 23681418a27Smrg is_same<decltype(__x->prepare(__n)), typename _Tp::mutable_buffers_type>, 23781418a27Smrg is_void<decltype(__x->commit(__n), __x->consume(__n), void())> 23881418a27Smrg >::value>; 23981418a27Smrg 24081418a27Smrg template<typename _Tp> 24181418a27Smrg struct __is_dynamic_buffer_impl<_Tp, 24281418a27Smrg decltype(__dynamic_buffer_reqs<_Tp>())> 24381418a27Smrg : true_type 24481418a27Smrg { }; 24581418a27Smrg 24681418a27Smrg template<typename _Tp> 24781418a27Smrg struct is_dynamic_buffer : __is_dynamic_buffer_impl<_Tp>::type 24881418a27Smrg { }; 24981418a27Smrg 25081418a27Smrg template<typename _Tp> 25181418a27Smrg constexpr bool is_dynamic_buffer_v = is_dynamic_buffer<_Tp>::value; 25281418a27Smrg 2537327edafSmrg /// @} 25481418a27Smrg 25581418a27Smrg /// buffer size 25681418a27Smrg template<typename _ConstBufferSequence> 25781418a27Smrg size_t 25881418a27Smrg buffer_size(const _ConstBufferSequence& __buffers) noexcept 25981418a27Smrg { 26081418a27Smrg size_t __total_size = 0; 26181418a27Smrg auto __i = net::buffer_sequence_begin(__buffers); 26281418a27Smrg const auto __end = net::buffer_sequence_end(__buffers); 26381418a27Smrg for (; __i != __end; ++__i) 26481418a27Smrg __total_size += const_buffer(*__i).size(); 26581418a27Smrg return __total_size; 26681418a27Smrg } 26781418a27Smrg 26881418a27Smrg template<typename _ConstBufferSequence> 26981418a27Smrg bool 27081418a27Smrg __buffer_empty(const _ConstBufferSequence& __buffers) noexcept 27181418a27Smrg { 27281418a27Smrg auto __i = net::buffer_sequence_begin(__buffers); 27381418a27Smrg const auto __end = net::buffer_sequence_end(__buffers); 27481418a27Smrg for (; __i != __end; ++__i) 27581418a27Smrg if (const_buffer(*__i).size() != 0) 27681418a27Smrg return false; 27781418a27Smrg return true; 27881418a27Smrg } 27981418a27Smrg 28081418a27Smrg // buffer copy: 28181418a27Smrg 28281418a27Smrg template<typename _MutableBufferSequence, typename _ConstBufferSequence> 28381418a27Smrg size_t 28481418a27Smrg buffer_copy(const _MutableBufferSequence& __dest, 28581418a27Smrg const _ConstBufferSequence& __source, 28681418a27Smrg size_t __max_size) noexcept 28781418a27Smrg { 28881418a27Smrg size_t __total_size = 0; 28981418a27Smrg auto __to_i = net::buffer_sequence_begin(__dest); 29081418a27Smrg const auto __to_end = net::buffer_sequence_end(__dest); 29181418a27Smrg auto __from_i = net::buffer_sequence_begin(__source); 29281418a27Smrg const auto __from_end = net::buffer_sequence_end(__source); 29381418a27Smrg mutable_buffer __to; 29481418a27Smrg const_buffer __from; 29581418a27Smrg while (((__from_i != __from_end && __to_i != __to_end) 29681418a27Smrg || (__from.size() && __to.size())) 29781418a27Smrg && __total_size < __max_size) 29881418a27Smrg { 29981418a27Smrg if (__from.size() == 0) 30081418a27Smrg __from = const_buffer{*__from_i++}; 30181418a27Smrg if (__to.size() == 0) 30281418a27Smrg __to = mutable_buffer{*__to_i++}; 30381418a27Smrg 30481418a27Smrg size_t __n = std::min(__from.size(), __to.size()); 30581418a27Smrg __n = std::min(__n, __max_size - __total_size); 30681418a27Smrg std::memcpy(__to.data(), __from.data(), __n); 30781418a27Smrg __from = { (const char*)__from.data() + __n, __from.size() - __n }; 30881418a27Smrg __to = { (char*)__to.data() + __n, __to.size() - __n }; 30981418a27Smrg __total_size += __n; 31081418a27Smrg } 31181418a27Smrg return __total_size; 31281418a27Smrg } 31381418a27Smrg 31481418a27Smrg template<typename _MutableBufferSequence, typename _ConstBufferSequence> 31581418a27Smrg inline size_t 31681418a27Smrg buffer_copy(const _MutableBufferSequence& __dest, 31781418a27Smrg const _ConstBufferSequence& __source) noexcept 318*f0fbc68bSmrg { return net::buffer_copy(__dest, __source, size_t(-1)); } 31981418a27Smrg 32081418a27Smrg 32181418a27Smrg // buffer arithmetic: 32281418a27Smrg 32381418a27Smrg inline mutable_buffer 32481418a27Smrg operator+(const mutable_buffer& __b, size_t __n) noexcept 32581418a27Smrg { 32681418a27Smrg if (__n > __b.size()) 32781418a27Smrg __n = __b.size(); 32881418a27Smrg return { static_cast<char*>(__b.data()) + __n, __b.size() - __n }; 32981418a27Smrg } 33081418a27Smrg 33181418a27Smrg inline mutable_buffer 33281418a27Smrg operator+(size_t __n, const mutable_buffer& __b) noexcept 33381418a27Smrg { return __b + __n; } 33481418a27Smrg 33581418a27Smrg inline const_buffer 33681418a27Smrg operator+(const const_buffer& __b, size_t __n) noexcept 33781418a27Smrg { 33881418a27Smrg if (__n > __b.size()) 33981418a27Smrg __n = __b.size(); 34081418a27Smrg return { static_cast<const char*>(__b.data()) + __n, __b.size() - __n }; 34181418a27Smrg } 34281418a27Smrg 34381418a27Smrg inline const_buffer 34481418a27Smrg operator+(size_t __n, const const_buffer& __b) noexcept 34581418a27Smrg { return __b + __n; } 34681418a27Smrg 34781418a27Smrg // buffer creation: 34881418a27Smrg 34981418a27Smrg inline mutable_buffer 35081418a27Smrg buffer(void* __p, size_t __n) noexcept 35181418a27Smrg { return { __p, __n }; } 35281418a27Smrg 35381418a27Smrg inline const_buffer 35481418a27Smrg buffer(const void* __p, size_t __n) noexcept 35581418a27Smrg { return { __p, __n }; } 35681418a27Smrg 35781418a27Smrg inline mutable_buffer 35881418a27Smrg buffer(const mutable_buffer& __b) noexcept 35981418a27Smrg { return __b; } 36081418a27Smrg 36181418a27Smrg inline mutable_buffer 36281418a27Smrg buffer(const mutable_buffer& __b, size_t __n) noexcept 36381418a27Smrg { return { __b.data(), std::min(__b.size(), __n) }; } 36481418a27Smrg 36581418a27Smrg inline const_buffer 36681418a27Smrg buffer(const const_buffer& __b) noexcept 36781418a27Smrg { return __b; } 36881418a27Smrg 36981418a27Smrg inline const_buffer 37081418a27Smrg buffer(const const_buffer& __b, size_t __n) noexcept 37181418a27Smrg { return { __b.data(), std::min(__b.size(), __n) }; } 37281418a27Smrg 37381418a27Smrg template<typename _Tp> 37481418a27Smrg inline mutable_buffer 37581418a27Smrg __to_mbuf(_Tp* __data, size_t __n) 37681418a27Smrg { return { __n ? __data : nullptr, __n * sizeof(_Tp) }; } 37781418a27Smrg 37881418a27Smrg template<typename _Tp> 37981418a27Smrg inline const_buffer 38081418a27Smrg __to_cbuf(const _Tp* __data, size_t __n) 38181418a27Smrg { return { __n ? __data : nullptr, __n * sizeof(_Tp) }; } 38281418a27Smrg 38381418a27Smrg template<typename _Tp, size_t _Nm> 38481418a27Smrg inline mutable_buffer 38581418a27Smrg buffer(_Tp (&__data)[_Nm]) noexcept 38681418a27Smrg { return net::__to_mbuf(__data, _Nm); } 38781418a27Smrg 38881418a27Smrg template<typename _Tp, size_t _Nm> 38981418a27Smrg inline const_buffer 39081418a27Smrg buffer(const _Tp (&__data)[_Nm]) noexcept 39181418a27Smrg { return net::__to_cbuf(__data, _Nm); } 39281418a27Smrg 39381418a27Smrg template<typename _Tp, size_t _Nm> 39481418a27Smrg inline mutable_buffer 39581418a27Smrg buffer(array<_Tp, _Nm>& __data) noexcept 39681418a27Smrg { return net::__to_mbuf(__data.data(), _Nm); } 39781418a27Smrg 39881418a27Smrg template<typename _Tp, size_t _Nm> 39981418a27Smrg inline const_buffer 40081418a27Smrg buffer(array<const _Tp, _Nm>& __data) noexcept 40181418a27Smrg { return net::__to_cbuf(__data.data(), __data.size()); } 40281418a27Smrg 40381418a27Smrg template<typename _Tp, size_t _Nm> 40481418a27Smrg inline const_buffer 40581418a27Smrg buffer(const array<_Tp, _Nm>& __data) noexcept 40681418a27Smrg { return net::__to_cbuf(__data.data(), __data.size()); } 40781418a27Smrg 40881418a27Smrg template<typename _Tp, typename _Allocator> 40981418a27Smrg inline mutable_buffer 41081418a27Smrg buffer(vector<_Tp, _Allocator>& __data) noexcept 41181418a27Smrg { return net::__to_mbuf(__data.data(), __data.size()); } 41281418a27Smrg 41381418a27Smrg template<typename _Tp, typename _Allocator> 41481418a27Smrg inline const_buffer 41581418a27Smrg buffer(const vector<_Tp, _Allocator>& __data) noexcept 41681418a27Smrg { return net::__to_cbuf(__data.data(), __data.size()); } 41781418a27Smrg 41881418a27Smrg template<typename _CharT, typename _Traits, typename _Allocator> 41981418a27Smrg inline mutable_buffer 42081418a27Smrg buffer(basic_string<_CharT, _Traits, _Allocator>& __data) noexcept 42181418a27Smrg { return net::__to_mbuf(&__data.front(), __data.size()); } 42281418a27Smrg 42381418a27Smrg template<typename _CharT, typename _Traits, typename _Allocator> 42481418a27Smrg inline const_buffer 42581418a27Smrg buffer(const basic_string<_CharT, _Traits, _Allocator>& __data) noexcept 42681418a27Smrg { return net::__to_cbuf(&__data.front(), __data.size()); } 42781418a27Smrg 42881418a27Smrg template<typename _CharT, typename _Traits> 42981418a27Smrg inline const_buffer 43081418a27Smrg buffer(basic_string_view<_CharT, _Traits> __data) noexcept 43181418a27Smrg { return net::__to_cbuf(__data.data(), __data.size()); } 43281418a27Smrg 43381418a27Smrg template<typename _Tp, size_t _Nm> 43481418a27Smrg inline mutable_buffer 43581418a27Smrg buffer(_Tp (&__data)[_Nm], size_t __n) noexcept 43681418a27Smrg { return buffer(net::buffer(__data), __n * sizeof(_Tp)); } 43781418a27Smrg 43881418a27Smrg template<typename _Tp, size_t _Nm> 43981418a27Smrg inline const_buffer 44081418a27Smrg buffer(const _Tp (&__data)[_Nm], size_t __n) noexcept 44181418a27Smrg { return buffer(net::buffer(__data), __n * sizeof(_Tp)); } 44281418a27Smrg 44381418a27Smrg template<typename _Tp, size_t _Nm> 44481418a27Smrg inline mutable_buffer 44581418a27Smrg buffer(array<_Tp, _Nm>& __data, size_t __n) noexcept 44681418a27Smrg { return buffer(net::buffer(__data), __n * sizeof(_Tp)); } 44781418a27Smrg 44881418a27Smrg template<typename _Tp, size_t _Nm> 44981418a27Smrg inline const_buffer 45081418a27Smrg buffer(array<const _Tp, _Nm>& __data, size_t __n) noexcept 45181418a27Smrg { return buffer(net::buffer(__data), __n * sizeof(_Tp)); } 45281418a27Smrg 45381418a27Smrg template<typename _Tp, size_t _Nm> 45481418a27Smrg inline const_buffer 45581418a27Smrg buffer(const array<_Tp, _Nm>& __data, size_t __n) noexcept 45681418a27Smrg { return buffer(net::buffer(__data), __n * sizeof(_Tp)); } 45781418a27Smrg 45881418a27Smrg template<typename _Tp, typename _Allocator> 45981418a27Smrg inline mutable_buffer 46081418a27Smrg buffer(vector<_Tp, _Allocator>& __data, size_t __n) noexcept 46181418a27Smrg { return buffer(net::buffer(__data), __n * sizeof(_Tp)); } 46281418a27Smrg 46381418a27Smrg template<typename _Tp, typename _Allocator> 46481418a27Smrg inline const_buffer 46581418a27Smrg buffer(const vector<_Tp, _Allocator>& __data, size_t __n) noexcept 46681418a27Smrg { return buffer(net::buffer(__data), __n * sizeof(_Tp)); } 46781418a27Smrg 46881418a27Smrg template<typename _CharT, typename _Traits, typename _Allocator> 46981418a27Smrg inline mutable_buffer 47081418a27Smrg buffer(basic_string<_CharT, _Traits, _Allocator>& __data, 47181418a27Smrg size_t __n) noexcept 47281418a27Smrg { return buffer(net::buffer(__data), __n * sizeof(_CharT)); } 47381418a27Smrg 47481418a27Smrg template<typename _CharT, typename _Traits, typename _Allocator> 47581418a27Smrg inline const_buffer 47681418a27Smrg buffer(const basic_string<_CharT, _Traits, _Allocator>& __data, 47781418a27Smrg size_t __n) noexcept 47881418a27Smrg { return buffer(net::buffer(__data), __n * sizeof(_CharT)); } 47981418a27Smrg 48081418a27Smrg template<typename _CharT, typename _Traits> 48181418a27Smrg inline const_buffer 48281418a27Smrg buffer(basic_string_view<_CharT, _Traits> __data, size_t __n) noexcept 48381418a27Smrg { return buffer(net::buffer(__data), __n * sizeof(_CharT)); } 48481418a27Smrg 48581418a27Smrg 48681418a27Smrg template<typename _Sequence> 48781418a27Smrg class __dynamic_buffer_base 48881418a27Smrg { 48981418a27Smrg public: 49081418a27Smrg // types: 491*f0fbc68bSmrg using const_buffers_type = const_buffer; 492*f0fbc68bSmrg using mutable_buffers_type = mutable_buffer; 49381418a27Smrg 49481418a27Smrg // constructors: 49581418a27Smrg explicit 49681418a27Smrg __dynamic_buffer_base(_Sequence& __seq) noexcept 49781418a27Smrg : _M_seq(__seq), _M_size(__seq.size()), _M_max_size(__seq.max_size()) 49881418a27Smrg { } 49981418a27Smrg 50081418a27Smrg __dynamic_buffer_base(_Sequence& __seq, size_t __maximum_size) noexcept 50181418a27Smrg : _M_seq(__seq), _M_size(__seq.size()), _M_max_size(__maximum_size) 50281418a27Smrg { __glibcxx_assert(__seq.size() <= __maximum_size); } 50381418a27Smrg 50481418a27Smrg __dynamic_buffer_base(__dynamic_buffer_base&&) = default; 50581418a27Smrg 50681418a27Smrg // members: 50781418a27Smrg size_t size() const noexcept { return _M_size; } 50881418a27Smrg size_t max_size() const noexcept { return _M_max_size; } 50981418a27Smrg size_t capacity() const noexcept { return _M_seq.capacity(); } 51081418a27Smrg 51181418a27Smrg const_buffers_type 51281418a27Smrg data() const noexcept 51381418a27Smrg { return net::buffer(_M_seq, _M_size); } 51481418a27Smrg 51581418a27Smrg mutable_buffers_type 51681418a27Smrg prepare(size_t __n) 51781418a27Smrg { 51881418a27Smrg if ((_M_size + __n) > _M_max_size) 51981418a27Smrg __throw_length_error("dynamic_vector_buffer::prepare"); 52081418a27Smrg 52181418a27Smrg _M_seq.resize(_M_size + __n); 52281418a27Smrg return buffer(net::buffer(_M_seq) + _M_size, __n); 52381418a27Smrg } 52481418a27Smrg 52581418a27Smrg void 52681418a27Smrg commit(size_t __n) 52781418a27Smrg { 52881418a27Smrg _M_size += std::min(__n, _M_seq.size() - _M_size); 52981418a27Smrg _M_seq.resize(_M_size); 53081418a27Smrg } 53181418a27Smrg 53281418a27Smrg void 53381418a27Smrg consume(size_t __n) 53481418a27Smrg { 53581418a27Smrg size_t __m = std::min(__n, _M_size); 53681418a27Smrg _M_seq.erase(_M_seq.begin(), _M_seq.begin() + __m); 53781418a27Smrg _M_size -= __m; 53881418a27Smrg } 53981418a27Smrg 54081418a27Smrg private: 54181418a27Smrg _Sequence& _M_seq; 54281418a27Smrg size_t _M_size; 54381418a27Smrg const size_t _M_max_size; 54481418a27Smrg }; 54581418a27Smrg 54681418a27Smrg template<typename _Tp, typename _Allocator> 54781418a27Smrg class dynamic_vector_buffer 54881418a27Smrg : public __dynamic_buffer_base<vector<_Tp, _Allocator>> 54981418a27Smrg { 55081418a27Smrg public: 55181418a27Smrg using __dynamic_buffer_base<vector<_Tp, _Allocator>>::__dynamic_buffer_base; 55281418a27Smrg }; 55381418a27Smrg 55481418a27Smrg template<typename _CharT, typename _Traits, typename _Allocator> 55581418a27Smrg class dynamic_string_buffer 55681418a27Smrg : public __dynamic_buffer_base<basic_string<_CharT, _Traits, _Allocator>> 55781418a27Smrg { 55881418a27Smrg public: 55981418a27Smrg using __dynamic_buffer_base<basic_string<_CharT, _Traits, _Allocator>>:: 56081418a27Smrg __dynamic_buffer_base; 56181418a27Smrg }; 56281418a27Smrg 56381418a27Smrg // dynamic buffer creation: 56481418a27Smrg 56581418a27Smrg template<typename _Tp, typename _Allocator> 56681418a27Smrg inline dynamic_vector_buffer<_Tp, _Allocator> 56781418a27Smrg dynamic_buffer(vector<_Tp, _Allocator>& __vec) noexcept 56881418a27Smrg { return dynamic_vector_buffer<_Tp, _Allocator>{__vec}; } 56981418a27Smrg 57081418a27Smrg template<typename _Tp, typename _Allocator> 57181418a27Smrg inline dynamic_vector_buffer<_Tp, _Allocator> 57281418a27Smrg dynamic_buffer(vector<_Tp, _Allocator>& __vec, size_t __n) noexcept 57381418a27Smrg { return {__vec, __n}; } 57481418a27Smrg 57581418a27Smrg template<typename _CharT, typename _Traits, typename _Allocator> 57681418a27Smrg inline dynamic_string_buffer<_CharT, _Traits, _Allocator> 57781418a27Smrg dynamic_buffer(basic_string<_CharT, _Traits, _Allocator>& __str) noexcept 57881418a27Smrg { return dynamic_string_buffer<_CharT, _Traits, _Allocator>{__str}; } 57981418a27Smrg 58081418a27Smrg template<typename _CharT, typename _Traits, typename _Allocator> 58181418a27Smrg inline dynamic_string_buffer<_CharT, _Traits, _Allocator> 58281418a27Smrg dynamic_buffer(basic_string<_CharT, _Traits, _Allocator>& __str, 58381418a27Smrg size_t __n) noexcept 58481418a27Smrg { return {__str, __n}; } 58581418a27Smrg 58681418a27Smrg class transfer_all 58781418a27Smrg { 58881418a27Smrg public: 58981418a27Smrg size_t operator()(const error_code& __ec, size_t) const 59081418a27Smrg { return !__ec ? 1500 : 0; } 59181418a27Smrg }; 59281418a27Smrg 59381418a27Smrg class transfer_at_least 59481418a27Smrg { 59581418a27Smrg public: 59681418a27Smrg explicit transfer_at_least(size_t __m) : _M_minimum(__m) { } 59781418a27Smrg 59881418a27Smrg size_t operator()(const error_code& __ec, size_t __n) const 59981418a27Smrg { return !__ec && __n < _M_minimum ? _M_minimum - __n : 0; } 60081418a27Smrg 60181418a27Smrg private: 60281418a27Smrg size_t _M_minimum; 60381418a27Smrg }; 60481418a27Smrg 60581418a27Smrg class transfer_exactly 60681418a27Smrg { 60781418a27Smrg public: 60881418a27Smrg explicit transfer_exactly(size_t __e) : _M_exact(__e) { } 60981418a27Smrg 61081418a27Smrg size_t operator()(const error_code& __ec, size_t __n) const 61181418a27Smrg { 61281418a27Smrg size_t _Nm = -1; 61381418a27Smrg return !__ec && __n < _M_exact ? std::min(_M_exact - __n, _Nm) : 0; 61481418a27Smrg } 61581418a27Smrg 61681418a27Smrg private: 61781418a27Smrg size_t _M_exact; 61881418a27Smrg }; 61981418a27Smrg 62081418a27Smrg /** @brief synchronous read operations 62181418a27Smrg * @{ 62281418a27Smrg */ 62381418a27Smrg 62481418a27Smrg template<typename _SyncReadStream, typename _MutableBufferSequence, 62581418a27Smrg typename _CompletionCondition> 62681418a27Smrg enable_if_t<is_mutable_buffer_sequence<_MutableBufferSequence>::value, 62781418a27Smrg size_t> 62881418a27Smrg read(_SyncReadStream& __stream, const _MutableBufferSequence& __buffers, 62981418a27Smrg _CompletionCondition __completion_condition, error_code& __ec) 63081418a27Smrg { 63181418a27Smrg __ec.clear(); 63281418a27Smrg auto __i = net::buffer_sequence_begin(__buffers); 63381418a27Smrg auto __end = net::buffer_sequence_end(__buffers); 63481418a27Smrg mutable_buffer __to; 63581418a27Smrg size_t __total = 0; 63681418a27Smrg size_t __n; 63781418a27Smrg while ((__n = __completion_condition(__ec, __total)) 63881418a27Smrg && (__i != __end || __to.size())) 63981418a27Smrg { 64081418a27Smrg if (__to.size() == 0) 64181418a27Smrg __to = mutable_buffer(*__i++); 64281418a27Smrg __n = __stream.read_some(buffer(__to, __n), __ec); 64381418a27Smrg __to = __to + __n; 64481418a27Smrg __total += __n; 64581418a27Smrg } 64681418a27Smrg return __total; 64781418a27Smrg } 64881418a27Smrg 64981418a27Smrg template<typename _SyncReadStream, typename _MutableBufferSequence> 65081418a27Smrg inline 65181418a27Smrg enable_if_t<is_mutable_buffer_sequence<_MutableBufferSequence>::value, 65281418a27Smrg size_t> 65381418a27Smrg read(_SyncReadStream& __stream, const _MutableBufferSequence& __buffers) 65481418a27Smrg { 65581418a27Smrg error_code __ec; 65681418a27Smrg return net::read(__stream, __buffers, transfer_all{}, __ec); 65781418a27Smrg } 65881418a27Smrg 65981418a27Smrg template<typename _SyncReadStream, typename _MutableBufferSequence> 66081418a27Smrg inline 66181418a27Smrg enable_if_t<is_mutable_buffer_sequence<_MutableBufferSequence>::value, 66281418a27Smrg size_t> 66381418a27Smrg read(_SyncReadStream& __stream, const _MutableBufferSequence& __buffers, 66481418a27Smrg error_code& __ec) 66581418a27Smrg { return net::read(__stream, __buffers, transfer_all{}, __ec); } 66681418a27Smrg 66781418a27Smrg template<typename _SyncReadStream, typename _MutableBufferSequence, 66881418a27Smrg typename _CompletionCondition> 66981418a27Smrg inline 67081418a27Smrg enable_if_t<is_mutable_buffer_sequence<_MutableBufferSequence>::value, 67181418a27Smrg size_t> 67281418a27Smrg read(_SyncReadStream& __stream, const _MutableBufferSequence& __buffers, 67381418a27Smrg _CompletionCondition __completion_condition) 67481418a27Smrg { 67581418a27Smrg error_code __ec; 67681418a27Smrg return net::read(__stream, __buffers, __completion_condition, __ec); 67781418a27Smrg } 67881418a27Smrg 67981418a27Smrg 68081418a27Smrg template<typename _SyncReadStream, typename _DynamicBuffer, 68181418a27Smrg typename _CompletionCondition> 68281418a27Smrg enable_if_t<is_dynamic_buffer<decay_t<_DynamicBuffer>>::value, size_t> 68381418a27Smrg read(_SyncReadStream& __stream, _DynamicBuffer&& __b, 68481418a27Smrg _CompletionCondition __completion_condition, error_code& __ec) 68581418a27Smrg { 68681418a27Smrg const size_t __limit = 64; 68781418a27Smrg __ec.clear(); 68881418a27Smrg size_t __cap = std::max(__b.capacity() - __b.size(), __limit); 68981418a27Smrg size_t __total = 0; 69081418a27Smrg size_t __n; 69181418a27Smrg while ((__n = __completion_condition(__ec, __total)) 69281418a27Smrg && __b.size() != __b.max_size()) 69381418a27Smrg { 69481418a27Smrg __n = std::min(__n, __b.max_size() - __b.size()); 69581418a27Smrg size_t __cap = std::max(__b.capacity() - __b.size(), __limit); 69681418a27Smrg mutable_buffer __to = __b.prepare(std::min(__cap, __n)); 69781418a27Smrg __n = __stream.read_some(__to, __ec); 69881418a27Smrg __to = __to + __n; 69981418a27Smrg __total += __n; 70081418a27Smrg __b.commit(__n); 70181418a27Smrg } 70281418a27Smrg return __total; 70381418a27Smrg } 70481418a27Smrg 70581418a27Smrg template<typename _SyncReadStream, typename _DynamicBuffer> 70681418a27Smrg inline enable_if_t<is_dynamic_buffer<_DynamicBuffer>::value, size_t> 70781418a27Smrg read(_SyncReadStream& __stream, _DynamicBuffer&& __b) 70881418a27Smrg { 70981418a27Smrg error_code __ec; 71081418a27Smrg return net::read(__stream, __b, transfer_all{}, __ec); 71181418a27Smrg } 71281418a27Smrg 71381418a27Smrg template<typename _SyncReadStream, typename _DynamicBuffer> 71481418a27Smrg inline enable_if_t<is_dynamic_buffer<_DynamicBuffer>::value, size_t> 71581418a27Smrg read(_SyncReadStream& __stream, _DynamicBuffer&& __b, error_code& __ec) 71681418a27Smrg { 71781418a27Smrg return net::read(__stream, __b, transfer_all{}, __ec); 71881418a27Smrg } 71981418a27Smrg 72081418a27Smrg template<typename _SyncReadStream, typename _DynamicBuffer, 72181418a27Smrg typename _CompletionCondition> 72281418a27Smrg inline enable_if_t<is_dynamic_buffer<_DynamicBuffer>::value, size_t> 72381418a27Smrg read(_SyncReadStream& __stream, _DynamicBuffer&& __b, 72481418a27Smrg _CompletionCondition __completion_condition) 72581418a27Smrg { 72681418a27Smrg error_code __ec; 72781418a27Smrg return net::read(__stream, __b, __completion_condition, __ec); 72881418a27Smrg } 72981418a27Smrg 7307327edafSmrg /// @} 73181418a27Smrg 73281418a27Smrg /** @brief asynchronous read operations 73381418a27Smrg * @{ 73481418a27Smrg */ 73581418a27Smrg 73681418a27Smrg template<typename _AsyncReadStream, typename _MutableBufferSequence, 73781418a27Smrg typename _CompletionCondition, typename _CompletionToken> 73881418a27Smrg __deduced_t<_CompletionToken, void(error_code, size_t)> 73981418a27Smrg async_read(_AsyncReadStream& __stream, 74081418a27Smrg const _MutableBufferSequence& __buffers, 74181418a27Smrg _CompletionCondition __completion_condition, 74281418a27Smrg _CompletionToken&& __token) 74381418a27Smrg { 74481418a27Smrg error_code __ec; 74581418a27Smrg } 74681418a27Smrg 74781418a27Smrg template<typename _AsyncReadStream, typename _MutableBufferSequence, 74881418a27Smrg typename _CompletionToken> 74981418a27Smrg inline __deduced_t<_CompletionToken, void(error_code, size_t)> 75081418a27Smrg async_read(_AsyncReadStream& __stream, 75181418a27Smrg const _MutableBufferSequence& __buffers, 75281418a27Smrg _CompletionToken&& __token) 75381418a27Smrg { 75481418a27Smrg return net::async_read(__stream, __buffers, transfer_all{}, 75581418a27Smrg std::forward<_CompletionToken>(__token)); 75681418a27Smrg } 75781418a27Smrg 75881418a27Smrg template<typename _AsyncReadStream, typename _DynamicBuffer, 75981418a27Smrg typename _CompletionCondition, typename _CompletionToken> 76081418a27Smrg __deduced_t<_CompletionToken, void(error_code, size_t)> 76181418a27Smrg async_read(_AsyncReadStream& __stream, _DynamicBuffer&& __b, 76281418a27Smrg _CompletionCondition __completion_condition, 76381418a27Smrg _CompletionToken&& __token) 76481418a27Smrg { 76581418a27Smrg error_code __ec; 76681418a27Smrg } 76781418a27Smrg 76881418a27Smrg template<typename _AsyncReadStream, typename _DynamicBuffer, 76981418a27Smrg typename _CompletionToken> 77081418a27Smrg inline __deduced_t<_CompletionToken, void(error_code, size_t)> 77181418a27Smrg async_read(_AsyncReadStream& __stream, _DynamicBuffer&& __b, 77281418a27Smrg _CompletionToken&& __token) 77381418a27Smrg { 77481418a27Smrg return net::async_read(__stream, __b, transfer_all{}, 77581418a27Smrg std::forward<_CompletionToken>(__token)); 77681418a27Smrg } 77781418a27Smrg 7787327edafSmrg /// @} 77981418a27Smrg 78081418a27Smrg#if 0 78181418a27Smrg /** @brief synchronous write operations: 78281418a27Smrg * @{ 78381418a27Smrg */ 78481418a27Smrg 78581418a27Smrg template<typename _SyncWriteStream, typename _ConstBufferSequence> 78681418a27Smrg size_t write(_SyncWriteStream& __stream, 78781418a27Smrg const _ConstBufferSequence& __buffers); 78881418a27Smrg template<typename _SyncWriteStream, typename _ConstBufferSequence> 78981418a27Smrg size_t write(_SyncWriteStream& __stream, 79081418a27Smrg const _ConstBufferSequence& __buffers, error_code& __ec); 79181418a27Smrg template<typename _SyncWriteStream, typename _ConstBufferSequence, 79281418a27Smrg typename _CompletionCondition> 79381418a27Smrg size_t write(_SyncWriteStream& __stream, 79481418a27Smrg const _ConstBufferSequence& __buffers, 79581418a27Smrg _CompletionCondition __completion_condition); 79681418a27Smrg template<typename _SyncWriteStream, typename _ConstBufferSequence, 79781418a27Smrg typename _CompletionCondition> 79881418a27Smrg size_t write(_SyncWriteStream& __stream, 79981418a27Smrg const _ConstBufferSequence& __buffers, 80081418a27Smrg _CompletionCondition __completion_condition, 80181418a27Smrg error_code& __ec); 80281418a27Smrg 80381418a27Smrg template<typename _SyncWriteStream, typename _DynamicBuffer> 80481418a27Smrg size_t write(_SyncWriteStream& __stream, _DynamicBuffer&& __b); 80581418a27Smrg template<typename _SyncWriteStream, typename _DynamicBuffer> 80681418a27Smrg size_t write(_SyncWriteStream& __stream, _DynamicBuffer&& __b, error_code& __ec); 80781418a27Smrg template<typename _SyncWriteStream, typename _DynamicBuffer, typename _CompletionCondition> 80881418a27Smrg size_t write(_SyncWriteStream& __stream, _DynamicBuffer&& __b, 80981418a27Smrg _CompletionCondition __completion_condition); 81081418a27Smrg template<typename _SyncWriteStream, typename _DynamicBuffer, typename _CompletionCondition> 81181418a27Smrg size_t write(_SyncWriteStream& __stream, _DynamicBuffer&& __b, 81281418a27Smrg _CompletionCondition __completion_condition, error_code& __ec); 81381418a27Smrg 8147327edafSmrg /// @} 81581418a27Smrg 81681418a27Smrg /** @brief asynchronous write operations 81781418a27Smrg * @{ 81881418a27Smrg */ 81981418a27Smrg 82081418a27Smrg template<typename _AsyncWriteStream, typename _ConstBufferSequence, 82181418a27Smrg typename _CompletionToken> 82281418a27Smrg DEDUCED async_write(_AsyncWriteStream& __stream, 82381418a27Smrg const _ConstBufferSequence& __buffers, 82481418a27Smrg _CompletionToken&& __token); 82581418a27Smrg template<typename _AsyncWriteStream, typename _ConstBufferSequence, 82681418a27Smrg typename _CompletionCondition, typename _CompletionToken> 82781418a27Smrg DEDUCED async_write(_AsyncWriteStream& __stream, 82881418a27Smrg const _ConstBufferSequence& __buffers, 82981418a27Smrg _CompletionCondition __completion_condition, 83081418a27Smrg _CompletionToken&& __token); 83181418a27Smrg 83281418a27Smrg template<typename _AsyncWriteStream, typename _DynamicBuffer, typename _CompletionToken> 83381418a27Smrg DEDUCED async_write(_AsyncWriteStream& __stream, 83481418a27Smrg _DynamicBuffer&& __b, _CompletionToken&& __token); 83581418a27Smrg template<typename _AsyncWriteStream, typename _DynamicBuffer, 83681418a27Smrg typename _CompletionCondition, typename _CompletionToken> 83781418a27Smrg DEDUCED async_write(_AsyncWriteStream& __stream, 83881418a27Smrg _DynamicBuffer&& __b, 83981418a27Smrg _CompletionCondition __completion_condition, 84081418a27Smrg _CompletionToken&& __token); 84181418a27Smrg 8427327edafSmrg /// @} 84381418a27Smrg 84481418a27Smrg /** @brief synchronous delimited read operations 84581418a27Smrg * @{ 84681418a27Smrg */ 84781418a27Smrg 84881418a27Smrg template<typename _SyncReadStream, typename _DynamicBuffer> 84981418a27Smrg size_t read_until(_SyncReadStream& __s, _DynamicBuffer&& __b, char __delim); 85081418a27Smrg template<typename _SyncReadStream, typename _DynamicBuffer> 85181418a27Smrg size_t read_until(_SyncReadStream& __s, _DynamicBuffer&& __b, 85281418a27Smrg char __delim, error_code& __ec); 85381418a27Smrg template<typename _SyncReadStream, typename _DynamicBuffer> 85481418a27Smrg size_t read_until(_SyncReadStream& __s, _DynamicBuffer&& __b, string_view __delim); 85581418a27Smrg template<typename _SyncReadStream, typename _DynamicBuffer> 85681418a27Smrg size_t read_until(_SyncReadStream& __s, _DynamicBuffer&& __b, 85781418a27Smrg string_view __delim, error_code& __ec); 85881418a27Smrg 8597327edafSmrg /// @} 86081418a27Smrg 86181418a27Smrg /** @brief asynchronous delimited read operations 86281418a27Smrg * @{ 86381418a27Smrg */ 86481418a27Smrg 86581418a27Smrg template<typename _AsyncReadStream, typename _DynamicBuffer, typename _CompletionToken> 86681418a27Smrg DEDUCED async_read_until(_AsyncReadStream& __s, 86781418a27Smrg _DynamicBuffer&& __b, char __delim, 86881418a27Smrg _CompletionToken&& __token); 86981418a27Smrg template<typename _AsyncReadStream, typename _DynamicBuffer, typename _CompletionToken> 87081418a27Smrg DEDUCED async_read_until(_AsyncReadStream& __s, 87181418a27Smrg _DynamicBuffer&& __b, string_view __delim, 87281418a27Smrg _CompletionToken&& __token); 87381418a27Smrg 8747327edafSmrg /// @} 87581418a27Smrg 87681418a27Smrg#endif 87781418a27Smrg /// @} 87881418a27Smrg 87981418a27Smrg} // namespace v1 88081418a27Smrg} // namespace net 88181418a27Smrg} // namespace experimental 88281418a27Smrg 88381418a27Smrg template<> 88481418a27Smrg struct is_error_code_enum<experimental::net::v1::stream_errc> 88581418a27Smrg : public true_type {}; 88681418a27Smrg 88781418a27Smrg_GLIBCXX_END_NAMESPACE_VERSION 88881418a27Smrg} // namespace std 88981418a27Smrg 89081418a27Smrg#endif // C++14 89181418a27Smrg 89281418a27Smrg#endif // _GLIBCXX_EXPERIMENTAL_BUFFER 893