fix doc example typo
[boost.git] / boost / asio / buffer.hpp
blob056d712751dcd5aa550f68b16709d76e8310cb40
1 //
2 // buffer.hpp
3 // ~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 //
11 #ifndef BOOST_ASIO_BUFFER_HPP
12 #define BOOST_ASIO_BUFFER_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/push_options.hpp>
20 #include <boost/asio/detail/push_options.hpp>
21 #include <cstddef>
22 #include <boost/config.hpp>
23 #include <boost/array.hpp>
24 #include <boost/type_traits/is_const.hpp>
25 #include <string>
26 #include <vector>
27 #include <boost/asio/detail/pop_options.hpp>
29 #if defined(BOOST_MSVC)
30 # if defined(_HAS_ITERATOR_DEBUGGING) && (_HAS_ITERATOR_DEBUGGING != 0)
31 # if !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING)
32 # define BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
33 # endif // !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING)
34 # endif // defined(_HAS_ITERATOR_DEBUGGING)
35 #endif // defined(BOOST_MSVC)
37 #if defined(__GNUC__)
38 # if defined(_GLIBCXX_DEBUG)
39 # if !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING)
40 # define BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
41 # endif // !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING)
42 # endif // defined(_GLIBCXX_DEBUG)
43 #endif // defined(__GNUC__)
45 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
46 # include <boost/asio/detail/push_options.hpp>
47 # include <boost/function.hpp>
48 # include <boost/asio/detail/pop_options.hpp>
49 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
51 namespace boost {
52 namespace asio {
54 class mutable_buffer;
55 class const_buffer;
57 namespace detail {
58 void* buffer_cast_helper(const mutable_buffer&);
59 const void* buffer_cast_helper(const const_buffer&);
60 std::size_t buffer_size_helper(const mutable_buffer&);
61 std::size_t buffer_size_helper(const const_buffer&);
62 } // namespace detail
64 /// Holds a buffer that can be modified.
65 /**
66 * The mutable_buffer class provides a safe representation of a buffer that can
67 * be modified. It does not own the underlying data, and so is cheap to copy or
68 * assign.
70 class mutable_buffer
72 public:
73 /// Construct an empty buffer.
74 mutable_buffer()
75 : data_(0),
76 size_(0)
80 /// Construct a buffer to represent a given memory range.
81 mutable_buffer(void* data, std::size_t size)
82 : data_(data),
83 size_(size)
87 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
88 mutable_buffer(void* data, std::size_t size,
89 boost::function<void()> debug_check)
90 : data_(data),
91 size_(size),
92 debug_check_(debug_check)
96 const boost::function<void()>& get_debug_check() const
98 return debug_check_;
100 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
102 private:
103 friend void* boost::asio::detail::buffer_cast_helper(
104 const mutable_buffer& b);
105 friend std::size_t boost::asio::detail::buffer_size_helper(
106 const mutable_buffer& b);
108 void* data_;
109 std::size_t size_;
111 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
112 boost::function<void()> debug_check_;
113 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
116 namespace detail {
118 inline void* buffer_cast_helper(const mutable_buffer& b)
120 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
121 if (b.size_ && b.debug_check_)
122 b.debug_check_();
123 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
124 return b.data_;
127 inline std::size_t buffer_size_helper(const mutable_buffer& b)
129 return b.size_;
132 } // namespace detail
134 /// Cast a non-modifiable buffer to a specified pointer to POD type.
136 * @relates mutable_buffer
138 template <typename PointerToPodType>
139 inline PointerToPodType buffer_cast(const mutable_buffer& b)
141 return static_cast<PointerToPodType>(detail::buffer_cast_helper(b));
144 /// Get the number of bytes in a non-modifiable buffer.
146 * @relates mutable_buffer
148 inline std::size_t buffer_size(const mutable_buffer& b)
150 return detail::buffer_size_helper(b);
153 /// Create a new modifiable buffer that is offset from the start of another.
155 * @relates mutable_buffer
157 inline mutable_buffer operator+(const mutable_buffer& b, std::size_t start)
159 if (start > buffer_size(b))
160 return mutable_buffer();
161 char* new_data = buffer_cast<char*>(b) + start;
162 std::size_t new_size = buffer_size(b) - start;
163 return mutable_buffer(new_data, new_size
164 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
165 , b.get_debug_check()
166 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
170 /// Create a new modifiable buffer that is offset from the start of another.
172 * @relates mutable_buffer
174 inline mutable_buffer operator+(std::size_t start, const mutable_buffer& b)
176 if (start > buffer_size(b))
177 return mutable_buffer();
178 char* new_data = buffer_cast<char*>(b) + start;
179 std::size_t new_size = buffer_size(b) - start;
180 return mutable_buffer(new_data, new_size
181 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
182 , b.get_debug_check()
183 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
187 /// Adapts a single modifiable buffer so that it meets the requirements of the
188 /// MutableBufferSequence concept.
189 class mutable_buffers_1
190 : public mutable_buffer
192 public:
193 /// The type for each element in the list of buffers.
194 typedef mutable_buffer value_type;
196 /// A random-access iterator type that may be used to read elements.
197 typedef const mutable_buffer* const_iterator;
199 /// Construct to represent a given memory range.
200 mutable_buffers_1(void* data, std::size_t size)
201 : mutable_buffer(data, size)
205 /// Construct to represent a single modifiable buffer.
206 explicit mutable_buffers_1(const mutable_buffer& b)
207 : mutable_buffer(b)
211 /// Get a random-access iterator to the first element.
212 const_iterator begin() const
214 return this;
217 /// Get a random-access iterator for one past the last element.
218 const_iterator end() const
220 return begin() + 1;
224 /// Holds a buffer that cannot be modified.
226 * The const_buffer class provides a safe representation of a buffer that cannot
227 * be modified. It does not own the underlying data, and so is cheap to copy or
228 * assign.
230 class const_buffer
232 public:
233 /// Construct an empty buffer.
234 const_buffer()
235 : data_(0),
236 size_(0)
240 /// Construct a buffer to represent a given memory range.
241 const_buffer(const void* data, std::size_t size)
242 : data_(data),
243 size_(size)
247 /// Construct a non-modifiable buffer from a modifiable one.
248 const_buffer(const mutable_buffer& b)
249 : data_(boost::asio::detail::buffer_cast_helper(b)),
250 size_(boost::asio::detail::buffer_size_helper(b))
251 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
252 , debug_check_(b.get_debug_check())
253 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
257 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
258 const_buffer(const void* data, std::size_t size,
259 boost::function<void()> debug_check)
260 : data_(data),
261 size_(size),
262 debug_check_(debug_check)
266 const boost::function<void()>& get_debug_check() const
268 return debug_check_;
270 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
272 private:
273 friend const void* boost::asio::detail::buffer_cast_helper(
274 const const_buffer& b);
275 friend std::size_t boost::asio::detail::buffer_size_helper(
276 const const_buffer& b);
278 const void* data_;
279 std::size_t size_;
281 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
282 boost::function<void()> debug_check_;
283 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
286 namespace detail {
288 inline const void* buffer_cast_helper(const const_buffer& b)
290 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
291 if (b.size_ && b.debug_check_)
292 b.debug_check_();
293 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
294 return b.data_;
297 inline std::size_t buffer_size_helper(const const_buffer& b)
299 return b.size_;
302 } // namespace detail
304 /// Cast a non-modifiable buffer to a specified pointer to POD type.
306 * @relates const_buffer
308 template <typename PointerToPodType>
309 inline PointerToPodType buffer_cast(const const_buffer& b)
311 return static_cast<PointerToPodType>(detail::buffer_cast_helper(b));
314 /// Get the number of bytes in a non-modifiable buffer.
316 * @relates const_buffer
318 inline std::size_t buffer_size(const const_buffer& b)
320 return detail::buffer_size_helper(b);
323 /// Create a new non-modifiable buffer that is offset from the start of another.
325 * @relates const_buffer
327 inline const_buffer operator+(const const_buffer& b, std::size_t start)
329 if (start > buffer_size(b))
330 return const_buffer();
331 const char* new_data = buffer_cast<const char*>(b) + start;
332 std::size_t new_size = buffer_size(b) - start;
333 return const_buffer(new_data, new_size
334 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
335 , b.get_debug_check()
336 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
340 /// Create a new non-modifiable buffer that is offset from the start of another.
342 * @relates const_buffer
344 inline const_buffer operator+(std::size_t start, const const_buffer& b)
346 if (start > buffer_size(b))
347 return const_buffer();
348 const char* new_data = buffer_cast<const char*>(b) + start;
349 std::size_t new_size = buffer_size(b) - start;
350 return const_buffer(new_data, new_size
351 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
352 , b.get_debug_check()
353 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
357 /// Adapts a single non-modifiable buffer so that it meets the requirements of
358 /// the ConstBufferSequence concept.
359 class const_buffers_1
360 : public const_buffer
362 public:
363 /// The type for each element in the list of buffers.
364 typedef const_buffer value_type;
366 /// A random-access iterator type that may be used to read elements.
367 typedef const const_buffer* const_iterator;
369 /// Construct to represent a given memory range.
370 const_buffers_1(const void* data, std::size_t size)
371 : const_buffer(data, size)
375 /// Construct to represent a single non-modifiable buffer.
376 explicit const_buffers_1(const const_buffer& b)
377 : const_buffer(b)
381 /// Get a random-access iterator to the first element.
382 const_iterator begin() const
384 return this;
387 /// Get a random-access iterator for one past the last element.
388 const_iterator end() const
390 return begin() + 1;
394 /// An implementation of both the ConstBufferSequence and MutableBufferSequence
395 /// concepts to represent a null buffer sequence.
396 class null_buffers
398 public:
399 /// The type for each element in the list of buffers.
400 typedef mutable_buffer value_type;
402 /// A random-access iterator type that may be used to read elements.
403 typedef const mutable_buffer* const_iterator;
405 /// Get a random-access iterator to the first element.
406 const_iterator begin() const
408 return &buf_;
411 /// Get a random-access iterator for one past the last element.
412 const_iterator end() const
414 return &buf_;
417 private:
418 mutable_buffer buf_;
421 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
422 namespace detail {
424 template <typename Iterator>
425 class buffer_debug_check
427 public:
428 buffer_debug_check(Iterator iter)
429 : iter_(iter)
433 ~buffer_debug_check()
435 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
436 // MSVC's string iterator checking may crash in a std::string::iterator
437 // object's destructor when the iterator points to an already-destroyed
438 // std::string object, unless the iterator is cleared first.
439 iter_ = Iterator();
440 #endif // BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
443 void operator()()
445 *iter_;
448 private:
449 Iterator iter_;
452 } // namespace detail
453 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
455 /** @defgroup buffer boost::asio::buffer
457 * @brief The boost::asio::buffer function is used to create a buffer object to
458 * represent raw memory, an array of POD elements, a vector of POD elements,
459 * or a std::string.
461 * A buffer object represents a contiguous region of memory as a 2-tuple
462 * consisting of a pointer and size in bytes. A tuple of the form <tt>{void*,
463 * size_t}</tt> specifies a mutable (modifiable) region of memory. Similarly, a
464 * tuple of the form <tt>{const void*, size_t}</tt> specifies a const
465 * (non-modifiable) region of memory. These two forms correspond to the classes
466 * mutable_buffer and const_buffer, respectively. To mirror C++'s conversion
467 * rules, a mutable_buffer is implicitly convertible to a const_buffer, and the
468 * opposite conversion is not permitted.
470 * The simplest use case involves reading or writing a single buffer of a
471 * specified size:
473 * @code sock.send(boost::asio::buffer(data, size)); @endcode
475 * In the above example, the return value of boost::asio::buffer meets the
476 * requirements of the ConstBufferSequence concept so that it may be directly
477 * passed to the socket's write function. A buffer created for modifiable
478 * memory also meets the requirements of the MutableBufferSequence concept.
480 * An individual buffer may be created from a builtin array, std::vector or
481 * boost::array of POD elements. This helps prevent buffer overruns by
482 * automatically determining the size of the buffer:
484 * @code char d1[128];
485 * size_t bytes_transferred = sock.receive(boost::asio::buffer(d1));
487 * std::vector<char> d2(128);
488 * bytes_transferred = sock.receive(boost::asio::buffer(d2));
490 * boost::array<char, 128> d3;
491 * bytes_transferred = sock.receive(boost::asio::buffer(d3)); @endcode
493 * In all three cases above, the buffers created are exactly 128 bytes long.
494 * Note that a vector is @e never automatically resized when creating or using
495 * a buffer. The buffer size is determined using the vector's <tt>size()</tt>
496 * member function, and not its capacity.
498 * @par Accessing Buffer Contents
500 * The contents of a buffer may be accessed using the boost::asio::buffer_size
501 * and boost::asio::buffer_cast functions:
503 * @code boost::asio::mutable_buffer b1 = ...;
504 * std::size_t s1 = boost::asio::buffer_size(b1);
505 * unsigned char* p1 = boost::asio::buffer_cast<unsigned char*>(b1);
507 * boost::asio::const_buffer b2 = ...;
508 * std::size_t s2 = boost::asio::buffer_size(b2);
509 * const void* p2 = boost::asio::buffer_cast<const void*>(b2); @endcode
511 * The boost::asio::buffer_cast function permits violations of type safety, so
512 * uses of it in application code should be carefully considered.
514 * @par Buffer Invalidation
516 * A buffer object does not have any ownership of the memory it refers to. It
517 * is the responsibility of the application to ensure the memory region remains
518 * valid until it is no longer required for an I/O operation. When the memory
519 * is no longer available, the buffer is said to have been invalidated.
521 * For the boost::asio::buffer overloads that accept an argument of type
522 * std::vector, the buffer objects returned are invalidated by any vector
523 * operation that also invalidates all references, pointers and iterators
524 * referring to the elements in the sequence (C++ Std, 23.2.4)
526 * For the boost::asio::buffer overloads that accept an argument of type
527 * std::string, the buffer objects returned are invalidated according to the
528 * rules defined for invalidation of references, pointers and iterators
529 * referring to elements of the sequence (C++ Std, 21.3).
531 * @par Buffer Arithmetic
533 * Buffer objects may be manipulated using simple arithmetic in a safe way
534 * which helps prevent buffer overruns. Consider an array initialised as
535 * follows:
537 * @code boost::array<char, 6> a = { 'a', 'b', 'c', 'd', 'e' }; @endcode
539 * A buffer object @c b1 created using:
541 * @code b1 = boost::asio::buffer(a); @endcode
543 * represents the entire array, <tt>{ 'a', 'b', 'c', 'd', 'e' }</tt>. An
544 * optional second argument to the boost::asio::buffer function may be used to
545 * limit the size, in bytes, of the buffer:
547 * @code b2 = boost::asio::buffer(a, 3); @endcode
549 * such that @c b2 represents the data <tt>{ 'a', 'b', 'c' }</tt>. Even if the
550 * size argument exceeds the actual size of the array, the size of the buffer
551 * object created will be limited to the array size.
553 * An offset may be applied to an existing buffer to create a new one:
555 * @code b3 = b1 + 2; @endcode
557 * where @c b3 will set to represent <tt>{ 'c', 'd', 'e' }</tt>. If the offset
558 * exceeds the size of the existing buffer, the newly created buffer will be
559 * empty.
561 * Both an offset and size may be specified to create a buffer that corresponds
562 * to a specific range of bytes within an existing buffer:
564 * @code b4 = boost::asio::buffer(b1 + 1, 3); @endcode
566 * so that @c b4 will refer to the bytes <tt>{ 'b', 'c', 'd' }</tt>.
568 * @par Buffers and Scatter-Gather I/O
570 * To read or write using multiple buffers (i.e. scatter-gather I/O), multiple
571 * buffer objects may be assigned into a container that supports the
572 * MutableBufferSequence (for read) or ConstBufferSequence (for write) concepts:
574 * @code
575 * char d1[128];
576 * std::vector<char> d2(128);
577 * boost::array<char, 128> d3;
579 * boost::array<mutable_buffer, 3> bufs1 = {
580 * boost::asio::buffer(d1),
581 * boost::asio::buffer(d2),
582 * boost::asio::buffer(d3) };
583 * bytes_transferred = sock.receive(bufs1);
585 * std::vector<const_buffer> bufs2;
586 * bufs2.push_back(boost::asio::buffer(d1));
587 * bufs2.push_back(boost::asio::buffer(d2));
588 * bufs2.push_back(boost::asio::buffer(d3));
589 * bytes_transferred = sock.send(bufs2); @endcode
591 /*@{*/
593 /// Create a new modifiable buffer from an existing buffer.
595 * @returns <tt>mutable_buffers_1(b)</tt>.
597 inline mutable_buffers_1 buffer(const mutable_buffer& b)
599 return mutable_buffers_1(b);
602 /// Create a new modifiable buffer from an existing buffer.
604 * @returns A mutable_buffers_1 value equivalent to:
605 * @code mutable_buffers_1(
606 * buffer_cast<void*>(b),
607 * min(buffer_size(b), max_size_in_bytes)); @endcode
609 inline mutable_buffers_1 buffer(const mutable_buffer& b,
610 std::size_t max_size_in_bytes)
612 return mutable_buffers_1(
613 mutable_buffer(buffer_cast<void*>(b),
614 buffer_size(b) < max_size_in_bytes
615 ? buffer_size(b) : max_size_in_bytes
616 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
617 , b.get_debug_check()
618 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
622 /// Create a new non-modifiable buffer from an existing buffer.
624 * @returns <tt>const_buffers_1(b)</tt>.
626 inline const_buffers_1 buffer(const const_buffer& b)
628 return const_buffers_1(b);
631 /// Create a new non-modifiable buffer from an existing buffer.
633 * @returns A const_buffers_1 value equivalent to:
634 * @code const_buffers_1(
635 * buffer_cast<const void*>(b),
636 * min(buffer_size(b), max_size_in_bytes)); @endcode
638 inline const_buffers_1 buffer(const const_buffer& b,
639 std::size_t max_size_in_bytes)
641 return const_buffers_1(
642 const_buffer(buffer_cast<const void*>(b),
643 buffer_size(b) < max_size_in_bytes
644 ? buffer_size(b) : max_size_in_bytes
645 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
646 , b.get_debug_check()
647 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
651 /// Create a new modifiable buffer that represents the given memory range.
653 * @returns <tt>mutable_buffers_1(data, size_in_bytes)</tt>.
655 inline mutable_buffers_1 buffer(void* data, std::size_t size_in_bytes)
657 return mutable_buffers_1(mutable_buffer(data, size_in_bytes));
660 /// Create a new non-modifiable buffer that represents the given memory range.
662 * @returns <tt>const_buffers_1(data, size_in_bytes)</tt>.
664 inline const_buffers_1 buffer(const void* data,
665 std::size_t size_in_bytes)
667 return const_buffers_1(const_buffer(data, size_in_bytes));
670 /// Create a new modifiable buffer that represents the given POD array.
672 * @returns A mutable_buffers_1 value equivalent to:
673 * @code mutable_buffers_1(
674 * static_cast<void*>(data),
675 * N * sizeof(PodType)); @endcode
677 template <typename PodType, std::size_t N>
678 inline mutable_buffers_1 buffer(PodType (&data)[N])
680 return mutable_buffers_1(mutable_buffer(data, N * sizeof(PodType)));
683 /// Create a new modifiable buffer that represents the given POD array.
685 * @returns A mutable_buffers_1 value equivalent to:
686 * @code mutable_buffers_1(
687 * static_cast<void*>(data),
688 * min(N * sizeof(PodType), max_size_in_bytes)); @endcode
690 template <typename PodType, std::size_t N>
691 inline mutable_buffers_1 buffer(PodType (&data)[N],
692 std::size_t max_size_in_bytes)
694 return mutable_buffers_1(
695 mutable_buffer(data,
696 N * sizeof(PodType) < max_size_in_bytes
697 ? N * sizeof(PodType) : max_size_in_bytes));
700 /// Create a new non-modifiable buffer that represents the given POD array.
702 * @returns A const_buffers_1 value equivalent to:
703 * @code const_buffers_1(
704 * static_cast<const void*>(data),
705 * N * sizeof(PodType)); @endcode
707 template <typename PodType, std::size_t N>
708 inline const_buffers_1 buffer(const PodType (&data)[N])
710 return const_buffers_1(const_buffer(data, N * sizeof(PodType)));
713 /// Create a new non-modifiable buffer that represents the given POD array.
715 * @returns A const_buffers_1 value equivalent to:
716 * @code const_buffers_1(
717 * static_cast<const void*>(data),
718 * min(N * sizeof(PodType), max_size_in_bytes)); @endcode
720 template <typename PodType, std::size_t N>
721 inline const_buffers_1 buffer(const PodType (&data)[N],
722 std::size_t max_size_in_bytes)
724 return const_buffers_1(
725 const_buffer(data,
726 N * sizeof(PodType) < max_size_in_bytes
727 ? N * sizeof(PodType) : max_size_in_bytes));
730 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) \
731 || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
733 // Borland C++ and Sun Studio think the overloads:
735 // unspecified buffer(boost::array<PodType, N>& array ...);
737 // and
739 // unspecified buffer(boost::array<const PodType, N>& array ...);
741 // are ambiguous. This will be worked around by using a buffer_types traits
742 // class that contains typedefs for the appropriate buffer and container
743 // classes, based on whether PodType is const or non-const.
745 namespace detail {
747 template <bool IsConst>
748 struct buffer_types_base;
750 template <>
751 struct buffer_types_base<false>
753 typedef mutable_buffer buffer_type;
754 typedef mutable_buffers_1 container_type;
757 template <>
758 struct buffer_types_base<true>
760 typedef const_buffer buffer_type;
761 typedef const_buffers_1 container_type;
764 template <typename PodType>
765 struct buffer_types
766 : public buffer_types_base<boost::is_const<PodType>::value>
770 } // namespace detail
772 template <typename PodType, std::size_t N>
773 inline typename detail::buffer_types<PodType>::container_type
774 buffer(boost::array<PodType, N>& data)
776 typedef typename boost::asio::detail::buffer_types<PodType>::buffer_type
777 buffer_type;
778 typedef typename boost::asio::detail::buffer_types<PodType>::container_type
779 container_type;
780 return container_type(
781 buffer_type(data.c_array(), data.size() * sizeof(PodType)));
784 template <typename PodType, std::size_t N>
785 inline typename detail::buffer_types<PodType>::container_type
786 buffer(boost::array<PodType, N>& data, std::size_t max_size_in_bytes)
788 typedef typename boost::asio::detail::buffer_types<PodType>::buffer_type
789 buffer_type;
790 typedef typename boost::asio::detail::buffer_types<PodType>::container_type
791 container_type;
792 return container_type(
793 buffer_type(data.c_array(),
794 data.size() * sizeof(PodType) < max_size_in_bytes
795 ? data.size() * sizeof(PodType) : max_size_in_bytes));
798 #else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
799 // || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
801 /// Create a new modifiable buffer that represents the given POD array.
803 * @returns A mutable_buffers_1 value equivalent to:
804 * @code mutable_buffers_1(
805 * data.data(),
806 * data.size() * sizeof(PodType)); @endcode
808 template <typename PodType, std::size_t N>
809 inline mutable_buffers_1 buffer(boost::array<PodType, N>& data)
811 return mutable_buffers_1(
812 mutable_buffer(data.c_array(), data.size() * sizeof(PodType)));
815 /// Create a new modifiable buffer that represents the given POD array.
817 * @returns A mutable_buffers_1 value equivalent to:
818 * @code mutable_buffers_1(
819 * data.data(),
820 * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
822 template <typename PodType, std::size_t N>
823 inline mutable_buffers_1 buffer(boost::array<PodType, N>& data,
824 std::size_t max_size_in_bytes)
826 return mutable_buffers_1(
827 mutable_buffer(data.c_array(),
828 data.size() * sizeof(PodType) < max_size_in_bytes
829 ? data.size() * sizeof(PodType) : max_size_in_bytes));
832 /// Create a new non-modifiable buffer that represents the given POD array.
834 * @returns A const_buffers_1 value equivalent to:
835 * @code const_buffers_1(
836 * data.data(),
837 * data.size() * sizeof(PodType)); @endcode
839 template <typename PodType, std::size_t N>
840 inline const_buffers_1 buffer(boost::array<const PodType, N>& data)
842 return const_buffers_1(
843 const_buffer(data.data(), data.size() * sizeof(PodType)));
846 /// Create a new non-modifiable buffer that represents the given POD array.
848 * @returns A const_buffers_1 value equivalent to:
849 * @code const_buffers_1(
850 * data.data(),
851 * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
853 template <typename PodType, std::size_t N>
854 inline const_buffers_1 buffer(boost::array<const PodType, N>& data,
855 std::size_t max_size_in_bytes)
857 return const_buffers_1(
858 const_buffer(data.data(),
859 data.size() * sizeof(PodType) < max_size_in_bytes
860 ? data.size() * sizeof(PodType) : max_size_in_bytes));
863 #endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
864 // || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
866 /// Create a new non-modifiable buffer that represents the given POD array.
868 * @returns A const_buffers_1 value equivalent to:
869 * @code const_buffers_1(
870 * data.data(),
871 * data.size() * sizeof(PodType)); @endcode
873 template <typename PodType, std::size_t N>
874 inline const_buffers_1 buffer(const boost::array<PodType, N>& data)
876 return const_buffers_1(
877 const_buffer(data.data(), data.size() * sizeof(PodType)));
880 /// Create a new non-modifiable buffer that represents the given POD array.
882 * @returns A const_buffers_1 value equivalent to:
883 * @code const_buffers_1(
884 * data.data(),
885 * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
887 template <typename PodType, std::size_t N>
888 inline const_buffers_1 buffer(const boost::array<PodType, N>& data,
889 std::size_t max_size_in_bytes)
891 return const_buffers_1(
892 const_buffer(data.data(),
893 data.size() * sizeof(PodType) < max_size_in_bytes
894 ? data.size() * sizeof(PodType) : max_size_in_bytes));
897 /// Create a new modifiable buffer that represents the given POD vector.
899 * @returns A mutable_buffers_1 value equivalent to:
900 * @code mutable_buffers_1(
901 * data.size() ? &data[0] : 0,
902 * data.size() * sizeof(PodType)); @endcode
904 * @note The buffer is invalidated by any vector operation that would also
905 * invalidate iterators.
907 template <typename PodType, typename Allocator>
908 inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data)
910 return mutable_buffers_1(
911 mutable_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType)
912 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
913 , detail::buffer_debug_check<
914 typename std::vector<PodType, Allocator>::iterator
915 >(data.begin())
916 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
920 /// Create a new modifiable buffer that represents the given POD vector.
922 * @returns A mutable_buffers_1 value equivalent to:
923 * @code mutable_buffers_1(
924 * data.size() ? &data[0] : 0,
925 * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
927 * @note The buffer is invalidated by any vector operation that would also
928 * invalidate iterators.
930 template <typename PodType, typename Allocator>
931 inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data,
932 std::size_t max_size_in_bytes)
934 return mutable_buffers_1(
935 mutable_buffer(data.size() ? &data[0] : 0,
936 data.size() * sizeof(PodType) < max_size_in_bytes
937 ? data.size() * sizeof(PodType) : max_size_in_bytes
938 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
939 , detail::buffer_debug_check<
940 typename std::vector<PodType, Allocator>::iterator
941 >(data.begin())
942 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
946 /// Create a new non-modifiable buffer that represents the given POD vector.
948 * @returns A const_buffers_1 value equivalent to:
949 * @code const_buffers_1(
950 * data.size() ? &data[0] : 0,
951 * data.size() * sizeof(PodType)); @endcode
953 * @note The buffer is invalidated by any vector operation that would also
954 * invalidate iterators.
956 template <typename PodType, typename Allocator>
957 inline const_buffers_1 buffer(
958 const std::vector<PodType, Allocator>& data)
960 return const_buffers_1(
961 const_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType)
962 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
963 , detail::buffer_debug_check<
964 typename std::vector<PodType, Allocator>::const_iterator
965 >(data.begin())
966 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
970 /// Create a new non-modifiable buffer that represents the given POD vector.
972 * @returns A const_buffers_1 value equivalent to:
973 * @code const_buffers_1(
974 * data.size() ? &data[0] : 0,
975 * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
977 * @note The buffer is invalidated by any vector operation that would also
978 * invalidate iterators.
980 template <typename PodType, typename Allocator>
981 inline const_buffers_1 buffer(
982 const std::vector<PodType, Allocator>& data, std::size_t max_size_in_bytes)
984 return const_buffers_1(
985 const_buffer(data.size() ? &data[0] : 0,
986 data.size() * sizeof(PodType) < max_size_in_bytes
987 ? data.size() * sizeof(PodType) : max_size_in_bytes
988 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
989 , detail::buffer_debug_check<
990 typename std::vector<PodType, Allocator>::const_iterator
991 >(data.begin())
992 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
996 /// Create a new non-modifiable buffer that represents the given string.
998 * @returns <tt>const_buffers_1(data.data(), data.size())</tt>.
1000 * @note The buffer is invalidated by any non-const operation called on the
1001 * given string object.
1003 inline const_buffers_1 buffer(const std::string& data)
1005 return const_buffers_1(const_buffer(data.data(), data.size()
1006 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
1007 , detail::buffer_debug_check<std::string::const_iterator>(data.begin())
1008 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
1012 /// Create a new non-modifiable buffer that represents the given string.
1014 * @returns A const_buffers_1 value equivalent to:
1015 * @code const_buffers_1(
1016 * data.data(),
1017 * min(data.size(), max_size_in_bytes)); @endcode
1019 * @note The buffer is invalidated by any non-const operation called on the
1020 * given string object.
1022 inline const_buffers_1 buffer(const std::string& data,
1023 std::size_t max_size_in_bytes)
1025 return const_buffers_1(
1026 const_buffer(data.data(),
1027 data.size() < max_size_in_bytes
1028 ? data.size() : max_size_in_bytes
1029 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
1030 , detail::buffer_debug_check<std::string::const_iterator>(data.begin())
1031 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
1035 /*@}*/
1037 } // namespace asio
1038 } // namespace boost
1040 #include <boost/asio/detail/pop_options.hpp>
1042 #endif // BOOST_ASIO_BUFFER_HPP