From bbba5657971016c0cfc59eb23d51180cb9fda7e3 Mon Sep 17 00:00:00 2001 From: Gudmundur Adalsteinsson Date: Fri, 10 May 2019 13:16:10 +0000 Subject: [PATCH] Simplify implementation of buffer creation functions --- zmq.hpp | 146 +++++++++++++++++++++++++------------------------------- 1 file changed, 66 insertions(+), 80 deletions(-) diff --git a/zmq.hpp b/zmq.hpp index afc2b5c..2f50669 100644 --- a/zmq.hpp +++ b/zmq.hpp @@ -737,7 +737,9 @@ class mutable_buffer constexpr mutable_buffer() noexcept : _data(nullptr), _size(0) {} constexpr mutable_buffer(void *p, size_t n) noexcept : _data(p), _size(n) { +#ifdef ZMQ_CPP14 assert(p != nullptr || n == 0); +#endif } constexpr void *data() const noexcept { return _data; } @@ -770,7 +772,12 @@ class const_buffer { public: 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 : _data(mb.data()), _size(mb.size()) @@ -817,7 +824,7 @@ constexpr mutable_buffer buffer(const mutable_buffer& mb) noexcept { 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)); } @@ -825,35 +832,13 @@ constexpr const_buffer buffer(const const_buffer& cb) noexcept { 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)); } namespace detail { -// utility functions for containers with data and size -// data is nullptr if the container is empty -template mutable_buffer buffar_mut_ds(T &data) noexcept -{ - return mutable_buffer(data.size() != 0u ? data.data() : nullptr, - data.size() * sizeof(*data.data())); -} -template 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 const_buffer buffar_const_ds(const T &data) noexcept -{ - return const_buffer(data.size() != 0u ? data.data() : nullptr, - data.size() * sizeof(*data.data())); -} -template 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 struct is_pod_like { // NOTE: The networking draft N4771 section 16.11 requires @@ -863,133 +848,136 @@ template struct is_pod_like static constexpr bool value = std::is_trivially_copyable::value && std::is_standard_layout::value; }; + +template constexpr auto seq_size(const C &c) noexcept -> decltype(c.size()) +{ + return c.size(); +} +template +constexpr size_t seq_size(const T (&/*array*/)[N]) noexcept +{ + return N; +} + +template +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::type>::type; + static_assert(detail::is_pod_like::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 +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::type>::type; + static_assert(detail::is_pod_like::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 // C array template mutable_buffer buffer(T (&data)[N]) noexcept { - static_assert(detail::is_pod_like::value, "T must be POD"); - static_assert(N > 0, "N > 0"); - return mutable_buffer(static_cast(data), N * sizeof(T)); + return detail::buffer_contiguous_sequence(data); } template mutable_buffer buffer(T (&data)[N], size_t n_bytes) noexcept { - static_assert(detail::is_pod_like::value, "T must be POD"); - static_assert(N > 0, "N > 0"); - return mutable_buffer(static_cast(data), (std::min)(N * sizeof(T), n_bytes)); + return detail::buffer_contiguous_sequence(data, n_bytes); } template const_buffer buffer(const T (&data)[N]) noexcept { - static_assert(detail::is_pod_like::value, "T must be POD"); - static_assert(N > 0, "N > 0"); - return const_buffer(static_cast(data), N * sizeof(T)); + return detail::buffer_contiguous_sequence(data); } template const_buffer buffer(const T (&data)[N], size_t n_bytes) noexcept { - static_assert(detail::is_pod_like::value, "T must be POD"); - static_assert(N > 0, "N > 0"); - return const_buffer(static_cast(data), - (std::min)(N * sizeof(T), n_bytes)); + return detail::buffer_contiguous_sequence(data, n_bytes); } // std::array template mutable_buffer buffer(std::array &data) noexcept { - static_assert(detail::is_pod_like::value, "T must be POD"); - static_assert(N > 0, "N > 0"); - return mutable_buffer(data.data(), N * sizeof(T)); + return detail::buffer_contiguous_sequence(data); } template mutable_buffer buffer(std::array &data, size_t n_bytes) noexcept { - static_assert(detail::is_pod_like::value, "T must be POD"); - static_assert(N > 0, "N > 0"); - return mutable_buffer(data.data(), (std::min)(N * sizeof(T), n_bytes)); + return detail::buffer_contiguous_sequence(data, n_bytes); } template const_buffer buffer(std::array &data) noexcept { - static_assert(detail::is_pod_like::value, "T must be POD"); - static_assert(N > 0, "N > 0"); - return const_buffer(data.data(), N * sizeof(T)); + return detail::buffer_contiguous_sequence(data); } template const_buffer buffer(std::array &data, size_t n_bytes) noexcept { - static_assert(detail::is_pod_like::value, "T must be POD"); - static_assert(N > 0, "N > 0"); - return const_buffer(data.data(), (std::min)(N * sizeof(T), n_bytes)); + return detail::buffer_contiguous_sequence(data, n_bytes); } template const_buffer buffer(const std::array &data) noexcept { - static_assert(detail::is_pod_like::value, "T must be POD"); - static_assert(N > 0, "N > 0"); - return const_buffer(data.data(), N * sizeof(T)); + return detail::buffer_contiguous_sequence(data); } template const_buffer buffer(const std::array &data, size_t n_bytes) noexcept { - static_assert(detail::is_pod_like::value, "T must be POD"); - static_assert(N > 0, "N > 0"); - return const_buffer(data.data(), (std::min)(N * sizeof(T), n_bytes)); + return detail::buffer_contiguous_sequence(data, n_bytes); } // std::vector template mutable_buffer buffer(std::vector &data) noexcept { - static_assert(detail::is_pod_like::value, "T must be POD"); - return detail::buffar_mut_ds(data); + return detail::buffer_contiguous_sequence(data); } template mutable_buffer buffer(std::vector &data, size_t n_bytes) noexcept { - static_assert(detail::is_pod_like::value, "T must be POD"); - return detail::buffar_mut_ds(data, n_bytes); + return detail::buffer_contiguous_sequence(data, n_bytes); } template const_buffer buffer(const std::vector &data) noexcept { - static_assert(detail::is_pod_like::value, "T must be POD"); - return detail::buffar_const_ds(data); + return detail::buffer_contiguous_sequence(data); } template const_buffer buffer(const std::vector &data, size_t n_bytes) noexcept { - static_assert(detail::is_pod_like::value, "T must be POD"); - return detail::buffar_const_ds(data, n_bytes); + return detail::buffer_contiguous_sequence(data, n_bytes); } // std::basic_string template mutable_buffer buffer(std::basic_string &data) noexcept { - static_assert(detail::is_pod_like::value, "T must be POD"); - // before C++17 string::data() returned const char* - return mutable_buffer(data.size() != 0u ? &data[0] : nullptr, - data.size() * sizeof(T)); + return detail::buffer_contiguous_sequence(data); } template mutable_buffer buffer(std::basic_string &data, size_t n_bytes) noexcept { - static_assert(detail::is_pod_like::value, "T must be POD"); - // 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)); + return detail::buffer_contiguous_sequence(data, n_bytes); } template const_buffer buffer(const std::basic_string &data) noexcept { - static_assert(detail::is_pod_like::value, "T must be POD"); - return detail::buffar_const_ds(data); + return detail::buffer_contiguous_sequence(data); } template const_buffer buffer(const std::basic_string &data, size_t n_bytes) noexcept { - static_assert(detail::is_pod_like::value, "T must be POD"); - return detail::buffar_const_ds(data, n_bytes); + return detail::buffer_contiguous_sequence(data, n_bytes); } #ifdef ZMQ_CPP17 @@ -997,14 +985,12 @@ const_buffer buffer(const std::basic_string &data, template const_buffer buffer(std::basic_string_view data) noexcept { - static_assert(detail::is_pod_like::value, "T must be POD"); - return detail::buffar_const_ds(data); + return detail::buffer_contiguous_sequence(data); } template const_buffer buffer(std::basic_string_view data, size_t n_bytes) noexcept { - static_assert(detail::is_pod_like::value, "T must be POD"); - return detail::buffar_const_ds(data, n_bytes); + return detail::buffer_contiguous_sequence(data, n_bytes); } #endif