Add safe buffer support for arrays, boost::array and vector.

This commit is contained in:
chris_kohlhoff 2005-09-18 05:12:36 +00:00
parent d7b8eb5f96
commit 1960f94b01
3 changed files with 528 additions and 61 deletions

View File

@ -20,6 +20,8 @@
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include <boost/array.hpp>
#include <vector>
#include "asio/detail/pop_options.hpp"
namespace asio {
@ -59,31 +61,21 @@ public:
return size_;
}
/// Obtain a new buffer that represents a part of the buffer.
mutable_buffer sub_buffer(std::size_t start) const
{
if (start > size_)
return mutable_buffer();
char* new_data = static_cast<char*>(data_) + start;
std::size_t new_size = size_ - start;
return mutable_buffer(new_data, new_size);
}
/// Obtain a new buffer that represents a part of the buffer.
mutable_buffer sub_buffer(std::size_t start, std::size_t size) const
{
if (start > size_)
return mutable_buffer();
char* new_data = static_cast<char*>(data_) + start;
std::size_t new_size = (size_ - start < size) ? (size_ - start) : size;
return mutable_buffer(new_data, new_size);
}
private:
void* data_;
std::size_t size_;
};
/// Create a new modifiable buffer that is offset from the start of another.
inline mutable_buffer operator+(const mutable_buffer& b, std::size_t start)
{
if (start > b.size())
return mutable_buffer();
char* new_data = static_cast<char*>(b.data()) + start;
std::size_t new_size = b.size() - start;
return mutable_buffer(new_data, new_size);
}
/// Holds a buffer that cannot be modified.
/**
* The const_buffer class provides a safe representation of a buffer that cannot
@ -126,41 +118,194 @@ public:
return size_;
}
/// Obtain a new buffer that represents a part of the buffer.
const_buffer sub_buffer(std::size_t start) const
{
if (start > size_)
return const_buffer();
const char* new_data = static_cast<const char*>(data_) + start;
std::size_t new_size = size_ - start;
return const_buffer(new_data, new_size);
}
/// Obtain a new buffer that represents a part of the buffer.
const_buffer sub_buffer(std::size_t start, std::size_t size) const
{
if (start > size_)
return const_buffer();
const char* new_data = static_cast<const char*>(data_) + start;
std::size_t new_size = (size_ - start < size) ? (size_ - start) : size;
return const_buffer(new_data, new_size);
}
private:
const void* data_;
std::size_t size_;
};
/// Create a new modifiable buffer that represents the given memory range.
inline mutable_buffer buffer(void* data, std::size_t size)
/// Create a new non-modifiable buffer that is offset from the start of another.
inline const_buffer operator+(const const_buffer& b, std::size_t start)
{
return mutable_buffer(data, size);
if (start > b.size())
return const_buffer();
const char* new_data = static_cast<const char*>(b.data()) + start;
std::size_t new_size = b.size() - start;
return const_buffer(new_data, new_size);
}
/// Create a new modifiable buffer from an existing buffer.
inline mutable_buffer buffer(const mutable_buffer& b)
{
return mutable_buffer(b);
}
/// Create a new modifiable buffer from an existing buffer.
inline mutable_buffer buffer(const mutable_buffer& b,
std::size_t max_size_in_bytes)
{
return mutable_buffer(b.data(),
b.size() < max_size_in_bytes ? b.size() : max_size_in_bytes);
}
/// Create a new non-modifiable buffer from an existing buffer.
inline const_buffer buffer(const const_buffer& b)
{
return const_buffer(b);
}
/// Create a new non-modifiable buffer from an existing buffer.
inline const_buffer buffer(const const_buffer& b,
std::size_t max_size_in_bytes)
{
return const_buffer(b.data(),
b.size() < max_size_in_bytes ? b.size() : max_size_in_bytes);
}
/// Create a new modifiable buffer that represents the given memory range.
inline mutable_buffer buffer(void* data, std::size_t size_in_bytes)
{
return mutable_buffer(data, size_in_bytes);
}
/// Create a new non-modifiable buffer that represents the given memory range.
inline const_buffer buffer(const void* data, std::size_t size)
inline const_buffer buffer(const void* data, std::size_t size_in_bytes)
{
return const_buffer(data, size);
return const_buffer(data, size_in_bytes);
}
/// Create a new modifiable buffer that represents the given POD array.
template <typename Pod_Type, std::size_t N>
inline mutable_buffer buffer(Pod_Type (&data)[N])
{
return mutable_buffer(data, N * sizeof(Pod_Type));
}
/// Create a new modifiable buffer that represents the given POD array.
template <typename Pod_Type, std::size_t N>
inline mutable_buffer buffer(Pod_Type (&data)[N], std::size_t max_size_in_bytes)
{
return mutable_buffer(data,
N * sizeof(Pod_Type) < max_size_in_bytes
? N * sizeof(Pod_Type) : max_size_in_bytes);
}
/// Create a new non-modifiable buffer that represents the given POD array.
template <typename Pod_Type, std::size_t N>
inline const_buffer buffer(const Pod_Type (&data)[N])
{
return const_buffer(data, N * sizeof(Pod_Type));
}
/// Create a new non-modifiable buffer that represents the given POD array.
template <typename Pod_Type, std::size_t N>
inline const_buffer buffer(const Pod_Type (&data)[N],
std::size_t max_size_in_bytes)
{
return const_buffer(data,
N * sizeof(Pod_Type) < max_size_in_bytes
? N * sizeof(Pod_Type) : max_size_in_bytes);
}
/// Create a new modifiable buffer that represents the given POD array.
template <typename Pod_Type, std::size_t N>
inline mutable_buffer buffer(boost::array<Pod_Type, N>& data)
{
return mutable_buffer(data.c_array(), data.size() * sizeof(Pod_Type));
}
/// Create a new modifiable buffer that represents the given POD array.
template <typename Pod_Type, std::size_t N>
inline mutable_buffer buffer(boost::array<Pod_Type, N>& data,
std::size_t max_size_in_bytes)
{
return mutable_buffer(data.c_array(),
data.size() * sizeof(Pod_Type) < max_size_in_bytes
? data.size() * sizeof(Pod_Type) : max_size_in_bytes);
}
/// Create a new non-modifiable buffer that represents the given POD array.
template <typename Pod_Type, std::size_t N>
inline const_buffer buffer(const boost::array<Pod_Type, N>& data)
{
return const_buffer(data.data(), data.size() * sizeof(Pod_Type));
}
/// Create a new non-modifiable buffer that represents the given POD array.
template <typename Pod_Type, std::size_t N>
inline const_buffer buffer(const boost::array<Pod_Type, N>& data,
std::size_t max_size_in_bytes)
{
return const_buffer(data.data(),
data.size() * sizeof(Pod_Type) < max_size_in_bytes
? data.size() * sizeof(Pod_Type) : max_size_in_bytes);
}
/// Create a new non-modifiable buffer that represents the given POD array.
template <typename Pod_Type, std::size_t N>
inline const_buffer buffer(boost::array<const Pod_Type, N>& data)
{
return const_buffer(data.data(), data.size() * sizeof(Pod_Type));
}
/// Create a new non-modifiable buffer that represents the given POD array.
template <typename Pod_Type, std::size_t N>
inline const_buffer buffer(boost::array<const Pod_Type, N>& data,
std::size_t max_size_in_bytes)
{
return const_buffer(data.data(),
data.size() * sizeof(Pod_Type) < max_size_in_bytes
? data.size() * sizeof(Pod_Type) : max_size_in_bytes);
}
/// Create a new modifiable buffer that represents the given POD vector.
template <typename Pod_Type>
inline mutable_buffer buffer(std::vector<Pod_Type>& data)
{
return mutable_buffer(&data[0], data.size() * sizeof(Pod_Type));
}
/// Create a new modifiable buffer that represents the given POD vector.
template <typename Pod_Type>
inline mutable_buffer buffer(std::vector<Pod_Type>& data,
std::size_t max_size_in_bytes)
{
return mutable_buffer(&data[0],
data.size() * sizeof(Pod_Type) < max_size_in_bytes
? data.size() * sizeof(Pod_Type) : max_size_in_bytes);
}
/// Create a new non-modifiable buffer that represents the given POD vector.
template <typename Pod_Type>
inline const_buffer buffer(const std::vector<Pod_Type>& data)
{
return const_buffer(&data[0], data.size() * sizeof(Pod_Type));
}
/// Create a new non-modifiable buffer that represents the given POD vector.
template <typename Pod_Type>
inline const_buffer buffer(const std::vector<Pod_Type>& data,
std::size_t max_size_in_bytes)
{
return const_buffer(&data[0],
data.size() * sizeof(Pod_Type) < max_size_in_bytes
? data.size() * sizeof(Pod_Type) : max_size_in_bytes);
}
/// Create a new non-modifiable buffer that represents the given POD vector.
template <typename Pod_Type>
inline const_buffer buffer(std::vector<const Pod_Type>& data)
{
return const_buffer(&data[0], data.size() * sizeof(Pod_Type));
}
/// Create a new non-modifiable buffer that represents the given POD vector.
template <typename Pod_Type>
inline const_buffer buffer(std::vector<const Pod_Type>& data,
std::size_t max_size_in_bytes)
{
return const_buffer(&data[0],
data.size() * sizeof(Pod_Type) < max_size_in_bytes
? data.size() * sizeof(Pod_Type) : max_size_in_bytes);
}
} // namespace asio

View File

@ -129,7 +129,7 @@ public:
}
/// Create a new const_buffers instance with one additional element.
const_buffers<N + 1> operator()(const const_buffer& b)
const_buffers<N + 1> operator()(const const_buffer& b) const
{
const_buffers<N + 1> tmp;
for (std::size_t i = 0; i < N; ++i)
@ -139,9 +139,62 @@ public:
}
/// Create a new const_buffers instance with one additional element.
const_buffers<N + 1> operator()(const void* data, std::size_t size)
const_buffers<N + 1> operator()(const const_buffer& b,
std::size_t max_size_in_bytes) const
{
return operator()(buffer(data, size));
return operator()(buffer(b, max_size_in_bytes));
}
/// Create a new const_buffers instance with one additional element.
const_buffers<N + 1> operator()(const void* data,
std::size_t size_in_bytes) const
{
return operator()(buffer(data, size_in_bytes));
}
/// Create a new const_buffers instance with one additional element.
template <typename Pod_Type, std::size_t Num>
const_buffers<N + 1> operator()(const Pod_Type (&data)[Num]) const
{
return operator()(buffer(data));
}
/// Create a new const_buffers instance with one additional element.
template <typename Pod_Type, std::size_t Num>
const_buffers<N + 1> operator()(const Pod_Type (&data)[Num],
std::size_t max_size_in_bytes) const
{
return operator()(buffer(data, max_size_in_bytes));
}
/// Create a new const_buffers instance with one additional element.
template <typename Pod_Type, std::size_t Num>
const_buffers<N + 1> operator()(const boost::array<Pod_Type, Num>& data) const
{
return operator()(buffer(data));
}
/// Create a new const_buffers instance with one additional element.
template <typename Pod_Type, std::size_t Num>
const_buffers<N + 1> operator()(const boost::array<Pod_Type, Num>& data,
std::size_t max_size_in_bytes) const
{
return operator()(buffer(data, max_size_in_bytes));
}
/// Create a new const_buffers instance with one additional element.
template <typename Pod_Type>
const_buffers<N + 1> operator()(const std::vector<Pod_Type>& data) const
{
return operator()(buffer(data));
}
/// Create a new const_buffers instance with one additional element.
template <typename Pod_Type>
const_buffers<N + 1> operator()(const std::vector<Pod_Type>& data,
std::size_t max_size_in_bytes) const
{
return operator()(buffer(data, max_size_in_bytes));
}
/// Convert to a container.
@ -263,7 +316,7 @@ public:
}
/// Create a new mutable_buffers instance with one additional element.
mutable_buffers<N + 1> operator()(const mutable_buffer& b)
mutable_buffers<N + 1> operator()(const mutable_buffer& b) const
{
mutable_buffers<N + 1> tmp;
for (std::size_t i = 0; i < N; ++i)
@ -272,8 +325,15 @@ public:
return tmp;
}
/// Create a new mutable_buffers instance with one additional element.
mutable_buffers<N + 1> operator()(const mutable_buffer& b,
std::size_t max_size_in_bytes) const
{
return operator()(buffer(b, max_size_in_bytes));
}
/// Create a new const_buffers instance with one additional element.
const_buffers<N + 1> operator()(const const_buffer& b)
const_buffers<N + 1> operator()(const const_buffer& b) const
{
const_buffers<N + 1> tmp;
for (std::size_t i = 0; i < N; ++i)
@ -282,16 +342,144 @@ public:
return tmp;
}
/// Create a new mutable_buffers instance with one additional element.
mutable_buffers<N + 1> operator()(void* data, std::size_t size)
/// Create a new const_buffers instance with one additional element.
const_buffers<N + 1> operator()(const const_buffer& b,
std::size_t max_size_in_bytes) const
{
return operator()(buffer(data, size));
return operator()(buffer(b, max_size_in_bytes));
}
/// Create a new mutable_buffers instance with one additional element.
mutable_buffers<N + 1> operator()(void* data, std::size_t size_in_bytes) const
{
return operator()(buffer(data, size_in_bytes));
}
/// Create a new const_buffers instance with one additional element.
const_buffers<N + 1> operator()(const void* data, std::size_t size)
const_buffers<N + 1> operator()(const void* data,
std::size_t size_in_bytes) const
{
return operator()(buffer(data, size));
return operator()(buffer(data, size_in_bytes));
}
/// Create a new mutable_buffers instance with one additional element.
template <typename Pod_Type, std::size_t Num>
mutable_buffers<N + 1> operator()(Pod_Type (&data)[Num]) const
{
return operator()(buffer(data));
}
/// Create a new mutable_buffers instance with one additional element.
template <typename Pod_Type, std::size_t Num>
mutable_buffers<N + 1> operator()(Pod_Type (&data)[Num],
std::size_t max_size_in_bytes) const
{
return operator()(buffer(data, max_size_in_bytes));
}
/// Create a new const_buffers instance with one additional element.
template <typename Pod_Type, std::size_t Num>
const_buffers<N + 1> operator()(const Pod_Type (&data)[Num]) const
{
return operator()(buffer(data));
}
/// Create a new const_buffers instance with one additional element.
template <typename Pod_Type, std::size_t Num>
const_buffers<N + 1> operator()(const Pod_Type (&data)[Num],
std::size_t max_size_in_bytes) const
{
return operator()(buffer(data, max_size_in_bytes));
}
/// Create a new const_buffers instance with one additional element.
template <typename Pod_Type, std::size_t Num>
mutable_buffers<N + 1> operator()(boost::array<Pod_Type, Num>& data) const
{
return operator()(buffer(data));
}
/// Create a new const_buffers instance with one additional element.
template <typename Pod_Type, std::size_t Num>
mutable_buffers<N + 1> operator()(boost::array<Pod_Type, Num>& data,
std::size_t max_size_in_bytes) const
{
return operator()(buffer(data, max_size_in_bytes));
}
/// Create a new const_buffers instance with one additional element.
template <typename Pod_Type, std::size_t Num>
const_buffers<N + 1> operator()(const boost::array<Pod_Type, Num>& data) const
{
return operator()(buffer(data));
}
/// Create a new const_buffers instance with one additional element.
template <typename Pod_Type, std::size_t Num>
const_buffers<N + 1> operator()(const boost::array<Pod_Type, Num>& data,
std::size_t max_size_in_bytes) const
{
return operator()(buffer(data, max_size_in_bytes));
}
/// Create a new const_buffers instance with one additional element.
template <typename Pod_Type, std::size_t Num>
const_buffers<N + 1> operator()(boost::array<const Pod_Type, Num>& data) const
{
return operator()(buffer(data));
}
/// Create a new const_buffers instance with one additional element.
template <typename Pod_Type, std::size_t Num>
const_buffers<N + 1> operator()(boost::array<const Pod_Type, Num>& data,
std::size_t max_size_in_bytes) const
{
return operator()(buffer(data, max_size_in_bytes));
}
/// Create a new const_buffers instance with one additional element.
template <typename Pod_Type>
mutable_buffers<N + 1> operator()(std::vector<Pod_Type>& data) const
{
return operator()(buffer(data));
}
/// Create a new const_buffers instance with one additional element.
template <typename Pod_Type>
mutable_buffers<N + 1> operator()(std::vector<Pod_Type>& data,
std::size_t max_size_in_bytes) const
{
return operator()(buffer(data, max_size_in_bytes));
}
/// Create a new const_buffers instance with one additional element.
template <typename Pod_Type>
const_buffers<N + 1> operator()(const std::vector<Pod_Type>& data) const
{
return operator()(buffer(data));
}
/// Create a new const_buffers instance with one additional element.
template <typename Pod_Type>
const_buffers<N + 1> operator()(const std::vector<Pod_Type>& data,
std::size_t max_size_in_bytes) const
{
return operator()(buffer(data, max_size_in_bytes));
}
/// Create a new const_buffers instance with one additional element.
template <typename Pod_Type>
const_buffers<N + 1> operator()(std::vector<const Pod_Type>& data) const
{
return operator()(buffer(data));
}
/// Create a new const_buffers instance with one additional element.
template <typename Pod_Type>
const_buffers<N + 1> operator()(std::vector<const Pod_Type>& data,
std::size_t max_size_in_bytes) const
{
return operator()(buffer(data, max_size_in_bytes));
}
/// Convert to a const_buffers instance.
@ -321,6 +509,13 @@ inline const_buffers<1> buffers(const const_buffer& b)
return tmp;
}
/// Create a const_buffers instance with one element.
inline const_buffers<1> buffers(const const_buffer& b,
std::size_t max_size_in_bytes)
{
return buffers(buffer(b, max_size_in_bytes));
}
/// Create a mutable_buffers instance with one element.
inline mutable_buffers<1> buffers(const mutable_buffer& b)
{
@ -329,16 +524,143 @@ inline mutable_buffers<1> buffers(const mutable_buffer& b)
return tmp;
}
/// Create a const_buffers instance with one element.
inline const_buffers<1> buffers(const void* data, std::size_t size)
/// Create a mutable_buffers instance with one element.
inline mutable_buffers<1> buffers(const mutable_buffer& b,
std::size_t max_size_in_bytes)
{
return buffers(buffer(data, size));
return buffers(buffer(b, max_size_in_bytes));
}
/// Create a const_buffers instance with one element.
inline const_buffers<1> buffers(const void* data, std::size_t size_in_bytes)
{
return buffers(buffer(data, size_in_bytes));
}
/// Create a mutable_buffers instance with one element.
inline mutable_buffers<1> buffers(void* data, std::size_t size)
inline mutable_buffers<1> buffers(void* data, std::size_t size_in_bytes)
{
return buffers(buffer(data, size));
return buffers(buffer(data, size_in_bytes));
}
/// Create a mutable_buffers instance with one element.
template <typename Pod_Type, std::size_t N>
inline mutable_buffers<1> buffers(Pod_Type (&data)[N])
{
return buffers(buffer(data));
}
/// Create a mutable_buffers instance with one element.
template <typename Pod_Type, std::size_t N>
inline mutable_buffers<1> buffers(Pod_Type (&data)[N],
std::size_t max_size_in_bytes)
{
return buffers(buffer(data, max_size_in_bytes));
}
/// Create a const_buffers instance with one element.
template <typename Pod_Type, std::size_t N>
inline const_buffers<1> buffers(const Pod_Type (&data)[N])
{
return buffers(buffer(data));
}
/// Create a const_buffers instance with one element.
template <typename Pod_Type, std::size_t N>
inline const_buffers<1> buffers(const Pod_Type (&data)[N],
std::size_t max_size_in_bytes)
{
return buffers(buffer(data, max_size_in_bytes));
}
/// Create a mutable_buffers instance with one element.
template <typename Pod_Type, std::size_t N>
inline mutable_buffers<1> buffers(boost::array<Pod_Type, N>& data)
{
return buffers(buffer(data));
}
/// Create a mutable_buffers instance with one element.
template <typename Pod_Type, std::size_t N>
inline mutable_buffers<1> buffers(boost::array<Pod_Type, N>& data,
std::size_t max_size_in_bytes)
{
return buffers(buffer(data, max_size_in_bytes));
}
/// Create a const_buffers instance with one element.
template <typename Pod_Type, std::size_t N>
inline const_buffers<1> buffers(const boost::array<Pod_Type, N>& data)
{
return buffers(buffer(data));
}
/// Create a const_buffers instance with one element.
template <typename Pod_Type, std::size_t N>
inline const_buffers<1> buffers(const boost::array<Pod_Type, N>& data,
std::size_t max_size_in_bytes)
{
return buffers(buffer(data, max_size_in_bytes));
}
/// Create a const_buffers instance with one element.
template <typename Pod_Type, std::size_t N>
inline const_buffers<1> buffers(boost::array<const Pod_Type, N>& data)
{
return buffers(buffer(data));
}
/// Create a const_buffers instance with one element.
template <typename Pod_Type, std::size_t N>
inline const_buffers<1> buffers(boost::array<const Pod_Type, N>& data,
std::size_t max_size_in_bytes)
{
return buffers(buffer(data, max_size_in_bytes));
}
/// Create a mutable_buffers instance with one element.
template <typename Pod_Type>
inline mutable_buffers<1> buffers(std::vector<Pod_Type>& data)
{
return buffers(buffer(data));
}
/// Create a mutable_buffers instance with one element.
template <typename Pod_Type>
inline mutable_buffers<1> buffers(std::vector<Pod_Type>& data,
std::size_t max_size_in_bytes)
{
return buffers(buffer(data, max_size_in_bytes));
}
/// Create a const_buffers instance with one element.
template <typename Pod_Type>
inline const_buffers<1> buffers(const std::vector<Pod_Type>& data)
{
return buffers(buffer(data));
}
/// Create a const_buffers instance with one element.
template <typename Pod_Type>
inline const_buffers<1> buffers(const std::vector<Pod_Type>& data,
std::size_t max_size_in_bytes)
{
return buffers(buffer(data, max_size_in_bytes));
}
/// Create a const_buffers instance with one element.
template <typename Pod_Type>
inline const_buffers<1> buffers(std::vector<const Pod_Type>& data)
{
return buffers(buffer(data));
}
/// Create a const_buffers instance with one element.
template <typename Pod_Type>
inline const_buffers<1> buffers(std::vector<const Pod_Type>& data,
std::size_t max_size_in_bytes)
{
return buffers(buffer(data, max_size_in_bytes));
}
} // namespace asio

View File

@ -105,7 +105,7 @@ public:
}
else
{
*begin_ = begin_->sub_buffer(size);
*begin_ = *begin_ + size;
size = 0;
}
}