Simplify implementation of buffer creation functions

This commit is contained in:
Gudmundur Adalsteinsson 2019-05-10 13:16:10 +00:00
parent 809acb2dc8
commit bbba565797

146
zmq.hpp
View File

@ -737,7 +737,9 @@ class mutable_buffer
constexpr mutable_buffer() noexcept : _data(nullptr), _size(0) {} constexpr mutable_buffer() noexcept : _data(nullptr), _size(0) {}
constexpr mutable_buffer(void *p, size_t n) noexcept : _data(p), _size(n) constexpr mutable_buffer(void *p, size_t n) noexcept : _data(p), _size(n)
{ {
#ifdef ZMQ_CPP14
assert(p != nullptr || n == 0); assert(p != nullptr || n == 0);
#endif
} }
constexpr void *data() const noexcept { return _data; } constexpr void *data() const noexcept { return _data; }
@ -770,7 +772,12 @@ class const_buffer
{ {
public: public:
constexpr const_buffer() noexcept : _data(nullptr), _size(0) {} constexpr const_buffer() noexcept : _data(nullptr), _size(0) {}
constexpr const_buffer(const void *p, size_t n) noexcept : _data(p), _size(n) {} constexpr const_buffer(const void *p, size_t n) noexcept : _data(p), _size(n)
{
#ifdef ZMQ_CPP14
assert(p != nullptr || n == 0);
#endif
}
constexpr const_buffer(const mutable_buffer &mb) noexcept : constexpr const_buffer(const mutable_buffer &mb) noexcept :
_data(mb.data()), _data(mb.data()),
_size(mb.size()) _size(mb.size())
@ -817,7 +824,7 @@ constexpr mutable_buffer buffer(const mutable_buffer& mb) noexcept
{ {
return mb; return mb;
} }
constexpr mutable_buffer buffer(const mutable_buffer& mb, size_t n) noexcept inline mutable_buffer buffer(const mutable_buffer& mb, size_t n) noexcept
{ {
return mutable_buffer(mb.data(), (std::min)(mb.size(), n)); return mutable_buffer(mb.data(), (std::min)(mb.size(), n));
} }
@ -825,35 +832,13 @@ constexpr const_buffer buffer(const const_buffer& cb) noexcept
{ {
return cb; return cb;
} }
constexpr const_buffer buffer(const const_buffer& cb, size_t n) noexcept inline const_buffer buffer(const const_buffer& cb, size_t n) noexcept
{ {
return const_buffer(cb.data(), (std::min)(cb.size(), n)); return const_buffer(cb.data(), (std::min)(cb.size(), n));
} }
namespace detail namespace detail
{ {
// utility functions for containers with data and size
// data is nullptr if the container is empty
template<class T> mutable_buffer buffar_mut_ds(T &data) noexcept
{
return mutable_buffer(data.size() != 0u ? data.data() : nullptr,
data.size() * sizeof(*data.data()));
}
template<class T> mutable_buffer buffar_mut_ds(T &data, size_t n_bytes) noexcept
{
return mutable_buffer(data.size() != 0u ? data.data() : nullptr,
(std::min)(data.size() * sizeof(*data.data()), n_bytes));
}
template<class T> const_buffer buffar_const_ds(const T &data) noexcept
{
return const_buffer(data.size() != 0u ? data.data() : nullptr,
data.size() * sizeof(*data.data()));
}
template<class T> const_buffer buffar_const_ds(const T &data, size_t n_bytes) noexcept
{
return const_buffer(data.size() != 0u ? data.data() : nullptr,
(std::min)(data.size() * sizeof(*data.data()), n_bytes));
}
template<class T> struct is_pod_like template<class T> struct is_pod_like
{ {
// NOTE: The networking draft N4771 section 16.11 requires // NOTE: The networking draft N4771 section 16.11 requires
@ -863,133 +848,136 @@ template<class T> struct is_pod_like
static constexpr bool value = static constexpr bool value =
std::is_trivially_copyable<T>::value && std::is_standard_layout<T>::value; std::is_trivially_copyable<T>::value && std::is_standard_layout<T>::value;
}; };
template<class C> constexpr auto seq_size(const C &c) noexcept -> decltype(c.size())
{
return c.size();
}
template<class T, size_t N>
constexpr size_t seq_size(const T (&/*array*/)[N]) noexcept
{
return N;
}
template<class Seq>
auto buffer_contiguous_sequence(Seq &&seq) noexcept
-> decltype(buffer(std::addressof(*std::begin(seq)), size_t{}))
{
using T = typename std::remove_cv<
typename std::remove_reference<decltype(*std::begin(seq))>::type>::type;
static_assert(detail::is_pod_like<T>::value, "T must be POD");
const auto size = seq_size(seq);
return buffer(size != 0u ? std::addressof(*std::begin(seq)) : nullptr,
size * sizeof(T));
}
template<class Seq>
auto buffer_contiguous_sequence(Seq &&seq, size_t n_bytes) noexcept
-> decltype(buffer_contiguous_sequence(seq))
{
using T = typename std::remove_cv<
typename std::remove_reference<decltype(*std::begin(seq))>::type>::type;
static_assert(detail::is_pod_like<T>::value, "T must be POD");
const auto size = seq_size(seq);
return buffer(size != 0u ? std::addressof(*std::begin(seq)) : nullptr,
(std::min)(size * sizeof(T), n_bytes));
}
} // namespace detail } // namespace detail
// C array // C array
template<class T, size_t N> mutable_buffer buffer(T (&data)[N]) noexcept template<class T, size_t N> mutable_buffer buffer(T (&data)[N]) noexcept
{ {
static_assert(detail::is_pod_like<T>::value, "T must be POD"); return detail::buffer_contiguous_sequence(data);
static_assert(N > 0, "N > 0");
return mutable_buffer(static_cast<T *>(data), N * sizeof(T));
} }
template<class T, size_t N> template<class T, size_t N>
mutable_buffer buffer(T (&data)[N], size_t n_bytes) noexcept mutable_buffer buffer(T (&data)[N], size_t n_bytes) noexcept
{ {
static_assert(detail::is_pod_like<T>::value, "T must be POD"); return detail::buffer_contiguous_sequence(data, n_bytes);
static_assert(N > 0, "N > 0");
return mutable_buffer(static_cast<T *>(data), (std::min)(N * sizeof(T), n_bytes));
} }
template<class T, size_t N> const_buffer buffer(const T (&data)[N]) noexcept template<class T, size_t N> const_buffer buffer(const T (&data)[N]) noexcept
{ {
static_assert(detail::is_pod_like<T>::value, "T must be POD"); return detail::buffer_contiguous_sequence(data);
static_assert(N > 0, "N > 0");
return const_buffer(static_cast<const T *>(data), N * sizeof(T));
} }
template<class T, size_t N> template<class T, size_t N>
const_buffer buffer(const T (&data)[N], size_t n_bytes) noexcept const_buffer buffer(const T (&data)[N], size_t n_bytes) noexcept
{ {
static_assert(detail::is_pod_like<T>::value, "T must be POD"); return detail::buffer_contiguous_sequence(data, n_bytes);
static_assert(N > 0, "N > 0");
return const_buffer(static_cast<const T *>(data),
(std::min)(N * sizeof(T), n_bytes));
} }
// std::array // std::array
template<class T, size_t N> mutable_buffer buffer(std::array<T, N> &data) noexcept template<class T, size_t N> mutable_buffer buffer(std::array<T, N> &data) noexcept
{ {
static_assert(detail::is_pod_like<T>::value, "T must be POD"); return detail::buffer_contiguous_sequence(data);
static_assert(N > 0, "N > 0");
return mutable_buffer(data.data(), N * sizeof(T));
} }
template<class T, size_t N> template<class T, size_t N>
mutable_buffer buffer(std::array<T, N> &data, size_t n_bytes) noexcept mutable_buffer buffer(std::array<T, N> &data, size_t n_bytes) noexcept
{ {
static_assert(detail::is_pod_like<T>::value, "T must be POD"); return detail::buffer_contiguous_sequence(data, n_bytes);
static_assert(N > 0, "N > 0");
return mutable_buffer(data.data(), (std::min)(N * sizeof(T), n_bytes));
} }
template<class T, size_t N> template<class T, size_t N>
const_buffer buffer(std::array<const T, N> &data) noexcept const_buffer buffer(std::array<const T, N> &data) noexcept
{ {
static_assert(detail::is_pod_like<T>::value, "T must be POD"); return detail::buffer_contiguous_sequence(data);
static_assert(N > 0, "N > 0");
return const_buffer(data.data(), N * sizeof(T));
} }
template<class T, size_t N> template<class T, size_t N>
const_buffer buffer(std::array<const T, N> &data, size_t n_bytes) noexcept const_buffer buffer(std::array<const T, N> &data, size_t n_bytes) noexcept
{ {
static_assert(detail::is_pod_like<T>::value, "T must be POD"); return detail::buffer_contiguous_sequence(data, n_bytes);
static_assert(N > 0, "N > 0");
return const_buffer(data.data(), (std::min)(N * sizeof(T), n_bytes));
} }
template<class T, size_t N> template<class T, size_t N>
const_buffer buffer(const std::array<T, N> &data) noexcept const_buffer buffer(const std::array<T, N> &data) noexcept
{ {
static_assert(detail::is_pod_like<T>::value, "T must be POD"); return detail::buffer_contiguous_sequence(data);
static_assert(N > 0, "N > 0");
return const_buffer(data.data(), N * sizeof(T));
} }
template<class T, size_t N> template<class T, size_t N>
const_buffer buffer(const std::array<T, N> &data, size_t n_bytes) noexcept const_buffer buffer(const std::array<T, N> &data, size_t n_bytes) noexcept
{ {
static_assert(detail::is_pod_like<T>::value, "T must be POD"); return detail::buffer_contiguous_sequence(data, n_bytes);
static_assert(N > 0, "N > 0");
return const_buffer(data.data(), (std::min)(N * sizeof(T), n_bytes));
} }
// std::vector // std::vector
template<class T, class Allocator> template<class T, class Allocator>
mutable_buffer buffer(std::vector<T, Allocator> &data) noexcept mutable_buffer buffer(std::vector<T, Allocator> &data) noexcept
{ {
static_assert(detail::is_pod_like<T>::value, "T must be POD"); return detail::buffer_contiguous_sequence(data);
return detail::buffar_mut_ds(data);
} }
template<class T, class Allocator> template<class T, class Allocator>
mutable_buffer buffer(std::vector<T, Allocator> &data, size_t n_bytes) noexcept mutable_buffer buffer(std::vector<T, Allocator> &data, size_t n_bytes) noexcept
{ {
static_assert(detail::is_pod_like<T>::value, "T must be POD"); return detail::buffer_contiguous_sequence(data, n_bytes);
return detail::buffar_mut_ds(data, n_bytes);
} }
template<class T, class Allocator> template<class T, class Allocator>
const_buffer buffer(const std::vector<T, Allocator> &data) noexcept const_buffer buffer(const std::vector<T, Allocator> &data) noexcept
{ {
static_assert(detail::is_pod_like<T>::value, "T must be POD"); return detail::buffer_contiguous_sequence(data);
return detail::buffar_const_ds(data);
} }
template<class T, class Allocator> template<class T, class Allocator>
const_buffer buffer(const std::vector<T, Allocator> &data, size_t n_bytes) noexcept const_buffer buffer(const std::vector<T, Allocator> &data, size_t n_bytes) noexcept
{ {
static_assert(detail::is_pod_like<T>::value, "T must be POD"); return detail::buffer_contiguous_sequence(data, n_bytes);
return detail::buffar_const_ds(data, n_bytes);
} }
// std::basic_string // std::basic_string
template<class T, class Traits, class Allocator> template<class T, class Traits, class Allocator>
mutable_buffer buffer(std::basic_string<T, Traits, Allocator> &data) noexcept mutable_buffer buffer(std::basic_string<T, Traits, Allocator> &data) noexcept
{ {
static_assert(detail::is_pod_like<T>::value, "T must be POD"); return detail::buffer_contiguous_sequence(data);
// before C++17 string::data() returned const char*
return mutable_buffer(data.size() != 0u ? &data[0] : nullptr,
data.size() * sizeof(T));
} }
template<class T, class Traits, class Allocator> template<class T, class Traits, class Allocator>
mutable_buffer buffer(std::basic_string<T, Traits, Allocator> &data, mutable_buffer buffer(std::basic_string<T, Traits, Allocator> &data,
size_t n_bytes) noexcept size_t n_bytes) noexcept
{ {
static_assert(detail::is_pod_like<T>::value, "T must be POD"); return detail::buffer_contiguous_sequence(data, n_bytes);
// before C++17 string::data() returned const char*
return mutable_buffer(data.size() != 0u ? &data[0] : nullptr,
(std::min)(data.size() * sizeof(T), n_bytes));
} }
template<class T, class Traits, class Allocator> template<class T, class Traits, class Allocator>
const_buffer buffer(const std::basic_string<T, Traits, Allocator> &data) noexcept const_buffer buffer(const std::basic_string<T, Traits, Allocator> &data) noexcept
{ {
static_assert(detail::is_pod_like<T>::value, "T must be POD"); return detail::buffer_contiguous_sequence(data);
return detail::buffar_const_ds(data);
} }
template<class T, class Traits, class Allocator> template<class T, class Traits, class Allocator>
const_buffer buffer(const std::basic_string<T, Traits, Allocator> &data, const_buffer buffer(const std::basic_string<T, Traits, Allocator> &data,
size_t n_bytes) noexcept size_t n_bytes) noexcept
{ {
static_assert(detail::is_pod_like<T>::value, "T must be POD"); return detail::buffer_contiguous_sequence(data, n_bytes);
return detail::buffar_const_ds(data, n_bytes);
} }
#ifdef ZMQ_CPP17 #ifdef ZMQ_CPP17
@ -997,14 +985,12 @@ const_buffer buffer(const std::basic_string<T, Traits, Allocator> &data,
template<class T, class Traits> template<class T, class Traits>
const_buffer buffer(std::basic_string_view<T, Traits> data) noexcept const_buffer buffer(std::basic_string_view<T, Traits> data) noexcept
{ {
static_assert(detail::is_pod_like<T>::value, "T must be POD"); return detail::buffer_contiguous_sequence(data);
return detail::buffar_const_ds(data);
} }
template<class T, class Traits> template<class T, class Traits>
const_buffer buffer(std::basic_string_view<T, Traits> data, size_t n_bytes) noexcept const_buffer buffer(std::basic_string_view<T, Traits> data, size_t n_bytes) noexcept
{ {
static_assert(detail::is_pod_like<T>::value, "T must be POD"); return detail::buffer_contiguous_sequence(data, n_bytes);
return detail::buffar_const_ds(data, n_bytes);
} }
#endif #endif