mirror of
https://github.com/deneraraujo/OpenVPNAdapter.git
synced 2026-02-11 00:00:08 +08:00
b3d2ab725 asio version 1.12.0 released
d9161a36e Update release script to match new boost doc build.
54c7b85de Update revision history.
9eaa2a2e5 Update tutorial text to use 'io_context'.
41eb9dc20 Ignore tsified directory.
9229964dc Don't use inline namespace 'v1' in example code snippets.
10098abd6 Include inline namespace 'v1' in tsified code.
9bdbef19f Regenerate documentation.
8fa11a15d Exclude use_future_t implementation detail from documentation.
577b69806 Workaround broken doxygen typedef linking when primary template is undefined.
ea1b39f04 Fix tsify.pl to work with latest code.
694ed5284 Document the new concurrency hints.
3834d7363 Some updates to 'Using' notes.
00873ce91 Document Networking TS changes.
8f25ea4b5 Remove spurious value_type from buffer sequence requirements.
b33eb0219 gcc 4.7 is the minimum version required for std::allocator_traits.
036faf66a Use new move-enabled form of async_accept.
f72304319 Ensure that use_future<std::allocator<void>> is always constexpr default-constructible.
4ad7a397c Add missing variadic template emulation in use_future.
5c591a466 Disable buffer debugging for older MSVC, as it triggers compiler misbehaviour.
f8bd903af Add assign() and clear() functions to error_code.
db4c0e83f Disable boost.chrono error handling.
cca13eefa Document the new handler tracking features.
ff9d69e2f Add check for _DEFAULT_SOURCE in addition to _BSD_SOURCE.
52498bbc6 Suppress recv truncation errors on Windows, to match POSIX behaviour.
e87c37ec9 Add documentation examples of using asio::post to submit work.
ad52c82d2 Create C++11 versions of the fork, local, multicast and nonblocking examples.
f16e39e78 Don't directly include <chrono>, to keep header C++03-compatible.
c016e1aec Boostify the TS headers.
559013298 Suppress MSVC dynamic initialisation warning.
efa18153d Add tests to ensure the ts/* headers compile and are self-contained.
41fccd565 asio/use_future.hpp is already in the convenience header.
2e743f737 Add waitable timer headers to convenience header.
fe5470f4f Use new post() in serialization example.
45dcb33c2 Use asio::coroutine in latency tests.
e556aed8d Update invocation examples to use executors.
5a9d0721d Fix up reference to post().
24050d5ea Show how to associate an executor using nested type and member function.
b02c6c758 Update allocation overview and examples to use new form.
3218be74e Fix typo in strands overview.
3152e77f8 Increase number of buffers per operation for consuming_buffers.
5acae1971 Increase threshold for small memory block recycling to 1KB.
986ef7361 Make sure asio/system_context.hpp is self-contained.
c80c1cbd5 Don't call memcpy with length 0, to avoid passing null pointers.
ede4e7597 Fix description of std::getline's behaviour.
60170d625 Fix copy/paste error in comment.
cff2b4998 Fix clang narrowing warning.
a40570919 Fix incorrect hyperlink target.
fcaf75700 Remove last remaining instance of auto_ptr.
fddf89126 Restore binder support for 3, 4 and 5 arguments.
096660c47 Fix double delete issue introduced by 47b9319acbc45d3c1bcb805a4a03cd47df177c11.
b44805ff0 Add backward compatibility for the old ConnectCondition form.
09c69982e Ensure make_network_vX error_code overload doesn't throw on invalid prefix length.
f4fecdfe4 Fix the rights for event objects on UWP.
2943ee65f Suppress implicit fallthrough warning on newer gcc.
b441bf70b Fix clang version detection for suppression of unused typedef warning.
565c6e8fa Fix compile errors in some asio::connect overloads.
d52b81646 Bump minimum MSVC version required for C++11 allocators.
5618fadb1 Fix compile warning under Emscripten
b2367dab2 Use proper SSL_version() function so that asio can build with BoringSSL.
cfe47e71d Regenerate documentation.
6377b0466 Patch up some template links.
2bda4b85c Add new macros to doxygen configuration.
4a4d28b0d Qualify use of error_code.
e39a95a73 Fix boostify.pl to work with latest code.
2ccb648f4 Only obtain associated allocator when handler is known to be valid.
230c0d2ae Asynchronous accept should not check user-set non-blocking flag.
862aed305 Require gcc >= 4.7 to use standard atomics.
a0d28e5a7 Don't use auto_ptr.
15e136fa8 Use deregister_internal_descriptor in signal_set_service.
59330e825 Put detail/config.hpp include first in detail/string_view.hpp.
d6144828b Only enable string_view with /std:c++17 on MSVC.
c2cb5395e Use hook allocation strategy whenever associated allocator is std::allocator.
5b4aa5ef9 Make epoll_reactor resistant to events with duplicate user data.
47b9319ac Don't free the reactor's per-descriptor state until after close.
cbf687653 Fix compile errors in dev_poll_reactor.
870124ab5 Add missing 'else' in epoll_reactor's handler tracking support.
b37b9449e Clean up socket release() implementation for reactor-based platforms.
f5c570826 Add out_of_band_inline socket option.
7f849376c Expose the system_executor's execution context as system_context.
9f62b6791 Update io_context run* documentation.
ac89cf0ba Enable newer language features for recent MSVC versions.
64ae9bcae Add alias templates for associators.
e502a6b36 Use shorter enum name resolver_errc::try_again.
b3ebdd8f6 Use ADL for calls to buffer_size.
c516cd591 Fix non-dereferencing pointer overflow in basic_streambuf::commit.
b8a34a1dc Fix work counting issue in asynchronous resolver implementation.
48e7ef864 is_continuation misplaced in reactive socket service
5adce6e26 Use poll.h rather than sys/poll.h if possible.
ddef4994f Avoid exception throwing from `make_network_v{4,6}(str, ec)`
0442bc922 Disable Boost.Chrono's dependency on Boost.System.
6c5b04eff Conditionally enable iostream move constructor and assignment.
a3bba3394 Fix version check for string_view.
246f387e7 Fix compile error on gcc 4.8.
fd024792c Add -lrt when linking on linux.
0921ab3db Simplify automatic detection of boost source distributions.
6b34f88a5 Make SSL/TLS version handling more consistent across OpenSSL versions.
1517bd1a1 Add travis and appveyor configuration.
70249b796 Use GetModuleHandleA rather than GetModuleHandle.
582ed12f7 Update copyright notices.
b6ac42dde Remove unused error code variable.
d52f28a09 Add missing rvalue cast in use_future implementation.
b33b3ae01 Unlocked reactor I/O implies a concurrency hint of 1.
cf351c44a Don't use non-portable sockaddr_storage member ss_len.
bbe092b3d Simplify and improve performance of executor operations.
e5acea17d Add shallow-constness to strands.
00a85845e Eliminate redundant copy as executors are now shallow-const.
git-subtree-dir: OpenVPN Adapter/Vendors/asio
git-subtree-split: 82be891ba69c65be4c684d709d78a225da69c3c5
522 lines
14 KiB
C++
522 lines
14 KiB
C++
//
|
|
// buffers_iterator.hpp
|
|
// ~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
|
//
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
//
|
|
|
|
#ifndef ASIO_BUFFERS_ITERATOR_HPP
|
|
#define ASIO_BUFFERS_ITERATOR_HPP
|
|
|
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
|
# pragma once
|
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
|
|
|
#include "asio/detail/config.hpp"
|
|
#include <cstddef>
|
|
#include <iterator>
|
|
#include "asio/buffer.hpp"
|
|
#include "asio/detail/assert.hpp"
|
|
#include "asio/detail/type_traits.hpp"
|
|
|
|
#include "asio/detail/push_options.hpp"
|
|
|
|
namespace asio {
|
|
|
|
namespace detail
|
|
{
|
|
template <bool IsMutable>
|
|
struct buffers_iterator_types_helper;
|
|
|
|
template <>
|
|
struct buffers_iterator_types_helper<false>
|
|
{
|
|
typedef const_buffer buffer_type;
|
|
template <typename ByteType>
|
|
struct byte_type
|
|
{
|
|
typedef typename add_const<ByteType>::type type;
|
|
};
|
|
};
|
|
|
|
template <>
|
|
struct buffers_iterator_types_helper<true>
|
|
{
|
|
typedef mutable_buffer buffer_type;
|
|
template <typename ByteType>
|
|
struct byte_type
|
|
{
|
|
typedef ByteType type;
|
|
};
|
|
};
|
|
|
|
template <typename BufferSequence, typename ByteType>
|
|
struct buffers_iterator_types
|
|
{
|
|
enum
|
|
{
|
|
is_mutable = is_convertible<
|
|
typename BufferSequence::value_type,
|
|
mutable_buffer>::value
|
|
};
|
|
typedef buffers_iterator_types_helper<is_mutable> helper;
|
|
typedef typename helper::buffer_type buffer_type;
|
|
typedef typename helper::template byte_type<ByteType>::type byte_type;
|
|
typedef typename BufferSequence::const_iterator const_iterator;
|
|
};
|
|
|
|
template <typename ByteType>
|
|
struct buffers_iterator_types<mutable_buffer, ByteType>
|
|
{
|
|
typedef mutable_buffer buffer_type;
|
|
typedef ByteType byte_type;
|
|
typedef const mutable_buffer* const_iterator;
|
|
};
|
|
|
|
template <typename ByteType>
|
|
struct buffers_iterator_types<const_buffer, ByteType>
|
|
{
|
|
typedef const_buffer buffer_type;
|
|
typedef typename add_const<ByteType>::type byte_type;
|
|
typedef const const_buffer* const_iterator;
|
|
};
|
|
|
|
#if !defined(ASIO_NO_DEPRECATED)
|
|
|
|
template <typename ByteType>
|
|
struct buffers_iterator_types<mutable_buffers_1, ByteType>
|
|
{
|
|
typedef mutable_buffer buffer_type;
|
|
typedef ByteType byte_type;
|
|
typedef const mutable_buffer* const_iterator;
|
|
};
|
|
|
|
template <typename ByteType>
|
|
struct buffers_iterator_types<const_buffers_1, ByteType>
|
|
{
|
|
typedef const_buffer buffer_type;
|
|
typedef typename add_const<ByteType>::type byte_type;
|
|
typedef const const_buffer* const_iterator;
|
|
};
|
|
|
|
#endif // !defined(ASIO_NO_DEPRECATED)
|
|
}
|
|
|
|
/// A random access iterator over the bytes in a buffer sequence.
|
|
template <typename BufferSequence, typename ByteType = char>
|
|
class buffers_iterator
|
|
{
|
|
private:
|
|
typedef typename detail::buffers_iterator_types<
|
|
BufferSequence, ByteType>::buffer_type buffer_type;
|
|
|
|
typedef typename detail::buffers_iterator_types<BufferSequence,
|
|
ByteType>::const_iterator buffer_sequence_iterator_type;
|
|
|
|
public:
|
|
/// The type used for the distance between two iterators.
|
|
typedef std::ptrdiff_t difference_type;
|
|
|
|
/// The type of the value pointed to by the iterator.
|
|
typedef ByteType value_type;
|
|
|
|
#if defined(GENERATING_DOCUMENTATION)
|
|
/// The type of the result of applying operator->() to the iterator.
|
|
/**
|
|
* If the buffer sequence stores buffer objects that are convertible to
|
|
* mutable_buffer, this is a pointer to a non-const ByteType. Otherwise, a
|
|
* pointer to a const ByteType.
|
|
*/
|
|
typedef const_or_non_const_ByteType* pointer;
|
|
#else // defined(GENERATING_DOCUMENTATION)
|
|
typedef typename detail::buffers_iterator_types<
|
|
BufferSequence, ByteType>::byte_type* pointer;
|
|
#endif // defined(GENERATING_DOCUMENTATION)
|
|
|
|
#if defined(GENERATING_DOCUMENTATION)
|
|
/// The type of the result of applying operator*() to the iterator.
|
|
/**
|
|
* If the buffer sequence stores buffer objects that are convertible to
|
|
* mutable_buffer, this is a reference to a non-const ByteType. Otherwise, a
|
|
* reference to a const ByteType.
|
|
*/
|
|
typedef const_or_non_const_ByteType& reference;
|
|
#else // defined(GENERATING_DOCUMENTATION)
|
|
typedef typename detail::buffers_iterator_types<
|
|
BufferSequence, ByteType>::byte_type& reference;
|
|
#endif // defined(GENERATING_DOCUMENTATION)
|
|
|
|
/// The iterator category.
|
|
typedef std::random_access_iterator_tag iterator_category;
|
|
|
|
/// Default constructor. Creates an iterator in an undefined state.
|
|
buffers_iterator()
|
|
: current_buffer_(),
|
|
current_buffer_position_(0),
|
|
begin_(),
|
|
current_(),
|
|
end_(),
|
|
position_(0)
|
|
{
|
|
}
|
|
|
|
/// Construct an iterator representing the beginning of the buffers' data.
|
|
static buffers_iterator begin(const BufferSequence& buffers)
|
|
#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
|
|
__attribute__ ((__noinline__))
|
|
#endif // defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
|
|
{
|
|
buffers_iterator new_iter;
|
|
new_iter.begin_ = asio::buffer_sequence_begin(buffers);
|
|
new_iter.current_ = asio::buffer_sequence_begin(buffers);
|
|
new_iter.end_ = asio::buffer_sequence_end(buffers);
|
|
while (new_iter.current_ != new_iter.end_)
|
|
{
|
|
new_iter.current_buffer_ = *new_iter.current_;
|
|
if (new_iter.current_buffer_.size() > 0)
|
|
break;
|
|
++new_iter.current_;
|
|
}
|
|
return new_iter;
|
|
}
|
|
|
|
/// Construct an iterator representing the end of the buffers' data.
|
|
static buffers_iterator end(const BufferSequence& buffers)
|
|
#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
|
|
__attribute__ ((__noinline__))
|
|
#endif // defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
|
|
{
|
|
buffers_iterator new_iter;
|
|
new_iter.begin_ = asio::buffer_sequence_begin(buffers);
|
|
new_iter.current_ = asio::buffer_sequence_begin(buffers);
|
|
new_iter.end_ = asio::buffer_sequence_end(buffers);
|
|
while (new_iter.current_ != new_iter.end_)
|
|
{
|
|
buffer_type buffer = *new_iter.current_;
|
|
new_iter.position_ += buffer.size();
|
|
++new_iter.current_;
|
|
}
|
|
return new_iter;
|
|
}
|
|
|
|
/// Dereference an iterator.
|
|
reference operator*() const
|
|
{
|
|
return dereference();
|
|
}
|
|
|
|
/// Dereference an iterator.
|
|
pointer operator->() const
|
|
{
|
|
return &dereference();
|
|
}
|
|
|
|
/// Access an individual element.
|
|
reference operator[](std::ptrdiff_t difference) const
|
|
{
|
|
buffers_iterator tmp(*this);
|
|
tmp.advance(difference);
|
|
return *tmp;
|
|
}
|
|
|
|
/// Increment operator (prefix).
|
|
buffers_iterator& operator++()
|
|
{
|
|
increment();
|
|
return *this;
|
|
}
|
|
|
|
/// Increment operator (postfix).
|
|
buffers_iterator operator++(int)
|
|
{
|
|
buffers_iterator tmp(*this);
|
|
++*this;
|
|
return tmp;
|
|
}
|
|
|
|
/// Decrement operator (prefix).
|
|
buffers_iterator& operator--()
|
|
{
|
|
decrement();
|
|
return *this;
|
|
}
|
|
|
|
/// Decrement operator (postfix).
|
|
buffers_iterator operator--(int)
|
|
{
|
|
buffers_iterator tmp(*this);
|
|
--*this;
|
|
return tmp;
|
|
}
|
|
|
|
/// Addition operator.
|
|
buffers_iterator& operator+=(std::ptrdiff_t difference)
|
|
{
|
|
advance(difference);
|
|
return *this;
|
|
}
|
|
|
|
/// Subtraction operator.
|
|
buffers_iterator& operator-=(std::ptrdiff_t difference)
|
|
{
|
|
advance(-difference);
|
|
return *this;
|
|
}
|
|
|
|
/// Addition operator.
|
|
friend buffers_iterator operator+(const buffers_iterator& iter,
|
|
std::ptrdiff_t difference)
|
|
{
|
|
buffers_iterator tmp(iter);
|
|
tmp.advance(difference);
|
|
return tmp;
|
|
}
|
|
|
|
/// Addition operator.
|
|
friend buffers_iterator operator+(std::ptrdiff_t difference,
|
|
const buffers_iterator& iter)
|
|
{
|
|
buffers_iterator tmp(iter);
|
|
tmp.advance(difference);
|
|
return tmp;
|
|
}
|
|
|
|
/// Subtraction operator.
|
|
friend buffers_iterator operator-(const buffers_iterator& iter,
|
|
std::ptrdiff_t difference)
|
|
{
|
|
buffers_iterator tmp(iter);
|
|
tmp.advance(-difference);
|
|
return tmp;
|
|
}
|
|
|
|
/// Subtraction operator.
|
|
friend std::ptrdiff_t operator-(const buffers_iterator& a,
|
|
const buffers_iterator& b)
|
|
{
|
|
return b.distance_to(a);
|
|
}
|
|
|
|
/// Test two iterators for equality.
|
|
friend bool operator==(const buffers_iterator& a, const buffers_iterator& b)
|
|
{
|
|
return a.equal(b);
|
|
}
|
|
|
|
/// Test two iterators for inequality.
|
|
friend bool operator!=(const buffers_iterator& a, const buffers_iterator& b)
|
|
{
|
|
return !a.equal(b);
|
|
}
|
|
|
|
/// Compare two iterators.
|
|
friend bool operator<(const buffers_iterator& a, const buffers_iterator& b)
|
|
{
|
|
return a.distance_to(b) > 0;
|
|
}
|
|
|
|
/// Compare two iterators.
|
|
friend bool operator<=(const buffers_iterator& a, const buffers_iterator& b)
|
|
{
|
|
return !(b < a);
|
|
}
|
|
|
|
/// Compare two iterators.
|
|
friend bool operator>(const buffers_iterator& a, const buffers_iterator& b)
|
|
{
|
|
return b < a;
|
|
}
|
|
|
|
/// Compare two iterators.
|
|
friend bool operator>=(const buffers_iterator& a, const buffers_iterator& b)
|
|
{
|
|
return !(a < b);
|
|
}
|
|
|
|
private:
|
|
// Dereference the iterator.
|
|
reference dereference() const
|
|
{
|
|
return static_cast<pointer>(
|
|
current_buffer_.data())[current_buffer_position_];
|
|
}
|
|
|
|
// Compare two iterators for equality.
|
|
bool equal(const buffers_iterator& other) const
|
|
{
|
|
return position_ == other.position_;
|
|
}
|
|
|
|
// Increment the iterator.
|
|
void increment()
|
|
{
|
|
ASIO_ASSERT(current_ != end_ && "iterator out of bounds");
|
|
++position_;
|
|
|
|
// Check if the increment can be satisfied by the current buffer.
|
|
++current_buffer_position_;
|
|
if (current_buffer_position_ != current_buffer_.size())
|
|
return;
|
|
|
|
// Find the next non-empty buffer.
|
|
++current_;
|
|
current_buffer_position_ = 0;
|
|
while (current_ != end_)
|
|
{
|
|
current_buffer_ = *current_;
|
|
if (current_buffer_.size() > 0)
|
|
return;
|
|
++current_;
|
|
}
|
|
}
|
|
|
|
// Decrement the iterator.
|
|
void decrement()
|
|
{
|
|
ASIO_ASSERT(position_ > 0 && "iterator out of bounds");
|
|
--position_;
|
|
|
|
// Check if the decrement can be satisfied by the current buffer.
|
|
if (current_buffer_position_ != 0)
|
|
{
|
|
--current_buffer_position_;
|
|
return;
|
|
}
|
|
|
|
// Find the previous non-empty buffer.
|
|
buffer_sequence_iterator_type iter = current_;
|
|
while (iter != begin_)
|
|
{
|
|
--iter;
|
|
buffer_type buffer = *iter;
|
|
std::size_t buffer_size = buffer.size();
|
|
if (buffer_size > 0)
|
|
{
|
|
current_ = iter;
|
|
current_buffer_ = buffer;
|
|
current_buffer_position_ = buffer_size - 1;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Advance the iterator by the specified distance.
|
|
void advance(std::ptrdiff_t n)
|
|
{
|
|
if (n > 0)
|
|
{
|
|
ASIO_ASSERT(current_ != end_ && "iterator out of bounds");
|
|
for (;;)
|
|
{
|
|
std::ptrdiff_t current_buffer_balance
|
|
= current_buffer_.size() - current_buffer_position_;
|
|
|
|
// Check if the advance can be satisfied by the current buffer.
|
|
if (current_buffer_balance > n)
|
|
{
|
|
position_ += n;
|
|
current_buffer_position_ += n;
|
|
return;
|
|
}
|
|
|
|
// Update position.
|
|
n -= current_buffer_balance;
|
|
position_ += current_buffer_balance;
|
|
|
|
// Move to next buffer. If it is empty then it will be skipped on the
|
|
// next iteration of this loop.
|
|
if (++current_ == end_)
|
|
{
|
|
ASIO_ASSERT(n == 0 && "iterator out of bounds");
|
|
current_buffer_ = buffer_type();
|
|
current_buffer_position_ = 0;
|
|
return;
|
|
}
|
|
current_buffer_ = *current_;
|
|
current_buffer_position_ = 0;
|
|
}
|
|
}
|
|
else if (n < 0)
|
|
{
|
|
std::size_t abs_n = -n;
|
|
ASIO_ASSERT(position_ >= abs_n && "iterator out of bounds");
|
|
for (;;)
|
|
{
|
|
// Check if the advance can be satisfied by the current buffer.
|
|
if (current_buffer_position_ >= abs_n)
|
|
{
|
|
position_ -= abs_n;
|
|
current_buffer_position_ -= abs_n;
|
|
return;
|
|
}
|
|
|
|
// Update position.
|
|
abs_n -= current_buffer_position_;
|
|
position_ -= current_buffer_position_;
|
|
|
|
// Check if we've reached the beginning of the buffers.
|
|
if (current_ == begin_)
|
|
{
|
|
ASIO_ASSERT(abs_n == 0 && "iterator out of bounds");
|
|
current_buffer_position_ = 0;
|
|
return;
|
|
}
|
|
|
|
// Find the previous non-empty buffer.
|
|
buffer_sequence_iterator_type iter = current_;
|
|
while (iter != begin_)
|
|
{
|
|
--iter;
|
|
buffer_type buffer = *iter;
|
|
std::size_t buffer_size = buffer.size();
|
|
if (buffer_size > 0)
|
|
{
|
|
current_ = iter;
|
|
current_buffer_ = buffer;
|
|
current_buffer_position_ = buffer_size;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Determine the distance between two iterators.
|
|
std::ptrdiff_t distance_to(const buffers_iterator& other) const
|
|
{
|
|
return other.position_ - position_;
|
|
}
|
|
|
|
buffer_type current_buffer_;
|
|
std::size_t current_buffer_position_;
|
|
buffer_sequence_iterator_type begin_;
|
|
buffer_sequence_iterator_type current_;
|
|
buffer_sequence_iterator_type end_;
|
|
std::size_t position_;
|
|
};
|
|
|
|
/// Construct an iterator representing the beginning of the buffers' data.
|
|
template <typename BufferSequence>
|
|
inline buffers_iterator<BufferSequence> buffers_begin(
|
|
const BufferSequence& buffers)
|
|
{
|
|
return buffers_iterator<BufferSequence>::begin(buffers);
|
|
}
|
|
|
|
/// Construct an iterator representing the end of the buffers' data.
|
|
template <typename BufferSequence>
|
|
inline buffers_iterator<BufferSequence> buffers_end(
|
|
const BufferSequence& buffers)
|
|
{
|
|
return buffers_iterator<BufferSequence>::end(buffers);
|
|
}
|
|
|
|
} // namespace asio
|
|
|
|
#include "asio/detail/pop_options.hpp"
|
|
|
|
#endif // ASIO_BUFFERS_ITERATOR_HPP
|