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