]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/asio/buffer.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / asio / buffer.hpp
CommitLineData
b32b8144
FG
1//
2// buffer.hpp
3// ~~~~~~~~~~
4//
1e59de90 5// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
b32b8144
FG
6//
7// Distributed under the Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9//
10
11#ifndef BOOST_ASIO_BUFFER_HPP
12#define BOOST_ASIO_BUFFER_HPP
13
14#if defined(_MSC_VER) && (_MSC_VER >= 1200)
15# pragma once
16#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17
18#include <boost/asio/detail/config.hpp>
19#include <cstddef>
20#include <cstring>
21#include <limits>
22#include <stdexcept>
23#include <string>
24#include <vector>
25#include <boost/asio/detail/array_fwd.hpp>
92f5a8d4 26#include <boost/asio/detail/memory.hpp>
b32b8144
FG
27#include <boost/asio/detail/string_view.hpp>
28#include <boost/asio/detail/throw_exception.hpp>
29#include <boost/asio/detail/type_traits.hpp>
30
31#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1700)
32# if defined(_HAS_ITERATOR_DEBUGGING) && (_HAS_ITERATOR_DEBUGGING != 0)
33# if !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING)
34# define BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
35# endif // !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING)
36# endif // defined(_HAS_ITERATOR_DEBUGGING)
37#endif // defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1700)
38
39#if defined(__GNUC__)
40# if defined(_GLIBCXX_DEBUG)
41# if !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING)
42# define BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
43# endif // !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING)
44# endif // defined(_GLIBCXX_DEBUG)
45#endif // defined(__GNUC__)
46
47#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
48# include <boost/asio/detail/functional.hpp>
49#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
50
51#if defined(BOOST_ASIO_HAS_BOOST_WORKAROUND)
52# include <boost/detail/workaround.hpp>
20effc67
TL
53# if !defined(__clang__)
54# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
55# define BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND
56# endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
57# elif BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
b32b8144 58# define BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND
20effc67 59# endif // BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
b32b8144
FG
60#endif // defined(BOOST_ASIO_HAS_BOOST_WORKAROUND)
61
62#if defined(BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)
63# include <boost/asio/detail/type_traits.hpp>
64#endif // defined(BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)
65
66#include <boost/asio/detail/push_options.hpp>
67
68namespace boost {
69namespace asio {
70
71class mutable_buffer;
72class const_buffer;
73
74/// Holds a buffer that can be modified.
75/**
76 * The mutable_buffer class provides a safe representation of a buffer that can
77 * be modified. It does not own the underlying data, and so is cheap to copy or
78 * assign.
79 *
80 * @par Accessing Buffer Contents
81 *
82 * The contents of a buffer may be accessed using the @c data() and @c size()
83 * member functions:
84 *
85 * @code boost::asio::mutable_buffer b1 = ...;
86 * std::size_t s1 = b1.size();
87 * unsigned char* p1 = static_cast<unsigned char*>(b1.data());
88 * @endcode
89 *
90 * The @c data() member function permits violations of type safety, so uses of
91 * it in application code should be carefully considered.
92 */
93class mutable_buffer
94{
95public:
96 /// Construct an empty buffer.
97 mutable_buffer() BOOST_ASIO_NOEXCEPT
98 : data_(0),
99 size_(0)
100 {
101 }
102
103 /// Construct a buffer to represent a given memory range.
104 mutable_buffer(void* data, std::size_t size) BOOST_ASIO_NOEXCEPT
105 : data_(data),
106 size_(size)
107 {
108 }
109
110#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
111 mutable_buffer(void* data, std::size_t size,
112 boost::asio::detail::function<void()> debug_check)
113 : data_(data),
114 size_(size),
115 debug_check_(debug_check)
116 {
117 }
118
119 const boost::asio::detail::function<void()>& get_debug_check() const
120 {
121 return debug_check_;
122 }
123#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
124
125 /// Get a pointer to the beginning of the memory range.
126 void* data() const BOOST_ASIO_NOEXCEPT
127 {
128#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
129 if (size_ && debug_check_)
130 debug_check_();
131#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
132 return data_;
133 }
134
135 /// Get the size of the memory range.
136 std::size_t size() const BOOST_ASIO_NOEXCEPT
137 {
138 return size_;
139 }
140
141 /// Move the start of the buffer by the specified number of bytes.
142 mutable_buffer& operator+=(std::size_t n) BOOST_ASIO_NOEXCEPT
143 {
144 std::size_t offset = n < size_ ? n : size_;
145 data_ = static_cast<char*>(data_) + offset;
146 size_ -= offset;
147 return *this;
148 }
149
150private:
151 void* data_;
152 std::size_t size_;
153
154#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
155 boost::asio::detail::function<void()> debug_check_;
156#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
157};
158
159#if !defined(BOOST_ASIO_NO_DEPRECATED)
160
161/// (Deprecated: Use mutable_buffer.) Adapts a single modifiable buffer so that
162/// it meets the requirements of the MutableBufferSequence concept.
163class mutable_buffers_1
164 : public mutable_buffer
165{
166public:
167 /// The type for each element in the list of buffers.
168 typedef mutable_buffer value_type;
169
170 /// A random-access iterator type that may be used to read elements.
171 typedef const mutable_buffer* const_iterator;
172
173 /// Construct to represent a given memory range.
174 mutable_buffers_1(void* data, std::size_t size) BOOST_ASIO_NOEXCEPT
175 : mutable_buffer(data, size)
176 {
177 }
178
179#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
180 mutable_buffers_1(void* data, std::size_t size,
181 boost::asio::detail::function<void()> debug_check)
182 : mutable_buffer(data, size, debug_check)
183 {
184 }
185#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
186
187 /// Construct to represent a single modifiable buffer.
188 explicit mutable_buffers_1(const mutable_buffer& b) BOOST_ASIO_NOEXCEPT
189 : mutable_buffer(b)
190 {
191 }
192
193 /// Get a random-access iterator to the first element.
194 const_iterator begin() const BOOST_ASIO_NOEXCEPT
195 {
196 return this;
197 }
198
199 /// Get a random-access iterator for one past the last element.
200 const_iterator end() const BOOST_ASIO_NOEXCEPT
201 {
202 return begin() + 1;
203 }
204};
205
206#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
207
208/// Holds a buffer that cannot be modified.
209/**
210 * The const_buffer class provides a safe representation of a buffer that cannot
211 * be modified. It does not own the underlying data, and so is cheap to copy or
212 * assign.
213 *
214 * @par Accessing Buffer Contents
215 *
216 * The contents of a buffer may be accessed using the @c data() and @c size()
217 * member functions:
218 *
219 * @code boost::asio::const_buffer b1 = ...;
220 * std::size_t s1 = b1.size();
221 * const unsigned char* p1 = static_cast<const unsigned char*>(b1.data());
222 * @endcode
223 *
224 * The @c data() member function permits violations of type safety, so uses of
225 * it in application code should be carefully considered.
226 */
227class const_buffer
228{
229public:
230 /// Construct an empty buffer.
231 const_buffer() BOOST_ASIO_NOEXCEPT
232 : data_(0),
233 size_(0)
234 {
235 }
236
237 /// Construct a buffer to represent a given memory range.
238 const_buffer(const void* data, std::size_t size) BOOST_ASIO_NOEXCEPT
239 : data_(data),
240 size_(size)
241 {
242 }
243
244 /// Construct a non-modifiable buffer from a modifiable one.
245 const_buffer(const mutable_buffer& b) BOOST_ASIO_NOEXCEPT
246 : data_(b.data()),
247 size_(b.size())
248#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
249 , debug_check_(b.get_debug_check())
250#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
251 {
252 }
253
254#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
255 const_buffer(const void* data, std::size_t size,
256 boost::asio::detail::function<void()> debug_check)
257 : data_(data),
258 size_(size),
259 debug_check_(debug_check)
260 {
261 }
262
263 const boost::asio::detail::function<void()>& get_debug_check() const
264 {
265 return debug_check_;
266 }
267#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
268
269 /// Get a pointer to the beginning of the memory range.
270 const void* data() const BOOST_ASIO_NOEXCEPT
271 {
272#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
273 if (size_ && debug_check_)
274 debug_check_();
275#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
276 return data_;
277 }
278
279 /// Get the size of the memory range.
280 std::size_t size() const BOOST_ASIO_NOEXCEPT
281 {
282 return size_;
283 }
284
285 /// Move the start of the buffer by the specified number of bytes.
286 const_buffer& operator+=(std::size_t n) BOOST_ASIO_NOEXCEPT
287 {
288 std::size_t offset = n < size_ ? n : size_;
289 data_ = static_cast<const char*>(data_) + offset;
290 size_ -= offset;
291 return *this;
292 }
293
294private:
295 const void* data_;
296 std::size_t size_;
297
298#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
299 boost::asio::detail::function<void()> debug_check_;
300#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
301};
302
303#if !defined(BOOST_ASIO_NO_DEPRECATED)
304
305/// (Deprecated: Use const_buffer.) Adapts a single non-modifiable buffer so
306/// that it meets the requirements of the ConstBufferSequence concept.
307class const_buffers_1
308 : public const_buffer
309{
310public:
311 /// The type for each element in the list of buffers.
312 typedef const_buffer value_type;
313
314 /// A random-access iterator type that may be used to read elements.
315 typedef const const_buffer* const_iterator;
316
317 /// Construct to represent a given memory range.
318 const_buffers_1(const void* data, std::size_t size) BOOST_ASIO_NOEXCEPT
319 : const_buffer(data, size)
320 {
321 }
322
323#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
324 const_buffers_1(const void* data, std::size_t size,
325 boost::asio::detail::function<void()> debug_check)
326 : const_buffer(data, size, debug_check)
327 {
328 }
329#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
330
331 /// Construct to represent a single non-modifiable buffer.
332 explicit const_buffers_1(const const_buffer& b) BOOST_ASIO_NOEXCEPT
333 : const_buffer(b)
334 {
335 }
336
337 /// Get a random-access iterator to the first element.
338 const_iterator begin() const BOOST_ASIO_NOEXCEPT
339 {
340 return this;
341 }
342
343 /// Get a random-access iterator for one past the last element.
344 const_iterator end() const BOOST_ASIO_NOEXCEPT
345 {
346 return begin() + 1;
347 }
348};
349
350#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
351
b32b8144
FG
352/// (Deprecated: Use the socket/descriptor wait() and async_wait() member
353/// functions.) An implementation of both the ConstBufferSequence and
354/// MutableBufferSequence concepts to represent a null buffer sequence.
355class null_buffers
356{
357public:
358 /// The type for each element in the list of buffers.
359 typedef mutable_buffer value_type;
360
361 /// A random-access iterator type that may be used to read elements.
362 typedef const mutable_buffer* const_iterator;
363
364 /// Get a random-access iterator to the first element.
365 const_iterator begin() const BOOST_ASIO_NOEXCEPT
366 {
367 return &buf_;
368 }
369
370 /// Get a random-access iterator for one past the last element.
371 const_iterator end() const BOOST_ASIO_NOEXCEPT
372 {
373 return &buf_;
374 }
375
376private:
377 mutable_buffer buf_;
378};
379
380/** @defgroup buffer_sequence_begin boost::asio::buffer_sequence_begin
381 *
382 * @brief The boost::asio::buffer_sequence_begin function returns an iterator
383 * pointing to the first element in a buffer sequence.
384 */
385/*@{*/
386
387/// Get an iterator to the first element in a buffer sequence.
92f5a8d4
TL
388template <typename MutableBuffer>
389inline const mutable_buffer* buffer_sequence_begin(const MutableBuffer& b,
1e59de90 390 typename constraint<
92f5a8d4 391 is_convertible<const MutableBuffer*, const mutable_buffer*>::value
1e59de90 392 >::type = 0) BOOST_ASIO_NOEXCEPT
b32b8144 393{
92f5a8d4 394 return static_cast<const mutable_buffer*>(detail::addressof(b));
b32b8144
FG
395}
396
397/// Get an iterator to the first element in a buffer sequence.
92f5a8d4
TL
398template <typename ConstBuffer>
399inline const const_buffer* buffer_sequence_begin(const ConstBuffer& b,
1e59de90 400 typename constraint<
92f5a8d4 401 is_convertible<const ConstBuffer*, const const_buffer*>::value
1e59de90 402 >::type = 0) BOOST_ASIO_NOEXCEPT
b32b8144 403{
92f5a8d4 404 return static_cast<const const_buffer*>(detail::addressof(b));
b32b8144
FG
405}
406
407#if defined(BOOST_ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)
408
409/// Get an iterator to the first element in a buffer sequence.
410template <typename C>
92f5a8d4 411inline auto buffer_sequence_begin(C& c,
1e59de90 412 typename constraint<
92f5a8d4
TL
413 !is_convertible<const C*, const mutable_buffer*>::value
414 && !is_convertible<const C*, const const_buffer*>::value
1e59de90 415 >::type = 0) BOOST_ASIO_NOEXCEPT -> decltype(c.begin())
b32b8144
FG
416{
417 return c.begin();
418}
419
420/// Get an iterator to the first element in a buffer sequence.
421template <typename C>
92f5a8d4 422inline auto buffer_sequence_begin(const C& c,
1e59de90 423 typename constraint<
92f5a8d4
TL
424 !is_convertible<const C*, const mutable_buffer*>::value
425 && !is_convertible<const C*, const const_buffer*>::value
1e59de90 426 >::type = 0) BOOST_ASIO_NOEXCEPT -> decltype(c.begin())
b32b8144
FG
427{
428 return c.begin();
429}
430
431#else // defined(BOOST_ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)
432
433template <typename C>
92f5a8d4 434inline typename C::iterator buffer_sequence_begin(C& c,
1e59de90 435 typename constraint<
92f5a8d4
TL
436 !is_convertible<const C*, const mutable_buffer*>::value
437 && !is_convertible<const C*, const const_buffer*>::value
1e59de90 438 >::type = 0) BOOST_ASIO_NOEXCEPT
b32b8144
FG
439{
440 return c.begin();
441}
442
443template <typename C>
92f5a8d4 444inline typename C::const_iterator buffer_sequence_begin(const C& c,
1e59de90 445 typename constraint<
92f5a8d4
TL
446 !is_convertible<const C*, const mutable_buffer*>::value
447 && !is_convertible<const C*, const const_buffer*>::value
1e59de90 448 >::type = 0) BOOST_ASIO_NOEXCEPT
b32b8144
FG
449{
450 return c.begin();
451}
452
453#endif // defined(BOOST_ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)
454
455/*@}*/
456
457/** @defgroup buffer_sequence_end boost::asio::buffer_sequence_end
458 *
459 * @brief The boost::asio::buffer_sequence_end function returns an iterator
460 * pointing to one past the end element in a buffer sequence.
461 */
462/*@{*/
463
464/// Get an iterator to one past the end element in a buffer sequence.
92f5a8d4
TL
465template <typename MutableBuffer>
466inline const mutable_buffer* buffer_sequence_end(const MutableBuffer& b,
1e59de90 467 typename constraint<
92f5a8d4 468 is_convertible<const MutableBuffer*, const mutable_buffer*>::value
1e59de90 469 >::type = 0) BOOST_ASIO_NOEXCEPT
b32b8144 470{
92f5a8d4 471 return static_cast<const mutable_buffer*>(detail::addressof(b)) + 1;
b32b8144
FG
472}
473
474/// Get an iterator to one past the end element in a buffer sequence.
92f5a8d4
TL
475template <typename ConstBuffer>
476inline const const_buffer* buffer_sequence_end(const ConstBuffer& b,
1e59de90 477 typename constraint<
92f5a8d4 478 is_convertible<const ConstBuffer*, const const_buffer*>::value
1e59de90 479 >::type = 0) BOOST_ASIO_NOEXCEPT
b32b8144 480{
92f5a8d4 481 return static_cast<const const_buffer*>(detail::addressof(b)) + 1;
b32b8144
FG
482}
483
484#if defined(BOOST_ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)
485
486/// Get an iterator to one past the end element in a buffer sequence.
487template <typename C>
92f5a8d4 488inline auto buffer_sequence_end(C& c,
1e59de90 489 typename constraint<
92f5a8d4
TL
490 !is_convertible<const C*, const mutable_buffer*>::value
491 && !is_convertible<const C*, const const_buffer*>::value
1e59de90 492 >::type = 0) BOOST_ASIO_NOEXCEPT -> decltype(c.end())
b32b8144
FG
493{
494 return c.end();
495}
496
497/// Get an iterator to one past the end element in a buffer sequence.
498template <typename C>
92f5a8d4 499inline auto buffer_sequence_end(const C& c,
1e59de90 500 typename constraint<
92f5a8d4
TL
501 !is_convertible<const C*, const mutable_buffer*>::value
502 && !is_convertible<const C*, const const_buffer*>::value
1e59de90 503 >::type = 0) BOOST_ASIO_NOEXCEPT -> decltype(c.end())
b32b8144
FG
504{
505 return c.end();
506}
507
508#else // defined(BOOST_ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)
509
510template <typename C>
92f5a8d4 511inline typename C::iterator buffer_sequence_end(C& c,
1e59de90 512 typename constraint<
92f5a8d4
TL
513 !is_convertible<const C*, const mutable_buffer*>::value
514 && !is_convertible<const C*, const const_buffer*>::value
1e59de90 515 >::type = 0) BOOST_ASIO_NOEXCEPT
b32b8144
FG
516{
517 return c.end();
518}
519
520template <typename C>
92f5a8d4 521inline typename C::const_iterator buffer_sequence_end(const C& c,
1e59de90 522 typename constraint<
92f5a8d4
TL
523 !is_convertible<const C*, const mutable_buffer*>::value
524 && !is_convertible<const C*, const const_buffer*>::value
1e59de90 525 >::type = 0) BOOST_ASIO_NOEXCEPT
b32b8144
FG
526{
527 return c.end();
528}
529
530#endif // defined(BOOST_ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)
531
532/*@}*/
533
534namespace detail {
535
536// Tag types used to select appropriately optimised overloads.
537struct one_buffer {};
538struct multiple_buffers {};
539
540// Helper trait to detect single buffers.
541template <typename BufferSequence>
542struct buffer_sequence_cardinality :
543 conditional<
544 is_same<BufferSequence, mutable_buffer>::value
545#if !defined(BOOST_ASIO_NO_DEPRECATED)
546 || is_same<BufferSequence, mutable_buffers_1>::value
547 || is_same<BufferSequence, const_buffers_1>::value
548#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
549 || is_same<BufferSequence, const_buffer>::value,
550 one_buffer, multiple_buffers>::type {};
551
552template <typename Iterator>
553inline std::size_t buffer_size(one_buffer,
554 Iterator begin, Iterator) BOOST_ASIO_NOEXCEPT
555{
556 return const_buffer(*begin).size();
557}
558
559template <typename Iterator>
560inline std::size_t buffer_size(multiple_buffers,
561 Iterator begin, Iterator end) BOOST_ASIO_NOEXCEPT
562{
563 std::size_t total_buffer_size = 0;
564
565 Iterator iter = begin;
566 for (; iter != end; ++iter)
567 {
568 const_buffer b(*iter);
569 total_buffer_size += b.size();
570 }
571
572 return total_buffer_size;
573}
574
575} // namespace detail
576
577/// Get the total number of bytes in a buffer sequence.
578/**
579 * The @c buffer_size function determines the total size of all buffers in the
580 * buffer sequence, as if computed as follows:
581 *
582 * @code size_t total_size = 0;
583 * auto i = boost::asio::buffer_sequence_begin(buffers);
584 * auto end = boost::asio::buffer_sequence_end(buffers);
585 * for (; i != end; ++i)
586 * {
587 * const_buffer b(*i);
588 * total_size += b.size();
589 * }
590 * return total_size; @endcode
591 *
592 * The @c BufferSequence template parameter may meet either of the @c
593 * ConstBufferSequence or @c MutableBufferSequence type requirements.
594 */
595template <typename BufferSequence>
596inline std::size_t buffer_size(const BufferSequence& b) BOOST_ASIO_NOEXCEPT
597{
598 return detail::buffer_size(
599 detail::buffer_sequence_cardinality<BufferSequence>(),
600 boost::asio::buffer_sequence_begin(b),
601 boost::asio::buffer_sequence_end(b));
602}
603
604#if !defined(BOOST_ASIO_NO_DEPRECATED)
605
606/** @defgroup buffer_cast boost::asio::buffer_cast
607 *
608 * @brief (Deprecated: Use the @c data() member function.) The
609 * boost::asio::buffer_cast function is used to obtain a pointer to the
610 * underlying memory region associated with a buffer.
611 *
612 * @par Examples:
613 *
614 * To access the memory of a non-modifiable buffer, use:
615 * @code boost::asio::const_buffer b1 = ...;
616 * const unsigned char* p1 = boost::asio::buffer_cast<const unsigned char*>(b1);
617 * @endcode
618 *
619 * To access the memory of a modifiable buffer, use:
620 * @code boost::asio::mutable_buffer b2 = ...;
621 * unsigned char* p2 = boost::asio::buffer_cast<unsigned char*>(b2);
622 * @endcode
623 *
624 * The boost::asio::buffer_cast function permits violations of type safety, so
625 * uses of it in application code should be carefully considered.
626 */
627/*@{*/
628
629/// Cast a non-modifiable buffer to a specified pointer to POD type.
630template <typename PointerToPodType>
631inline PointerToPodType buffer_cast(const mutable_buffer& b) BOOST_ASIO_NOEXCEPT
632{
633 return static_cast<PointerToPodType>(b.data());
634}
635
636/// Cast a non-modifiable buffer to a specified pointer to POD type.
637template <typename PointerToPodType>
638inline PointerToPodType buffer_cast(const const_buffer& b) BOOST_ASIO_NOEXCEPT
639{
640 return static_cast<PointerToPodType>(b.data());
641}
642
643/*@}*/
644
645#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
646
647/// Create a new modifiable buffer that is offset from the start of another.
648/**
649 * @relates mutable_buffer
650 */
651inline mutable_buffer operator+(const mutable_buffer& b,
652 std::size_t n) BOOST_ASIO_NOEXCEPT
653{
654 std::size_t offset = n < b.size() ? n : b.size();
655 char* new_data = static_cast<char*>(b.data()) + offset;
656 std::size_t new_size = b.size() - offset;
657 return mutable_buffer(new_data, new_size
658#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
659 , b.get_debug_check()
660#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
661 );
662}
663
664/// Create a new modifiable buffer that is offset from the start of another.
665/**
666 * @relates mutable_buffer
667 */
668inline mutable_buffer operator+(std::size_t n,
669 const mutable_buffer& b) BOOST_ASIO_NOEXCEPT
670{
671 return b + n;
672}
673
674/// Create a new non-modifiable buffer that is offset from the start of another.
675/**
676 * @relates const_buffer
677 */
678inline const_buffer operator+(const const_buffer& b,
679 std::size_t n) BOOST_ASIO_NOEXCEPT
680{
681 std::size_t offset = n < b.size() ? n : b.size();
682 const char* new_data = static_cast<const char*>(b.data()) + offset;
683 std::size_t new_size = b.size() - offset;
684 return const_buffer(new_data, new_size
685#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
686 , b.get_debug_check()
687#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
688 );
689}
690
691/// Create a new non-modifiable buffer that is offset from the start of another.
692/**
693 * @relates const_buffer
694 */
695inline const_buffer operator+(std::size_t n,
696 const const_buffer& b) BOOST_ASIO_NOEXCEPT
697{
698 return b + n;
699}
700
701#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
702namespace detail {
703
704template <typename Iterator>
705class buffer_debug_check
706{
707public:
708 buffer_debug_check(Iterator iter)
709 : iter_(iter)
710 {
711 }
712
713 ~buffer_debug_check()
714 {
715#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC == 1400)
716 // MSVC 8's string iterator checking may crash in a std::string::iterator
717 // object's destructor when the iterator points to an already-destroyed
718 // std::string object, unless the iterator is cleared first.
719 iter_ = Iterator();
720#endif // defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC == 1400)
721 }
722
723 void operator()()
724 {
11fdf7f2 725 (void)*iter_;
b32b8144
FG
726 }
727
728private:
729 Iterator iter_;
730};
731
732} // namespace detail
733#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
734
735/** @defgroup buffer boost::asio::buffer
736 *
737 * @brief The boost::asio::buffer function is used to create a buffer object to
738 * represent raw memory, an array of POD elements, a vector of POD elements,
739 * or a std::string.
740 *
741 * A buffer object represents a contiguous region of memory as a 2-tuple
742 * consisting of a pointer and size in bytes. A tuple of the form <tt>{void*,
743 * size_t}</tt> specifies a mutable (modifiable) region of memory. Similarly, a
744 * tuple of the form <tt>{const void*, size_t}</tt> specifies a const
745 * (non-modifiable) region of memory. These two forms correspond to the classes
746 * mutable_buffer and const_buffer, respectively. To mirror C++'s conversion
747 * rules, a mutable_buffer is implicitly convertible to a const_buffer, and the
748 * opposite conversion is not permitted.
749 *
750 * The simplest use case involves reading or writing a single buffer of a
751 * specified size:
752 *
753 * @code sock.send(boost::asio::buffer(data, size)); @endcode
754 *
755 * In the above example, the return value of boost::asio::buffer meets the
756 * requirements of the ConstBufferSequence concept so that it may be directly
757 * passed to the socket's write function. A buffer created for modifiable
758 * memory also meets the requirements of the MutableBufferSequence concept.
759 *
760 * An individual buffer may be created from a builtin array, std::vector,
761 * std::array or boost::array of POD elements. This helps prevent buffer
762 * overruns by automatically determining the size of the buffer:
763 *
764 * @code char d1[128];
765 * size_t bytes_transferred = sock.receive(boost::asio::buffer(d1));
766 *
767 * std::vector<char> d2(128);
768 * bytes_transferred = sock.receive(boost::asio::buffer(d2));
769 *
770 * std::array<char, 128> d3;
771 * bytes_transferred = sock.receive(boost::asio::buffer(d3));
772 *
773 * boost::array<char, 128> d4;
774 * bytes_transferred = sock.receive(boost::asio::buffer(d4)); @endcode
775 *
776 * In all three cases above, the buffers created are exactly 128 bytes long.
777 * Note that a vector is @e never automatically resized when creating or using
778 * a buffer. The buffer size is determined using the vector's <tt>size()</tt>
779 * member function, and not its capacity.
780 *
781 * @par Accessing Buffer Contents
782 *
783 * The contents of a buffer may be accessed using the @c data() and @c size()
784 * member functions:
785 *
786 * @code boost::asio::mutable_buffer b1 = ...;
787 * std::size_t s1 = b1.size();
788 * unsigned char* p1 = static_cast<unsigned char*>(b1.data());
789 *
790 * boost::asio::const_buffer b2 = ...;
791 * std::size_t s2 = b2.size();
792 * const void* p2 = b2.data(); @endcode
793 *
794 * The @c data() member function permits violations of type safety, so
795 * uses of it in application code should be carefully considered.
796 *
797 * For convenience, a @ref buffer_size function is provided that works with
798 * both buffers and buffer sequences (that is, types meeting the
799 * ConstBufferSequence or MutableBufferSequence type requirements). In this
800 * case, the function returns the total size of all buffers in the sequence.
801 *
802 * @par Buffer Copying
803 *
804 * The @ref buffer_copy function may be used to copy raw bytes between
805 * individual buffers and buffer sequences.
806*
807 * In particular, when used with the @ref buffer_size function, the @ref
808 * buffer_copy function can be used to linearise a sequence of buffers. For
809 * example:
810 *
811 * @code vector<const_buffer> buffers = ...;
812 *
813 * vector<unsigned char> data(boost::asio::buffer_size(buffers));
814 * boost::asio::buffer_copy(boost::asio::buffer(data), buffers); @endcode
815 *
816 * Note that @ref buffer_copy is implemented in terms of @c memcpy, and
817 * consequently it cannot be used to copy between overlapping memory regions.
818 *
819 * @par Buffer Invalidation
820 *
821 * A buffer object does not have any ownership of the memory it refers to. It
822 * is the responsibility of the application to ensure the memory region remains
823 * valid until it is no longer required for an I/O operation. When the memory
824 * is no longer available, the buffer is said to have been invalidated.
825 *
826 * For the boost::asio::buffer overloads that accept an argument of type
827 * std::vector, the buffer objects returned are invalidated by any vector
828 * operation that also invalidates all references, pointers and iterators
829 * referring to the elements in the sequence (C++ Std, 23.2.4)
830 *
831 * For the boost::asio::buffer overloads that accept an argument of type
832 * std::basic_string, the buffer objects returned are invalidated according to
833 * the rules defined for invalidation of references, pointers and iterators
834 * referring to elements of the sequence (C++ Std, 21.3).
835 *
836 * @par Buffer Arithmetic
837 *
838 * Buffer objects may be manipulated using simple arithmetic in a safe way
839 * which helps prevent buffer overruns. Consider an array initialised as
840 * follows:
841 *
842 * @code boost::array<char, 6> a = { 'a', 'b', 'c', 'd', 'e' }; @endcode
843 *
844 * A buffer object @c b1 created using:
845 *
846 * @code b1 = boost::asio::buffer(a); @endcode
847 *
848 * represents the entire array, <tt>{ 'a', 'b', 'c', 'd', 'e' }</tt>. An
849 * optional second argument to the boost::asio::buffer function may be used to
850 * limit the size, in bytes, of the buffer:
851 *
852 * @code b2 = boost::asio::buffer(a, 3); @endcode
853 *
854 * such that @c b2 represents the data <tt>{ 'a', 'b', 'c' }</tt>. Even if the
855 * size argument exceeds the actual size of the array, the size of the buffer
856 * object created will be limited to the array size.
857 *
858 * An offset may be applied to an existing buffer to create a new one:
859 *
860 * @code b3 = b1 + 2; @endcode
861 *
862 * where @c b3 will set to represent <tt>{ 'c', 'd', 'e' }</tt>. If the offset
863 * exceeds the size of the existing buffer, the newly created buffer will be
864 * empty.
865 *
866 * Both an offset and size may be specified to create a buffer that corresponds
867 * to a specific range of bytes within an existing buffer:
868 *
869 * @code b4 = boost::asio::buffer(b1 + 1, 3); @endcode
870 *
871 * so that @c b4 will refer to the bytes <tt>{ 'b', 'c', 'd' }</tt>.
872 *
873 * @par Buffers and Scatter-Gather I/O
874 *
875 * To read or write using multiple buffers (i.e. scatter-gather I/O), multiple
876 * buffer objects may be assigned into a container that supports the
877 * MutableBufferSequence (for read) or ConstBufferSequence (for write) concepts:
878 *
879 * @code
880 * char d1[128];
881 * std::vector<char> d2(128);
882 * boost::array<char, 128> d3;
883 *
884 * boost::array<mutable_buffer, 3> bufs1 = {
885 * boost::asio::buffer(d1),
886 * boost::asio::buffer(d2),
887 * boost::asio::buffer(d3) };
888 * bytes_transferred = sock.receive(bufs1);
889 *
890 * std::vector<const_buffer> bufs2;
891 * bufs2.push_back(boost::asio::buffer(d1));
892 * bufs2.push_back(boost::asio::buffer(d2));
893 * bufs2.push_back(boost::asio::buffer(d3));
894 * bytes_transferred = sock.send(bufs2); @endcode
895 */
896/*@{*/
897
898#if defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
899# define BOOST_ASIO_MUTABLE_BUFFER mutable_buffer
900# define BOOST_ASIO_CONST_BUFFER const_buffer
901#else // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
902# define BOOST_ASIO_MUTABLE_BUFFER mutable_buffers_1
903# define BOOST_ASIO_CONST_BUFFER const_buffers_1
904#endif // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
905
906/// Create a new modifiable buffer from an existing buffer.
907/**
908 * @returns <tt>mutable_buffer(b)</tt>.
909 */
1e59de90 910BOOST_ASIO_NODISCARD inline BOOST_ASIO_MUTABLE_BUFFER buffer(
b32b8144
FG
911 const mutable_buffer& b) BOOST_ASIO_NOEXCEPT
912{
913 return BOOST_ASIO_MUTABLE_BUFFER(b);
914}
915
916/// Create a new modifiable buffer from an existing buffer.
917/**
918 * @returns A mutable_buffer value equivalent to:
919 * @code mutable_buffer(
920 * b.data(),
921 * min(b.size(), max_size_in_bytes)); @endcode
922 */
1e59de90
TL
923BOOST_ASIO_NODISCARD inline BOOST_ASIO_MUTABLE_BUFFER buffer(
924 const mutable_buffer& b,
b32b8144
FG
925 std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
926{
927 return BOOST_ASIO_MUTABLE_BUFFER(
928 mutable_buffer(b.data(),
929 b.size() < max_size_in_bytes
930 ? b.size() : max_size_in_bytes
931#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
932 , b.get_debug_check()
933#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
934 ));
935}
936
937/// Create a new non-modifiable buffer from an existing buffer.
938/**
939 * @returns <tt>const_buffer(b)</tt>.
940 */
1e59de90 941BOOST_ASIO_NODISCARD inline BOOST_ASIO_CONST_BUFFER buffer(
b32b8144
FG
942 const const_buffer& b) BOOST_ASIO_NOEXCEPT
943{
944 return BOOST_ASIO_CONST_BUFFER(b);
945}
946
947/// Create a new non-modifiable buffer from an existing buffer.
948/**
949 * @returns A const_buffer value equivalent to:
950 * @code const_buffer(
951 * b.data(),
952 * min(b.size(), max_size_in_bytes)); @endcode
953 */
1e59de90
TL
954BOOST_ASIO_NODISCARD inline BOOST_ASIO_CONST_BUFFER buffer(
955 const const_buffer& b,
b32b8144
FG
956 std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
957{
958 return BOOST_ASIO_CONST_BUFFER(b.data(),
959 b.size() < max_size_in_bytes
960 ? b.size() : max_size_in_bytes
961#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
962 , b.get_debug_check()
963#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
964 );
965}
966
967/// Create a new modifiable buffer that represents the given memory range.
968/**
969 * @returns <tt>mutable_buffer(data, size_in_bytes)</tt>.
970 */
1e59de90
TL
971BOOST_ASIO_NODISCARD inline BOOST_ASIO_MUTABLE_BUFFER buffer(
972 void* data, std::size_t size_in_bytes) BOOST_ASIO_NOEXCEPT
b32b8144
FG
973{
974 return BOOST_ASIO_MUTABLE_BUFFER(data, size_in_bytes);
975}
976
977/// Create a new non-modifiable buffer that represents the given memory range.
978/**
979 * @returns <tt>const_buffer(data, size_in_bytes)</tt>.
980 */
1e59de90
TL
981BOOST_ASIO_NODISCARD inline BOOST_ASIO_CONST_BUFFER buffer(
982 const void* data, std::size_t size_in_bytes) BOOST_ASIO_NOEXCEPT
b32b8144
FG
983{
984 return BOOST_ASIO_CONST_BUFFER(data, size_in_bytes);
985}
986
987/// Create a new modifiable buffer that represents the given POD array.
988/**
989 * @returns A mutable_buffer value equivalent to:
990 * @code mutable_buffer(
991 * static_cast<void*>(data),
992 * N * sizeof(PodType)); @endcode
993 */
994template <typename PodType, std::size_t N>
1e59de90
TL
995BOOST_ASIO_NODISCARD inline BOOST_ASIO_MUTABLE_BUFFER buffer(
996 PodType (&data)[N]) BOOST_ASIO_NOEXCEPT
b32b8144
FG
997{
998 return BOOST_ASIO_MUTABLE_BUFFER(data, N * sizeof(PodType));
999}
1000
1001/// Create a new modifiable buffer that represents the given POD array.
1002/**
1003 * @returns A mutable_buffer value equivalent to:
1004 * @code mutable_buffer(
1005 * static_cast<void*>(data),
1006 * min(N * sizeof(PodType), max_size_in_bytes)); @endcode
1007 */
1008template <typename PodType, std::size_t N>
1e59de90
TL
1009BOOST_ASIO_NODISCARD inline BOOST_ASIO_MUTABLE_BUFFER buffer(
1010 PodType (&data)[N],
b32b8144
FG
1011 std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
1012{
1013 return BOOST_ASIO_MUTABLE_BUFFER(data,
1014 N * sizeof(PodType) < max_size_in_bytes
1015 ? N * sizeof(PodType) : max_size_in_bytes);
1016}
1017
1018/// Create a new non-modifiable buffer that represents the given POD array.
1019/**
1020 * @returns A const_buffer value equivalent to:
1021 * @code const_buffer(
1022 * static_cast<const void*>(data),
1023 * N * sizeof(PodType)); @endcode
1024 */
1025template <typename PodType, std::size_t N>
1e59de90 1026BOOST_ASIO_NODISCARD inline BOOST_ASIO_CONST_BUFFER buffer(
b32b8144
FG
1027 const PodType (&data)[N]) BOOST_ASIO_NOEXCEPT
1028{
1029 return BOOST_ASIO_CONST_BUFFER(data, N * sizeof(PodType));
1030}
1031
1032/// Create a new non-modifiable buffer that represents the given POD array.
1033/**
1034 * @returns A const_buffer value equivalent to:
1035 * @code const_buffer(
1036 * static_cast<const void*>(data),
1037 * min(N * sizeof(PodType), max_size_in_bytes)); @endcode
1038 */
1039template <typename PodType, std::size_t N>
1e59de90
TL
1040BOOST_ASIO_NODISCARD inline BOOST_ASIO_CONST_BUFFER buffer(
1041 const PodType (&data)[N],
b32b8144
FG
1042 std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
1043{
1044 return BOOST_ASIO_CONST_BUFFER(data,
1045 N * sizeof(PodType) < max_size_in_bytes
1046 ? N * sizeof(PodType) : max_size_in_bytes);
1047}
1048
1049#if defined(BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)
1050
1051// Borland C++ and Sun Studio think the overloads:
1052//
1053// unspecified buffer(boost::array<PodType, N>& array ...);
1054//
1055// and
1056//
1057// unspecified buffer(boost::array<const PodType, N>& array ...);
1058//
1059// are ambiguous. This will be worked around by using a buffer_types traits
1060// class that contains typedefs for the appropriate buffer and container
1061// classes, based on whether PodType is const or non-const.
1062
1063namespace detail {
1064
1065template <bool IsConst>
1066struct buffer_types_base;
1067
1068template <>
1069struct buffer_types_base<false>
1070{
1071 typedef mutable_buffer buffer_type;
1072 typedef BOOST_ASIO_MUTABLE_BUFFER container_type;
1073};
1074
1075template <>
1076struct buffer_types_base<true>
1077{
1078 typedef const_buffer buffer_type;
1079 typedef BOOST_ASIO_CONST_BUFFER container_type;
1080};
1081
1082template <typename PodType>
1083struct buffer_types
1084 : public buffer_types_base<is_const<PodType>::value>
1085{
1086};
1087
1088} // namespace detail
1089
1090template <typename PodType, std::size_t N>
1e59de90
TL
1091BOOST_ASIO_NODISCARD inline
1092typename detail::buffer_types<PodType>::container_type
b32b8144
FG
1093buffer(boost::array<PodType, N>& data) BOOST_ASIO_NOEXCEPT
1094{
1095 typedef typename boost::asio::detail::buffer_types<PodType>::buffer_type
1096 buffer_type;
1097 typedef typename boost::asio::detail::buffer_types<PodType>::container_type
1098 container_type;
1099 return container_type(
1100 buffer_type(data.c_array(), data.size() * sizeof(PodType)));
1101}
1102
1103template <typename PodType, std::size_t N>
1e59de90
TL
1104BOOST_ASIO_NODISCARD inline
1105typename detail::buffer_types<PodType>::container_type
b32b8144
FG
1106buffer(boost::array<PodType, N>& data,
1107 std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
1108{
1109 typedef typename boost::asio::detail::buffer_types<PodType>::buffer_type
1110 buffer_type;
1111 typedef typename boost::asio::detail::buffer_types<PodType>::container_type
1112 container_type;
1113 return container_type(
1114 buffer_type(data.c_array(),
1115 data.size() * sizeof(PodType) < max_size_in_bytes
1116 ? data.size() * sizeof(PodType) : max_size_in_bytes));
1117}
1118
1119#else // defined(BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)
1120
1121/// Create a new modifiable buffer that represents the given POD array.
1122/**
1123 * @returns A mutable_buffer value equivalent to:
1124 * @code mutable_buffer(
1125 * data.data(),
1126 * data.size() * sizeof(PodType)); @endcode
1127 */
1128template <typename PodType, std::size_t N>
1e59de90 1129BOOST_ASIO_NODISCARD inline BOOST_ASIO_MUTABLE_BUFFER buffer(
b32b8144
FG
1130 boost::array<PodType, N>& data) BOOST_ASIO_NOEXCEPT
1131{
1132 return BOOST_ASIO_MUTABLE_BUFFER(
1133 data.c_array(), data.size() * sizeof(PodType));
1134}
1135
1136/// Create a new modifiable buffer that represents the given POD array.
1137/**
1138 * @returns A mutable_buffer value equivalent to:
1139 * @code mutable_buffer(
1140 * data.data(),
1141 * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
1142 */
1143template <typename PodType, std::size_t N>
1e59de90
TL
1144BOOST_ASIO_NODISCARD inline BOOST_ASIO_MUTABLE_BUFFER buffer(
1145 boost::array<PodType, N>& data,
b32b8144
FG
1146 std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
1147{
1148 return BOOST_ASIO_MUTABLE_BUFFER(data.c_array(),
1149 data.size() * sizeof(PodType) < max_size_in_bytes
1150 ? data.size() * sizeof(PodType) : max_size_in_bytes);
1151}
1152
1153/// Create a new non-modifiable buffer that represents the given POD array.
1154/**
1155 * @returns A const_buffer value equivalent to:
1156 * @code const_buffer(
1157 * data.data(),
1158 * data.size() * sizeof(PodType)); @endcode
1159 */
1160template <typename PodType, std::size_t N>
1e59de90 1161BOOST_ASIO_NODISCARD inline BOOST_ASIO_CONST_BUFFER buffer(
b32b8144
FG
1162 boost::array<const PodType, N>& data) BOOST_ASIO_NOEXCEPT
1163{
1164 return BOOST_ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));
1165}
1166
1167/// Create a new non-modifiable buffer that represents the given POD array.
1168/**
1169 * @returns A const_buffer value equivalent to:
1170 * @code const_buffer(
1171 * data.data(),
1172 * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
1173 */
1174template <typename PodType, std::size_t N>
1e59de90
TL
1175BOOST_ASIO_NODISCARD inline BOOST_ASIO_CONST_BUFFER buffer(
1176 boost::array<const PodType, N>& data,
b32b8144
FG
1177 std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
1178{
1179 return BOOST_ASIO_CONST_BUFFER(data.data(),
1180 data.size() * sizeof(PodType) < max_size_in_bytes
1181 ? data.size() * sizeof(PodType) : max_size_in_bytes);
1182}
1183
1184#endif // defined(BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)
1185
1186/// Create a new non-modifiable buffer that represents the given POD array.
1187/**
1188 * @returns A const_buffer value equivalent to:
1189 * @code const_buffer(
1190 * data.data(),
1191 * data.size() * sizeof(PodType)); @endcode
1192 */
1193template <typename PodType, std::size_t N>
1e59de90 1194BOOST_ASIO_NODISCARD inline BOOST_ASIO_CONST_BUFFER buffer(
b32b8144
FG
1195 const boost::array<PodType, N>& data) BOOST_ASIO_NOEXCEPT
1196{
1197 return BOOST_ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));
1198}
1199
1200/// Create a new non-modifiable buffer that represents the given POD array.
1201/**
1202 * @returns A const_buffer value equivalent to:
1203 * @code const_buffer(
1204 * data.data(),
1205 * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
1206 */
1207template <typename PodType, std::size_t N>
1e59de90
TL
1208BOOST_ASIO_NODISCARD inline BOOST_ASIO_CONST_BUFFER buffer(
1209 const boost::array<PodType, N>& data,
b32b8144
FG
1210 std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
1211{
1212 return BOOST_ASIO_CONST_BUFFER(data.data(),
1213 data.size() * sizeof(PodType) < max_size_in_bytes
1214 ? data.size() * sizeof(PodType) : max_size_in_bytes);
1215}
1216
1217#if defined(BOOST_ASIO_HAS_STD_ARRAY) || defined(GENERATING_DOCUMENTATION)
1218
1219/// Create a new modifiable buffer that represents the given POD array.
1220/**
1221 * @returns A mutable_buffer value equivalent to:
1222 * @code mutable_buffer(
1223 * data.data(),
1224 * data.size() * sizeof(PodType)); @endcode
1225 */
1226template <typename PodType, std::size_t N>
1e59de90 1227BOOST_ASIO_NODISCARD inline BOOST_ASIO_MUTABLE_BUFFER buffer(
b32b8144
FG
1228 std::array<PodType, N>& data) BOOST_ASIO_NOEXCEPT
1229{
1230 return BOOST_ASIO_MUTABLE_BUFFER(data.data(), data.size() * sizeof(PodType));
1231}
1232
1233/// Create a new modifiable buffer that represents the given POD array.
1234/**
1235 * @returns A mutable_buffer value equivalent to:
1236 * @code mutable_buffer(
1237 * data.data(),
1238 * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
1239 */
1240template <typename PodType, std::size_t N>
1e59de90
TL
1241BOOST_ASIO_NODISCARD inline BOOST_ASIO_MUTABLE_BUFFER buffer(
1242 std::array<PodType, N>& data,
b32b8144
FG
1243 std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
1244{
1245 return BOOST_ASIO_MUTABLE_BUFFER(data.data(),
1246 data.size() * sizeof(PodType) < max_size_in_bytes
1247 ? data.size() * sizeof(PodType) : max_size_in_bytes);
1248}
1249
1250/// Create a new non-modifiable buffer that represents the given POD array.
1251/**
1252 * @returns A const_buffer value equivalent to:
1253 * @code const_buffer(
1254 * data.data(),
1255 * data.size() * sizeof(PodType)); @endcode
1256 */
1257template <typename PodType, std::size_t N>
1e59de90 1258BOOST_ASIO_NODISCARD inline BOOST_ASIO_CONST_BUFFER buffer(
b32b8144
FG
1259 std::array<const PodType, N>& data) BOOST_ASIO_NOEXCEPT
1260{
1261 return BOOST_ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));
1262}
1263
1264/// Create a new non-modifiable buffer that represents the given POD array.
1265/**
1266 * @returns A const_buffer value equivalent to:
1267 * @code const_buffer(
1268 * data.data(),
1269 * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
1270 */
1271template <typename PodType, std::size_t N>
1e59de90
TL
1272BOOST_ASIO_NODISCARD inline BOOST_ASIO_CONST_BUFFER buffer(
1273 std::array<const PodType, N>& data,
b32b8144
FG
1274 std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
1275{
1276 return BOOST_ASIO_CONST_BUFFER(data.data(),
1277 data.size() * sizeof(PodType) < max_size_in_bytes
1278 ? data.size() * sizeof(PodType) : max_size_in_bytes);
1279}
1280
1281/// Create a new non-modifiable buffer that represents the given POD array.
1282/**
1283 * @returns A const_buffer value equivalent to:
1284 * @code const_buffer(
1285 * data.data(),
1286 * data.size() * sizeof(PodType)); @endcode
1287 */
1288template <typename PodType, std::size_t N>
1e59de90 1289BOOST_ASIO_NODISCARD inline BOOST_ASIO_CONST_BUFFER buffer(
b32b8144
FG
1290 const std::array<PodType, N>& data) BOOST_ASIO_NOEXCEPT
1291{
1292 return BOOST_ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));
1293}
1294
1295/// Create a new non-modifiable buffer that represents the given POD array.
1296/**
1297 * @returns A const_buffer value equivalent to:
1298 * @code const_buffer(
1299 * data.data(),
1300 * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
1301 */
1302template <typename PodType, std::size_t N>
1e59de90
TL
1303BOOST_ASIO_NODISCARD inline BOOST_ASIO_CONST_BUFFER buffer(
1304 const std::array<PodType, N>& data,
b32b8144
FG
1305 std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
1306{
1307 return BOOST_ASIO_CONST_BUFFER(data.data(),
1308 data.size() * sizeof(PodType) < max_size_in_bytes
1309 ? data.size() * sizeof(PodType) : max_size_in_bytes);
1310}
1311
1312#endif // defined(BOOST_ASIO_HAS_STD_ARRAY) || defined(GENERATING_DOCUMENTATION)
1313
1314/// Create a new modifiable buffer that represents the given POD vector.
1315/**
1316 * @returns A mutable_buffer value equivalent to:
1317 * @code mutable_buffer(
1318 * data.size() ? &data[0] : 0,
1319 * data.size() * sizeof(PodType)); @endcode
1320 *
1321 * @note The buffer is invalidated by any vector operation that would also
1322 * invalidate iterators.
1323 */
1324template <typename PodType, typename Allocator>
1e59de90 1325BOOST_ASIO_NODISCARD inline BOOST_ASIO_MUTABLE_BUFFER buffer(
b32b8144
FG
1326 std::vector<PodType, Allocator>& data) BOOST_ASIO_NOEXCEPT
1327{
1328 return BOOST_ASIO_MUTABLE_BUFFER(
1329 data.size() ? &data[0] : 0, data.size() * sizeof(PodType)
1330#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
1331 , detail::buffer_debug_check<
1332 typename std::vector<PodType, Allocator>::iterator
1333 >(data.begin())
1334#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
1335 );
1336}
1337
1338/// Create a new modifiable buffer that represents the given POD vector.
1339/**
1340 * @returns A mutable_buffer value equivalent to:
1341 * @code mutable_buffer(
1342 * data.size() ? &data[0] : 0,
1343 * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
1344 *
1345 * @note The buffer is invalidated by any vector operation that would also
1346 * invalidate iterators.
1347 */
1348template <typename PodType, typename Allocator>
1e59de90
TL
1349BOOST_ASIO_NODISCARD inline BOOST_ASIO_MUTABLE_BUFFER buffer(
1350 std::vector<PodType, Allocator>& data,
b32b8144
FG
1351 std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
1352{
1353 return BOOST_ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0,
1354 data.size() * sizeof(PodType) < max_size_in_bytes
1355 ? data.size() * sizeof(PodType) : max_size_in_bytes
1356#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
1357 , detail::buffer_debug_check<
1358 typename std::vector<PodType, Allocator>::iterator
1359 >(data.begin())
1360#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
1361 );
1362}
1363
1364/// Create a new non-modifiable buffer that represents the given POD vector.
1365/**
1366 * @returns A const_buffer value equivalent to:
1367 * @code const_buffer(
1368 * data.size() ? &data[0] : 0,
1369 * data.size() * sizeof(PodType)); @endcode
1370 *
1371 * @note The buffer is invalidated by any vector operation that would also
1372 * invalidate iterators.
1373 */
1374template <typename PodType, typename Allocator>
1e59de90 1375BOOST_ASIO_NODISCARD inline BOOST_ASIO_CONST_BUFFER buffer(
b32b8144
FG
1376 const std::vector<PodType, Allocator>& data) BOOST_ASIO_NOEXCEPT
1377{
1378 return BOOST_ASIO_CONST_BUFFER(
1379 data.size() ? &data[0] : 0, data.size() * sizeof(PodType)
1380#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
1381 , detail::buffer_debug_check<
1382 typename std::vector<PodType, Allocator>::const_iterator
1383 >(data.begin())
1384#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
1385 );
1386}
1387
1388/// Create a new non-modifiable buffer that represents the given POD vector.
1389/**
1390 * @returns A const_buffer value equivalent to:
1391 * @code const_buffer(
1392 * data.size() ? &data[0] : 0,
1393 * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
1394 *
1395 * @note The buffer is invalidated by any vector operation that would also
1396 * invalidate iterators.
1397 */
1398template <typename PodType, typename Allocator>
1e59de90 1399BOOST_ASIO_NODISCARD inline BOOST_ASIO_CONST_BUFFER buffer(
b32b8144
FG
1400 const std::vector<PodType, Allocator>& data,
1401 std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
1402{
1403 return BOOST_ASIO_CONST_BUFFER(data.size() ? &data[0] : 0,
1404 data.size() * sizeof(PodType) < max_size_in_bytes
1405 ? data.size() * sizeof(PodType) : max_size_in_bytes
1406#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
1407 , detail::buffer_debug_check<
1408 typename std::vector<PodType, Allocator>::const_iterator
1409 >(data.begin())
1410#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
1411 );
1412}
1413
1414/// Create a new modifiable buffer that represents the given string.
1415/**
1416 * @returns <tt>mutable_buffer(data.size() ? &data[0] : 0,
1417 * data.size() * sizeof(Elem))</tt>.
1418 *
1419 * @note The buffer is invalidated by any non-const operation called on the
1420 * given string object.
1421 */
1422template <typename Elem, typename Traits, typename Allocator>
1e59de90 1423BOOST_ASIO_NODISCARD inline BOOST_ASIO_MUTABLE_BUFFER buffer(
b32b8144
FG
1424 std::basic_string<Elem, Traits, Allocator>& data) BOOST_ASIO_NOEXCEPT
1425{
1426 return BOOST_ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0,
1427 data.size() * sizeof(Elem)
1428#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
1429 , detail::buffer_debug_check<
1430 typename std::basic_string<Elem, Traits, Allocator>::iterator
1431 >(data.begin())
1432#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
1433 );
1434}
1435
92f5a8d4 1436/// Create a new modifiable buffer that represents the given string.
b32b8144
FG
1437/**
1438 * @returns A mutable_buffer value equivalent to:
1439 * @code mutable_buffer(
1440 * data.size() ? &data[0] : 0,
1441 * min(data.size() * sizeof(Elem), max_size_in_bytes)); @endcode
1442 *
1443 * @note The buffer is invalidated by any non-const operation called on the
1444 * given string object.
1445 */
1446template <typename Elem, typename Traits, typename Allocator>
1e59de90 1447BOOST_ASIO_NODISCARD inline BOOST_ASIO_MUTABLE_BUFFER buffer(
b32b8144
FG
1448 std::basic_string<Elem, Traits, Allocator>& data,
1449 std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
1450{
1451 return BOOST_ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0,
1452 data.size() * sizeof(Elem) < max_size_in_bytes
1453 ? data.size() * sizeof(Elem) : max_size_in_bytes
1454#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
1455 , detail::buffer_debug_check<
1456 typename std::basic_string<Elem, Traits, Allocator>::iterator
1457 >(data.begin())
1458#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
1459 );
1460}
1461
1462/// Create a new non-modifiable buffer that represents the given string.
1463/**
1464 * @returns <tt>const_buffer(data.data(), data.size() * sizeof(Elem))</tt>.
1465 *
1466 * @note The buffer is invalidated by any non-const operation called on the
1467 * given string object.
1468 */
1469template <typename Elem, typename Traits, typename Allocator>
1e59de90 1470BOOST_ASIO_NODISCARD inline BOOST_ASIO_CONST_BUFFER buffer(
b32b8144
FG
1471 const std::basic_string<Elem, Traits, Allocator>& data) BOOST_ASIO_NOEXCEPT
1472{
1473 return BOOST_ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(Elem)
1474#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
1475 , detail::buffer_debug_check<
1476 typename std::basic_string<Elem, Traits, Allocator>::const_iterator
1477 >(data.begin())
1478#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
1479 );
1480}
1481
1482/// Create a new non-modifiable buffer that represents the given string.
1483/**
1484 * @returns A const_buffer value equivalent to:
1485 * @code const_buffer(
1486 * data.data(),
1487 * min(data.size() * sizeof(Elem), max_size_in_bytes)); @endcode
1488 *
1489 * @note The buffer is invalidated by any non-const operation called on the
1490 * given string object.
1491 */
1492template <typename Elem, typename Traits, typename Allocator>
1e59de90 1493BOOST_ASIO_NODISCARD inline BOOST_ASIO_CONST_BUFFER buffer(
b32b8144
FG
1494 const std::basic_string<Elem, Traits, Allocator>& data,
1495 std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
1496{
1497 return BOOST_ASIO_CONST_BUFFER(data.data(),
1498 data.size() * sizeof(Elem) < max_size_in_bytes
1499 ? data.size() * sizeof(Elem) : max_size_in_bytes
1500#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
1501 , detail::buffer_debug_check<
1502 typename std::basic_string<Elem, Traits, Allocator>::const_iterator
1503 >(data.begin())
1504#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
1505 );
1506}
1507
11fdf7f2 1508#if defined(BOOST_ASIO_HAS_STRING_VIEW) \
b32b8144
FG
1509 || defined(GENERATING_DOCUMENTATION)
1510
1511/// Create a new modifiable buffer that represents the given string_view.
1512/**
1513 * @returns <tt>mutable_buffer(data.size() ? &data[0] : 0,
1514 * data.size() * sizeof(Elem))</tt>.
1515 */
1516template <typename Elem, typename Traits>
1e59de90 1517BOOST_ASIO_NODISCARD inline BOOST_ASIO_CONST_BUFFER buffer(
b32b8144
FG
1518 basic_string_view<Elem, Traits> data) BOOST_ASIO_NOEXCEPT
1519{
1520 return BOOST_ASIO_CONST_BUFFER(data.size() ? &data[0] : 0,
1521 data.size() * sizeof(Elem)
1522#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
1523 , detail::buffer_debug_check<
1524 typename basic_string_view<Elem, Traits>::iterator
1525 >(data.begin())
1526#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
1527 );
1528}
1529
1530/// Create a new non-modifiable buffer that represents the given string.
1531/**
1532 * @returns A mutable_buffer value equivalent to:
1533 * @code mutable_buffer(
1534 * data.size() ? &data[0] : 0,
1535 * min(data.size() * sizeof(Elem), max_size_in_bytes)); @endcode
1536 */
1537template <typename Elem, typename Traits>
1e59de90 1538BOOST_ASIO_NODISCARD inline BOOST_ASIO_CONST_BUFFER buffer(
b32b8144
FG
1539 basic_string_view<Elem, Traits> data,
1540 std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
1541{
1542 return BOOST_ASIO_CONST_BUFFER(data.size() ? &data[0] : 0,
1543 data.size() * sizeof(Elem) < max_size_in_bytes
1544 ? data.size() * sizeof(Elem) : max_size_in_bytes
1545#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
1546 , detail::buffer_debug_check<
1547 typename basic_string_view<Elem, Traits>::iterator
1548 >(data.begin())
1549#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
1550 );
1551}
1552
11fdf7f2 1553#endif // defined(BOOST_ASIO_HAS_STRING_VIEW)
b32b8144
FG
1554 // || defined(GENERATING_DOCUMENTATION)
1555
1556/*@}*/
1557
1558/// Adapt a basic_string to the DynamicBuffer requirements.
1559/**
1560 * Requires that <tt>sizeof(Elem) == 1</tt>.
1561 */
1562template <typename Elem, typename Traits, typename Allocator>
1563class dynamic_string_buffer
1564{
1565public:
92f5a8d4
TL
1566 /// The type used to represent a sequence of constant buffers that refers to
1567 /// the underlying memory.
b32b8144
FG
1568 typedef BOOST_ASIO_CONST_BUFFER const_buffers_type;
1569
92f5a8d4
TL
1570 /// The type used to represent a sequence of mutable buffers that refers to
1571 /// the underlying memory.
b32b8144
FG
1572 typedef BOOST_ASIO_MUTABLE_BUFFER mutable_buffers_type;
1573
1574 /// Construct a dynamic buffer from a string.
1575 /**
1576 * @param s The string to be used as backing storage for the dynamic buffer.
92f5a8d4
TL
1577 * The object stores a reference to the string and the user is responsible
1578 * for ensuring that the string object remains valid while the
1579 * dynamic_string_buffer object, and copies of the object, are in use.
1580 *
1581 * @b DynamicBuffer_v1: Any existing data in the string is treated as the
1582 * dynamic buffer's input sequence.
b32b8144
FG
1583 *
1584 * @param maximum_size Specifies a maximum size for the buffer, in bytes.
1585 */
1586 explicit dynamic_string_buffer(std::basic_string<Elem, Traits, Allocator>& s,
1587 std::size_t maximum_size =
1588 (std::numeric_limits<std::size_t>::max)()) BOOST_ASIO_NOEXCEPT
1589 : string_(s),
92f5a8d4
TL
1590#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1591 size_((std::numeric_limits<std::size_t>::max)()),
1592#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
b32b8144
FG
1593 max_size_(maximum_size)
1594 {
1595 }
1596
92f5a8d4
TL
1597 /// @b DynamicBuffer_v2: Copy construct a dynamic buffer.
1598 dynamic_string_buffer(const dynamic_string_buffer& other) BOOST_ASIO_NOEXCEPT
1599 : string_(other.string_),
1600#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1601 size_(other.size_),
1602#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1603 max_size_(other.max_size_)
1604 {
1605 }
1606
b32b8144
FG
1607#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
1608 /// Move construct a dynamic buffer.
1609 dynamic_string_buffer(dynamic_string_buffer&& other) BOOST_ASIO_NOEXCEPT
1610 : string_(other.string_),
92f5a8d4 1611#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
b32b8144 1612 size_(other.size_),
92f5a8d4 1613#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
b32b8144
FG
1614 max_size_(other.max_size_)
1615 {
1616 }
1617#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
1618
92f5a8d4
TL
1619 /// @b DynamicBuffer_v1: Get the size of the input sequence.
1620 /// @b DynamicBuffer_v2: Get the current size of the underlying memory.
1621 /**
1622 * @returns @b DynamicBuffer_v1 The current size of the input sequence.
1623 * @b DynamicBuffer_v2: The current size of the underlying string if less than
1624 * max_size(). Otherwise returns max_size().
1625 */
b32b8144
FG
1626 std::size_t size() const BOOST_ASIO_NOEXCEPT
1627 {
92f5a8d4
TL
1628#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1629 if (size_ != (std::numeric_limits<std::size_t>::max)())
1630 return size_;
1631#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1632 return (std::min)(string_.size(), max_size());
b32b8144
FG
1633 }
1634
1635 /// Get the maximum size of the dynamic buffer.
1636 /**
92f5a8d4 1637 * @returns The allowed maximum size of the underlying memory.
b32b8144
FG
1638 */
1639 std::size_t max_size() const BOOST_ASIO_NOEXCEPT
1640 {
1641 return max_size_;
1642 }
1643
92f5a8d4
TL
1644 /// Get the maximum size that the buffer may grow to without triggering
1645 /// reallocation.
b32b8144 1646 /**
92f5a8d4
TL
1647 * @returns The current capacity of the underlying string if less than
1648 * max_size(). Otherwise returns max_size().
b32b8144
FG
1649 */
1650 std::size_t capacity() const BOOST_ASIO_NOEXCEPT
1651 {
92f5a8d4 1652 return (std::min)(string_.capacity(), max_size());
b32b8144
FG
1653 }
1654
92f5a8d4
TL
1655#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1656 /// @b DynamicBuffer_v1: Get a list of buffers that represents the input
1657 /// sequence.
b32b8144
FG
1658 /**
1659 * @returns An object of type @c const_buffers_type that satisfies
1660 * ConstBufferSequence requirements, representing the basic_string memory in
92f5a8d4 1661 * the input sequence.
b32b8144
FG
1662 *
1663 * @note The returned object is invalidated by any @c dynamic_string_buffer
92f5a8d4 1664 * or @c basic_string member function that resizes or erases the string.
b32b8144
FG
1665 */
1666 const_buffers_type data() const BOOST_ASIO_NOEXCEPT
1667 {
1668 return const_buffers_type(boost::asio::buffer(string_, size_));
1669 }
92f5a8d4
TL
1670#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1671
1672 /// @b DynamicBuffer_v2: Get a sequence of buffers that represents the
1673 /// underlying memory.
1674 /**
1675 * @param pos Position of the first byte to represent in the buffer sequence
1676 *
1677 * @param n The number of bytes to return in the buffer sequence. If the
1678 * underlying memory is shorter, the buffer sequence represents as many bytes
1679 * as are available.
1680 *
1681 * @returns An object of type @c mutable_buffers_type that satisfies
1682 * MutableBufferSequence requirements, representing the basic_string memory.
1683 *
1684 * @note The returned object is invalidated by any @c dynamic_string_buffer
1685 * or @c basic_string member function that resizes or erases the string.
1686 */
1687 mutable_buffers_type data(std::size_t pos, std::size_t n) BOOST_ASIO_NOEXCEPT
1688 {
1689 return mutable_buffers_type(boost::asio::buffer(
1690 boost::asio::buffer(string_, max_size_) + pos, n));
1691 }
1692
1693 /// @b DynamicBuffer_v2: Get a sequence of buffers that represents the
1694 /// underlying memory.
1695 /**
1696 * @param pos Position of the first byte to represent in the buffer sequence
1697 *
1698 * @param n The number of bytes to return in the buffer sequence. If the
1699 * underlying memory is shorter, the buffer sequence represents as many bytes
1700 * as are available.
1701 *
1702 * @note The returned object is invalidated by any @c dynamic_string_buffer
1703 * or @c basic_string member function that resizes or erases the string.
1704 */
1705 const_buffers_type data(std::size_t pos,
1706 std::size_t n) const BOOST_ASIO_NOEXCEPT
1707 {
1708 return const_buffers_type(boost::asio::buffer(
1709 boost::asio::buffer(string_, max_size_) + pos, n));
1710 }
b32b8144 1711
92f5a8d4
TL
1712#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1713 /// @b DynamicBuffer_v1: Get a list of buffers that represents the output
1714 /// sequence, with the given size.
b32b8144
FG
1715 /**
1716 * Ensures that the output sequence can accommodate @c n bytes, resizing the
1717 * basic_string object as necessary.
1718 *
1719 * @returns An object of type @c mutable_buffers_type that satisfies
1720 * MutableBufferSequence requirements, representing basic_string memory
1721 * at the start of the output sequence of size @c n.
1722 *
1723 * @throws std::length_error If <tt>size() + n > max_size()</tt>.
1724 *
1725 * @note The returned object is invalidated by any @c dynamic_string_buffer
1726 * or @c basic_string member function that modifies the input sequence or
1727 * output sequence.
1728 */
1729 mutable_buffers_type prepare(std::size_t n)
1730 {
92f5a8d4 1731 if (size() > max_size() || max_size() - size() < n)
b32b8144
FG
1732 {
1733 std::length_error ex("dynamic_string_buffer too long");
1734 boost::asio::detail::throw_exception(ex);
1735 }
1736
92f5a8d4
TL
1737 if (size_ == (std::numeric_limits<std::size_t>::max)())
1738 size_ = string_.size(); // Enable v1 behaviour.
1739
b32b8144
FG
1740 string_.resize(size_ + n);
1741
1742 return boost::asio::buffer(boost::asio::buffer(string_) + size_, n);
1743 }
1744
92f5a8d4
TL
1745 /// @b DynamicBuffer_v1: Move bytes from the output sequence to the input
1746 /// sequence.
b32b8144
FG
1747 /**
1748 * @param n The number of bytes to append from the start of the output
1749 * sequence to the end of the input sequence. The remainder of the output
1750 * sequence is discarded.
1751 *
1752 * Requires a preceding call <tt>prepare(x)</tt> where <tt>x >= n</tt>, and
1753 * no intervening operations that modify the input or output sequence.
1754 *
1755 * @note If @c n is greater than the size of the output sequence, the entire
1756 * output sequence is moved to the input sequence and no error is issued.
1757 */
1758 void commit(std::size_t n)
1759 {
1760 size_ += (std::min)(n, string_.size() - size_);
1761 string_.resize(size_);
1762 }
92f5a8d4
TL
1763#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1764
1765 /// @b DynamicBuffer_v2: Grow the underlying memory by the specified number of
1766 /// bytes.
1767 /**
1768 * Resizes the string to accommodate an additional @c n bytes at the end.
1769 *
1770 * @throws std::length_error If <tt>size() + n > max_size()</tt>.
1771 */
1772 void grow(std::size_t n)
1773 {
1774 if (size() > max_size() || max_size() - size() < n)
1775 {
1776 std::length_error ex("dynamic_string_buffer too long");
1777 boost::asio::detail::throw_exception(ex);
1778 }
1779
1780 string_.resize(size() + n);
1781 }
b32b8144 1782
92f5a8d4
TL
1783 /// @b DynamicBuffer_v2: Shrink the underlying memory by the specified number
1784 /// of bytes.
b32b8144 1785 /**
92f5a8d4
TL
1786 * Erases @c n bytes from the end of the string by resizing the basic_string
1787 * object. If @c n is greater than the current size of the string, the string
1788 * is emptied.
1789 */
1790 void shrink(std::size_t n)
1791 {
1792 string_.resize(n > size() ? 0 : size() - n);
1793 }
1794
1795 /// @b DynamicBuffer_v1: Remove characters from the input sequence.
1796 /// @b DynamicBuffer_v2: Consume the specified number of bytes from the
1797 /// beginning of the underlying memory.
1798 /**
1799 * @b DynamicBuffer_v1: Removes @c n characters from the beginning of the
1800 * input sequence. @note If @c n is greater than the size of the input
1801 * sequence, the entire input sequence is consumed and no error is issued.
b32b8144 1802 *
92f5a8d4
TL
1803 * @b DynamicBuffer_v2: Erases @c n bytes from the beginning of the string.
1804 * If @c n is greater than the current size of the string, the string is
1805 * emptied.
b32b8144
FG
1806 */
1807 void consume(std::size_t n)
1808 {
92f5a8d4
TL
1809#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1810 if (size_ != (std::numeric_limits<std::size_t>::max)())
1811 {
1812 std::size_t consume_length = (std::min)(n, size_);
1813 string_.erase(0, consume_length);
1814 size_ -= consume_length;
1815 return;
1816 }
1817#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1818 string_.erase(0, n);
b32b8144
FG
1819 }
1820
1821private:
1822 std::basic_string<Elem, Traits, Allocator>& string_;
92f5a8d4 1823#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
b32b8144 1824 std::size_t size_;
92f5a8d4 1825#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
b32b8144
FG
1826 const std::size_t max_size_;
1827};
1828
1829/// Adapt a vector to the DynamicBuffer requirements.
1830/**
1831 * Requires that <tt>sizeof(Elem) == 1</tt>.
1832 */
1833template <typename Elem, typename Allocator>
1834class dynamic_vector_buffer
1835{
1836public:
92f5a8d4
TL
1837 /// The type used to represent a sequence of constant buffers that refers to
1838 /// the underlying memory.
b32b8144
FG
1839 typedef BOOST_ASIO_CONST_BUFFER const_buffers_type;
1840
92f5a8d4
TL
1841 /// The type used to represent a sequence of mutable buffers that refers to
1842 /// the underlying memory.
b32b8144
FG
1843 typedef BOOST_ASIO_MUTABLE_BUFFER mutable_buffers_type;
1844
92f5a8d4 1845 /// Construct a dynamic buffer from a vector.
b32b8144
FG
1846 /**
1847 * @param v The vector to be used as backing storage for the dynamic buffer.
92f5a8d4
TL
1848 * The object stores a reference to the vector and the user is responsible
1849 * for ensuring that the vector object remains valid while the
1850 * dynamic_vector_buffer object, and copies of the object, are in use.
b32b8144
FG
1851 *
1852 * @param maximum_size Specifies a maximum size for the buffer, in bytes.
1853 */
1854 explicit dynamic_vector_buffer(std::vector<Elem, Allocator>& v,
1855 std::size_t maximum_size =
1856 (std::numeric_limits<std::size_t>::max)()) BOOST_ASIO_NOEXCEPT
1857 : vector_(v),
92f5a8d4
TL
1858#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1859 size_((std::numeric_limits<std::size_t>::max)()),
1860#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
b32b8144
FG
1861 max_size_(maximum_size)
1862 {
1863 }
1864
92f5a8d4
TL
1865 /// @b DynamicBuffer_v2: Copy construct a dynamic buffer.
1866 dynamic_vector_buffer(const dynamic_vector_buffer& other) BOOST_ASIO_NOEXCEPT
1867 : vector_(other.vector_),
1868#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1869 size_(other.size_),
1870#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1871 max_size_(other.max_size_)
1872 {
1873 }
1874
b32b8144
FG
1875#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
1876 /// Move construct a dynamic buffer.
1877 dynamic_vector_buffer(dynamic_vector_buffer&& other) BOOST_ASIO_NOEXCEPT
1878 : vector_(other.vector_),
92f5a8d4 1879#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
b32b8144 1880 size_(other.size_),
92f5a8d4 1881#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
b32b8144
FG
1882 max_size_(other.max_size_)
1883 {
1884 }
1885#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
1886
92f5a8d4
TL
1887 /// @b DynamicBuffer_v1: Get the size of the input sequence.
1888 /// @b DynamicBuffer_v2: Get the current size of the underlying memory.
1889 /**
1890 * @returns @b DynamicBuffer_v1 The current size of the input sequence.
1891 * @b DynamicBuffer_v2: The current size of the underlying vector if less than
1892 * max_size(). Otherwise returns max_size().
1893 */
b32b8144
FG
1894 std::size_t size() const BOOST_ASIO_NOEXCEPT
1895 {
92f5a8d4
TL
1896#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1897 if (size_ != (std::numeric_limits<std::size_t>::max)())
1898 return size_;
1899#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1900 return (std::min)(vector_.size(), max_size());
b32b8144
FG
1901 }
1902
1903 /// Get the maximum size of the dynamic buffer.
1904 /**
92f5a8d4
TL
1905 * @returns @b DynamicBuffer_v1: The allowed maximum of the sum of the sizes
1906 * of the input sequence and output sequence. @b DynamicBuffer_v2: The allowed
1907 * maximum size of the underlying memory.
b32b8144
FG
1908 */
1909 std::size_t max_size() const BOOST_ASIO_NOEXCEPT
1910 {
1911 return max_size_;
1912 }
1913
92f5a8d4
TL
1914 /// Get the maximum size that the buffer may grow to without triggering
1915 /// reallocation.
b32b8144 1916 /**
92f5a8d4
TL
1917 * @returns @b DynamicBuffer_v1: The current total capacity of the buffer,
1918 * i.e. for both the input sequence and output sequence. @b DynamicBuffer_v2:
1919 * The current capacity of the underlying vector if less than max_size().
1920 * Otherwise returns max_size().
b32b8144
FG
1921 */
1922 std::size_t capacity() const BOOST_ASIO_NOEXCEPT
1923 {
92f5a8d4 1924 return (std::min)(vector_.capacity(), max_size());
b32b8144
FG
1925 }
1926
92f5a8d4
TL
1927#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1928 /// @b DynamicBuffer_v1: Get a list of buffers that represents the input
1929 /// sequence.
b32b8144
FG
1930 /**
1931 * @returns An object of type @c const_buffers_type that satisfies
92f5a8d4 1932 * ConstBufferSequence requirements, representing the vector memory in the
b32b8144
FG
1933 * input sequence.
1934 *
1935 * @note The returned object is invalidated by any @c dynamic_vector_buffer
92f5a8d4
TL
1936 * or @c vector member function that modifies the input sequence or output
1937 * sequence.
b32b8144
FG
1938 */
1939 const_buffers_type data() const BOOST_ASIO_NOEXCEPT
1940 {
1941 return const_buffers_type(boost::asio::buffer(vector_, size_));
1942 }
92f5a8d4 1943#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
b32b8144 1944
92f5a8d4
TL
1945 /// @b DynamicBuffer_v2: Get a sequence of buffers that represents the
1946 /// underlying memory.
1947 /**
1948 * @param pos Position of the first byte to represent in the buffer sequence
1949 *
1950 * @param n The number of bytes to return in the buffer sequence. If the
1951 * underlying memory is shorter, the buffer sequence represents as many bytes
1952 * as are available.
1953 *
1954 * @returns An object of type @c mutable_buffers_type that satisfies
1955 * MutableBufferSequence requirements, representing the vector memory.
1956 *
1957 * @note The returned object is invalidated by any @c dynamic_vector_buffer
1958 * or @c vector member function that resizes or erases the vector.
1959 */
1960 mutable_buffers_type data(std::size_t pos, std::size_t n) BOOST_ASIO_NOEXCEPT
1961 {
1962 return mutable_buffers_type(boost::asio::buffer(
1963 boost::asio::buffer(vector_, max_size_) + pos, n));
1964 }
1965
1966 /// @b DynamicBuffer_v2: Get a sequence of buffers that represents the
1967 /// underlying memory.
1968 /**
1969 * @param pos Position of the first byte to represent in the buffer sequence
1970 *
1971 * @param n The number of bytes to return in the buffer sequence. If the
1972 * underlying memory is shorter, the buffer sequence represents as many bytes
1973 * as are available.
1974 *
1975 * @note The returned object is invalidated by any @c dynamic_vector_buffer
1976 * or @c vector member function that resizes or erases the vector.
1977 */
1978 const_buffers_type data(std::size_t pos,
1979 std::size_t n) const BOOST_ASIO_NOEXCEPT
1980 {
1981 return const_buffers_type(boost::asio::buffer(
1982 boost::asio::buffer(vector_, max_size_) + pos, n));
1983 }
1984
1985#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1986 /// @b DynamicBuffer_v1: Get a list of buffers that represents the output
1987 /// sequence, with the given size.
b32b8144
FG
1988 /**
1989 * Ensures that the output sequence can accommodate @c n bytes, resizing the
92f5a8d4 1990 * vector object as necessary.
b32b8144
FG
1991 *
1992 * @returns An object of type @c mutable_buffers_type that satisfies
92f5a8d4
TL
1993 * MutableBufferSequence requirements, representing vector memory at the
1994 * start of the output sequence of size @c n.
b32b8144
FG
1995 *
1996 * @throws std::length_error If <tt>size() + n > max_size()</tt>.
1997 *
1998 * @note The returned object is invalidated by any @c dynamic_vector_buffer
92f5a8d4
TL
1999 * or @c vector member function that modifies the input sequence or output
2000 * sequence.
b32b8144
FG
2001 */
2002 mutable_buffers_type prepare(std::size_t n)
2003 {
2004 if (size () > max_size() || max_size() - size() < n)
2005 {
2006 std::length_error ex("dynamic_vector_buffer too long");
2007 boost::asio::detail::throw_exception(ex);
2008 }
2009
92f5a8d4
TL
2010 if (size_ == (std::numeric_limits<std::size_t>::max)())
2011 size_ = vector_.size(); // Enable v1 behaviour.
2012
b32b8144
FG
2013 vector_.resize(size_ + n);
2014
2015 return boost::asio::buffer(boost::asio::buffer(vector_) + size_, n);
2016 }
2017
92f5a8d4
TL
2018 /// @b DynamicBuffer_v1: Move bytes from the output sequence to the input
2019 /// sequence.
b32b8144
FG
2020 /**
2021 * @param n The number of bytes to append from the start of the output
2022 * sequence to the end of the input sequence. The remainder of the output
2023 * sequence is discarded.
2024 *
2025 * Requires a preceding call <tt>prepare(x)</tt> where <tt>x >= n</tt>, and
2026 * no intervening operations that modify the input or output sequence.
2027 *
2028 * @note If @c n is greater than the size of the output sequence, the entire
2029 * output sequence is moved to the input sequence and no error is issued.
2030 */
2031 void commit(std::size_t n)
2032 {
2033 size_ += (std::min)(n, vector_.size() - size_);
2034 vector_.resize(size_);
2035 }
92f5a8d4
TL
2036#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
2037
2038 /// @b DynamicBuffer_v2: Grow the underlying memory by the specified number of
2039 /// bytes.
2040 /**
2041 * Resizes the vector to accommodate an additional @c n bytes at the end.
2042 *
2043 * @throws std::length_error If <tt>size() + n > max_size()</tt>.
2044 */
2045 void grow(std::size_t n)
2046 {
2047 if (size() > max_size() || max_size() - size() < n)
2048 {
2049 std::length_error ex("dynamic_vector_buffer too long");
2050 boost::asio::detail::throw_exception(ex);
2051 }
2052
2053 vector_.resize(size() + n);
2054 }
2055
2056 /// @b DynamicBuffer_v2: Shrink the underlying memory by the specified number
2057 /// of bytes.
2058 /**
2059 * Erases @c n bytes from the end of the vector by resizing the vector
2060 * object. If @c n is greater than the current size of the vector, the vector
2061 * is emptied.
2062 */
2063 void shrink(std::size_t n)
2064 {
2065 vector_.resize(n > size() ? 0 : size() - n);
2066 }
b32b8144 2067
92f5a8d4
TL
2068 /// @b DynamicBuffer_v1: Remove characters from the input sequence.
2069 /// @b DynamicBuffer_v2: Consume the specified number of bytes from the
2070 /// beginning of the underlying memory.
b32b8144 2071 /**
92f5a8d4
TL
2072 * @b DynamicBuffer_v1: Removes @c n characters from the beginning of the
2073 * input sequence. @note If @c n is greater than the size of the input
2074 * sequence, the entire input sequence is consumed and no error is issued.
b32b8144 2075 *
92f5a8d4
TL
2076 * @b DynamicBuffer_v2: Erases @c n bytes from the beginning of the vector.
2077 * If @c n is greater than the current size of the vector, the vector is
2078 * emptied.
b32b8144
FG
2079 */
2080 void consume(std::size_t n)
2081 {
92f5a8d4
TL
2082#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
2083 if (size_ != (std::numeric_limits<std::size_t>::max)())
2084 {
2085 std::size_t consume_length = (std::min)(n, size_);
2086 vector_.erase(vector_.begin(), vector_.begin() + consume_length);
2087 size_ -= consume_length;
2088 return;
2089 }
2090#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
2091 vector_.erase(vector_.begin(), vector_.begin() + (std::min)(size(), n));
b32b8144
FG
2092 }
2093
2094private:
2095 std::vector<Elem, Allocator>& vector_;
92f5a8d4 2096#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
b32b8144 2097 std::size_t size_;
92f5a8d4 2098#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
b32b8144
FG
2099 const std::size_t max_size_;
2100};
2101
2102/** @defgroup dynamic_buffer boost::asio::dynamic_buffer
2103 *
2104 * @brief The boost::asio::dynamic_buffer function is used to create a
2105 * dynamically resized buffer from a @c std::basic_string or @c std::vector.
2106 */
2107/*@{*/
2108
2109/// Create a new dynamic buffer that represents the given string.
2110/**
2111 * @returns <tt>dynamic_string_buffer<Elem, Traits, Allocator>(data)</tt>.
2112 */
2113template <typename Elem, typename Traits, typename Allocator>
1e59de90
TL
2114BOOST_ASIO_NODISCARD inline
2115dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer(
b32b8144
FG
2116 std::basic_string<Elem, Traits, Allocator>& data) BOOST_ASIO_NOEXCEPT
2117{
2118 return dynamic_string_buffer<Elem, Traits, Allocator>(data);
2119}
2120
2121/// Create a new dynamic buffer that represents the given string.
2122/**
2123 * @returns <tt>dynamic_string_buffer<Elem, Traits, Allocator>(data,
2124 * max_size)</tt>.
2125 */
2126template <typename Elem, typename Traits, typename Allocator>
1e59de90
TL
2127BOOST_ASIO_NODISCARD inline
2128dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer(
b32b8144
FG
2129 std::basic_string<Elem, Traits, Allocator>& data,
2130 std::size_t max_size) BOOST_ASIO_NOEXCEPT
2131{
2132 return dynamic_string_buffer<Elem, Traits, Allocator>(data, max_size);
2133}
2134
2135/// Create a new dynamic buffer that represents the given vector.
2136/**
2137 * @returns <tt>dynamic_vector_buffer<Elem, Allocator>(data)</tt>.
2138 */
2139template <typename Elem, typename Allocator>
1e59de90
TL
2140BOOST_ASIO_NODISCARD inline
2141dynamic_vector_buffer<Elem, Allocator> dynamic_buffer(
b32b8144
FG
2142 std::vector<Elem, Allocator>& data) BOOST_ASIO_NOEXCEPT
2143{
2144 return dynamic_vector_buffer<Elem, Allocator>(data);
2145}
2146
2147/// Create a new dynamic buffer that represents the given vector.
2148/**
2149 * @returns <tt>dynamic_vector_buffer<Elem, Allocator>(data, max_size)</tt>.
2150 */
2151template <typename Elem, typename Allocator>
1e59de90
TL
2152BOOST_ASIO_NODISCARD inline
2153dynamic_vector_buffer<Elem, Allocator> dynamic_buffer(
b32b8144
FG
2154 std::vector<Elem, Allocator>& data,
2155 std::size_t max_size) BOOST_ASIO_NOEXCEPT
2156{
2157 return dynamic_vector_buffer<Elem, Allocator>(data, max_size);
2158}
2159
2160/*@}*/
2161
2162/** @defgroup buffer_copy boost::asio::buffer_copy
2163 *
2164 * @brief The boost::asio::buffer_copy function is used to copy bytes from a
2165 * source buffer (or buffer sequence) to a target buffer (or buffer sequence).
2166 *
2167 * The @c buffer_copy function is available in two forms:
2168 *
2169 * @li A 2-argument form: @c buffer_copy(target, source)
2170 *
2171 * @li A 3-argument form: @c buffer_copy(target, source, max_bytes_to_copy)
2172 *
2173 * Both forms return the number of bytes actually copied. The number of bytes
2174 * copied is the lesser of:
2175 *
2176 * @li @c buffer_size(target)
2177 *
2178 * @li @c buffer_size(source)
2179 *
2180 * @li @c If specified, @c max_bytes_to_copy.
2181 *
2182 * This prevents buffer overflow, regardless of the buffer sizes used in the
2183 * copy operation.
2184 *
2185 * Note that @ref buffer_copy is implemented in terms of @c memcpy, and
2186 * consequently it cannot be used to copy between overlapping memory regions.
2187 */
2188/*@{*/
2189
2190namespace detail {
2191
2192inline std::size_t buffer_copy_1(const mutable_buffer& target,
2193 const const_buffer& source)
2194{
2195 using namespace std; // For memcpy.
2196 std::size_t target_size = target.size();
2197 std::size_t source_size = source.size();
2198 std::size_t n = target_size < source_size ? target_size : source_size;
2199 if (n > 0)
2200 memcpy(target.data(), source.data(), n);
2201 return n;
2202}
2203
2204template <typename TargetIterator, typename SourceIterator>
2205inline std::size_t buffer_copy(one_buffer, one_buffer,
2206 TargetIterator target_begin, TargetIterator,
2207 SourceIterator source_begin, SourceIterator) BOOST_ASIO_NOEXCEPT
2208{
2209 return (buffer_copy_1)(*target_begin, *source_begin);
2210}
2211
2212template <typename TargetIterator, typename SourceIterator>
2213inline std::size_t buffer_copy(one_buffer, one_buffer,
2214 TargetIterator target_begin, TargetIterator,
2215 SourceIterator source_begin, SourceIterator,
2216 std::size_t max_bytes_to_copy) BOOST_ASIO_NOEXCEPT
2217{
2218 return (buffer_copy_1)(*target_begin,
2219 boost::asio::buffer(*source_begin, max_bytes_to_copy));
2220}
2221
2222template <typename TargetIterator, typename SourceIterator>
2223std::size_t buffer_copy(one_buffer, multiple_buffers,
2224 TargetIterator target_begin, TargetIterator,
2225 SourceIterator source_begin, SourceIterator source_end,
2226 std::size_t max_bytes_to_copy
2227 = (std::numeric_limits<std::size_t>::max)()) BOOST_ASIO_NOEXCEPT
2228{
2229 std::size_t total_bytes_copied = 0;
2230 SourceIterator source_iter = source_begin;
2231
2232 for (mutable_buffer target_buffer(
2233 boost::asio::buffer(*target_begin, max_bytes_to_copy));
2234 target_buffer.size() && source_iter != source_end; ++source_iter)
2235 {
2236 const_buffer source_buffer(*source_iter);
2237 std::size_t bytes_copied = (buffer_copy_1)(target_buffer, source_buffer);
2238 total_bytes_copied += bytes_copied;
2239 target_buffer += bytes_copied;
2240 }
2241
2242 return total_bytes_copied;
2243}
2244
2245template <typename TargetIterator, typename SourceIterator>
2246std::size_t buffer_copy(multiple_buffers, one_buffer,
2247 TargetIterator target_begin, TargetIterator target_end,
2248 SourceIterator source_begin, SourceIterator,
2249 std::size_t max_bytes_to_copy
2250 = (std::numeric_limits<std::size_t>::max)()) BOOST_ASIO_NOEXCEPT
2251{
2252 std::size_t total_bytes_copied = 0;
2253 TargetIterator target_iter = target_begin;
2254
2255 for (const_buffer source_buffer(
2256 boost::asio::buffer(*source_begin, max_bytes_to_copy));
2257 source_buffer.size() && target_iter != target_end; ++target_iter)
2258 {
2259 mutable_buffer target_buffer(*target_iter);
2260 std::size_t bytes_copied = (buffer_copy_1)(target_buffer, source_buffer);
2261 total_bytes_copied += bytes_copied;
2262 source_buffer += bytes_copied;
2263 }
2264
2265 return total_bytes_copied;
2266}
2267
2268template <typename TargetIterator, typename SourceIterator>
2269std::size_t buffer_copy(multiple_buffers, multiple_buffers,
2270 TargetIterator target_begin, TargetIterator target_end,
2271 SourceIterator source_begin, SourceIterator source_end) BOOST_ASIO_NOEXCEPT
2272{
2273 std::size_t total_bytes_copied = 0;
2274
2275 TargetIterator target_iter = target_begin;
2276 std::size_t target_buffer_offset = 0;
2277
2278 SourceIterator source_iter = source_begin;
2279 std::size_t source_buffer_offset = 0;
2280
2281 while (target_iter != target_end && source_iter != source_end)
2282 {
2283 mutable_buffer target_buffer =
2284 mutable_buffer(*target_iter) + target_buffer_offset;
2285
2286 const_buffer source_buffer =
2287 const_buffer(*source_iter) + source_buffer_offset;
2288
2289 std::size_t bytes_copied = (buffer_copy_1)(target_buffer, source_buffer);
2290 total_bytes_copied += bytes_copied;
2291
2292 if (bytes_copied == target_buffer.size())
2293 {
2294 ++target_iter;
2295 target_buffer_offset = 0;
2296 }
2297 else
2298 target_buffer_offset += bytes_copied;
2299
2300 if (bytes_copied == source_buffer.size())
2301 {
2302 ++source_iter;
2303 source_buffer_offset = 0;
2304 }
2305 else
2306 source_buffer_offset += bytes_copied;
2307 }
2308
2309 return total_bytes_copied;
2310}
2311
2312template <typename TargetIterator, typename SourceIterator>
2313std::size_t buffer_copy(multiple_buffers, multiple_buffers,
2314 TargetIterator target_begin, TargetIterator target_end,
2315 SourceIterator source_begin, SourceIterator source_end,
2316 std::size_t max_bytes_to_copy) BOOST_ASIO_NOEXCEPT
2317{
2318 std::size_t total_bytes_copied = 0;
2319
2320 TargetIterator target_iter = target_begin;
2321 std::size_t target_buffer_offset = 0;
2322
2323 SourceIterator source_iter = source_begin;
2324 std::size_t source_buffer_offset = 0;
2325
2326 while (total_bytes_copied != max_bytes_to_copy
2327 && target_iter != target_end && source_iter != source_end)
2328 {
2329 mutable_buffer target_buffer =
2330 mutable_buffer(*target_iter) + target_buffer_offset;
2331
2332 const_buffer source_buffer =
2333 const_buffer(*source_iter) + source_buffer_offset;
2334
2335 std::size_t bytes_copied = (buffer_copy_1)(
2336 target_buffer, boost::asio::buffer(source_buffer,
2337 max_bytes_to_copy - total_bytes_copied));
2338 total_bytes_copied += bytes_copied;
2339
2340 if (bytes_copied == target_buffer.size())
2341 {
2342 ++target_iter;
2343 target_buffer_offset = 0;
2344 }
2345 else
2346 target_buffer_offset += bytes_copied;
2347
2348 if (bytes_copied == source_buffer.size())
2349 {
2350 ++source_iter;
2351 source_buffer_offset = 0;
2352 }
2353 else
2354 source_buffer_offset += bytes_copied;
2355 }
2356
2357 return total_bytes_copied;
2358}
2359
2360} // namespace detail
2361
2362/// Copies bytes from a source buffer sequence to a target buffer sequence.
2363/**
2364 * @param target A modifiable buffer sequence representing the memory regions to
2365 * which the bytes will be copied.
2366 *
2367 * @param source A non-modifiable buffer sequence representing the memory
2368 * regions from which the bytes will be copied.
2369 *
2370 * @returns The number of bytes copied.
2371 *
2372 * @note The number of bytes copied is the lesser of:
2373 *
2374 * @li @c buffer_size(target)
2375 *
2376 * @li @c buffer_size(source)
2377 *
2378 * This function is implemented in terms of @c memcpy, and consequently it
2379 * cannot be used to copy between overlapping memory regions.
2380 */
2381template <typename MutableBufferSequence, typename ConstBufferSequence>
2382inline std::size_t buffer_copy(const MutableBufferSequence& target,
2383 const ConstBufferSequence& source) BOOST_ASIO_NOEXCEPT
2384{
2385 return detail::buffer_copy(
2386 detail::buffer_sequence_cardinality<MutableBufferSequence>(),
2387 detail::buffer_sequence_cardinality<ConstBufferSequence>(),
2388 boost::asio::buffer_sequence_begin(target),
2389 boost::asio::buffer_sequence_end(target),
2390 boost::asio::buffer_sequence_begin(source),
2391 boost::asio::buffer_sequence_end(source));
2392}
2393
2394/// Copies a limited number of bytes from a source buffer sequence to a target
2395/// buffer sequence.
2396/**
2397 * @param target A modifiable buffer sequence representing the memory regions to
2398 * which the bytes will be copied.
2399 *
2400 * @param source A non-modifiable buffer sequence representing the memory
2401 * regions from which the bytes will be copied.
2402 *
2403 * @param max_bytes_to_copy The maximum number of bytes to be copied.
2404 *
2405 * @returns The number of bytes copied.
2406 *
2407 * @note The number of bytes copied is the lesser of:
2408 *
2409 * @li @c buffer_size(target)
2410 *
2411 * @li @c buffer_size(source)
2412 *
2413 * @li @c max_bytes_to_copy
2414 *
2415 * This function is implemented in terms of @c memcpy, and consequently it
2416 * cannot be used to copy between overlapping memory regions.
2417 */
2418template <typename MutableBufferSequence, typename ConstBufferSequence>
2419inline std::size_t buffer_copy(const MutableBufferSequence& target,
2420 const ConstBufferSequence& source,
2421 std::size_t max_bytes_to_copy) BOOST_ASIO_NOEXCEPT
2422{
2423 return detail::buffer_copy(
2424 detail::buffer_sequence_cardinality<MutableBufferSequence>(),
2425 detail::buffer_sequence_cardinality<ConstBufferSequence>(),
2426 boost::asio::buffer_sequence_begin(target),
2427 boost::asio::buffer_sequence_end(target),
2428 boost::asio::buffer_sequence_begin(source),
2429 boost::asio::buffer_sequence_end(source), max_bytes_to_copy);
2430}
2431
2432/*@}*/
2433
2434} // namespace asio
2435} // namespace boost
2436
92f5a8d4
TL
2437#include <boost/asio/detail/pop_options.hpp>
2438#include <boost/asio/detail/is_buffer_sequence.hpp>
2439#include <boost/asio/detail/push_options.hpp>
2440
2441namespace boost {
2442namespace asio {
2443
2444/// Trait to determine whether a type satisfies the MutableBufferSequence
2445/// requirements.
2446template <typename T>
2447struct is_mutable_buffer_sequence
2448#if defined(GENERATING_DOCUMENTATION)
2449 : integral_constant<bool, automatically_determined>
2450#else // defined(GENERATING_DOCUMENTATION)
2451 : boost::asio::detail::is_buffer_sequence<T, mutable_buffer>
2452#endif // defined(GENERATING_DOCUMENTATION)
2453{
2454};
2455
2456/// Trait to determine whether a type satisfies the ConstBufferSequence
2457/// requirements.
2458template <typename T>
2459struct is_const_buffer_sequence
2460#if defined(GENERATING_DOCUMENTATION)
2461 : integral_constant<bool, automatically_determined>
2462#else // defined(GENERATING_DOCUMENTATION)
2463 : boost::asio::detail::is_buffer_sequence<T, const_buffer>
2464#endif // defined(GENERATING_DOCUMENTATION)
2465{
2466};
2467
2468#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
2469/// Trait to determine whether a type satisfies the DynamicBuffer_v1
2470/// requirements.
2471template <typename T>
2472struct is_dynamic_buffer_v1
2473#if defined(GENERATING_DOCUMENTATION)
2474 : integral_constant<bool, automatically_determined>
2475#else // defined(GENERATING_DOCUMENTATION)
2476 : boost::asio::detail::is_dynamic_buffer_v1<T>
2477#endif // defined(GENERATING_DOCUMENTATION)
2478{
2479};
2480#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
2481
2482/// Trait to determine whether a type satisfies the DynamicBuffer_v2
2483/// requirements.
2484template <typename T>
2485struct is_dynamic_buffer_v2
2486#if defined(GENERATING_DOCUMENTATION)
2487 : integral_constant<bool, automatically_determined>
2488#else // defined(GENERATING_DOCUMENTATION)
2489 : boost::asio::detail::is_dynamic_buffer_v2<T>
2490#endif // defined(GENERATING_DOCUMENTATION)
2491{
2492};
2493
2494/// Trait to determine whether a type satisfies the DynamicBuffer requirements.
2495/**
2496 * If @c BOOST_ASIO_NO_DYNAMIC_BUFFER_V1 is not defined, determines whether the
2497 * type satisfies the DynamicBuffer_v1 requirements. Otherwise, if @c
2498 * BOOST_ASIO_NO_DYNAMIC_BUFFER_V1 is defined, determines whether the type
2499 * satisfies the DynamicBuffer_v2 requirements.
2500 */
2501template <typename T>
2502struct is_dynamic_buffer
2503#if defined(GENERATING_DOCUMENTATION)
2504 : integral_constant<bool, automatically_determined>
2505#elif defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
2506 : boost::asio::is_dynamic_buffer_v2<T>
2507#else // defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
2508 : boost::asio::is_dynamic_buffer_v1<T>
2509#endif // defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
2510{
2511};
2512
2513} // namespace asio
2514} // namespace boost
2515
b32b8144
FG
2516#include <boost/asio/detail/pop_options.hpp>
2517
2518#endif // BOOST_ASIO_BUFFER_HPP