1 1.1 mrg // <experimental/buffer> -*- C++ -*- 2 1.1 mrg 3 1.1.1.3 mrg // Copyright (C) 2015-2022 Free Software Foundation, Inc. 4 1.1 mrg // 5 1.1 mrg // This file is part of the GNU ISO C++ Library. This library is free 6 1.1 mrg // software; you can redistribute it and/or modify it under the 7 1.1 mrg // terms of the GNU General Public License as published by the 8 1.1 mrg // Free Software Foundation; either version 3, or (at your option) 9 1.1 mrg // any later version. 10 1.1 mrg 11 1.1 mrg // This library is distributed in the hope that it will be useful, 12 1.1 mrg // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 mrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 1.1 mrg // GNU General Public License for more details. 15 1.1 mrg 16 1.1 mrg // Under Section 7 of GPL version 3, you are granted additional 17 1.1 mrg // permissions described in the GCC Runtime Library Exception, version 18 1.1 mrg // 3.1, as published by the Free Software Foundation. 19 1.1 mrg 20 1.1 mrg // You should have received a copy of the GNU General Public License and 21 1.1 mrg // a copy of the GCC Runtime Library Exception along with this program; 22 1.1 mrg // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 1.1 mrg // <http://www.gnu.org/licenses/>. 24 1.1 mrg 25 1.1 mrg /** @file experimental/buffer 26 1.1 mrg * This is a TS C++ Library header. 27 1.1.1.2 mrg * @ingroup networking-ts 28 1.1 mrg */ 29 1.1 mrg 30 1.1 mrg #ifndef _GLIBCXX_EXPERIMENTAL_BUFFER 31 1.1 mrg #define _GLIBCXX_EXPERIMENTAL_BUFFER 1 32 1.1 mrg 33 1.1 mrg #pragma GCC system_header 34 1.1 mrg 35 1.1 mrg #if __cplusplus >= 201402L 36 1.1 mrg 37 1.1 mrg #include <array> 38 1.1 mrg #include <string> 39 1.1 mrg #include <system_error> 40 1.1 mrg #include <vector> 41 1.1 mrg #include <cstring> 42 1.1 mrg #include <experimental/string_view> 43 1.1 mrg #include <experimental/bits/net.h> 44 1.1 mrg 45 1.1 mrg namespace std _GLIBCXX_VISIBILITY(default) 46 1.1 mrg { 47 1.1 mrg _GLIBCXX_BEGIN_NAMESPACE_VERSION 48 1.1 mrg namespace experimental 49 1.1 mrg { 50 1.1 mrg namespace net 51 1.1 mrg { 52 1.1 mrg inline namespace v1 53 1.1 mrg { 54 1.1 mrg 55 1.1.1.2 mrg /** @addtogroup networking-ts 56 1.1.1.2 mrg * @{ 57 1.1 mrg */ 58 1.1 mrg 59 1.1 mrg enum class stream_errc { // TODO decide values 60 1.1 mrg eof = 1, 61 1.1 mrg not_found = 2 62 1.1 mrg }; 63 1.1 mrg 64 1.1 mrg const error_category& stream_category() noexcept // TODO not inline 65 1.1 mrg { 66 1.1 mrg struct __cat : error_category 67 1.1 mrg { 68 1.1 mrg const char* name() const noexcept { return "stream"; } 69 1.1 mrg 70 1.1 mrg std::string message(int __e) const 71 1.1 mrg { 72 1.1 mrg if (__e == (int)stream_errc::eof) 73 1.1 mrg return "EOF"; 74 1.1 mrg else if (__e == (int)stream_errc::not_found) 75 1.1 mrg return "not found"; 76 1.1 mrg return "stream"; 77 1.1 mrg } 78 1.1 mrg 79 1.1 mrg virtual void __message(int) { } // TODO dual ABI XXX 80 1.1 mrg }; 81 1.1 mrg static __cat __c; 82 1.1 mrg return __c; 83 1.1 mrg } 84 1.1 mrg 85 1.1 mrg inline error_code 86 1.1 mrg make_error_code(stream_errc __e) noexcept 87 1.1 mrg { return error_code(static_cast<int>(__e), stream_category()); } 88 1.1 mrg 89 1.1 mrg inline error_condition 90 1.1 mrg make_error_condition(stream_errc __e) noexcept 91 1.1 mrg { return error_condition(static_cast<int>(__e), stream_category()); } 92 1.1 mrg 93 1.1 mrg class mutable_buffer 94 1.1 mrg { 95 1.1 mrg public: 96 1.1 mrg // constructors: 97 1.1 mrg mutable_buffer() noexcept : _M_data(), _M_size() { } 98 1.1 mrg 99 1.1 mrg mutable_buffer(void* __p, size_t __n) noexcept 100 1.1 mrg : _M_data(__p), _M_size(__n) { } 101 1.1 mrg 102 1.1 mrg // members: 103 1.1 mrg void* data() const noexcept { return _M_data; } 104 1.1 mrg size_t size() const noexcept { return _M_size; } 105 1.1 mrg 106 1.1 mrg private: 107 1.1 mrg void* _M_data; 108 1.1 mrg size_t _M_size; 109 1.1 mrg }; 110 1.1 mrg 111 1.1 mrg class const_buffer 112 1.1 mrg { 113 1.1 mrg public: 114 1.1 mrg // constructors: 115 1.1 mrg const_buffer() noexcept : _M_data(), _M_size() { } 116 1.1 mrg 117 1.1 mrg const_buffer(const void* __p, size_t __n) noexcept 118 1.1 mrg : _M_data(__p), _M_size(__n) { } 119 1.1 mrg 120 1.1 mrg const_buffer(const mutable_buffer& __b) noexcept 121 1.1 mrg : _M_data(__b.data()), _M_size(__b.size()) { } 122 1.1 mrg 123 1.1 mrg // members: 124 1.1 mrg const void* data() const noexcept { return _M_data; } 125 1.1 mrg size_t size() const noexcept { return _M_size; } 126 1.1 mrg 127 1.1 mrg private: 128 1.1 mrg const void* _M_data; 129 1.1 mrg size_t _M_size; 130 1.1 mrg }; 131 1.1 mrg 132 1.1 mrg 133 1.1 mrg /** @brief buffer sequence access 134 1.1 mrg * 135 1.1 mrg * Uniform access to types that meet the BufferSequence requirements. 136 1.1 mrg * @{ 137 1.1 mrg */ 138 1.1 mrg 139 1.1 mrg inline const mutable_buffer* 140 1.1 mrg buffer_sequence_begin(const mutable_buffer& __b) 141 1.1 mrg { return std::addressof(__b); } 142 1.1 mrg 143 1.1 mrg inline const const_buffer* 144 1.1 mrg buffer_sequence_begin(const const_buffer& __b) 145 1.1 mrg { return std::addressof(__b); } 146 1.1 mrg 147 1.1 mrg inline const mutable_buffer* 148 1.1 mrg buffer_sequence_end(const mutable_buffer& __b) 149 1.1 mrg { return std::addressof(__b) + 1; } 150 1.1 mrg 151 1.1 mrg inline const const_buffer* 152 1.1 mrg buffer_sequence_end(const const_buffer& __b) 153 1.1 mrg { return std::addressof(__b) + 1; } 154 1.1 mrg 155 1.1 mrg template<typename _Cont> 156 1.1 mrg auto 157 1.1 mrg buffer_sequence_begin(_Cont& __c) -> decltype(__c.begin()) 158 1.1 mrg { return __c.begin(); } 159 1.1 mrg 160 1.1 mrg template<typename _Cont> 161 1.1 mrg auto 162 1.1 mrg buffer_sequence_begin(const _Cont& __c) -> decltype(__c.begin()) 163 1.1 mrg { return __c.begin(); } 164 1.1 mrg 165 1.1 mrg template<typename _Cont> 166 1.1 mrg auto 167 1.1 mrg buffer_sequence_end(_Cont& __c) -> decltype(__c.end()) 168 1.1 mrg { return __c.end(); } 169 1.1 mrg 170 1.1 mrg template<typename _Cont> 171 1.1 mrg auto 172 1.1 mrg buffer_sequence_end(const _Cont& __c) -> decltype(__c.end()) 173 1.1 mrg { return __c.end(); } 174 1.1 mrg 175 1.1.1.2 mrg /// @} 176 1.1 mrg 177 1.1 mrg 178 1.1 mrg /** @brief buffer type traits 179 1.1 mrg * 180 1.1 mrg * @{ 181 1.1 mrg */ 182 1.1 mrg 183 1.1 mrg template<typename _Tp, typename _Buffer, 184 1.1 mrg typename _Begin 185 1.1 mrg = decltype(net::buffer_sequence_begin(std::declval<_Tp&>())), 186 1.1 mrg typename _End 187 1.1 mrg = decltype(net::buffer_sequence_end(std::declval<_Tp&>()))> 188 1.1 mrg using __buffer_sequence = enable_if_t<__and_< 189 1.1 mrg __is_value_constructible<_Tp>, is_same<_Begin, _End>, 190 1.1 mrg is_convertible<typename iterator_traits<_Begin>::value_type, _Buffer> 191 1.1 mrg >::value>; 192 1.1 mrg 193 1.1 mrg template<typename _Tp, typename _Buffer, typename = void> 194 1.1 mrg struct __is_buffer_sequence : false_type 195 1.1 mrg { }; 196 1.1 mrg 197 1.1 mrg template<typename _Tp, typename _Buffer> 198 1.1 mrg struct __is_buffer_sequence<_Tp, _Buffer, __buffer_sequence<_Tp, _Buffer>> 199 1.1 mrg : true_type 200 1.1 mrg { }; 201 1.1 mrg 202 1.1 mrg template<typename _Tp> 203 1.1 mrg struct is_mutable_buffer_sequence 204 1.1 mrg : __is_buffer_sequence<_Tp, mutable_buffer>::type 205 1.1 mrg { }; 206 1.1 mrg 207 1.1 mrg template<typename _Tp> 208 1.1 mrg struct is_const_buffer_sequence 209 1.1 mrg : __is_buffer_sequence<_Tp, const_buffer>::type 210 1.1 mrg { }; 211 1.1 mrg 212 1.1 mrg template<typename _Tp> 213 1.1 mrg constexpr bool is_mutable_buffer_sequence_v 214 1.1 mrg = is_mutable_buffer_sequence<_Tp>::value; 215 1.1 mrg 216 1.1 mrg template<typename _Tp> 217 1.1 mrg constexpr bool is_const_buffer_sequence_v 218 1.1 mrg = is_const_buffer_sequence<_Tp>::value; 219 1.1 mrg 220 1.1 mrg template<typename _Tp, typename = void> 221 1.1 mrg struct __is_dynamic_buffer_impl : false_type 222 1.1 mrg { }; 223 1.1 mrg 224 1.1 mrg // Check DynamicBuffer requirements. 225 1.1 mrg template<typename _Tp, typename _Up = remove_const_t<_Tp>> 226 1.1 mrg auto 227 1.1 mrg __dynamic_buffer_reqs(_Up* __x = 0, const _Up* __x1 = 0, size_t __n = 0) 228 1.1 mrg -> enable_if_t<__and_< 229 1.1 mrg is_move_constructible<_Up>, 230 1.1 mrg is_const_buffer_sequence<typename _Tp::const_buffers_type>, 231 1.1 mrg is_mutable_buffer_sequence<typename _Tp::mutable_buffers_type>, 232 1.1 mrg is_same<decltype(__x1->size()), size_t>, 233 1.1 mrg is_same<decltype(__x1->max_size()), size_t>, 234 1.1 mrg is_same<decltype(__x1->capacity()), size_t>, 235 1.1 mrg is_same<decltype(__x1->data()), typename _Tp::const_buffers_type>, 236 1.1 mrg is_same<decltype(__x->prepare(__n)), typename _Tp::mutable_buffers_type>, 237 1.1 mrg is_void<decltype(__x->commit(__n), __x->consume(__n), void())> 238 1.1 mrg >::value>; 239 1.1 mrg 240 1.1 mrg template<typename _Tp> 241 1.1 mrg struct __is_dynamic_buffer_impl<_Tp, 242 1.1 mrg decltype(__dynamic_buffer_reqs<_Tp>())> 243 1.1 mrg : true_type 244 1.1 mrg { }; 245 1.1 mrg 246 1.1 mrg template<typename _Tp> 247 1.1 mrg struct is_dynamic_buffer : __is_dynamic_buffer_impl<_Tp>::type 248 1.1 mrg { }; 249 1.1 mrg 250 1.1 mrg template<typename _Tp> 251 1.1 mrg constexpr bool is_dynamic_buffer_v = is_dynamic_buffer<_Tp>::value; 252 1.1 mrg 253 1.1.1.2 mrg /// @} 254 1.1 mrg 255 1.1 mrg /// buffer size 256 1.1 mrg template<typename _ConstBufferSequence> 257 1.1 mrg size_t 258 1.1 mrg buffer_size(const _ConstBufferSequence& __buffers) noexcept 259 1.1 mrg { 260 1.1 mrg size_t __total_size = 0; 261 1.1 mrg auto __i = net::buffer_sequence_begin(__buffers); 262 1.1 mrg const auto __end = net::buffer_sequence_end(__buffers); 263 1.1 mrg for (; __i != __end; ++__i) 264 1.1 mrg __total_size += const_buffer(*__i).size(); 265 1.1 mrg return __total_size; 266 1.1 mrg } 267 1.1 mrg 268 1.1 mrg template<typename _ConstBufferSequence> 269 1.1 mrg bool 270 1.1 mrg __buffer_empty(const _ConstBufferSequence& __buffers) noexcept 271 1.1 mrg { 272 1.1 mrg auto __i = net::buffer_sequence_begin(__buffers); 273 1.1 mrg const auto __end = net::buffer_sequence_end(__buffers); 274 1.1 mrg for (; __i != __end; ++__i) 275 1.1 mrg if (const_buffer(*__i).size() != 0) 276 1.1 mrg return false; 277 1.1 mrg return true; 278 1.1 mrg } 279 1.1 mrg 280 1.1 mrg // buffer copy: 281 1.1 mrg 282 1.1 mrg template<typename _MutableBufferSequence, typename _ConstBufferSequence> 283 1.1 mrg size_t 284 1.1 mrg buffer_copy(const _MutableBufferSequence& __dest, 285 1.1 mrg const _ConstBufferSequence& __source, 286 1.1 mrg size_t __max_size) noexcept 287 1.1 mrg { 288 1.1 mrg size_t __total_size = 0; 289 1.1 mrg auto __to_i = net::buffer_sequence_begin(__dest); 290 1.1 mrg const auto __to_end = net::buffer_sequence_end(__dest); 291 1.1 mrg auto __from_i = net::buffer_sequence_begin(__source); 292 1.1 mrg const auto __from_end = net::buffer_sequence_end(__source); 293 1.1 mrg mutable_buffer __to; 294 1.1 mrg const_buffer __from; 295 1.1 mrg while (((__from_i != __from_end && __to_i != __to_end) 296 1.1 mrg || (__from.size() && __to.size())) 297 1.1 mrg && __total_size < __max_size) 298 1.1 mrg { 299 1.1 mrg if (__from.size() == 0) 300 1.1 mrg __from = const_buffer{*__from_i++}; 301 1.1 mrg if (__to.size() == 0) 302 1.1 mrg __to = mutable_buffer{*__to_i++}; 303 1.1 mrg 304 1.1 mrg size_t __n = std::min(__from.size(), __to.size()); 305 1.1 mrg __n = std::min(__n, __max_size - __total_size); 306 1.1 mrg std::memcpy(__to.data(), __from.data(), __n); 307 1.1 mrg __from = { (const char*)__from.data() + __n, __from.size() - __n }; 308 1.1 mrg __to = { (char*)__to.data() + __n, __to.size() - __n }; 309 1.1 mrg __total_size += __n; 310 1.1 mrg } 311 1.1 mrg return __total_size; 312 1.1 mrg } 313 1.1 mrg 314 1.1 mrg template<typename _MutableBufferSequence, typename _ConstBufferSequence> 315 1.1 mrg inline size_t 316 1.1 mrg buffer_copy(const _MutableBufferSequence& __dest, 317 1.1 mrg const _ConstBufferSequence& __source) noexcept 318 1.1.1.3 mrg { return net::buffer_copy(__dest, __source, size_t(-1)); } 319 1.1 mrg 320 1.1 mrg 321 1.1 mrg // buffer arithmetic: 322 1.1 mrg 323 1.1 mrg inline mutable_buffer 324 1.1 mrg operator+(const mutable_buffer& __b, size_t __n) noexcept 325 1.1 mrg { 326 1.1 mrg if (__n > __b.size()) 327 1.1 mrg __n = __b.size(); 328 1.1 mrg return { static_cast<char*>(__b.data()) + __n, __b.size() - __n }; 329 1.1 mrg } 330 1.1 mrg 331 1.1 mrg inline mutable_buffer 332 1.1 mrg operator+(size_t __n, const mutable_buffer& __b) noexcept 333 1.1 mrg { return __b + __n; } 334 1.1 mrg 335 1.1 mrg inline const_buffer 336 1.1 mrg operator+(const const_buffer& __b, size_t __n) noexcept 337 1.1 mrg { 338 1.1 mrg if (__n > __b.size()) 339 1.1 mrg __n = __b.size(); 340 1.1 mrg return { static_cast<const char*>(__b.data()) + __n, __b.size() - __n }; 341 1.1 mrg } 342 1.1 mrg 343 1.1 mrg inline const_buffer 344 1.1 mrg operator+(size_t __n, const const_buffer& __b) noexcept 345 1.1 mrg { return __b + __n; } 346 1.1 mrg 347 1.1 mrg // buffer creation: 348 1.1 mrg 349 1.1 mrg inline mutable_buffer 350 1.1 mrg buffer(void* __p, size_t __n) noexcept 351 1.1 mrg { return { __p, __n }; } 352 1.1 mrg 353 1.1 mrg inline const_buffer 354 1.1 mrg buffer(const void* __p, size_t __n) noexcept 355 1.1 mrg { return { __p, __n }; } 356 1.1 mrg 357 1.1 mrg inline mutable_buffer 358 1.1 mrg buffer(const mutable_buffer& __b) noexcept 359 1.1 mrg { return __b; } 360 1.1 mrg 361 1.1 mrg inline mutable_buffer 362 1.1 mrg buffer(const mutable_buffer& __b, size_t __n) noexcept 363 1.1 mrg { return { __b.data(), std::min(__b.size(), __n) }; } 364 1.1 mrg 365 1.1 mrg inline const_buffer 366 1.1 mrg buffer(const const_buffer& __b) noexcept 367 1.1 mrg { return __b; } 368 1.1 mrg 369 1.1 mrg inline const_buffer 370 1.1 mrg buffer(const const_buffer& __b, size_t __n) noexcept 371 1.1 mrg { return { __b.data(), std::min(__b.size(), __n) }; } 372 1.1 mrg 373 1.1 mrg template<typename _Tp> 374 1.1 mrg inline mutable_buffer 375 1.1 mrg __to_mbuf(_Tp* __data, size_t __n) 376 1.1 mrg { return { __n ? __data : nullptr, __n * sizeof(_Tp) }; } 377 1.1 mrg 378 1.1 mrg template<typename _Tp> 379 1.1 mrg inline const_buffer 380 1.1 mrg __to_cbuf(const _Tp* __data, size_t __n) 381 1.1 mrg { return { __n ? __data : nullptr, __n * sizeof(_Tp) }; } 382 1.1 mrg 383 1.1 mrg template<typename _Tp, size_t _Nm> 384 1.1 mrg inline mutable_buffer 385 1.1 mrg buffer(_Tp (&__data)[_Nm]) noexcept 386 1.1 mrg { return net::__to_mbuf(__data, _Nm); } 387 1.1 mrg 388 1.1 mrg template<typename _Tp, size_t _Nm> 389 1.1 mrg inline const_buffer 390 1.1 mrg buffer(const _Tp (&__data)[_Nm]) noexcept 391 1.1 mrg { return net::__to_cbuf(__data, _Nm); } 392 1.1 mrg 393 1.1 mrg template<typename _Tp, size_t _Nm> 394 1.1 mrg inline mutable_buffer 395 1.1 mrg buffer(array<_Tp, _Nm>& __data) noexcept 396 1.1 mrg { return net::__to_mbuf(__data.data(), _Nm); } 397 1.1 mrg 398 1.1 mrg template<typename _Tp, size_t _Nm> 399 1.1 mrg inline const_buffer 400 1.1 mrg buffer(array<const _Tp, _Nm>& __data) noexcept 401 1.1 mrg { return net::__to_cbuf(__data.data(), __data.size()); } 402 1.1 mrg 403 1.1 mrg template<typename _Tp, size_t _Nm> 404 1.1 mrg inline const_buffer 405 1.1 mrg buffer(const array<_Tp, _Nm>& __data) noexcept 406 1.1 mrg { return net::__to_cbuf(__data.data(), __data.size()); } 407 1.1 mrg 408 1.1 mrg template<typename _Tp, typename _Allocator> 409 1.1 mrg inline mutable_buffer 410 1.1 mrg buffer(vector<_Tp, _Allocator>& __data) noexcept 411 1.1 mrg { return net::__to_mbuf(__data.data(), __data.size()); } 412 1.1 mrg 413 1.1 mrg template<typename _Tp, typename _Allocator> 414 1.1 mrg inline const_buffer 415 1.1 mrg buffer(const vector<_Tp, _Allocator>& __data) noexcept 416 1.1 mrg { return net::__to_cbuf(__data.data(), __data.size()); } 417 1.1 mrg 418 1.1 mrg template<typename _CharT, typename _Traits, typename _Allocator> 419 1.1 mrg inline mutable_buffer 420 1.1 mrg buffer(basic_string<_CharT, _Traits, _Allocator>& __data) noexcept 421 1.1 mrg { return net::__to_mbuf(&__data.front(), __data.size()); } 422 1.1 mrg 423 1.1 mrg template<typename _CharT, typename _Traits, typename _Allocator> 424 1.1 mrg inline const_buffer 425 1.1 mrg buffer(const basic_string<_CharT, _Traits, _Allocator>& __data) noexcept 426 1.1 mrg { return net::__to_cbuf(&__data.front(), __data.size()); } 427 1.1 mrg 428 1.1 mrg template<typename _CharT, typename _Traits> 429 1.1 mrg inline const_buffer 430 1.1 mrg buffer(basic_string_view<_CharT, _Traits> __data) noexcept 431 1.1 mrg { return net::__to_cbuf(__data.data(), __data.size()); } 432 1.1 mrg 433 1.1 mrg template<typename _Tp, size_t _Nm> 434 1.1 mrg inline mutable_buffer 435 1.1 mrg buffer(_Tp (&__data)[_Nm], size_t __n) noexcept 436 1.1 mrg { return buffer(net::buffer(__data), __n * sizeof(_Tp)); } 437 1.1 mrg 438 1.1 mrg template<typename _Tp, size_t _Nm> 439 1.1 mrg inline const_buffer 440 1.1 mrg buffer(const _Tp (&__data)[_Nm], size_t __n) noexcept 441 1.1 mrg { return buffer(net::buffer(__data), __n * sizeof(_Tp)); } 442 1.1 mrg 443 1.1 mrg template<typename _Tp, size_t _Nm> 444 1.1 mrg inline mutable_buffer 445 1.1 mrg buffer(array<_Tp, _Nm>& __data, size_t __n) noexcept 446 1.1 mrg { return buffer(net::buffer(__data), __n * sizeof(_Tp)); } 447 1.1 mrg 448 1.1 mrg template<typename _Tp, size_t _Nm> 449 1.1 mrg inline const_buffer 450 1.1 mrg buffer(array<const _Tp, _Nm>& __data, size_t __n) noexcept 451 1.1 mrg { return buffer(net::buffer(__data), __n * sizeof(_Tp)); } 452 1.1 mrg 453 1.1 mrg template<typename _Tp, size_t _Nm> 454 1.1 mrg inline const_buffer 455 1.1 mrg buffer(const array<_Tp, _Nm>& __data, size_t __n) noexcept 456 1.1 mrg { return buffer(net::buffer(__data), __n * sizeof(_Tp)); } 457 1.1 mrg 458 1.1 mrg template<typename _Tp, typename _Allocator> 459 1.1 mrg inline mutable_buffer 460 1.1 mrg buffer(vector<_Tp, _Allocator>& __data, size_t __n) noexcept 461 1.1 mrg { return buffer(net::buffer(__data), __n * sizeof(_Tp)); } 462 1.1 mrg 463 1.1 mrg template<typename _Tp, typename _Allocator> 464 1.1 mrg inline const_buffer 465 1.1 mrg buffer(const vector<_Tp, _Allocator>& __data, size_t __n) noexcept 466 1.1 mrg { return buffer(net::buffer(__data), __n * sizeof(_Tp)); } 467 1.1 mrg 468 1.1 mrg template<typename _CharT, typename _Traits, typename _Allocator> 469 1.1 mrg inline mutable_buffer 470 1.1 mrg buffer(basic_string<_CharT, _Traits, _Allocator>& __data, 471 1.1 mrg size_t __n) noexcept 472 1.1 mrg { return buffer(net::buffer(__data), __n * sizeof(_CharT)); } 473 1.1 mrg 474 1.1 mrg template<typename _CharT, typename _Traits, typename _Allocator> 475 1.1 mrg inline const_buffer 476 1.1 mrg buffer(const basic_string<_CharT, _Traits, _Allocator>& __data, 477 1.1 mrg size_t __n) noexcept 478 1.1 mrg { return buffer(net::buffer(__data), __n * sizeof(_CharT)); } 479 1.1 mrg 480 1.1 mrg template<typename _CharT, typename _Traits> 481 1.1 mrg inline const_buffer 482 1.1 mrg buffer(basic_string_view<_CharT, _Traits> __data, size_t __n) noexcept 483 1.1 mrg { return buffer(net::buffer(__data), __n * sizeof(_CharT)); } 484 1.1 mrg 485 1.1 mrg 486 1.1 mrg template<typename _Sequence> 487 1.1 mrg class __dynamic_buffer_base 488 1.1 mrg { 489 1.1 mrg public: 490 1.1 mrg // types: 491 1.1.1.3 mrg using const_buffers_type = const_buffer; 492 1.1.1.3 mrg using mutable_buffers_type = mutable_buffer; 493 1.1 mrg 494 1.1 mrg // constructors: 495 1.1 mrg explicit 496 1.1 mrg __dynamic_buffer_base(_Sequence& __seq) noexcept 497 1.1 mrg : _M_seq(__seq), _M_size(__seq.size()), _M_max_size(__seq.max_size()) 498 1.1 mrg { } 499 1.1 mrg 500 1.1 mrg __dynamic_buffer_base(_Sequence& __seq, size_t __maximum_size) noexcept 501 1.1 mrg : _M_seq(__seq), _M_size(__seq.size()), _M_max_size(__maximum_size) 502 1.1 mrg { __glibcxx_assert(__seq.size() <= __maximum_size); } 503 1.1 mrg 504 1.1 mrg __dynamic_buffer_base(__dynamic_buffer_base&&) = default; 505 1.1 mrg 506 1.1 mrg // members: 507 1.1 mrg size_t size() const noexcept { return _M_size; } 508 1.1 mrg size_t max_size() const noexcept { return _M_max_size; } 509 1.1 mrg size_t capacity() const noexcept { return _M_seq.capacity(); } 510 1.1 mrg 511 1.1 mrg const_buffers_type 512 1.1 mrg data() const noexcept 513 1.1 mrg { return net::buffer(_M_seq, _M_size); } 514 1.1 mrg 515 1.1 mrg mutable_buffers_type 516 1.1 mrg prepare(size_t __n) 517 1.1 mrg { 518 1.1 mrg if ((_M_size + __n) > _M_max_size) 519 1.1 mrg __throw_length_error("dynamic_vector_buffer::prepare"); 520 1.1 mrg 521 1.1 mrg _M_seq.resize(_M_size + __n); 522 1.1 mrg return buffer(net::buffer(_M_seq) + _M_size, __n); 523 1.1 mrg } 524 1.1 mrg 525 1.1 mrg void 526 1.1 mrg commit(size_t __n) 527 1.1 mrg { 528 1.1 mrg _M_size += std::min(__n, _M_seq.size() - _M_size); 529 1.1 mrg _M_seq.resize(_M_size); 530 1.1 mrg } 531 1.1 mrg 532 1.1 mrg void 533 1.1 mrg consume(size_t __n) 534 1.1 mrg { 535 1.1 mrg size_t __m = std::min(__n, _M_size); 536 1.1 mrg _M_seq.erase(_M_seq.begin(), _M_seq.begin() + __m); 537 1.1 mrg _M_size -= __m; 538 1.1 mrg } 539 1.1 mrg 540 1.1 mrg private: 541 1.1 mrg _Sequence& _M_seq; 542 1.1 mrg size_t _M_size; 543 1.1 mrg const size_t _M_max_size; 544 1.1 mrg }; 545 1.1 mrg 546 1.1 mrg template<typename _Tp, typename _Allocator> 547 1.1 mrg class dynamic_vector_buffer 548 1.1 mrg : public __dynamic_buffer_base<vector<_Tp, _Allocator>> 549 1.1 mrg { 550 1.1 mrg public: 551 1.1 mrg using __dynamic_buffer_base<vector<_Tp, _Allocator>>::__dynamic_buffer_base; 552 1.1 mrg }; 553 1.1 mrg 554 1.1 mrg template<typename _CharT, typename _Traits, typename _Allocator> 555 1.1 mrg class dynamic_string_buffer 556 1.1 mrg : public __dynamic_buffer_base<basic_string<_CharT, _Traits, _Allocator>> 557 1.1 mrg { 558 1.1 mrg public: 559 1.1 mrg using __dynamic_buffer_base<basic_string<_CharT, _Traits, _Allocator>>:: 560 1.1 mrg __dynamic_buffer_base; 561 1.1 mrg }; 562 1.1 mrg 563 1.1 mrg // dynamic buffer creation: 564 1.1 mrg 565 1.1 mrg template<typename _Tp, typename _Allocator> 566 1.1 mrg inline dynamic_vector_buffer<_Tp, _Allocator> 567 1.1 mrg dynamic_buffer(vector<_Tp, _Allocator>& __vec) noexcept 568 1.1 mrg { return dynamic_vector_buffer<_Tp, _Allocator>{__vec}; } 569 1.1 mrg 570 1.1 mrg template<typename _Tp, typename _Allocator> 571 1.1 mrg inline dynamic_vector_buffer<_Tp, _Allocator> 572 1.1 mrg dynamic_buffer(vector<_Tp, _Allocator>& __vec, size_t __n) noexcept 573 1.1 mrg { return {__vec, __n}; } 574 1.1 mrg 575 1.1 mrg template<typename _CharT, typename _Traits, typename _Allocator> 576 1.1 mrg inline dynamic_string_buffer<_CharT, _Traits, _Allocator> 577 1.1 mrg dynamic_buffer(basic_string<_CharT, _Traits, _Allocator>& __str) noexcept 578 1.1 mrg { return dynamic_string_buffer<_CharT, _Traits, _Allocator>{__str}; } 579 1.1 mrg 580 1.1 mrg template<typename _CharT, typename _Traits, typename _Allocator> 581 1.1 mrg inline dynamic_string_buffer<_CharT, _Traits, _Allocator> 582 1.1 mrg dynamic_buffer(basic_string<_CharT, _Traits, _Allocator>& __str, 583 1.1 mrg size_t __n) noexcept 584 1.1 mrg { return {__str, __n}; } 585 1.1 mrg 586 1.1 mrg class transfer_all 587 1.1 mrg { 588 1.1 mrg public: 589 1.1 mrg size_t operator()(const error_code& __ec, size_t) const 590 1.1 mrg { return !__ec ? 1500 : 0; } 591 1.1 mrg }; 592 1.1 mrg 593 1.1 mrg class transfer_at_least 594 1.1 mrg { 595 1.1 mrg public: 596 1.1 mrg explicit transfer_at_least(size_t __m) : _M_minimum(__m) { } 597 1.1 mrg 598 1.1 mrg size_t operator()(const error_code& __ec, size_t __n) const 599 1.1 mrg { return !__ec && __n < _M_minimum ? _M_minimum - __n : 0; } 600 1.1 mrg 601 1.1 mrg private: 602 1.1 mrg size_t _M_minimum; 603 1.1 mrg }; 604 1.1 mrg 605 1.1 mrg class transfer_exactly 606 1.1 mrg { 607 1.1 mrg public: 608 1.1 mrg explicit transfer_exactly(size_t __e) : _M_exact(__e) { } 609 1.1 mrg 610 1.1 mrg size_t operator()(const error_code& __ec, size_t __n) const 611 1.1 mrg { 612 1.1 mrg size_t _Nm = -1; 613 1.1 mrg return !__ec && __n < _M_exact ? std::min(_M_exact - __n, _Nm) : 0; 614 1.1 mrg } 615 1.1 mrg 616 1.1 mrg private: 617 1.1 mrg size_t _M_exact; 618 1.1 mrg }; 619 1.1 mrg 620 1.1 mrg /** @brief synchronous read operations 621 1.1 mrg * @{ 622 1.1 mrg */ 623 1.1 mrg 624 1.1 mrg template<typename _SyncReadStream, typename _MutableBufferSequence, 625 1.1 mrg typename _CompletionCondition> 626 1.1 mrg enable_if_t<is_mutable_buffer_sequence<_MutableBufferSequence>::value, 627 1.1 mrg size_t> 628 1.1 mrg read(_SyncReadStream& __stream, const _MutableBufferSequence& __buffers, 629 1.1 mrg _CompletionCondition __completion_condition, error_code& __ec) 630 1.1 mrg { 631 1.1 mrg __ec.clear(); 632 1.1 mrg auto __i = net::buffer_sequence_begin(__buffers); 633 1.1 mrg auto __end = net::buffer_sequence_end(__buffers); 634 1.1 mrg mutable_buffer __to; 635 1.1 mrg size_t __total = 0; 636 1.1 mrg size_t __n; 637 1.1 mrg while ((__n = __completion_condition(__ec, __total)) 638 1.1 mrg && (__i != __end || __to.size())) 639 1.1 mrg { 640 1.1 mrg if (__to.size() == 0) 641 1.1 mrg __to = mutable_buffer(*__i++); 642 1.1 mrg __n = __stream.read_some(buffer(__to, __n), __ec); 643 1.1 mrg __to = __to + __n; 644 1.1 mrg __total += __n; 645 1.1 mrg } 646 1.1 mrg return __total; 647 1.1 mrg } 648 1.1 mrg 649 1.1 mrg template<typename _SyncReadStream, typename _MutableBufferSequence> 650 1.1 mrg inline 651 1.1 mrg enable_if_t<is_mutable_buffer_sequence<_MutableBufferSequence>::value, 652 1.1 mrg size_t> 653 1.1 mrg read(_SyncReadStream& __stream, const _MutableBufferSequence& __buffers) 654 1.1 mrg { 655 1.1 mrg error_code __ec; 656 1.1 mrg return net::read(__stream, __buffers, transfer_all{}, __ec); 657 1.1 mrg } 658 1.1 mrg 659 1.1 mrg template<typename _SyncReadStream, typename _MutableBufferSequence> 660 1.1 mrg inline 661 1.1 mrg enable_if_t<is_mutable_buffer_sequence<_MutableBufferSequence>::value, 662 1.1 mrg size_t> 663 1.1 mrg read(_SyncReadStream& __stream, const _MutableBufferSequence& __buffers, 664 1.1 mrg error_code& __ec) 665 1.1 mrg { return net::read(__stream, __buffers, transfer_all{}, __ec); } 666 1.1 mrg 667 1.1 mrg template<typename _SyncReadStream, typename _MutableBufferSequence, 668 1.1 mrg typename _CompletionCondition> 669 1.1 mrg inline 670 1.1 mrg enable_if_t<is_mutable_buffer_sequence<_MutableBufferSequence>::value, 671 1.1 mrg size_t> 672 1.1 mrg read(_SyncReadStream& __stream, const _MutableBufferSequence& __buffers, 673 1.1 mrg _CompletionCondition __completion_condition) 674 1.1 mrg { 675 1.1 mrg error_code __ec; 676 1.1 mrg return net::read(__stream, __buffers, __completion_condition, __ec); 677 1.1 mrg } 678 1.1 mrg 679 1.1 mrg 680 1.1 mrg template<typename _SyncReadStream, typename _DynamicBuffer, 681 1.1 mrg typename _CompletionCondition> 682 1.1 mrg enable_if_t<is_dynamic_buffer<decay_t<_DynamicBuffer>>::value, size_t> 683 1.1 mrg read(_SyncReadStream& __stream, _DynamicBuffer&& __b, 684 1.1 mrg _CompletionCondition __completion_condition, error_code& __ec) 685 1.1 mrg { 686 1.1 mrg const size_t __limit = 64; 687 1.1 mrg __ec.clear(); 688 1.1 mrg size_t __cap = std::max(__b.capacity() - __b.size(), __limit); 689 1.1 mrg size_t __total = 0; 690 1.1 mrg size_t __n; 691 1.1 mrg while ((__n = __completion_condition(__ec, __total)) 692 1.1 mrg && __b.size() != __b.max_size()) 693 1.1 mrg { 694 1.1 mrg __n = std::min(__n, __b.max_size() - __b.size()); 695 1.1 mrg size_t __cap = std::max(__b.capacity() - __b.size(), __limit); 696 1.1 mrg mutable_buffer __to = __b.prepare(std::min(__cap, __n)); 697 1.1 mrg __n = __stream.read_some(__to, __ec); 698 1.1 mrg __to = __to + __n; 699 1.1 mrg __total += __n; 700 1.1 mrg __b.commit(__n); 701 1.1 mrg } 702 1.1 mrg return __total; 703 1.1 mrg } 704 1.1 mrg 705 1.1 mrg template<typename _SyncReadStream, typename _DynamicBuffer> 706 1.1 mrg inline enable_if_t<is_dynamic_buffer<_DynamicBuffer>::value, size_t> 707 1.1 mrg read(_SyncReadStream& __stream, _DynamicBuffer&& __b) 708 1.1 mrg { 709 1.1 mrg error_code __ec; 710 1.1 mrg return net::read(__stream, __b, transfer_all{}, __ec); 711 1.1 mrg } 712 1.1 mrg 713 1.1 mrg template<typename _SyncReadStream, typename _DynamicBuffer> 714 1.1 mrg inline enable_if_t<is_dynamic_buffer<_DynamicBuffer>::value, size_t> 715 1.1 mrg read(_SyncReadStream& __stream, _DynamicBuffer&& __b, error_code& __ec) 716 1.1 mrg { 717 1.1 mrg return net::read(__stream, __b, transfer_all{}, __ec); 718 1.1 mrg } 719 1.1 mrg 720 1.1 mrg template<typename _SyncReadStream, typename _DynamicBuffer, 721 1.1 mrg typename _CompletionCondition> 722 1.1 mrg inline enable_if_t<is_dynamic_buffer<_DynamicBuffer>::value, size_t> 723 1.1 mrg read(_SyncReadStream& __stream, _DynamicBuffer&& __b, 724 1.1 mrg _CompletionCondition __completion_condition) 725 1.1 mrg { 726 1.1 mrg error_code __ec; 727 1.1 mrg return net::read(__stream, __b, __completion_condition, __ec); 728 1.1 mrg } 729 1.1 mrg 730 1.1.1.2 mrg /// @} 731 1.1 mrg 732 1.1 mrg /** @brief asynchronous read operations 733 1.1 mrg * @{ 734 1.1 mrg */ 735 1.1 mrg 736 1.1 mrg template<typename _AsyncReadStream, typename _MutableBufferSequence, 737 1.1 mrg typename _CompletionCondition, typename _CompletionToken> 738 1.1 mrg __deduced_t<_CompletionToken, void(error_code, size_t)> 739 1.1 mrg async_read(_AsyncReadStream& __stream, 740 1.1 mrg const _MutableBufferSequence& __buffers, 741 1.1 mrg _CompletionCondition __completion_condition, 742 1.1 mrg _CompletionToken&& __token) 743 1.1 mrg { 744 1.1 mrg error_code __ec; 745 1.1 mrg } 746 1.1 mrg 747 1.1 mrg template<typename _AsyncReadStream, typename _MutableBufferSequence, 748 1.1 mrg typename _CompletionToken> 749 1.1 mrg inline __deduced_t<_CompletionToken, void(error_code, size_t)> 750 1.1 mrg async_read(_AsyncReadStream& __stream, 751 1.1 mrg const _MutableBufferSequence& __buffers, 752 1.1 mrg _CompletionToken&& __token) 753 1.1 mrg { 754 1.1 mrg return net::async_read(__stream, __buffers, transfer_all{}, 755 1.1 mrg std::forward<_CompletionToken>(__token)); 756 1.1 mrg } 757 1.1 mrg 758 1.1 mrg template<typename _AsyncReadStream, typename _DynamicBuffer, 759 1.1 mrg typename _CompletionCondition, typename _CompletionToken> 760 1.1 mrg __deduced_t<_CompletionToken, void(error_code, size_t)> 761 1.1 mrg async_read(_AsyncReadStream& __stream, _DynamicBuffer&& __b, 762 1.1 mrg _CompletionCondition __completion_condition, 763 1.1 mrg _CompletionToken&& __token) 764 1.1 mrg { 765 1.1 mrg error_code __ec; 766 1.1 mrg } 767 1.1 mrg 768 1.1 mrg template<typename _AsyncReadStream, typename _DynamicBuffer, 769 1.1 mrg typename _CompletionToken> 770 1.1 mrg inline __deduced_t<_CompletionToken, void(error_code, size_t)> 771 1.1 mrg async_read(_AsyncReadStream& __stream, _DynamicBuffer&& __b, 772 1.1 mrg _CompletionToken&& __token) 773 1.1 mrg { 774 1.1 mrg return net::async_read(__stream, __b, transfer_all{}, 775 1.1 mrg std::forward<_CompletionToken>(__token)); 776 1.1 mrg } 777 1.1 mrg 778 1.1.1.2 mrg /// @} 779 1.1 mrg 780 1.1 mrg #if 0 781 1.1 mrg /** @brief synchronous write operations: 782 1.1 mrg * @{ 783 1.1 mrg */ 784 1.1 mrg 785 1.1 mrg template<typename _SyncWriteStream, typename _ConstBufferSequence> 786 1.1 mrg size_t write(_SyncWriteStream& __stream, 787 1.1 mrg const _ConstBufferSequence& __buffers); 788 1.1 mrg template<typename _SyncWriteStream, typename _ConstBufferSequence> 789 1.1 mrg size_t write(_SyncWriteStream& __stream, 790 1.1 mrg const _ConstBufferSequence& __buffers, error_code& __ec); 791 1.1 mrg template<typename _SyncWriteStream, typename _ConstBufferSequence, 792 1.1 mrg typename _CompletionCondition> 793 1.1 mrg size_t write(_SyncWriteStream& __stream, 794 1.1 mrg const _ConstBufferSequence& __buffers, 795 1.1 mrg _CompletionCondition __completion_condition); 796 1.1 mrg template<typename _SyncWriteStream, typename _ConstBufferSequence, 797 1.1 mrg typename _CompletionCondition> 798 1.1 mrg size_t write(_SyncWriteStream& __stream, 799 1.1 mrg const _ConstBufferSequence& __buffers, 800 1.1 mrg _CompletionCondition __completion_condition, 801 1.1 mrg error_code& __ec); 802 1.1 mrg 803 1.1 mrg template<typename _SyncWriteStream, typename _DynamicBuffer> 804 1.1 mrg size_t write(_SyncWriteStream& __stream, _DynamicBuffer&& __b); 805 1.1 mrg template<typename _SyncWriteStream, typename _DynamicBuffer> 806 1.1 mrg size_t write(_SyncWriteStream& __stream, _DynamicBuffer&& __b, error_code& __ec); 807 1.1 mrg template<typename _SyncWriteStream, typename _DynamicBuffer, typename _CompletionCondition> 808 1.1 mrg size_t write(_SyncWriteStream& __stream, _DynamicBuffer&& __b, 809 1.1 mrg _CompletionCondition __completion_condition); 810 1.1 mrg template<typename _SyncWriteStream, typename _DynamicBuffer, typename _CompletionCondition> 811 1.1 mrg size_t write(_SyncWriteStream& __stream, _DynamicBuffer&& __b, 812 1.1 mrg _CompletionCondition __completion_condition, error_code& __ec); 813 1.1 mrg 814 1.1.1.2 mrg /// @} 815 1.1 mrg 816 1.1 mrg /** @brief asynchronous write operations 817 1.1 mrg * @{ 818 1.1 mrg */ 819 1.1 mrg 820 1.1 mrg template<typename _AsyncWriteStream, typename _ConstBufferSequence, 821 1.1 mrg typename _CompletionToken> 822 1.1 mrg DEDUCED async_write(_AsyncWriteStream& __stream, 823 1.1 mrg const _ConstBufferSequence& __buffers, 824 1.1 mrg _CompletionToken&& __token); 825 1.1 mrg template<typename _AsyncWriteStream, typename _ConstBufferSequence, 826 1.1 mrg typename _CompletionCondition, typename _CompletionToken> 827 1.1 mrg DEDUCED async_write(_AsyncWriteStream& __stream, 828 1.1 mrg const _ConstBufferSequence& __buffers, 829 1.1 mrg _CompletionCondition __completion_condition, 830 1.1 mrg _CompletionToken&& __token); 831 1.1 mrg 832 1.1 mrg template<typename _AsyncWriteStream, typename _DynamicBuffer, typename _CompletionToken> 833 1.1 mrg DEDUCED async_write(_AsyncWriteStream& __stream, 834 1.1 mrg _DynamicBuffer&& __b, _CompletionToken&& __token); 835 1.1 mrg template<typename _AsyncWriteStream, typename _DynamicBuffer, 836 1.1 mrg typename _CompletionCondition, typename _CompletionToken> 837 1.1 mrg DEDUCED async_write(_AsyncWriteStream& __stream, 838 1.1 mrg _DynamicBuffer&& __b, 839 1.1 mrg _CompletionCondition __completion_condition, 840 1.1 mrg _CompletionToken&& __token); 841 1.1 mrg 842 1.1.1.2 mrg /// @} 843 1.1 mrg 844 1.1 mrg /** @brief synchronous delimited read operations 845 1.1 mrg * @{ 846 1.1 mrg */ 847 1.1 mrg 848 1.1 mrg template<typename _SyncReadStream, typename _DynamicBuffer> 849 1.1 mrg size_t read_until(_SyncReadStream& __s, _DynamicBuffer&& __b, char __delim); 850 1.1 mrg template<typename _SyncReadStream, typename _DynamicBuffer> 851 1.1 mrg size_t read_until(_SyncReadStream& __s, _DynamicBuffer&& __b, 852 1.1 mrg char __delim, error_code& __ec); 853 1.1 mrg template<typename _SyncReadStream, typename _DynamicBuffer> 854 1.1 mrg size_t read_until(_SyncReadStream& __s, _DynamicBuffer&& __b, string_view __delim); 855 1.1 mrg template<typename _SyncReadStream, typename _DynamicBuffer> 856 1.1 mrg size_t read_until(_SyncReadStream& __s, _DynamicBuffer&& __b, 857 1.1 mrg string_view __delim, error_code& __ec); 858 1.1 mrg 859 1.1.1.2 mrg /// @} 860 1.1 mrg 861 1.1 mrg /** @brief asynchronous delimited read operations 862 1.1 mrg * @{ 863 1.1 mrg */ 864 1.1 mrg 865 1.1 mrg template<typename _AsyncReadStream, typename _DynamicBuffer, typename _CompletionToken> 866 1.1 mrg DEDUCED async_read_until(_AsyncReadStream& __s, 867 1.1 mrg _DynamicBuffer&& __b, char __delim, 868 1.1 mrg _CompletionToken&& __token); 869 1.1 mrg template<typename _AsyncReadStream, typename _DynamicBuffer, typename _CompletionToken> 870 1.1 mrg DEDUCED async_read_until(_AsyncReadStream& __s, 871 1.1 mrg _DynamicBuffer&& __b, string_view __delim, 872 1.1 mrg _CompletionToken&& __token); 873 1.1 mrg 874 1.1.1.2 mrg /// @} 875 1.1 mrg 876 1.1 mrg #endif 877 1.1 mrg /// @} 878 1.1 mrg 879 1.1 mrg } // namespace v1 880 1.1 mrg } // namespace net 881 1.1 mrg } // namespace experimental 882 1.1 mrg 883 1.1 mrg template<> 884 1.1 mrg struct is_error_code_enum<experimental::net::v1::stream_errc> 885 1.1 mrg : public true_type {}; 886 1.1 mrg 887 1.1 mrg _GLIBCXX_END_NAMESPACE_VERSION 888 1.1 mrg } // namespace std 889 1.1 mrg 890 1.1 mrg #endif // C++14 891 1.1 mrg 892 1.1 mrg #endif // _GLIBCXX_EXPERIMENTAL_BUFFER 893