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