]>
Commit | Line | Data |
---|---|---|
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 | ||
47 | namespace std _GLIBCXX_VISIBILITY(default) | |
48 | { | |
a70a4be9 | 49 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
e5989e71 JW |
50 | namespace experimental |
51 | { | |
52 | namespace net | |
53 | { | |
54 | inline 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 |