Clementine
buffer.hpp
1 //
2 // buffer.hpp
3 // ~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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 ASIO_BUFFER_HPP
12 #define 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 "asio/detail/config.hpp"
19 #include <cstddef>
20 #include <cstring>
21 #include <limits>
22 #include <stdexcept>
23 #include <string>
24 #include <vector>
25 #include "asio/detail/array_fwd.hpp"
26 #include "asio/detail/memory.hpp"
27 #include "asio/detail/string_view.hpp"
28 #include "asio/detail/throw_exception.hpp"
29 #include "asio/detail/type_traits.hpp"
30 
31 #if defined(ASIO_MSVC) && (ASIO_MSVC >= 1700)
32 # if defined(_HAS_ITERATOR_DEBUGGING) && (_HAS_ITERATOR_DEBUGGING != 0)
33 # if !defined(ASIO_DISABLE_BUFFER_DEBUGGING)
34 # define ASIO_ENABLE_BUFFER_DEBUGGING
35 # endif // !defined(ASIO_DISABLE_BUFFER_DEBUGGING)
36 # endif // defined(_HAS_ITERATOR_DEBUGGING)
37 #endif // defined(ASIO_MSVC) && (ASIO_MSVC >= 1700)
38 
39 #if defined(__GNUC__)
40 # if defined(_GLIBCXX_DEBUG)
41 # if !defined(ASIO_DISABLE_BUFFER_DEBUGGING)
42 # define ASIO_ENABLE_BUFFER_DEBUGGING
43 # endif // !defined(ASIO_DISABLE_BUFFER_DEBUGGING)
44 # endif // defined(_GLIBCXX_DEBUG)
45 #endif // defined(__GNUC__)
46 
47 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
48 # include "asio/detail/functional.hpp"
49 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
50 
51 #if defined(ASIO_HAS_BOOST_WORKAROUND)
52 # include <boost/detail/workaround.hpp>
53 # if !defined(__clang__)
54 # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
55 # define ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND
56 # endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
57 # elif BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
58 # define ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND
59 # endif // BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
60 #endif // defined(ASIO_HAS_BOOST_WORKAROUND)
61 
62 #if defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)
63 # include "asio/detail/type_traits.hpp"
64 #endif // defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)
65 
66 #include "asio/detail/push_options.hpp"
67 
68 namespace asio {
69 
70 class mutable_buffer;
71 class const_buffer;
72 
74 
93 {
94 public:
96  mutable_buffer() ASIO_NOEXCEPT
97  : data_(0),
98  size_(0)
99  {
100  }
101 
103  mutable_buffer(void* data, std::size_t size) ASIO_NOEXCEPT
104  : data_(data),
105  size_(size)
106  {
107  }
108 
109 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
110  mutable_buffer(void* data, std::size_t size,
111  asio::detail::function<void()> debug_check)
112  : data_(data),
113  size_(size),
114  debug_check_(debug_check)
115  {
116  }
117 
118  const asio::detail::function<void()>& get_debug_check() const
119  {
120  return debug_check_;
121  }
122 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
123 
125  void* data() const ASIO_NOEXCEPT
126  {
127 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
128  if (size_ && debug_check_)
129  debug_check_();
130 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
131  return data_;
132  }
133 
135  std::size_t size() const ASIO_NOEXCEPT
136  {
137  return size_;
138  }
139 
141  mutable_buffer& operator+=(std::size_t n) ASIO_NOEXCEPT
142  {
143  std::size_t offset = n < size_ ? n : size_;
144  data_ = static_cast<char*>(data_) + offset;
145  size_ -= offset;
146  return *this;
147  }
148 
149 private:
150  void* data_;
151  std::size_t size_;
152 
153 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
154  asio::detail::function<void()> debug_check_;
155 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
156 };
157 
158 #if !defined(ASIO_NO_DEPRECATED)
159 
163  : public mutable_buffer
164 {
165 public:
168 
171 
173  mutable_buffers_1(void* data, std::size_t size) ASIO_NOEXCEPT
174  : mutable_buffer(data, size)
175  {
176  }
177 
178 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
179  mutable_buffers_1(void* data, std::size_t size,
180  asio::detail::function<void()> debug_check)
181  : mutable_buffer(data, size, debug_check)
182  {
183  }
184 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
185 
187  explicit mutable_buffers_1(const mutable_buffer& b) ASIO_NOEXCEPT
188  : mutable_buffer(b)
189  {
190  }
191 
193  const_iterator begin() const ASIO_NOEXCEPT
194  {
195  return this;
196  }
197 
199  const_iterator end() const ASIO_NOEXCEPT
200  {
201  return begin() + 1;
202  }
203 };
204 
205 #endif // !defined(ASIO_NO_DEPRECATED)
206 
208 
227 {
228 public:
230  const_buffer() ASIO_NOEXCEPT
231  : data_(0),
232  size_(0)
233  {
234  }
235 
237  const_buffer(const void* data, std::size_t size) ASIO_NOEXCEPT
238  : data_(data),
239  size_(size)
240  {
241  }
242 
244  const_buffer(const mutable_buffer& b) ASIO_NOEXCEPT
245  : data_(b.data()),
246  size_(b.size())
247 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
248  , debug_check_(b.get_debug_check())
249 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
250  {
251  }
252 
253 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
254  const_buffer(const void* data, std::size_t size,
255  asio::detail::function<void()> debug_check)
256  : data_(data),
257  size_(size),
258  debug_check_(debug_check)
259  {
260  }
261 
262  const asio::detail::function<void()>& get_debug_check() const
263  {
264  return debug_check_;
265  }
266 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
267 
269  const void* data() const ASIO_NOEXCEPT
270  {
271 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
272  if (size_ && debug_check_)
273  debug_check_();
274 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
275  return data_;
276  }
277 
279  std::size_t size() const ASIO_NOEXCEPT
280  {
281  return size_;
282  }
283 
285  const_buffer& operator+=(std::size_t n) ASIO_NOEXCEPT
286  {
287  std::size_t offset = n < size_ ? n : size_;
288  data_ = static_cast<const char*>(data_) + offset;
289  size_ -= offset;
290  return *this;
291  }
292 
293 private:
294  const void* data_;
295  std::size_t size_;
296 
297 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
298  asio::detail::function<void()> debug_check_;
299 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
300 };
301 
302 #if !defined(ASIO_NO_DEPRECATED)
303 
307  : public const_buffer
308 {
309 public:
312 
314  typedef const const_buffer* const_iterator;
315 
317  const_buffers_1(const void* data, std::size_t size) ASIO_NOEXCEPT
318  : const_buffer(data, size)
319  {
320  }
321 
322 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
323  const_buffers_1(const void* data, std::size_t size,
324  asio::detail::function<void()> debug_check)
325  : const_buffer(data, size, debug_check)
326  {
327  }
328 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
329 
331  explicit const_buffers_1(const const_buffer& b) ASIO_NOEXCEPT
332  : const_buffer(b)
333  {
334  }
335 
337  const_iterator begin() const ASIO_NOEXCEPT
338  {
339  return this;
340  }
341 
343  const_iterator end() const ASIO_NOEXCEPT
344  {
345  return begin() + 1;
346  }
347 };
348 
349 #endif // !defined(ASIO_NO_DEPRECATED)
350 
355 {
356 public:
359 
362 
364  const_iterator begin() const ASIO_NOEXCEPT
365  {
366  return &buf_;
367  }
368 
370  const_iterator end() const ASIO_NOEXCEPT
371  {
372  return &buf_;
373  }
374 
375 private:
376  mutable_buffer buf_;
377 };
378 
385 
387 template <typename MutableBuffer>
388 inline const mutable_buffer* buffer_sequence_begin(const MutableBuffer& b,
389  typename enable_if<
390  is_convertible<const MutableBuffer*, const mutable_buffer*>::value
391  >::type* = 0) ASIO_NOEXCEPT
392 {
393  return static_cast<const mutable_buffer*>(detail::addressof(b));
394 }
395 
397 template <typename ConstBuffer>
398 inline const const_buffer* buffer_sequence_begin(const ConstBuffer& b,
399  typename enable_if<
400  is_convertible<const ConstBuffer*, const const_buffer*>::value
401  >::type* = 0) ASIO_NOEXCEPT
402 {
403  return static_cast<const const_buffer*>(detail::addressof(b));
404 }
405 
406 #if defined(ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)
407 
409 template <typename C>
410 inline auto buffer_sequence_begin(C& c,
411  typename enable_if<
412  !is_convertible<const C*, const mutable_buffer*>::value
413  && !is_convertible<const C*, const const_buffer*>::value
414  >::type* = 0) ASIO_NOEXCEPT -> decltype(c.begin())
415 {
416  return c.begin();
417 }
418 
420 template <typename C>
421 inline auto buffer_sequence_begin(const C& c,
422  typename enable_if<
423  !is_convertible<const C*, const mutable_buffer*>::value
424  && !is_convertible<const C*, const const_buffer*>::value
425  >::type* = 0) ASIO_NOEXCEPT -> decltype(c.begin())
426 {
427  return c.begin();
428 }
429 
430 #else // defined(ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)
431 
432 template <typename C>
433 inline typename C::iterator buffer_sequence_begin(C& c,
434  typename enable_if<
435  !is_convertible<const C*, const mutable_buffer*>::value
436  && !is_convertible<const C*, const const_buffer*>::value
437  >::type* = 0) ASIO_NOEXCEPT
438 {
439  return c.begin();
440 }
441 
442 template <typename C>
443 inline typename C::const_iterator buffer_sequence_begin(const C& c,
444  typename enable_if<
445  !is_convertible<const C*, const mutable_buffer*>::value
446  && !is_convertible<const C*, const const_buffer*>::value
447  >::type* = 0) ASIO_NOEXCEPT
448 {
449  return c.begin();
450 }
451 
452 #endif // defined(ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)
453 
462 
464 template <typename MutableBuffer>
465 inline const mutable_buffer* buffer_sequence_end(const MutableBuffer& b,
466  typename enable_if<
467  is_convertible<const MutableBuffer*, const mutable_buffer*>::value
468  >::type* = 0) ASIO_NOEXCEPT
469 {
470  return static_cast<const mutable_buffer*>(detail::addressof(b)) + 1;
471 }
472 
474 template <typename ConstBuffer>
475 inline const const_buffer* buffer_sequence_end(const ConstBuffer& b,
476  typename enable_if<
477  is_convertible<const ConstBuffer*, const const_buffer*>::value
478  >::type* = 0) ASIO_NOEXCEPT
479 {
480  return static_cast<const const_buffer*>(detail::addressof(b)) + 1;
481 }
482 
483 #if defined(ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)
484 
486 template <typename C>
487 inline auto buffer_sequence_end(C& c,
488  typename enable_if<
489  !is_convertible<const C*, const mutable_buffer*>::value
490  && !is_convertible<const C*, const const_buffer*>::value
491  >::type* = 0) ASIO_NOEXCEPT -> decltype(c.end())
492 {
493  return c.end();
494 }
495 
497 template <typename C>
498 inline auto buffer_sequence_end(const C& c,
499  typename enable_if<
500  !is_convertible<const C*, const mutable_buffer*>::value
501  && !is_convertible<const C*, const const_buffer*>::value
502  >::type* = 0) ASIO_NOEXCEPT -> decltype(c.end())
503 {
504  return c.end();
505 }
506 
507 #else // defined(ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)
508 
509 template <typename C>
510 inline typename C::iterator buffer_sequence_end(C& c,
511  typename enable_if<
512  !is_convertible<const C*, const mutable_buffer*>::value
513  && !is_convertible<const C*, const const_buffer*>::value
514  >::type* = 0) ASIO_NOEXCEPT
515 {
516  return c.end();
517 }
518 
519 template <typename C>
520 inline typename C::const_iterator buffer_sequence_end(const C& c,
521  typename enable_if<
522  !is_convertible<const C*, const mutable_buffer*>::value
523  && !is_convertible<const C*, const const_buffer*>::value
524  >::type* = 0) ASIO_NOEXCEPT
525 {
526  return c.end();
527 }
528 
529 #endif // defined(ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)
530 
533 namespace detail {
534 
535 // Tag types used to select appropriately optimised overloads.
536 struct one_buffer {};
538 
539 // Helper trait to detect single buffers.
540 template <typename BufferSequence>
542  conditional<
543  is_same<BufferSequence, mutable_buffer>::value
544 #if !defined(ASIO_NO_DEPRECATED)
545  || is_same<BufferSequence, mutable_buffers_1>::value
546  || is_same<BufferSequence, const_buffers_1>::value
547 #endif // !defined(ASIO_NO_DEPRECATED)
548  || is_same<BufferSequence, const_buffer>::value,
549  one_buffer, multiple_buffers>::type {};
550 
551 template <typename Iterator>
552 inline std::size_t buffer_size(one_buffer,
553  Iterator begin, Iterator) ASIO_NOEXCEPT
554 {
555  return const_buffer(*begin).size();
556 }
557 
558 template <typename Iterator>
559 inline std::size_t buffer_size(multiple_buffers,
560  Iterator begin, Iterator end) ASIO_NOEXCEPT
561 {
562  std::size_t total_buffer_size = 0;
563 
564  Iterator iter = begin;
565  for (; iter != end; ++iter)
566  {
567  const_buffer b(*iter);
568  total_buffer_size += b.size();
569  }
570 
571  return total_buffer_size;
572 }
573 
574 } // namespace detail
575 
577 
594 template <typename BufferSequence>
595 inline std::size_t buffer_size(const BufferSequence& b) ASIO_NOEXCEPT
596 {
597  return detail::buffer_size(
599  asio::buffer_sequence_begin(b),
600  asio::buffer_sequence_end(b));
601 }
602 
603 #if !defined(ASIO_NO_DEPRECATED)
604 
627 
629 template <typename PointerToPodType>
630 inline PointerToPodType buffer_cast(const mutable_buffer& b) ASIO_NOEXCEPT
631 {
632  return static_cast<PointerToPodType>(b.data());
633 }
634 
636 template <typename PointerToPodType>
637 inline PointerToPodType buffer_cast(const const_buffer& b) ASIO_NOEXCEPT
638 {
639  return static_cast<PointerToPodType>(b.data());
640 }
641 
644 #endif // !defined(ASIO_NO_DEPRECATED)
645 
647 
651  std::size_t n) ASIO_NOEXCEPT
652 {
653  std::size_t offset = n < b.size() ? n : b.size();
654  char* new_data = static_cast<char*>(b.data()) + offset;
655  std::size_t new_size = b.size() - offset;
656  return mutable_buffer(new_data, new_size
657 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
658  , b.get_debug_check()
659 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
660  );
661 }
662 
664 
667 inline mutable_buffer operator+(std::size_t n,
668  const mutable_buffer& b) ASIO_NOEXCEPT
669 {
670  return b + n;
671 }
672 
674 
678  std::size_t n) ASIO_NOEXCEPT
679 {
680  std::size_t offset = n < b.size() ? n : b.size();
681  const char* new_data = static_cast<const char*>(b.data()) + offset;
682  std::size_t new_size = b.size() - offset;
683  return const_buffer(new_data, new_size
684 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
685  , b.get_debug_check()
686 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
687  );
688 }
689 
691 
694 inline const_buffer operator+(std::size_t n,
695  const const_buffer& b) ASIO_NOEXCEPT
696 {
697  return b + n;
698 }
699 
700 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
701 namespace detail {
702 
703 template <typename Iterator>
704 class buffer_debug_check
705 {
706 public:
707  buffer_debug_check(Iterator iter)
708  : iter_(iter)
709  {
710  }
711 
712  ~buffer_debug_check()
713  {
714 #if defined(ASIO_MSVC) && (ASIO_MSVC == 1400)
715  // MSVC 8's string iterator checking may crash in a std::string::iterator
716  // object's destructor when the iterator points to an already-destroyed
717  // std::string object, unless the iterator is cleared first.
718  iter_ = Iterator();
719 #endif // defined(ASIO_MSVC) && (ASIO_MSVC == 1400)
720  }
721 
722  void operator()()
723  {
724  (void)*iter_;
725  }
726 
727 private:
728  Iterator iter_;
729 };
730 
731 } // namespace detail
732 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
733 
896 
897 #if defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
898 # define ASIO_MUTABLE_BUFFER mutable_buffer
899 # define ASIO_CONST_BUFFER const_buffer
900 #else // defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
901 # define ASIO_MUTABLE_BUFFER mutable_buffers_1
902 # define ASIO_CONST_BUFFER const_buffers_1
903 #endif // defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
904 
906 
909 inline ASIO_MUTABLE_BUFFER buffer(
910  const mutable_buffer& b) ASIO_NOEXCEPT
911 {
912  return ASIO_MUTABLE_BUFFER(b);
913 }
914 
916 
922 inline ASIO_MUTABLE_BUFFER buffer(const mutable_buffer& b,
923  std::size_t max_size_in_bytes) ASIO_NOEXCEPT
924 {
925  return ASIO_MUTABLE_BUFFER(
926  mutable_buffer(b.data(),
927  b.size() < max_size_in_bytes
928  ? b.size() : max_size_in_bytes
929 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
930  , b.get_debug_check()
931 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
932  ));
933 }
934 
936 
939 inline ASIO_CONST_BUFFER buffer(
940  const const_buffer& b) ASIO_NOEXCEPT
941 {
942  return ASIO_CONST_BUFFER(b);
943 }
944 
946 
952 inline ASIO_CONST_BUFFER buffer(const const_buffer& b,
953  std::size_t max_size_in_bytes) ASIO_NOEXCEPT
954 {
955  return ASIO_CONST_BUFFER(b.data(),
956  b.size() < max_size_in_bytes
957  ? b.size() : max_size_in_bytes
958 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
959  , b.get_debug_check()
960 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
961  );
962 }
963 
965 
968 inline ASIO_MUTABLE_BUFFER buffer(void* data,
969  std::size_t size_in_bytes) ASIO_NOEXCEPT
970 {
971  return ASIO_MUTABLE_BUFFER(data, size_in_bytes);
972 }
973 
975 
978 inline ASIO_CONST_BUFFER buffer(const void* data,
979  std::size_t size_in_bytes) ASIO_NOEXCEPT
980 {
981  return ASIO_CONST_BUFFER(data, size_in_bytes);
982 }
983 
985 
991 template <typename PodType, std::size_t N>
992 inline ASIO_MUTABLE_BUFFER buffer(PodType (&data)[N]) ASIO_NOEXCEPT
993 {
994  return ASIO_MUTABLE_BUFFER(data, N * sizeof(PodType));
995 }
996 
998 
1004 template <typename PodType, std::size_t N>
1005 inline ASIO_MUTABLE_BUFFER buffer(PodType (&data)[N],
1006  std::size_t max_size_in_bytes) ASIO_NOEXCEPT
1007 {
1008  return ASIO_MUTABLE_BUFFER(data,
1009  N * sizeof(PodType) < max_size_in_bytes
1010  ? N * sizeof(PodType) : max_size_in_bytes);
1011 }
1012 
1014 
1020 template <typename PodType, std::size_t N>
1021 inline ASIO_CONST_BUFFER buffer(
1022  const PodType (&data)[N]) ASIO_NOEXCEPT
1023 {
1024  return ASIO_CONST_BUFFER(data, N * sizeof(PodType));
1025 }
1026 
1028 
1034 template <typename PodType, std::size_t N>
1035 inline ASIO_CONST_BUFFER buffer(const PodType (&data)[N],
1036  std::size_t max_size_in_bytes) ASIO_NOEXCEPT
1037 {
1038  return ASIO_CONST_BUFFER(data,
1039  N * sizeof(PodType) < max_size_in_bytes
1040  ? N * sizeof(PodType) : max_size_in_bytes);
1041 }
1042 
1043 #if defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)
1044 
1045 // Borland C++ and Sun Studio think the overloads:
1046 //
1047 // unspecified buffer(boost::array<PodType, N>& array ...);
1048 //
1049 // and
1050 //
1051 // unspecified buffer(boost::array<const PodType, N>& array ...);
1052 //
1053 // are ambiguous. This will be worked around by using a buffer_types traits
1054 // class that contains typedefs for the appropriate buffer and container
1055 // classes, based on whether PodType is const or non-const.
1056 
1057 namespace detail {
1058 
1059 template <bool IsConst>
1060 struct buffer_types_base;
1061 
1062 template <>
1063 struct buffer_types_base<false>
1064 {
1065  typedef mutable_buffer buffer_type;
1066  typedef ASIO_MUTABLE_BUFFER container_type;
1067 };
1068 
1069 template <>
1070 struct buffer_types_base<true>
1071 {
1072  typedef const_buffer buffer_type;
1073  typedef ASIO_CONST_BUFFER container_type;
1074 };
1075 
1076 template <typename PodType>
1077 struct buffer_types
1078  : public buffer_types_base<is_const<PodType>::value>
1079 {
1080 };
1081 
1082 } // namespace detail
1083 
1084 template <typename PodType, std::size_t N>
1085 inline typename detail::buffer_types<PodType>::container_type
1086 buffer(boost::array<PodType, N>& data) ASIO_NOEXCEPT
1087 {
1088  typedef typename asio::detail::buffer_types<PodType>::buffer_type
1089  buffer_type;
1090  typedef typename asio::detail::buffer_types<PodType>::container_type
1091  container_type;
1092  return container_type(
1093  buffer_type(data.c_array(), data.size() * sizeof(PodType)));
1094 }
1095 
1096 template <typename PodType, std::size_t N>
1097 inline typename detail::buffer_types<PodType>::container_type
1099  std::size_t max_size_in_bytes) ASIO_NOEXCEPT
1100 {
1101  typedef typename asio::detail::buffer_types<PodType>::buffer_type
1102  buffer_type;
1103  typedef typename asio::detail::buffer_types<PodType>::container_type
1104  container_type;
1105  return container_type(
1106  buffer_type(data.c_array(),
1107  data.size() * sizeof(PodType) < max_size_in_bytes
1108  ? data.size() * sizeof(PodType) : max_size_in_bytes));
1109 }
1110 
1111 #else // defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)
1112 
1114 
1120 template <typename PodType, std::size_t N>
1121 inline ASIO_MUTABLE_BUFFER buffer(
1122  boost::array<PodType, N>& data) ASIO_NOEXCEPT
1123 {
1124  return ASIO_MUTABLE_BUFFER(
1125  data.c_array(), data.size() * sizeof(PodType));
1126 }
1127 
1129 
1135 template <typename PodType, std::size_t N>
1136 inline ASIO_MUTABLE_BUFFER buffer(boost::array<PodType, N>& data,
1137  std::size_t max_size_in_bytes) ASIO_NOEXCEPT
1138 {
1139  return ASIO_MUTABLE_BUFFER(data.c_array(),
1140  data.size() * sizeof(PodType) < max_size_in_bytes
1141  ? data.size() * sizeof(PodType) : max_size_in_bytes);
1142 }
1143 
1145 
1151 template <typename PodType, std::size_t N>
1152 inline ASIO_CONST_BUFFER buffer(
1153  boost::array<const PodType, N>& data) ASIO_NOEXCEPT
1154 {
1155  return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));
1156 }
1157 
1159 
1165 template <typename PodType, std::size_t N>
1166 inline ASIO_CONST_BUFFER buffer(boost::array<const PodType, N>& data,
1167  std::size_t max_size_in_bytes) ASIO_NOEXCEPT
1168 {
1169  return ASIO_CONST_BUFFER(data.data(),
1170  data.size() * sizeof(PodType) < max_size_in_bytes
1171  ? data.size() * sizeof(PodType) : max_size_in_bytes);
1172 }
1173 
1174 #endif // defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)
1175 
1177 
1183 template <typename PodType, std::size_t N>
1184 inline ASIO_CONST_BUFFER buffer(
1185  const boost::array<PodType, N>& data) ASIO_NOEXCEPT
1186 {
1187  return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));
1188 }
1189 
1191 
1197 template <typename PodType, std::size_t N>
1198 inline ASIO_CONST_BUFFER buffer(const boost::array<PodType, N>& data,
1199  std::size_t max_size_in_bytes) ASIO_NOEXCEPT
1200 {
1201  return ASIO_CONST_BUFFER(data.data(),
1202  data.size() * sizeof(PodType) < max_size_in_bytes
1203  ? data.size() * sizeof(PodType) : max_size_in_bytes);
1204 }
1205 
1206 #if defined(ASIO_HAS_STD_ARRAY) || defined(GENERATING_DOCUMENTATION)
1207 
1209 
1215 template <typename PodType, std::size_t N>
1216 inline ASIO_MUTABLE_BUFFER buffer(
1217  std::array<PodType, N>& data) ASIO_NOEXCEPT
1218 {
1219  return ASIO_MUTABLE_BUFFER(data.data(), data.size() * sizeof(PodType));
1220 }
1221 
1223 
1229 template <typename PodType, std::size_t N>
1230 inline ASIO_MUTABLE_BUFFER buffer(std::array<PodType, N>& data,
1231  std::size_t max_size_in_bytes) ASIO_NOEXCEPT
1232 {
1233  return ASIO_MUTABLE_BUFFER(data.data(),
1234  data.size() * sizeof(PodType) < max_size_in_bytes
1235  ? data.size() * sizeof(PodType) : max_size_in_bytes);
1236 }
1237 
1239 
1245 template <typename PodType, std::size_t N>
1246 inline ASIO_CONST_BUFFER buffer(
1247  std::array<const PodType, N>& data) ASIO_NOEXCEPT
1248 {
1249  return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));
1250 }
1251 
1253 
1259 template <typename PodType, std::size_t N>
1260 inline ASIO_CONST_BUFFER buffer(std::array<const PodType, N>& data,
1261  std::size_t max_size_in_bytes) ASIO_NOEXCEPT
1262 {
1263  return ASIO_CONST_BUFFER(data.data(),
1264  data.size() * sizeof(PodType) < max_size_in_bytes
1265  ? data.size() * sizeof(PodType) : max_size_in_bytes);
1266 }
1267 
1269 
1275 template <typename PodType, std::size_t N>
1276 inline ASIO_CONST_BUFFER buffer(
1277  const std::array<PodType, N>& data) ASIO_NOEXCEPT
1278 {
1279  return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));
1280 }
1281 
1283 
1289 template <typename PodType, std::size_t N>
1290 inline ASIO_CONST_BUFFER buffer(const std::array<PodType, N>& data,
1291  std::size_t max_size_in_bytes) ASIO_NOEXCEPT
1292 {
1293  return ASIO_CONST_BUFFER(data.data(),
1294  data.size() * sizeof(PodType) < max_size_in_bytes
1295  ? data.size() * sizeof(PodType) : max_size_in_bytes);
1296 }
1297 
1298 #endif // defined(ASIO_HAS_STD_ARRAY) || defined(GENERATING_DOCUMENTATION)
1299 
1301 
1310 template <typename PodType, typename Allocator>
1311 inline ASIO_MUTABLE_BUFFER buffer(
1312  std::vector<PodType, Allocator>& data) ASIO_NOEXCEPT
1313 {
1314  return ASIO_MUTABLE_BUFFER(
1315  data.size() ? &data[0] : 0, data.size() * sizeof(PodType)
1316 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
1317  , detail::buffer_debug_check<
1318  typename std::vector<PodType, Allocator>::iterator
1319  >(data.begin())
1320 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
1321  );
1322 }
1323 
1325 
1334 template <typename PodType, typename Allocator>
1335 inline ASIO_MUTABLE_BUFFER buffer(std::vector<PodType, Allocator>& data,
1336  std::size_t max_size_in_bytes) ASIO_NOEXCEPT
1337 {
1338  return ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0,
1339  data.size() * sizeof(PodType) < max_size_in_bytes
1340  ? data.size() * sizeof(PodType) : max_size_in_bytes
1341 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
1342  , detail::buffer_debug_check<
1343  typename std::vector<PodType, Allocator>::iterator
1344  >(data.begin())
1345 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
1346  );
1347 }
1348 
1350 
1359 template <typename PodType, typename Allocator>
1360 inline ASIO_CONST_BUFFER buffer(
1361  const std::vector<PodType, Allocator>& data) ASIO_NOEXCEPT
1362 {
1363  return ASIO_CONST_BUFFER(
1364  data.size() ? &data[0] : 0, data.size() * sizeof(PodType)
1365 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
1366  , detail::buffer_debug_check<
1367  typename std::vector<PodType, Allocator>::const_iterator
1368  >(data.begin())
1369 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
1370  );
1371 }
1372 
1374 
1383 template <typename PodType, typename Allocator>
1384 inline ASIO_CONST_BUFFER buffer(
1385  const std::vector<PodType, Allocator>& data,
1386  std::size_t max_size_in_bytes) ASIO_NOEXCEPT
1387 {
1388  return ASIO_CONST_BUFFER(data.size() ? &data[0] : 0,
1389  data.size() * sizeof(PodType) < max_size_in_bytes
1390  ? data.size() * sizeof(PodType) : max_size_in_bytes
1391 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
1392  , detail::buffer_debug_check<
1393  typename std::vector<PodType, Allocator>::const_iterator
1394  >(data.begin())
1395 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
1396  );
1397 }
1398 
1400 
1407 template <typename Elem, typename Traits, typename Allocator>
1408 inline ASIO_MUTABLE_BUFFER buffer(
1409  std::basic_string<Elem, Traits, Allocator>& data) ASIO_NOEXCEPT
1410 {
1411  return ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0,
1412  data.size() * sizeof(Elem)
1413 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
1414  , detail::buffer_debug_check<
1415  typename std::basic_string<Elem, Traits, Allocator>::iterator
1416  >(data.begin())
1417 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
1418  );
1419 }
1420 
1422 
1431 template <typename Elem, typename Traits, typename Allocator>
1432 inline ASIO_MUTABLE_BUFFER buffer(
1433  std::basic_string<Elem, Traits, Allocator>& data,
1434  std::size_t max_size_in_bytes) ASIO_NOEXCEPT
1435 {
1436  return ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0,
1437  data.size() * sizeof(Elem) < max_size_in_bytes
1438  ? data.size() * sizeof(Elem) : max_size_in_bytes
1439 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
1440  , detail::buffer_debug_check<
1441  typename std::basic_string<Elem, Traits, Allocator>::iterator
1442  >(data.begin())
1443 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
1444  );
1445 }
1446 
1448 
1454 template <typename Elem, typename Traits, typename Allocator>
1455 inline ASIO_CONST_BUFFER buffer(
1456  const std::basic_string<Elem, Traits, Allocator>& data) ASIO_NOEXCEPT
1457 {
1458  return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(Elem)
1459 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
1460  , detail::buffer_debug_check<
1461  typename std::basic_string<Elem, Traits, Allocator>::const_iterator
1462  >(data.begin())
1463 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
1464  );
1465 }
1466 
1468 
1477 template <typename Elem, typename Traits, typename Allocator>
1478 inline ASIO_CONST_BUFFER buffer(
1479  const std::basic_string<Elem, Traits, Allocator>& data,
1480  std::size_t max_size_in_bytes) ASIO_NOEXCEPT
1481 {
1482  return ASIO_CONST_BUFFER(data.data(),
1483  data.size() * sizeof(Elem) < max_size_in_bytes
1484  ? data.size() * sizeof(Elem) : max_size_in_bytes
1485 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
1486  , detail::buffer_debug_check<
1487  typename std::basic_string<Elem, Traits, Allocator>::const_iterator
1488  >(data.begin())
1489 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
1490  );
1491 }
1492 
1493 #if defined(ASIO_HAS_STRING_VIEW) \
1494  || defined(GENERATING_DOCUMENTATION)
1495 
1497 
1501 template <typename Elem, typename Traits>
1502 inline ASIO_CONST_BUFFER buffer(
1503  basic_string_view<Elem, Traits> data) ASIO_NOEXCEPT
1504 {
1505  return ASIO_CONST_BUFFER(data.size() ? &data[0] : 0,
1506  data.size() * sizeof(Elem)
1507 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
1508  , detail::buffer_debug_check<
1509  typename basic_string_view<Elem, Traits>::iterator
1510  >(data.begin())
1511 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
1512  );
1513 }
1514 
1516 
1522 template <typename Elem, typename Traits>
1523 inline ASIO_CONST_BUFFER buffer(
1525  std::size_t max_size_in_bytes) ASIO_NOEXCEPT
1526 {
1527  return ASIO_CONST_BUFFER(data.size() ? &data[0] : 0,
1528  data.size() * sizeof(Elem) < max_size_in_bytes
1529  ? data.size() * sizeof(Elem) : max_size_in_bytes
1530 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
1531  , detail::buffer_debug_check<
1532  typename basic_string_view<Elem, Traits>::iterator
1533  >(data.begin())
1534 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
1535  );
1536 }
1537 
1538 #endif // defined(ASIO_HAS_STRING_VIEW)
1539  // || defined(GENERATING_DOCUMENTATION)
1540 
1543 
1547 template <typename Elem, typename Traits, typename Allocator>
1549 {
1550 public:
1553  typedef ASIO_CONST_BUFFER const_buffers_type;
1554 
1557  typedef ASIO_MUTABLE_BUFFER mutable_buffers_type;
1558 
1560 
1571  explicit dynamic_string_buffer(std::basic_string<Elem, Traits, Allocator>& s,
1572  std::size_t maximum_size =
1573  (std::numeric_limits<std::size_t>::max)()) ASIO_NOEXCEPT
1574  : string_(s),
1575 #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1576  size_((std::numeric_limits<std::size_t>::max)()),
1577 #endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1578  max_size_(maximum_size)
1579  {
1580  }
1581 
1583  dynamic_string_buffer(const dynamic_string_buffer& other) ASIO_NOEXCEPT
1584  : string_(other.string_),
1585 #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1586  size_(other.size_),
1587 #endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1588  max_size_(other.max_size_)
1589  {
1590  }
1591 
1592 #if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
1593  dynamic_string_buffer(dynamic_string_buffer&& other) ASIO_NOEXCEPT
1595  : string_(other.string_),
1596 #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1597  size_(other.size_),
1598 #endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1599  max_size_(other.max_size_)
1600  {
1601  }
1602 #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
1603 
1606 
1611  std::size_t size() const ASIO_NOEXCEPT
1612  {
1613 #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1614  if (size_ != (std::numeric_limits<std::size_t>::max)())
1615  return size_;
1616 #endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1617  return (std::min)(string_.size(), max_size());
1618  }
1619 
1621 
1624  std::size_t max_size() const ASIO_NOEXCEPT
1625  {
1626  return max_size_;
1627  }
1628 
1631 
1635  std::size_t capacity() const ASIO_NOEXCEPT
1636  {
1637  return (std::min)(string_.capacity(), max_size());
1638  }
1639 
1640 #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1641 
1651  const_buffers_type data() const ASIO_NOEXCEPT
1652  {
1653  return const_buffers_type(asio::buffer(string_, size_));
1654  }
1655 #endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1656 
1659 
1672  mutable_buffers_type data(std::size_t pos, std::size_t n) ASIO_NOEXCEPT
1673  {
1674  return mutable_buffers_type(asio::buffer(
1675  asio::buffer(string_, max_size_) + pos, n));
1676  }
1677 
1680 
1690  const_buffers_type data(std::size_t pos,
1691  std::size_t n) const ASIO_NOEXCEPT
1692  {
1693  return const_buffers_type(asio::buffer(
1694  asio::buffer(string_, max_size_) + pos, n));
1695  }
1696 
1697 #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1698 
1714  mutable_buffers_type prepare(std::size_t n)
1715  {
1716  if (size() > max_size() || max_size() - size() < n)
1717  {
1718  std::length_error ex("dynamic_string_buffer too long");
1719  asio::detail::throw_exception(ex);
1720  }
1721 
1722  if (size_ == (std::numeric_limits<std::size_t>::max)())
1723  size_ = string_.size(); // Enable v1 behaviour.
1724 
1725  string_.resize(size_ + n);
1726 
1727  return asio::buffer(asio::buffer(string_) + size_, n);
1728  }
1729 
1732 
1743  void commit(std::size_t n)
1744  {
1745  size_ += (std::min)(n, string_.size() - size_);
1746  string_.resize(size_);
1747  }
1748 #endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1749 
1752 
1757  void grow(std::size_t n)
1758  {
1759  if (size() > max_size() || max_size() - size() < n)
1760  {
1761  std::length_error ex("dynamic_string_buffer too long");
1762  asio::detail::throw_exception(ex);
1763  }
1764 
1765  string_.resize(size() + n);
1766  }
1767 
1770 
1775  void shrink(std::size_t n)
1776  {
1777  string_.resize(n > size() ? 0 : size() - n);
1778  }
1779 
1783 
1792  void consume(std::size_t n)
1793  {
1794 #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1795  if (size_ != (std::numeric_limits<std::size_t>::max)())
1796  {
1797  std::size_t consume_length = (std::min)(n, size_);
1798  string_.erase(0, consume_length);
1799  size_ -= consume_length;
1800  return;
1801  }
1802 #endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1803  string_.erase(0, n);
1804  }
1805 
1806 private:
1807  std::basic_string<Elem, Traits, Allocator>& string_;
1808 #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1809  std::size_t size_;
1810 #endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1811  const std::size_t max_size_;
1812 };
1813 
1815 
1818 template <typename Elem, typename Allocator>
1820 {
1821 public:
1824  typedef ASIO_CONST_BUFFER const_buffers_type;
1825 
1828  typedef ASIO_MUTABLE_BUFFER mutable_buffers_type;
1829 
1831 
1839  explicit dynamic_vector_buffer(std::vector<Elem, Allocator>& v,
1840  std::size_t maximum_size =
1841  (std::numeric_limits<std::size_t>::max)()) ASIO_NOEXCEPT
1842  : vector_(v),
1843 #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1844  size_((std::numeric_limits<std::size_t>::max)()),
1845 #endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1846  max_size_(maximum_size)
1847  {
1848  }
1849 
1851  dynamic_vector_buffer(const dynamic_vector_buffer& other) ASIO_NOEXCEPT
1852  : vector_(other.vector_),
1853 #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1854  size_(other.size_),
1855 #endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1856  max_size_(other.max_size_)
1857  {
1858  }
1859 
1860 #if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
1861  dynamic_vector_buffer(dynamic_vector_buffer&& other) ASIO_NOEXCEPT
1863  : vector_(other.vector_),
1864 #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1865  size_(other.size_),
1866 #endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1867  max_size_(other.max_size_)
1868  {
1869  }
1870 #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
1871 
1874 
1879  std::size_t size() const ASIO_NOEXCEPT
1880  {
1881 #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1882  if (size_ != (std::numeric_limits<std::size_t>::max)())
1883  return size_;
1884 #endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1885  return (std::min)(vector_.size(), max_size());
1886  }
1887 
1889 
1894  std::size_t max_size() const ASIO_NOEXCEPT
1895  {
1896  return max_size_;
1897  }
1898 
1901 
1907  std::size_t capacity() const ASIO_NOEXCEPT
1908  {
1909  return (std::min)(vector_.capacity(), max_size());
1910  }
1911 
1912 #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1913 
1924  const_buffers_type data() const ASIO_NOEXCEPT
1925  {
1926  return const_buffers_type(asio::buffer(vector_, size_));
1927  }
1928 #endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1929 
1932 
1945  mutable_buffers_type data(std::size_t pos, std::size_t n) ASIO_NOEXCEPT
1946  {
1947  return mutable_buffers_type(asio::buffer(
1948  asio::buffer(vector_, max_size_) + pos, n));
1949  }
1950 
1953 
1963  const_buffers_type data(std::size_t pos,
1964  std::size_t n) const ASIO_NOEXCEPT
1965  {
1966  return const_buffers_type(asio::buffer(
1967  asio::buffer(vector_, max_size_) + pos, n));
1968  }
1969 
1970 #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
1971 
1987  mutable_buffers_type prepare(std::size_t n)
1988  {
1989  if (size () > max_size() || max_size() - size() < n)
1990  {
1991  std::length_error ex("dynamic_vector_buffer too long");
1992  asio::detail::throw_exception(ex);
1993  }
1994 
1995  if (size_ == (std::numeric_limits<std::size_t>::max)())
1996  size_ = vector_.size(); // Enable v1 behaviour.
1997 
1998  vector_.resize(size_ + n);
1999 
2000  return asio::buffer(asio::buffer(vector_) + size_, n);
2001  }
2002 
2005 
2016  void commit(std::size_t n)
2017  {
2018  size_ += (std::min)(n, vector_.size() - size_);
2019  vector_.resize(size_);
2020  }
2021 #endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
2022 
2025 
2030  void grow(std::size_t n)
2031  {
2032  if (size() > max_size() || max_size() - size() < n)
2033  {
2034  std::length_error ex("dynamic_vector_buffer too long");
2035  asio::detail::throw_exception(ex);
2036  }
2037 
2038  vector_.resize(size() + n);
2039  }
2040 
2043 
2048  void shrink(std::size_t n)
2049  {
2050  vector_.resize(n > size() ? 0 : size() - n);
2051  }
2052 
2056 
2065  void consume(std::size_t n)
2066  {
2067 #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
2068  if (size_ != (std::numeric_limits<std::size_t>::max)())
2069  {
2070  std::size_t consume_length = (std::min)(n, size_);
2071  vector_.erase(vector_.begin(), vector_.begin() + consume_length);
2072  size_ -= consume_length;
2073  return;
2074  }
2075 #endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
2076  vector_.erase(vector_.begin(), vector_.begin() + (std::min)(size(), n));
2077  }
2078 
2079 private:
2080  std::vector<Elem, Allocator>& vector_;
2081 #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
2082  std::size_t size_;
2083 #endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
2084  const std::size_t max_size_;
2085 };
2086 
2093 
2095 
2098 template <typename Elem, typename Traits, typename Allocator>
2100  std::basic_string<Elem, Traits, Allocator>& data) ASIO_NOEXCEPT
2101 {
2103 }
2104 
2106 
2110 template <typename Elem, typename Traits, typename Allocator>
2112  std::basic_string<Elem, Traits, Allocator>& data,
2113  std::size_t max_size) ASIO_NOEXCEPT
2114 {
2116 }
2117 
2119 
2122 template <typename Elem, typename Allocator>
2124  std::vector<Elem, Allocator>& data) ASIO_NOEXCEPT
2125 {
2127 }
2128 
2130 
2133 template <typename Elem, typename Allocator>
2135  std::vector<Elem, Allocator>& data,
2136  std::size_t max_size) ASIO_NOEXCEPT
2137 {
2138  return dynamic_vector_buffer<Elem, Allocator>(data, max_size);
2139 }
2140 
2170 
2171 namespace detail {
2172 
2173 inline std::size_t buffer_copy_1(const mutable_buffer& target,
2174  const const_buffer& source)
2175 {
2176  using namespace std; // For memcpy.
2177  std::size_t target_size = target.size();
2178  std::size_t source_size = source.size();
2179  std::size_t n = target_size < source_size ? target_size : source_size;
2180  if (n > 0)
2181  memcpy(target.data(), source.data(), n);
2182  return n;
2183 }
2184 
2185 template <typename TargetIterator, typename SourceIterator>
2186 inline std::size_t buffer_copy(one_buffer, one_buffer,
2187  TargetIterator target_begin, TargetIterator,
2188  SourceIterator source_begin, SourceIterator) ASIO_NOEXCEPT
2189 {
2190  return (buffer_copy_1)(*target_begin, *source_begin);
2191 }
2192 
2193 template <typename TargetIterator, typename SourceIterator>
2194 inline std::size_t buffer_copy(one_buffer, one_buffer,
2195  TargetIterator target_begin, TargetIterator,
2196  SourceIterator source_begin, SourceIterator,
2197  std::size_t max_bytes_to_copy) ASIO_NOEXCEPT
2198 {
2199  return (buffer_copy_1)(*target_begin,
2200  asio::buffer(*source_begin, max_bytes_to_copy));
2201 }
2202 
2203 template <typename TargetIterator, typename SourceIterator>
2204 std::size_t buffer_copy(one_buffer, multiple_buffers,
2205  TargetIterator target_begin, TargetIterator,
2206  SourceIterator source_begin, SourceIterator source_end,
2207  std::size_t max_bytes_to_copy
2208  = (std::numeric_limits<std::size_t>::max)()) ASIO_NOEXCEPT
2209 {
2210  std::size_t total_bytes_copied = 0;
2211  SourceIterator source_iter = source_begin;
2212 
2213  for (mutable_buffer target_buffer(
2214  asio::buffer(*target_begin, max_bytes_to_copy));
2215  target_buffer.size() && source_iter != source_end; ++source_iter)
2216  {
2217  const_buffer source_buffer(*source_iter);
2218  std::size_t bytes_copied = (buffer_copy_1)(target_buffer, source_buffer);
2219  total_bytes_copied += bytes_copied;
2220  target_buffer += bytes_copied;
2221  }
2222 
2223  return total_bytes_copied;
2224 }
2225 
2226 template <typename TargetIterator, typename SourceIterator>
2227 std::size_t buffer_copy(multiple_buffers, one_buffer,
2228  TargetIterator target_begin, TargetIterator target_end,
2229  SourceIterator source_begin, SourceIterator,
2230  std::size_t max_bytes_to_copy
2231  = (std::numeric_limits<std::size_t>::max)()) ASIO_NOEXCEPT
2232 {
2233  std::size_t total_bytes_copied = 0;
2234  TargetIterator target_iter = target_begin;
2235 
2236  for (const_buffer source_buffer(
2237  asio::buffer(*source_begin, max_bytes_to_copy));
2238  source_buffer.size() && target_iter != target_end; ++target_iter)
2239  {
2240  mutable_buffer target_buffer(*target_iter);
2241  std::size_t bytes_copied = (buffer_copy_1)(target_buffer, source_buffer);
2242  total_bytes_copied += bytes_copied;
2243  source_buffer += bytes_copied;
2244  }
2245 
2246  return total_bytes_copied;
2247 }
2248 
2249 template <typename TargetIterator, typename SourceIterator>
2250 std::size_t buffer_copy(multiple_buffers, multiple_buffers,
2251  TargetIterator target_begin, TargetIterator target_end,
2252  SourceIterator source_begin, SourceIterator source_end) ASIO_NOEXCEPT
2253 {
2254  std::size_t total_bytes_copied = 0;
2255 
2256  TargetIterator target_iter = target_begin;
2257  std::size_t target_buffer_offset = 0;
2258 
2259  SourceIterator source_iter = source_begin;
2260  std::size_t source_buffer_offset = 0;
2261 
2262  while (target_iter != target_end && source_iter != source_end)
2263  {
2264  mutable_buffer target_buffer =
2265  mutable_buffer(*target_iter) + target_buffer_offset;
2266 
2267  const_buffer source_buffer =
2268  const_buffer(*source_iter) + source_buffer_offset;
2269 
2270  std::size_t bytes_copied = (buffer_copy_1)(target_buffer, source_buffer);
2271  total_bytes_copied += bytes_copied;
2272 
2273  if (bytes_copied == target_buffer.size())
2274  {
2275  ++target_iter;
2276  target_buffer_offset = 0;
2277  }
2278  else
2279  target_buffer_offset += bytes_copied;
2280 
2281  if (bytes_copied == source_buffer.size())
2282  {
2283  ++source_iter;
2284  source_buffer_offset = 0;
2285  }
2286  else
2287  source_buffer_offset += bytes_copied;
2288  }
2289 
2290  return total_bytes_copied;
2291 }
2292 
2293 template <typename TargetIterator, typename SourceIterator>
2294 std::size_t buffer_copy(multiple_buffers, multiple_buffers,
2295  TargetIterator target_begin, TargetIterator target_end,
2296  SourceIterator source_begin, SourceIterator source_end,
2297  std::size_t max_bytes_to_copy) ASIO_NOEXCEPT
2298 {
2299  std::size_t total_bytes_copied = 0;
2300 
2301  TargetIterator target_iter = target_begin;
2302  std::size_t target_buffer_offset = 0;
2303 
2304  SourceIterator source_iter = source_begin;
2305  std::size_t source_buffer_offset = 0;
2306 
2307  while (total_bytes_copied != max_bytes_to_copy
2308  && target_iter != target_end && source_iter != source_end)
2309  {
2310  mutable_buffer target_buffer =
2311  mutable_buffer(*target_iter) + target_buffer_offset;
2312 
2313  const_buffer source_buffer =
2314  const_buffer(*source_iter) + source_buffer_offset;
2315 
2316  std::size_t bytes_copied = (buffer_copy_1)(
2317  target_buffer, asio::buffer(source_buffer,
2318  max_bytes_to_copy - total_bytes_copied));
2319  total_bytes_copied += bytes_copied;
2320 
2321  if (bytes_copied == target_buffer.size())
2322  {
2323  ++target_iter;
2324  target_buffer_offset = 0;
2325  }
2326  else
2327  target_buffer_offset += bytes_copied;
2328 
2329  if (bytes_copied == source_buffer.size())
2330  {
2331  ++source_iter;
2332  source_buffer_offset = 0;
2333  }
2334  else
2335  source_buffer_offset += bytes_copied;
2336  }
2337 
2338  return total_bytes_copied;
2339 }
2340 
2341 } // namespace detail
2342 
2344 
2362 template <typename MutableBufferSequence, typename ConstBufferSequence>
2363 inline std::size_t buffer_copy(const MutableBufferSequence& target,
2364  const ConstBufferSequence& source) ASIO_NOEXCEPT
2365 {
2366  return detail::buffer_copy(
2369  asio::buffer_sequence_begin(target),
2370  asio::buffer_sequence_end(target),
2371  asio::buffer_sequence_begin(source),
2372  asio::buffer_sequence_end(source));
2373 }
2374 
2377 
2399 template <typename MutableBufferSequence, typename ConstBufferSequence>
2400 inline std::size_t buffer_copy(const MutableBufferSequence& target,
2401  const ConstBufferSequence& source,
2402  std::size_t max_bytes_to_copy) ASIO_NOEXCEPT
2403 {
2404  return detail::buffer_copy(
2407  asio::buffer_sequence_begin(target),
2408  asio::buffer_sequence_end(target),
2409  asio::buffer_sequence_begin(source),
2410  asio::buffer_sequence_end(source), max_bytes_to_copy);
2411 }
2412 
2415 } // namespace asio
2416 
2417 #include "asio/detail/pop_options.hpp"
2418 #include "asio/detail/is_buffer_sequence.hpp"
2419 #include "asio/detail/push_options.hpp"
2420 
2421 namespace asio {
2422 
2425 template <typename T>
2427 #if defined(GENERATING_DOCUMENTATION)
2428  : integral_constant<bool, automatically_determined>
2429 #else // defined(GENERATING_DOCUMENTATION)
2430  : asio::detail::is_buffer_sequence<T, mutable_buffer>
2431 #endif // defined(GENERATING_DOCUMENTATION)
2432 {
2433 };
2434 
2437 template <typename T>
2439 #if defined(GENERATING_DOCUMENTATION)
2440  : integral_constant<bool, automatically_determined>
2441 #else // defined(GENERATING_DOCUMENTATION)
2442  : asio::detail::is_buffer_sequence<T, const_buffer>
2443 #endif // defined(GENERATING_DOCUMENTATION)
2444 {
2445 };
2446 
2447 #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
2448 template <typename T>
2452 #if defined(GENERATING_DOCUMENTATION)
2453  : integral_constant<bool, automatically_determined>
2454 #else // defined(GENERATING_DOCUMENTATION)
2456 #endif // defined(GENERATING_DOCUMENTATION)
2457 {
2458 };
2459 #endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
2460 
2463 template <typename T>
2465 #if defined(GENERATING_DOCUMENTATION)
2466  : integral_constant<bool, automatically_determined>
2467 #else // defined(GENERATING_DOCUMENTATION)
2469 #endif // defined(GENERATING_DOCUMENTATION)
2470 {
2471 };
2472 
2474 
2480 template <typename T>
2482 #if defined(GENERATING_DOCUMENTATION)
2483  : integral_constant<bool, automatically_determined>
2484 #elif defined(ASIO_NO_DYNAMIC_BUFFER_V1)
2486 #else // defined(ASIO_NO_DYNAMIC_BUFFER_V1)
2488 #endif // defined(ASIO_NO_DYNAMIC_BUFFER_V1)
2489 {
2490 };
2491 
2492 } // namespace asio
2493 
2494 #include "asio/detail/pop_options.hpp"
2495 
2496 #endif // ASIO_BUFFER_HPP
const_iterator begin() const ASIO_NOEXCEPT
Get a random-access iterator to the first element.
Definition: buffer.hpp:337
dynamic_vector_buffer(std::vector< Elem, Allocator > &v, std::size_t maximum_size=(std::numeric_limits< std::size_t >::max)()) ASIO_NOEXCEPT
Construct a dynamic buffer from a vector.
Definition: buffer.hpp:1839
const_buffer operator+(const const_buffer &b, std::size_t n) ASIO_NOEXCEPT
Create a new non-modifiable buffer that is offset from the start of another.
Definition: buffer.hpp:677
const_iterator end() const ASIO_NOEXCEPT
Get a random-access iterator for one past the last element.
Definition: buffer.hpp:199
void commit(std::size_t n)
DynamicBuffer_v1: Move bytes from the output sequence to the input sequence.
Definition: buffer.hpp:1743
const_buffer() ASIO_NOEXCEPT
Construct an empty buffer.
Definition: buffer.hpp:230
mutable_buffer() ASIO_NOEXCEPT
Construct an empty buffer.
Definition: buffer.hpp:96
mutable_buffers_1(const mutable_buffer &b) ASIO_NOEXCEPT
Construct to represent a single modifiable buffer.
Definition: buffer.hpp:187
Definition: buffer.hpp:537
void consume(std::size_t n)
DynamicBuffer_v1: Remove characters from the input sequence.
Definition: buffer.hpp:2065
const_iterator begin() const ASIO_NOEXCEPT
Get a random-access iterator to the first element.
Definition: buffer.hpp:364
const void * data() const ASIO_NOEXCEPT
Get a pointer to the beginning of the memory range.
Definition: buffer.hpp:269
Holds a buffer that cannot be modified.
Definition: buffer.hpp:226
mutable_buffers_type prepare(std::size_t n)
DynamicBuffer_v1: Get a list of buffers that represents the output sequence, with the given size...
Definition: buffer.hpp:1987
Definition: blocking.hpp:208
mutable_buffer & operator+=(std::size_t n) ASIO_NOEXCEPT
Move the start of the buffer by the specified number of bytes.
Definition: buffer.hpp:141
const_buffers_type data(std::size_t pos, std::size_t n) const ASIO_NOEXCEPT
DynamicBuffer_v2: Get a sequence of buffers that represents the underlying memory.
Definition: buffer.hpp:1963
const_buffers_1(const const_buffer &b) ASIO_NOEXCEPT
Construct to represent a single non-modifiable buffer.
Definition: buffer.hpp:331
Trait to determine whether a type satisfies the DynamicBuffer requirements.
Definition: buffer.hpp:2481
mutable_buffers_1(void *data, std::size_t size) ASIO_NOEXCEPT
Construct to represent a given memory range.
Definition: buffer.hpp:173
mutable_buffer value_type
The type for each element in the list of buffers.
Definition: buffer.hpp:167
const_buffer(const mutable_buffer &b) ASIO_NOEXCEPT
Construct a non-modifiable buffer from a modifiable one.
Definition: buffer.hpp:244
mutable_buffer operator+(std::size_t n, const mutable_buffer &b) ASIO_NOEXCEPT
Create a new modifiable buffer that is offset from the start of another.
Definition: buffer.hpp:667
Definition: awaitable.hpp:421
const_iterator begin() const ASIO_NOEXCEPT
Get a random-access iterator to the first element.
Definition: buffer.hpp:193
dynamic_vector_buffer< Elem, Allocator > dynamic_buffer(std::vector< Elem, Allocator > &data, std::size_t max_size) ASIO_NOEXCEPT
Create a new dynamic buffer that represents the given vector.
Definition: buffer.hpp:2134
std::size_t capacity() const ASIO_NOEXCEPT
Get the maximum size that the buffer may grow to without triggering reallocation. ...
Definition: buffer.hpp:1907
const_buffers_1(const void *data, std::size_t size) ASIO_NOEXCEPT
Construct to represent a given memory range.
Definition: buffer.hpp:317
const_buffer value_type
The type for each element in the list of buffers.
Definition: buffer.hpp:311
void shrink(std::size_t n)
DynamicBuffer_v2: Shrink the underlying memory by the specified number of bytes.
Definition: buffer.hpp:1775
const_buffers_type data() const ASIO_NOEXCEPT
DynamicBuffer_v1: Get a list of buffers that represents the input sequence.
Definition: buffer.hpp:1651
ASIO_CONST_BUFFER buffer(const std::basic_string< Elem, Traits, Allocator > &data, std::size_t max_size_in_bytes) ASIO_NOEXCEPT
Create a new non-modifiable buffer that represents the given string.
Definition: buffer.hpp:1478
mutable_buffer operator+(const mutable_buffer &b, std::size_t n) ASIO_NOEXCEPT
Create a new modifiable buffer that is offset from the start of another.
Definition: buffer.hpp:650
std::size_t capacity() const ASIO_NOEXCEPT
Get the maximum size that the buffer may grow to without triggering reallocation. ...
Definition: buffer.hpp:1635
std::size_t max_size() const ASIO_NOEXCEPT
Get the maximum size of the dynamic buffer.
Definition: buffer.hpp:1894
const mutable_buffer * const_iterator
A random-access iterator type that may be used to read elements.
Definition: buffer.hpp:361
const_iterator end() const ASIO_NOEXCEPT
Get a random-access iterator for one past the last element.
Definition: buffer.hpp:370
Adapt a vector to the DynamicBuffer requirements.
Definition: buffer.hpp:1819
(Deprecated: Use const_buffer.) Adapts a single non-modifiable buffer so that it meets the requiremen...
Definition: buffer.hpp:306
PointerToPodType buffer_cast(const const_buffer &b) ASIO_NOEXCEPT
Cast a non-modifiable buffer to a specified pointer to POD type.
Definition: buffer.hpp:637
std::size_t size() const ASIO_NOEXCEPT
Get the size of the memory range.
Definition: buffer.hpp:279
const_buffer operator+(std::size_t n, const const_buffer &b) ASIO_NOEXCEPT
Create a new non-modifiable buffer that is offset from the start of another.
Definition: buffer.hpp:694
mutable_buffers_type data(std::size_t pos, std::size_t n) ASIO_NOEXCEPT
DynamicBuffer_v2: Get a sequence of buffers that represents the underlying memory.
Definition: buffer.hpp:1945
void grow(std::size_t n)
DynamicBuffer_v2: Grow the underlying memory by the specified number of bytes.
Definition: buffer.hpp:1757
Definition: chrono.h:284
An implementation of std::basic_string_view for pre-C++17.
Definition: core.h:355
std::size_t buffer_copy(const MutableBufferSequence &target, const ConstBufferSequence &source, std::size_t max_bytes_to_copy) ASIO_NOEXCEPT
Copies a limited number of bytes from a source buffer sequence to a target buffer sequence...
Definition: buffer.hpp:2400
dynamic_vector_buffer(const dynamic_vector_buffer &other) ASIO_NOEXCEPT
DynamicBuffer_v2: Copy construct a dynamic buffer.
Definition: buffer.hpp:1851
Definition: is_buffer_sequence.hpp:300
Adapt a basic_string to the DynamicBuffer requirements.
Definition: buffer.hpp:1548
Definition: type_traits.hpp:97
void grow(std::size_t n)
DynamicBuffer_v2: Grow the underlying memory by the specified number of bytes.
Definition: buffer.hpp:2030
Trait to determine whether a type satisfies the MutableBufferSequence requirements.
Definition: buffer.hpp:2426
dynamic_string_buffer(std::basic_string< Elem, Traits, Allocator > &s, std::size_t maximum_size=(std::numeric_limits< std::size_t >::max)()) ASIO_NOEXCEPT
Construct a dynamic buffer from a string.
Definition: buffer.hpp:1571
void commit(std::size_t n)
DynamicBuffer_v1: Move bytes from the output sequence to the input sequence.
Definition: buffer.hpp:2016
Holds a buffer that can be modified.
Definition: buffer.hpp:92
void consume(std::size_t n)
DynamicBuffer_v1: Remove characters from the input sequence.
Definition: buffer.hpp:1792
const_iterator end() const ASIO_NOEXCEPT
Get a random-access iterator for one past the last element.
Definition: buffer.hpp:343
ASIO_MUTABLE_BUFFER mutable_buffers_type
The type used to represent a sequence of mutable buffers that refers to the underlying memory...
Definition: buffer.hpp:1557
mutable_buffer(void *data, std::size_t size) ASIO_NOEXCEPT
Construct a buffer to represent a given memory range.
Definition: buffer.hpp:103
const_buffers_type data() const ASIO_NOEXCEPT
DynamicBuffer_v1: Get a list of buffers that represents the input sequence.
Definition: buffer.hpp:1924
dynamic_string_buffer(const dynamic_string_buffer &other) ASIO_NOEXCEPT
DynamicBuffer_v2: Copy construct a dynamic buffer.
Definition: buffer.hpp:1583
Definition: is_buffer_sequence.hpp:277
std::size_t size() const ASIO_NOEXCEPT
DynamicBuffer_v1: Get the size of the input sequence.
Definition: buffer.hpp:1879
Trait to determine whether a type satisfies the DynamicBuffer_v2 requirements.
Definition: buffer.hpp:2464
const_buffers_type data(std::size_t pos, std::size_t n) const ASIO_NOEXCEPT
DynamicBuffer_v2: Get a sequence of buffers that represents the underlying memory.
Definition: buffer.hpp:1690
mutable_buffer value_type
The type for each element in the list of buffers.
Definition: buffer.hpp:358
Definition: is_buffer_sequence.hpp:230
mutable_buffers_type prepare(std::size_t n)
DynamicBuffer_v1: Get a list of buffers that represents the output sequence, with the given size...
Definition: buffer.hpp:1714
(Deprecated: Use the socket/descriptor wait() and async_wait() member functions.) An implementation o...
Definition: buffer.hpp:354
const mutable_buffer * buffer_sequence_begin(const MutableBuffer &b, typename enable_if< is_convertible< const MutableBuffer *, const mutable_buffer *>::value >::type *=0) ASIO_NOEXCEPT
Get an iterator to the first element in a buffer sequence.
Definition: buffer.hpp:388
void * data() const ASIO_NOEXCEPT
Get a pointer to the beginning of the memory range.
Definition: buffer.hpp:125
Trait to determine whether a type satisfies the ConstBufferSequence requirements. ...
Definition: buffer.hpp:2438
std::size_t size() const ASIO_NOEXCEPT
Get the size of the memory range.
Definition: buffer.hpp:135
const mutable_buffer * buffer_sequence_end(const MutableBuffer &b, typename enable_if< is_convertible< const MutableBuffer *, const mutable_buffer *>::value >::type *=0) ASIO_NOEXCEPT
Get an iterator to one past the end element in a buffer sequence.
Definition: buffer.hpp:465
ASIO_CONST_BUFFER const_buffers_type
The type used to represent a sequence of constant buffers that refers to the underlying memory...
Definition: buffer.hpp:1553
void shrink(std::size_t n)
DynamicBuffer_v2: Shrink the underlying memory by the specified number of bytes.
Definition: buffer.hpp:2048
std::size_t size() const ASIO_NOEXCEPT
DynamicBuffer_v1: Get the size of the input sequence.
Definition: buffer.hpp:1611
const mutable_buffer * const_iterator
A random-access iterator type that may be used to read elements.
Definition: buffer.hpp:170
const const_buffer * const_iterator
A random-access iterator type that may be used to read elements.
Definition: buffer.hpp:314
mutable_buffers_type data(std::size_t pos, std::size_t n) ASIO_NOEXCEPT
DynamicBuffer_v2: Get a sequence of buffers that represents the underlying memory.
Definition: buffer.hpp:1672
Definition: any_io_executor.hpp:28
std::size_t max_size() const ASIO_NOEXCEPT
Get the maximum size of the dynamic buffer.
Definition: buffer.hpp:1624
(Deprecated: Use mutable_buffer.) Adapts a single modifiable buffer so that it meets the requirements...
Definition: buffer.hpp:162
Definition: buffer.hpp:536
Trait to determine whether a type satisfies the DynamicBuffer_v1 requirements.
Definition: buffer.hpp:2451
Definition: array_fwd.hpp:23
const_buffer & operator+=(std::size_t n) ASIO_NOEXCEPT
Move the start of the buffer by the specified number of bytes.
Definition: buffer.hpp:285
const_buffer(const void *data, std::size_t size) ASIO_NOEXCEPT
Construct a buffer to represent a given memory range.
Definition: buffer.hpp:237
constexpr size_t size() const
Returns the string size.
Definition: core.h:399