]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/include/experimental/buffer
1641eafd7ad97150c66f2904206cd79b729e5547
[thirdparty/gcc.git] / libstdc++-v3 / include / 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