diff options
Diffstat (limited to 'boost/asio/buffer.hpp')
-rw-r--r-- | boost/asio/buffer.hpp | 2289 |
1 files changed, 1106 insertions, 1183 deletions
diff --git a/boost/asio/buffer.hpp b/boost/asio/buffer.hpp index 700654d21d..66d638ec51 100644 --- a/boost/asio/buffer.hpp +++ b/boost/asio/buffer.hpp @@ -18,17 +18,23 @@ #include <boost/asio/detail/config.hpp> #include <cstddef> #include <cstring> +#include <limits> +#include <stdexcept> #include <string> #include <vector> #include <boost/asio/detail/array_fwd.hpp> +#include <boost/asio/detail/is_buffer_sequence.hpp> +#include <boost/asio/detail/string_view.hpp> +#include <boost/asio/detail/throw_exception.hpp> +#include <boost/asio/detail/type_traits.hpp> -#if defined(BOOST_ASIO_MSVC) +#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1700) # if defined(_HAS_ITERATOR_DEBUGGING) && (_HAS_ITERATOR_DEBUGGING != 0) # if !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING) # define BOOST_ASIO_ENABLE_BUFFER_DEBUGGING # endif // !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING) # endif // defined(_HAS_ITERATOR_DEBUGGING) -#endif // defined(BOOST_ASIO_MSVC) +#endif // defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1700) #if defined(__GNUC__) # if defined(_GLIBCXX_DEBUG) @@ -39,7 +45,7 @@ #endif // defined(__GNUC__) #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) -# include <boost/asio/detail/function.hpp> +# include <boost/asio/detail/functional.hpp> #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING #if defined(BOOST_ASIO_HAS_BOOST_WORKAROUND) @@ -63,13 +69,6 @@ namespace asio { class mutable_buffer; class const_buffer; -namespace detail { -void* buffer_cast_helper(const mutable_buffer&); -const void* buffer_cast_helper(const const_buffer&); -std::size_t buffer_size_helper(const mutable_buffer&); -std::size_t buffer_size_helper(const const_buffer&); -} // namespace detail - /// Holds a buffer that can be modified. /** * The mutable_buffer class provides a safe representation of a buffer that can @@ -78,29 +77,29 @@ std::size_t buffer_size_helper(const const_buffer&); * * @par Accessing Buffer Contents * - * The contents of a buffer may be accessed using the @ref buffer_size - * and @ref buffer_cast functions: + * The contents of a buffer may be accessed using the @c data() and @c size() + * member functions: * * @code boost::asio::mutable_buffer b1 = ...; - * std::size_t s1 = boost::asio::buffer_size(b1); - * unsigned char* p1 = boost::asio::buffer_cast<unsigned char*>(b1); + * std::size_t s1 = b1.size(); + * unsigned char* p1 = static_cast<unsigned char*>(b1.data()); * @endcode * - * The boost::asio::buffer_cast function permits violations of type safety, so - * uses of it in application code should be carefully considered. + * The @c data() member function permits violations of type safety, so uses of + * it in application code should be carefully considered. */ class mutable_buffer { public: /// Construct an empty buffer. - mutable_buffer() + mutable_buffer() BOOST_ASIO_NOEXCEPT : data_(0), size_(0) { } /// Construct a buffer to represent a given memory range. - mutable_buffer(void* data, std::size_t size) + mutable_buffer(void* data, std::size_t size) BOOST_ASIO_NOEXCEPT : data_(data), size_(size) { @@ -121,12 +120,32 @@ public: } #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING -private: - friend void* boost::asio::detail::buffer_cast_helper( - const mutable_buffer& b); - friend std::size_t boost::asio::detail::buffer_size_helper( - const mutable_buffer& b); + /// Get a pointer to the beginning of the memory range. + void* data() const BOOST_ASIO_NOEXCEPT + { +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + if (size_ && debug_check_) + debug_check_(); +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + return data_; + } + + /// Get the size of the memory range. + std::size_t size() const BOOST_ASIO_NOEXCEPT + { + return size_; + } + + /// Move the start of the buffer by the specified number of bytes. + mutable_buffer& operator+=(std::size_t n) BOOST_ASIO_NOEXCEPT + { + std::size_t offset = n < size_ ? n : size_; + data_ = static_cast<char*>(data_) + offset; + size_ -= offset; + return *this; + } +private: void* data_; std::size_t size_; @@ -135,26 +154,10 @@ private: #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING }; -namespace detail { - -inline void* buffer_cast_helper(const mutable_buffer& b) -{ -#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) - if (b.size_ && b.debug_check_) - b.debug_check_(); -#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING - return b.data_; -} +#if !defined(BOOST_ASIO_NO_DEPRECATED) -inline std::size_t buffer_size_helper(const mutable_buffer& b) -{ - return b.size_; -} - -} // namespace detail - -/// Adapts a single modifiable buffer so that it meets the requirements of the -/// MutableBufferSequence concept. +/// (Deprecated: Use mutable_buffer.) Adapts a single modifiable buffer so that +/// it meets the requirements of the MutableBufferSequence concept. class mutable_buffers_1 : public mutable_buffer { @@ -166,30 +169,40 @@ public: typedef const mutable_buffer* const_iterator; /// Construct to represent a given memory range. - mutable_buffers_1(void* data, std::size_t size) + mutable_buffers_1(void* data, std::size_t size) BOOST_ASIO_NOEXCEPT : mutable_buffer(data, size) { } +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + mutable_buffers_1(void* data, std::size_t size, + boost::asio::detail::function<void()> debug_check) + : mutable_buffer(data, size, debug_check) + { + } +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + /// Construct to represent a single modifiable buffer. - explicit mutable_buffers_1(const mutable_buffer& b) + explicit mutable_buffers_1(const mutable_buffer& b) BOOST_ASIO_NOEXCEPT : mutable_buffer(b) { } /// Get a random-access iterator to the first element. - const_iterator begin() const + const_iterator begin() const BOOST_ASIO_NOEXCEPT { return this; } /// Get a random-access iterator for one past the last element. - const_iterator end() const + const_iterator end() const BOOST_ASIO_NOEXCEPT { return begin() + 1; } }; +#endif // !defined(BOOST_ASIO_NO_DEPRECATED) + /// Holds a buffer that cannot be modified. /** * The const_buffer class provides a safe representation of a buffer that cannot @@ -198,38 +211,38 @@ public: * * @par Accessing Buffer Contents * - * The contents of a buffer may be accessed using the @ref buffer_size - * and @ref buffer_cast functions: + * The contents of a buffer may be accessed using the @c data() and @c size() + * member functions: * * @code boost::asio::const_buffer b1 = ...; - * std::size_t s1 = boost::asio::buffer_size(b1); - * const unsigned char* p1 = boost::asio::buffer_cast<const unsigned char*>(b1); + * std::size_t s1 = b1.size(); + * const unsigned char* p1 = static_cast<const unsigned char*>(b1.data()); * @endcode * - * The boost::asio::buffer_cast function permits violations of type safety, so - * uses of it in application code should be carefully considered. + * The @c data() member function permits violations of type safety, so uses of + * it in application code should be carefully considered. */ class const_buffer { public: /// Construct an empty buffer. - const_buffer() + const_buffer() BOOST_ASIO_NOEXCEPT : data_(0), size_(0) { } /// Construct a buffer to represent a given memory range. - const_buffer(const void* data, std::size_t size) + const_buffer(const void* data, std::size_t size) BOOST_ASIO_NOEXCEPT : data_(data), size_(size) { } /// Construct a non-modifiable buffer from a modifiable one. - const_buffer(const mutable_buffer& b) - : data_(boost::asio::detail::buffer_cast_helper(b)), - size_(boost::asio::detail::buffer_size_helper(b)) + const_buffer(const mutable_buffer& b) BOOST_ASIO_NOEXCEPT + : data_(b.data()), + size_(b.size()) #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) , debug_check_(b.get_debug_check()) #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING @@ -251,12 +264,32 @@ public: } #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING -private: - friend const void* boost::asio::detail::buffer_cast_helper( - const const_buffer& b); - friend std::size_t boost::asio::detail::buffer_size_helper( - const const_buffer& b); + /// Get a pointer to the beginning of the memory range. + const void* data() const BOOST_ASIO_NOEXCEPT + { +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + if (size_ && debug_check_) + debug_check_(); +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + return data_; + } + /// Get the size of the memory range. + std::size_t size() const BOOST_ASIO_NOEXCEPT + { + return size_; + } + + /// Move the start of the buffer by the specified number of bytes. + const_buffer& operator+=(std::size_t n) BOOST_ASIO_NOEXCEPT + { + std::size_t offset = n < size_ ? n : size_; + data_ = static_cast<const char*>(data_) + offset; + size_ -= offset; + return *this; + } + +private: const void* data_; std::size_t size_; @@ -265,26 +298,10 @@ private: #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING }; -namespace detail { - -inline const void* buffer_cast_helper(const const_buffer& b) -{ -#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) - if (b.size_ && b.debug_check_) - b.debug_check_(); -#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING - return b.data_; -} - -inline std::size_t buffer_size_helper(const const_buffer& b) -{ - return b.size_; -} - -} // namespace detail +#if !defined(BOOST_ASIO_NO_DEPRECATED) -/// Adapts a single non-modifiable buffer so that it meets the requirements of -/// the ConstBufferSequence concept. +/// (Deprecated: Use const_buffer.) Adapts a single non-modifiable buffer so +/// that it meets the requirements of the ConstBufferSequence concept. class const_buffers_1 : public const_buffer { @@ -296,32 +313,78 @@ public: typedef const const_buffer* const_iterator; /// Construct to represent a given memory range. - const_buffers_1(const void* data, std::size_t size) + const_buffers_1(const void* data, std::size_t size) BOOST_ASIO_NOEXCEPT : const_buffer(data, size) { } +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + const_buffers_1(const void* data, std::size_t size, + boost::asio::detail::function<void()> debug_check) + : const_buffer(data, size, debug_check) + { + } +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + /// Construct to represent a single non-modifiable buffer. - explicit const_buffers_1(const const_buffer& b) + explicit const_buffers_1(const const_buffer& b) BOOST_ASIO_NOEXCEPT : const_buffer(b) { } /// Get a random-access iterator to the first element. - const_iterator begin() const + const_iterator begin() const BOOST_ASIO_NOEXCEPT { return this; } /// Get a random-access iterator for one past the last element. - const_iterator end() const + const_iterator end() const BOOST_ASIO_NOEXCEPT { return begin() + 1; } }; -/// An implementation of both the ConstBufferSequence and MutableBufferSequence -/// concepts to represent a null buffer sequence. +#endif // !defined(BOOST_ASIO_NO_DEPRECATED) + +/// Trait to determine whether a type satisfies the MutableBufferSequence +/// requirements. +template <typename T> +struct is_mutable_buffer_sequence +#if defined(GENERATING_DOCUMENTATION) + : integral_constant<bool, automatically_determined> +#else // defined(GENERATING_DOCUMENTATION) + : boost::asio::detail::is_buffer_sequence<T, mutable_buffer> +#endif // defined(GENERATING_DOCUMENTATION) +{ +}; + +/// Trait to determine whether a type satisfies the ConstBufferSequence +/// requirements. +template <typename T> +struct is_const_buffer_sequence +#if defined(GENERATING_DOCUMENTATION) + : integral_constant<bool, automatically_determined> +#else // defined(GENERATING_DOCUMENTATION) + : boost::asio::detail::is_buffer_sequence<T, const_buffer> +#endif // defined(GENERATING_DOCUMENTATION) +{ +}; + +/// Trait to determine whether a type satisfies the DynamicBuffer requirements. +template <typename T> +struct is_dynamic_buffer +#if defined(GENERATING_DOCUMENTATION) + : integral_constant<bool, automatically_determined> +#else // defined(GENERATING_DOCUMENTATION) + : boost::asio::detail::is_dynamic_buffer<T> +#endif // defined(GENERATING_DOCUMENTATION) +{ +}; + +/// (Deprecated: Use the socket/descriptor wait() and async_wait() member +/// functions.) An implementation of both the ConstBufferSequence and +/// MutableBufferSequence concepts to represent a null buffer sequence. class null_buffers { public: @@ -332,13 +395,13 @@ public: typedef const mutable_buffer* const_iterator; /// Get a random-access iterator to the first element. - const_iterator begin() const + const_iterator begin() const BOOST_ASIO_NOEXCEPT { return &buf_; } /// Get a random-access iterator for one past the last element. - const_iterator end() const + const_iterator end() const BOOST_ASIO_NOEXCEPT { return &buf_; } @@ -347,61 +410,189 @@ private: mutable_buffer buf_; }; -/** @defgroup buffer_size boost::asio::buffer_size +/** @defgroup buffer_sequence_begin boost::asio::buffer_sequence_begin * - * @brief The boost::asio::buffer_size function determines the total number of - * bytes in a buffer or buffer sequence. + * @brief The boost::asio::buffer_sequence_begin function returns an iterator + * pointing to the first element in a buffer sequence. */ /*@{*/ -/// Get the number of bytes in a modifiable buffer. -inline std::size_t buffer_size(const mutable_buffer& b) +/// Get an iterator to the first element in a buffer sequence. +inline const mutable_buffer* buffer_sequence_begin(const mutable_buffer& b) { - return detail::buffer_size_helper(b); + return &b; } -/// Get the number of bytes in a modifiable buffer. -inline std::size_t buffer_size(const mutable_buffers_1& b) +/// Get an iterator to the first element in a buffer sequence. +inline const const_buffer* buffer_sequence_begin(const const_buffer& b) { - return detail::buffer_size_helper(b); + return &b; } -/// Get the number of bytes in a non-modifiable buffer. -inline std::size_t buffer_size(const const_buffer& b) +#if defined(BOOST_ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION) + +/// Get an iterator to the first element in a buffer sequence. +template <typename C> +inline auto buffer_sequence_begin(C& c) -> decltype(c.begin()) { - return detail::buffer_size_helper(b); + return c.begin(); } -/// Get the number of bytes in a non-modifiable buffer. -inline std::size_t buffer_size(const const_buffers_1& b) +/// Get an iterator to the first element in a buffer sequence. +template <typename C> +inline auto buffer_sequence_begin(const C& c) -> decltype(c.begin()) { - return detail::buffer_size_helper(b); + return c.begin(); } -/// Get the total number of bytes in a buffer sequence. -/** - * The @c BufferSequence template parameter may meet either of the @c - * ConstBufferSequence or @c MutableBufferSequence type requirements. +#else // defined(BOOST_ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION) + +template <typename C> +inline typename C::iterator buffer_sequence_begin(C& c) +{ + return c.begin(); +} + +template <typename C> +inline typename C::const_iterator buffer_sequence_begin(const C& c) +{ + return c.begin(); +} + +#endif // defined(BOOST_ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION) + +/*@}*/ + +/** @defgroup buffer_sequence_end boost::asio::buffer_sequence_end + * + * @brief The boost::asio::buffer_sequence_end function returns an iterator + * pointing to one past the end element in a buffer sequence. */ +/*@{*/ + +/// Get an iterator to one past the end element in a buffer sequence. +inline const mutable_buffer* buffer_sequence_end(const mutable_buffer& b) +{ + return &b + 1; +} + +/// Get an iterator to one past the end element in a buffer sequence. +inline const const_buffer* buffer_sequence_end(const const_buffer& b) +{ + return &b + 1; +} + +#if defined(BOOST_ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION) + +/// Get an iterator to one past the end element in a buffer sequence. +template <typename C> +inline auto buffer_sequence_end(C& c) -> decltype(c.end()) +{ + return c.end(); +} + +/// Get an iterator to one past the end element in a buffer sequence. +template <typename C> +inline auto buffer_sequence_end(const C& c) -> decltype(c.end()) +{ + return c.end(); +} + +#else // defined(BOOST_ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION) + +template <typename C> +inline typename C::iterator buffer_sequence_end(C& c) +{ + return c.end(); +} + +template <typename C> +inline typename C::const_iterator buffer_sequence_end(const C& c) +{ + return c.end(); +} + +#endif // defined(BOOST_ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION) + +/*@}*/ + +namespace detail { + +// Tag types used to select appropriately optimised overloads. +struct one_buffer {}; +struct multiple_buffers {}; + +// Helper trait to detect single buffers. template <typename BufferSequence> -inline std::size_t buffer_size(const BufferSequence& b) +struct buffer_sequence_cardinality : + conditional< + is_same<BufferSequence, mutable_buffer>::value +#if !defined(BOOST_ASIO_NO_DEPRECATED) + || is_same<BufferSequence, mutable_buffers_1>::value + || is_same<BufferSequence, const_buffers_1>::value +#endif // !defined(BOOST_ASIO_NO_DEPRECATED) + || is_same<BufferSequence, const_buffer>::value, + one_buffer, multiple_buffers>::type {}; + +template <typename Iterator> +inline std::size_t buffer_size(one_buffer, + Iterator begin, Iterator) BOOST_ASIO_NOEXCEPT +{ + return const_buffer(*begin).size(); +} + +template <typename Iterator> +inline std::size_t buffer_size(multiple_buffers, + Iterator begin, Iterator end) BOOST_ASIO_NOEXCEPT { std::size_t total_buffer_size = 0; - typename BufferSequence::const_iterator iter = b.begin(); - typename BufferSequence::const_iterator end = b.end(); + Iterator iter = begin; for (; iter != end; ++iter) - total_buffer_size += detail::buffer_size_helper(*iter); + { + const_buffer b(*iter); + total_buffer_size += b.size(); + } return total_buffer_size; } -/*@}*/ +} // namespace detail + +/// Get the total number of bytes in a buffer sequence. +/** + * The @c buffer_size function determines the total size of all buffers in the + * buffer sequence, as if computed as follows: + * + * @code size_t total_size = 0; + * auto i = boost::asio::buffer_sequence_begin(buffers); + * auto end = boost::asio::buffer_sequence_end(buffers); + * for (; i != end; ++i) + * { + * const_buffer b(*i); + * total_size += b.size(); + * } + * return total_size; @endcode + * + * The @c BufferSequence template parameter may meet either of the @c + * ConstBufferSequence or @c MutableBufferSequence type requirements. + */ +template <typename BufferSequence> +inline std::size_t buffer_size(const BufferSequence& b) BOOST_ASIO_NOEXCEPT +{ + return detail::buffer_size( + detail::buffer_sequence_cardinality<BufferSequence>(), + boost::asio::buffer_sequence_begin(b), + boost::asio::buffer_sequence_end(b)); +} + +#if !defined(BOOST_ASIO_NO_DEPRECATED) /** @defgroup buffer_cast boost::asio::buffer_cast * - * @brief The boost::asio::buffer_cast function is used to obtain a pointer to - * the underlying memory region associated with a buffer. + * @brief (Deprecated: Use the @c data() member function.) The + * boost::asio::buffer_cast function is used to obtain a pointer to the + * underlying memory region associated with a buffer. * * @par Examples: * @@ -422,30 +613,32 @@ inline std::size_t buffer_size(const BufferSequence& b) /// Cast a non-modifiable buffer to a specified pointer to POD type. template <typename PointerToPodType> -inline PointerToPodType buffer_cast(const mutable_buffer& b) +inline PointerToPodType buffer_cast(const mutable_buffer& b) BOOST_ASIO_NOEXCEPT { - return static_cast<PointerToPodType>(detail::buffer_cast_helper(b)); + return static_cast<PointerToPodType>(b.data()); } /// Cast a non-modifiable buffer to a specified pointer to POD type. template <typename PointerToPodType> -inline PointerToPodType buffer_cast(const const_buffer& b) +inline PointerToPodType buffer_cast(const const_buffer& b) BOOST_ASIO_NOEXCEPT { - return static_cast<PointerToPodType>(detail::buffer_cast_helper(b)); + return static_cast<PointerToPodType>(b.data()); } /*@}*/ +#endif // !defined(BOOST_ASIO_NO_DEPRECATED) + /// Create a new modifiable buffer that is offset from the start of another. /** * @relates mutable_buffer */ -inline mutable_buffer operator+(const mutable_buffer& b, std::size_t start) +inline mutable_buffer operator+(const mutable_buffer& b, + std::size_t n) BOOST_ASIO_NOEXCEPT { - if (start > buffer_size(b)) - return mutable_buffer(); - char* new_data = buffer_cast<char*>(b) + start; - std::size_t new_size = buffer_size(b) - start; + std::size_t offset = n < b.size() ? n : b.size(); + char* new_data = static_cast<char*>(b.data()) + offset; + std::size_t new_size = b.size() - offset; return mutable_buffer(new_data, new_size #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) , b.get_debug_check() @@ -457,29 +650,22 @@ inline mutable_buffer operator+(const mutable_buffer& b, std::size_t start) /** * @relates mutable_buffer */ -inline mutable_buffer operator+(std::size_t start, const mutable_buffer& b) +inline mutable_buffer operator+(std::size_t n, + const mutable_buffer& b) BOOST_ASIO_NOEXCEPT { - if (start > buffer_size(b)) - return mutable_buffer(); - char* new_data = buffer_cast<char*>(b) + start; - std::size_t new_size = buffer_size(b) - start; - return mutable_buffer(new_data, new_size -#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) - , b.get_debug_check() -#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING - ); + return b + n; } /// Create a new non-modifiable buffer that is offset from the start of another. /** * @relates const_buffer */ -inline const_buffer operator+(const const_buffer& b, std::size_t start) +inline const_buffer operator+(const const_buffer& b, + std::size_t n) BOOST_ASIO_NOEXCEPT { - if (start > buffer_size(b)) - return const_buffer(); - const char* new_data = buffer_cast<const char*>(b) + start; - std::size_t new_size = buffer_size(b) - start; + std::size_t offset = n < b.size() ? n : b.size(); + const char* new_data = static_cast<const char*>(b.data()) + offset; + std::size_t new_size = b.size() - offset; return const_buffer(new_data, new_size #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) , b.get_debug_check() @@ -491,17 +677,10 @@ inline const_buffer operator+(const const_buffer& b, std::size_t start) /** * @relates const_buffer */ -inline const_buffer operator+(std::size_t start, const const_buffer& b) +inline const_buffer operator+(std::size_t n, + const const_buffer& b) BOOST_ASIO_NOEXCEPT { - if (start > buffer_size(b)) - return const_buffer(); - const char* new_data = buffer_cast<const char*>(b) + start; - std::size_t new_size = buffer_size(b) - start; - return const_buffer(new_data, new_size -#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) - , b.get_debug_check() -#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING - ); + return b + n; } #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) @@ -586,32 +765,33 @@ private: * * @par Accessing Buffer Contents * - * The contents of a buffer may be accessed using the @ref buffer_size and - * @ref buffer_cast functions: + * The contents of a buffer may be accessed using the @c data() and @c size() + * member functions: * * @code boost::asio::mutable_buffer b1 = ...; - * std::size_t s1 = boost::asio::buffer_size(b1); - * unsigned char* p1 = boost::asio::buffer_cast<unsigned char*>(b1); + * std::size_t s1 = b1.size(); + * unsigned char* p1 = static_cast<unsigned char*>(b1.data()); * * boost::asio::const_buffer b2 = ...; - * std::size_t s2 = boost::asio::buffer_size(b2); - * const void* p2 = boost::asio::buffer_cast<const void*>(b2); @endcode + * std::size_t s2 = b2.size(); + * const void* p2 = b2.data(); @endcode * - * The boost::asio::buffer_cast function permits violations of type safety, so + * The @c data() member function permits violations of type safety, so * uses of it in application code should be carefully considered. * - * For convenience, the @ref buffer_size function also works on buffer - * sequences (that is, types meeting the ConstBufferSequence or - * MutableBufferSequence type requirements). In this case, the function returns - * the total size of all buffers in the sequence. + * For convenience, a @ref buffer_size function is provided that works with + * both buffers and buffer sequences (that is, types meeting the + * ConstBufferSequence or MutableBufferSequence type requirements). In this + * case, the function returns the total size of all buffers in the sequence. * * @par Buffer Copying * * The @ref buffer_copy function may be used to copy raw bytes between * individual buffers and buffer sequences. - * - * In particular, when used with the @ref buffer_size, the @ref buffer_copy - * function can be used to linearise a sequence of buffers. For example: +* + * In particular, when used with the @ref buffer_size function, the @ref + * buffer_copy function can be used to linearise a sequence of buffers. For + * example: * * @code vector<const_buffer> buffers = ...; * @@ -700,29 +880,38 @@ private: */ /*@{*/ +#if defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) +# define BOOST_ASIO_MUTABLE_BUFFER mutable_buffer +# define BOOST_ASIO_CONST_BUFFER const_buffer +#else // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) +# define BOOST_ASIO_MUTABLE_BUFFER mutable_buffers_1 +# define BOOST_ASIO_CONST_BUFFER const_buffers_1 +#endif // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) + /// Create a new modifiable buffer from an existing buffer. /** - * @returns <tt>mutable_buffers_1(b)</tt>. + * @returns <tt>mutable_buffer(b)</tt>. */ -inline mutable_buffers_1 buffer(const mutable_buffer& b) +inline BOOST_ASIO_MUTABLE_BUFFER buffer( + const mutable_buffer& b) BOOST_ASIO_NOEXCEPT { - return mutable_buffers_1(b); + return BOOST_ASIO_MUTABLE_BUFFER(b); } /// Create a new modifiable buffer from an existing buffer. /** - * @returns A mutable_buffers_1 value equivalent to: - * @code mutable_buffers_1( - * buffer_cast<void*>(b), - * min(buffer_size(b), max_size_in_bytes)); @endcode + * @returns A mutable_buffer value equivalent to: + * @code mutable_buffer( + * b.data(), + * min(b.size(), max_size_in_bytes)); @endcode */ -inline mutable_buffers_1 buffer(const mutable_buffer& b, - std::size_t max_size_in_bytes) +inline BOOST_ASIO_MUTABLE_BUFFER buffer(const mutable_buffer& b, + std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT { - return mutable_buffers_1( - mutable_buffer(buffer_cast<void*>(b), - buffer_size(b) < max_size_in_bytes - ? buffer_size(b) : max_size_in_bytes + return BOOST_ASIO_MUTABLE_BUFFER( + mutable_buffer(b.data(), + b.size() < max_size_in_bytes + ? b.size() : max_size_in_bytes #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) , b.get_debug_check() #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING @@ -731,110 +920,110 @@ inline mutable_buffers_1 buffer(const mutable_buffer& b, /// Create a new non-modifiable buffer from an existing buffer. /** - * @returns <tt>const_buffers_1(b)</tt>. + * @returns <tt>const_buffer(b)</tt>. */ -inline const_buffers_1 buffer(const const_buffer& b) +inline BOOST_ASIO_CONST_BUFFER buffer( + const const_buffer& b) BOOST_ASIO_NOEXCEPT { - return const_buffers_1(b); + return BOOST_ASIO_CONST_BUFFER(b); } /// Create a new non-modifiable buffer from an existing buffer. /** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( - * buffer_cast<const void*>(b), - * min(buffer_size(b), max_size_in_bytes)); @endcode + * @returns A const_buffer value equivalent to: + * @code const_buffer( + * b.data(), + * min(b.size(), max_size_in_bytes)); @endcode */ -inline const_buffers_1 buffer(const const_buffer& b, - std::size_t max_size_in_bytes) +inline BOOST_ASIO_CONST_BUFFER buffer(const const_buffer& b, + std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT { - return const_buffers_1( - const_buffer(buffer_cast<const void*>(b), - buffer_size(b) < max_size_in_bytes - ? buffer_size(b) : max_size_in_bytes + return BOOST_ASIO_CONST_BUFFER(b.data(), + b.size() < max_size_in_bytes + ? b.size() : max_size_in_bytes #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) - , b.get_debug_check() + , b.get_debug_check() #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING - )); + ); } /// Create a new modifiable buffer that represents the given memory range. /** - * @returns <tt>mutable_buffers_1(data, size_in_bytes)</tt>. + * @returns <tt>mutable_buffer(data, size_in_bytes)</tt>. */ -inline mutable_buffers_1 buffer(void* data, std::size_t size_in_bytes) +inline BOOST_ASIO_MUTABLE_BUFFER buffer(void* data, + std::size_t size_in_bytes) BOOST_ASIO_NOEXCEPT { - return mutable_buffers_1(mutable_buffer(data, size_in_bytes)); + return BOOST_ASIO_MUTABLE_BUFFER(data, size_in_bytes); } /// Create a new non-modifiable buffer that represents the given memory range. /** - * @returns <tt>const_buffers_1(data, size_in_bytes)</tt>. + * @returns <tt>const_buffer(data, size_in_bytes)</tt>. */ -inline const_buffers_1 buffer(const void* data, - std::size_t size_in_bytes) +inline BOOST_ASIO_CONST_BUFFER buffer(const void* data, + std::size_t size_in_bytes) BOOST_ASIO_NOEXCEPT { - return const_buffers_1(const_buffer(data, size_in_bytes)); + return BOOST_ASIO_CONST_BUFFER(data, size_in_bytes); } /// Create a new modifiable buffer that represents the given POD array. /** - * @returns A mutable_buffers_1 value equivalent to: - * @code mutable_buffers_1( + * @returns A mutable_buffer value equivalent to: + * @code mutable_buffer( * static_cast<void*>(data), * N * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N> -inline mutable_buffers_1 buffer(PodType (&data)[N]) +inline BOOST_ASIO_MUTABLE_BUFFER buffer(PodType (&data)[N]) BOOST_ASIO_NOEXCEPT { - return mutable_buffers_1(mutable_buffer(data, N * sizeof(PodType))); + return BOOST_ASIO_MUTABLE_BUFFER(data, N * sizeof(PodType)); } /// Create a new modifiable buffer that represents the given POD array. /** - * @returns A mutable_buffers_1 value equivalent to: - * @code mutable_buffers_1( + * @returns A mutable_buffer value equivalent to: + * @code mutable_buffer( * static_cast<void*>(data), * min(N * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N> -inline mutable_buffers_1 buffer(PodType (&data)[N], - std::size_t max_size_in_bytes) +inline BOOST_ASIO_MUTABLE_BUFFER buffer(PodType (&data)[N], + std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT { - return mutable_buffers_1( - mutable_buffer(data, - N * sizeof(PodType) < max_size_in_bytes - ? N * sizeof(PodType) : max_size_in_bytes)); + return BOOST_ASIO_MUTABLE_BUFFER(data, + N * sizeof(PodType) < max_size_in_bytes + ? N * sizeof(PodType) : max_size_in_bytes); } /// Create a new non-modifiable buffer that represents the given POD array. /** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( + * @returns A const_buffer value equivalent to: + * @code const_buffer( * static_cast<const void*>(data), * N * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N> -inline const_buffers_1 buffer(const PodType (&data)[N]) +inline BOOST_ASIO_CONST_BUFFER buffer( + const PodType (&data)[N]) BOOST_ASIO_NOEXCEPT { - return const_buffers_1(const_buffer(data, N * sizeof(PodType))); + return BOOST_ASIO_CONST_BUFFER(data, N * sizeof(PodType)); } /// Create a new non-modifiable buffer that represents the given POD array. /** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( + * @returns A const_buffer value equivalent to: + * @code const_buffer( * static_cast<const void*>(data), * min(N * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N> -inline const_buffers_1 buffer(const PodType (&data)[N], - std::size_t max_size_in_bytes) +inline BOOST_ASIO_CONST_BUFFER buffer(const PodType (&data)[N], + std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT { - return const_buffers_1( - const_buffer(data, - N * sizeof(PodType) < max_size_in_bytes - ? N * sizeof(PodType) : max_size_in_bytes)); + return BOOST_ASIO_CONST_BUFFER(data, + N * sizeof(PodType) < max_size_in_bytes + ? N * sizeof(PodType) : max_size_in_bytes); } #if defined(BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND) @@ -860,14 +1049,14 @@ template <> struct buffer_types_base<false> { typedef mutable_buffer buffer_type; - typedef mutable_buffers_1 container_type; + typedef BOOST_ASIO_MUTABLE_BUFFER container_type; }; template <> struct buffer_types_base<true> { typedef const_buffer buffer_type; - typedef const_buffers_1 container_type; + typedef BOOST_ASIO_CONST_BUFFER container_type; }; template <typename PodType> @@ -880,7 +1069,7 @@ struct buffer_types template <typename PodType, std::size_t N> inline typename detail::buffer_types<PodType>::container_type -buffer(boost::array<PodType, N>& data) +buffer(boost::array<PodType, N>& data) BOOST_ASIO_NOEXCEPT { typedef typename boost::asio::detail::buffer_types<PodType>::buffer_type buffer_type; @@ -892,7 +1081,8 @@ buffer(boost::array<PodType, N>& data) template <typename PodType, std::size_t N> inline typename detail::buffer_types<PodType>::container_type -buffer(boost::array<PodType, N>& data, std::size_t max_size_in_bytes) +buffer(boost::array<PodType, N>& data, + std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT { typedef typename boost::asio::detail::buffer_types<PodType>::buffer_type buffer_type; @@ -908,200 +1098,195 @@ buffer(boost::array<PodType, N>& data, std::size_t max_size_in_bytes) /// Create a new modifiable buffer that represents the given POD array. /** - * @returns A mutable_buffers_1 value equivalent to: - * @code mutable_buffers_1( + * @returns A mutable_buffer value equivalent to: + * @code mutable_buffer( * data.data(), * data.size() * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N> -inline mutable_buffers_1 buffer(boost::array<PodType, N>& data) +inline BOOST_ASIO_MUTABLE_BUFFER buffer( + boost::array<PodType, N>& data) BOOST_ASIO_NOEXCEPT { - return mutable_buffers_1( - mutable_buffer(data.c_array(), data.size() * sizeof(PodType))); + return BOOST_ASIO_MUTABLE_BUFFER( + data.c_array(), data.size() * sizeof(PodType)); } /// Create a new modifiable buffer that represents the given POD array. /** - * @returns A mutable_buffers_1 value equivalent to: - * @code mutable_buffers_1( + * @returns A mutable_buffer value equivalent to: + * @code mutable_buffer( * data.data(), * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N> -inline mutable_buffers_1 buffer(boost::array<PodType, N>& data, - std::size_t max_size_in_bytes) +inline BOOST_ASIO_MUTABLE_BUFFER buffer(boost::array<PodType, N>& data, + std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT { - return mutable_buffers_1( - mutable_buffer(data.c_array(), - data.size() * sizeof(PodType) < max_size_in_bytes - ? data.size() * sizeof(PodType) : max_size_in_bytes)); + return BOOST_ASIO_MUTABLE_BUFFER(data.c_array(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes); } /// Create a new non-modifiable buffer that represents the given POD array. /** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( + * @returns A const_buffer value equivalent to: + * @code const_buffer( * data.data(), * data.size() * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N> -inline const_buffers_1 buffer(boost::array<const PodType, N>& data) +inline BOOST_ASIO_CONST_BUFFER buffer( + boost::array<const PodType, N>& data) BOOST_ASIO_NOEXCEPT { - return const_buffers_1( - const_buffer(data.data(), data.size() * sizeof(PodType))); + return BOOST_ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType)); } /// Create a new non-modifiable buffer that represents the given POD array. /** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( + * @returns A const_buffer value equivalent to: + * @code const_buffer( * data.data(), * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N> -inline const_buffers_1 buffer(boost::array<const PodType, N>& data, - std::size_t max_size_in_bytes) +inline BOOST_ASIO_CONST_BUFFER buffer(boost::array<const PodType, N>& data, + std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT { - return const_buffers_1( - const_buffer(data.data(), - data.size() * sizeof(PodType) < max_size_in_bytes - ? data.size() * sizeof(PodType) : max_size_in_bytes)); + return BOOST_ASIO_CONST_BUFFER(data.data(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes); } #endif // defined(BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND) /// Create a new non-modifiable buffer that represents the given POD array. /** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( + * @returns A const_buffer value equivalent to: + * @code const_buffer( * data.data(), * data.size() * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N> -inline const_buffers_1 buffer(const boost::array<PodType, N>& data) +inline BOOST_ASIO_CONST_BUFFER buffer( + const boost::array<PodType, N>& data) BOOST_ASIO_NOEXCEPT { - return const_buffers_1( - const_buffer(data.data(), data.size() * sizeof(PodType))); + return BOOST_ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType)); } /// Create a new non-modifiable buffer that represents the given POD array. /** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( + * @returns A const_buffer value equivalent to: + * @code const_buffer( * data.data(), * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N> -inline const_buffers_1 buffer(const boost::array<PodType, N>& data, - std::size_t max_size_in_bytes) +inline BOOST_ASIO_CONST_BUFFER buffer(const boost::array<PodType, N>& data, + std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT { - return const_buffers_1( - const_buffer(data.data(), - data.size() * sizeof(PodType) < max_size_in_bytes - ? data.size() * sizeof(PodType) : max_size_in_bytes)); + return BOOST_ASIO_CONST_BUFFER(data.data(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes); } #if defined(BOOST_ASIO_HAS_STD_ARRAY) || defined(GENERATING_DOCUMENTATION) /// Create a new modifiable buffer that represents the given POD array. /** - * @returns A mutable_buffers_1 value equivalent to: - * @code mutable_buffers_1( + * @returns A mutable_buffer value equivalent to: + * @code mutable_buffer( * data.data(), * data.size() * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N> -inline mutable_buffers_1 buffer(std::array<PodType, N>& data) +inline BOOST_ASIO_MUTABLE_BUFFER buffer( + std::array<PodType, N>& data) BOOST_ASIO_NOEXCEPT { - return mutable_buffers_1( - mutable_buffer(data.data(), data.size() * sizeof(PodType))); + return BOOST_ASIO_MUTABLE_BUFFER(data.data(), data.size() * sizeof(PodType)); } /// Create a new modifiable buffer that represents the given POD array. /** - * @returns A mutable_buffers_1 value equivalent to: - * @code mutable_buffers_1( + * @returns A mutable_buffer value equivalent to: + * @code mutable_buffer( * data.data(), * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N> -inline mutable_buffers_1 buffer(std::array<PodType, N>& data, - std::size_t max_size_in_bytes) +inline BOOST_ASIO_MUTABLE_BUFFER buffer(std::array<PodType, N>& data, + std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT { - return mutable_buffers_1( - mutable_buffer(data.data(), - data.size() * sizeof(PodType) < max_size_in_bytes - ? data.size() * sizeof(PodType) : max_size_in_bytes)); + return BOOST_ASIO_MUTABLE_BUFFER(data.data(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes); } /// Create a new non-modifiable buffer that represents the given POD array. /** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( + * @returns A const_buffer value equivalent to: + * @code const_buffer( * data.data(), * data.size() * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N> -inline const_buffers_1 buffer(std::array<const PodType, N>& data) +inline BOOST_ASIO_CONST_BUFFER buffer( + std::array<const PodType, N>& data) BOOST_ASIO_NOEXCEPT { - return const_buffers_1( - const_buffer(data.data(), data.size() * sizeof(PodType))); + return BOOST_ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType)); } /// Create a new non-modifiable buffer that represents the given POD array. /** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( + * @returns A const_buffer value equivalent to: + * @code const_buffer( * data.data(), * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N> -inline const_buffers_1 buffer(std::array<const PodType, N>& data, - std::size_t max_size_in_bytes) +inline BOOST_ASIO_CONST_BUFFER buffer(std::array<const PodType, N>& data, + std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT { - return const_buffers_1( - const_buffer(data.data(), - data.size() * sizeof(PodType) < max_size_in_bytes - ? data.size() * sizeof(PodType) : max_size_in_bytes)); + return BOOST_ASIO_CONST_BUFFER(data.data(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes); } /// Create a new non-modifiable buffer that represents the given POD array. /** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( + * @returns A const_buffer value equivalent to: + * @code const_buffer( * data.data(), * data.size() * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N> -inline const_buffers_1 buffer(const std::array<PodType, N>& data) +inline BOOST_ASIO_CONST_BUFFER buffer( + const std::array<PodType, N>& data) BOOST_ASIO_NOEXCEPT { - return const_buffers_1( - const_buffer(data.data(), data.size() * sizeof(PodType))); + return BOOST_ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType)); } /// Create a new non-modifiable buffer that represents the given POD array. /** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( + * @returns A const_buffer value equivalent to: + * @code const_buffer( * data.data(), * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N> -inline const_buffers_1 buffer(const std::array<PodType, N>& data, - std::size_t max_size_in_bytes) +inline BOOST_ASIO_CONST_BUFFER buffer(const std::array<PodType, N>& data, + std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT { - return const_buffers_1( - const_buffer(data.data(), - data.size() * sizeof(PodType) < max_size_in_bytes - ? data.size() * sizeof(PodType) : max_size_in_bytes)); + return BOOST_ASIO_CONST_BUFFER(data.data(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes); } #endif // defined(BOOST_ASIO_HAS_STD_ARRAY) || defined(GENERATING_DOCUMENTATION) /// Create a new modifiable buffer that represents the given POD vector. /** - * @returns A mutable_buffers_1 value equivalent to: - * @code mutable_buffers_1( + * @returns A mutable_buffer value equivalent to: + * @code mutable_buffer( * data.size() ? &data[0] : 0, * data.size() * sizeof(PodType)); @endcode * @@ -1109,22 +1294,23 @@ inline const_buffers_1 buffer(const std::array<PodType, N>& data, * invalidate iterators. */ template <typename PodType, typename Allocator> -inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data) +inline BOOST_ASIO_MUTABLE_BUFFER buffer( + std::vector<PodType, Allocator>& data) BOOST_ASIO_NOEXCEPT { - return mutable_buffers_1( - mutable_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType) + return BOOST_ASIO_MUTABLE_BUFFER( + data.size() ? &data[0] : 0, data.size() * sizeof(PodType) #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) - , detail::buffer_debug_check< - typename std::vector<PodType, Allocator>::iterator - >(data.begin()) + , detail::buffer_debug_check< + typename std::vector<PodType, Allocator>::iterator + >(data.begin()) #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING - )); + ); } /// Create a new modifiable buffer that represents the given POD vector. /** - * @returns A mutable_buffers_1 value equivalent to: - * @code mutable_buffers_1( + * @returns A mutable_buffer value equivalent to: + * @code mutable_buffer( * data.size() ? &data[0] : 0, * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode * @@ -1132,25 +1318,24 @@ inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data) * invalidate iterators. */ template <typename PodType, typename Allocator> -inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data, - std::size_t max_size_in_bytes) +inline BOOST_ASIO_MUTABLE_BUFFER buffer(std::vector<PodType, Allocator>& data, + std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT { - return mutable_buffers_1( - mutable_buffer(data.size() ? &data[0] : 0, - data.size() * sizeof(PodType) < max_size_in_bytes - ? data.size() * sizeof(PodType) : max_size_in_bytes + return BOOST_ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0, + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) - , detail::buffer_debug_check< - typename std::vector<PodType, Allocator>::iterator - >(data.begin()) + , detail::buffer_debug_check< + typename std::vector<PodType, Allocator>::iterator + >(data.begin()) #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING - )); + ); } /// Create a new non-modifiable buffer that represents the given POD vector. /** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( + * @returns A const_buffer value equivalent to: + * @code const_buffer( * data.size() ? &data[0] : 0, * data.size() * sizeof(PodType)); @endcode * @@ -1158,23 +1343,23 @@ inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data, * invalidate iterators. */ template <typename PodType, typename Allocator> -inline const_buffers_1 buffer( - const std::vector<PodType, Allocator>& data) +inline BOOST_ASIO_CONST_BUFFER buffer( + const std::vector<PodType, Allocator>& data) BOOST_ASIO_NOEXCEPT { - return const_buffers_1( - const_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType) + return BOOST_ASIO_CONST_BUFFER( + data.size() ? &data[0] : 0, data.size() * sizeof(PodType) #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) - , detail::buffer_debug_check< - typename std::vector<PodType, Allocator>::const_iterator - >(data.begin()) + , detail::buffer_debug_check< + typename std::vector<PodType, Allocator>::const_iterator + >(data.begin()) #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING - )); + ); } /// Create a new non-modifiable buffer that represents the given POD vector. /** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( + * @returns A const_buffer value equivalent to: + * @code const_buffer( * data.size() ? &data[0] : 0, * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode * @@ -1182,527 +1367,640 @@ inline const_buffers_1 buffer( * invalidate iterators. */ template <typename PodType, typename Allocator> -inline const_buffers_1 buffer( - const std::vector<PodType, Allocator>& data, std::size_t max_size_in_bytes) +inline BOOST_ASIO_CONST_BUFFER buffer( + const std::vector<PodType, Allocator>& data, + std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT { - return const_buffers_1( - const_buffer(data.size() ? &data[0] : 0, - data.size() * sizeof(PodType) < max_size_in_bytes - ? data.size() * sizeof(PodType) : max_size_in_bytes + return BOOST_ASIO_CONST_BUFFER(data.size() ? &data[0] : 0, + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) - , detail::buffer_debug_check< - typename std::vector<PodType, Allocator>::const_iterator - >(data.begin()) + , detail::buffer_debug_check< + typename std::vector<PodType, Allocator>::const_iterator + >(data.begin()) #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING - )); + ); } -/// Create a new non-modifiable buffer that represents the given string. +/// Create a new modifiable buffer that represents the given string. /** - * @returns <tt>const_buffers_1(data.data(), data.size() * sizeof(Elem))</tt>. + * @returns <tt>mutable_buffer(data.size() ? &data[0] : 0, + * data.size() * sizeof(Elem))</tt>. * * @note The buffer is invalidated by any non-const operation called on the * given string object. */ template <typename Elem, typename Traits, typename Allocator> -inline const_buffers_1 buffer( - const std::basic_string<Elem, Traits, Allocator>& data) +inline BOOST_ASIO_MUTABLE_BUFFER buffer( + std::basic_string<Elem, Traits, Allocator>& data) BOOST_ASIO_NOEXCEPT { - return const_buffers_1(const_buffer(data.data(), data.size() * sizeof(Elem) + return BOOST_ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0, + data.size() * sizeof(Elem) #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) - , detail::buffer_debug_check< - typename std::basic_string<Elem, Traits, Allocator>::const_iterator - >(data.begin()) + , detail::buffer_debug_check< + typename std::basic_string<Elem, Traits, Allocator>::iterator + >(data.begin()) #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING - )); + ); } /// Create a new non-modifiable buffer that represents the given string. /** - * @returns A const_buffers_1 value equivalent to: - * @code const_buffers_1( - * data.data(), + * @returns A mutable_buffer value equivalent to: + * @code mutable_buffer( + * data.size() ? &data[0] : 0, * min(data.size() * sizeof(Elem), max_size_in_bytes)); @endcode * * @note The buffer is invalidated by any non-const operation called on the * given string object. */ template <typename Elem, typename Traits, typename Allocator> -inline const_buffers_1 buffer( - const std::basic_string<Elem, Traits, Allocator>& data, - std::size_t max_size_in_bytes) +inline BOOST_ASIO_MUTABLE_BUFFER buffer( + std::basic_string<Elem, Traits, Allocator>& data, + std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT { - return const_buffers_1( - const_buffer(data.data(), - data.size() * sizeof(Elem) < max_size_in_bytes - ? data.size() * sizeof(Elem) : max_size_in_bytes + return BOOST_ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0, + data.size() * sizeof(Elem) < max_size_in_bytes + ? data.size() * sizeof(Elem) : max_size_in_bytes #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) - , detail::buffer_debug_check< - typename std::basic_string<Elem, Traits, Allocator>::const_iterator - >(data.begin()) + , detail::buffer_debug_check< + typename std::basic_string<Elem, Traits, Allocator>::iterator + >(data.begin()) #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING - )); + ); } -/*@}*/ - -/** @defgroup buffer_copy boost::asio::buffer_copy - * - * @brief The boost::asio::buffer_copy function is used to copy bytes from a - * source buffer (or buffer sequence) to a target buffer (or buffer sequence). - * - * The @c buffer_copy function is available in two forms: - * - * @li A 2-argument form: @c buffer_copy(target, source) - * - * @li A 3-argument form: @c buffer_copy(target, source, max_bytes_to_copy) - - * Both forms return the number of bytes actually copied. The number of bytes - * copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * @li @c If specified, @c max_bytes_to_copy. - * - * This prevents buffer overflow, regardless of the buffer sizes used in the - * copy operation. - * - * Note that @ref buffer_copy is implemented in terms of @c memcpy, and - * consequently it cannot be used to copy between overlapping memory regions. - */ -/*@{*/ - -/// Copies bytes from a source buffer to a target buffer. +/// Create a new non-modifiable buffer that represents the given string. /** - * @param target A modifiable buffer representing the memory region to which - * the bytes will be copied. + * @returns <tt>const_buffer(data.data(), data.size() * sizeof(Elem))</tt>. * - * @param source A non-modifiable buffer representing the memory region from - * which the bytes will be copied. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. + * @note The buffer is invalidated by any non-const operation called on the + * given string object. */ -inline std::size_t buffer_copy(const mutable_buffer& target, - const const_buffer& source) +template <typename Elem, typename Traits, typename Allocator> +inline BOOST_ASIO_CONST_BUFFER buffer( + const std::basic_string<Elem, Traits, Allocator>& data) BOOST_ASIO_NOEXCEPT { - using namespace std; // For memcpy. - std::size_t target_size = buffer_size(target); - std::size_t source_size = buffer_size(source); - std::size_t n = target_size < source_size ? target_size : source_size; - memcpy(buffer_cast<void*>(target), buffer_cast<const void*>(source), n); - return n; + return BOOST_ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(Elem) +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , detail::buffer_debug_check< + typename std::basic_string<Elem, Traits, Allocator>::const_iterator + >(data.begin()) +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + ); } -/// Copies bytes from a source buffer to a target buffer. +/// Create a new non-modifiable buffer that represents the given string. /** - * @param target A modifiable buffer representing the memory region to which - * the bytes will be copied. - * - * @param source A non-modifiable buffer representing the memory region from - * which the bytes will be copied. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) + * @returns A const_buffer value equivalent to: + * @code const_buffer( + * data.data(), + * min(data.size() * sizeof(Elem), max_size_in_bytes)); @endcode * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. + * @note The buffer is invalidated by any non-const operation called on the + * given string object. */ -inline std::size_t buffer_copy(const mutable_buffer& target, - const const_buffers_1& source) +template <typename Elem, typename Traits, typename Allocator> +inline BOOST_ASIO_CONST_BUFFER buffer( + const std::basic_string<Elem, Traits, Allocator>& data, + std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT { - return buffer_copy(target, static_cast<const const_buffer&>(source)); + return BOOST_ASIO_CONST_BUFFER(data.data(), + data.size() * sizeof(Elem) < max_size_in_bytes + ? data.size() * sizeof(Elem) : max_size_in_bytes +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , detail::buffer_debug_check< + typename std::basic_string<Elem, Traits, Allocator>::const_iterator + >(data.begin()) +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + ); } -/// Copies bytes from a source buffer to a target buffer. +#if defined(BOOST_ASIO_HAS_STD_STRING_VIEW) \ + || defined(GENERATING_DOCUMENTATION) + +/// Create a new modifiable buffer that represents the given string_view. /** - * @param target A modifiable buffer representing the memory region to which - * the bytes will be copied. - * - * @param source A modifiable buffer representing the memory region from which - * the bytes will be copied. The contents of the source buffer will not be - * modified. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. + * @returns <tt>mutable_buffer(data.size() ? &data[0] : 0, + * data.size() * sizeof(Elem))</tt>. */ -inline std::size_t buffer_copy(const mutable_buffer& target, - const mutable_buffer& source) +template <typename Elem, typename Traits> +inline BOOST_ASIO_CONST_BUFFER buffer( + basic_string_view<Elem, Traits> data) BOOST_ASIO_NOEXCEPT { - return buffer_copy(target, const_buffer(source)); + return BOOST_ASIO_CONST_BUFFER(data.size() ? &data[0] : 0, + data.size() * sizeof(Elem) +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , detail::buffer_debug_check< + typename basic_string_view<Elem, Traits>::iterator + >(data.begin()) +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + ); } -/// Copies bytes from a source buffer to a target buffer. +/// Create a new non-modifiable buffer that represents the given string. /** - * @param target A modifiable buffer representing the memory region to which - * the bytes will be copied. - * - * @param source A modifiable buffer representing the memory region from which - * the bytes will be copied. The contents of the source buffer will not be - * modified. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. + * @returns A mutable_buffer value equivalent to: + * @code mutable_buffer( + * data.size() ? &data[0] : 0, + * min(data.size() * sizeof(Elem), max_size_in_bytes)); @endcode */ -inline std::size_t buffer_copy(const mutable_buffer& target, - const mutable_buffers_1& source) +template <typename Elem, typename Traits> +inline BOOST_ASIO_CONST_BUFFER buffer( + basic_string_view<Elem, Traits> data, + std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT { - return buffer_copy(target, const_buffer(source)); + return BOOST_ASIO_CONST_BUFFER(data.size() ? &data[0] : 0, + data.size() * sizeof(Elem) < max_size_in_bytes + ? data.size() * sizeof(Elem) : max_size_in_bytes +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , detail::buffer_debug_check< + typename basic_string_view<Elem, Traits>::iterator + >(data.begin()) +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + ); } -/// Copies bytes from a source buffer sequence to a target buffer. +#endif // defined(BOOST_ASIO_HAS_STD_STRING_VIEW) + // || defined(GENERATING_DOCUMENTATION) + +/*@}*/ + +/// Adapt a basic_string to the DynamicBuffer requirements. /** - * @param target A modifiable buffer representing the memory region to which - * the bytes will be copied. - * - * @param source A non-modifiable buffer sequence representing the memory - * regions from which the bytes will be copied. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. + * Requires that <tt>sizeof(Elem) == 1</tt>. */ -template <typename ConstBufferSequence> -std::size_t buffer_copy(const mutable_buffer& target, - const ConstBufferSequence& source) +template <typename Elem, typename Traits, typename Allocator> +class dynamic_string_buffer { - std::size_t total_bytes_copied = 0; +public: + /// The type used to represent the input sequence as a list of buffers. + typedef BOOST_ASIO_CONST_BUFFER const_buffers_type; + + /// The type used to represent the output sequence as a list of buffers. + typedef BOOST_ASIO_MUTABLE_BUFFER mutable_buffers_type; + + /// Construct a dynamic buffer from a string. + /** + * @param s The string to be used as backing storage for the dynamic buffer. + * Any existing data in the string is treated as the dynamic buffer's input + * sequence. The object stores a reference to the string and the user is + * responsible for ensuring that the string object remains valid until the + * dynamic_string_buffer object is destroyed. + * + * @param maximum_size Specifies a maximum size for the buffer, in bytes. + */ + explicit dynamic_string_buffer(std::basic_string<Elem, Traits, Allocator>& s, + std::size_t maximum_size = + (std::numeric_limits<std::size_t>::max)()) BOOST_ASIO_NOEXCEPT + : string_(s), + size_(string_.size()), + max_size_(maximum_size) + { + } + +#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Move construct a dynamic buffer. + dynamic_string_buffer(dynamic_string_buffer&& other) BOOST_ASIO_NOEXCEPT + : string_(other.string_), + size_(other.size_), + max_size_(other.max_size_) + { + } +#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - typename ConstBufferSequence::const_iterator source_iter = source.begin(); - typename ConstBufferSequence::const_iterator source_end = source.end(); + /// Get the size of the input sequence. + std::size_t size() const BOOST_ASIO_NOEXCEPT + { + return size_; + } - for (mutable_buffer target_buffer(target); - buffer_size(target_buffer) && source_iter != source_end; ++source_iter) + /// Get the maximum size of the dynamic buffer. + /** + * @returns The allowed maximum of the sum of the sizes of the input sequence + * and output sequence. + */ + std::size_t max_size() const BOOST_ASIO_NOEXCEPT { - const_buffer source_buffer(*source_iter); - std::size_t bytes_copied = buffer_copy(target_buffer, source_buffer); - total_bytes_copied += bytes_copied; - target_buffer = target_buffer + bytes_copied; + return max_size_; } - return total_bytes_copied; -} + /// Get the current capacity of the dynamic buffer. + /** + * @returns The current total capacity of the buffer, i.e. for both the input + * sequence and output sequence. + */ + std::size_t capacity() const BOOST_ASIO_NOEXCEPT + { + return string_.capacity(); + } + + /// Get a list of buffers that represents the input sequence. + /** + * @returns An object of type @c const_buffers_type that satisfies + * ConstBufferSequence requirements, representing the basic_string memory in + * input sequence. + * + * @note The returned object is invalidated by any @c dynamic_string_buffer + * or @c basic_string member function that modifies the input sequence or + * output sequence. + */ + const_buffers_type data() const BOOST_ASIO_NOEXCEPT + { + return const_buffers_type(boost::asio::buffer(string_, size_)); + } + + /// Get a list of buffers that represents the output sequence, with the given + /// size. + /** + * Ensures that the output sequence can accommodate @c n bytes, resizing the + * basic_string object as necessary. + * + * @returns An object of type @c mutable_buffers_type that satisfies + * MutableBufferSequence requirements, representing basic_string memory + * at the start of the output sequence of size @c n. + * + * @throws std::length_error If <tt>size() + n > max_size()</tt>. + * + * @note The returned object is invalidated by any @c dynamic_string_buffer + * or @c basic_string member function that modifies the input sequence or + * output sequence. + */ + mutable_buffers_type prepare(std::size_t n) + { + if (size () > max_size() || max_size() - size() < n) + { + std::length_error ex("dynamic_string_buffer too long"); + boost::asio::detail::throw_exception(ex); + } + + string_.resize(size_ + n); + + return boost::asio::buffer(boost::asio::buffer(string_) + size_, n); + } + + /// Move bytes from the output sequence to the input sequence. + /** + * @param n The number of bytes to append from the start of the output + * sequence to the end of the input sequence. The remainder of the output + * sequence is discarded. + * + * Requires a preceding call <tt>prepare(x)</tt> where <tt>x >= n</tt>, and + * no intervening operations that modify the input or output sequence. + * + * @note If @c n is greater than the size of the output sequence, the entire + * output sequence is moved to the input sequence and no error is issued. + */ + void commit(std::size_t n) + { + size_ += (std::min)(n, string_.size() - size_); + string_.resize(size_); + } + + /// Remove characters from the input sequence. + /** + * Removes @c n characters from the beginning of the input sequence. + * + * @note If @c n is greater than the size of the input sequence, the entire + * input sequence is consumed and no error is issued. + */ + void consume(std::size_t n) + { + std::size_t consume_length = (std::min)(n, size_); + string_.erase(0, consume_length); + size_ -= consume_length; + } + +private: + std::basic_string<Elem, Traits, Allocator>& string_; + std::size_t size_; + const std::size_t max_size_; +}; -/// Copies bytes from a source buffer to a target buffer. +/// Adapt a vector to the DynamicBuffer requirements. /** - * @param target A modifiable buffer representing the memory region to which - * the bytes will be copied. - * - * @param source A non-modifiable buffer representing the memory region from - * which the bytes will be copied. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. + * Requires that <tt>sizeof(Elem) == 1</tt>. */ -inline std::size_t buffer_copy(const mutable_buffers_1& target, - const const_buffer& source) +template <typename Elem, typename Allocator> +class dynamic_vector_buffer { - return buffer_copy(static_cast<const mutable_buffer&>(target), source); -} +public: + /// The type used to represent the input sequence as a list of buffers. + typedef BOOST_ASIO_CONST_BUFFER const_buffers_type; + + /// The type used to represent the output sequence as a list of buffers. + typedef BOOST_ASIO_MUTABLE_BUFFER mutable_buffers_type; + + /// Construct a dynamic buffer from a string. + /** + * @param v The vector to be used as backing storage for the dynamic buffer. + * Any existing data in the vector is treated as the dynamic buffer's input + * sequence. The object stores a reference to the vector and the user is + * responsible for ensuring that the vector object remains valid until the + * dynamic_vector_buffer object is destroyed. + * + * @param maximum_size Specifies a maximum size for the buffer, in bytes. + */ + explicit dynamic_vector_buffer(std::vector<Elem, Allocator>& v, + std::size_t maximum_size = + (std::numeric_limits<std::size_t>::max)()) BOOST_ASIO_NOEXCEPT + : vector_(v), + size_(vector_.size()), + max_size_(maximum_size) + { + } -/// Copies bytes from a source buffer to a target buffer. -/** - * @param target A modifiable buffer representing the memory region to which - * the bytes will be copied. - * - * @param source A non-modifiable buffer representing the memory region from - * which the bytes will be copied. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) +#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Move construct a dynamic buffer. + dynamic_vector_buffer(dynamic_vector_buffer&& other) BOOST_ASIO_NOEXCEPT + : vector_(other.vector_), + size_(other.size_), + max_size_(other.max_size_) + { + } +#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// Get the size of the input sequence. + std::size_t size() const BOOST_ASIO_NOEXCEPT + { + return size_; + } + + /// Get the maximum size of the dynamic buffer. + /** + * @returns The allowed maximum of the sum of the sizes of the input sequence + * and output sequence. + */ + std::size_t max_size() const BOOST_ASIO_NOEXCEPT + { + return max_size_; + } + + /// Get the current capacity of the dynamic buffer. + /** + * @returns The current total capacity of the buffer, i.e. for both the input + * sequence and output sequence. + */ + std::size_t capacity() const BOOST_ASIO_NOEXCEPT + { + return vector_.capacity(); + } + + /// Get a list of buffers that represents the input sequence. + /** + * @returns An object of type @c const_buffers_type that satisfies + * ConstBufferSequence requirements, representing the basic_string memory in + * input sequence. + * + * @note The returned object is invalidated by any @c dynamic_vector_buffer + * or @c basic_string member function that modifies the input sequence or + * output sequence. + */ + const_buffers_type data() const BOOST_ASIO_NOEXCEPT + { + return const_buffers_type(boost::asio::buffer(vector_, size_)); + } + + /// Get a list of buffers that represents the output sequence, with the given + /// size. + /** + * Ensures that the output sequence can accommodate @c n bytes, resizing the + * basic_string object as necessary. + * + * @returns An object of type @c mutable_buffers_type that satisfies + * MutableBufferSequence requirements, representing basic_string memory + * at the start of the output sequence of size @c n. + * + * @throws std::length_error If <tt>size() + n > max_size()</tt>. + * + * @note The returned object is invalidated by any @c dynamic_vector_buffer + * or @c basic_string member function that modifies the input sequence or + * output sequence. + */ + mutable_buffers_type prepare(std::size_t n) + { + if (size () > max_size() || max_size() - size() < n) + { + std::length_error ex("dynamic_vector_buffer too long"); + boost::asio::detail::throw_exception(ex); + } + + vector_.resize(size_ + n); + + return boost::asio::buffer(boost::asio::buffer(vector_) + size_, n); + } + + /// Move bytes from the output sequence to the input sequence. + /** + * @param n The number of bytes to append from the start of the output + * sequence to the end of the input sequence. The remainder of the output + * sequence is discarded. + * + * Requires a preceding call <tt>prepare(x)</tt> where <tt>x >= n</tt>, and + * no intervening operations that modify the input or output sequence. + * + * @note If @c n is greater than the size of the output sequence, the entire + * output sequence is moved to the input sequence and no error is issued. + */ + void commit(std::size_t n) + { + size_ += (std::min)(n, vector_.size() - size_); + vector_.resize(size_); + } + + /// Remove characters from the input sequence. + /** + * Removes @c n characters from the beginning of the input sequence. + * + * @note If @c n is greater than the size of the input sequence, the entire + * input sequence is consumed and no error is issued. + */ + void consume(std::size_t n) + { + std::size_t consume_length = (std::min)(n, size_); + vector_.erase(vector_.begin(), vector_.begin() + consume_length); + size_ -= consume_length; + } + +private: + std::vector<Elem, Allocator>& vector_; + std::size_t size_; + const std::size_t max_size_; +}; + +/** @defgroup dynamic_buffer boost::asio::dynamic_buffer * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. + * @brief The boost::asio::dynamic_buffer function is used to create a + * dynamically resized buffer from a @c std::basic_string or @c std::vector. + */ +/*@{*/ + +/// Create a new dynamic buffer that represents the given string. +/** + * @returns <tt>dynamic_string_buffer<Elem, Traits, Allocator>(data)</tt>. */ -inline std::size_t buffer_copy(const mutable_buffers_1& target, - const const_buffers_1& source) +template <typename Elem, typename Traits, typename Allocator> +inline dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer( + std::basic_string<Elem, Traits, Allocator>& data) BOOST_ASIO_NOEXCEPT { - return buffer_copy(static_cast<const mutable_buffer&>(target), - static_cast<const const_buffer&>(source)); + return dynamic_string_buffer<Elem, Traits, Allocator>(data); } -/// Copies bytes from a source buffer to a target buffer. +/// Create a new dynamic buffer that represents the given string. /** - * @param target A modifiable buffer representing the memory region to which - * the bytes will be copied. - * - * @param source A modifiable buffer representing the memory region from which - * the bytes will be copied. The contents of the source buffer will not be - * modified. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. + * @returns <tt>dynamic_string_buffer<Elem, Traits, Allocator>(data, + * max_size)</tt>. */ -inline std::size_t buffer_copy(const mutable_buffers_1& target, - const mutable_buffer& source) +template <typename Elem, typename Traits, typename Allocator> +inline dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer( + std::basic_string<Elem, Traits, Allocator>& data, + std::size_t max_size) BOOST_ASIO_NOEXCEPT { - return buffer_copy(static_cast<const mutable_buffer&>(target), - const_buffer(source)); + return dynamic_string_buffer<Elem, Traits, Allocator>(data, max_size); } -/// Copies bytes from a source buffer to a target buffer. +/// Create a new dynamic buffer that represents the given vector. /** - * @param target A modifiable buffer representing the memory region to which - * the bytes will be copied. - * - * @param source A modifiable buffer representing the memory region from which - * the bytes will be copied. The contents of the source buffer will not be - * modified. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. + * @returns <tt>dynamic_vector_buffer<Elem, Allocator>(data)</tt>. */ -inline std::size_t buffer_copy(const mutable_buffers_1& target, - const mutable_buffers_1& source) +template <typename Elem, typename Allocator> +inline dynamic_vector_buffer<Elem, Allocator> dynamic_buffer( + std::vector<Elem, Allocator>& data) BOOST_ASIO_NOEXCEPT { - return buffer_copy(static_cast<const mutable_buffer&>(target), - const_buffer(source)); + return dynamic_vector_buffer<Elem, Allocator>(data); } -/// Copies bytes from a source buffer sequence to a target buffer. +/// Create a new dynamic buffer that represents the given vector. /** - * @param target A modifiable buffer representing the memory region to which - * the bytes will be copied. - * - * @param source A non-modifiable buffer sequence representing the memory - * regions from which the bytes will be copied. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. + * @returns <tt>dynamic_vector_buffer<Elem, Allocator>(data, max_size)</tt>. */ -template <typename ConstBufferSequence> -inline std::size_t buffer_copy(const mutable_buffers_1& target, - const ConstBufferSequence& source) +template <typename Elem, typename Allocator> +inline dynamic_vector_buffer<Elem, Allocator> dynamic_buffer( + std::vector<Elem, Allocator>& data, + std::size_t max_size) BOOST_ASIO_NOEXCEPT { - return buffer_copy(static_cast<const mutable_buffer&>(target), source); + return dynamic_vector_buffer<Elem, Allocator>(data, max_size); } -/// Copies bytes from a source buffer to a target buffer sequence. -/** - * @param target A modifiable buffer sequence representing the memory regions to - * which the bytes will be copied. +/*@}*/ + +/** @defgroup buffer_copy boost::asio::buffer_copy * - * @param source A non-modifiable buffer representing the memory region from - * which the bytes will be copied. + * @brief The boost::asio::buffer_copy function is used to copy bytes from a + * source buffer (or buffer sequence) to a target buffer (or buffer sequence). * - * @returns The number of bytes copied. + * The @c buffer_copy function is available in two forms: * - * @note The number of bytes copied is the lesser of: + * @li A 2-argument form: @c buffer_copy(target, source) + * + * @li A 3-argument form: @c buffer_copy(target, source, max_bytes_to_copy) + * + * Both forms return the number of bytes actually copied. The number of bytes + * copied is the lesser of: * * @li @c buffer_size(target) * * @li @c buffer_size(source) * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. + * @li @c If specified, @c max_bytes_to_copy. + * + * This prevents buffer overflow, regardless of the buffer sizes used in the + * copy operation. + * + * Note that @ref buffer_copy is implemented in terms of @c memcpy, and + * consequently it cannot be used to copy between overlapping memory regions. */ -template <typename MutableBufferSequence> -std::size_t buffer_copy(const MutableBufferSequence& target, +/*@{*/ + +namespace detail { + +inline std::size_t buffer_copy_1(const mutable_buffer& target, const const_buffer& source) { - std::size_t total_bytes_copied = 0; + using namespace std; // For memcpy. + std::size_t target_size = target.size(); + std::size_t source_size = source.size(); + std::size_t n = target_size < source_size ? target_size : source_size; + if (n > 0) + memcpy(target.data(), source.data(), n); + return n; +} - typename MutableBufferSequence::const_iterator target_iter = target.begin(); - typename MutableBufferSequence::const_iterator target_end = target.end(); +template <typename TargetIterator, typename SourceIterator> +inline std::size_t buffer_copy(one_buffer, one_buffer, + TargetIterator target_begin, TargetIterator, + SourceIterator source_begin, SourceIterator) BOOST_ASIO_NOEXCEPT +{ + return (buffer_copy_1)(*target_begin, *source_begin); +} - for (const_buffer source_buffer(source); - buffer_size(source_buffer) && target_iter != target_end; ++target_iter) +template <typename TargetIterator, typename SourceIterator> +inline std::size_t buffer_copy(one_buffer, one_buffer, + TargetIterator target_begin, TargetIterator, + SourceIterator source_begin, SourceIterator, + std::size_t max_bytes_to_copy) BOOST_ASIO_NOEXCEPT +{ + return (buffer_copy_1)(*target_begin, + boost::asio::buffer(*source_begin, max_bytes_to_copy)); +} + +template <typename TargetIterator, typename SourceIterator> +std::size_t buffer_copy(one_buffer, multiple_buffers, + TargetIterator target_begin, TargetIterator, + SourceIterator source_begin, SourceIterator source_end, + std::size_t max_bytes_to_copy + = (std::numeric_limits<std::size_t>::max)()) BOOST_ASIO_NOEXCEPT +{ + std::size_t total_bytes_copied = 0; + SourceIterator source_iter = source_begin; + + for (mutable_buffer target_buffer( + boost::asio::buffer(*target_begin, max_bytes_to_copy)); + target_buffer.size() && source_iter != source_end; ++source_iter) { - mutable_buffer target_buffer(*target_iter); - std::size_t bytes_copied = buffer_copy(target_buffer, source_buffer); + const_buffer source_buffer(*source_iter); + std::size_t bytes_copied = (buffer_copy_1)(target_buffer, source_buffer); total_bytes_copied += bytes_copied; - source_buffer = source_buffer + bytes_copied; + target_buffer += bytes_copied; } return total_bytes_copied; } -/// Copies bytes from a source buffer to a target buffer sequence. -/** - * @param target A modifiable buffer sequence representing the memory regions to - * which the bytes will be copied. - * - * @param source A non-modifiable buffer representing the memory region from - * which the bytes will be copied. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. - */ -template <typename MutableBufferSequence> -inline std::size_t buffer_copy(const MutableBufferSequence& target, - const const_buffers_1& source) +template <typename TargetIterator, typename SourceIterator> +std::size_t buffer_copy(multiple_buffers, one_buffer, + TargetIterator target_begin, TargetIterator target_end, + SourceIterator source_begin, SourceIterator, + std::size_t max_bytes_to_copy + = (std::numeric_limits<std::size_t>::max)()) BOOST_ASIO_NOEXCEPT { - return buffer_copy(target, static_cast<const const_buffer&>(source)); -} + std::size_t total_bytes_copied = 0; + TargetIterator target_iter = target_begin; -/// Copies bytes from a source buffer to a target buffer sequence. -/** - * @param target A modifiable buffer sequence representing the memory regions to - * which the bytes will be copied. - * - * @param source A modifiable buffer representing the memory region from which - * the bytes will be copied. The contents of the source buffer will not be - * modified. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. - */ -template <typename MutableBufferSequence> -inline std::size_t buffer_copy(const MutableBufferSequence& target, - const mutable_buffer& source) -{ - return buffer_copy(target, const_buffer(source)); -} + for (const_buffer source_buffer( + boost::asio::buffer(*source_begin, max_bytes_to_copy)); + source_buffer.size() && target_iter != target_end; ++target_iter) + { + mutable_buffer target_buffer(*target_iter); + std::size_t bytes_copied = (buffer_copy_1)(target_buffer, source_buffer); + total_bytes_copied += bytes_copied; + source_buffer += bytes_copied; + } -/// Copies bytes from a source buffer to a target buffer sequence. -/** - * @param target A modifiable buffer sequence representing the memory regions to - * which the bytes will be copied. - * - * @param source A modifiable buffer representing the memory region from which - * the bytes will be copied. The contents of the source buffer will not be - * modified. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. - */ -template <typename MutableBufferSequence> -inline std::size_t buffer_copy(const MutableBufferSequence& target, - const mutable_buffers_1& source) -{ - return buffer_copy(target, const_buffer(source)); + return total_bytes_copied; } -/// Copies bytes from a source buffer sequence to a target buffer sequence. -/** - * @param target A modifiable buffer sequence representing the memory regions to - * which the bytes will be copied. - * - * @param source A non-modifiable buffer sequence representing the memory - * regions from which the bytes will be copied. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. - */ -template <typename MutableBufferSequence, typename ConstBufferSequence> -std::size_t buffer_copy(const MutableBufferSequence& target, - const ConstBufferSequence& source) +template <typename TargetIterator, typename SourceIterator> +std::size_t buffer_copy(multiple_buffers, multiple_buffers, + TargetIterator target_begin, TargetIterator target_end, + SourceIterator source_begin, SourceIterator source_end) BOOST_ASIO_NOEXCEPT { std::size_t total_bytes_copied = 0; - typename MutableBufferSequence::const_iterator target_iter = target.begin(); - typename MutableBufferSequence::const_iterator target_end = target.end(); + TargetIterator target_iter = target_begin; std::size_t target_buffer_offset = 0; - typename ConstBufferSequence::const_iterator source_iter = source.begin(); - typename ConstBufferSequence::const_iterator source_end = source.end(); + SourceIterator source_iter = source_begin; std::size_t source_buffer_offset = 0; while (target_iter != target_end && source_iter != source_end) @@ -1713,10 +2011,10 @@ std::size_t buffer_copy(const MutableBufferSequence& target, const_buffer source_buffer = const_buffer(*source_iter) + source_buffer_offset; - std::size_t bytes_copied = buffer_copy(target_buffer, source_buffer); + std::size_t bytes_copied = (buffer_copy_1)(target_buffer, source_buffer); total_bytes_copied += bytes_copied; - if (bytes_copied == buffer_size(target_buffer)) + if (bytes_copied == target_buffer.size()) { ++target_iter; target_buffer_offset = 0; @@ -1724,7 +2022,7 @@ std::size_t buffer_copy(const MutableBufferSequence& target, else target_buffer_offset += bytes_copied; - if (bytes_copied == buffer_size(source_buffer)) + if (bytes_copied == source_buffer.size()) { ++source_iter; source_buffer_offset = 0; @@ -1736,409 +2034,63 @@ std::size_t buffer_copy(const MutableBufferSequence& target, return total_bytes_copied; } -/// Copies a limited number of bytes from a source buffer to a target buffer. -/** - * @param target A modifiable buffer representing the memory region to which - * the bytes will be copied. - * - * @param source A non-modifiable buffer representing the memory region from - * which the bytes will be copied. - * - * @param max_bytes_to_copy The maximum number of bytes to be copied. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * @li @c max_bytes_to_copy - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. - */ -inline std::size_t buffer_copy(const mutable_buffer& target, - const const_buffer& source, std::size_t max_bytes_to_copy) +template <typename TargetIterator, typename SourceIterator> +std::size_t buffer_copy(multiple_buffers, multiple_buffers, + TargetIterator target_begin, TargetIterator target_end, + SourceIterator source_begin, SourceIterator source_end, + std::size_t max_bytes_to_copy) BOOST_ASIO_NOEXCEPT { - return buffer_copy(buffer(target, max_bytes_to_copy), source); -} - -/// Copies a limited number of bytes from a source buffer to a target buffer. -/** - * @param target A modifiable buffer representing the memory region to which - * the bytes will be copied. - * - * @param source A non-modifiable buffer representing the memory region from - * which the bytes will be copied. - * - * @param max_bytes_to_copy The maximum number of bytes to be copied. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * @li @c max_bytes_to_copy - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. - */ -inline std::size_t buffer_copy(const mutable_buffer& target, - const const_buffers_1& source, std::size_t max_bytes_to_copy) -{ - return buffer_copy(buffer(target, max_bytes_to_copy), source); -} - -/// Copies a limited number of bytes from a source buffer to a target buffer. -/** - * @param target A modifiable buffer representing the memory region to which - * the bytes will be copied. - * - * @param source A modifiable buffer representing the memory region from which - * the bytes will be copied. The contents of the source buffer will not be - * modified. - * - * @param max_bytes_to_copy The maximum number of bytes to be copied. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * @li @c max_bytes_to_copy - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. - */ -inline std::size_t buffer_copy(const mutable_buffer& target, - const mutable_buffer& source, std::size_t max_bytes_to_copy) -{ - return buffer_copy(buffer(target, max_bytes_to_copy), source); -} - -/// Copies a limited number of bytes from a source buffer to a target buffer. -/** - * @param target A modifiable buffer representing the memory region to which - * the bytes will be copied. - * - * @param source A modifiable buffer representing the memory region from which - * the bytes will be copied. The contents of the source buffer will not be - * modified. - * - * @param max_bytes_to_copy The maximum number of bytes to be copied. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * @li @c max_bytes_to_copy - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. - */ -inline std::size_t buffer_copy(const mutable_buffer& target, - const mutable_buffers_1& source, std::size_t max_bytes_to_copy) -{ - return buffer_copy(buffer(target, max_bytes_to_copy), source); -} + std::size_t total_bytes_copied = 0; -/// Copies a limited number of bytes from a source buffer sequence to a target -/// buffer. -/** - * @param target A modifiable buffer representing the memory region to which - * the bytes will be copied. - * - * @param source A non-modifiable buffer sequence representing the memory - * regions from which the bytes will be copied. - * - * @param max_bytes_to_copy The maximum number of bytes to be copied. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * @li @c max_bytes_to_copy - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. - */ -template <typename ConstBufferSequence> -inline std::size_t buffer_copy(const mutable_buffer& target, - const ConstBufferSequence& source, std::size_t max_bytes_to_copy) -{ - return buffer_copy(buffer(target, max_bytes_to_copy), source); -} + TargetIterator target_iter = target_begin; + std::size_t target_buffer_offset = 0; -/// Copies a limited number of bytes from a source buffer to a target buffer. -/** - * @param target A modifiable buffer representing the memory region to which - * the bytes will be copied. - * - * @param source A non-modifiable buffer representing the memory region from - * which the bytes will be copied. - * - * @param max_bytes_to_copy The maximum number of bytes to be copied. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * @li @c max_bytes_to_copy - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. - */ -inline std::size_t buffer_copy(const mutable_buffers_1& target, - const const_buffer& source, std::size_t max_bytes_to_copy) -{ - return buffer_copy(buffer(target, max_bytes_to_copy), source); -} + SourceIterator source_iter = source_begin; + std::size_t source_buffer_offset = 0; -/// Copies a limited number of bytes from a source buffer to a target buffer. -/** - * @param target A modifiable buffer representing the memory region to which - * the bytes will be copied. - * - * @param source A non-modifiable buffer representing the memory region from - * which the bytes will be copied. - * - * @param max_bytes_to_copy The maximum number of bytes to be copied. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * @li @c max_bytes_to_copy - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. - */ -inline std::size_t buffer_copy(const mutable_buffers_1& target, - const const_buffers_1& source, std::size_t max_bytes_to_copy) -{ - return buffer_copy(buffer(target, max_bytes_to_copy), source); -} + while (total_bytes_copied != max_bytes_to_copy + && target_iter != target_end && source_iter != source_end) + { + mutable_buffer target_buffer = + mutable_buffer(*target_iter) + target_buffer_offset; -/// Copies a limited number of bytes from a source buffer to a target buffer. -/** - * @param target A modifiable buffer representing the memory region to which - * the bytes will be copied. - * - * @param source A modifiable buffer representing the memory region from which - * the bytes will be copied. The contents of the source buffer will not be - * modified. - * - * @param max_bytes_to_copy The maximum number of bytes to be copied. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * @li @c max_bytes_to_copy - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. - */ -inline std::size_t buffer_copy(const mutable_buffers_1& target, - const mutable_buffer& source, std::size_t max_bytes_to_copy) -{ - return buffer_copy(buffer(target, max_bytes_to_copy), source); -} + const_buffer source_buffer = + const_buffer(*source_iter) + source_buffer_offset; -/// Copies a limited number of bytes from a source buffer to a target buffer. -/** - * @param target A modifiable buffer representing the memory region to which - * the bytes will be copied. - * - * @param source A modifiable buffer representing the memory region from which - * the bytes will be copied. The contents of the source buffer will not be - * modified. - * - * @param max_bytes_to_copy The maximum number of bytes to be copied. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * @li @c max_bytes_to_copy - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. - */ -inline std::size_t buffer_copy(const mutable_buffers_1& target, - const mutable_buffers_1& source, std::size_t max_bytes_to_copy) -{ - return buffer_copy(buffer(target, max_bytes_to_copy), source); -} + std::size_t bytes_copied = (buffer_copy_1)( + target_buffer, boost::asio::buffer(source_buffer, + max_bytes_to_copy - total_bytes_copied)); + total_bytes_copied += bytes_copied; -/// Copies a limited number of bytes from a source buffer sequence to a target -/// buffer. -/** - * @param target A modifiable buffer representing the memory region to which - * the bytes will be copied. - * - * @param source A non-modifiable buffer sequence representing the memory - * regions from which the bytes will be copied. - * - * @param max_bytes_to_copy The maximum number of bytes to be copied. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * @li @c max_bytes_to_copy - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. - */ -template <typename ConstBufferSequence> -inline std::size_t buffer_copy(const mutable_buffers_1& target, - const ConstBufferSequence& source, std::size_t max_bytes_to_copy) -{ - return buffer_copy(buffer(target, max_bytes_to_copy), source); -} + if (bytes_copied == target_buffer.size()) + { + ++target_iter; + target_buffer_offset = 0; + } + else + target_buffer_offset += bytes_copied; -/// Copies a limited number of bytes from a source buffer to a target buffer -/// sequence. -/** - * @param target A modifiable buffer sequence representing the memory regions to - * which the bytes will be copied. - * - * @param source A non-modifiable buffer representing the memory region from - * which the bytes will be copied. - * - * @param max_bytes_to_copy The maximum number of bytes to be copied. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * @li @c max_bytes_to_copy - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. - */ -template <typename MutableBufferSequence> -inline std::size_t buffer_copy(const MutableBufferSequence& target, - const const_buffer& source, std::size_t max_bytes_to_copy) -{ - return buffer_copy(target, buffer(source, max_bytes_to_copy)); -} + if (bytes_copied == source_buffer.size()) + { + ++source_iter; + source_buffer_offset = 0; + } + else + source_buffer_offset += bytes_copied; + } -/// Copies a limited number of bytes from a source buffer to a target buffer -/// sequence. -/** - * @param target A modifiable buffer sequence representing the memory regions to - * which the bytes will be copied. - * - * @param source A non-modifiable buffer representing the memory region from - * which the bytes will be copied. - * - * @param max_bytes_to_copy The maximum number of bytes to be copied. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * @li @c max_bytes_to_copy - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. - */ -template <typename MutableBufferSequence> -inline std::size_t buffer_copy(const MutableBufferSequence& target, - const const_buffers_1& source, std::size_t max_bytes_to_copy) -{ - return buffer_copy(target, buffer(source, max_bytes_to_copy)); + return total_bytes_copied; } -/// Copies a limited number of bytes from a source buffer to a target buffer -/// sequence. -/** - * @param target A modifiable buffer sequence representing the memory regions to - * which the bytes will be copied. - * - * @param source A modifiable buffer representing the memory region from which - * the bytes will be copied. The contents of the source buffer will not be - * modified. - * - * @param max_bytes_to_copy The maximum number of bytes to be copied. - * - * @returns The number of bytes copied. - * - * @note The number of bytes copied is the lesser of: - * - * @li @c buffer_size(target) - * - * @li @c buffer_size(source) - * - * @li @c max_bytes_to_copy - * - * This function is implemented in terms of @c memcpy, and consequently it - * cannot be used to copy between overlapping memory regions. - */ -template <typename MutableBufferSequence> -inline std::size_t buffer_copy(const MutableBufferSequence& target, - const mutable_buffer& source, std::size_t max_bytes_to_copy) -{ - return buffer_copy(target, buffer(source, max_bytes_to_copy)); -} +} // namespace detail -/// Copies a limited number of bytes from a source buffer to a target buffer -/// sequence. +/// Copies bytes from a source buffer sequence to a target buffer sequence. /** * @param target A modifiable buffer sequence representing the memory regions to * which the bytes will be copied. * - * @param source A modifiable buffer representing the memory region from which - * the bytes will be copied. The contents of the source buffer will not be - * modified. - * - * @param max_bytes_to_copy The maximum number of bytes to be copied. + * @param source A non-modifiable buffer sequence representing the memory + * regions from which the bytes will be copied. * * @returns The number of bytes copied. * @@ -2148,16 +2100,20 @@ inline std::size_t buffer_copy(const MutableBufferSequence& target, * * @li @c buffer_size(source) * - * @li @c max_bytes_to_copy - * * This function is implemented in terms of @c memcpy, and consequently it * cannot be used to copy between overlapping memory regions. */ -template <typename MutableBufferSequence> +template <typename MutableBufferSequence, typename ConstBufferSequence> inline std::size_t buffer_copy(const MutableBufferSequence& target, - const mutable_buffers_1& source, std::size_t max_bytes_to_copy) + const ConstBufferSequence& source) BOOST_ASIO_NOEXCEPT { - return buffer_copy(target, buffer(source, max_bytes_to_copy)); + return detail::buffer_copy( + detail::buffer_sequence_cardinality<MutableBufferSequence>(), + detail::buffer_sequence_cardinality<ConstBufferSequence>(), + boost::asio::buffer_sequence_begin(target), + boost::asio::buffer_sequence_end(target), + boost::asio::buffer_sequence_begin(source), + boost::asio::buffer_sequence_end(source)); } /// Copies a limited number of bytes from a source buffer sequence to a target @@ -2185,50 +2141,17 @@ inline std::size_t buffer_copy(const MutableBufferSequence& target, * cannot be used to copy between overlapping memory regions. */ template <typename MutableBufferSequence, typename ConstBufferSequence> -std::size_t buffer_copy(const MutableBufferSequence& target, - const ConstBufferSequence& source, std::size_t max_bytes_to_copy) -{ - std::size_t total_bytes_copied = 0; - - typename MutableBufferSequence::const_iterator target_iter = target.begin(); - typename MutableBufferSequence::const_iterator target_end = target.end(); - std::size_t target_buffer_offset = 0; - - typename ConstBufferSequence::const_iterator source_iter = source.begin(); - typename ConstBufferSequence::const_iterator source_end = source.end(); - std::size_t source_buffer_offset = 0; - - while (total_bytes_copied != max_bytes_to_copy - && target_iter != target_end && source_iter != source_end) - { - mutable_buffer target_buffer = - mutable_buffer(*target_iter) + target_buffer_offset; - - const_buffer source_buffer = - const_buffer(*source_iter) + source_buffer_offset; - - std::size_t bytes_copied = buffer_copy(target_buffer, - source_buffer, max_bytes_to_copy - total_bytes_copied); - total_bytes_copied += bytes_copied; - - if (bytes_copied == buffer_size(target_buffer)) - { - ++target_iter; - target_buffer_offset = 0; - } - else - target_buffer_offset += bytes_copied; - - if (bytes_copied == buffer_size(source_buffer)) - { - ++source_iter; - source_buffer_offset = 0; - } - else - source_buffer_offset += bytes_copied; - } - - return total_bytes_copied; +inline std::size_t buffer_copy(const MutableBufferSequence& target, + const ConstBufferSequence& source, + std::size_t max_bytes_to_copy) BOOST_ASIO_NOEXCEPT +{ + return detail::buffer_copy( + detail::buffer_sequence_cardinality<MutableBufferSequence>(), + detail::buffer_sequence_cardinality<ConstBufferSequence>(), + boost::asio::buffer_sequence_begin(target), + boost::asio::buffer_sequence_end(target), + boost::asio::buffer_sequence_begin(source), + boost::asio::buffer_sequence_end(source), max_bytes_to_copy); } /*@}*/ |