...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
The buffer
function is used to create a buffer object to represent raw memory, an array
of POD elements, a vector of POD elements, or a std::string.
Create a new modifiable buffer from an existing buffer.
mutable_buffer buffer( const mutable_buffer & b); » more... mutable_buffer buffer( const mutable_buffer & b, std::size_t max_size_in_bytes); » more...
Create a new non-modifiable buffer from an existing buffer.
const_buffer buffer( const const_buffer & b); » more... const_buffer buffer( const const_buffer & b, std::size_t max_size_in_bytes); » more...
Create a new modifiable buffer that represents the given memory range.
mutable_buffer buffer( void * data, std::size_t size_in_bytes); » more...
Create a new non-modifiable buffer that represents the given memory range.
const_buffer buffer( const void * data, std::size_t size_in_bytes); » more...
Create a new modifiable buffer that represents the given POD array.
template< typename PodType, std::size_t N> mutable_buffer buffer( PodType((&data)[N]); » more... template< typename PodType, std::size_t N> mutable_buffer buffer( PodType((&data)[N], std::size_t max_size_in_bytes); » more...
Create a new non-modifiable buffer that represents the given POD array.
template< typename PodType, std::size_t N> const_buffer buffer( const PodType((&data)[N]); » more... template< typename PodType, std::size_t N> const_buffer buffer( const PodType((&data)[N], std::size_t max_size_in_bytes); » more...
Create a new modifiable buffer that represents the given POD array.
template< typename PodType, std::size_t N> mutable_buffer buffer( boost::array< PodType, N > & data); » more... template< typename PodType, std::size_t N> mutable_buffer buffer( boost::array< PodType, N > & data, std::size_t max_size_in_bytes); » more...
Create a new non-modifiable buffer that represents the given POD array.
template< typename PodType, std::size_t N> const_buffer buffer( boost::array< const PodType, N > & data); » more... template< typename PodType, std::size_t N> const_buffer buffer( boost::array< const PodType, N > & data, std::size_t max_size_in_bytes); » more...
Create a new modifiable buffer that represents the given POD array.
template< typename PodType, std::size_t N> mutable_buffer buffer( std::array< PodType, N > & data); » more... template< typename PodType, std::size_t N> mutable_buffer buffer( std::array< PodType, N > & data, std::size_t max_size_in_bytes); » more...
Create a new non-modifiable buffer that represents the given POD array.
template< typename PodType, std::size_t N> const_buffer buffer( std::array< const PodType, N > & data); » more... template< typename PodType, std::size_t N> const_buffer buffer( std::array< const PodType, N > & data, std::size_t max_size_in_bytes); » more...
Create a new modifiable buffer that represents the given POD vector.
template< typename PodType, typename Allocator> mutable_buffer buffer( std::vector< PodType, Allocator > & data); » more... template< typename PodType, typename Allocator> mutable_buffer buffer( std::vector< PodType, Allocator > & data, std::size_t max_size_in_bytes); » more...
Create a new non-modifiable buffer that represents the given POD vector.
template< typename PodType, typename Allocator> const_buffer buffer( const std::vector< PodType, Allocator > & data); » more... template< typename PodType, typename Allocator> const_buffer buffer( const std::vector< PodType, Allocator > & data, std::size_t max_size_in_bytes); » more...
Create a new modifiable buffer that represents the given string.
template< typename Elem, typename Traits, typename Allocator> mutable_buffer buffer( std::basic_string< Elem, Traits, Allocator > & data); » more... template< typename Elem, typename Traits, typename Allocator> mutable_buffer buffer( std::basic_string< Elem, Traits, Allocator > & data, std::size_t max_size_in_bytes); » more...
Create a new non-modifiable buffer that represents the given string.
template< typename Elem, typename Traits, typename Allocator> const_buffer buffer( const std::basic_string< Elem, Traits, Allocator > & data); » more... template< typename Elem, typename Traits, typename Allocator> const_buffer buffer( const std::basic_string< Elem, Traits, Allocator > & data, std::size_t max_size_in_bytes); » more...
Create a new non-modifiable buffer that represents the given string_view.
template< typename Elem, typename Traits> const_buffer buffer( basic_string_view< Elem, Traits > data); » more...
Create a new non-modifiable buffer that represents the given string.
template< typename Elem, typename Traits> const_buffer buffer( basic_string_view< Elem, Traits > data, std::size_t max_size_in_bytes); » more...
Create a new modifiable buffer from a contiguous container.
template< typename T> mutable_buffer buffer( T & data, constraint_t< is_contiguous_iterator< typename T::iterator >::value, defaulted_constraint > = defaulted_constraint(), constraint_t< !is_convertible< T, const_buffer >::value, defaulted_constraint > = defaulted_constraint(), constraint_t< !is_convertible< T, mutable_buffer >::value, defaulted_constraint > = defaulted_constraint(), constraint_t< !is_const< remove_reference_t< typename std::iterator_traits< typename T::iterator >::reference > >::value, defaulted_constraint > = defaulted_constraint()); » more... template< typename T> mutable_buffer buffer( T & data, std::size_t max_size_in_bytes, constraint_t< is_contiguous_iterator< typename T::iterator >::value, defaulted_constraint > = defaulted_constraint(), constraint_t< !is_convertible< T, const_buffer >::value, defaulted_constraint > = defaulted_constraint(), constraint_t< !is_convertible< T, mutable_buffer >::value, defaulted_constraint > = defaulted_constraint(), constraint_t< !is_const< remove_reference_t< typename std::iterator_traits< typename T::iterator >::reference > >::value, defaulted_constraint > = defaulted_constraint()); » more...
Create a new non-modifiable buffer from a contiguous container.
template< typename T> const_buffer buffer( T & data, constraint_t< is_contiguous_iterator< typename T::iterator >::value, defaulted_constraint > = defaulted_constraint(), constraint_t< !is_convertible< T, const_buffer >::value, defaulted_constraint > = defaulted_constraint(), constraint_t< !is_convertible< T, mutable_buffer >::value, defaulted_constraint > = defaulted_constraint(), constraint_t< is_const< remove_reference_t< typename std::iterator_traits< typename T::iterator >::reference > >::value, defaulted_constraint > = defaulted_constraint()); » more... template< typename T> const_buffer buffer( T & data, std::size_t max_size_in_bytes, constraint_t< is_contiguous_iterator< typename T::iterator >::value, defaulted_constraint > = defaulted_constraint(), constraint_t< !is_convertible< T, const_buffer >::value, defaulted_constraint > = defaulted_constraint(), constraint_t< !is_convertible< T, mutable_buffer >::value, defaulted_constraint > = defaulted_constraint(), constraint_t< is_const< remove_reference_t< typename std::iterator_traits< typename T::iterator >::reference > >::value, defaulted_constraint > = defaulted_constraint()); » more... template< typename T> const_buffer buffer( const T & data, constraint_t< is_contiguous_iterator< typename T::const_iterator >::value, defaulted_constraint > = defaulted_constraint(), constraint_t< !is_convertible< T, const_buffer >::value, defaulted_constraint > = defaulted_constraint(), constraint_t< !is_convertible< T, mutable_buffer >::value, defaulted_constraint > = defaulted_constraint()); » more... template< typename T> const_buffer buffer( const T & data, std::size_t max_size_in_bytes, constraint_t< is_contiguous_iterator< typename T::const_iterator >::value, defaulted_constraint > = defaulted_constraint(), constraint_t< !is_convertible< T, const_buffer >::value, defaulted_constraint > = defaulted_constraint(), constraint_t< !is_convertible< T, mutable_buffer >::value, defaulted_constraint > = defaulted_constraint()); » more...
Obtain a buffer representing the entire registered buffer.
mutable_registered_buffer buffer( const mutable_registered_buffer & b); » more... const_registered_buffer buffer( const const_registered_buffer & b); » more...
Obtain a buffer representing part of a registered buffer.
mutable_registered_buffer buffer( const mutable_registered_buffer & b, std::size_t n); » more... const_registered_buffer buffer( const const_registered_buffer & b, std::size_t n); » more...
A buffer object represents a contiguous region of memory as a 2-tuple consisting
of a pointer and size in bytes. A tuple of the form {void*, size_t}
specifies a mutable (modifiable) region
of memory. Similarly, a tuple of the form {const void*, size_t}
specifies a const (non-modifiable) region
of memory. These two forms correspond to the classes mutable_buffer
and const_buffer
, respectively. To mirror
C++'s conversion rules, a mutable_buffer
is implicitly convertible
to a const_buffer
,
and the opposite conversion is not permitted.
The simplest use case involves reading or writing a single buffer of a specified size:
sock.send(boost::asio::buffer(data, size));
In the above example, the return value of buffer
meets the requirements of
the ConstBufferSequence concept so that it may be directly passed to the
socket's write function. A buffer created for modifiable memory also meets
the requirements of the MutableBufferSequence concept.
An individual buffer may be created from a builtin array, std::vector, std::array or boost::array of POD elements. This helps prevent buffer overruns by automatically determining the size of the buffer:
char d1[128]; size_t bytes_transferred = sock.receive(boost::asio::buffer(d1)); std::vector<char> d2(128); bytes_transferred = sock.receive(boost::asio::buffer(d2)); std::array<char, 128> d3; bytes_transferred = sock.receive(boost::asio::buffer(d3)); boost::array<char, 128> d4; bytes_transferred = sock.receive(boost::asio::buffer(d4));
In all three cases above, the buffers created are exactly 128 bytes long.
Note that a vector is never automatically resized when
creating or using a buffer. The buffer size is determined using the vector's
size()
member function, and not its capacity.
The contents of a buffer may be accessed using the data()
and size()
member functions:
boost::asio::mutable_buffer 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 = b2.size(); const void* p2 = b2.data();
The data()
member function permits violations of type safety, so uses of it in application
code should be carefully considered.
For convenience, a 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.
The buffer_copy
function may be used to copy raw bytes between individual buffers and buffer
sequences.
In particular, when used with the buffer_size
function, the buffer_copy
function can be used to linearise a sequence of buffers. For example:
vector<const_buffer> buffers = ...; vector<unsigned char> data(boost::asio::buffer_size(buffers)); boost::asio::buffer_copy(boost::asio::buffer(data), buffers);
Note that buffer_copy
is implemented in terms
of memcpy
, and consequently
it cannot be used to copy between overlapping memory regions.
A buffer object does not have any ownership of the memory it refers to. It is the responsibility of the application to ensure the memory region remains valid until it is no longer required for an I/O operation. When the memory is no longer available, the buffer is said to have been invalidated.
For the buffer
overloads that accept an argument of type std::vector, the buffer objects
returned are invalidated by any vector operation that also invalidates all
references, pointers and iterators referring to the elements in the sequence
(C++ Std, 23.2.4)
For the buffer
overloads that accept an argument of type std::basic_string, the buffer objects
returned are invalidated according to the rules defined for invalidation
of references, pointers and iterators referring to elements of the sequence
(C++ Std, 21.3).
Buffer objects may be manipulated using simple arithmetic in a safe way which helps prevent buffer overruns. Consider an array initialised as follows:
boost::array<char, 6> a = { 'a', 'b', 'c', 'd', 'e' };
A buffer object b1
created
using:
b1 = boost::asio::buffer(a);
represents the entire array, { 'a', 'b', 'c',
'd', 'e' }
. An optional
second argument to the buffer
function may be used to limit
the size, in bytes, of the buffer:
b2 = boost::asio::buffer(a, 3);
such that b2
represents the
data { 'a', 'b',
'c' }
.
Even if the size argument exceeds the actual size of the array, the size
of the buffer object created will be limited to the array size.
An offset may be applied to an existing buffer to create a new one:
b3 = b1 + 2;
where b3
will set to represent
{ 'c', 'd',
'e' }
.
If the offset exceeds the size of the existing buffer, the newly created
buffer will be empty.
Both an offset and size may be specified to create a buffer that corresponds to a specific range of bytes within an existing buffer:
b4 = boost::asio::buffer(b1 + 1, 3);
so that b4
will refer to
the bytes { 'b', 'c',
'd' }
.
To read or write using multiple buffers (i.e. scatter-gather I/O), multiple buffer objects may be assigned into a container that supports the MutableBufferSequence (for read) or ConstBufferSequence (for write) concepts:
char d1[128]; std::vector<char> d2(128); boost::array<char, 128> d3; boost::array<mutable_buffer, 3> bufs1 = { boost::asio::buffer(d1), boost::asio::buffer(d2), boost::asio::buffer(d3) }; bytes_transferred = sock.receive(bufs1); std::vector<const_buffer> bufs2; bufs2.push_back(boost::asio::buffer(d1)); bufs2.push_back(boost::asio::buffer(d2)); bufs2.push_back(boost::asio::buffer(d3)); bytes_transferred = sock.send(bufs2);
The _buf
literal suffix,
defined in namespace boost::asio::buffer_literals
,
may be used to create const_buffer
objects from string, binary integer, and hexadecimal integer literals. For
example:
using namespace boost::asio::buffer_literals; boost::asio::const_buffer b1 = "hello"_buf; boost::asio::const_buffer b2 = 0xdeadbeef_buf; boost::asio::const_buffer b3 = 0x0123456789abcdef0123456789abcdef_buf; boost::asio::const_buffer b4 = 0b1010101011001100_buf;
Note that the memory associated with a buffer literal is valid for the lifetime of the program. This means that the buffer can be safely used with asynchronous operations.
Header: boost/asio/buffer.hpp
Convenience header: boost/asio.hpp