5 // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #ifndef BOOST_ASIO_BUFFER_HPP
12 #define BOOST_ASIO_BUFFER_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/push_options.hpp>
20 #include <boost/asio/detail/push_options.hpp>
22 #include <boost/config.hpp>
23 #include <boost/array.hpp>
24 #include <boost/type_traits/is_const.hpp>
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)
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
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
&);
64 /// Holds a buffer that can be modified.
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
73 /// Construct an empty buffer.
80 /// Construct a buffer to represent a given memory range.
81 mutable_buffer(void* data
, std::size_t size
)
87 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
88 mutable_buffer(void* data
, std::size_t size
,
89 boost::function
<void()> debug_check
)
92 debug_check_(debug_check
)
96 const boost::function
<void()>& get_debug_check() const
100 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
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
);
111 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
112 boost::function
<void()> debug_check_
;
113 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
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_
)
123 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
127 inline std::size_t buffer_size_helper(const mutable_buffer
& b
)
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
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
)
211 /// Get a random-access iterator to the first element.
212 const_iterator
begin() const
217 /// Get a random-access iterator for one past the last element.
218 const_iterator
end() const
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
233 /// Construct an empty buffer.
240 /// Construct a buffer to represent a given memory range.
241 const_buffer(const void* data
, std::size_t 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
)
262 debug_check_(debug_check
)
266 const boost::function
<void()>& get_debug_check() const
270 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
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
);
281 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
282 boost::function
<void()> debug_check_
;
283 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
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_
)
293 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
297 inline std::size_t buffer_size_helper(const const_buffer
& b
)
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
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
)
381 /// Get a random-access iterator to the first element.
382 const_iterator
begin() const
387 /// Get a random-access iterator for one past the last element.
388 const_iterator
end() const
394 /// An implementation of both the ConstBufferSequence and MutableBufferSequence
395 /// concepts to represent a null buffer sequence.
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
411 /// Get a random-access iterator for one past the last element.
412 const_iterator
end() const
421 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
424 template <typename Iterator
>
425 class buffer_debug_check
428 buffer_debug_check(Iterator 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.
440 #endif // BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
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,
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
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
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
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:
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
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(
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(
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 ...);
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.
747 template <bool IsConst
>
748 struct buffer_types_base
;
751 struct buffer_types_base
<false>
753 typedef mutable_buffer buffer_type
;
754 typedef mutable_buffers_1 container_type
;
758 struct buffer_types_base
<true>
760 typedef const_buffer buffer_type
;
761 typedef const_buffers_1 container_type
;
764 template <typename PodType
>
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
778 typedef typename
boost::asio::detail::buffer_types
<PodType
>::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
790 typedef typename
boost::asio::detail::buffer_types
<PodType
>::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(
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(
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(
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(
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(
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(
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
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
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
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
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(
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
1038 } // namespace boost
1040 #include <boost/asio/detail/pop_options.hpp>
1042 #endif // BOOST_ASIO_BUFFER_HPP