Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-05-18 08:30:31

0001 /*
0002     Copyright (c) 2016-2017 ZeroMQ community
0003     Copyright (c) 2009-2011 250bpm s.r.o.
0004     Copyright (c) 2011 Botond Ballo
0005     Copyright (c) 2007-2009 iMatix Corporation
0006 
0007     Permission is hereby granted, free of charge, to any person obtaining a copy
0008     of this software and associated documentation files (the "Software"), to
0009     deal in the Software without restriction, including without limitation the
0010     rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
0011     sell copies of the Software, and to permit persons to whom the Software is
0012     furnished to do so, subject to the following conditions:
0013 
0014     The above copyright notice and this permission notice shall be included in
0015     all copies or substantial portions of the Software.
0016 
0017     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0018     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0019     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
0020     AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0021     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
0022     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
0023     IN THE SOFTWARE.
0024 */
0025 
0026 #ifndef __ZMQ_HPP_INCLUDED__
0027 #define __ZMQ_HPP_INCLUDED__
0028 
0029 #ifdef _WIN32
0030 #ifndef NOMINMAX
0031 #define NOMINMAX
0032 #endif
0033 #endif
0034 
0035 // included here for _HAS_CXX* macros
0036 #include <zmq.h>
0037 
0038 #if defined(_MSVC_LANG)
0039 #define CPPZMQ_LANG _MSVC_LANG
0040 #else
0041 #define CPPZMQ_LANG __cplusplus
0042 #endif
0043 // overwrite if specific language macros indicate higher version
0044 #if defined(_HAS_CXX14) && _HAS_CXX14 && CPPZMQ_LANG < 201402L
0045 #undef CPPZMQ_LANG
0046 #define CPPZMQ_LANG 201402L
0047 #endif
0048 #if defined(_HAS_CXX17) && _HAS_CXX17 && CPPZMQ_LANG < 201703L
0049 #undef CPPZMQ_LANG
0050 #define CPPZMQ_LANG 201703L
0051 #endif
0052 
0053 // macros defined if has a specific standard or greater
0054 #if CPPZMQ_LANG >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
0055 #define ZMQ_CPP11
0056 #endif
0057 #if CPPZMQ_LANG >= 201402L
0058 #define ZMQ_CPP14
0059 #endif
0060 #if CPPZMQ_LANG >= 201703L
0061 #define ZMQ_CPP17
0062 #endif
0063 
0064 #if defined(ZMQ_CPP14) && !defined(_MSC_VER)
0065 #define ZMQ_DEPRECATED(msg) [[deprecated(msg)]]
0066 #elif defined(_MSC_VER)
0067 #define ZMQ_DEPRECATED(msg) __declspec(deprecated(msg))
0068 #elif defined(__GNUC__)
0069 #define ZMQ_DEPRECATED(msg) __attribute__((deprecated(msg)))
0070 #else
0071 #define ZMQ_DEPRECATED(msg)
0072 #endif
0073 
0074 #if defined(ZMQ_CPP17)
0075 #define ZMQ_NODISCARD [[nodiscard]]
0076 #else
0077 #define ZMQ_NODISCARD
0078 #endif
0079 
0080 #if defined(ZMQ_CPP11)
0081 #define ZMQ_NOTHROW noexcept
0082 #define ZMQ_EXPLICIT explicit
0083 #define ZMQ_OVERRIDE override
0084 #define ZMQ_NULLPTR nullptr
0085 #define ZMQ_CONSTEXPR_FN constexpr
0086 #define ZMQ_CONSTEXPR_VAR constexpr
0087 #define ZMQ_CPP11_DEPRECATED(msg) ZMQ_DEPRECATED(msg)
0088 #else
0089 #define ZMQ_NOTHROW throw()
0090 #define ZMQ_EXPLICIT
0091 #define ZMQ_OVERRIDE
0092 #define ZMQ_NULLPTR 0
0093 #define ZMQ_CONSTEXPR_FN
0094 #define ZMQ_CONSTEXPR_VAR const
0095 #define ZMQ_CPP11_DEPRECATED(msg)
0096 #endif
0097 #if defined(ZMQ_CPP14) && (!defined(_MSC_VER) || _MSC_VER > 1900) && (!defined(__GNUC__) || __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ > 3))
0098 #define ZMQ_EXTENDED_CONSTEXPR
0099 #endif
0100 #if defined(ZMQ_CPP17)
0101 #define ZMQ_INLINE_VAR inline
0102 #define ZMQ_CONSTEXPR_IF constexpr
0103 #else
0104 #define ZMQ_INLINE_VAR
0105 #define ZMQ_CONSTEXPR_IF
0106 #endif
0107 
0108 #include <cassert>
0109 #include <cstring>
0110 
0111 #include <algorithm>
0112 #include <exception>
0113 #include <iomanip>
0114 #include <sstream>
0115 #include <string>
0116 #include <vector>
0117 #ifdef ZMQ_CPP11
0118 #include <array>
0119 #include <chrono>
0120 #include <tuple>
0121 #include <memory>
0122 #endif
0123 
0124 #if defined(__has_include) && defined(ZMQ_CPP17)
0125 #define CPPZMQ_HAS_INCLUDE_CPP17(X) __has_include(X)
0126 #else
0127 #define CPPZMQ_HAS_INCLUDE_CPP17(X) 0
0128 #endif
0129 
0130 #if CPPZMQ_HAS_INCLUDE_CPP17(<optional>) && !defined(CPPZMQ_HAS_OPTIONAL)
0131 #define CPPZMQ_HAS_OPTIONAL 1
0132 #endif
0133 #ifndef CPPZMQ_HAS_OPTIONAL
0134 #define CPPZMQ_HAS_OPTIONAL 0
0135 #elif CPPZMQ_HAS_OPTIONAL
0136 #include <optional>
0137 #endif
0138 
0139 #if CPPZMQ_HAS_INCLUDE_CPP17(<string_view>) && !defined(CPPZMQ_HAS_STRING_VIEW)
0140 #define CPPZMQ_HAS_STRING_VIEW 1
0141 #endif
0142 #ifndef CPPZMQ_HAS_STRING_VIEW
0143 #define CPPZMQ_HAS_STRING_VIEW 0
0144 #elif CPPZMQ_HAS_STRING_VIEW
0145 #include <string_view>
0146 #endif
0147 
0148 /*  Version macros for compile-time API version detection                     */
0149 #define CPPZMQ_VERSION_MAJOR 4
0150 #define CPPZMQ_VERSION_MINOR 9
0151 #define CPPZMQ_VERSION_PATCH 0
0152 
0153 #define CPPZMQ_VERSION                                                              \
0154     ZMQ_MAKE_VERSION(CPPZMQ_VERSION_MAJOR, CPPZMQ_VERSION_MINOR,                    \
0155                      CPPZMQ_VERSION_PATCH)
0156 
0157 //  Detect whether the compiler supports C++11 rvalue references.
0158 #if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2))   \
0159      && defined(__GXX_EXPERIMENTAL_CXX0X__))
0160 #define ZMQ_HAS_RVALUE_REFS
0161 #define ZMQ_DELETED_FUNCTION = delete
0162 #elif defined(__clang__)
0163 #if __has_feature(cxx_rvalue_references)
0164 #define ZMQ_HAS_RVALUE_REFS
0165 #endif
0166 
0167 #if __has_feature(cxx_deleted_functions)
0168 #define ZMQ_DELETED_FUNCTION = delete
0169 #else
0170 #define ZMQ_DELETED_FUNCTION
0171 #endif
0172 #elif defined(_MSC_VER) && (_MSC_VER >= 1900)
0173 #define ZMQ_HAS_RVALUE_REFS
0174 #define ZMQ_DELETED_FUNCTION = delete
0175 #elif defined(_MSC_VER) && (_MSC_VER >= 1600)
0176 #define ZMQ_HAS_RVALUE_REFS
0177 #define ZMQ_DELETED_FUNCTION
0178 #else
0179 #define ZMQ_DELETED_FUNCTION
0180 #endif
0181 
0182 #if defined(ZMQ_CPP11) && !defined(__llvm__) && !defined(__INTEL_COMPILER)          \
0183   && defined(__GNUC__) && __GNUC__ < 5
0184 #define ZMQ_CPP11_PARTIAL
0185 #elif defined(__GLIBCXX__) && __GLIBCXX__ < 20160805
0186 //the date here is the last date of gcc 4.9.4, which
0187 // effectively means libstdc++ from gcc 5.5 and higher won't trigger this branch
0188 #define ZMQ_CPP11_PARTIAL
0189 #endif
0190 
0191 #ifdef ZMQ_CPP11
0192 #ifdef ZMQ_CPP11_PARTIAL
0193 #define ZMQ_IS_TRIVIALLY_COPYABLE(T) __has_trivial_copy(T)
0194 #else
0195 #include <type_traits>
0196 #define ZMQ_IS_TRIVIALLY_COPYABLE(T) std::is_trivially_copyable<T>::value
0197 #endif
0198 #endif
0199 
0200 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3, 3, 0)
0201 #define ZMQ_NEW_MONITOR_EVENT_LAYOUT
0202 #endif
0203 
0204 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0)
0205 #define ZMQ_HAS_PROXY_STEERABLE
0206 /*  Socket event data  */
0207 typedef struct
0208 {
0209     uint16_t event; // id of the event as bitfield
0210     int32_t value;  // value is either error code, fd or reconnect interval
0211 } zmq_event_t;
0212 #endif
0213 
0214 // Avoid using deprecated message receive function when possible
0215 #if ZMQ_VERSION < ZMQ_MAKE_VERSION(3, 2, 0)
0216 #define zmq_msg_recv(msg, socket, flags) zmq_recvmsg(socket, msg, flags)
0217 #endif
0218 
0219 
0220 // In order to prevent unused variable warnings when building in non-debug
0221 // mode use this macro to make assertions.
0222 #ifndef NDEBUG
0223 #define ZMQ_ASSERT(expression) assert(expression)
0224 #else
0225 #define ZMQ_ASSERT(expression) (void) (expression)
0226 #endif
0227 
0228 namespace zmq
0229 {
0230 #ifdef ZMQ_CPP11
0231 namespace detail
0232 {
0233 namespace ranges
0234 {
0235 using std::begin;
0236 using std::end;
0237 template<class T> auto begin(T &&r) -> decltype(begin(std::forward<T>(r)))
0238 {
0239     return begin(std::forward<T>(r));
0240 }
0241 template<class T> auto end(T &&r) -> decltype(end(std::forward<T>(r)))
0242 {
0243     return end(std::forward<T>(r));
0244 }
0245 } // namespace ranges
0246 
0247 template<class T> using void_t = void;
0248 
0249 template<class Iter>
0250 using iter_value_t = typename std::iterator_traits<Iter>::value_type;
0251 
0252 template<class Range>
0253 using range_iter_t = decltype(
0254   ranges::begin(std::declval<typename std::remove_reference<Range>::type &>()));
0255 
0256 template<class Range> using range_value_t = iter_value_t<range_iter_t<Range>>;
0257 
0258 template<class T, class = void> struct is_range : std::false_type
0259 {
0260 };
0261 
0262 template<class T>
0263 struct is_range<
0264   T,
0265   void_t<decltype(
0266     ranges::begin(std::declval<typename std::remove_reference<T>::type &>())
0267     == ranges::end(std::declval<typename std::remove_reference<T>::type &>()))>>
0268     : std::true_type
0269 {
0270 };
0271 
0272 } // namespace detail
0273 #endif
0274 
0275 typedef zmq_free_fn free_fn;
0276 typedef zmq_pollitem_t pollitem_t;
0277 
0278 // duplicate definition from libzmq 4.3.3
0279 #if defined _WIN32
0280 #if defined _WIN64
0281 typedef unsigned __int64 fd_t;
0282 #else
0283 typedef unsigned int fd_t;
0284 #endif
0285 #else
0286 typedef int fd_t;
0287 #endif
0288 
0289 class error_t : public std::exception
0290 {
0291   public:
0292     error_t() ZMQ_NOTHROW : errnum(zmq_errno()) {}
0293     explicit error_t(int err) ZMQ_NOTHROW : errnum(err) {}
0294     virtual const char *what() const ZMQ_NOTHROW ZMQ_OVERRIDE
0295     {
0296         return zmq_strerror(errnum);
0297     }
0298     int num() const ZMQ_NOTHROW { return errnum; }
0299 
0300   private:
0301     int errnum;
0302 };
0303 
0304 namespace detail {
0305 inline int poll(zmq_pollitem_t *items_, size_t nitems_, long timeout_)
0306 {
0307     int rc = zmq_poll(items_, static_cast<int>(nitems_), timeout_);
0308     if (rc < 0)
0309         throw error_t();
0310     return rc;
0311 }
0312 }
0313 
0314 #ifdef ZMQ_CPP11
0315 ZMQ_DEPRECATED("from 4.8.0, use poll taking std::chrono::duration instead of long")
0316 inline int poll(zmq_pollitem_t *items_, size_t nitems_, long timeout_)
0317 #else
0318 inline int poll(zmq_pollitem_t *items_, size_t nitems_, long timeout_ = -1)
0319 #endif
0320 {
0321     return detail::poll(items_, nitems_, timeout_);
0322 }
0323 
0324 ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
0325 inline int poll(zmq_pollitem_t const *items_, size_t nitems_, long timeout_ = -1)
0326 {
0327     return detail::poll(const_cast<zmq_pollitem_t *>(items_), nitems_, timeout_);
0328 }
0329 
0330 #ifdef ZMQ_CPP11
0331 ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
0332 inline int
0333 poll(zmq_pollitem_t const *items, size_t nitems, std::chrono::milliseconds timeout)
0334 {
0335     return detail::poll(const_cast<zmq_pollitem_t *>(items), nitems,
0336                 static_cast<long>(timeout.count()));
0337 }
0338 
0339 ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
0340 inline int poll(std::vector<zmq_pollitem_t> const &items,
0341                 std::chrono::milliseconds timeout)
0342 {
0343     return detail::poll(const_cast<zmq_pollitem_t *>(items.data()), items.size(),
0344                 static_cast<long>(timeout.count()));
0345 }
0346 
0347 ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
0348 inline int poll(std::vector<zmq_pollitem_t> const &items, long timeout_ = -1)
0349 {
0350     return detail::poll(const_cast<zmq_pollitem_t *>(items.data()), items.size(), timeout_);
0351 }
0352 
0353 inline int
0354 poll(zmq_pollitem_t *items, size_t nitems, std::chrono::milliseconds timeout = std::chrono::milliseconds{-1})
0355 {
0356     return detail::poll(items, nitems, static_cast<long>(timeout.count()));
0357 }
0358 
0359 inline int poll(std::vector<zmq_pollitem_t> &items,
0360                 std::chrono::milliseconds timeout = std::chrono::milliseconds{-1})
0361 {
0362     return detail::poll(items.data(), items.size(), static_cast<long>(timeout.count()));
0363 }
0364 
0365 ZMQ_DEPRECATED("from 4.3.1, use poll taking std::chrono::duration instead of long")
0366 inline int poll(std::vector<zmq_pollitem_t> &items, long timeout_)
0367 {
0368     return detail::poll(items.data(), items.size(), timeout_);
0369 }
0370 
0371 template<std::size_t SIZE>
0372 inline int poll(std::array<zmq_pollitem_t, SIZE> &items,
0373                 std::chrono::milliseconds timeout = std::chrono::milliseconds{-1})
0374 {
0375     return detail::poll(items.data(), items.size(), static_cast<long>(timeout.count()));
0376 }
0377 #endif
0378 
0379 
0380 inline void version(int *major_, int *minor_, int *patch_)
0381 {
0382     zmq_version(major_, minor_, patch_);
0383 }
0384 
0385 #ifdef ZMQ_CPP11
0386 inline std::tuple<int, int, int> version()
0387 {
0388     std::tuple<int, int, int> v;
0389     zmq_version(&std::get<0>(v), &std::get<1>(v), &std::get<2>(v));
0390     return v;
0391 }
0392 
0393 #if !defined(ZMQ_CPP11_PARTIAL)
0394 namespace detail
0395 {
0396 template<class T> struct is_char_type
0397 {
0398     // true if character type for string literals in C++11
0399     static constexpr bool value =
0400       std::is_same<T, char>::value || std::is_same<T, wchar_t>::value
0401       || std::is_same<T, char16_t>::value || std::is_same<T, char32_t>::value;
0402 };
0403 }
0404 #endif
0405 
0406 #endif
0407 
0408 class message_t
0409 {
0410   public:
0411     message_t() ZMQ_NOTHROW
0412     {
0413         int rc = zmq_msg_init(&msg);
0414         ZMQ_ASSERT(rc == 0);
0415     }
0416 
0417     explicit message_t(size_t size_)
0418     {
0419         int rc = zmq_msg_init_size(&msg, size_);
0420         if (rc != 0)
0421             throw error_t();
0422     }
0423 
0424     template<class ForwardIter> message_t(ForwardIter first, ForwardIter last)
0425     {
0426         typedef typename std::iterator_traits<ForwardIter>::value_type value_t;
0427 
0428         assert(std::distance(first, last) >= 0);
0429         size_t const size_ =
0430           static_cast<size_t>(std::distance(first, last)) * sizeof(value_t);
0431         int const rc = zmq_msg_init_size(&msg, size_);
0432         if (rc != 0)
0433             throw error_t();
0434         std::copy(first, last, data<value_t>());
0435     }
0436 
0437     message_t(const void *data_, size_t size_)
0438     {
0439         int rc = zmq_msg_init_size(&msg, size_);
0440         if (rc != 0)
0441             throw error_t();
0442         if (size_) {
0443             // this constructor allows (nullptr, 0),
0444             // memcpy with a null pointer is UB
0445             memcpy(data(), data_, size_);
0446         }
0447     }
0448 
0449     message_t(void *data_, size_t size_, free_fn *ffn_, void *hint_ = ZMQ_NULLPTR)
0450     {
0451         int rc = zmq_msg_init_data(&msg, data_, size_, ffn_, hint_);
0452         if (rc != 0)
0453             throw error_t();
0454     }
0455 
0456     // overload set of string-like types and generic containers
0457 #if defined(ZMQ_CPP11) && !defined(ZMQ_CPP11_PARTIAL)
0458     // NOTE this constructor will include the null terminator
0459     // when called with a string literal.
0460     // An overload taking const char* can not be added because
0461     // it would be preferred over this function and break compatiblity.
0462     template<
0463       class Char,
0464       size_t N,
0465       typename = typename std::enable_if<detail::is_char_type<Char>::value>::type>
0466     ZMQ_DEPRECATED("from 4.7.0, use constructors taking iterators, (pointer, size) "
0467                    "or strings instead")
0468     explicit message_t(const Char (&data)[N]) :
0469         message_t(detail::ranges::begin(data), detail::ranges::end(data))
0470     {
0471     }
0472 
0473     template<class Range,
0474              typename = typename std::enable_if<
0475                detail::is_range<Range>::value
0476                && ZMQ_IS_TRIVIALLY_COPYABLE(detail::range_value_t<Range>)
0477                && !detail::is_char_type<detail::range_value_t<Range>>::value
0478                && !std::is_same<Range, message_t>::value>::type>
0479     explicit message_t(const Range &rng) :
0480         message_t(detail::ranges::begin(rng), detail::ranges::end(rng))
0481     {
0482     }
0483 
0484     explicit message_t(const std::string &str) : message_t(str.data(), str.size()) {}
0485 
0486 #if CPPZMQ_HAS_STRING_VIEW
0487     explicit message_t(std::string_view str) : message_t(str.data(), str.size()) {}
0488 #endif
0489 
0490 #endif
0491 
0492 #ifdef ZMQ_HAS_RVALUE_REFS
0493     message_t(message_t &&rhs) ZMQ_NOTHROW : msg(rhs.msg)
0494     {
0495         int rc = zmq_msg_init(&rhs.msg);
0496         ZMQ_ASSERT(rc == 0);
0497     }
0498 
0499     message_t &operator=(message_t &&rhs) ZMQ_NOTHROW
0500     {
0501         std::swap(msg, rhs.msg);
0502         return *this;
0503     }
0504 #endif
0505 
0506     ~message_t() ZMQ_NOTHROW
0507     {
0508         int rc = zmq_msg_close(&msg);
0509         ZMQ_ASSERT(rc == 0);
0510     }
0511 
0512     void rebuild()
0513     {
0514         int rc = zmq_msg_close(&msg);
0515         if (rc != 0)
0516             throw error_t();
0517         rc = zmq_msg_init(&msg);
0518         ZMQ_ASSERT(rc == 0);
0519     }
0520 
0521     void rebuild(size_t size_)
0522     {
0523         int rc = zmq_msg_close(&msg);
0524         if (rc != 0)
0525             throw error_t();
0526         rc = zmq_msg_init_size(&msg, size_);
0527         if (rc != 0)
0528             throw error_t();
0529     }
0530 
0531     void rebuild(const void *data_, size_t size_)
0532     {
0533         int rc = zmq_msg_close(&msg);
0534         if (rc != 0)
0535             throw error_t();
0536         rc = zmq_msg_init_size(&msg, size_);
0537         if (rc != 0)
0538             throw error_t();
0539         memcpy(data(), data_, size_);
0540     }
0541 
0542     void rebuild(void *data_, size_t size_, free_fn *ffn_, void *hint_ = ZMQ_NULLPTR)
0543     {
0544         int rc = zmq_msg_close(&msg);
0545         if (rc != 0)
0546             throw error_t();
0547         rc = zmq_msg_init_data(&msg, data_, size_, ffn_, hint_);
0548         if (rc != 0)
0549             throw error_t();
0550     }
0551 
0552     ZMQ_DEPRECATED("from 4.3.1, use move taking non-const reference instead")
0553     void move(message_t const *msg_)
0554     {
0555         int rc = zmq_msg_move(&msg, const_cast<zmq_msg_t *>(msg_->handle()));
0556         if (rc != 0)
0557             throw error_t();
0558     }
0559 
0560     void move(message_t &msg_)
0561     {
0562         int rc = zmq_msg_move(&msg, msg_.handle());
0563         if (rc != 0)
0564             throw error_t();
0565     }
0566 
0567     ZMQ_DEPRECATED("from 4.3.1, use copy taking non-const reference instead")
0568     void copy(message_t const *msg_)
0569     {
0570         int rc = zmq_msg_copy(&msg, const_cast<zmq_msg_t *>(msg_->handle()));
0571         if (rc != 0)
0572             throw error_t();
0573     }
0574 
0575     void copy(message_t &msg_)
0576     {
0577         int rc = zmq_msg_copy(&msg, msg_.handle());
0578         if (rc != 0)
0579             throw error_t();
0580     }
0581 
0582     bool more() const ZMQ_NOTHROW
0583     {
0584         int rc = zmq_msg_more(const_cast<zmq_msg_t *>(&msg));
0585         return rc != 0;
0586     }
0587 
0588     void *data() ZMQ_NOTHROW { return zmq_msg_data(&msg); }
0589 
0590     const void *data() const ZMQ_NOTHROW
0591     {
0592         return zmq_msg_data(const_cast<zmq_msg_t *>(&msg));
0593     }
0594 
0595     size_t size() const ZMQ_NOTHROW
0596     {
0597         return zmq_msg_size(const_cast<zmq_msg_t *>(&msg));
0598     }
0599 
0600     ZMQ_NODISCARD bool empty() const ZMQ_NOTHROW { return size() == 0u; }
0601 
0602     template<typename T> T *data() ZMQ_NOTHROW { return static_cast<T *>(data()); }
0603 
0604     template<typename T> T const *data() const ZMQ_NOTHROW
0605     {
0606         return static_cast<T const *>(data());
0607     }
0608 
0609     ZMQ_DEPRECATED("from 4.3.0, use operator== instead")
0610     bool equal(const message_t *other) const ZMQ_NOTHROW { return *this == *other; }
0611 
0612     bool operator==(const message_t &other) const ZMQ_NOTHROW
0613     {
0614         const size_t my_size = size();
0615         return my_size == other.size() && 0 == memcmp(data(), other.data(), my_size);
0616     }
0617 
0618     bool operator!=(const message_t &other) const ZMQ_NOTHROW
0619     {
0620         return !(*this == other);
0621     }
0622 
0623 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3, 2, 0)
0624     int get(int property_)
0625     {
0626         int value = zmq_msg_get(&msg, property_);
0627         if (value == -1)
0628             throw error_t();
0629         return value;
0630     }
0631 #endif
0632 
0633 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0)
0634     const char *gets(const char *property_)
0635     {
0636         const char *value = zmq_msg_gets(&msg, property_);
0637         if (value == ZMQ_NULLPTR)
0638             throw error_t();
0639         return value;
0640     }
0641 #endif
0642 
0643 #if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0)
0644     uint32_t routing_id() const
0645     {
0646         return zmq_msg_routing_id(const_cast<zmq_msg_t *>(&msg));
0647     }
0648 
0649     void set_routing_id(uint32_t routing_id)
0650     {
0651         int rc = zmq_msg_set_routing_id(&msg, routing_id);
0652         if (rc != 0)
0653             throw error_t();
0654     }
0655 
0656     const char *group() const
0657     {
0658         return zmq_msg_group(const_cast<zmq_msg_t *>(&msg));
0659     }
0660 
0661     void set_group(const char *group)
0662     {
0663         int rc = zmq_msg_set_group(&msg, group);
0664         if (rc != 0)
0665             throw error_t();
0666     }
0667 #endif
0668 
0669     // interpret message content as a string
0670     std::string to_string() const
0671     {
0672         return std::string(static_cast<const char *>(data()), size());
0673     }
0674 #if CPPZMQ_HAS_STRING_VIEW
0675     // interpret message content as a string
0676     std::string_view to_string_view() const noexcept
0677     {
0678         return std::string_view(static_cast<const char *>(data()), size());
0679     }
0680 #endif
0681 
0682     /** Dump content to string for debugging.
0683     *   Ascii chars are readable, the rest is printed as hex.
0684     *   Probably ridiculously slow.
0685     *   Use to_string() or to_string_view() for
0686     *   interpreting the message as a string.
0687     */
0688     std::string str() const
0689     {
0690         // Partly mutuated from the same method in zmq::multipart_t
0691         std::stringstream os;
0692 
0693         const unsigned char *msg_data = this->data<unsigned char>();
0694         unsigned char byte;
0695         size_t size = this->size();
0696         int is_ascii[2] = {0, 0};
0697 
0698         os << "zmq::message_t [size " << std::dec << std::setw(3)
0699            << std::setfill('0') << size << "] (";
0700         // Totally arbitrary
0701         if (size >= 1000) {
0702             os << "... too big to print)";
0703         } else {
0704             while (size--) {
0705                 byte = *msg_data++;
0706 
0707                 is_ascii[1] = (byte >= 32 && byte < 127);
0708                 if (is_ascii[1] != is_ascii[0])
0709                     os << " "; // Separate text/non text
0710 
0711                 if (is_ascii[1]) {
0712                     os << byte;
0713                 } else {
0714                     os << std::hex << std::uppercase << std::setw(2)
0715                        << std::setfill('0') << static_cast<short>(byte);
0716                 }
0717                 is_ascii[0] = is_ascii[1];
0718             }
0719             os << ")";
0720         }
0721         return os.str();
0722     }
0723 
0724     void swap(message_t &other) ZMQ_NOTHROW
0725     {
0726         // this assumes zmq::msg_t from libzmq is trivially relocatable
0727         std::swap(msg, other.msg);
0728     }
0729 
0730     ZMQ_NODISCARD zmq_msg_t *handle() ZMQ_NOTHROW { return &msg; }
0731     ZMQ_NODISCARD const zmq_msg_t *handle() const ZMQ_NOTHROW { return &msg; }
0732 
0733   private:
0734     //  The underlying message
0735     zmq_msg_t msg;
0736 
0737     //  Disable implicit message copying, so that users won't use shared
0738     //  messages (less efficient) without being aware of the fact.
0739     message_t(const message_t &) ZMQ_DELETED_FUNCTION;
0740     void operator=(const message_t &) ZMQ_DELETED_FUNCTION;
0741 };
0742 
0743 inline void swap(message_t &a, message_t &b) ZMQ_NOTHROW
0744 {
0745     a.swap(b);
0746 }
0747 
0748 #ifdef ZMQ_CPP11
0749 enum class ctxopt
0750 {
0751 #ifdef ZMQ_BLOCKY
0752     blocky = ZMQ_BLOCKY,
0753 #endif
0754 #ifdef ZMQ_IO_THREADS
0755     io_threads = ZMQ_IO_THREADS,
0756 #endif
0757 #ifdef ZMQ_THREAD_SCHED_POLICY
0758     thread_sched_policy = ZMQ_THREAD_SCHED_POLICY,
0759 #endif
0760 #ifdef ZMQ_THREAD_PRIORITY
0761     thread_priority = ZMQ_THREAD_PRIORITY,
0762 #endif
0763 #ifdef ZMQ_THREAD_AFFINITY_CPU_ADD
0764     thread_affinity_cpu_add = ZMQ_THREAD_AFFINITY_CPU_ADD,
0765 #endif
0766 #ifdef ZMQ_THREAD_AFFINITY_CPU_REMOVE
0767     thread_affinity_cpu_remove = ZMQ_THREAD_AFFINITY_CPU_REMOVE,
0768 #endif
0769 #ifdef ZMQ_THREAD_NAME_PREFIX
0770     thread_name_prefix = ZMQ_THREAD_NAME_PREFIX,
0771 #endif
0772 #ifdef ZMQ_MAX_MSGSZ
0773     max_msgsz = ZMQ_MAX_MSGSZ,
0774 #endif
0775 #ifdef ZMQ_ZERO_COPY_RECV
0776     zero_copy_recv = ZMQ_ZERO_COPY_RECV,
0777 #endif
0778 #ifdef ZMQ_MAX_SOCKETS
0779     max_sockets = ZMQ_MAX_SOCKETS,
0780 #endif
0781 #ifdef ZMQ_SOCKET_LIMIT
0782     socket_limit = ZMQ_SOCKET_LIMIT,
0783 #endif
0784 #ifdef ZMQ_IPV6
0785     ipv6 = ZMQ_IPV6,
0786 #endif
0787 #ifdef ZMQ_MSG_T_SIZE
0788     msg_t_size = ZMQ_MSG_T_SIZE
0789 #endif
0790 };
0791 #endif
0792 
0793 class context_t
0794 {
0795   public:
0796     context_t()
0797     {
0798         ptr = zmq_ctx_new();
0799         if (ptr == ZMQ_NULLPTR)
0800             throw error_t();
0801     }
0802 
0803 
0804     explicit context_t(int io_threads_, int max_sockets_ = ZMQ_MAX_SOCKETS_DFLT)
0805     {
0806         ptr = zmq_ctx_new();
0807         if (ptr == ZMQ_NULLPTR)
0808             throw error_t();
0809 
0810         int rc = zmq_ctx_set(ptr, ZMQ_IO_THREADS, io_threads_);
0811         ZMQ_ASSERT(rc == 0);
0812 
0813         rc = zmq_ctx_set(ptr, ZMQ_MAX_SOCKETS, max_sockets_);
0814         ZMQ_ASSERT(rc == 0);
0815     }
0816 
0817 #ifdef ZMQ_HAS_RVALUE_REFS
0818     context_t(context_t &&rhs) ZMQ_NOTHROW : ptr(rhs.ptr) { rhs.ptr = ZMQ_NULLPTR; }
0819     context_t &operator=(context_t &&rhs) ZMQ_NOTHROW
0820     {
0821         close();
0822         std::swap(ptr, rhs.ptr);
0823         return *this;
0824     }
0825 #endif
0826 
0827     ~context_t() ZMQ_NOTHROW { close(); }
0828 
0829     ZMQ_CPP11_DEPRECATED("from 4.7.0, use set taking zmq::ctxopt instead")
0830     int setctxopt(int option_, int optval_)
0831     {
0832         int rc = zmq_ctx_set(ptr, option_, optval_);
0833         ZMQ_ASSERT(rc == 0);
0834         return rc;
0835     }
0836 
0837     ZMQ_CPP11_DEPRECATED("from 4.7.0, use get taking zmq::ctxopt instead")
0838     int getctxopt(int option_) { return zmq_ctx_get(ptr, option_); }
0839 
0840 #ifdef ZMQ_CPP11
0841     void set(ctxopt option, int optval)
0842     {
0843         int rc = zmq_ctx_set(ptr, static_cast<int>(option), optval);
0844         if (rc == -1)
0845             throw error_t();
0846     }
0847 
0848     ZMQ_NODISCARD int get(ctxopt option)
0849     {
0850         int rc = zmq_ctx_get(ptr, static_cast<int>(option));
0851         // some options have a default value of -1
0852         // which is unfortunate, and may result in errors
0853         // that don't make sense
0854         if (rc == -1)
0855             throw error_t();
0856         return rc;
0857     }
0858 #endif
0859 
0860     // Terminates context (see also shutdown()).
0861     void close() ZMQ_NOTHROW
0862     {
0863         if (ptr == ZMQ_NULLPTR)
0864             return;
0865 
0866         int rc;
0867         do {
0868             rc = zmq_ctx_term(ptr);
0869         } while (rc == -1 && errno == EINTR);
0870 
0871         ZMQ_ASSERT(rc == 0);
0872         ptr = ZMQ_NULLPTR;
0873     }
0874 
0875     // Shutdown context in preparation for termination (close()).
0876     // Causes all blocking socket operations and any further
0877     // socket operations to return with ETERM.
0878     void shutdown() ZMQ_NOTHROW
0879     {
0880         if (ptr == ZMQ_NULLPTR)
0881             return;
0882         int rc = zmq_ctx_shutdown(ptr);
0883         ZMQ_ASSERT(rc == 0);
0884     }
0885 
0886     //  Be careful with this, it's probably only useful for
0887     //  using the C api together with an existing C++ api.
0888     //  Normally you should never need to use this.
0889     ZMQ_EXPLICIT operator void *() ZMQ_NOTHROW { return ptr; }
0890 
0891     ZMQ_EXPLICIT operator void const *() const ZMQ_NOTHROW { return ptr; }
0892 
0893     ZMQ_NODISCARD void *handle() ZMQ_NOTHROW { return ptr; }
0894 
0895     ZMQ_DEPRECATED("from 4.7.0, use handle() != nullptr instead")
0896     operator bool() const ZMQ_NOTHROW { return ptr != ZMQ_NULLPTR; }
0897 
0898     void swap(context_t &other) ZMQ_NOTHROW { std::swap(ptr, other.ptr); }
0899 
0900   private:
0901     void *ptr;
0902 
0903     context_t(const context_t &) ZMQ_DELETED_FUNCTION;
0904     void operator=(const context_t &) ZMQ_DELETED_FUNCTION;
0905 };
0906 
0907 inline void swap(context_t &a, context_t &b) ZMQ_NOTHROW
0908 {
0909     a.swap(b);
0910 }
0911 
0912 #ifdef ZMQ_CPP11
0913 
0914 struct recv_buffer_size
0915 {
0916     size_t size;             // number of bytes written to buffer
0917     size_t untruncated_size; // untruncated message size in bytes
0918 
0919     ZMQ_NODISCARD bool truncated() const noexcept
0920     {
0921         return size != untruncated_size;
0922     }
0923 };
0924 
0925 #if CPPZMQ_HAS_OPTIONAL
0926 
0927 using send_result_t = std::optional<size_t>;
0928 using recv_result_t = std::optional<size_t>;
0929 using recv_buffer_result_t = std::optional<recv_buffer_size>;
0930 
0931 #else
0932 
0933 namespace detail
0934 {
0935 // A C++11 type emulating the most basic
0936 // operations of std::optional for trivial types
0937 template<class T> class trivial_optional
0938 {
0939   public:
0940     static_assert(std::is_trivial<T>::value, "T must be trivial");
0941     using value_type = T;
0942 
0943     trivial_optional() = default;
0944     trivial_optional(T value) noexcept : _value(value), _has_value(true) {}
0945 
0946     const T *operator->() const noexcept
0947     {
0948         assert(_has_value);
0949         return &_value;
0950     }
0951     T *operator->() noexcept
0952     {
0953         assert(_has_value);
0954         return &_value;
0955     }
0956 
0957     const T &operator*() const noexcept
0958     {
0959         assert(_has_value);
0960         return _value;
0961     }
0962     T &operator*() noexcept
0963     {
0964         assert(_has_value);
0965         return _value;
0966     }
0967 
0968     T &value()
0969     {
0970         if (!_has_value)
0971             throw std::exception();
0972         return _value;
0973     }
0974     const T &value() const
0975     {
0976         if (!_has_value)
0977             throw std::exception();
0978         return _value;
0979     }
0980 
0981     explicit operator bool() const noexcept { return _has_value; }
0982     bool has_value() const noexcept { return _has_value; }
0983 
0984   private:
0985     T _value{};
0986     bool _has_value{false};
0987 };
0988 } // namespace detail
0989 
0990 using send_result_t = detail::trivial_optional<size_t>;
0991 using recv_result_t = detail::trivial_optional<size_t>;
0992 using recv_buffer_result_t = detail::trivial_optional<recv_buffer_size>;
0993 
0994 #endif
0995 
0996 namespace detail
0997 {
0998 template<class T> constexpr T enum_bit_or(T a, T b) noexcept
0999 {
1000     static_assert(std::is_enum<T>::value, "must be enum");
1001     using U = typename std::underlying_type<T>::type;
1002     return static_cast<T>(static_cast<U>(a) | static_cast<U>(b));
1003 }
1004 template<class T> constexpr T enum_bit_and(T a, T b) noexcept
1005 {
1006     static_assert(std::is_enum<T>::value, "must be enum");
1007     using U = typename std::underlying_type<T>::type;
1008     return static_cast<T>(static_cast<U>(a) & static_cast<U>(b));
1009 }
1010 template<class T> constexpr T enum_bit_xor(T a, T b) noexcept
1011 {
1012     static_assert(std::is_enum<T>::value, "must be enum");
1013     using U = typename std::underlying_type<T>::type;
1014     return static_cast<T>(static_cast<U>(a) ^ static_cast<U>(b));
1015 }
1016 template<class T> constexpr T enum_bit_not(T a) noexcept
1017 {
1018     static_assert(std::is_enum<T>::value, "must be enum");
1019     using U = typename std::underlying_type<T>::type;
1020     return static_cast<T>(~static_cast<U>(a));
1021 }
1022 } // namespace detail
1023 
1024 // partially satisfies named requirement BitmaskType
1025 enum class send_flags : int
1026 {
1027     none = 0,
1028     dontwait = ZMQ_DONTWAIT,
1029     sndmore = ZMQ_SNDMORE
1030 };
1031 
1032 constexpr send_flags operator|(send_flags a, send_flags b) noexcept
1033 {
1034     return detail::enum_bit_or(a, b);
1035 }
1036 constexpr send_flags operator&(send_flags a, send_flags b) noexcept
1037 {
1038     return detail::enum_bit_and(a, b);
1039 }
1040 constexpr send_flags operator^(send_flags a, send_flags b) noexcept
1041 {
1042     return detail::enum_bit_xor(a, b);
1043 }
1044 constexpr send_flags operator~(send_flags a) noexcept
1045 {
1046     return detail::enum_bit_not(a);
1047 }
1048 
1049 // partially satisfies named requirement BitmaskType
1050 enum class recv_flags : int
1051 {
1052     none = 0,
1053     dontwait = ZMQ_DONTWAIT
1054 };
1055 
1056 constexpr recv_flags operator|(recv_flags a, recv_flags b) noexcept
1057 {
1058     return detail::enum_bit_or(a, b);
1059 }
1060 constexpr recv_flags operator&(recv_flags a, recv_flags b) noexcept
1061 {
1062     return detail::enum_bit_and(a, b);
1063 }
1064 constexpr recv_flags operator^(recv_flags a, recv_flags b) noexcept
1065 {
1066     return detail::enum_bit_xor(a, b);
1067 }
1068 constexpr recv_flags operator~(recv_flags a) noexcept
1069 {
1070     return detail::enum_bit_not(a);
1071 }
1072 
1073 
1074 // mutable_buffer, const_buffer and buffer are based on
1075 // the Networking TS specification, draft:
1076 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4771.pdf
1077 
1078 class mutable_buffer
1079 {
1080   public:
1081     constexpr mutable_buffer() noexcept : _data(nullptr), _size(0) {}
1082     constexpr mutable_buffer(void *p, size_t n) noexcept : _data(p), _size(n)
1083     {
1084 #ifdef ZMQ_EXTENDED_CONSTEXPR
1085         assert(p != nullptr || n == 0);
1086 #endif
1087     }
1088 
1089     constexpr void *data() const noexcept { return _data; }
1090     constexpr size_t size() const noexcept { return _size; }
1091     mutable_buffer &operator+=(size_t n) noexcept
1092     {
1093         // (std::min) is a workaround for when a min macro is defined
1094         const auto shift = (std::min)(n, _size);
1095         _data = static_cast<char *>(_data) + shift;
1096         _size -= shift;
1097         return *this;
1098     }
1099 
1100   private:
1101     void *_data;
1102     size_t _size;
1103 };
1104 
1105 inline mutable_buffer operator+(const mutable_buffer &mb, size_t n) noexcept
1106 {
1107     return mutable_buffer(static_cast<char *>(mb.data()) + (std::min)(n, mb.size()),
1108                           mb.size() - (std::min)(n, mb.size()));
1109 }
1110 inline mutable_buffer operator+(size_t n, const mutable_buffer &mb) noexcept
1111 {
1112     return mb + n;
1113 }
1114 
1115 class const_buffer
1116 {
1117   public:
1118     constexpr const_buffer() noexcept : _data(nullptr), _size(0) {}
1119     constexpr const_buffer(const void *p, size_t n) noexcept : _data(p), _size(n)
1120     {
1121 #ifdef ZMQ_EXTENDED_CONSTEXPR
1122         assert(p != nullptr || n == 0);
1123 #endif
1124     }
1125     constexpr const_buffer(const mutable_buffer &mb) noexcept :
1126         _data(mb.data()), _size(mb.size())
1127     {
1128     }
1129 
1130     constexpr const void *data() const noexcept { return _data; }
1131     constexpr size_t size() const noexcept { return _size; }
1132     const_buffer &operator+=(size_t n) noexcept
1133     {
1134         const auto shift = (std::min)(n, _size);
1135         _data = static_cast<const char *>(_data) + shift;
1136         _size -= shift;
1137         return *this;
1138     }
1139 
1140   private:
1141     const void *_data;
1142     size_t _size;
1143 };
1144 
1145 inline const_buffer operator+(const const_buffer &cb, size_t n) noexcept
1146 {
1147     return const_buffer(static_cast<const char *>(cb.data())
1148                           + (std::min)(n, cb.size()),
1149                         cb.size() - (std::min)(n, cb.size()));
1150 }
1151 inline const_buffer operator+(size_t n, const const_buffer &cb) noexcept
1152 {
1153     return cb + n;
1154 }
1155 
1156 // buffer creation
1157 
1158 constexpr mutable_buffer buffer(void *p, size_t n) noexcept
1159 {
1160     return mutable_buffer(p, n);
1161 }
1162 constexpr const_buffer buffer(const void *p, size_t n) noexcept
1163 {
1164     return const_buffer(p, n);
1165 }
1166 constexpr mutable_buffer buffer(const mutable_buffer &mb) noexcept
1167 {
1168     return mb;
1169 }
1170 inline mutable_buffer buffer(const mutable_buffer &mb, size_t n) noexcept
1171 {
1172     return mutable_buffer(mb.data(), (std::min)(mb.size(), n));
1173 }
1174 constexpr const_buffer buffer(const const_buffer &cb) noexcept
1175 {
1176     return cb;
1177 }
1178 inline const_buffer buffer(const const_buffer &cb, size_t n) noexcept
1179 {
1180     return const_buffer(cb.data(), (std::min)(cb.size(), n));
1181 }
1182 
1183 namespace detail
1184 {
1185 template<class T> struct is_buffer
1186 {
1187     static constexpr bool value =
1188       std::is_same<T, const_buffer>::value || std::is_same<T, mutable_buffer>::value;
1189 };
1190 
1191 template<class T> struct is_pod_like
1192 {
1193     // NOTE: The networking draft N4771 section 16.11 requires
1194     // T in the buffer functions below to be
1195     // trivially copyable OR standard layout.
1196     // Here we decide to be conservative and require both.
1197     static constexpr bool value =
1198       ZMQ_IS_TRIVIALLY_COPYABLE(T) && std::is_standard_layout<T>::value;
1199 };
1200 
1201 template<class C> constexpr auto seq_size(const C &c) noexcept -> decltype(c.size())
1202 {
1203     return c.size();
1204 }
1205 template<class T, size_t N>
1206 constexpr size_t seq_size(const T (&/*array*/)[N]) noexcept
1207 {
1208     return N;
1209 }
1210 
1211 template<class Seq>
1212 auto buffer_contiguous_sequence(Seq &&seq) noexcept
1213   -> decltype(buffer(std::addressof(*std::begin(seq)), size_t{}))
1214 {
1215     using T = typename std::remove_cv<
1216       typename std::remove_reference<decltype(*std::begin(seq))>::type>::type;
1217     static_assert(detail::is_pod_like<T>::value, "T must be POD");
1218 
1219     const auto size = seq_size(seq);
1220     return buffer(size != 0u ? std::addressof(*std::begin(seq)) : nullptr,
1221                   size * sizeof(T));
1222 }
1223 template<class Seq>
1224 auto buffer_contiguous_sequence(Seq &&seq, size_t n_bytes) noexcept
1225   -> decltype(buffer_contiguous_sequence(seq))
1226 {
1227     using T = typename std::remove_cv<
1228       typename std::remove_reference<decltype(*std::begin(seq))>::type>::type;
1229     static_assert(detail::is_pod_like<T>::value, "T must be POD");
1230 
1231     const auto size = seq_size(seq);
1232     return buffer(size != 0u ? std::addressof(*std::begin(seq)) : nullptr,
1233                   (std::min)(size * sizeof(T), n_bytes));
1234 }
1235 
1236 } // namespace detail
1237 
1238 // C array
1239 template<class T, size_t N> mutable_buffer buffer(T (&data)[N]) noexcept
1240 {
1241     return detail::buffer_contiguous_sequence(data);
1242 }
1243 template<class T, size_t N>
1244 mutable_buffer buffer(T (&data)[N], size_t n_bytes) noexcept
1245 {
1246     return detail::buffer_contiguous_sequence(data, n_bytes);
1247 }
1248 template<class T, size_t N> const_buffer buffer(const T (&data)[N]) noexcept
1249 {
1250     return detail::buffer_contiguous_sequence(data);
1251 }
1252 template<class T, size_t N>
1253 const_buffer buffer(const T (&data)[N], size_t n_bytes) noexcept
1254 {
1255     return detail::buffer_contiguous_sequence(data, n_bytes);
1256 }
1257 // std::array
1258 template<class T, size_t N> mutable_buffer buffer(std::array<T, N> &data) noexcept
1259 {
1260     return detail::buffer_contiguous_sequence(data);
1261 }
1262 template<class T, size_t N>
1263 mutable_buffer buffer(std::array<T, N> &data, size_t n_bytes) noexcept
1264 {
1265     return detail::buffer_contiguous_sequence(data, n_bytes);
1266 }
1267 template<class T, size_t N>
1268 const_buffer buffer(std::array<const T, N> &data) noexcept
1269 {
1270     return detail::buffer_contiguous_sequence(data);
1271 }
1272 template<class T, size_t N>
1273 const_buffer buffer(std::array<const T, N> &data, size_t n_bytes) noexcept
1274 {
1275     return detail::buffer_contiguous_sequence(data, n_bytes);
1276 }
1277 template<class T, size_t N>
1278 const_buffer buffer(const std::array<T, N> &data) noexcept
1279 {
1280     return detail::buffer_contiguous_sequence(data);
1281 }
1282 template<class T, size_t N>
1283 const_buffer buffer(const std::array<T, N> &data, size_t n_bytes) noexcept
1284 {
1285     return detail::buffer_contiguous_sequence(data, n_bytes);
1286 }
1287 // std::vector
1288 template<class T, class Allocator>
1289 mutable_buffer buffer(std::vector<T, Allocator> &data) noexcept
1290 {
1291     return detail::buffer_contiguous_sequence(data);
1292 }
1293 template<class T, class Allocator>
1294 mutable_buffer buffer(std::vector<T, Allocator> &data, size_t n_bytes) noexcept
1295 {
1296     return detail::buffer_contiguous_sequence(data, n_bytes);
1297 }
1298 template<class T, class Allocator>
1299 const_buffer buffer(const std::vector<T, Allocator> &data) noexcept
1300 {
1301     return detail::buffer_contiguous_sequence(data);
1302 }
1303 template<class T, class Allocator>
1304 const_buffer buffer(const std::vector<T, Allocator> &data, size_t n_bytes) noexcept
1305 {
1306     return detail::buffer_contiguous_sequence(data, n_bytes);
1307 }
1308 // std::basic_string
1309 template<class T, class Traits, class Allocator>
1310 mutable_buffer buffer(std::basic_string<T, Traits, Allocator> &data) noexcept
1311 {
1312     return detail::buffer_contiguous_sequence(data);
1313 }
1314 template<class T, class Traits, class Allocator>
1315 mutable_buffer buffer(std::basic_string<T, Traits, Allocator> &data,
1316                       size_t n_bytes) noexcept
1317 {
1318     return detail::buffer_contiguous_sequence(data, n_bytes);
1319 }
1320 template<class T, class Traits, class Allocator>
1321 const_buffer buffer(const std::basic_string<T, Traits, Allocator> &data) noexcept
1322 {
1323     return detail::buffer_contiguous_sequence(data);
1324 }
1325 template<class T, class Traits, class Allocator>
1326 const_buffer buffer(const std::basic_string<T, Traits, Allocator> &data,
1327                     size_t n_bytes) noexcept
1328 {
1329     return detail::buffer_contiguous_sequence(data, n_bytes);
1330 }
1331 
1332 #if CPPZMQ_HAS_STRING_VIEW
1333 // std::basic_string_view
1334 template<class T, class Traits>
1335 const_buffer buffer(std::basic_string_view<T, Traits> data) noexcept
1336 {
1337     return detail::buffer_contiguous_sequence(data);
1338 }
1339 template<class T, class Traits>
1340 const_buffer buffer(std::basic_string_view<T, Traits> data, size_t n_bytes) noexcept
1341 {
1342     return detail::buffer_contiguous_sequence(data, n_bytes);
1343 }
1344 #endif
1345 
1346 // Buffer for a string literal (null terminated)
1347 // where the buffer size excludes the terminating character.
1348 // Equivalent to zmq::buffer(std::string_view("...")).
1349 template<class Char, size_t N>
1350 constexpr const_buffer str_buffer(const Char (&data)[N]) noexcept
1351 {
1352     static_assert(detail::is_pod_like<Char>::value, "Char must be POD");
1353 #ifdef ZMQ_EXTENDED_CONSTEXPR
1354     assert(data[N - 1] == Char{0});
1355 #endif
1356     return const_buffer(static_cast<const Char *>(data), (N - 1) * sizeof(Char));
1357 }
1358 
1359 namespace literals
1360 {
1361 constexpr const_buffer operator"" _zbuf(const char *str, size_t len) noexcept
1362 {
1363     return const_buffer(str, len * sizeof(char));
1364 }
1365 constexpr const_buffer operator"" _zbuf(const wchar_t *str, size_t len) noexcept
1366 {
1367     return const_buffer(str, len * sizeof(wchar_t));
1368 }
1369 constexpr const_buffer operator"" _zbuf(const char16_t *str, size_t len) noexcept
1370 {
1371     return const_buffer(str, len * sizeof(char16_t));
1372 }
1373 constexpr const_buffer operator"" _zbuf(const char32_t *str, size_t len) noexcept
1374 {
1375     return const_buffer(str, len * sizeof(char32_t));
1376 }
1377 }
1378 
1379 #ifdef ZMQ_CPP11
1380 enum class socket_type : int
1381 {
1382     req = ZMQ_REQ,
1383     rep = ZMQ_REP,
1384     dealer = ZMQ_DEALER,
1385     router = ZMQ_ROUTER,
1386     pub = ZMQ_PUB,
1387     sub = ZMQ_SUB,
1388     xpub = ZMQ_XPUB,
1389     xsub = ZMQ_XSUB,
1390     push = ZMQ_PUSH,
1391     pull = ZMQ_PULL,
1392 #if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0)
1393     server = ZMQ_SERVER,
1394     client = ZMQ_CLIENT,
1395     radio = ZMQ_RADIO,
1396     dish = ZMQ_DISH,
1397     gather = ZMQ_GATHER,
1398     scatter = ZMQ_SCATTER,
1399     dgram = ZMQ_DGRAM,
1400 #endif
1401 #if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 3, 3)
1402     peer = ZMQ_PEER,
1403     channel = ZMQ_CHANNEL,
1404 #endif
1405 #if ZMQ_VERSION_MAJOR >= 4
1406     stream = ZMQ_STREAM,
1407 #endif
1408     pair = ZMQ_PAIR
1409 };
1410 #endif
1411 
1412 namespace sockopt
1413 {
1414 // There are two types of options,
1415 // integral type with known compiler time size (int, bool, int64_t, uint64_t)
1416 // and arrays with dynamic size (strings, binary data).
1417 
1418 // BoolUnit: if true accepts values of type bool (but passed as T into libzmq)
1419 template<int Opt, class T, bool BoolUnit = false> struct integral_option
1420 {
1421 };
1422 
1423 // NullTerm:
1424 // 0: binary data
1425 // 1: null-terminated string (`getsockopt` size includes null)
1426 // 2: binary (size 32) or Z85 encoder string of size 41 (null included)
1427 template<int Opt, int NullTerm = 1> struct array_option
1428 {
1429 };
1430 
1431 #define ZMQ_DEFINE_INTEGRAL_OPT(OPT, NAME, TYPE)                                    \
1432     using NAME##_t = integral_option<OPT, TYPE, false>;                             \
1433     ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1434 #define ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(OPT, NAME, TYPE)                          \
1435     using NAME##_t = integral_option<OPT, TYPE, true>;                              \
1436     ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1437 #define ZMQ_DEFINE_ARRAY_OPT(OPT, NAME)                                             \
1438     using NAME##_t = array_option<OPT>;                                             \
1439     ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1440 #define ZMQ_DEFINE_ARRAY_OPT_BINARY(OPT, NAME)                                      \
1441     using NAME##_t = array_option<OPT, 0>;                                          \
1442     ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1443 #define ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(OPT, NAME)                                  \
1444     using NAME##_t = array_option<OPT, 2>;                                          \
1445     ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1446 
1447 // deprecated, use zmq::fd_t
1448 using cppzmq_fd_t = ::zmq::fd_t;
1449 
1450 #ifdef ZMQ_AFFINITY
1451 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_AFFINITY, affinity, uint64_t);
1452 #endif
1453 #ifdef ZMQ_BACKLOG
1454 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_BACKLOG, backlog, int);
1455 #endif
1456 #ifdef ZMQ_BINDTODEVICE
1457 ZMQ_DEFINE_ARRAY_OPT_BINARY(ZMQ_BINDTODEVICE, bindtodevice);
1458 #endif
1459 #ifdef ZMQ_CONFLATE
1460 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_CONFLATE, conflate, int);
1461 #endif
1462 #ifdef ZMQ_CONNECT_ROUTING_ID
1463 ZMQ_DEFINE_ARRAY_OPT(ZMQ_CONNECT_ROUTING_ID, connect_routing_id);
1464 #endif
1465 #ifdef ZMQ_CONNECT_TIMEOUT
1466 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_CONNECT_TIMEOUT, connect_timeout, int);
1467 #endif
1468 #ifdef ZMQ_CURVE_PUBLICKEY
1469 ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_PUBLICKEY, curve_publickey);
1470 #endif
1471 #ifdef ZMQ_CURVE_SECRETKEY
1472 ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_SECRETKEY, curve_secretkey);
1473 #endif
1474 #ifdef ZMQ_CURVE_SERVER
1475 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_CURVE_SERVER, curve_server, int);
1476 #endif
1477 #ifdef ZMQ_CURVE_SERVERKEY
1478 ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_SERVERKEY, curve_serverkey);
1479 #endif
1480 #ifdef ZMQ_EVENTS
1481 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_EVENTS, events, int);
1482 #endif
1483 #ifdef ZMQ_FD
1484 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_FD, fd, ::zmq::fd_t);
1485 #endif
1486 #ifdef ZMQ_GSSAPI_PLAINTEXT
1487 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_GSSAPI_PLAINTEXT, gssapi_plaintext, int);
1488 #endif
1489 #ifdef ZMQ_GSSAPI_SERVER
1490 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_GSSAPI_SERVER, gssapi_server, int);
1491 #endif
1492 #ifdef ZMQ_GSSAPI_SERVICE_PRINCIPAL
1493 ZMQ_DEFINE_ARRAY_OPT(ZMQ_GSSAPI_SERVICE_PRINCIPAL, gssapi_service_principal);
1494 #endif
1495 #ifdef ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE
1496 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE,
1497                         gssapi_service_principal_nametype,
1498                         int);
1499 #endif
1500 #ifdef ZMQ_GSSAPI_PRINCIPAL
1501 ZMQ_DEFINE_ARRAY_OPT(ZMQ_GSSAPI_PRINCIPAL, gssapi_principal);
1502 #endif
1503 #ifdef ZMQ_GSSAPI_PRINCIPAL_NAMETYPE
1504 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_GSSAPI_PRINCIPAL_NAMETYPE,
1505                         gssapi_principal_nametype,
1506                         int);
1507 #endif
1508 #ifdef ZMQ_HANDSHAKE_IVL
1509 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HANDSHAKE_IVL, handshake_ivl, int);
1510 #endif
1511 #ifdef ZMQ_HEARTBEAT_IVL
1512 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_IVL, heartbeat_ivl, int);
1513 #endif
1514 #ifdef ZMQ_HEARTBEAT_TIMEOUT
1515 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_TIMEOUT, heartbeat_timeout, int);
1516 #endif
1517 #ifdef ZMQ_HEARTBEAT_TTL
1518 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_TTL, heartbeat_ttl, int);
1519 #endif
1520 #ifdef ZMQ_IMMEDIATE
1521 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_IMMEDIATE, immediate, int);
1522 #endif
1523 #ifdef ZMQ_INVERT_MATCHING
1524 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_INVERT_MATCHING, invert_matching, int);
1525 #endif
1526 #ifdef ZMQ_IPV6
1527 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_IPV6, ipv6, int);
1528 #endif
1529 #ifdef ZMQ_LAST_ENDPOINT
1530 ZMQ_DEFINE_ARRAY_OPT(ZMQ_LAST_ENDPOINT, last_endpoint);
1531 #endif
1532 #ifdef ZMQ_LINGER
1533 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_LINGER, linger, int);
1534 #endif
1535 #ifdef ZMQ_MAXMSGSIZE
1536 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MAXMSGSIZE, maxmsgsize, int64_t);
1537 #endif
1538 #ifdef ZMQ_MECHANISM
1539 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MECHANISM, mechanism, int);
1540 #endif
1541 #ifdef ZMQ_METADATA
1542 ZMQ_DEFINE_ARRAY_OPT(ZMQ_METADATA, metadata);
1543 #endif
1544 #ifdef ZMQ_MULTICAST_HOPS
1545 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MULTICAST_HOPS, multicast_hops, int);
1546 #endif
1547 #ifdef ZMQ_MULTICAST_LOOP
1548 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_MULTICAST_LOOP, multicast_loop, int);
1549 #endif
1550 #ifdef ZMQ_MULTICAST_MAXTPDU
1551 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MULTICAST_MAXTPDU, multicast_maxtpdu, int);
1552 #endif
1553 #ifdef ZMQ_ONLY_FIRST_SUBSCRIBE
1554 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ONLY_FIRST_SUBSCRIBE, only_first_subscribe, int);
1555 #endif
1556 #ifdef ZMQ_PLAIN_SERVER
1557 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_PLAIN_SERVER, plain_server, int);
1558 #endif
1559 #ifdef ZMQ_PLAIN_PASSWORD
1560 ZMQ_DEFINE_ARRAY_OPT(ZMQ_PLAIN_PASSWORD, plain_password);
1561 #endif
1562 #ifdef ZMQ_PLAIN_USERNAME
1563 ZMQ_DEFINE_ARRAY_OPT(ZMQ_PLAIN_USERNAME, plain_username);
1564 #endif
1565 #ifdef ZMQ_USE_FD
1566 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_USE_FD, use_fd, int);
1567 #endif
1568 #ifdef ZMQ_PROBE_ROUTER
1569 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_PROBE_ROUTER, probe_router, int);
1570 #endif
1571 #ifdef ZMQ_RATE
1572 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RATE, rate, int);
1573 #endif
1574 #ifdef ZMQ_RCVBUF
1575 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVBUF, rcvbuf, int);
1576 #endif
1577 #ifdef ZMQ_RCVHWM
1578 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVHWM, rcvhwm, int);
1579 #endif
1580 #ifdef ZMQ_RCVMORE
1581 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_RCVMORE, rcvmore, int);
1582 #endif
1583 #ifdef ZMQ_RCVTIMEO
1584 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVTIMEO, rcvtimeo, int);
1585 #endif
1586 #ifdef ZMQ_RECONNECT_IVL
1587 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECONNECT_IVL, reconnect_ivl, int);
1588 #endif
1589 #ifdef ZMQ_RECONNECT_IVL_MAX
1590 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECONNECT_IVL_MAX, reconnect_ivl_max, int);
1591 #endif
1592 #ifdef ZMQ_RECOVERY_IVL
1593 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECOVERY_IVL, recovery_ivl, int);
1594 #endif
1595 #ifdef ZMQ_REQ_CORRELATE
1596 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_REQ_CORRELATE, req_correlate, int);
1597 #endif
1598 #ifdef ZMQ_REQ_RELAXED
1599 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_REQ_RELAXED, req_relaxed, int);
1600 #endif
1601 #ifdef ZMQ_ROUTER_HANDOVER
1602 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ROUTER_HANDOVER, router_handover, int);
1603 #endif
1604 #ifdef ZMQ_ROUTER_MANDATORY
1605 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ROUTER_MANDATORY, router_mandatory, int);
1606 #endif
1607 #ifdef ZMQ_ROUTER_NOTIFY
1608 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_ROUTER_NOTIFY, router_notify, int);
1609 #endif
1610 #ifdef ZMQ_ROUTING_ID
1611 ZMQ_DEFINE_ARRAY_OPT_BINARY(ZMQ_ROUTING_ID, routing_id);
1612 #endif
1613 #ifdef ZMQ_SNDBUF
1614 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDBUF, sndbuf, int);
1615 #endif
1616 #ifdef ZMQ_SNDHWM
1617 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDHWM, sndhwm, int);
1618 #endif
1619 #ifdef ZMQ_SNDTIMEO
1620 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDTIMEO, sndtimeo, int);
1621 #endif
1622 #ifdef ZMQ_SOCKS_PROXY
1623 ZMQ_DEFINE_ARRAY_OPT(ZMQ_SOCKS_PROXY, socks_proxy);
1624 #endif
1625 #ifdef ZMQ_STREAM_NOTIFY
1626 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_STREAM_NOTIFY, stream_notify, int);
1627 #endif
1628 #ifdef ZMQ_SUBSCRIBE
1629 ZMQ_DEFINE_ARRAY_OPT(ZMQ_SUBSCRIBE, subscribe);
1630 #endif
1631 #ifdef ZMQ_TCP_KEEPALIVE
1632 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE, tcp_keepalive, int);
1633 #endif
1634 #ifdef ZMQ_TCP_KEEPALIVE_CNT
1635 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_CNT, tcp_keepalive_cnt, int);
1636 #endif
1637 #ifdef ZMQ_TCP_KEEPALIVE_IDLE
1638 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_IDLE, tcp_keepalive_idle, int);
1639 #endif
1640 #ifdef ZMQ_TCP_KEEPALIVE_INTVL
1641 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_INTVL, tcp_keepalive_intvl, int);
1642 #endif
1643 #ifdef ZMQ_TCP_MAXRT
1644 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_MAXRT, tcp_maxrt, int);
1645 #endif
1646 #ifdef ZMQ_THREAD_SAFE
1647 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_THREAD_SAFE, thread_safe, int);
1648 #endif
1649 #ifdef ZMQ_TOS
1650 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TOS, tos, int);
1651 #endif
1652 #ifdef ZMQ_TYPE
1653 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TYPE, type, int);
1654 #ifdef ZMQ_CPP11
1655 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TYPE, socket_type, socket_type);
1656 #endif // ZMQ_CPP11
1657 #endif // ZMQ_TYPE
1658 #ifdef ZMQ_UNSUBSCRIBE
1659 ZMQ_DEFINE_ARRAY_OPT(ZMQ_UNSUBSCRIBE, unsubscribe);
1660 #endif
1661 #ifdef ZMQ_VMCI_BUFFER_SIZE
1662 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_SIZE, vmci_buffer_size, uint64_t);
1663 #endif
1664 #ifdef ZMQ_VMCI_BUFFER_MIN_SIZE
1665 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_MIN_SIZE, vmci_buffer_min_size, uint64_t);
1666 #endif
1667 #ifdef ZMQ_VMCI_BUFFER_MAX_SIZE
1668 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_MAX_SIZE, vmci_buffer_max_size, uint64_t);
1669 #endif
1670 #ifdef ZMQ_VMCI_CONNECT_TIMEOUT
1671 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_CONNECT_TIMEOUT, vmci_connect_timeout, int);
1672 #endif
1673 #ifdef ZMQ_XPUB_VERBOSE
1674 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_VERBOSE, xpub_verbose, int);
1675 #endif
1676 #ifdef ZMQ_XPUB_VERBOSER
1677 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_VERBOSER, xpub_verboser, int);
1678 #endif
1679 #ifdef ZMQ_XPUB_MANUAL
1680 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_MANUAL, xpub_manual, int);
1681 #endif
1682 #ifdef ZMQ_XPUB_NODROP
1683 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_NODROP, xpub_nodrop, int);
1684 #endif
1685 #ifdef ZMQ_XPUB_WELCOME_MSG
1686 ZMQ_DEFINE_ARRAY_OPT(ZMQ_XPUB_WELCOME_MSG, xpub_welcome_msg);
1687 #endif
1688 #ifdef ZMQ_ZAP_ENFORCE_DOMAIN
1689 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ZAP_ENFORCE_DOMAIN, zap_enforce_domain, int);
1690 #endif
1691 #ifdef ZMQ_ZAP_DOMAIN
1692 ZMQ_DEFINE_ARRAY_OPT(ZMQ_ZAP_DOMAIN, zap_domain);
1693 #endif
1694 
1695 } // namespace sockopt
1696 #endif // ZMQ_CPP11
1697 
1698 
1699 namespace detail
1700 {
1701 class socket_base
1702 {
1703   public:
1704     socket_base() ZMQ_NOTHROW : _handle(ZMQ_NULLPTR) {}
1705     ZMQ_EXPLICIT socket_base(void *handle) ZMQ_NOTHROW : _handle(handle) {}
1706 
1707     template<typename T>
1708     ZMQ_CPP11_DEPRECATED("from 4.7.0, use `set` taking option from zmq::sockopt")
1709     void setsockopt(int option_, T const &optval)
1710     {
1711         setsockopt(option_, &optval, sizeof(T));
1712     }
1713 
1714     ZMQ_CPP11_DEPRECATED("from 4.7.0, use `set` taking option from zmq::sockopt")
1715     void setsockopt(int option_, const void *optval_, size_t optvallen_)
1716     {
1717         int rc = zmq_setsockopt(_handle, option_, optval_, optvallen_);
1718         if (rc != 0)
1719             throw error_t();
1720     }
1721 
1722     ZMQ_CPP11_DEPRECATED("from 4.7.0, use `get` taking option from zmq::sockopt")
1723     void getsockopt(int option_, void *optval_, size_t *optvallen_) const
1724     {
1725         int rc = zmq_getsockopt(_handle, option_, optval_, optvallen_);
1726         if (rc != 0)
1727             throw error_t();
1728     }
1729 
1730     template<typename T>
1731     ZMQ_CPP11_DEPRECATED("from 4.7.0, use `get` taking option from zmq::sockopt")
1732     T getsockopt(int option_) const
1733     {
1734         T optval;
1735         size_t optlen = sizeof(T);
1736         getsockopt(option_, &optval, &optlen);
1737         return optval;
1738     }
1739 
1740 #ifdef ZMQ_CPP11
1741     // Set integral socket option, e.g.
1742     // `socket.set(zmq::sockopt::linger, 0)`
1743     template<int Opt, class T, bool BoolUnit>
1744     void set(sockopt::integral_option<Opt, T, BoolUnit>, const T &val)
1745     {
1746         static_assert(std::is_integral<T>::value, "T must be integral");
1747         set_option(Opt, &val, sizeof val);
1748     }
1749 
1750     // Set integral socket option from boolean, e.g.
1751     // `socket.set(zmq::sockopt::immediate, false)`
1752     template<int Opt, class T>
1753     void set(sockopt::integral_option<Opt, T, true>, bool val)
1754     {
1755         static_assert(std::is_integral<T>::value, "T must be integral");
1756         T rep_val = val;
1757         set_option(Opt, &rep_val, sizeof rep_val);
1758     }
1759 
1760     // Set array socket option, e.g.
1761     // `socket.set(zmq::sockopt::plain_username, "foo123")`
1762     template<int Opt, int NullTerm>
1763     void set(sockopt::array_option<Opt, NullTerm>, const char *buf)
1764     {
1765         set_option(Opt, buf, std::strlen(buf));
1766     }
1767 
1768     // Set array socket option, e.g.
1769     // `socket.set(zmq::sockopt::routing_id, zmq::buffer(id))`
1770     template<int Opt, int NullTerm>
1771     void set(sockopt::array_option<Opt, NullTerm>, const_buffer buf)
1772     {
1773         set_option(Opt, buf.data(), buf.size());
1774     }
1775 
1776     // Set array socket option, e.g.
1777     // `socket.set(zmq::sockopt::routing_id, id_str)`
1778     template<int Opt, int NullTerm>
1779     void set(sockopt::array_option<Opt, NullTerm>, const std::string &buf)
1780     {
1781         set_option(Opt, buf.data(), buf.size());
1782     }
1783 
1784 #if CPPZMQ_HAS_STRING_VIEW
1785     // Set array socket option, e.g.
1786     // `socket.set(zmq::sockopt::routing_id, id_str)`
1787     template<int Opt, int NullTerm>
1788     void set(sockopt::array_option<Opt, NullTerm>, std::string_view buf)
1789     {
1790         set_option(Opt, buf.data(), buf.size());
1791     }
1792 #endif
1793 
1794     // Get scalar socket option, e.g.
1795     // `auto opt = socket.get(zmq::sockopt::linger)`
1796     template<int Opt, class T, bool BoolUnit>
1797     ZMQ_NODISCARD T get(sockopt::integral_option<Opt, T, BoolUnit>) const
1798     {
1799         static_assert(std::is_scalar<T>::value, "T must be scalar");
1800         T val;
1801         size_t size = sizeof val;
1802         get_option(Opt, &val, &size);
1803         assert(size == sizeof val);
1804         return val;
1805     }
1806 
1807     // Get array socket option, writes to buf, returns option size in bytes, e.g.
1808     // `size_t optsize = socket.get(zmq::sockopt::routing_id, zmq::buffer(id))`
1809     template<int Opt, int NullTerm>
1810     ZMQ_NODISCARD size_t get(sockopt::array_option<Opt, NullTerm>,
1811                              mutable_buffer buf) const
1812     {
1813         size_t size = buf.size();
1814         get_option(Opt, buf.data(), &size);
1815         return size;
1816     }
1817 
1818     // Get array socket option as string (initializes the string buffer size to init_size) e.g.
1819     // `auto s = socket.get(zmq::sockopt::routing_id)`
1820     // Note: removes the null character from null-terminated string options,
1821     // i.e. the string size excludes the null character.
1822     template<int Opt, int NullTerm>
1823     ZMQ_NODISCARD std::string get(sockopt::array_option<Opt, NullTerm>,
1824                                   size_t init_size = 1024) const
1825     {
1826         if ZMQ_CONSTEXPR_IF (NullTerm == 2) {
1827             if (init_size == 1024) {
1828                 init_size = 41; // get as Z85 string
1829             }
1830         }
1831         std::string str(init_size, '\0');
1832         size_t size = get(sockopt::array_option<Opt>{}, buffer(str));
1833         if ZMQ_CONSTEXPR_IF (NullTerm == 1) {
1834             if (size > 0) {
1835                 assert(str[size - 1] == '\0');
1836                 --size;
1837             }
1838         } else if ZMQ_CONSTEXPR_IF (NullTerm == 2) {
1839             assert(size == 32 || size == 41);
1840             if (size == 41) {
1841                 assert(str[size - 1] == '\0');
1842                 --size;
1843             }
1844         }
1845         str.resize(size);
1846         return str;
1847     }
1848 #endif
1849 
1850     void bind(std::string const &addr) { bind(addr.c_str()); }
1851 
1852     void bind(const char *addr_)
1853     {
1854         int rc = zmq_bind(_handle, addr_);
1855         if (rc != 0)
1856             throw error_t();
1857     }
1858 
1859     void unbind(std::string const &addr) { unbind(addr.c_str()); }
1860 
1861     void unbind(const char *addr_)
1862     {
1863         int rc = zmq_unbind(_handle, addr_);
1864         if (rc != 0)
1865             throw error_t();
1866     }
1867 
1868     void connect(std::string const &addr) { connect(addr.c_str()); }
1869 
1870     void connect(const char *addr_)
1871     {
1872         int rc = zmq_connect(_handle, addr_);
1873         if (rc != 0)
1874             throw error_t();
1875     }
1876 
1877     void disconnect(std::string const &addr) { disconnect(addr.c_str()); }
1878 
1879     void disconnect(const char *addr_)
1880     {
1881         int rc = zmq_disconnect(_handle, addr_);
1882         if (rc != 0)
1883             throw error_t();
1884     }
1885 
1886     ZMQ_DEPRECATED("from 4.7.1, use handle() != nullptr or operator bool")
1887     bool connected() const ZMQ_NOTHROW { return (_handle != ZMQ_NULLPTR); }
1888 
1889     ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking a const_buffer and send_flags")
1890     size_t send(const void *buf_, size_t len_, int flags_ = 0)
1891     {
1892         int nbytes = zmq_send(_handle, buf_, len_, flags_);
1893         if (nbytes >= 0)
1894             return static_cast<size_t>(nbytes);
1895         if (zmq_errno() == EAGAIN)
1896             return 0;
1897         throw error_t();
1898     }
1899 
1900     ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking message_t and send_flags")
1901     bool send(message_t &msg_,
1902               int flags_ = 0) // default until removed
1903     {
1904         int nbytes = zmq_msg_send(msg_.handle(), _handle, flags_);
1905         if (nbytes >= 0)
1906             return true;
1907         if (zmq_errno() == EAGAIN)
1908             return false;
1909         throw error_t();
1910     }
1911 
1912     template<typename T>
1913     ZMQ_CPP11_DEPRECATED(
1914       "from 4.4.1, use send taking message_t or buffer (for contiguous "
1915       "ranges), and send_flags")
1916     bool send(T first, T last, int flags_ = 0)
1917     {
1918         zmq::message_t msg(first, last);
1919         int nbytes = zmq_msg_send(msg.handle(), _handle, flags_);
1920         if (nbytes >= 0)
1921             return true;
1922         if (zmq_errno() == EAGAIN)
1923             return false;
1924         throw error_t();
1925     }
1926 
1927 #ifdef ZMQ_HAS_RVALUE_REFS
1928     ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking message_t and send_flags")
1929     bool send(message_t &&msg_,
1930               int flags_ = 0) // default until removed
1931     {
1932 #ifdef ZMQ_CPP11
1933         return send(msg_, static_cast<send_flags>(flags_)).has_value();
1934 #else
1935         return send(msg_, flags_);
1936 #endif
1937     }
1938 #endif
1939 
1940 #ifdef ZMQ_CPP11
1941     send_result_t send(const_buffer buf, send_flags flags = send_flags::none)
1942     {
1943         const int nbytes =
1944           zmq_send(_handle, buf.data(), buf.size(), static_cast<int>(flags));
1945         if (nbytes >= 0)
1946             return static_cast<size_t>(nbytes);
1947         if (zmq_errno() == EAGAIN)
1948             return {};
1949         throw error_t();
1950     }
1951 
1952     send_result_t send(message_t &msg, send_flags flags)
1953     {
1954         int nbytes = zmq_msg_send(msg.handle(), _handle, static_cast<int>(flags));
1955         if (nbytes >= 0)
1956             return static_cast<size_t>(nbytes);
1957         if (zmq_errno() == EAGAIN)
1958             return {};
1959         throw error_t();
1960     }
1961 
1962     send_result_t send(message_t &&msg, send_flags flags)
1963     {
1964         return send(msg, flags);
1965     }
1966 #endif
1967 
1968     ZMQ_CPP11_DEPRECATED(
1969       "from 4.3.1, use recv taking a mutable_buffer and recv_flags")
1970     size_t recv(void *buf_, size_t len_, int flags_ = 0)
1971     {
1972         int nbytes = zmq_recv(_handle, buf_, len_, flags_);
1973         if (nbytes >= 0)
1974             return static_cast<size_t>(nbytes);
1975         if (zmq_errno() == EAGAIN)
1976             return 0;
1977         throw error_t();
1978     }
1979 
1980     ZMQ_CPP11_DEPRECATED(
1981       "from 4.3.1, use recv taking a reference to message_t and recv_flags")
1982     bool recv(message_t *msg_, int flags_ = 0)
1983     {
1984         int nbytes = zmq_msg_recv(msg_->handle(), _handle, flags_);
1985         if (nbytes >= 0)
1986             return true;
1987         if (zmq_errno() == EAGAIN)
1988             return false;
1989         throw error_t();
1990     }
1991 
1992 #ifdef ZMQ_CPP11
1993     ZMQ_NODISCARD
1994     recv_buffer_result_t recv(mutable_buffer buf,
1995                               recv_flags flags = recv_flags::none)
1996     {
1997         const int nbytes =
1998           zmq_recv(_handle, buf.data(), buf.size(), static_cast<int>(flags));
1999         if (nbytes >= 0) {
2000             return recv_buffer_size{
2001               (std::min)(static_cast<size_t>(nbytes), buf.size()),
2002               static_cast<size_t>(nbytes)};
2003         }
2004         if (zmq_errno() == EAGAIN)
2005             return {};
2006         throw error_t();
2007     }
2008 
2009     ZMQ_NODISCARD
2010     recv_result_t recv(message_t &msg, recv_flags flags = recv_flags::none)
2011     {
2012         const int nbytes =
2013           zmq_msg_recv(msg.handle(), _handle, static_cast<int>(flags));
2014         if (nbytes >= 0) {
2015             assert(msg.size() == static_cast<size_t>(nbytes));
2016             return static_cast<size_t>(nbytes);
2017         }
2018         if (zmq_errno() == EAGAIN)
2019             return {};
2020         throw error_t();
2021     }
2022 #endif
2023 
2024 #if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0)
2025     void join(const char *group)
2026     {
2027         int rc = zmq_join(_handle, group);
2028         if (rc != 0)
2029             throw error_t();
2030     }
2031 
2032     void leave(const char *group)
2033     {
2034         int rc = zmq_leave(_handle, group);
2035         if (rc != 0)
2036             throw error_t();
2037     }
2038 #endif
2039 
2040     ZMQ_NODISCARD void *handle() ZMQ_NOTHROW { return _handle; }
2041     ZMQ_NODISCARD const void *handle() const ZMQ_NOTHROW { return _handle; }
2042 
2043     ZMQ_EXPLICIT operator bool() const ZMQ_NOTHROW { return _handle != ZMQ_NULLPTR; }
2044     // note: non-const operator bool can be removed once
2045     // operator void* is removed from socket_t
2046     ZMQ_EXPLICIT operator bool() ZMQ_NOTHROW { return _handle != ZMQ_NULLPTR; }
2047 
2048   protected:
2049     void *_handle;
2050 
2051   private:
2052     void set_option(int option_, const void *optval_, size_t optvallen_)
2053     {
2054         int rc = zmq_setsockopt(_handle, option_, optval_, optvallen_);
2055         if (rc != 0)
2056             throw error_t();
2057     }
2058 
2059     void get_option(int option_, void *optval_, size_t *optvallen_) const
2060     {
2061         int rc = zmq_getsockopt(_handle, option_, optval_, optvallen_);
2062         if (rc != 0)
2063             throw error_t();
2064     }
2065 };
2066 } // namespace detail
2067 
2068 struct from_handle_t
2069 {
2070     struct _private
2071     {
2072     }; // disabling use other than with from_handle
2073     ZMQ_CONSTEXPR_FN ZMQ_EXPLICIT from_handle_t(_private /*p*/) ZMQ_NOTHROW {}
2074 };
2075 
2076 ZMQ_CONSTEXPR_VAR from_handle_t from_handle =
2077   from_handle_t(from_handle_t::_private());
2078 
2079 // A non-owning nullable reference to a socket.
2080 // The reference is invalidated on socket close or destruction.
2081 class socket_ref : public detail::socket_base
2082 {
2083   public:
2084     socket_ref() ZMQ_NOTHROW : detail::socket_base() {}
2085 #ifdef ZMQ_CPP11
2086     socket_ref(std::nullptr_t) ZMQ_NOTHROW : detail::socket_base() {}
2087 #endif
2088     socket_ref(from_handle_t /*fh*/, void *handle) ZMQ_NOTHROW
2089         : detail::socket_base(handle)
2090     {
2091     }
2092 };
2093 
2094 #ifdef ZMQ_CPP11
2095 inline bool operator==(socket_ref sr, std::nullptr_t /*p*/) ZMQ_NOTHROW
2096 {
2097     return sr.handle() == nullptr;
2098 }
2099 inline bool operator==(std::nullptr_t /*p*/, socket_ref sr) ZMQ_NOTHROW
2100 {
2101     return sr.handle() == nullptr;
2102 }
2103 inline bool operator!=(socket_ref sr, std::nullptr_t /*p*/) ZMQ_NOTHROW
2104 {
2105     return !(sr == nullptr);
2106 }
2107 inline bool operator!=(std::nullptr_t /*p*/, socket_ref sr) ZMQ_NOTHROW
2108 {
2109     return !(sr == nullptr);
2110 }
2111 #endif
2112 
2113 inline bool operator==(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2114 {
2115     return std::equal_to<const void *>()(a.handle(), b.handle());
2116 }
2117 inline bool operator!=(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2118 {
2119     return !(a == b);
2120 }
2121 inline bool operator<(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2122 {
2123     return std::less<const void *>()(a.handle(), b.handle());
2124 }
2125 inline bool operator>(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2126 {
2127     return b < a;
2128 }
2129 inline bool operator<=(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2130 {
2131     return !(a > b);
2132 }
2133 inline bool operator>=(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2134 {
2135     return !(a < b);
2136 }
2137 
2138 } // namespace zmq
2139 
2140 #ifdef ZMQ_CPP11
2141 namespace std
2142 {
2143 template<> struct hash<zmq::socket_ref>
2144 {
2145     size_t operator()(zmq::socket_ref sr) const ZMQ_NOTHROW
2146     {
2147         return hash<void *>()(sr.handle());
2148     }
2149 };
2150 } // namespace std
2151 #endif
2152 
2153 namespace zmq
2154 {
2155 class socket_t : public detail::socket_base
2156 {
2157     friend class monitor_t;
2158 
2159   public:
2160     socket_t() ZMQ_NOTHROW : detail::socket_base(ZMQ_NULLPTR), ctxptr(ZMQ_NULLPTR) {}
2161 
2162     socket_t(context_t &context_, int type_) :
2163         detail::socket_base(zmq_socket(context_.handle(), type_)),
2164         ctxptr(context_.handle())
2165     {
2166         if (_handle == ZMQ_NULLPTR)
2167             throw error_t();
2168     }
2169 
2170 #ifdef ZMQ_CPP11
2171     socket_t(context_t &context_, socket_type type_) :
2172         socket_t(context_, static_cast<int>(type_))
2173     {
2174     }
2175 #endif
2176 
2177 #ifdef ZMQ_HAS_RVALUE_REFS
2178     socket_t(socket_t &&rhs) ZMQ_NOTHROW : detail::socket_base(rhs._handle),
2179                                            ctxptr(rhs.ctxptr)
2180     {
2181         rhs._handle = ZMQ_NULLPTR;
2182         rhs.ctxptr = ZMQ_NULLPTR;
2183     }
2184     socket_t &operator=(socket_t &&rhs) ZMQ_NOTHROW
2185     {
2186         close();
2187         std::swap(_handle, rhs._handle);
2188         std::swap(ctxptr, rhs.ctxptr);
2189         return *this;
2190     }
2191 #endif
2192 
2193     ~socket_t() ZMQ_NOTHROW { close(); }
2194 
2195     operator void *() ZMQ_NOTHROW { return _handle; }
2196 
2197     operator void const *() const ZMQ_NOTHROW { return _handle; }
2198 
2199     void close() ZMQ_NOTHROW
2200     {
2201         if (_handle == ZMQ_NULLPTR)
2202             // already closed
2203             return;
2204         int rc = zmq_close(_handle);
2205         ZMQ_ASSERT(rc == 0);
2206         _handle = ZMQ_NULLPTR;
2207         ctxptr = ZMQ_NULLPTR;
2208     }
2209 
2210     void swap(socket_t &other) ZMQ_NOTHROW
2211     {
2212         std::swap(_handle, other._handle);
2213         std::swap(ctxptr, other.ctxptr);
2214     }
2215 
2216     operator socket_ref() ZMQ_NOTHROW { return socket_ref(from_handle, _handle); }
2217 
2218   private:
2219     void *ctxptr;
2220 
2221     socket_t(const socket_t &) ZMQ_DELETED_FUNCTION;
2222     void operator=(const socket_t &) ZMQ_DELETED_FUNCTION;
2223 
2224     // used by monitor_t
2225     socket_t(void *context_, int type_) :
2226         detail::socket_base(zmq_socket(context_, type_)), ctxptr(context_)
2227     {
2228         if (_handle == ZMQ_NULLPTR)
2229             throw error_t();
2230         if (ctxptr == ZMQ_NULLPTR)
2231             throw error_t();
2232     }
2233 };
2234 
2235 inline void swap(socket_t &a, socket_t &b) ZMQ_NOTHROW
2236 {
2237     a.swap(b);
2238 }
2239 
2240 ZMQ_DEPRECATED("from 4.3.1, use proxy taking socket_t objects")
2241 inline void proxy(void *frontend, void *backend, void *capture)
2242 {
2243     int rc = zmq_proxy(frontend, backend, capture);
2244     if (rc != 0)
2245         throw error_t();
2246 }
2247 
2248 inline void
2249 proxy(socket_ref frontend, socket_ref backend, socket_ref capture = socket_ref())
2250 {
2251     int rc = zmq_proxy(frontend.handle(), backend.handle(), capture.handle());
2252     if (rc != 0)
2253         throw error_t();
2254 }
2255 
2256 #ifdef ZMQ_HAS_PROXY_STEERABLE
2257 ZMQ_DEPRECATED("from 4.3.1, use proxy_steerable taking socket_t objects")
2258 inline void
2259 proxy_steerable(void *frontend, void *backend, void *capture, void *control)
2260 {
2261     int rc = zmq_proxy_steerable(frontend, backend, capture, control);
2262     if (rc != 0)
2263         throw error_t();
2264 }
2265 
2266 inline void proxy_steerable(socket_ref frontend,
2267                             socket_ref backend,
2268                             socket_ref capture,
2269                             socket_ref control)
2270 {
2271     int rc = zmq_proxy_steerable(frontend.handle(), backend.handle(),
2272                                  capture.handle(), control.handle());
2273     if (rc != 0)
2274         throw error_t();
2275 }
2276 #endif
2277 
2278 class monitor_t
2279 {
2280   public:
2281     monitor_t() : _socket(), _monitor_socket() {}
2282 
2283     virtual ~monitor_t() { close(); }
2284 
2285 #ifdef ZMQ_HAS_RVALUE_REFS
2286     monitor_t(monitor_t &&rhs) ZMQ_NOTHROW : _socket(), _monitor_socket()
2287     {
2288         std::swap(_socket, rhs._socket);
2289         std::swap(_monitor_socket, rhs._monitor_socket);
2290     }
2291 
2292     monitor_t &operator=(monitor_t &&rhs) ZMQ_NOTHROW
2293     {
2294         close();
2295         _socket = socket_ref();
2296         std::swap(_socket, rhs._socket);
2297         std::swap(_monitor_socket, rhs._monitor_socket);
2298         return *this;
2299     }
2300 #endif
2301 
2302 
2303     void
2304     monitor(socket_t &socket, std::string const &addr, int events = ZMQ_EVENT_ALL)
2305     {
2306         monitor(socket, addr.c_str(), events);
2307     }
2308 
2309     void monitor(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL)
2310     {
2311         init(socket, addr_, events);
2312         while (true) {
2313             check_event(-1);
2314         }
2315     }
2316 
2317     void init(socket_t &socket, std::string const &addr, int events = ZMQ_EVENT_ALL)
2318     {
2319         init(socket, addr.c_str(), events);
2320     }
2321 
2322     void init(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL)
2323     {
2324         int rc = zmq_socket_monitor(socket.handle(), addr_, events);
2325         if (rc != 0)
2326             throw error_t();
2327 
2328         _socket = socket;
2329         _monitor_socket = socket_t(socket.ctxptr, ZMQ_PAIR);
2330         _monitor_socket.connect(addr_);
2331 
2332         on_monitor_started();
2333     }
2334 
2335     bool check_event(int timeout = 0)
2336     {
2337         assert(_monitor_socket);
2338 
2339         zmq::message_t eventMsg;
2340 
2341         zmq::pollitem_t items[] = {
2342           {_monitor_socket.handle(), 0, ZMQ_POLLIN, 0},
2343         };
2344 
2345         #ifdef ZMQ_CPP11
2346         zmq::poll(&items[0], 1, std::chrono::milliseconds(timeout));
2347         #else
2348         zmq::poll(&items[0], 1, timeout);
2349         #endif
2350 
2351         if (items[0].revents & ZMQ_POLLIN) {
2352             int rc = zmq_msg_recv(eventMsg.handle(), _monitor_socket.handle(), 0);
2353             if (rc == -1 && zmq_errno() == ETERM)
2354                 return false;
2355             assert(rc != -1);
2356 
2357         } else {
2358             return false;
2359         }
2360 
2361 #if ZMQ_VERSION_MAJOR >= 4
2362         const char *data = static_cast<const char *>(eventMsg.data());
2363         zmq_event_t msgEvent;
2364         memcpy(&msgEvent.event, data, sizeof(uint16_t));
2365         data += sizeof(uint16_t);
2366         memcpy(&msgEvent.value, data, sizeof(int32_t));
2367         zmq_event_t *event = &msgEvent;
2368 #else
2369         zmq_event_t *event = static_cast<zmq_event_t *>(eventMsg.data());
2370 #endif
2371 
2372 #ifdef ZMQ_NEW_MONITOR_EVENT_LAYOUT
2373         zmq::message_t addrMsg;
2374         int rc = zmq_msg_recv(addrMsg.handle(), _monitor_socket.handle(), 0);
2375         if (rc == -1 && zmq_errno() == ETERM) {
2376             return false;
2377         }
2378 
2379         assert(rc != -1);
2380         std::string address = addrMsg.to_string();
2381 #else
2382         // Bit of a hack, but all events in the zmq_event_t union have the same layout so this will work for all event types.
2383         std::string address = event->data.connected.addr;
2384 #endif
2385 
2386 #ifdef ZMQ_EVENT_MONITOR_STOPPED
2387         if (event->event == ZMQ_EVENT_MONITOR_STOPPED) {
2388             return false;
2389         }
2390 
2391 #endif
2392 
2393         switch (event->event) {
2394             case ZMQ_EVENT_CONNECTED:
2395                 on_event_connected(*event, address.c_str());
2396                 break;
2397             case ZMQ_EVENT_CONNECT_DELAYED:
2398                 on_event_connect_delayed(*event, address.c_str());
2399                 break;
2400             case ZMQ_EVENT_CONNECT_RETRIED:
2401                 on_event_connect_retried(*event, address.c_str());
2402                 break;
2403             case ZMQ_EVENT_LISTENING:
2404                 on_event_listening(*event, address.c_str());
2405                 break;
2406             case ZMQ_EVENT_BIND_FAILED:
2407                 on_event_bind_failed(*event, address.c_str());
2408                 break;
2409             case ZMQ_EVENT_ACCEPTED:
2410                 on_event_accepted(*event, address.c_str());
2411                 break;
2412             case ZMQ_EVENT_ACCEPT_FAILED:
2413                 on_event_accept_failed(*event, address.c_str());
2414                 break;
2415             case ZMQ_EVENT_CLOSED:
2416                 on_event_closed(*event, address.c_str());
2417                 break;
2418             case ZMQ_EVENT_CLOSE_FAILED:
2419                 on_event_close_failed(*event, address.c_str());
2420                 break;
2421             case ZMQ_EVENT_DISCONNECTED:
2422                 on_event_disconnected(*event, address.c_str());
2423                 break;
2424 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 3, 0) || (defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3))
2425             case ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL:
2426                 on_event_handshake_failed_no_detail(*event, address.c_str());
2427                 break;
2428             case ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL:
2429                 on_event_handshake_failed_protocol(*event, address.c_str());
2430                 break;
2431             case ZMQ_EVENT_HANDSHAKE_FAILED_AUTH:
2432                 on_event_handshake_failed_auth(*event, address.c_str());
2433                 break;
2434             case ZMQ_EVENT_HANDSHAKE_SUCCEEDED:
2435                 on_event_handshake_succeeded(*event, address.c_str());
2436                 break;
2437 #elif defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 1)
2438             case ZMQ_EVENT_HANDSHAKE_FAILED:
2439                 on_event_handshake_failed(*event, address.c_str());
2440                 break;
2441             case ZMQ_EVENT_HANDSHAKE_SUCCEED:
2442                 on_event_handshake_succeed(*event, address.c_str());
2443                 break;
2444 #endif
2445             default:
2446                 on_event_unknown(*event, address.c_str());
2447                 break;
2448         }
2449 
2450         return true;
2451     }
2452 
2453 #ifdef ZMQ_EVENT_MONITOR_STOPPED
2454     void abort()
2455     {
2456         if (_socket)
2457             zmq_socket_monitor(_socket.handle(), ZMQ_NULLPTR, 0);
2458 
2459         _socket = socket_ref();
2460     }
2461 #endif
2462     virtual void on_monitor_started() {}
2463     virtual void on_event_connected(const zmq_event_t &event_, const char *addr_)
2464     {
2465         (void) event_;
2466         (void) addr_;
2467     }
2468     virtual void on_event_connect_delayed(const zmq_event_t &event_,
2469                                           const char *addr_)
2470     {
2471         (void) event_;
2472         (void) addr_;
2473     }
2474     virtual void on_event_connect_retried(const zmq_event_t &event_,
2475                                           const char *addr_)
2476     {
2477         (void) event_;
2478         (void) addr_;
2479     }
2480     virtual void on_event_listening(const zmq_event_t &event_, const char *addr_)
2481     {
2482         (void) event_;
2483         (void) addr_;
2484     }
2485     virtual void on_event_bind_failed(const zmq_event_t &event_, const char *addr_)
2486     {
2487         (void) event_;
2488         (void) addr_;
2489     }
2490     virtual void on_event_accepted(const zmq_event_t &event_, const char *addr_)
2491     {
2492         (void) event_;
2493         (void) addr_;
2494     }
2495     virtual void on_event_accept_failed(const zmq_event_t &event_, const char *addr_)
2496     {
2497         (void) event_;
2498         (void) addr_;
2499     }
2500     virtual void on_event_closed(const zmq_event_t &event_, const char *addr_)
2501     {
2502         (void) event_;
2503         (void) addr_;
2504     }
2505     virtual void on_event_close_failed(const zmq_event_t &event_, const char *addr_)
2506     {
2507         (void) event_;
2508         (void) addr_;
2509     }
2510     virtual void on_event_disconnected(const zmq_event_t &event_, const char *addr_)
2511     {
2512         (void) event_;
2513         (void) addr_;
2514     }
2515 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3)
2516     virtual void on_event_handshake_failed_no_detail(const zmq_event_t &event_,
2517                                                      const char *addr_)
2518     {
2519         (void) event_;
2520         (void) addr_;
2521     }
2522     virtual void on_event_handshake_failed_protocol(const zmq_event_t &event_,
2523                                                     const char *addr_)
2524     {
2525         (void) event_;
2526         (void) addr_;
2527     }
2528     virtual void on_event_handshake_failed_auth(const zmq_event_t &event_,
2529                                                 const char *addr_)
2530     {
2531         (void) event_;
2532         (void) addr_;
2533     }
2534     virtual void on_event_handshake_succeeded(const zmq_event_t &event_,
2535                                               const char *addr_)
2536     {
2537         (void) event_;
2538         (void) addr_;
2539     }
2540 #elif ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 1)
2541     virtual void on_event_handshake_failed(const zmq_event_t &event_,
2542                                            const char *addr_)
2543     {
2544         (void) event_;
2545         (void) addr_;
2546     }
2547     virtual void on_event_handshake_succeed(const zmq_event_t &event_,
2548                                             const char *addr_)
2549     {
2550         (void) event_;
2551         (void) addr_;
2552     }
2553 #endif
2554     virtual void on_event_unknown(const zmq_event_t &event_, const char *addr_)
2555     {
2556         (void) event_;
2557         (void) addr_;
2558     }
2559 
2560   private:
2561     monitor_t(const monitor_t &) ZMQ_DELETED_FUNCTION;
2562     void operator=(const monitor_t &) ZMQ_DELETED_FUNCTION;
2563 
2564     socket_ref _socket;
2565     socket_t _monitor_socket;
2566 
2567     void close() ZMQ_NOTHROW
2568     {
2569         if (_socket)
2570             zmq_socket_monitor(_socket.handle(), ZMQ_NULLPTR, 0);
2571         _monitor_socket.close();
2572     }
2573 };
2574 
2575 #if defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER)
2576 
2577 // polling events
2578 enum class event_flags : short
2579 {
2580     none = 0,
2581     pollin = ZMQ_POLLIN,
2582     pollout = ZMQ_POLLOUT,
2583     pollerr = ZMQ_POLLERR,
2584     pollpri = ZMQ_POLLPRI
2585 };
2586 
2587 constexpr event_flags operator|(event_flags a, event_flags b) noexcept
2588 {
2589     return detail::enum_bit_or(a, b);
2590 }
2591 constexpr event_flags operator&(event_flags a, event_flags b) noexcept
2592 {
2593     return detail::enum_bit_and(a, b);
2594 }
2595 constexpr event_flags operator^(event_flags a, event_flags b) noexcept
2596 {
2597     return detail::enum_bit_xor(a, b);
2598 }
2599 constexpr event_flags operator~(event_flags a) noexcept
2600 {
2601     return detail::enum_bit_not(a);
2602 }
2603 
2604 struct no_user_data;
2605 
2606 // layout compatible with zmq_poller_event_t
2607 template<class T = no_user_data> struct poller_event
2608 {
2609     socket_ref socket;
2610     ::zmq::fd_t fd;
2611     T *user_data;
2612     event_flags events;
2613 };
2614 
2615 template<typename T = no_user_data> class poller_t
2616 {
2617   public:
2618     using event_type = poller_event<T>;
2619 
2620     poller_t() : poller_ptr(zmq_poller_new())
2621     {
2622         if (!poller_ptr)
2623             throw error_t();
2624     }
2625 
2626     template<
2627       typename Dummy = void,
2628       typename =
2629         typename std::enable_if<!std::is_same<T, no_user_data>::value, Dummy>::type>
2630     void add(zmq::socket_ref socket, event_flags events, T *user_data)
2631     {
2632         add_impl(socket, events, user_data);
2633     }
2634 
2635     void add(zmq::socket_ref socket, event_flags events)
2636     {
2637         add_impl(socket, events, nullptr);
2638     }
2639 
2640     void remove(zmq::socket_ref socket)
2641     {
2642         if (0 != zmq_poller_remove(poller_ptr.get(), socket.handle())) {
2643             throw error_t();
2644         }
2645     }
2646 
2647     void modify(zmq::socket_ref socket, event_flags events)
2648     {
2649         if (0
2650             != zmq_poller_modify(poller_ptr.get(), socket.handle(),
2651                                  static_cast<short>(events))) {
2652             throw error_t();
2653         }
2654     }
2655 
2656     size_t wait_all(std::vector<event_type> &poller_events,
2657                     const std::chrono::milliseconds timeout)
2658     {
2659         int rc = zmq_poller_wait_all(
2660           poller_ptr.get(),
2661           reinterpret_cast<zmq_poller_event_t *>(poller_events.data()),
2662           static_cast<int>(poller_events.size()),
2663           static_cast<long>(timeout.count()));
2664         if (rc > 0)
2665             return static_cast<size_t>(rc);
2666 
2667 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3)
2668         if (zmq_errno() == EAGAIN)
2669 #else
2670         if (zmq_errno() == ETIMEDOUT)
2671 #endif
2672             return 0;
2673 
2674         throw error_t();
2675     }
2676 
2677 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 3, 3)
2678     size_t size() const noexcept
2679     {
2680         int rc = zmq_poller_size(const_cast<void *>(poller_ptr.get()));
2681         ZMQ_ASSERT(rc >= 0);
2682         return static_cast<size_t>(std::max(rc, 0));
2683     }
2684 #endif
2685 
2686   private:
2687     struct destroy_poller_t
2688     {
2689         void operator()(void *ptr) noexcept
2690         {
2691             int rc = zmq_poller_destroy(&ptr);
2692             ZMQ_ASSERT(rc == 0);
2693         }
2694     };
2695 
2696     std::unique_ptr<void, destroy_poller_t> poller_ptr;
2697 
2698     void add_impl(zmq::socket_ref socket, event_flags events, T *user_data)
2699     {
2700         if (0
2701             != zmq_poller_add(poller_ptr.get(), socket.handle(), user_data,
2702                               static_cast<short>(events))) {
2703             throw error_t();
2704         }
2705     }
2706 };
2707 #endif //  defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER)
2708 
2709 inline std::ostream &operator<<(std::ostream &os, const message_t &msg)
2710 {
2711     return os << msg.str();
2712 }
2713 
2714 } // namespace zmq
2715 
2716 #endif // __ZMQ_HPP_INCLUDED__