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