]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | // |
2 | // buffer.hpp | |
3 | // ~~~~~~~~~~ | |
4 | // | |
f67539c2 | 5 | // Copyright (c) 2003-2020 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 | ||
68 | namespace boost { | |
69 | namespace asio { | |
70 | ||
71 | class mutable_buffer; | |
72 | class 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 | */ | |
93 | class mutable_buffer | |
94 | { | |
95 | public: | |
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 | ||
150 | private: | |
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. | |
163 | class mutable_buffers_1 | |
164 | : public mutable_buffer | |
165 | { | |
166 | public: | |
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 | */ | |
227 | class const_buffer | |
228 | { | |
229 | public: | |
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 | ||
294 | private: | |
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. | |
307 | class const_buffers_1 | |
308 | : public const_buffer | |
309 | { | |
310 | public: | |
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. | |
355 | class null_buffers | |
356 | { | |
357 | public: | |
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 | ||
376 | private: | |
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 |
388 | template <typename MutableBuffer> |
389 | inline const mutable_buffer* buffer_sequence_begin(const MutableBuffer& b, | |
390 | typename enable_if< | |
391 | is_convertible<const MutableBuffer*, const mutable_buffer*>::value | |
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 |
398 | template <typename ConstBuffer> |
399 | inline const const_buffer* buffer_sequence_begin(const ConstBuffer& b, | |
400 | typename enable_if< | |
401 | is_convertible<const ConstBuffer*, const const_buffer*>::value | |
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. | |
410 | template <typename C> | |
92f5a8d4 TL |
411 | inline auto buffer_sequence_begin(C& c, |
412 | typename enable_if< | |
413 | !is_convertible<const C*, const mutable_buffer*>::value | |
414 | && !is_convertible<const C*, const const_buffer*>::value | |
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. | |
421 | template <typename C> | |
92f5a8d4 TL |
422 | inline auto buffer_sequence_begin(const C& c, |
423 | typename enable_if< | |
424 | !is_convertible<const C*, const mutable_buffer*>::value | |
425 | && !is_convertible<const C*, const const_buffer*>::value | |
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 | ||
433 | template <typename C> | |
92f5a8d4 TL |
434 | inline typename C::iterator buffer_sequence_begin(C& c, |
435 | typename enable_if< | |
436 | !is_convertible<const C*, const mutable_buffer*>::value | |
437 | && !is_convertible<const C*, const const_buffer*>::value | |
438 | >::type* = 0) BOOST_ASIO_NOEXCEPT | |
b32b8144 FG |
439 | { |
440 | return c.begin(); | |
441 | } | |
442 | ||
443 | template <typename C> | |
92f5a8d4 TL |
444 | inline typename C::const_iterator buffer_sequence_begin(const C& c, |
445 | typename enable_if< | |
446 | !is_convertible<const C*, const mutable_buffer*>::value | |
447 | && !is_convertible<const C*, const const_buffer*>::value | |
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 |
465 | template <typename MutableBuffer> |
466 | inline const mutable_buffer* buffer_sequence_end(const MutableBuffer& b, | |
467 | typename enable_if< | |
468 | is_convertible<const MutableBuffer*, const mutable_buffer*>::value | |
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 |
475 | template <typename ConstBuffer> |
476 | inline const const_buffer* buffer_sequence_end(const ConstBuffer& b, | |
477 | typename enable_if< | |
478 | is_convertible<const ConstBuffer*, const const_buffer*>::value | |
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. | |
487 | template <typename C> | |
92f5a8d4 TL |
488 | inline auto buffer_sequence_end(C& c, |
489 | typename enable_if< | |
490 | !is_convertible<const C*, const mutable_buffer*>::value | |
491 | && !is_convertible<const C*, const const_buffer*>::value | |
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. | |
498 | template <typename C> | |
92f5a8d4 TL |
499 | inline auto buffer_sequence_end(const C& c, |
500 | typename enable_if< | |
501 | !is_convertible<const C*, const mutable_buffer*>::value | |
502 | && !is_convertible<const C*, const const_buffer*>::value | |
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 | ||
510 | template <typename C> | |
92f5a8d4 TL |
511 | inline typename C::iterator buffer_sequence_end(C& c, |
512 | typename enable_if< | |
513 | !is_convertible<const C*, const mutable_buffer*>::value | |
514 | && !is_convertible<const C*, const const_buffer*>::value | |
515 | >::type* = 0) BOOST_ASIO_NOEXCEPT | |
b32b8144 FG |
516 | { |
517 | return c.end(); | |
518 | } | |
519 | ||
520 | template <typename C> | |
92f5a8d4 TL |
521 | inline typename C::const_iterator buffer_sequence_end(const C& c, |
522 | typename enable_if< | |
523 | !is_convertible<const C*, const mutable_buffer*>::value | |
524 | && !is_convertible<const C*, const const_buffer*>::value | |
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 | ||
534 | namespace detail { | |
535 | ||
536 | // Tag types used to select appropriately optimised overloads. | |
537 | struct one_buffer {}; | |
538 | struct multiple_buffers {}; | |
539 | ||
540 | // Helper trait to detect single buffers. | |
541 | template <typename BufferSequence> | |
542 | struct 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 | ||
552 | template <typename Iterator> | |
553 | inline std::size_t buffer_size(one_buffer, | |
554 | Iterator begin, Iterator) BOOST_ASIO_NOEXCEPT | |
555 | { | |
556 | return const_buffer(*begin).size(); | |
557 | } | |
558 | ||
559 | template <typename Iterator> | |
560 | inline 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 | */ | |
595 | template <typename BufferSequence> | |
596 | inline 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. | |
630 | template <typename PointerToPodType> | |
631 | inline 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. | |
637 | template <typename PointerToPodType> | |
638 | inline 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 | */ | |
651 | inline 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 | */ | |
668 | inline 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 | */ | |
678 | inline 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 | */ | |
695 | inline 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) | |
702 | namespace detail { | |
703 | ||
704 | template <typename Iterator> | |
705 | class buffer_debug_check | |
706 | { | |
707 | public: | |
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 | ||
728 | private: | |
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 | */ | |
910 | inline BOOST_ASIO_MUTABLE_BUFFER buffer( | |
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 | */ | |
923 | inline BOOST_ASIO_MUTABLE_BUFFER buffer(const mutable_buffer& b, | |
924 | std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT | |
925 | { | |
926 | return BOOST_ASIO_MUTABLE_BUFFER( | |
927 | mutable_buffer(b.data(), | |
928 | b.size() < max_size_in_bytes | |
929 | ? b.size() : max_size_in_bytes | |
930 | #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) | |
931 | , b.get_debug_check() | |
932 | #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING | |
933 | )); | |
934 | } | |
935 | ||
936 | /// Create a new non-modifiable buffer from an existing buffer. | |
937 | /** | |
938 | * @returns <tt>const_buffer(b)</tt>. | |
939 | */ | |
940 | inline BOOST_ASIO_CONST_BUFFER buffer( | |
941 | const const_buffer& b) BOOST_ASIO_NOEXCEPT | |
942 | { | |
943 | return BOOST_ASIO_CONST_BUFFER(b); | |
944 | } | |
945 | ||
946 | /// Create a new non-modifiable buffer from an existing buffer. | |
947 | /** | |
948 | * @returns A const_buffer value equivalent to: | |
949 | * @code const_buffer( | |
950 | * b.data(), | |
951 | * min(b.size(), max_size_in_bytes)); @endcode | |
952 | */ | |
953 | inline BOOST_ASIO_CONST_BUFFER buffer(const const_buffer& b, | |
954 | std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT | |
955 | { | |
956 | return BOOST_ASIO_CONST_BUFFER(b.data(), | |
957 | b.size() < max_size_in_bytes | |
958 | ? b.size() : max_size_in_bytes | |
959 | #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) | |
960 | , b.get_debug_check() | |
961 | #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING | |
962 | ); | |
963 | } | |
964 | ||
965 | /// Create a new modifiable buffer that represents the given memory range. | |
966 | /** | |
967 | * @returns <tt>mutable_buffer(data, size_in_bytes)</tt>. | |
968 | */ | |
969 | inline BOOST_ASIO_MUTABLE_BUFFER buffer(void* data, | |
970 | std::size_t size_in_bytes) BOOST_ASIO_NOEXCEPT | |
971 | { | |
972 | return BOOST_ASIO_MUTABLE_BUFFER(data, size_in_bytes); | |
973 | } | |
974 | ||
975 | /// Create a new non-modifiable buffer that represents the given memory range. | |
976 | /** | |
977 | * @returns <tt>const_buffer(data, size_in_bytes)</tt>. | |
978 | */ | |
979 | inline BOOST_ASIO_CONST_BUFFER buffer(const void* data, | |
980 | std::size_t size_in_bytes) BOOST_ASIO_NOEXCEPT | |
981 | { | |
982 | return BOOST_ASIO_CONST_BUFFER(data, size_in_bytes); | |
983 | } | |
984 | ||
985 | /// Create a new modifiable buffer that represents the given POD array. | |
986 | /** | |
987 | * @returns A mutable_buffer value equivalent to: | |
988 | * @code mutable_buffer( | |
989 | * static_cast<void*>(data), | |
990 | * N * sizeof(PodType)); @endcode | |
991 | */ | |
992 | template <typename PodType, std::size_t N> | |
993 | inline BOOST_ASIO_MUTABLE_BUFFER buffer(PodType (&data)[N]) BOOST_ASIO_NOEXCEPT | |
994 | { | |
995 | return BOOST_ASIO_MUTABLE_BUFFER(data, N * sizeof(PodType)); | |
996 | } | |
997 | ||
998 | /// Create a new modifiable buffer that represents the given POD array. | |
999 | /** | |
1000 | * @returns A mutable_buffer value equivalent to: | |
1001 | * @code mutable_buffer( | |
1002 | * static_cast<void*>(data), | |
1003 | * min(N * sizeof(PodType), max_size_in_bytes)); @endcode | |
1004 | */ | |
1005 | template <typename PodType, std::size_t N> | |
1006 | inline BOOST_ASIO_MUTABLE_BUFFER buffer(PodType (&data)[N], | |
1007 | std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT | |
1008 | { | |
1009 | return BOOST_ASIO_MUTABLE_BUFFER(data, | |
1010 | N * sizeof(PodType) < max_size_in_bytes | |
1011 | ? N * sizeof(PodType) : max_size_in_bytes); | |
1012 | } | |
1013 | ||
1014 | /// Create a new non-modifiable buffer that represents the given POD array. | |
1015 | /** | |
1016 | * @returns A const_buffer value equivalent to: | |
1017 | * @code const_buffer( | |
1018 | * static_cast<const void*>(data), | |
1019 | * N * sizeof(PodType)); @endcode | |
1020 | */ | |
1021 | template <typename PodType, std::size_t N> | |
1022 | inline BOOST_ASIO_CONST_BUFFER buffer( | |
1023 | const PodType (&data)[N]) BOOST_ASIO_NOEXCEPT | |
1024 | { | |
1025 | return BOOST_ASIO_CONST_BUFFER(data, N * sizeof(PodType)); | |
1026 | } | |
1027 | ||
1028 | /// Create a new non-modifiable buffer that represents the given POD array. | |
1029 | /** | |
1030 | * @returns A const_buffer value equivalent to: | |
1031 | * @code const_buffer( | |
1032 | * static_cast<const void*>(data), | |
1033 | * min(N * sizeof(PodType), max_size_in_bytes)); @endcode | |
1034 | */ | |
1035 | template <typename PodType, std::size_t N> | |
1036 | inline BOOST_ASIO_CONST_BUFFER buffer(const PodType (&data)[N], | |
1037 | std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT | |
1038 | { | |
1039 | return BOOST_ASIO_CONST_BUFFER(data, | |
1040 | N * sizeof(PodType) < max_size_in_bytes | |
1041 | ? N * sizeof(PodType) : max_size_in_bytes); | |
1042 | } | |
1043 | ||
1044 | #if defined(BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND) | |
1045 | ||
1046 | // Borland C++ and Sun Studio think the overloads: | |
1047 | // | |
1048 | // unspecified buffer(boost::array<PodType, N>& array ...); | |
1049 | // | |
1050 | // and | |
1051 | // | |
1052 | // unspecified buffer(boost::array<const PodType, N>& array ...); | |
1053 | // | |
1054 | // are ambiguous. This will be worked around by using a buffer_types traits | |
1055 | // class that contains typedefs for the appropriate buffer and container | |
1056 | // classes, based on whether PodType is const or non-const. | |
1057 | ||
1058 | namespace detail { | |
1059 | ||
1060 | template <bool IsConst> | |
1061 | struct buffer_types_base; | |
1062 | ||
1063 | template <> | |
1064 | struct buffer_types_base<false> | |
1065 | { | |
1066 | typedef mutable_buffer buffer_type; | |
1067 | typedef BOOST_ASIO_MUTABLE_BUFFER container_type; | |
1068 | }; | |
1069 | ||
1070 | template <> | |
1071 | struct buffer_types_base<true> | |
1072 | { | |
1073 | typedef const_buffer buffer_type; | |
1074 | typedef BOOST_ASIO_CONST_BUFFER container_type; | |
1075 | }; | |
1076 | ||
1077 | template <typename PodType> | |
1078 | struct buffer_types | |
1079 | : public buffer_types_base<is_const<PodType>::value> | |
1080 | { | |
1081 | }; | |
1082 | ||
1083 | } // namespace detail | |
1084 | ||
1085 | template <typename PodType, std::size_t N> | |
1086 | inline typename detail::buffer_types<PodType>::container_type | |
1087 | buffer(boost::array<PodType, N>& data) BOOST_ASIO_NOEXCEPT | |
1088 | { | |
1089 | typedef typename boost::asio::detail::buffer_types<PodType>::buffer_type | |
1090 | buffer_type; | |
1091 | typedef typename boost::asio::detail::buffer_types<PodType>::container_type | |
1092 | container_type; | |
1093 | return container_type( | |
1094 | buffer_type(data.c_array(), data.size() * sizeof(PodType))); | |
1095 | } | |
1096 | ||
1097 | template <typename PodType, std::size_t N> | |
1098 | inline typename detail::buffer_types<PodType>::container_type | |
1099 | buffer(boost::array<PodType, N>& data, | |
1100 | std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT | |
1101 | { | |
1102 | typedef typename boost::asio::detail::buffer_types<PodType>::buffer_type | |
1103 | buffer_type; | |
1104 | typedef typename boost::asio::detail::buffer_types<PodType>::container_type | |
1105 | container_type; | |
1106 | return container_type( | |
1107 | buffer_type(data.c_array(), | |
1108 | data.size() * sizeof(PodType) < max_size_in_bytes | |
1109 | ? data.size() * sizeof(PodType) : max_size_in_bytes)); | |
1110 | } | |
1111 | ||
1112 | #else // defined(BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND) | |
1113 | ||
1114 | /// Create a new modifiable buffer that represents the given POD array. | |
1115 | /** | |
1116 | * @returns A mutable_buffer value equivalent to: | |
1117 | * @code mutable_buffer( | |
1118 | * data.data(), | |
1119 | * data.size() * sizeof(PodType)); @endcode | |
1120 | */ | |
1121 | template <typename PodType, std::size_t N> | |
1122 | inline BOOST_ASIO_MUTABLE_BUFFER buffer( | |
1123 | boost::array<PodType, N>& data) BOOST_ASIO_NOEXCEPT | |
1124 | { | |
1125 | return BOOST_ASIO_MUTABLE_BUFFER( | |
1126 | data.c_array(), data.size() * sizeof(PodType)); | |
1127 | } | |
1128 | ||
1129 | /// Create a new modifiable buffer that represents the given POD array. | |
1130 | /** | |
1131 | * @returns A mutable_buffer value equivalent to: | |
1132 | * @code mutable_buffer( | |
1133 | * data.data(), | |
1134 | * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode | |
1135 | */ | |
1136 | template <typename PodType, std::size_t N> | |
1137 | inline BOOST_ASIO_MUTABLE_BUFFER buffer(boost::array<PodType, N>& data, | |
1138 | std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT | |
1139 | { | |
1140 | return BOOST_ASIO_MUTABLE_BUFFER(data.c_array(), | |
1141 | data.size() * sizeof(PodType) < max_size_in_bytes | |
1142 | ? data.size() * sizeof(PodType) : max_size_in_bytes); | |
1143 | } | |
1144 | ||
1145 | /// Create a new non-modifiable buffer that represents the given POD array. | |
1146 | /** | |
1147 | * @returns A const_buffer value equivalent to: | |
1148 | * @code const_buffer( | |
1149 | * data.data(), | |
1150 | * data.size() * sizeof(PodType)); @endcode | |
1151 | */ | |
1152 | template <typename PodType, std::size_t N> | |
1153 | inline BOOST_ASIO_CONST_BUFFER buffer( | |
1154 | boost::array<const PodType, N>& data) BOOST_ASIO_NOEXCEPT | |
1155 | { | |
1156 | return BOOST_ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType)); | |
1157 | } | |
1158 | ||
1159 | /// Create a new non-modifiable buffer that represents the given POD array. | |
1160 | /** | |
1161 | * @returns A const_buffer value equivalent to: | |
1162 | * @code const_buffer( | |
1163 | * data.data(), | |
1164 | * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode | |
1165 | */ | |
1166 | template <typename PodType, std::size_t N> | |
1167 | inline BOOST_ASIO_CONST_BUFFER buffer(boost::array<const PodType, N>& data, | |
1168 | std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT | |
1169 | { | |
1170 | return BOOST_ASIO_CONST_BUFFER(data.data(), | |
1171 | data.size() * sizeof(PodType) < max_size_in_bytes | |
1172 | ? data.size() * sizeof(PodType) : max_size_in_bytes); | |
1173 | } | |
1174 | ||
1175 | #endif // defined(BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND) | |
1176 | ||
1177 | /// Create a new non-modifiable buffer that represents the given POD array. | |
1178 | /** | |
1179 | * @returns A const_buffer value equivalent to: | |
1180 | * @code const_buffer( | |
1181 | * data.data(), | |
1182 | * data.size() * sizeof(PodType)); @endcode | |
1183 | */ | |
1184 | template <typename PodType, std::size_t N> | |
1185 | inline BOOST_ASIO_CONST_BUFFER buffer( | |
1186 | const boost::array<PodType, N>& data) BOOST_ASIO_NOEXCEPT | |
1187 | { | |
1188 | return BOOST_ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType)); | |
1189 | } | |
1190 | ||
1191 | /// Create a new non-modifiable buffer that represents the given POD array. | |
1192 | /** | |
1193 | * @returns A const_buffer value equivalent to: | |
1194 | * @code const_buffer( | |
1195 | * data.data(), | |
1196 | * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode | |
1197 | */ | |
1198 | template <typename PodType, std::size_t N> | |
1199 | inline BOOST_ASIO_CONST_BUFFER buffer(const boost::array<PodType, N>& data, | |
1200 | std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT | |
1201 | { | |
1202 | return BOOST_ASIO_CONST_BUFFER(data.data(), | |
1203 | data.size() * sizeof(PodType) < max_size_in_bytes | |
1204 | ? data.size() * sizeof(PodType) : max_size_in_bytes); | |
1205 | } | |
1206 | ||
1207 | #if defined(BOOST_ASIO_HAS_STD_ARRAY) || defined(GENERATING_DOCUMENTATION) | |
1208 | ||
1209 | /// Create a new modifiable buffer that represents the given POD array. | |
1210 | /** | |
1211 | * @returns A mutable_buffer value equivalent to: | |
1212 | * @code mutable_buffer( | |
1213 | * data.data(), | |
1214 | * data.size() * sizeof(PodType)); @endcode | |
1215 | */ | |
1216 | template <typename PodType, std::size_t N> | |
1217 | inline BOOST_ASIO_MUTABLE_BUFFER buffer( | |
1218 | std::array<PodType, N>& data) BOOST_ASIO_NOEXCEPT | |
1219 | { | |
1220 | return BOOST_ASIO_MUTABLE_BUFFER(data.data(), data.size() * sizeof(PodType)); | |
1221 | } | |
1222 | ||
1223 | /// Create a new modifiable buffer that represents the given POD array. | |
1224 | /** | |
1225 | * @returns A mutable_buffer value equivalent to: | |
1226 | * @code mutable_buffer( | |
1227 | * data.data(), | |
1228 | * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode | |
1229 | */ | |
1230 | template <typename PodType, std::size_t N> | |
1231 | inline BOOST_ASIO_MUTABLE_BUFFER buffer(std::array<PodType, N>& data, | |
1232 | std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT | |
1233 | { | |
1234 | return BOOST_ASIO_MUTABLE_BUFFER(data.data(), | |
1235 | data.size() * sizeof(PodType) < max_size_in_bytes | |
1236 | ? data.size() * sizeof(PodType) : max_size_in_bytes); | |
1237 | } | |
1238 | ||
1239 | /// Create a new non-modifiable buffer that represents the given POD array. | |
1240 | /** | |
1241 | * @returns A const_buffer value equivalent to: | |
1242 | * @code const_buffer( | |
1243 | * data.data(), | |
1244 | * data.size() * sizeof(PodType)); @endcode | |
1245 | */ | |
1246 | template <typename PodType, std::size_t N> | |
1247 | inline BOOST_ASIO_CONST_BUFFER buffer( | |
1248 | std::array<const PodType, N>& data) BOOST_ASIO_NOEXCEPT | |
1249 | { | |
1250 | return BOOST_ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType)); | |
1251 | } | |
1252 | ||
1253 | /// Create a new non-modifiable buffer that represents the given POD array. | |
1254 | /** | |
1255 | * @returns A const_buffer value equivalent to: | |
1256 | * @code const_buffer( | |
1257 | * data.data(), | |
1258 | * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode | |
1259 | */ | |
1260 | template <typename PodType, std::size_t N> | |
1261 | inline BOOST_ASIO_CONST_BUFFER buffer(std::array<const PodType, N>& data, | |
1262 | std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT | |
1263 | { | |
1264 | return BOOST_ASIO_CONST_BUFFER(data.data(), | |
1265 | data.size() * sizeof(PodType) < max_size_in_bytes | |
1266 | ? data.size() * sizeof(PodType) : max_size_in_bytes); | |
1267 | } | |
1268 | ||
1269 | /// Create a new non-modifiable buffer that represents the given POD array. | |
1270 | /** | |
1271 | * @returns A const_buffer value equivalent to: | |
1272 | * @code const_buffer( | |
1273 | * data.data(), | |
1274 | * data.size() * sizeof(PodType)); @endcode | |
1275 | */ | |
1276 | template <typename PodType, std::size_t N> | |
1277 | inline BOOST_ASIO_CONST_BUFFER buffer( | |
1278 | const std::array<PodType, N>& data) BOOST_ASIO_NOEXCEPT | |
1279 | { | |
1280 | return BOOST_ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType)); | |
1281 | } | |
1282 | ||
1283 | /// Create a new non-modifiable buffer that represents the given POD array. | |
1284 | /** | |
1285 | * @returns A const_buffer value equivalent to: | |
1286 | * @code const_buffer( | |
1287 | * data.data(), | |
1288 | * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode | |
1289 | */ | |
1290 | template <typename PodType, std::size_t N> | |
1291 | inline BOOST_ASIO_CONST_BUFFER buffer(const std::array<PodType, N>& data, | |
1292 | std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT | |
1293 | { | |
1294 | return BOOST_ASIO_CONST_BUFFER(data.data(), | |
1295 | data.size() * sizeof(PodType) < max_size_in_bytes | |
1296 | ? data.size() * sizeof(PodType) : max_size_in_bytes); | |
1297 | } | |
1298 | ||
1299 | #endif // defined(BOOST_ASIO_HAS_STD_ARRAY) || defined(GENERATING_DOCUMENTATION) | |
1300 | ||
1301 | /// Create a new modifiable buffer that represents the given POD vector. | |
1302 | /** | |
1303 | * @returns A mutable_buffer value equivalent to: | |
1304 | * @code mutable_buffer( | |
1305 | * data.size() ? &data[0] : 0, | |
1306 | * data.size() * sizeof(PodType)); @endcode | |
1307 | * | |
1308 | * @note The buffer is invalidated by any vector operation that would also | |
1309 | * invalidate iterators. | |
1310 | */ | |
1311 | template <typename PodType, typename Allocator> | |
1312 | inline BOOST_ASIO_MUTABLE_BUFFER buffer( | |
1313 | std::vector<PodType, Allocator>& data) BOOST_ASIO_NOEXCEPT | |
1314 | { | |
1315 | return BOOST_ASIO_MUTABLE_BUFFER( | |
1316 | data.size() ? &data[0] : 0, data.size() * sizeof(PodType) | |
1317 | #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) | |
1318 | , detail::buffer_debug_check< | |
1319 | typename std::vector<PodType, Allocator>::iterator | |
1320 | >(data.begin()) | |
1321 | #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING | |
1322 | ); | |
1323 | } | |
1324 | ||
1325 | /// Create a new modifiable buffer that represents the given POD vector. | |
1326 | /** | |
1327 | * @returns A mutable_buffer value equivalent to: | |
1328 | * @code mutable_buffer( | |
1329 | * data.size() ? &data[0] : 0, | |
1330 | * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode | |
1331 | * | |
1332 | * @note The buffer is invalidated by any vector operation that would also | |
1333 | * invalidate iterators. | |
1334 | */ | |
1335 | template <typename PodType, typename Allocator> | |
1336 | inline BOOST_ASIO_MUTABLE_BUFFER buffer(std::vector<PodType, Allocator>& data, | |
1337 | std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT | |
1338 | { | |
1339 | return BOOST_ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0, | |
1340 | data.size() * sizeof(PodType) < max_size_in_bytes | |
1341 | ? data.size() * sizeof(PodType) : max_size_in_bytes | |
1342 | #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) | |
1343 | , detail::buffer_debug_check< | |
1344 | typename std::vector<PodType, Allocator>::iterator | |
1345 | >(data.begin()) | |
1346 | #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING | |
1347 | ); | |
1348 | } | |
1349 | ||
1350 | /// Create a new non-modifiable buffer that represents the given POD vector. | |
1351 | /** | |
1352 | * @returns A const_buffer value equivalent to: | |
1353 | * @code const_buffer( | |
1354 | * data.size() ? &data[0] : 0, | |
1355 | * data.size() * sizeof(PodType)); @endcode | |
1356 | * | |
1357 | * @note The buffer is invalidated by any vector operation that would also | |
1358 | * invalidate iterators. | |
1359 | */ | |
1360 | template <typename PodType, typename Allocator> | |
1361 | inline BOOST_ASIO_CONST_BUFFER buffer( | |
1362 | const std::vector<PodType, Allocator>& data) BOOST_ASIO_NOEXCEPT | |
1363 | { | |
1364 | return BOOST_ASIO_CONST_BUFFER( | |
1365 | data.size() ? &data[0] : 0, data.size() * sizeof(PodType) | |
1366 | #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) | |
1367 | , detail::buffer_debug_check< | |
1368 | typename std::vector<PodType, Allocator>::const_iterator | |
1369 | >(data.begin()) | |
1370 | #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING | |
1371 | ); | |
1372 | } | |
1373 | ||
1374 | /// Create a new non-modifiable buffer that represents the given POD vector. | |
1375 | /** | |
1376 | * @returns A const_buffer value equivalent to: | |
1377 | * @code const_buffer( | |
1378 | * data.size() ? &data[0] : 0, | |
1379 | * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode | |
1380 | * | |
1381 | * @note The buffer is invalidated by any vector operation that would also | |
1382 | * invalidate iterators. | |
1383 | */ | |
1384 | template <typename PodType, typename Allocator> | |
1385 | inline BOOST_ASIO_CONST_BUFFER buffer( | |
1386 | const std::vector<PodType, Allocator>& data, | |
1387 | std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT | |
1388 | { | |
1389 | return BOOST_ASIO_CONST_BUFFER(data.size() ? &data[0] : 0, | |
1390 | data.size() * sizeof(PodType) < max_size_in_bytes | |
1391 | ? data.size() * sizeof(PodType) : max_size_in_bytes | |
1392 | #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) | |
1393 | , detail::buffer_debug_check< | |
1394 | typename std::vector<PodType, Allocator>::const_iterator | |
1395 | >(data.begin()) | |
1396 | #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING | |
1397 | ); | |
1398 | } | |
1399 | ||
1400 | /// Create a new modifiable buffer that represents the given string. | |
1401 | /** | |
1402 | * @returns <tt>mutable_buffer(data.size() ? &data[0] : 0, | |
1403 | * data.size() * sizeof(Elem))</tt>. | |
1404 | * | |
1405 | * @note The buffer is invalidated by any non-const operation called on the | |
1406 | * given string object. | |
1407 | */ | |
1408 | template <typename Elem, typename Traits, typename Allocator> | |
1409 | inline BOOST_ASIO_MUTABLE_BUFFER buffer( | |
1410 | std::basic_string<Elem, Traits, Allocator>& data) BOOST_ASIO_NOEXCEPT | |
1411 | { | |
1412 | return BOOST_ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0, | |
1413 | data.size() * sizeof(Elem) | |
1414 | #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) | |
1415 | , detail::buffer_debug_check< | |
1416 | typename std::basic_string<Elem, Traits, Allocator>::iterator | |
1417 | >(data.begin()) | |
1418 | #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING | |
1419 | ); | |
1420 | } | |
1421 | ||
92f5a8d4 | 1422 | /// Create a new modifiable buffer that represents the given string. |
b32b8144 FG |
1423 | /** |
1424 | * @returns A mutable_buffer value equivalent to: | |
1425 | * @code mutable_buffer( | |
1426 | * data.size() ? &data[0] : 0, | |
1427 | * min(data.size() * sizeof(Elem), max_size_in_bytes)); @endcode | |
1428 | * | |
1429 | * @note The buffer is invalidated by any non-const operation called on the | |
1430 | * given string object. | |
1431 | */ | |
1432 | template <typename Elem, typename Traits, typename Allocator> | |
1433 | inline BOOST_ASIO_MUTABLE_BUFFER buffer( | |
1434 | std::basic_string<Elem, Traits, Allocator>& data, | |
1435 | std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT | |
1436 | { | |
1437 | return BOOST_ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0, | |
1438 | data.size() * sizeof(Elem) < max_size_in_bytes | |
1439 | ? data.size() * sizeof(Elem) : max_size_in_bytes | |
1440 | #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) | |
1441 | , detail::buffer_debug_check< | |
1442 | typename std::basic_string<Elem, Traits, Allocator>::iterator | |
1443 | >(data.begin()) | |
1444 | #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING | |
1445 | ); | |
1446 | } | |
1447 | ||
1448 | /// Create a new non-modifiable buffer that represents the given string. | |
1449 | /** | |
1450 | * @returns <tt>const_buffer(data.data(), data.size() * sizeof(Elem))</tt>. | |
1451 | * | |
1452 | * @note The buffer is invalidated by any non-const operation called on the | |
1453 | * given string object. | |
1454 | */ | |
1455 | template <typename Elem, typename Traits, typename Allocator> | |
1456 | inline BOOST_ASIO_CONST_BUFFER buffer( | |
1457 | const std::basic_string<Elem, Traits, Allocator>& data) BOOST_ASIO_NOEXCEPT | |
1458 | { | |
1459 | return BOOST_ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(Elem) | |
1460 | #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) | |
1461 | , detail::buffer_debug_check< | |
1462 | typename std::basic_string<Elem, Traits, Allocator>::const_iterator | |
1463 | >(data.begin()) | |
1464 | #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING | |
1465 | ); | |
1466 | } | |
1467 | ||
1468 | /// Create a new non-modifiable buffer that represents the given string. | |
1469 | /** | |
1470 | * @returns A const_buffer value equivalent to: | |
1471 | * @code const_buffer( | |
1472 | * data.data(), | |
1473 | * min(data.size() * sizeof(Elem), max_size_in_bytes)); @endcode | |
1474 | * | |
1475 | * @note The buffer is invalidated by any non-const operation called on the | |
1476 | * given string object. | |
1477 | */ | |
1478 | template <typename Elem, typename Traits, typename Allocator> | |
1479 | inline BOOST_ASIO_CONST_BUFFER buffer( | |
1480 | const std::basic_string<Elem, Traits, Allocator>& data, | |
1481 | std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT | |
1482 | { | |
1483 | return BOOST_ASIO_CONST_BUFFER(data.data(), | |
1484 | data.size() * sizeof(Elem) < max_size_in_bytes | |
1485 | ? data.size() * sizeof(Elem) : max_size_in_bytes | |
1486 | #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) | |
1487 | , detail::buffer_debug_check< | |
1488 | typename std::basic_string<Elem, Traits, Allocator>::const_iterator | |
1489 | >(data.begin()) | |
1490 | #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING | |
1491 | ); | |
1492 | } | |
1493 | ||
11fdf7f2 | 1494 | #if defined(BOOST_ASIO_HAS_STRING_VIEW) \ |
b32b8144 FG |
1495 | || defined(GENERATING_DOCUMENTATION) |
1496 | ||
1497 | /// Create a new modifiable buffer that represents the given string_view. | |
1498 | /** | |
1499 | * @returns <tt>mutable_buffer(data.size() ? &data[0] : 0, | |
1500 | * data.size() * sizeof(Elem))</tt>. | |
1501 | */ | |
1502 | template <typename Elem, typename Traits> | |
1503 | inline BOOST_ASIO_CONST_BUFFER buffer( | |
1504 | basic_string_view<Elem, Traits> data) BOOST_ASIO_NOEXCEPT | |
1505 | { | |
1506 | return BOOST_ASIO_CONST_BUFFER(data.size() ? &data[0] : 0, | |
1507 | data.size() * sizeof(Elem) | |
1508 | #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) | |
1509 | , detail::buffer_debug_check< | |
1510 | typename basic_string_view<Elem, Traits>::iterator | |
1511 | >(data.begin()) | |
1512 | #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING | |
1513 | ); | |
1514 | } | |
1515 | ||
1516 | /// Create a new non-modifiable buffer that represents the given string. | |
1517 | /** | |
1518 | * @returns A mutable_buffer value equivalent to: | |
1519 | * @code mutable_buffer( | |
1520 | * data.size() ? &data[0] : 0, | |
1521 | * min(data.size() * sizeof(Elem), max_size_in_bytes)); @endcode | |
1522 | */ | |
1523 | template <typename Elem, typename Traits> | |
1524 | inline BOOST_ASIO_CONST_BUFFER buffer( | |
1525 | basic_string_view<Elem, Traits> data, | |
1526 | std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT | |
1527 | { | |
1528 | return BOOST_ASIO_CONST_BUFFER(data.size() ? &data[0] : 0, | |
1529 | data.size() * sizeof(Elem) < max_size_in_bytes | |
1530 | ? data.size() * sizeof(Elem) : max_size_in_bytes | |
1531 | #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) | |
1532 | , detail::buffer_debug_check< | |
1533 | typename basic_string_view<Elem, Traits>::iterator | |
1534 | >(data.begin()) | |
1535 | #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING | |
1536 | ); | |
1537 | } | |
1538 | ||
11fdf7f2 | 1539 | #endif // defined(BOOST_ASIO_HAS_STRING_VIEW) |
b32b8144 FG |
1540 | // || defined(GENERATING_DOCUMENTATION) |
1541 | ||
1542 | /*@}*/ | |
1543 | ||
1544 | /// Adapt a basic_string to the DynamicBuffer requirements. | |
1545 | /** | |
1546 | * Requires that <tt>sizeof(Elem) == 1</tt>. | |
1547 | */ | |
1548 | template <typename Elem, typename Traits, typename Allocator> | |
1549 | class dynamic_string_buffer | |
1550 | { | |
1551 | public: | |
92f5a8d4 TL |
1552 | /// The type used to represent a sequence of constant buffers that refers to |
1553 | /// the underlying memory. | |
b32b8144 FG |
1554 | typedef BOOST_ASIO_CONST_BUFFER const_buffers_type; |
1555 | ||
92f5a8d4 TL |
1556 | /// The type used to represent a sequence of mutable buffers that refers to |
1557 | /// the underlying memory. | |
b32b8144 FG |
1558 | typedef BOOST_ASIO_MUTABLE_BUFFER mutable_buffers_type; |
1559 | ||
1560 | /// Construct a dynamic buffer from a string. | |
1561 | /** | |
1562 | * @param s The string to be used as backing storage for the dynamic buffer. | |
92f5a8d4 TL |
1563 | * The object stores a reference to the string and the user is responsible |
1564 | * for ensuring that the string object remains valid while the | |
1565 | * dynamic_string_buffer object, and copies of the object, are in use. | |
1566 | * | |
1567 | * @b DynamicBuffer_v1: Any existing data in the string is treated as the | |
1568 | * dynamic buffer's input sequence. | |
b32b8144 FG |
1569 | * |
1570 | * @param maximum_size Specifies a maximum size for the buffer, in bytes. | |
1571 | */ | |
1572 | explicit dynamic_string_buffer(std::basic_string<Elem, Traits, Allocator>& s, | |
1573 | std::size_t maximum_size = | |
1574 | (std::numeric_limits<std::size_t>::max)()) BOOST_ASIO_NOEXCEPT | |
1575 | : string_(s), | |
92f5a8d4 TL |
1576 | #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
1577 | size_((std::numeric_limits<std::size_t>::max)()), | |
1578 | #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) | |
b32b8144 FG |
1579 | max_size_(maximum_size) |
1580 | { | |
1581 | } | |
1582 | ||
92f5a8d4 TL |
1583 | /// @b DynamicBuffer_v2: Copy construct a dynamic buffer. |
1584 | dynamic_string_buffer(const dynamic_string_buffer& other) BOOST_ASIO_NOEXCEPT | |
1585 | : string_(other.string_), | |
1586 | #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) | |
1587 | size_(other.size_), | |
1588 | #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) | |
1589 | max_size_(other.max_size_) | |
1590 | { | |
1591 | } | |
1592 | ||
b32b8144 FG |
1593 | #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) |
1594 | /// Move construct a dynamic buffer. | |
1595 | dynamic_string_buffer(dynamic_string_buffer&& other) BOOST_ASIO_NOEXCEPT | |
1596 | : string_(other.string_), | |
92f5a8d4 | 1597 | #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
b32b8144 | 1598 | size_(other.size_), |
92f5a8d4 | 1599 | #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
b32b8144 FG |
1600 | max_size_(other.max_size_) |
1601 | { | |
1602 | } | |
1603 | #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) | |
1604 | ||
92f5a8d4 TL |
1605 | /// @b DynamicBuffer_v1: Get the size of the input sequence. |
1606 | /// @b DynamicBuffer_v2: Get the current size of the underlying memory. | |
1607 | /** | |
1608 | * @returns @b DynamicBuffer_v1 The current size of the input sequence. | |
1609 | * @b DynamicBuffer_v2: The current size of the underlying string if less than | |
1610 | * max_size(). Otherwise returns max_size(). | |
1611 | */ | |
b32b8144 FG |
1612 | std::size_t size() const BOOST_ASIO_NOEXCEPT |
1613 | { | |
92f5a8d4 TL |
1614 | #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
1615 | if (size_ != (std::numeric_limits<std::size_t>::max)()) | |
1616 | return size_; | |
1617 | #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) | |
1618 | return (std::min)(string_.size(), max_size()); | |
b32b8144 FG |
1619 | } |
1620 | ||
1621 | /// Get the maximum size of the dynamic buffer. | |
1622 | /** | |
92f5a8d4 | 1623 | * @returns The allowed maximum size of the underlying memory. |
b32b8144 FG |
1624 | */ |
1625 | std::size_t max_size() const BOOST_ASIO_NOEXCEPT | |
1626 | { | |
1627 | return max_size_; | |
1628 | } | |
1629 | ||
92f5a8d4 TL |
1630 | /// Get the maximum size that the buffer may grow to without triggering |
1631 | /// reallocation. | |
b32b8144 | 1632 | /** |
92f5a8d4 TL |
1633 | * @returns The current capacity of the underlying string if less than |
1634 | * max_size(). Otherwise returns max_size(). | |
b32b8144 FG |
1635 | */ |
1636 | std::size_t capacity() const BOOST_ASIO_NOEXCEPT | |
1637 | { | |
92f5a8d4 | 1638 | return (std::min)(string_.capacity(), max_size()); |
b32b8144 FG |
1639 | } |
1640 | ||
92f5a8d4 TL |
1641 | #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
1642 | /// @b DynamicBuffer_v1: Get a list of buffers that represents the input | |
1643 | /// sequence. | |
b32b8144 FG |
1644 | /** |
1645 | * @returns An object of type @c const_buffers_type that satisfies | |
1646 | * ConstBufferSequence requirements, representing the basic_string memory in | |
92f5a8d4 | 1647 | * the input sequence. |
b32b8144 FG |
1648 | * |
1649 | * @note The returned object is invalidated by any @c dynamic_string_buffer | |
92f5a8d4 | 1650 | * or @c basic_string member function that resizes or erases the string. |
b32b8144 FG |
1651 | */ |
1652 | const_buffers_type data() const BOOST_ASIO_NOEXCEPT | |
1653 | { | |
1654 | return const_buffers_type(boost::asio::buffer(string_, size_)); | |
1655 | } | |
92f5a8d4 TL |
1656 | #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
1657 | ||
1658 | /// @b DynamicBuffer_v2: Get a sequence of buffers that represents the | |
1659 | /// underlying memory. | |
1660 | /** | |
1661 | * @param pos Position of the first byte to represent in the buffer sequence | |
1662 | * | |
1663 | * @param n The number of bytes to return in the buffer sequence. If the | |
1664 | * underlying memory is shorter, the buffer sequence represents as many bytes | |
1665 | * as are available. | |
1666 | * | |
1667 | * @returns An object of type @c mutable_buffers_type that satisfies | |
1668 | * MutableBufferSequence requirements, representing the basic_string memory. | |
1669 | * | |
1670 | * @note The returned object is invalidated by any @c dynamic_string_buffer | |
1671 | * or @c basic_string member function that resizes or erases the string. | |
1672 | */ | |
1673 | mutable_buffers_type data(std::size_t pos, std::size_t n) BOOST_ASIO_NOEXCEPT | |
1674 | { | |
1675 | return mutable_buffers_type(boost::asio::buffer( | |
1676 | boost::asio::buffer(string_, max_size_) + pos, n)); | |
1677 | } | |
1678 | ||
1679 | /// @b DynamicBuffer_v2: Get a sequence of buffers that represents the | |
1680 | /// underlying memory. | |
1681 | /** | |
1682 | * @param pos Position of the first byte to represent in the buffer sequence | |
1683 | * | |
1684 | * @param n The number of bytes to return in the buffer sequence. If the | |
1685 | * underlying memory is shorter, the buffer sequence represents as many bytes | |
1686 | * as are available. | |
1687 | * | |
1688 | * @note The returned object is invalidated by any @c dynamic_string_buffer | |
1689 | * or @c basic_string member function that resizes or erases the string. | |
1690 | */ | |
1691 | const_buffers_type data(std::size_t pos, | |
1692 | std::size_t n) const BOOST_ASIO_NOEXCEPT | |
1693 | { | |
1694 | return const_buffers_type(boost::asio::buffer( | |
1695 | boost::asio::buffer(string_, max_size_) + pos, n)); | |
1696 | } | |
b32b8144 | 1697 | |
92f5a8d4 TL |
1698 | #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
1699 | /// @b DynamicBuffer_v1: Get a list of buffers that represents the output | |
1700 | /// sequence, with the given size. | |
b32b8144 FG |
1701 | /** |
1702 | * Ensures that the output sequence can accommodate @c n bytes, resizing the | |
1703 | * basic_string object as necessary. | |
1704 | * | |
1705 | * @returns An object of type @c mutable_buffers_type that satisfies | |
1706 | * MutableBufferSequence requirements, representing basic_string memory | |
1707 | * at the start of the output sequence of size @c n. | |
1708 | * | |
1709 | * @throws std::length_error If <tt>size() + n > max_size()</tt>. | |
1710 | * | |
1711 | * @note The returned object is invalidated by any @c dynamic_string_buffer | |
1712 | * or @c basic_string member function that modifies the input sequence or | |
1713 | * output sequence. | |
1714 | */ | |
1715 | mutable_buffers_type prepare(std::size_t n) | |
1716 | { | |
92f5a8d4 | 1717 | if (size() > max_size() || max_size() - size() < n) |
b32b8144 FG |
1718 | { |
1719 | std::length_error ex("dynamic_string_buffer too long"); | |
1720 | boost::asio::detail::throw_exception(ex); | |
1721 | } | |
1722 | ||
92f5a8d4 TL |
1723 | if (size_ == (std::numeric_limits<std::size_t>::max)()) |
1724 | size_ = string_.size(); // Enable v1 behaviour. | |
1725 | ||
b32b8144 FG |
1726 | string_.resize(size_ + n); |
1727 | ||
1728 | return boost::asio::buffer(boost::asio::buffer(string_) + size_, n); | |
1729 | } | |
1730 | ||
92f5a8d4 TL |
1731 | /// @b DynamicBuffer_v1: Move bytes from the output sequence to the input |
1732 | /// sequence. | |
b32b8144 FG |
1733 | /** |
1734 | * @param n The number of bytes to append from the start of the output | |
1735 | * sequence to the end of the input sequence. The remainder of the output | |
1736 | * sequence is discarded. | |
1737 | * | |
1738 | * Requires a preceding call <tt>prepare(x)</tt> where <tt>x >= n</tt>, and | |
1739 | * no intervening operations that modify the input or output sequence. | |
1740 | * | |
1741 | * @note If @c n is greater than the size of the output sequence, the entire | |
1742 | * output sequence is moved to the input sequence and no error is issued. | |
1743 | */ | |
1744 | void commit(std::size_t n) | |
1745 | { | |
1746 | size_ += (std::min)(n, string_.size() - size_); | |
1747 | string_.resize(size_); | |
1748 | } | |
92f5a8d4 TL |
1749 | #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
1750 | ||
1751 | /// @b DynamicBuffer_v2: Grow the underlying memory by the specified number of | |
1752 | /// bytes. | |
1753 | /** | |
1754 | * Resizes the string to accommodate an additional @c n bytes at the end. | |
1755 | * | |
1756 | * @throws std::length_error If <tt>size() + n > max_size()</tt>. | |
1757 | */ | |
1758 | void grow(std::size_t n) | |
1759 | { | |
1760 | if (size() > max_size() || max_size() - size() < n) | |
1761 | { | |
1762 | std::length_error ex("dynamic_string_buffer too long"); | |
1763 | boost::asio::detail::throw_exception(ex); | |
1764 | } | |
1765 | ||
1766 | string_.resize(size() + n); | |
1767 | } | |
b32b8144 | 1768 | |
92f5a8d4 TL |
1769 | /// @b DynamicBuffer_v2: Shrink the underlying memory by the specified number |
1770 | /// of bytes. | |
b32b8144 | 1771 | /** |
92f5a8d4 TL |
1772 | * Erases @c n bytes from the end of the string by resizing the basic_string |
1773 | * object. If @c n is greater than the current size of the string, the string | |
1774 | * is emptied. | |
1775 | */ | |
1776 | void shrink(std::size_t n) | |
1777 | { | |
1778 | string_.resize(n > size() ? 0 : size() - n); | |
1779 | } | |
1780 | ||
1781 | /// @b DynamicBuffer_v1: Remove characters from the input sequence. | |
1782 | /// @b DynamicBuffer_v2: Consume the specified number of bytes from the | |
1783 | /// beginning of the underlying memory. | |
1784 | /** | |
1785 | * @b DynamicBuffer_v1: Removes @c n characters from the beginning of the | |
1786 | * input sequence. @note If @c n is greater than the size of the input | |
1787 | * sequence, the entire input sequence is consumed and no error is issued. | |
b32b8144 | 1788 | * |
92f5a8d4 TL |
1789 | * @b DynamicBuffer_v2: Erases @c n bytes from the beginning of the string. |
1790 | * If @c n is greater than the current size of the string, the string is | |
1791 | * emptied. | |
b32b8144 FG |
1792 | */ |
1793 | void consume(std::size_t n) | |
1794 | { | |
92f5a8d4 TL |
1795 | #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
1796 | if (size_ != (std::numeric_limits<std::size_t>::max)()) | |
1797 | { | |
1798 | std::size_t consume_length = (std::min)(n, size_); | |
1799 | string_.erase(0, consume_length); | |
1800 | size_ -= consume_length; | |
1801 | return; | |
1802 | } | |
1803 | #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) | |
1804 | string_.erase(0, n); | |
b32b8144 FG |
1805 | } |
1806 | ||
1807 | private: | |
1808 | std::basic_string<Elem, Traits, Allocator>& string_; | |
92f5a8d4 | 1809 | #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
b32b8144 | 1810 | std::size_t size_; |
92f5a8d4 | 1811 | #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
b32b8144 FG |
1812 | const std::size_t max_size_; |
1813 | }; | |
1814 | ||
1815 | /// Adapt a vector to the DynamicBuffer requirements. | |
1816 | /** | |
1817 | * Requires that <tt>sizeof(Elem) == 1</tt>. | |
1818 | */ | |
1819 | template <typename Elem, typename Allocator> | |
1820 | class dynamic_vector_buffer | |
1821 | { | |
1822 | public: | |
92f5a8d4 TL |
1823 | /// The type used to represent a sequence of constant buffers that refers to |
1824 | /// the underlying memory. | |
b32b8144 FG |
1825 | typedef BOOST_ASIO_CONST_BUFFER const_buffers_type; |
1826 | ||
92f5a8d4 TL |
1827 | /// The type used to represent a sequence of mutable buffers that refers to |
1828 | /// the underlying memory. | |
b32b8144 FG |
1829 | typedef BOOST_ASIO_MUTABLE_BUFFER mutable_buffers_type; |
1830 | ||
92f5a8d4 | 1831 | /// Construct a dynamic buffer from a vector. |
b32b8144 FG |
1832 | /** |
1833 | * @param v The vector to be used as backing storage for the dynamic buffer. | |
92f5a8d4 TL |
1834 | * The object stores a reference to the vector and the user is responsible |
1835 | * for ensuring that the vector object remains valid while the | |
1836 | * dynamic_vector_buffer object, and copies of the object, are in use. | |
b32b8144 FG |
1837 | * |
1838 | * @param maximum_size Specifies a maximum size for the buffer, in bytes. | |
1839 | */ | |
1840 | explicit dynamic_vector_buffer(std::vector<Elem, Allocator>& v, | |
1841 | std::size_t maximum_size = | |
1842 | (std::numeric_limits<std::size_t>::max)()) BOOST_ASIO_NOEXCEPT | |
1843 | : vector_(v), | |
92f5a8d4 TL |
1844 | #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
1845 | size_((std::numeric_limits<std::size_t>::max)()), | |
1846 | #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) | |
b32b8144 FG |
1847 | max_size_(maximum_size) |
1848 | { | |
1849 | } | |
1850 | ||
92f5a8d4 TL |
1851 | /// @b DynamicBuffer_v2: Copy construct a dynamic buffer. |
1852 | dynamic_vector_buffer(const dynamic_vector_buffer& other) BOOST_ASIO_NOEXCEPT | |
1853 | : vector_(other.vector_), | |
1854 | #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) | |
1855 | size_(other.size_), | |
1856 | #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) | |
1857 | max_size_(other.max_size_) | |
1858 | { | |
1859 | } | |
1860 | ||
b32b8144 FG |
1861 | #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) |
1862 | /// Move construct a dynamic buffer. | |
1863 | dynamic_vector_buffer(dynamic_vector_buffer&& other) BOOST_ASIO_NOEXCEPT | |
1864 | : vector_(other.vector_), | |
92f5a8d4 | 1865 | #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
b32b8144 | 1866 | size_(other.size_), |
92f5a8d4 | 1867 | #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
b32b8144 FG |
1868 | max_size_(other.max_size_) |
1869 | { | |
1870 | } | |
1871 | #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) | |
1872 | ||
92f5a8d4 TL |
1873 | /// @b DynamicBuffer_v1: Get the size of the input sequence. |
1874 | /// @b DynamicBuffer_v2: Get the current size of the underlying memory. | |
1875 | /** | |
1876 | * @returns @b DynamicBuffer_v1 The current size of the input sequence. | |
1877 | * @b DynamicBuffer_v2: The current size of the underlying vector if less than | |
1878 | * max_size(). Otherwise returns max_size(). | |
1879 | */ | |
b32b8144 FG |
1880 | std::size_t size() const BOOST_ASIO_NOEXCEPT |
1881 | { | |
92f5a8d4 TL |
1882 | #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
1883 | if (size_ != (std::numeric_limits<std::size_t>::max)()) | |
1884 | return size_; | |
1885 | #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) | |
1886 | return (std::min)(vector_.size(), max_size()); | |
b32b8144 FG |
1887 | } |
1888 | ||
1889 | /// Get the maximum size of the dynamic buffer. | |
1890 | /** | |
92f5a8d4 TL |
1891 | * @returns @b DynamicBuffer_v1: The allowed maximum of the sum of the sizes |
1892 | * of the input sequence and output sequence. @b DynamicBuffer_v2: The allowed | |
1893 | * maximum size of the underlying memory. | |
b32b8144 FG |
1894 | */ |
1895 | std::size_t max_size() const BOOST_ASIO_NOEXCEPT | |
1896 | { | |
1897 | return max_size_; | |
1898 | } | |
1899 | ||
92f5a8d4 TL |
1900 | /// Get the maximum size that the buffer may grow to without triggering |
1901 | /// reallocation. | |
b32b8144 | 1902 | /** |
92f5a8d4 TL |
1903 | * @returns @b DynamicBuffer_v1: The current total capacity of the buffer, |
1904 | * i.e. for both the input sequence and output sequence. @b DynamicBuffer_v2: | |
1905 | * The current capacity of the underlying vector if less than max_size(). | |
1906 | * Otherwise returns max_size(). | |
b32b8144 FG |
1907 | */ |
1908 | std::size_t capacity() const BOOST_ASIO_NOEXCEPT | |
1909 | { | |
92f5a8d4 | 1910 | return (std::min)(vector_.capacity(), max_size()); |
b32b8144 FG |
1911 | } |
1912 | ||
92f5a8d4 TL |
1913 | #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
1914 | /// @b DynamicBuffer_v1: Get a list of buffers that represents the input | |
1915 | /// sequence. | |
b32b8144 FG |
1916 | /** |
1917 | * @returns An object of type @c const_buffers_type that satisfies | |
92f5a8d4 | 1918 | * ConstBufferSequence requirements, representing the vector memory in the |
b32b8144 FG |
1919 | * input sequence. |
1920 | * | |
1921 | * @note The returned object is invalidated by any @c dynamic_vector_buffer | |
92f5a8d4 TL |
1922 | * or @c vector member function that modifies the input sequence or output |
1923 | * sequence. | |
b32b8144 FG |
1924 | */ |
1925 | const_buffers_type data() const BOOST_ASIO_NOEXCEPT | |
1926 | { | |
1927 | return const_buffers_type(boost::asio::buffer(vector_, size_)); | |
1928 | } | |
92f5a8d4 | 1929 | #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
b32b8144 | 1930 | |
92f5a8d4 TL |
1931 | /// @b DynamicBuffer_v2: Get a sequence of buffers that represents the |
1932 | /// underlying memory. | |
1933 | /** | |
1934 | * @param pos Position of the first byte to represent in the buffer sequence | |
1935 | * | |
1936 | * @param n The number of bytes to return in the buffer sequence. If the | |
1937 | * underlying memory is shorter, the buffer sequence represents as many bytes | |
1938 | * as are available. | |
1939 | * | |
1940 | * @returns An object of type @c mutable_buffers_type that satisfies | |
1941 | * MutableBufferSequence requirements, representing the vector memory. | |
1942 | * | |
1943 | * @note The returned object is invalidated by any @c dynamic_vector_buffer | |
1944 | * or @c vector member function that resizes or erases the vector. | |
1945 | */ | |
1946 | mutable_buffers_type data(std::size_t pos, std::size_t n) BOOST_ASIO_NOEXCEPT | |
1947 | { | |
1948 | return mutable_buffers_type(boost::asio::buffer( | |
1949 | boost::asio::buffer(vector_, max_size_) + pos, n)); | |
1950 | } | |
1951 | ||
1952 | /// @b DynamicBuffer_v2: Get a sequence of buffers that represents the | |
1953 | /// underlying memory. | |
1954 | /** | |
1955 | * @param pos Position of the first byte to represent in the buffer sequence | |
1956 | * | |
1957 | * @param n The number of bytes to return in the buffer sequence. If the | |
1958 | * underlying memory is shorter, the buffer sequence represents as many bytes | |
1959 | * as are available. | |
1960 | * | |
1961 | * @note The returned object is invalidated by any @c dynamic_vector_buffer | |
1962 | * or @c vector member function that resizes or erases the vector. | |
1963 | */ | |
1964 | const_buffers_type data(std::size_t pos, | |
1965 | std::size_t n) const BOOST_ASIO_NOEXCEPT | |
1966 | { | |
1967 | return const_buffers_type(boost::asio::buffer( | |
1968 | boost::asio::buffer(vector_, max_size_) + pos, n)); | |
1969 | } | |
1970 | ||
1971 | #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) | |
1972 | /// @b DynamicBuffer_v1: Get a list of buffers that represents the output | |
1973 | /// sequence, with the given size. | |
b32b8144 FG |
1974 | /** |
1975 | * Ensures that the output sequence can accommodate @c n bytes, resizing the | |
92f5a8d4 | 1976 | * vector object as necessary. |
b32b8144 FG |
1977 | * |
1978 | * @returns An object of type @c mutable_buffers_type that satisfies | |
92f5a8d4 TL |
1979 | * MutableBufferSequence requirements, representing vector memory at the |
1980 | * start of the output sequence of size @c n. | |
b32b8144 FG |
1981 | * |
1982 | * @throws std::length_error If <tt>size() + n > max_size()</tt>. | |
1983 | * | |
1984 | * @note The returned object is invalidated by any @c dynamic_vector_buffer | |
92f5a8d4 TL |
1985 | * or @c vector member function that modifies the input sequence or output |
1986 | * sequence. | |
b32b8144 FG |
1987 | */ |
1988 | mutable_buffers_type prepare(std::size_t n) | |
1989 | { | |
1990 | if (size () > max_size() || max_size() - size() < n) | |
1991 | { | |
1992 | std::length_error ex("dynamic_vector_buffer too long"); | |
1993 | boost::asio::detail::throw_exception(ex); | |
1994 | } | |
1995 | ||
92f5a8d4 TL |
1996 | if (size_ == (std::numeric_limits<std::size_t>::max)()) |
1997 | size_ = vector_.size(); // Enable v1 behaviour. | |
1998 | ||
b32b8144 FG |
1999 | vector_.resize(size_ + n); |
2000 | ||
2001 | return boost::asio::buffer(boost::asio::buffer(vector_) + size_, n); | |
2002 | } | |
2003 | ||
92f5a8d4 TL |
2004 | /// @b DynamicBuffer_v1: Move bytes from the output sequence to the input |
2005 | /// sequence. | |
b32b8144 FG |
2006 | /** |
2007 | * @param n The number of bytes to append from the start of the output | |
2008 | * sequence to the end of the input sequence. The remainder of the output | |
2009 | * sequence is discarded. | |
2010 | * | |
2011 | * Requires a preceding call <tt>prepare(x)</tt> where <tt>x >= n</tt>, and | |
2012 | * no intervening operations that modify the input or output sequence. | |
2013 | * | |
2014 | * @note If @c n is greater than the size of the output sequence, the entire | |
2015 | * output sequence is moved to the input sequence and no error is issued. | |
2016 | */ | |
2017 | void commit(std::size_t n) | |
2018 | { | |
2019 | size_ += (std::min)(n, vector_.size() - size_); | |
2020 | vector_.resize(size_); | |
2021 | } | |
92f5a8d4 TL |
2022 | #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
2023 | ||
2024 | /// @b DynamicBuffer_v2: Grow the underlying memory by the specified number of | |
2025 | /// bytes. | |
2026 | /** | |
2027 | * Resizes the vector to accommodate an additional @c n bytes at the end. | |
2028 | * | |
2029 | * @throws std::length_error If <tt>size() + n > max_size()</tt>. | |
2030 | */ | |
2031 | void grow(std::size_t n) | |
2032 | { | |
2033 | if (size() > max_size() || max_size() - size() < n) | |
2034 | { | |
2035 | std::length_error ex("dynamic_vector_buffer too long"); | |
2036 | boost::asio::detail::throw_exception(ex); | |
2037 | } | |
2038 | ||
2039 | vector_.resize(size() + n); | |
2040 | } | |
2041 | ||
2042 | /// @b DynamicBuffer_v2: Shrink the underlying memory by the specified number | |
2043 | /// of bytes. | |
2044 | /** | |
2045 | * Erases @c n bytes from the end of the vector by resizing the vector | |
2046 | * object. If @c n is greater than the current size of the vector, the vector | |
2047 | * is emptied. | |
2048 | */ | |
2049 | void shrink(std::size_t n) | |
2050 | { | |
2051 | vector_.resize(n > size() ? 0 : size() - n); | |
2052 | } | |
b32b8144 | 2053 | |
92f5a8d4 TL |
2054 | /// @b DynamicBuffer_v1: Remove characters from the input sequence. |
2055 | /// @b DynamicBuffer_v2: Consume the specified number of bytes from the | |
2056 | /// beginning of the underlying memory. | |
b32b8144 | 2057 | /** |
92f5a8d4 TL |
2058 | * @b DynamicBuffer_v1: Removes @c n characters from the beginning of the |
2059 | * input sequence. @note If @c n is greater than the size of the input | |
2060 | * sequence, the entire input sequence is consumed and no error is issued. | |
b32b8144 | 2061 | * |
92f5a8d4 TL |
2062 | * @b DynamicBuffer_v2: Erases @c n bytes from the beginning of the vector. |
2063 | * If @c n is greater than the current size of the vector, the vector is | |
2064 | * emptied. | |
b32b8144 FG |
2065 | */ |
2066 | void consume(std::size_t n) | |
2067 | { | |
92f5a8d4 TL |
2068 | #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
2069 | if (size_ != (std::numeric_limits<std::size_t>::max)()) | |
2070 | { | |
2071 | std::size_t consume_length = (std::min)(n, size_); | |
2072 | vector_.erase(vector_.begin(), vector_.begin() + consume_length); | |
2073 | size_ -= consume_length; | |
2074 | return; | |
2075 | } | |
2076 | #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) | |
2077 | vector_.erase(vector_.begin(), vector_.begin() + (std::min)(size(), n)); | |
b32b8144 FG |
2078 | } |
2079 | ||
2080 | private: | |
2081 | std::vector<Elem, Allocator>& vector_; | |
92f5a8d4 | 2082 | #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
b32b8144 | 2083 | std::size_t size_; |
92f5a8d4 | 2084 | #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) |
b32b8144 FG |
2085 | const std::size_t max_size_; |
2086 | }; | |
2087 | ||
2088 | /** @defgroup dynamic_buffer boost::asio::dynamic_buffer | |
2089 | * | |
2090 | * @brief The boost::asio::dynamic_buffer function is used to create a | |
2091 | * dynamically resized buffer from a @c std::basic_string or @c std::vector. | |
2092 | */ | |
2093 | /*@{*/ | |
2094 | ||
2095 | /// Create a new dynamic buffer that represents the given string. | |
2096 | /** | |
2097 | * @returns <tt>dynamic_string_buffer<Elem, Traits, Allocator>(data)</tt>. | |
2098 | */ | |
2099 | template <typename Elem, typename Traits, typename Allocator> | |
2100 | inline dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer( | |
2101 | std::basic_string<Elem, Traits, Allocator>& data) BOOST_ASIO_NOEXCEPT | |
2102 | { | |
2103 | return dynamic_string_buffer<Elem, Traits, Allocator>(data); | |
2104 | } | |
2105 | ||
2106 | /// Create a new dynamic buffer that represents the given string. | |
2107 | /** | |
2108 | * @returns <tt>dynamic_string_buffer<Elem, Traits, Allocator>(data, | |
2109 | * max_size)</tt>. | |
2110 | */ | |
2111 | template <typename Elem, typename Traits, typename Allocator> | |
2112 | inline dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer( | |
2113 | std::basic_string<Elem, Traits, Allocator>& data, | |
2114 | std::size_t max_size) BOOST_ASIO_NOEXCEPT | |
2115 | { | |
2116 | return dynamic_string_buffer<Elem, Traits, Allocator>(data, max_size); | |
2117 | } | |
2118 | ||
2119 | /// Create a new dynamic buffer that represents the given vector. | |
2120 | /** | |
2121 | * @returns <tt>dynamic_vector_buffer<Elem, Allocator>(data)</tt>. | |
2122 | */ | |
2123 | template <typename Elem, typename Allocator> | |
2124 | inline dynamic_vector_buffer<Elem, Allocator> dynamic_buffer( | |
2125 | std::vector<Elem, Allocator>& data) BOOST_ASIO_NOEXCEPT | |
2126 | { | |
2127 | return dynamic_vector_buffer<Elem, Allocator>(data); | |
2128 | } | |
2129 | ||
2130 | /// Create a new dynamic buffer that represents the given vector. | |
2131 | /** | |
2132 | * @returns <tt>dynamic_vector_buffer<Elem, Allocator>(data, max_size)</tt>. | |
2133 | */ | |
2134 | template <typename Elem, typename Allocator> | |
2135 | inline dynamic_vector_buffer<Elem, Allocator> dynamic_buffer( | |
2136 | std::vector<Elem, Allocator>& data, | |
2137 | std::size_t max_size) BOOST_ASIO_NOEXCEPT | |
2138 | { | |
2139 | return dynamic_vector_buffer<Elem, Allocator>(data, max_size); | |
2140 | } | |
2141 | ||
2142 | /*@}*/ | |
2143 | ||
2144 | /** @defgroup buffer_copy boost::asio::buffer_copy | |
2145 | * | |
2146 | * @brief The boost::asio::buffer_copy function is used to copy bytes from a | |
2147 | * source buffer (or buffer sequence) to a target buffer (or buffer sequence). | |
2148 | * | |
2149 | * The @c buffer_copy function is available in two forms: | |
2150 | * | |
2151 | * @li A 2-argument form: @c buffer_copy(target, source) | |
2152 | * | |
2153 | * @li A 3-argument form: @c buffer_copy(target, source, max_bytes_to_copy) | |
2154 | * | |
2155 | * Both forms return the number of bytes actually copied. The number of bytes | |
2156 | * copied is the lesser of: | |
2157 | * | |
2158 | * @li @c buffer_size(target) | |
2159 | * | |
2160 | * @li @c buffer_size(source) | |
2161 | * | |
2162 | * @li @c If specified, @c max_bytes_to_copy. | |
2163 | * | |
2164 | * This prevents buffer overflow, regardless of the buffer sizes used in the | |
2165 | * copy operation. | |
2166 | * | |
2167 | * Note that @ref buffer_copy is implemented in terms of @c memcpy, and | |
2168 | * consequently it cannot be used to copy between overlapping memory regions. | |
2169 | */ | |
2170 | /*@{*/ | |
2171 | ||
2172 | namespace detail { | |
2173 | ||
2174 | inline std::size_t buffer_copy_1(const mutable_buffer& target, | |
2175 | const const_buffer& source) | |
2176 | { | |
2177 | using namespace std; // For memcpy. | |
2178 | std::size_t target_size = target.size(); | |
2179 | std::size_t source_size = source.size(); | |
2180 | std::size_t n = target_size < source_size ? target_size : source_size; | |
2181 | if (n > 0) | |
2182 | memcpy(target.data(), source.data(), n); | |
2183 | return n; | |
2184 | } | |
2185 | ||
2186 | template <typename TargetIterator, typename SourceIterator> | |
2187 | inline std::size_t buffer_copy(one_buffer, one_buffer, | |
2188 | TargetIterator target_begin, TargetIterator, | |
2189 | SourceIterator source_begin, SourceIterator) BOOST_ASIO_NOEXCEPT | |
2190 | { | |
2191 | return (buffer_copy_1)(*target_begin, *source_begin); | |
2192 | } | |
2193 | ||
2194 | template <typename TargetIterator, typename SourceIterator> | |
2195 | inline std::size_t buffer_copy(one_buffer, one_buffer, | |
2196 | TargetIterator target_begin, TargetIterator, | |
2197 | SourceIterator source_begin, SourceIterator, | |
2198 | std::size_t max_bytes_to_copy) BOOST_ASIO_NOEXCEPT | |
2199 | { | |
2200 | return (buffer_copy_1)(*target_begin, | |
2201 | boost::asio::buffer(*source_begin, max_bytes_to_copy)); | |
2202 | } | |
2203 | ||
2204 | template <typename TargetIterator, typename SourceIterator> | |
2205 | std::size_t buffer_copy(one_buffer, multiple_buffers, | |
2206 | TargetIterator target_begin, TargetIterator, | |
2207 | SourceIterator source_begin, SourceIterator source_end, | |
2208 | std::size_t max_bytes_to_copy | |
2209 | = (std::numeric_limits<std::size_t>::max)()) BOOST_ASIO_NOEXCEPT | |
2210 | { | |
2211 | std::size_t total_bytes_copied = 0; | |
2212 | SourceIterator source_iter = source_begin; | |
2213 | ||
2214 | for (mutable_buffer target_buffer( | |
2215 | boost::asio::buffer(*target_begin, max_bytes_to_copy)); | |
2216 | target_buffer.size() && source_iter != source_end; ++source_iter) | |
2217 | { | |
2218 | const_buffer source_buffer(*source_iter); | |
2219 | std::size_t bytes_copied = (buffer_copy_1)(target_buffer, source_buffer); | |
2220 | total_bytes_copied += bytes_copied; | |
2221 | target_buffer += bytes_copied; | |
2222 | } | |
2223 | ||
2224 | return total_bytes_copied; | |
2225 | } | |
2226 | ||
2227 | template <typename TargetIterator, typename SourceIterator> | |
2228 | std::size_t buffer_copy(multiple_buffers, one_buffer, | |
2229 | TargetIterator target_begin, TargetIterator target_end, | |
2230 | SourceIterator source_begin, SourceIterator, | |
2231 | std::size_t max_bytes_to_copy | |
2232 | = (std::numeric_limits<std::size_t>::max)()) BOOST_ASIO_NOEXCEPT | |
2233 | { | |
2234 | std::size_t total_bytes_copied = 0; | |
2235 | TargetIterator target_iter = target_begin; | |
2236 | ||
2237 | for (const_buffer source_buffer( | |
2238 | boost::asio::buffer(*source_begin, max_bytes_to_copy)); | |
2239 | source_buffer.size() && target_iter != target_end; ++target_iter) | |
2240 | { | |
2241 | mutable_buffer target_buffer(*target_iter); | |
2242 | std::size_t bytes_copied = (buffer_copy_1)(target_buffer, source_buffer); | |
2243 | total_bytes_copied += bytes_copied; | |
2244 | source_buffer += bytes_copied; | |
2245 | } | |
2246 | ||
2247 | return total_bytes_copied; | |
2248 | } | |
2249 | ||
2250 | template <typename TargetIterator, typename SourceIterator> | |
2251 | std::size_t buffer_copy(multiple_buffers, multiple_buffers, | |
2252 | TargetIterator target_begin, TargetIterator target_end, | |
2253 | SourceIterator source_begin, SourceIterator source_end) BOOST_ASIO_NOEXCEPT | |
2254 | { | |
2255 | std::size_t total_bytes_copied = 0; | |
2256 | ||
2257 | TargetIterator target_iter = target_begin; | |
2258 | std::size_t target_buffer_offset = 0; | |
2259 | ||
2260 | SourceIterator source_iter = source_begin; | |
2261 | std::size_t source_buffer_offset = 0; | |
2262 | ||
2263 | while (target_iter != target_end && source_iter != source_end) | |
2264 | { | |
2265 | mutable_buffer target_buffer = | |
2266 | mutable_buffer(*target_iter) + target_buffer_offset; | |
2267 | ||
2268 | const_buffer source_buffer = | |
2269 | const_buffer(*source_iter) + source_buffer_offset; | |
2270 | ||
2271 | std::size_t bytes_copied = (buffer_copy_1)(target_buffer, source_buffer); | |
2272 | total_bytes_copied += bytes_copied; | |
2273 | ||
2274 | if (bytes_copied == target_buffer.size()) | |
2275 | { | |
2276 | ++target_iter; | |
2277 | target_buffer_offset = 0; | |
2278 | } | |
2279 | else | |
2280 | target_buffer_offset += bytes_copied; | |
2281 | ||
2282 | if (bytes_copied == source_buffer.size()) | |
2283 | { | |
2284 | ++source_iter; | |
2285 | source_buffer_offset = 0; | |
2286 | } | |
2287 | else | |
2288 | source_buffer_offset += bytes_copied; | |
2289 | } | |
2290 | ||
2291 | return total_bytes_copied; | |
2292 | } | |
2293 | ||
2294 | template <typename TargetIterator, typename SourceIterator> | |
2295 | std::size_t buffer_copy(multiple_buffers, multiple_buffers, | |
2296 | TargetIterator target_begin, TargetIterator target_end, | |
2297 | SourceIterator source_begin, SourceIterator source_end, | |
2298 | std::size_t max_bytes_to_copy) BOOST_ASIO_NOEXCEPT | |
2299 | { | |
2300 | std::size_t total_bytes_copied = 0; | |
2301 | ||
2302 | TargetIterator target_iter = target_begin; | |
2303 | std::size_t target_buffer_offset = 0; | |
2304 | ||
2305 | SourceIterator source_iter = source_begin; | |
2306 | std::size_t source_buffer_offset = 0; | |
2307 | ||
2308 | while (total_bytes_copied != max_bytes_to_copy | |
2309 | && target_iter != target_end && source_iter != source_end) | |
2310 | { | |
2311 | mutable_buffer target_buffer = | |
2312 | mutable_buffer(*target_iter) + target_buffer_offset; | |
2313 | ||
2314 | const_buffer source_buffer = | |
2315 | const_buffer(*source_iter) + source_buffer_offset; | |
2316 | ||
2317 | std::size_t bytes_copied = (buffer_copy_1)( | |
2318 | target_buffer, boost::asio::buffer(source_buffer, | |
2319 | max_bytes_to_copy - total_bytes_copied)); | |
2320 | total_bytes_copied += bytes_copied; | |
2321 | ||
2322 | if (bytes_copied == target_buffer.size()) | |
2323 | { | |
2324 | ++target_iter; | |
2325 | target_buffer_offset = 0; | |
2326 | } | |
2327 | else | |
2328 | target_buffer_offset += bytes_copied; | |
2329 | ||
2330 | if (bytes_copied == source_buffer.size()) | |
2331 | { | |
2332 | ++source_iter; | |
2333 | source_buffer_offset = 0; | |
2334 | } | |
2335 | else | |
2336 | source_buffer_offset += bytes_copied; | |
2337 | } | |
2338 | ||
2339 | return total_bytes_copied; | |
2340 | } | |
2341 | ||
2342 | } // namespace detail | |
2343 | ||
2344 | /// Copies bytes from a source buffer sequence to a target buffer sequence. | |
2345 | /** | |
2346 | * @param target A modifiable buffer sequence representing the memory regions to | |
2347 | * which the bytes will be copied. | |
2348 | * | |
2349 | * @param source A non-modifiable buffer sequence representing the memory | |
2350 | * regions from which the bytes will be copied. | |
2351 | * | |
2352 | * @returns The number of bytes copied. | |
2353 | * | |
2354 | * @note The number of bytes copied is the lesser of: | |
2355 | * | |
2356 | * @li @c buffer_size(target) | |
2357 | * | |
2358 | * @li @c buffer_size(source) | |
2359 | * | |
2360 | * This function is implemented in terms of @c memcpy, and consequently it | |
2361 | * cannot be used to copy between overlapping memory regions. | |
2362 | */ | |
2363 | template <typename MutableBufferSequence, typename ConstBufferSequence> | |
2364 | inline std::size_t buffer_copy(const MutableBufferSequence& target, | |
2365 | const ConstBufferSequence& source) BOOST_ASIO_NOEXCEPT | |
2366 | { | |
2367 | return detail::buffer_copy( | |
2368 | detail::buffer_sequence_cardinality<MutableBufferSequence>(), | |
2369 | detail::buffer_sequence_cardinality<ConstBufferSequence>(), | |
2370 | boost::asio::buffer_sequence_begin(target), | |
2371 | boost::asio::buffer_sequence_end(target), | |
2372 | boost::asio::buffer_sequence_begin(source), | |
2373 | boost::asio::buffer_sequence_end(source)); | |
2374 | } | |
2375 | ||
2376 | /// Copies a limited number of bytes from a source buffer sequence to a target | |
2377 | /// buffer sequence. | |
2378 | /** | |
2379 | * @param target A modifiable buffer sequence representing the memory regions to | |
2380 | * which the bytes will be copied. | |
2381 | * | |
2382 | * @param source A non-modifiable buffer sequence representing the memory | |
2383 | * regions from which the bytes will be copied. | |
2384 | * | |
2385 | * @param max_bytes_to_copy The maximum number of bytes to be copied. | |
2386 | * | |
2387 | * @returns The number of bytes copied. | |
2388 | * | |
2389 | * @note The number of bytes copied is the lesser of: | |
2390 | * | |
2391 | * @li @c buffer_size(target) | |
2392 | * | |
2393 | * @li @c buffer_size(source) | |
2394 | * | |
2395 | * @li @c max_bytes_to_copy | |
2396 | * | |
2397 | * This function is implemented in terms of @c memcpy, and consequently it | |
2398 | * cannot be used to copy between overlapping memory regions. | |
2399 | */ | |
2400 | template <typename MutableBufferSequence, typename ConstBufferSequence> | |
2401 | inline std::size_t buffer_copy(const MutableBufferSequence& target, | |
2402 | const ConstBufferSequence& source, | |
2403 | std::size_t max_bytes_to_copy) BOOST_ASIO_NOEXCEPT | |
2404 | { | |
2405 | return detail::buffer_copy( | |
2406 | detail::buffer_sequence_cardinality<MutableBufferSequence>(), | |
2407 | detail::buffer_sequence_cardinality<ConstBufferSequence>(), | |
2408 | boost::asio::buffer_sequence_begin(target), | |
2409 | boost::asio::buffer_sequence_end(target), | |
2410 | boost::asio::buffer_sequence_begin(source), | |
2411 | boost::asio::buffer_sequence_end(source), max_bytes_to_copy); | |
2412 | } | |
2413 | ||
2414 | /*@}*/ | |
2415 | ||
2416 | } // namespace asio | |
2417 | } // namespace boost | |
2418 | ||
92f5a8d4 TL |
2419 | #include <boost/asio/detail/pop_options.hpp> |
2420 | #include <boost/asio/detail/is_buffer_sequence.hpp> | |
2421 | #include <boost/asio/detail/push_options.hpp> | |
2422 | ||
2423 | namespace boost { | |
2424 | namespace asio { | |
2425 | ||
2426 | /// Trait to determine whether a type satisfies the MutableBufferSequence | |
2427 | /// requirements. | |
2428 | template <typename T> | |
2429 | struct is_mutable_buffer_sequence | |
2430 | #if defined(GENERATING_DOCUMENTATION) | |
2431 | : integral_constant<bool, automatically_determined> | |
2432 | #else // defined(GENERATING_DOCUMENTATION) | |
2433 | : boost::asio::detail::is_buffer_sequence<T, mutable_buffer> | |
2434 | #endif // defined(GENERATING_DOCUMENTATION) | |
2435 | { | |
2436 | }; | |
2437 | ||
2438 | /// Trait to determine whether a type satisfies the ConstBufferSequence | |
2439 | /// requirements. | |
2440 | template <typename T> | |
2441 | struct is_const_buffer_sequence | |
2442 | #if defined(GENERATING_DOCUMENTATION) | |
2443 | : integral_constant<bool, automatically_determined> | |
2444 | #else // defined(GENERATING_DOCUMENTATION) | |
2445 | : boost::asio::detail::is_buffer_sequence<T, const_buffer> | |
2446 | #endif // defined(GENERATING_DOCUMENTATION) | |
2447 | { | |
2448 | }; | |
2449 | ||
2450 | #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) | |
2451 | /// Trait to determine whether a type satisfies the DynamicBuffer_v1 | |
2452 | /// requirements. | |
2453 | template <typename T> | |
2454 | struct is_dynamic_buffer_v1 | |
2455 | #if defined(GENERATING_DOCUMENTATION) | |
2456 | : integral_constant<bool, automatically_determined> | |
2457 | #else // defined(GENERATING_DOCUMENTATION) | |
2458 | : boost::asio::detail::is_dynamic_buffer_v1<T> | |
2459 | #endif // defined(GENERATING_DOCUMENTATION) | |
2460 | { | |
2461 | }; | |
2462 | #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) | |
2463 | ||
2464 | /// Trait to determine whether a type satisfies the DynamicBuffer_v2 | |
2465 | /// requirements. | |
2466 | template <typename T> | |
2467 | struct is_dynamic_buffer_v2 | |
2468 | #if defined(GENERATING_DOCUMENTATION) | |
2469 | : integral_constant<bool, automatically_determined> | |
2470 | #else // defined(GENERATING_DOCUMENTATION) | |
2471 | : boost::asio::detail::is_dynamic_buffer_v2<T> | |
2472 | #endif // defined(GENERATING_DOCUMENTATION) | |
2473 | { | |
2474 | }; | |
2475 | ||
2476 | /// Trait to determine whether a type satisfies the DynamicBuffer requirements. | |
2477 | /** | |
2478 | * If @c BOOST_ASIO_NO_DYNAMIC_BUFFER_V1 is not defined, determines whether the | |
2479 | * type satisfies the DynamicBuffer_v1 requirements. Otherwise, if @c | |
2480 | * BOOST_ASIO_NO_DYNAMIC_BUFFER_V1 is defined, determines whether the type | |
2481 | * satisfies the DynamicBuffer_v2 requirements. | |
2482 | */ | |
2483 | template <typename T> | |
2484 | struct is_dynamic_buffer | |
2485 | #if defined(GENERATING_DOCUMENTATION) | |
2486 | : integral_constant<bool, automatically_determined> | |
2487 | #elif defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) | |
2488 | : boost::asio::is_dynamic_buffer_v2<T> | |
2489 | #else // defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) | |
2490 | : boost::asio::is_dynamic_buffer_v1<T> | |
2491 | #endif // defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1) | |
2492 | { | |
2493 | }; | |
2494 | ||
2495 | } // namespace asio | |
2496 | } // namespace boost | |
2497 | ||
b32b8144 FG |
2498 | #include <boost/asio/detail/pop_options.hpp> |
2499 | ||
2500 | #endif // BOOST_ASIO_BUFFER_HPP |