src/loggers/zmq.hpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 2016-2017 ZeroMQ community
3  Copyright (c) 2009-2011 250bpm s.r.o.
4  Copyright (c) 2011 Botond Ballo
5  Copyright (c) 2007-2009 iMatix Corporation
6 
7  Permission is hereby granted, free of charge, to any person obtaining a copy
8  of this software and associated documentation files (the "Software"), to
9  deal in the Software without restriction, including without limitation the
10  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11  sell copies of the Software, and to permit persons to whom the Software is
12  furnished to do so, subject to the following conditions:
13 
14  The above copyright notice and this permission notice shall be included in
15  all copies or substantial portions of the Software.
16 
17  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23  IN THE SOFTWARE.
24 */
25 
26 #ifndef __ZMQ_HPP_INCLUDED__
27 #define __ZMQ_HPP_INCLUDED__
28 
29 #ifdef _WIN32
30 #ifndef NOMINMAX
31 #define NOMINMAX
32 #endif
33 #endif
34 
35 // included here for _HAS_CXX* macros
36 #include <zmq.h>
37 
38 #if defined(_MSVC_LANG)
39 #define CPPZMQ_LANG _MSVC_LANG
40 #else
41 #define CPPZMQ_LANG __cplusplus
42 #endif
43 // overwrite if specific language macros indicate higher version
44 #if defined(_HAS_CXX14) && _HAS_CXX14 && CPPZMQ_LANG < 201402L
45 #undef CPPZMQ_LANG
46 #define CPPZMQ_LANG 201402L
47 #endif
48 #if defined(_HAS_CXX17) && _HAS_CXX17 && CPPZMQ_LANG < 201703L
49 #undef CPPZMQ_LANG
50 #define CPPZMQ_LANG 201703L
51 #endif
52 
53 // macros defined if has a specific standard or greater
54 #if CPPZMQ_LANG >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
55 #define ZMQ_CPP11
56 #endif
57 #if CPPZMQ_LANG >= 201402L
58 #define ZMQ_CPP14
59 #endif
60 #if CPPZMQ_LANG >= 201703L
61 #define ZMQ_CPP17
62 #endif
63 
64 #if defined(ZMQ_CPP14) && !defined(_MSC_VER)
65 #define ZMQ_DEPRECATED(msg) [[deprecated(msg)]]
66 #elif defined(_MSC_VER)
67 #define ZMQ_DEPRECATED(msg) __declspec(deprecated(msg))
68 #elif defined(__GNUC__)
69 #define ZMQ_DEPRECATED(msg) __attribute__((deprecated(msg)))
70 #endif
71 
72 #if defined(ZMQ_CPP17)
73 #define ZMQ_NODISCARD [[nodiscard]]
74 #else
75 #define ZMQ_NODISCARD
76 #endif
77 
78 #if defined(ZMQ_CPP11)
79 #define ZMQ_NOTHROW noexcept
80 #define ZMQ_EXPLICIT explicit
81 #define ZMQ_OVERRIDE override
82 #define ZMQ_NULLPTR nullptr
83 #define ZMQ_CONSTEXPR_FN constexpr
84 #define ZMQ_CONSTEXPR_VAR constexpr
85 #define ZMQ_CPP11_DEPRECATED(msg) ZMQ_DEPRECATED(msg)
86 #else
87 #define ZMQ_NOTHROW throw()
88 #define ZMQ_EXPLICIT
89 #define ZMQ_OVERRIDE
90 #define ZMQ_NULLPTR 0
91 #define ZMQ_CONSTEXPR_FN
92 #define ZMQ_CONSTEXPR_VAR const
93 #define ZMQ_CPP11_DEPRECATED(msg)
94 #endif
95 #if defined(ZMQ_CPP14) && (!defined(_MSC_VER) || _MSC_VER > 1900)
96 #define ZMQ_EXTENDED_CONSTEXPR
97 #endif
98 #if defined(ZMQ_CPP17)
99 #define ZMQ_INLINE_VAR inline
100 #else
101 #define ZMQ_INLINE_VAR
102 #endif
103 
104 #include <cassert>
105 #include <cstring>
106 
107 #include <algorithm>
108 #include <exception>
109 #include <iomanip>
110 #include <sstream>
111 #include <string>
112 #include <vector>
113 #ifdef ZMQ_CPP11
114 #include <array>
115 #include <chrono>
116 #include <tuple>
117 #include <memory>
118 #endif
119 
120 #if defined(__has_include) && defined(ZMQ_CPP17)
121 #define CPPZMQ_HAS_INCLUDE_CPP17(X) __has_include(X)
122 #else
123 #define CPPZMQ_HAS_INCLUDE_CPP17(X) 0
124 #endif
125 
126 #if CPPZMQ_HAS_INCLUDE_CPP17(<optional>) && !defined(CPPZMQ_HAS_OPTIONAL)
127 #define CPPZMQ_HAS_OPTIONAL 1
128 #endif
129 #ifndef CPPZMQ_HAS_OPTIONAL
130 #define CPPZMQ_HAS_OPTIONAL 0
131 #elif CPPZMQ_HAS_OPTIONAL
132 #include <optional>
133 #endif
134 
135 #if CPPZMQ_HAS_INCLUDE_CPP17(<string_view>) && !defined(CPPZMQ_HAS_STRING_VIEW)
136 #define CPPZMQ_HAS_STRING_VIEW 1
137 #endif
138 #ifndef CPPZMQ_HAS_STRING_VIEW
139 #define CPPZMQ_HAS_STRING_VIEW 0
140 #elif CPPZMQ_HAS_STRING_VIEW
141 #include <string_view>
142 #endif
143 
144 /* Version macros for compile-time API version detection */
145 #define CPPZMQ_VERSION_MAJOR 4
146 #define CPPZMQ_VERSION_MINOR 7
147 #define CPPZMQ_VERSION_PATCH 1
148 
149 #define CPPZMQ_VERSION \
150  ZMQ_MAKE_VERSION(CPPZMQ_VERSION_MAJOR, CPPZMQ_VERSION_MINOR, CPPZMQ_VERSION_PATCH)
151 
152 // Detect whether the compiler supports C++11 rvalue references.
153 #if(defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && \
154  defined(__GXX_EXPERIMENTAL_CXX0X__))
155 #define ZMQ_HAS_RVALUE_REFS
156 #define ZMQ_DELETED_FUNCTION = delete
157 #elif defined(__clang__)
158 #if __has_feature(cxx_rvalue_references)
159 #define ZMQ_HAS_RVALUE_REFS
160 #endif
161 
162 #if __has_feature(cxx_deleted_functions)
163 #define ZMQ_DELETED_FUNCTION = delete
164 #else
165 #define ZMQ_DELETED_FUNCTION
166 #endif
167 #elif defined(_MSC_VER) && (_MSC_VER >= 1900)
168 #define ZMQ_HAS_RVALUE_REFS
169 #define ZMQ_DELETED_FUNCTION = delete
170 #elif defined(_MSC_VER) && (_MSC_VER >= 1600)
171 #define ZMQ_HAS_RVALUE_REFS
172 #define ZMQ_DELETED_FUNCTION
173 #else
174 #define ZMQ_DELETED_FUNCTION
175 #endif
176 
177 #if defined(ZMQ_CPP11) && !defined(__llvm__) && !defined(__INTEL_COMPILER) && \
178  defined(__GNUC__) && __GNUC__ < 5
179 #define ZMQ_CPP11_PARTIAL
180 #elif defined(__GLIBCXX__) && __GLIBCXX__ < 20160805
181 //the date here is the last date of gcc 4.9.4, which
182 // effectively means libstdc++ from gcc 5.5 and higher won't trigger this branch
183 #define ZMQ_CPP11_PARTIAL
184 #endif
185 
186 #ifdef ZMQ_CPP11
187 #ifdef ZMQ_CPP11_PARTIAL
188 #define ZMQ_IS_TRIVIALLY_COPYABLE(T) __has_trivial_copy(T)
189 #else
190 #include <type_traits>
191 #define ZMQ_IS_TRIVIALLY_COPYABLE(T) std::is_trivially_copyable<T>::value
192 #endif
193 #endif
194 
195 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3, 3, 0)
196 #define ZMQ_NEW_MONITOR_EVENT_LAYOUT
197 #endif
198 
199 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0)
200 #define ZMQ_HAS_PROXY_STEERABLE
201 /* Socket event data */
202 typedef struct
203 {
204  uint16_t event; // id of the event as bitfield
205  int32_t value; // value is either error code, fd or reconnect interval
206 } zmq_event_t;
207 #endif
208 
209 // Avoid using deprecated message receive function when possible
210 #if ZMQ_VERSION < ZMQ_MAKE_VERSION(3, 2, 0)
211 #define zmq_msg_recv(msg, socket, flags) zmq_recvmsg(socket, msg, flags)
212 #endif
213 
214 // In order to prevent unused variable warnings when building in non-debug
215 // mode use this macro to make assertions.
216 #ifndef NDEBUG
217 #define ZMQ_ASSERT(expression) assert(expression)
218 #else
219 #define ZMQ_ASSERT(expression) (void)(expression)
220 #endif
221 
222 namespace zmq
223 {
224 #ifdef ZMQ_CPP11
225 namespace detail
226 {
227 namespace ranges
228 {
229 using std::begin;
230 using std::end;
231 template <class T>
232 auto begin(T&& r) -> decltype(begin(std::forward<T>(r)))
233 {
234  return begin(std::forward<T>(r));
235 }
236 template <class T>
237 auto end(T&& r) -> decltype(end(std::forward<T>(r)))
238 {
239  return end(std::forward<T>(r));
240 }
241 } // namespace ranges
242 
243 template <class T>
244 using void_t = void;
245 
246 template <class Iter>
247 using iter_value_t = typename std::iterator_traits<Iter>::value_type;
248 
249 template <class Range>
250 using range_iter_t =
251  decltype(ranges::begin(std::declval<typename std::remove_reference<Range>::type&>()));
252 
253 template <class Range>
254 using range_value_t = iter_value_t<range_iter_t<Range>>;
255 
256 template <class T, class = void>
257 struct is_range : std::false_type
258 {
259 };
260 
261 template <class T>
262 struct is_range<
263  T, void_t<decltype(ranges::begin(
264  std::declval<typename std::remove_reference<T>::type&>()) ==
265  ranges::end(
266  std::declval<typename std::remove_reference<T>::type&>()))>>
267  : std::true_type
268 {
269 };
270 
271 } // namespace detail
272 #endif
273 
274 typedef zmq_free_fn free_fn;
275 typedef zmq_pollitem_t pollitem_t;
276 
277 class error_t : public std::exception
278 {
279 public:
280  error_t() ZMQ_NOTHROW : errnum(zmq_errno())
281  {}
282  explicit error_t(int err) ZMQ_NOTHROW : errnum(err)
283  {}
284  virtual const char* what() const ZMQ_NOTHROW ZMQ_OVERRIDE
285  {
286  return zmq_strerror(errnum);
287  }
288  int num() const ZMQ_NOTHROW
289  {
290  return errnum;
291  }
292 
293 private:
294  int errnum;
295 };
296 
297 inline int poll(zmq_pollitem_t* items_, size_t nitems_, long timeout_ = -1)
298 {
299  int rc = zmq_poll(items_, static_cast<int>(nitems_), timeout_);
300  if(rc < 0)
301  throw error_t();
302  return rc;
303 }
304 
305 ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
306 inline int poll(zmq_pollitem_t const* items_, size_t nitems_, long timeout_ = -1)
307 {
308  return poll(const_cast<zmq_pollitem_t*>(items_), nitems_, timeout_);
309 }
310 
311 #ifdef ZMQ_CPP11
312 ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
313 inline int poll(zmq_pollitem_t const* items, size_t nitems,
314  std::chrono::milliseconds timeout)
315 {
316  return poll(const_cast<zmq_pollitem_t*>(items), nitems,
317  static_cast<long>(timeout.count()));
318 }
319 
320 ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
321 inline int poll(std::vector<zmq_pollitem_t> const& items,
322  std::chrono::milliseconds timeout)
323 {
324  return poll(const_cast<zmq_pollitem_t*>(items.data()), items.size(),
325  static_cast<long>(timeout.count()));
326 }
327 
328 ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
329 inline int poll(std::vector<zmq_pollitem_t> const& items, long timeout_ = -1)
330 {
331  return poll(const_cast<zmq_pollitem_t*>(items.data()), items.size(), timeout_);
332 }
333 
334 inline int poll(zmq_pollitem_t* items, size_t nitems, std::chrono::milliseconds timeout)
335 {
336  return poll(items, nitems, static_cast<long>(timeout.count()));
337 }
338 
339 inline int poll(std::vector<zmq_pollitem_t>& items, std::chrono::milliseconds timeout)
340 {
341  return poll(items.data(), items.size(), static_cast<long>(timeout.count()));
342 }
343 
344 ZMQ_DEPRECATED("from 4.3.1, use poll taking std::chrono instead of long")
345 inline int poll(std::vector<zmq_pollitem_t>& items, long timeout_ = -1)
346 {
347  return poll(items.data(), items.size(), timeout_);
348 }
349 
350 template <std::size_t SIZE>
351 inline int poll(std::array<zmq_pollitem_t, SIZE>& items,
352  std::chrono::milliseconds timeout)
353 {
354  return poll(items.data(), items.size(), static_cast<long>(timeout.count()));
355 }
356 #endif
357 
358 inline void version(int* major_, int* minor_, int* patch_)
359 {
360  zmq_version(major_, minor_, patch_);
361 }
362 
363 #ifdef ZMQ_CPP11
364 inline std::tuple<int, int, int> version()
365 {
366  std::tuple<int, int, int> v;
367  zmq_version(&std::get<0>(v), &std::get<1>(v), &std::get<2>(v));
368  return v;
369 }
370 
371 #if !defined(ZMQ_CPP11_PARTIAL)
372 namespace detail
373 {
374 template <class T>
375 struct is_char_type
376 {
377  // true if character type for string literals in C++11
378  static constexpr bool value =
381 };
382 } // namespace detail
383 #endif
384 
385 #endif
386 
387 class message_t
388 {
389 public:
391  {
392  int rc = zmq_msg_init(&msg);
393  ZMQ_ASSERT(rc == 0);
394  }
395 
396  explicit message_t(size_t size_)
397  {
398  int rc = zmq_msg_init_size(&msg, size_);
399  if(rc != 0)
400  throw error_t();
401  }
402 
403  template <class ForwardIter>
404  message_t(ForwardIter first, ForwardIter last)
405  {
406  typedef typename std::iterator_traits<ForwardIter>::value_type value_t;
407 
408  assert(std::distance(first, last) >= 0);
409  size_t const size_ =
410  static_cast<size_t>(std::distance(first, last)) * sizeof(value_t);
411  int const rc = zmq_msg_init_size(&msg, size_);
412  if(rc != 0)
413  throw error_t();
414  std::copy(first, last, data<value_t>());
415  }
416 
417  message_t(const void* data_, size_t size_)
418  {
419  int rc = zmq_msg_init_size(&msg, size_);
420  if(rc != 0)
421  throw error_t();
422  if(size_)
423  {
424  // this constructor allows (nullptr, 0),
425  // memcpy with a null pointer is UB
426  memcpy(data(), data_, size_);
427  }
428  }
429 
430  message_t(void* data_, size_t size_, free_fn* ffn_, void* hint_ = ZMQ_NULLPTR)
431  {
432  int rc = zmq_msg_init_data(&msg, data_, size_, ffn_, hint_);
433  if(rc != 0)
434  throw error_t();
435  }
436 
437  // overload set of string-like types and generic containers
438 #if defined(ZMQ_CPP11) && !defined(ZMQ_CPP11_PARTIAL)
439  // NOTE this constructor will include the null terminator
440  // when called with a string literal.
441  // An overload taking const char* can not be added because
442  // it would be preferred over this function and break compatiblity.
443  template <class Char, size_t N,
444  typename = typename std::enable_if<detail::is_char_type<Char>::value>::type>
445  ZMQ_DEPRECATED("from 4.7.0, use constructors taking iterators, (pointer, size) "
446  "or strings instead")
447  explicit message_t(const Char (&data)[N])
448  : message_t(detail::ranges::begin(data), detail::ranges::end(data))
449  {}
450 
451  template <class Range, typename = typename std::enable_if<
453  ZMQ_IS_TRIVIALLY_COPYABLE(detail::range_value_t<Range>) &&
454  !detail::is_char_type<detail::range_value_t<Range>>::value &&
456  explicit message_t(const Range& rng)
457  : message_t(detail::ranges::begin(rng), detail::ranges::end(rng))
458  {}
459 
460  explicit message_t(const std::string& str) : message_t(str.data(), str.size())
461  {}
462 
463 #if CPPZMQ_HAS_STRING_VIEW
465  {}
466 #endif
467 
468 #endif
469 
470 #ifdef ZMQ_HAS_RVALUE_REFS
471  message_t(message_t&& rhs) ZMQ_NOTHROW : msg(rhs.msg)
472  {
473  int rc = zmq_msg_init(&rhs.msg);
474  ZMQ_ASSERT(rc == 0);
475  }
476 
478  {
479  std::swap(msg, rhs.msg);
480  return *this;
481  }
482 #endif
483 
485  {
486  int rc = zmq_msg_close(&msg);
487  ZMQ_ASSERT(rc == 0);
488  }
489 
490  void rebuild()
491  {
492  int rc = zmq_msg_close(&msg);
493  if(rc != 0)
494  throw error_t();
495  rc = zmq_msg_init(&msg);
496  ZMQ_ASSERT(rc == 0);
497  }
498 
499  void rebuild(size_t size_)
500  {
501  int rc = zmq_msg_close(&msg);
502  if(rc != 0)
503  throw error_t();
504  rc = zmq_msg_init_size(&msg, size_);
505  if(rc != 0)
506  throw error_t();
507  }
508 
509  void rebuild(const void* data_, size_t size_)
510  {
511  int rc = zmq_msg_close(&msg);
512  if(rc != 0)
513  throw error_t();
514  rc = zmq_msg_init_size(&msg, size_);
515  if(rc != 0)
516  throw error_t();
517  memcpy(data(), data_, size_);
518  }
519 
520  void rebuild(void* data_, size_t size_, free_fn* ffn_, void* hint_ = ZMQ_NULLPTR)
521  {
522  int rc = zmq_msg_close(&msg);
523  if(rc != 0)
524  throw error_t();
525  rc = zmq_msg_init_data(&msg, data_, size_, ffn_, hint_);
526  if(rc != 0)
527  throw error_t();
528  }
529 
530  ZMQ_DEPRECATED("from 4.3.1, use move taking non-const reference instead")
531  void move(message_t const* msg_)
532  {
533  int rc = zmq_msg_move(&msg, const_cast<zmq_msg_t*>(msg_->handle()));
534  if(rc != 0)
535  throw error_t();
536  }
537 
538  void move(message_t& msg_)
539  {
540  int rc = zmq_msg_move(&msg, msg_.handle());
541  if(rc != 0)
542  throw error_t();
543  }
544 
545  ZMQ_DEPRECATED("from 4.3.1, use copy taking non-const reference instead")
546  void copy(message_t const* msg_)
547  {
548  int rc = zmq_msg_copy(&msg, const_cast<zmq_msg_t*>(msg_->handle()));
549  if(rc != 0)
550  throw error_t();
551  }
552 
553  void copy(message_t& msg_)
554  {
555  int rc = zmq_msg_copy(&msg, msg_.handle());
556  if(rc != 0)
557  throw error_t();
558  }
559 
560  bool more() const ZMQ_NOTHROW
561  {
562  int rc = zmq_msg_more(const_cast<zmq_msg_t*>(&msg));
563  return rc != 0;
564  }
565 
567  {
568  return zmq_msg_data(&msg);
569  }
570 
571  const void* data() const ZMQ_NOTHROW
572  {
573  return zmq_msg_data(const_cast<zmq_msg_t*>(&msg));
574  }
575 
576  size_t size() const ZMQ_NOTHROW
577  {
578  return zmq_msg_size(const_cast<zmq_msg_t*>(&msg));
579  }
580 
582  {
583  return size() == 0u;
584  }
585 
586  template <typename T>
588  {
589  return static_cast<T*>(data());
590  }
591 
592  template <typename T>
593  T const* data() const ZMQ_NOTHROW
594  {
595  return static_cast<T const*>(data());
596  }
597 
598  ZMQ_DEPRECATED("from 4.3.0, use operator== instead")
599  bool equal(const message_t* other) const ZMQ_NOTHROW
600  {
601  return *this == *other;
602  }
603 
604  bool operator==(const message_t& other) const ZMQ_NOTHROW
605  {
606  const size_t my_size = size();
607  return my_size == other.size() && 0 == memcmp(data(), other.data(), my_size);
608  }
609 
610  bool operator!=(const message_t& other) const ZMQ_NOTHROW
611  {
612  return !(*this == other);
613  }
614 
615 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3, 2, 0)
616  int get(int property_)
617  {
618  int value = zmq_msg_get(&msg, property_);
619  if(value == -1)
620  throw error_t();
621  return value;
622  }
623 #endif
624 
625 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0)
626  const char* gets(const char* property_)
627  {
628  const char* value = zmq_msg_gets(&msg, property_);
629  if(value == ZMQ_NULLPTR)
630  throw error_t();
631  return value;
632  }
633 #endif
634 
635 #if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0)
636  uint32_t routing_id() const
637  {
638  return zmq_msg_routing_id(const_cast<zmq_msg_t*>(&msg));
639  }
640 
641  void set_routing_id(uint32_t routing_id)
642  {
643  int rc = zmq_msg_set_routing_id(&msg, routing_id);
644  if(rc != 0)
645  throw error_t();
646  }
647 
648  const char* group() const
649  {
650  return zmq_msg_group(const_cast<zmq_msg_t*>(&msg));
651  }
652 
653  void set_group(const char* group)
654  {
655  int rc = zmq_msg_set_group(&msg, group);
656  if(rc != 0)
657  throw error_t();
658  }
659 #endif
660 
661  // interpret message content as a string
662  std::string to_string() const
663  {
664  return std::string(static_cast<const char*>(data()), size());
665  }
666 #if CPPZMQ_HAS_STRING_VIEW
667  // interpret message content as a string
668  std::string_view to_string_view() const noexcept
669  {
670  return std::string_view(static_cast<const char*>(data()), size());
671  }
672 #endif
673 
680  std::string str() const
681  {
682  // Partly mutuated from the same method in zmq::multipart_t
683  std::stringstream os;
684 
685  const unsigned char* msg_data = this->data<unsigned char>();
686  unsigned char byte;
687  size_t size = this->size();
688  int is_ascii[2] = { 0, 0 };
689 
690  os << "zmq::message_t [size " << std::dec << std::setw(3) << std::setfill('0') << size
691  << "] (";
692  // Totally arbitrary
693  if(size >= 1000)
694  {
695  os << "... too big to print)";
696  }
697  else
698  {
699  while(size--)
700  {
701  byte = *msg_data++;
702 
703  is_ascii[1] = (byte >= 32 && byte < 127);
704  if(is_ascii[1] != is_ascii[0])
705  os << " "; // Separate text/non text
706 
707  if(is_ascii[1])
708  {
709  os << byte;
710  }
711  else
712  {
713  os << std::hex << std::uppercase << std::setw(2) << std::setfill('0')
714  << static_cast<short>(byte);
715  }
716  is_ascii[0] = is_ascii[1];
717  }
718  os << ")";
719  }
720  return os.str();
721  }
722 
724  {
725  // this assumes zmq::msg_t from libzmq is trivially relocatable
726  std::swap(msg, other.msg);
727  }
728 
730  {
731  return &msg;
732  }
733  ZMQ_NODISCARD const zmq_msg_t* handle() const ZMQ_NOTHROW
734  {
735  return &msg;
736  }
737 
738 private:
739  // The underlying message
740  zmq_msg_t msg;
741 
742  // Disable implicit message copying, so that users won't use shared
743  // messages (less efficient) without being aware of the fact.
746 };
747 
748 inline void swap(message_t& a, message_t& b) ZMQ_NOTHROW
749 {
750  a.swap(b);
751 }
752 
753 #ifdef ZMQ_CPP11
754 enum class ctxopt
755 {
756 #ifdef ZMQ_BLOCKY
757  blocky = ZMQ_BLOCKY,
758 #endif
759 #ifdef ZMQ_IO_THREADS
760  io_threads = ZMQ_IO_THREADS,
761 #endif
762 #ifdef ZMQ_THREAD_SCHED_POLICY
763  thread_sched_policy = ZMQ_THREAD_SCHED_POLICY,
764 #endif
765 #ifdef ZMQ_THREAD_PRIORITY
766  thread_priority = ZMQ_THREAD_PRIORITY,
767 #endif
768 #ifdef ZMQ_THREAD_AFFINITY_CPU_ADD
769  thread_affinity_cpu_add = ZMQ_THREAD_AFFINITY_CPU_ADD,
770 #endif
771 #ifdef ZMQ_THREAD_AFFINITY_CPU_REMOVE
772  thread_affinity_cpu_remove = ZMQ_THREAD_AFFINITY_CPU_REMOVE,
773 #endif
774 #ifdef ZMQ_THREAD_NAME_PREFIX
775  thread_name_prefix = ZMQ_THREAD_NAME_PREFIX,
776 #endif
777 #ifdef ZMQ_MAX_MSGSZ
778  max_msgsz = ZMQ_MAX_MSGSZ,
779 #endif
780 #ifdef ZMQ_ZERO_COPY_RECV
781  zero_copy_recv = ZMQ_ZERO_COPY_RECV,
782 #endif
783 #ifdef ZMQ_MAX_SOCKETS
784  max_sockets = ZMQ_MAX_SOCKETS,
785 #endif
786 #ifdef ZMQ_SOCKET_LIMIT
787  socket_limit = ZMQ_SOCKET_LIMIT,
788 #endif
789 #ifdef ZMQ_IPV6
790  ipv6 = ZMQ_IPV6,
791 #endif
792 #ifdef ZMQ_MSG_T_SIZE
793  msg_t_size = ZMQ_MSG_T_SIZE
794 #endif
795 };
796 #endif
797 
798 class context_t
799 {
800 public:
802  {
803  ptr = zmq_ctx_new();
804  if(ptr == ZMQ_NULLPTR)
805  throw error_t();
806  }
807 
808  explicit context_t(int io_threads_, int max_sockets_ = ZMQ_MAX_SOCKETS_DFLT)
809  {
810  ptr = zmq_ctx_new();
811  if(ptr == ZMQ_NULLPTR)
812  throw error_t();
813 
814  int rc = zmq_ctx_set(ptr, ZMQ_IO_THREADS, io_threads_);
815  ZMQ_ASSERT(rc == 0);
816 
817  rc = zmq_ctx_set(ptr, ZMQ_MAX_SOCKETS, max_sockets_);
818  ZMQ_ASSERT(rc == 0);
819  }
820 
821 #ifdef ZMQ_HAS_RVALUE_REFS
822  context_t(context_t&& rhs) ZMQ_NOTHROW : ptr(rhs.ptr)
823  {
824  rhs.ptr = ZMQ_NULLPTR;
825  }
827  {
828  close();
829  std::swap(ptr, rhs.ptr);
830  return *this;
831  }
832 #endif
833 
835  {
836  close();
837  }
838 
839  ZMQ_CPP11_DEPRECATED("from 4.7.0, use set taking zmq::ctxopt instead")
840  int setctxopt(int option_, int optval_)
841  {
842  int rc = zmq_ctx_set(ptr, option_, optval_);
843  ZMQ_ASSERT(rc == 0);
844  return rc;
845  }
846 
847  ZMQ_CPP11_DEPRECATED("from 4.7.0, use get taking zmq::ctxopt instead")
848  int getctxopt(int option_)
849  {
850  return zmq_ctx_get(ptr, option_);
851  }
852 
853 #ifdef ZMQ_CPP11
854  void set(ctxopt option, int optval)
855  {
856  int rc = zmq_ctx_set(ptr, static_cast<int>(option), optval);
857  if(rc == -1)
858  throw error_t();
859  }
860 
861  ZMQ_NODISCARD int get(ctxopt option)
862  {
863  int rc = zmq_ctx_get(ptr, static_cast<int>(option));
864  // some options have a default value of -1
865  // which is unfortunate, and may result in errors
866  // that don't make sense
867  if(rc == -1)
868  throw error_t();
869  return rc;
870  }
871 #endif
872 
873  // Terminates context (see also shutdown()).
875  {
876  if(ptr == ZMQ_NULLPTR)
877  return;
878 
879  int rc;
880  do
881  {
882  rc = zmq_ctx_destroy(ptr);
883  } while(rc == -1 && errno == EINTR);
884 
885  ZMQ_ASSERT(rc == 0);
886  ptr = ZMQ_NULLPTR;
887  }
888 
889  // Shutdown context in preparation for termination (close()).
890  // Causes all blocking socket operations and any further
891  // socket operations to return with ETERM.
893  {
894  if(ptr == ZMQ_NULLPTR)
895  return;
896  int rc = zmq_ctx_shutdown(ptr);
897  ZMQ_ASSERT(rc == 0);
898  }
899 
900  // Be careful with this, it's probably only useful for
901  // using the C api together with an existing C++ api.
902  // Normally you should never need to use this.
903  ZMQ_EXPLICIT operator void*() ZMQ_NOTHROW
904  {
905  return ptr;
906  }
907 
908  ZMQ_EXPLICIT operator void const*() const ZMQ_NOTHROW
909  {
910  return ptr;
911  }
912 
914  {
915  return ptr;
916  }
917 
918  ZMQ_DEPRECATED("from 4.7.0, use handle() != nullptr instead")
919  operator bool() const ZMQ_NOTHROW
920  {
921  return ptr != ZMQ_NULLPTR;
922  }
923 
925  {
926  std::swap(ptr, other.ptr);
927  }
928 
929 private:
930  void* ptr;
931 
934 };
935 
936 inline void swap(context_t& a, context_t& b) ZMQ_NOTHROW
937 {
938  a.swap(b);
939 }
940 
941 #ifdef ZMQ_CPP11
942 
943 struct recv_buffer_size
944 {
945  size_t size; // number of bytes written to buffer
946  size_t untruncated_size; // untruncated message size in bytes
947 
948  ZMQ_NODISCARD bool truncated() const noexcept
949  {
950  return size != untruncated_size;
951  }
952 };
953 
954 #if CPPZMQ_HAS_OPTIONAL
955 
956 using send_result_t = std::optional<size_t>;
957 using recv_result_t = std::optional<size_t>;
958 using recv_buffer_result_t = std::optional<recv_buffer_size>;
959 
960 #else
961 
962 namespace detail
963 {
964 // A C++11 type emulating the most basic
965 // operations of std::optional for trivial types
966 template <class T>
967 class trivial_optional
968 {
969 public:
970  static_assert(std::is_trivial<T>::value, "T must be trivial");
971  using value_type = T;
972 
973  trivial_optional() = default;
974  trivial_optional(T value) noexcept : _value(value), _has_value(true)
975  {}
976 
977  const T* operator->() const noexcept
978  {
979  assert(_has_value);
980  return &_value;
981  }
982  T* operator->() noexcept
983  {
984  assert(_has_value);
985  return &_value;
986  }
987 
988  const T& operator*() const noexcept
989  {
990  assert(_has_value);
991  return _value;
992  }
993  T& operator*() noexcept
994  {
995  assert(_has_value);
996  return _value;
997  }
998 
999  T& value()
1000  {
1001  if(!_has_value)
1002  throw std::exception();
1003  return _value;
1004  }
1005  const T& value() const
1006  {
1007  if(!_has_value)
1008  throw std::exception();
1009  return _value;
1010  }
1011 
1012  explicit operator bool() const noexcept
1013  {
1014  return _has_value;
1015  }
1016  bool has_value() const noexcept
1017  {
1018  return _has_value;
1019  }
1020 
1021 private:
1022  T _value{};
1023  bool _has_value{ false };
1024 };
1025 } // namespace detail
1026 
1027 using send_result_t = detail::trivial_optional<size_t>;
1028 using recv_result_t = detail::trivial_optional<size_t>;
1029 using recv_buffer_result_t = detail::trivial_optional<recv_buffer_size>;
1030 
1031 #endif
1032 
1033 namespace detail
1034 {
1035 template <class T>
1036 constexpr T enum_bit_or(T a, T b) noexcept
1037 {
1038  static_assert(std::is_enum<T>::value, "must be enum");
1039  using U = typename std::underlying_type<T>::type;
1040  return static_cast<T>(static_cast<U>(a) | static_cast<U>(b));
1041 }
1042 template <class T>
1043 constexpr T enum_bit_and(T a, T b) noexcept
1044 {
1045  static_assert(std::is_enum<T>::value, "must be enum");
1046  using U = typename std::underlying_type<T>::type;
1047  return static_cast<T>(static_cast<U>(a) & static_cast<U>(b));
1048 }
1049 template <class T>
1050 constexpr T enum_bit_xor(T a, T b) noexcept
1051 {
1052  static_assert(std::is_enum<T>::value, "must be enum");
1053  using U = typename std::underlying_type<T>::type;
1054  return static_cast<T>(static_cast<U>(a) ^ static_cast<U>(b));
1055 }
1056 template <class T>
1057 constexpr T enum_bit_not(T a) noexcept
1058 {
1059  static_assert(std::is_enum<T>::value, "must be enum");
1060  using U = typename std::underlying_type<T>::type;
1061  return static_cast<T>(~static_cast<U>(a));
1062 }
1063 } // namespace detail
1064 
1065 // partially satisfies named requirement BitmaskType
1066 enum class send_flags : int
1067 {
1068  none = 0,
1069  dontwait = ZMQ_DONTWAIT,
1070  sndmore = ZMQ_SNDMORE
1071 };
1072 
1073 constexpr send_flags operator|(send_flags a, send_flags b) noexcept
1074 {
1075  return detail::enum_bit_or(a, b);
1076 }
1077 constexpr send_flags operator&(send_flags a, send_flags b) noexcept
1078 {
1079  return detail::enum_bit_and(a, b);
1080 }
1081 constexpr send_flags operator^(send_flags a, send_flags b) noexcept
1082 {
1083  return detail::enum_bit_xor(a, b);
1084 }
1085 constexpr send_flags operator~(send_flags a) noexcept
1086 {
1087  return detail::enum_bit_not(a);
1088 }
1089 
1090 // partially satisfies named requirement BitmaskType
1091 enum class recv_flags : int
1092 {
1093  none = 0,
1094  dontwait = ZMQ_DONTWAIT
1095 };
1096 
1097 constexpr recv_flags operator|(recv_flags a, recv_flags b) noexcept
1098 {
1099  return detail::enum_bit_or(a, b);
1100 }
1101 constexpr recv_flags operator&(recv_flags a, recv_flags b) noexcept
1102 {
1103  return detail::enum_bit_and(a, b);
1104 }
1105 constexpr recv_flags operator^(recv_flags a, recv_flags b) noexcept
1106 {
1107  return detail::enum_bit_xor(a, b);
1108 }
1109 constexpr recv_flags operator~(recv_flags a) noexcept
1110 {
1111  return detail::enum_bit_not(a);
1112 }
1113 
1114 // mutable_buffer, const_buffer and buffer are based on
1115 // the Networking TS specification, draft:
1116 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4771.pdf
1117 
1118 class mutable_buffer
1119 {
1120 public:
1121  constexpr mutable_buffer() noexcept : _data(nullptr), _size(0)
1122  {}
1123  constexpr mutable_buffer(void* p, size_t n) noexcept : _data(p), _size(n)
1124  {
1125 #ifdef ZMQ_EXTENDED_CONSTEXPR
1126  assert(p != nullptr || n == 0);
1127 #endif
1128  }
1129 
1130  constexpr void* data() const noexcept
1131  {
1132  return _data;
1133  }
1134  constexpr size_t size() const noexcept
1135  {
1136  return _size;
1137  }
1138  mutable_buffer& operator+=(size_t n) noexcept
1139  {
1140  // (std::min) is a workaround for when a min macro is defined
1141  const auto shift = (std::min)(n, _size);
1142  _data = static_cast<char*>(_data) + shift;
1143  _size -= shift;
1144  return *this;
1145  }
1146 
1147 private:
1148  void* _data;
1149  size_t _size;
1150 };
1151 
1152 inline mutable_buffer operator+(const mutable_buffer& mb, size_t n) noexcept
1153 {
1154  return mutable_buffer(static_cast<char*>(mb.data()) + (std::min)(n, mb.size()),
1155  mb.size() - (std::min)(n, mb.size()));
1156 }
1157 inline mutable_buffer operator+(size_t n, const mutable_buffer& mb) noexcept
1158 {
1159  return mb + n;
1160 }
1161 
1162 class const_buffer
1163 {
1164 public:
1165  constexpr const_buffer() noexcept : _data(nullptr), _size(0)
1166  {}
1167  constexpr const_buffer(const void* p, size_t n) noexcept : _data(p), _size(n)
1168  {
1169 #ifdef ZMQ_EXTENDED_CONSTEXPR
1170  assert(p != nullptr || n == 0);
1171 #endif
1172  }
1173  constexpr const_buffer(const mutable_buffer& mb) noexcept
1174  : _data(mb.data()), _size(mb.size())
1175  {}
1176 
1177  constexpr const void* data() const noexcept
1178  {
1179  return _data;
1180  }
1181  constexpr size_t size() const noexcept
1182  {
1183  return _size;
1184  }
1185  const_buffer& operator+=(size_t n) noexcept
1186  {
1187  const auto shift = (std::min)(n, _size);
1188  _data = static_cast<const char*>(_data) + shift;
1189  _size -= shift;
1190  return *this;
1191  }
1192 
1193 private:
1194  const void* _data;
1195  size_t _size;
1196 };
1197 
1198 inline const_buffer operator+(const const_buffer& cb, size_t n) noexcept
1199 {
1200  return const_buffer(static_cast<const char*>(cb.data()) + (std::min)(n, cb.size()),
1201  cb.size() - (std::min)(n, cb.size()));
1202 }
1203 inline const_buffer operator+(size_t n, const const_buffer& cb) noexcept
1204 {
1205  return cb + n;
1206 }
1207 
1208 // buffer creation
1209 
1210 constexpr mutable_buffer buffer(void* p, size_t n) noexcept
1211 {
1212  return mutable_buffer(p, n);
1213 }
1214 constexpr const_buffer buffer(const void* p, size_t n) noexcept
1215 {
1216  return const_buffer(p, n);
1217 }
1218 constexpr mutable_buffer buffer(const mutable_buffer& mb) noexcept
1219 {
1220  return mb;
1221 }
1222 inline mutable_buffer buffer(const mutable_buffer& mb, size_t n) noexcept
1223 {
1224  return mutable_buffer(mb.data(), (std::min)(mb.size(), n));
1225 }
1226 constexpr const_buffer buffer(const const_buffer& cb) noexcept
1227 {
1228  return cb;
1229 }
1230 inline const_buffer buffer(const const_buffer& cb, size_t n) noexcept
1231 {
1232  return const_buffer(cb.data(), (std::min)(cb.size(), n));
1233 }
1234 
1235 namespace detail
1236 {
1237 template <class T>
1238 struct is_buffer
1239 {
1240  static constexpr bool value =
1242 };
1243 
1244 template <class T>
1245 struct is_pod_like
1246 {
1247  // NOTE: The networking draft N4771 section 16.11 requires
1248  // T in the buffer functions below to be
1249  // trivially copyable OR standard layout.
1250  // Here we decide to be conservative and require both.
1251  static constexpr bool value =
1252  ZMQ_IS_TRIVIALLY_COPYABLE(T) && std::is_standard_layout<T>::value;
1253 };
1254 
1255 template <class C>
1256 constexpr auto seq_size(const C& c) noexcept -> decltype(c.size())
1257 {
1258  return c.size();
1259 }
1260 template <class T, size_t N>
1261 constexpr size_t seq_size(const T (& /*array*/)[N]) noexcept
1262 {
1263  return N;
1264 }
1265 
1266 template <class Seq>
1267 auto buffer_contiguous_sequence(Seq&& seq) noexcept
1268  -> decltype(buffer(std::addressof(*std::begin(seq)), size_t{}))
1269 {
1270  using T = typename std::remove_cv<
1271  typename std::remove_reference<decltype(*std::begin(seq))>::type>::type;
1272  static_assert(detail::is_pod_like<T>::value, "T must be POD");
1273 
1274  const auto size = seq_size(seq);
1275  return buffer(size != 0u ? std::addressof(*std::begin(seq)) : nullptr,
1276  size * sizeof(T));
1277 }
1278 template <class Seq>
1279 auto buffer_contiguous_sequence(Seq&& seq, size_t n_bytes) noexcept
1280  -> decltype(buffer_contiguous_sequence(seq))
1281 {
1282  using T = typename std::remove_cv<
1283  typename std::remove_reference<decltype(*std::begin(seq))>::type>::type;
1284  static_assert(detail::is_pod_like<T>::value, "T must be POD");
1285 
1286  const auto size = seq_size(seq);
1287  return buffer(size != 0u ? std::addressof(*std::begin(seq)) : nullptr,
1288  (std::min)(size * sizeof(T), n_bytes));
1289 }
1290 
1291 } // namespace detail
1292 
1293 // C array
1294 template <class T, size_t N>
1295 mutable_buffer buffer(T (&data)[N]) noexcept
1296 {
1297  return detail::buffer_contiguous_sequence(data);
1298 }
1299 template <class T, size_t N>
1300 mutable_buffer buffer(T (&data)[N], size_t n_bytes) noexcept
1301 {
1302  return detail::buffer_contiguous_sequence(data, n_bytes);
1303 }
1304 template <class T, size_t N>
1305 const_buffer buffer(const T (&data)[N]) noexcept
1306 {
1307  return detail::buffer_contiguous_sequence(data);
1308 }
1309 template <class T, size_t N>
1310 const_buffer buffer(const T (&data)[N], size_t n_bytes) noexcept
1311 {
1312  return detail::buffer_contiguous_sequence(data, n_bytes);
1313 }
1314 // std::array
1315 template <class T, size_t N>
1316 mutable_buffer buffer(std::array<T, N>& data) noexcept
1317 {
1318  return detail::buffer_contiguous_sequence(data);
1319 }
1320 template <class T, size_t N>
1321 mutable_buffer buffer(std::array<T, N>& data, size_t n_bytes) noexcept
1322 {
1323  return detail::buffer_contiguous_sequence(data, n_bytes);
1324 }
1325 template <class T, size_t N>
1326 const_buffer buffer(std::array<const T, N>& data) noexcept
1327 {
1328  return detail::buffer_contiguous_sequence(data);
1329 }
1330 template <class T, size_t N>
1331 const_buffer buffer(std::array<const T, N>& data, size_t n_bytes) noexcept
1332 {
1333  return detail::buffer_contiguous_sequence(data, n_bytes);
1334 }
1335 template <class T, size_t N>
1336 const_buffer buffer(const std::array<T, N>& data) noexcept
1337 {
1338  return detail::buffer_contiguous_sequence(data);
1339 }
1340 template <class T, size_t N>
1341 const_buffer buffer(const std::array<T, N>& data, size_t n_bytes) noexcept
1342 {
1343  return detail::buffer_contiguous_sequence(data, n_bytes);
1344 }
1345 // std::vector
1346 template <class T, class Allocator>
1347 mutable_buffer buffer(std::vector<T, Allocator>& data) noexcept
1348 {
1349  return detail::buffer_contiguous_sequence(data);
1350 }
1351 template <class T, class Allocator>
1352 mutable_buffer buffer(std::vector<T, Allocator>& data, size_t n_bytes) noexcept
1353 {
1354  return detail::buffer_contiguous_sequence(data, n_bytes);
1355 }
1356 template <class T, class Allocator>
1357 const_buffer buffer(const std::vector<T, Allocator>& data) noexcept
1358 {
1359  return detail::buffer_contiguous_sequence(data);
1360 }
1361 template <class T, class Allocator>
1362 const_buffer buffer(const std::vector<T, Allocator>& data, size_t n_bytes) noexcept
1363 {
1364  return detail::buffer_contiguous_sequence(data, n_bytes);
1365 }
1366 // std::basic_string
1367 template <class T, class Traits, class Allocator>
1368 mutable_buffer buffer(std::basic_string<T, Traits, Allocator>& data) noexcept
1369 {
1370  return detail::buffer_contiguous_sequence(data);
1371 }
1372 template <class T, class Traits, class Allocator>
1373 mutable_buffer buffer(std::basic_string<T, Traits, Allocator>& data,
1374  size_t n_bytes) noexcept
1375 {
1376  return detail::buffer_contiguous_sequence(data, n_bytes);
1377 }
1378 template <class T, class Traits, class Allocator>
1379 const_buffer buffer(const std::basic_string<T, Traits, Allocator>& data) noexcept
1380 {
1381  return detail::buffer_contiguous_sequence(data);
1382 }
1383 template <class T, class Traits, class Allocator>
1384 const_buffer buffer(const std::basic_string<T, Traits, Allocator>& data,
1385  size_t n_bytes) noexcept
1386 {
1387  return detail::buffer_contiguous_sequence(data, n_bytes);
1388 }
1389 
1390 #if CPPZMQ_HAS_STRING_VIEW
1391 // std::basic_string_view
1392 template <class T, class Traits>
1393 const_buffer buffer(std::basic_string_view<T, Traits> data) noexcept
1394 {
1395  return detail::buffer_contiguous_sequence(data);
1396 }
1397 template <class T, class Traits>
1398 const_buffer buffer(std::basic_string_view<T, Traits> data, size_t n_bytes) noexcept
1399 {
1400  return detail::buffer_contiguous_sequence(data, n_bytes);
1401 }
1402 #endif
1403 
1404 // Buffer for a string literal (null terminated)
1405 // where the buffer size excludes the terminating character.
1406 // Equivalent to zmq::buffer(std::string_view("...")).
1407 template <class Char, size_t N>
1408 constexpr const_buffer str_buffer(const Char (&data)[N]) noexcept
1409 {
1410  static_assert(detail::is_pod_like<Char>::value, "Char must be POD");
1411 #ifdef ZMQ_EXTENDED_CONSTEXPR
1412  assert(data[N - 1] == Char{ 0 });
1413 #endif
1414  return const_buffer(static_cast<const Char*>(data), (N - 1) * sizeof(Char));
1415 }
1416 
1417 namespace literals
1418 {
1419 constexpr const_buffer operator"" _zbuf(const char* str, size_t len) noexcept
1420 {
1421  return const_buffer(str, len * sizeof(char));
1422 }
1423 constexpr const_buffer operator"" _zbuf(const wchar_t* str, size_t len) noexcept
1424 {
1425  return const_buffer(str, len * sizeof(wchar_t));
1426 }
1427 constexpr const_buffer operator"" _zbuf(const char16_t* str, size_t len) noexcept
1428 {
1429  return const_buffer(str, len * sizeof(char16_t));
1430 }
1431 constexpr const_buffer operator"" _zbuf(const char32_t* str, size_t len) noexcept
1432 {
1433  return const_buffer(str, len * sizeof(char32_t));
1434 }
1435 } // namespace literals
1436 
1437 #endif // ZMQ_CPP11
1438 
1439 #ifdef ZMQ_CPP11
1440 namespace sockopt
1441 {
1442 // There are two types of options,
1443 // integral type with known compiler time size (int, bool, int64_t, uint64_t)
1444 // and arrays with dynamic size (strings, binary data).
1445 
1446 // BoolUnit: if true accepts values of type bool (but passed as T into libzmq)
1447 template <int Opt, class T, bool BoolUnit = false>
1448 struct integral_option
1449 {
1450 };
1451 
1452 // NullTerm:
1453 // 0: binary data
1454 // 1: null-terminated string (`getsockopt` size includes null)
1455 // 2: binary (size 32) or Z85 encoder string of size 41 (null included)
1456 template <int Opt, int NullTerm = 1>
1457 struct array_option
1458 {
1459 };
1460 
1461 #define ZMQ_DEFINE_INTEGRAL_OPT(OPT, NAME, TYPE) \
1462  using NAME##_t = integral_option<OPT, TYPE, false>; \
1463  ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME \
1464  {}
1465 #define ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(OPT, NAME, TYPE) \
1466  using NAME##_t = integral_option<OPT, TYPE, true>; \
1467  ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME \
1468  {}
1469 #define ZMQ_DEFINE_ARRAY_OPT(OPT, NAME) \
1470  using NAME##_t = array_option<OPT>; \
1471  ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME \
1472  {}
1473 #define ZMQ_DEFINE_ARRAY_OPT_BINARY(OPT, NAME) \
1474  using NAME##_t = array_option<OPT, 0>; \
1475  ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME \
1476  {}
1477 #define ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(OPT, NAME) \
1478  using NAME##_t = array_option<OPT, 2>; \
1479  ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME \
1480  {}
1481 
1482 // duplicate definition from libzmq 4.3.3
1483 #if defined _WIN32
1484 #if defined _WIN64
1485 typedef unsigned __int64 cppzmq_fd_t;
1486 #else
1487 typedef unsigned int cppzmq_fd_t;
1488 #endif
1489 #else
1490 typedef int cppzmq_fd_t;
1491 #endif
1492 
1493 #ifdef ZMQ_AFFINITY
1494 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_AFFINITY, affinity, uint64_t);
1495 #endif
1496 #ifdef ZMQ_BACKLOG
1497 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_BACKLOG, backlog, int);
1498 #endif
1499 #ifdef ZMQ_BINDTODEVICE
1500 ZMQ_DEFINE_ARRAY_OPT_BINARY(ZMQ_BINDTODEVICE, bindtodevice);
1501 #endif
1502 #ifdef ZMQ_CONFLATE
1503 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_CONFLATE, conflate, int);
1504 #endif
1505 #ifdef ZMQ_CONNECT_ROUTING_ID
1506 ZMQ_DEFINE_ARRAY_OPT(ZMQ_CONNECT_ROUTING_ID, connect_routing_id);
1507 #endif
1508 #ifdef ZMQ_CONNECT_TIMEOUT
1509 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_CONNECT_TIMEOUT, connect_timeout, int);
1510 #endif
1511 #ifdef ZMQ_CURVE_PUBLICKEY
1512 ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_PUBLICKEY, curve_publickey);
1513 #endif
1514 #ifdef ZMQ_CURVE_SECRETKEY
1515 ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_SECRETKEY, curve_secretkey);
1516 #endif
1517 #ifdef ZMQ_CURVE_SERVER
1518 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_CURVE_SERVER, curve_server, int);
1519 #endif
1520 #ifdef ZMQ_CURVE_SERVERKEY
1521 ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_SERVERKEY, curve_serverkey);
1522 #endif
1523 #ifdef ZMQ_EVENTS
1524 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_EVENTS, events, int);
1525 #endif
1526 #ifdef ZMQ_FD
1527 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_FD, fd, cppzmq_fd_t);
1528 #endif
1529 #ifdef ZMQ_GSSAPI_PLAINTEXT
1530 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_GSSAPI_PLAINTEXT, gssapi_plaintext, int);
1531 #endif
1532 #ifdef ZMQ_GSSAPI_SERVER
1533 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_GSSAPI_SERVER, gssapi_server, int);
1534 #endif
1535 #ifdef ZMQ_GSSAPI_SERVICE_PRINCIPAL
1536 ZMQ_DEFINE_ARRAY_OPT(ZMQ_GSSAPI_SERVICE_PRINCIPAL, gssapi_service_principal);
1537 #endif
1538 #ifdef ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE
1539 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE,
1540  gssapi_service_principal_nametype, int);
1541 #endif
1542 #ifdef ZMQ_GSSAPI_PRINCIPAL
1543 ZMQ_DEFINE_ARRAY_OPT(ZMQ_GSSAPI_PRINCIPAL, gssapi_principal);
1544 #endif
1545 #ifdef ZMQ_GSSAPI_PRINCIPAL_NAMETYPE
1546 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_GSSAPI_PRINCIPAL_NAMETYPE, gssapi_principal_nametype, int);
1547 #endif
1548 #ifdef ZMQ_HANDSHAKE_IVL
1549 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HANDSHAKE_IVL, handshake_ivl, int);
1550 #endif
1551 #ifdef ZMQ_HEARTBEAT_IVL
1552 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_IVL, heartbeat_ivl, int);
1553 #endif
1554 #ifdef ZMQ_HEARTBEAT_TIMEOUT
1555 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_TIMEOUT, heartbeat_timeout, int);
1556 #endif
1557 #ifdef ZMQ_HEARTBEAT_TTL
1558 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_TTL, heartbeat_ttl, int);
1559 #endif
1560 #ifdef ZMQ_IMMEDIATE
1561 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_IMMEDIATE, immediate, int);
1562 #endif
1563 #ifdef ZMQ_INVERT_MATCHING
1564 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_INVERT_MATCHING, invert_matching, int);
1565 #endif
1566 #ifdef ZMQ_IPV6
1567 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_IPV6, ipv6, int);
1568 #endif
1569 #ifdef ZMQ_LAST_ENDPOINT
1570 ZMQ_DEFINE_ARRAY_OPT(ZMQ_LAST_ENDPOINT, last_endpoint);
1571 #endif
1572 #ifdef ZMQ_LINGER
1573 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_LINGER, linger, int);
1574 #endif
1575 #ifdef ZMQ_MAXMSGSIZE
1576 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MAXMSGSIZE, maxmsgsize, int64_t);
1577 #endif
1578 #ifdef ZMQ_MECHANISM
1579 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MECHANISM, mechanism, int);
1580 #endif
1581 #ifdef ZMQ_METADATA
1582 ZMQ_DEFINE_ARRAY_OPT(ZMQ_METADATA, metadata);
1583 #endif
1584 #ifdef ZMQ_MULTICAST_HOPS
1585 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MULTICAST_HOPS, multicast_hops, int);
1586 #endif
1587 #ifdef ZMQ_MULTICAST_LOOP
1588 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_MULTICAST_LOOP, multicast_loop, int);
1589 #endif
1590 #ifdef ZMQ_MULTICAST_MAXTPDU
1591 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MULTICAST_MAXTPDU, multicast_maxtpdu, int);
1592 #endif
1593 #ifdef ZMQ_PLAIN_SERVER
1594 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_PLAIN_SERVER, plain_server, int);
1595 #endif
1596 #ifdef ZMQ_PLAIN_PASSWORD
1597 ZMQ_DEFINE_ARRAY_OPT(ZMQ_PLAIN_PASSWORD, plain_password);
1598 #endif
1599 #ifdef ZMQ_PLAIN_USERNAME
1600 ZMQ_DEFINE_ARRAY_OPT(ZMQ_PLAIN_USERNAME, plain_username);
1601 #endif
1602 #ifdef ZMQ_USE_FD
1603 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_USE_FD, use_fd, int);
1604 #endif
1605 #ifdef ZMQ_PROBE_ROUTER
1606 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_PROBE_ROUTER, probe_router, int);
1607 #endif
1608 #ifdef ZMQ_RATE
1609 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RATE, rate, int);
1610 #endif
1611 #ifdef ZMQ_RCVBUF
1612 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVBUF, rcvbuf, int);
1613 #endif
1614 #ifdef ZMQ_RCVHWM
1615 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVHWM, rcvhwm, int);
1616 #endif
1617 #ifdef ZMQ_RCVMORE
1618 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_RCVMORE, rcvmore, int);
1619 #endif
1620 #ifdef ZMQ_RCVTIMEO
1621 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVTIMEO, rcvtimeo, int);
1622 #endif
1623 #ifdef ZMQ_RECONNECT_IVL
1624 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECONNECT_IVL, reconnect_ivl, int);
1625 #endif
1626 #ifdef ZMQ_RECONNECT_IVL_MAX
1627 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECONNECT_IVL_MAX, reconnect_ivl_max, int);
1628 #endif
1629 #ifdef ZMQ_RECOVERY_IVL
1630 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECOVERY_IVL, recovery_ivl, int);
1631 #endif
1632 #ifdef ZMQ_REQ_CORRELATE
1633 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_REQ_CORRELATE, req_correlate, int);
1634 #endif
1635 #ifdef ZMQ_REQ_RELAXED
1636 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_REQ_RELAXED, req_relaxed, int);
1637 #endif
1638 #ifdef ZMQ_ROUTER_HANDOVER
1639 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ROUTER_HANDOVER, router_handover, int);
1640 #endif
1641 #ifdef ZMQ_ROUTER_MANDATORY
1642 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ROUTER_MANDATORY, router_mandatory, int);
1643 #endif
1644 #ifdef ZMQ_ROUTER_NOTIFY
1645 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_ROUTER_NOTIFY, router_notify, int);
1646 #endif
1647 #ifdef ZMQ_ROUTING_ID
1648 ZMQ_DEFINE_ARRAY_OPT_BINARY(ZMQ_ROUTING_ID, routing_id);
1649 #endif
1650 #ifdef ZMQ_SNDBUF
1651 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDBUF, sndbuf, int);
1652 #endif
1653 #ifdef ZMQ_SNDHWM
1654 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDHWM, sndhwm, int);
1655 #endif
1656 #ifdef ZMQ_SNDTIMEO
1657 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDTIMEO, sndtimeo, int);
1658 #endif
1659 #ifdef ZMQ_SOCKS_PROXY
1660 ZMQ_DEFINE_ARRAY_OPT(ZMQ_SOCKS_PROXY, socks_proxy);
1661 #endif
1662 #ifdef ZMQ_STREAM_NOTIFY
1663 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_STREAM_NOTIFY, stream_notify, int);
1664 #endif
1665 #ifdef ZMQ_SUBSCRIBE
1666 ZMQ_DEFINE_ARRAY_OPT(ZMQ_SUBSCRIBE, subscribe);
1667 #endif
1668 #ifdef ZMQ_TCP_KEEPALIVE
1669 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE, tcp_keepalive, int);
1670 #endif
1671 #ifdef ZMQ_TCP_KEEPALIVE_CNT
1672 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_CNT, tcp_keepalive_cnt, int);
1673 #endif
1674 #ifdef ZMQ_TCP_KEEPALIVE_IDLE
1675 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_IDLE, tcp_keepalive_idle, int);
1676 #endif
1677 #ifdef ZMQ_TCP_KEEPALIVE_INTVL
1678 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_INTVL, tcp_keepalive_intvl, int);
1679 #endif
1680 #ifdef ZMQ_TCP_MAXRT
1681 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_MAXRT, tcp_maxrt, int);
1682 #endif
1683 #ifdef ZMQ_THREAD_SAFE
1684 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_THREAD_SAFE, thread_safe, int);
1685 #endif
1686 #ifdef ZMQ_TOS
1687 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TOS, tos, int);
1688 #endif
1689 #ifdef ZMQ_TYPE
1690 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TYPE, type, int);
1691 #endif
1692 #ifdef ZMQ_UNSUBSCRIBE
1693 ZMQ_DEFINE_ARRAY_OPT(ZMQ_UNSUBSCRIBE, unsubscribe);
1694 #endif
1695 #ifdef ZMQ_VMCI_BUFFER_SIZE
1696 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_SIZE, vmci_buffer_size, uint64_t);
1697 #endif
1698 #ifdef ZMQ_VMCI_BUFFER_MIN_SIZE
1699 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_MIN_SIZE, vmci_buffer_min_size, uint64_t);
1700 #endif
1701 #ifdef ZMQ_VMCI_BUFFER_MAX_SIZE
1702 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_MAX_SIZE, vmci_buffer_max_size, uint64_t);
1703 #endif
1704 #ifdef ZMQ_VMCI_CONNECT_TIMEOUT
1705 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_CONNECT_TIMEOUT, vmci_connect_timeout, int);
1706 #endif
1707 #ifdef ZMQ_XPUB_VERBOSE
1708 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_VERBOSE, xpub_verbose, int);
1709 #endif
1710 #ifdef ZMQ_XPUB_VERBOSER
1711 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_VERBOSER, xpub_verboser, int);
1712 #endif
1713 #ifdef ZMQ_XPUB_MANUAL
1714 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_MANUAL, xpub_manual, int);
1715 #endif
1716 #ifdef ZMQ_XPUB_NODROP
1717 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_NODROP, xpub_nodrop, int);
1718 #endif
1719 #ifdef ZMQ_XPUB_WELCOME_MSG
1720 ZMQ_DEFINE_ARRAY_OPT(ZMQ_XPUB_WELCOME_MSG, xpub_welcome_msg);
1721 #endif
1722 #ifdef ZMQ_ZAP_ENFORCE_DOMAIN
1723 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ZAP_ENFORCE_DOMAIN, zap_enforce_domain, int);
1724 #endif
1725 #ifdef ZMQ_ZAP_DOMAIN
1726 ZMQ_DEFINE_ARRAY_OPT(ZMQ_ZAP_DOMAIN, zap_domain);
1727 #endif
1728 
1729 } // namespace sockopt
1730 #endif // ZMQ_CPP11
1731 
1732 namespace detail
1733 {
1734 class socket_base
1735 {
1736 public:
1738  {}
1739  ZMQ_EXPLICIT socket_base(void* handle) ZMQ_NOTHROW : _handle(handle)
1740  {}
1741 
1742  template <typename T>
1743  ZMQ_CPP11_DEPRECATED("from 4.7.0, use `set` taking option from zmq::sockopt")
1744  void setsockopt(int option_, T const& optval)
1745  {
1746  setsockopt(option_, &optval, sizeof(T));
1747  }
1748 
1749  ZMQ_CPP11_DEPRECATED("from 4.7.0, use `set` taking option from zmq::sockopt")
1750  void setsockopt(int option_, const void* optval_, size_t optvallen_)
1751  {
1752  int rc = zmq_setsockopt(_handle, option_, optval_, optvallen_);
1753  if(rc != 0)
1754  throw error_t();
1755  }
1756 
1757  ZMQ_CPP11_DEPRECATED("from 4.7.0, use `get` taking option from zmq::sockopt")
1758  void getsockopt(int option_, void* optval_, size_t* optvallen_) const
1759  {
1760  int rc = zmq_getsockopt(_handle, option_, optval_, optvallen_);
1761  if(rc != 0)
1762  throw error_t();
1763  }
1764 
1765  template <typename T>
1766  ZMQ_CPP11_DEPRECATED("from 4.7.0, use `get` taking option from zmq::sockopt")
1767  T getsockopt(int option_) const
1768  {
1769  T optval;
1770  size_t optlen = sizeof(T);
1771  getsockopt(option_, &optval, &optlen);
1772  return optval;
1773  }
1774 
1775 #ifdef ZMQ_CPP11
1776  // Set integral socket option, e.g.
1777  // `socket.set(zmq::sockopt::linger, 0)`
1778  template <int Opt, class T, bool BoolUnit>
1779  void set(sockopt::integral_option<Opt, T, BoolUnit>, const T& val)
1780  {
1781  static_assert(std::is_integral<T>::value, "T must be integral");
1782  set_option(Opt, &val, sizeof val);
1783  }
1784 
1785  // Set integral socket option from boolean, e.g.
1786  // `socket.set(zmq::sockopt::immediate, false)`
1787  template <int Opt, class T>
1788  void set(sockopt::integral_option<Opt, T, true>, bool val)
1789  {
1790  static_assert(std::is_integral<T>::value, "T must be integral");
1791  T rep_val = val;
1792  set_option(Opt, &rep_val, sizeof rep_val);
1793  }
1794 
1795  // Set array socket option, e.g.
1796  // `socket.set(zmq::sockopt::plain_username, "foo123")`
1797  template <int Opt, int NullTerm>
1798  void set(sockopt::array_option<Opt, NullTerm>, const char* buf)
1799  {
1800  set_option(Opt, buf, std::strlen(buf));
1801  }
1802 
1803  // Set array socket option, e.g.
1804  // `socket.set(zmq::sockopt::routing_id, zmq::buffer(id))`
1805  template <int Opt, int NullTerm>
1806  void set(sockopt::array_option<Opt, NullTerm>, const_buffer buf)
1807  {
1808  set_option(Opt, buf.data(), buf.size());
1809  }
1810 
1811  // Set array socket option, e.g.
1812  // `socket.set(zmq::sockopt::routing_id, id_str)`
1813  template <int Opt, int NullTerm>
1814  void set(sockopt::array_option<Opt, NullTerm>, const std::string& buf)
1815  {
1816  set_option(Opt, buf.data(), buf.size());
1817  }
1818 
1819 #if CPPZMQ_HAS_STRING_VIEW
1820  // Set array socket option, e.g.
1821  // `socket.set(zmq::sockopt::routing_id, id_str)`
1822  template <int Opt, int NullTerm>
1823  void set(sockopt::array_option<Opt, NullTerm>, std::string_view buf)
1824  {
1825  set_option(Opt, buf.data(), buf.size());
1826  }
1827 #endif
1828 
1829  // Get scalar socket option, e.g.
1830  // `auto opt = socket.get(zmq::sockopt::linger)`
1831  template <int Opt, class T, bool BoolUnit>
1832  ZMQ_NODISCARD T get(sockopt::integral_option<Opt, T, BoolUnit>) const
1833  {
1834  static_assert(std::is_integral<T>::value, "T must be integral");
1835  T val;
1836  size_t size = sizeof val;
1837  get_option(Opt, &val, &size);
1838  assert(size == sizeof val);
1839  return val;
1840  }
1841 
1842  // Get array socket option, writes to buf, returns option size in bytes, e.g.
1843  // `size_t optsize = socket.get(zmq::sockopt::routing_id, zmq::buffer(id))`
1844  template <int Opt, int NullTerm>
1845  ZMQ_NODISCARD size_t get(sockopt::array_option<Opt, NullTerm>, mutable_buffer buf) const
1846  {
1847  size_t size = buf.size();
1848  get_option(Opt, buf.data(), &size);
1849  return size;
1850  }
1851 
1852  // Get array socket option as string (initializes the string buffer size to init_size) e.g.
1853  // `auto s = socket.get(zmq::sockopt::routing_id)`
1854  // Note: removes the null character from null-terminated string options,
1855  // i.e. the string size excludes the null character.
1856  template <int Opt, int NullTerm>
1857  ZMQ_NODISCARD std::string get(sockopt::array_option<Opt, NullTerm>,
1858  size_t init_size = 1024) const
1859  {
1860  if(NullTerm == 2 && init_size == 1024)
1861  {
1862  init_size = 41; // get as Z85 string
1863  }
1864  std::string str(init_size, '\0');
1865  size_t size = get(sockopt::array_option<Opt>{}, buffer(str));
1866  if(NullTerm == 1)
1867  {
1868  if(size > 0)
1869  {
1870  assert(str[size - 1] == '\0');
1871  --size;
1872  }
1873  }
1874  else if(NullTerm == 2)
1875  {
1876  assert(size == 32 || size == 41);
1877  if(size == 41)
1878  {
1879  assert(str[size - 1] == '\0');
1880  --size;
1881  }
1882  }
1883  str.resize(size);
1884  return str;
1885  }
1886 #endif
1887 
1888  void bind(std::string const& addr)
1889  {
1890  bind(addr.c_str());
1891  }
1892 
1893  void bind(const char* addr_)
1894  {
1895  int rc = zmq_bind(_handle, addr_);
1896  if(rc != 0)
1897  throw error_t();
1898  }
1899 
1900  void unbind(std::string const& addr)
1901  {
1902  unbind(addr.c_str());
1903  }
1904 
1905  void unbind(const char* addr_)
1906  {
1907  int rc = zmq_unbind(_handle, addr_);
1908  if(rc != 0)
1909  throw error_t();
1910  }
1911 
1912  void connect(std::string const& addr)
1913  {
1914  connect(addr.c_str());
1915  }
1916 
1917  void connect(const char* addr_)
1918  {
1919  int rc = zmq_connect(_handle, addr_);
1920  if(rc != 0)
1921  throw error_t();
1922  }
1923 
1924  void disconnect(std::string const& addr)
1925  {
1926  disconnect(addr.c_str());
1927  }
1928 
1929  void disconnect(const char* addr_)
1930  {
1931  int rc = zmq_disconnect(_handle, addr_);
1932  if(rc != 0)
1933  throw error_t();
1934  }
1935 
1936  bool connected() const ZMQ_NOTHROW
1937  {
1938  return (_handle != ZMQ_NULLPTR);
1939  }
1940 
1941  ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking a const_buffer and send_flags")
1942  size_t send(const void* buf_, size_t len_, int flags_ = 0)
1943  {
1944  int nbytes = zmq_send(_handle, buf_, len_, flags_);
1945  if(nbytes >= 0)
1946  return static_cast<size_t>(nbytes);
1947  if(zmq_errno() == EAGAIN)
1948  return 0;
1949  throw error_t();
1950  }
1951 
1952  ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking message_t and send_flags")
1953  bool send(message_t& msg_,
1954  int flags_ = 0) // default until removed
1955  {
1956  int nbytes = zmq_msg_send(msg_.handle(), _handle, flags_);
1957  if(nbytes >= 0)
1958  return true;
1959  if(zmq_errno() == EAGAIN)
1960  return false;
1961  throw error_t();
1962  }
1963 
1964  template <typename T>
1965  ZMQ_CPP11_DEPRECATED("from 4.4.1, use send taking message_t or buffer (for contiguous "
1966  "ranges), and send_flags")
1967  bool send(T first, T last, int flags_ = 0)
1968  {
1969  zmq::message_t msg(first, last);
1970  int nbytes = zmq_msg_send(msg.handle(), _handle, flags_);
1971  if(nbytes >= 0)
1972  return true;
1973  if(zmq_errno() == EAGAIN)
1974  return false;
1975  throw error_t();
1976  }
1977 
1978 #ifdef ZMQ_HAS_RVALUE_REFS
1979  ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking message_t and send_flags")
1980  bool send(message_t&& msg_,
1981  int flags_ = 0) // default until removed
1982  {
1983 #ifdef ZMQ_CPP11
1984  return send(msg_, static_cast<send_flags>(flags_)).has_value();
1985 #else
1986  return send(msg_, flags_);
1987 #endif
1988  }
1989 #endif
1990 
1991 #ifdef ZMQ_CPP11
1992  send_result_t send(const_buffer buf, send_flags flags = send_flags::none)
1993  {
1994  const int nbytes = zmq_send(_handle, buf.data(), buf.size(), static_cast<int>(flags));
1995  if(nbytes >= 0)
1996  return static_cast<size_t>(nbytes);
1997  if(zmq_errno() == EAGAIN)
1998  return {};
1999  throw error_t();
2000  }
2001 
2002  send_result_t send(message_t& msg, send_flags flags)
2003  {
2004  int nbytes = zmq_msg_send(msg.handle(), _handle, static_cast<int>(flags));
2005  if(nbytes >= 0)
2006  return static_cast<size_t>(nbytes);
2007  if(zmq_errno() == EAGAIN)
2008  return {};
2009  throw error_t();
2010  }
2011 
2012  send_result_t send(message_t&& msg, send_flags flags)
2013  {
2014  return send(msg, flags);
2015  }
2016 #endif
2017 
2018  ZMQ_CPP11_DEPRECATED("from 4.3.1, use recv taking a mutable_buffer and recv_flags")
2019  size_t recv(void* buf_, size_t len_, int flags_ = 0)
2020  {
2021  int nbytes = zmq_recv(_handle, buf_, len_, flags_);
2022  if(nbytes >= 0)
2023  return static_cast<size_t>(nbytes);
2024  if(zmq_errno() == EAGAIN)
2025  return 0;
2026  throw error_t();
2027  }
2028 
2029  ZMQ_CPP11_DEPRECATED("from 4.3.1, use recv taking a reference to message_t and "
2030  "recv_flags")
2031  bool recv(message_t* msg_, int flags_ = 0)
2032  {
2033  int nbytes = zmq_msg_recv(msg_->handle(), _handle, flags_);
2034  if(nbytes >= 0)
2035  return true;
2036  if(zmq_errno() == EAGAIN)
2037  return false;
2038  throw error_t();
2039  }
2040 
2041 #ifdef ZMQ_CPP11
2043  recv_buffer_result_t recv(mutable_buffer buf, recv_flags flags = recv_flags::none)
2044  {
2045  const int nbytes = zmq_recv(_handle, buf.data(), buf.size(), static_cast<int>(flags));
2046  if(nbytes >= 0)
2047  {
2048  return recv_buffer_size{ (std::min)(static_cast<size_t>(nbytes), buf.size()),
2049  static_cast<size_t>(nbytes) };
2050  }
2051  if(zmq_errno() == EAGAIN)
2052  return {};
2053  throw error_t();
2054  }
2055 
2057  recv_result_t recv(message_t& msg, recv_flags flags = recv_flags::none)
2058  {
2059  const int nbytes = zmq_msg_recv(msg.handle(), _handle, static_cast<int>(flags));
2060  if(nbytes >= 0)
2061  {
2062  assert(msg.size() == static_cast<size_t>(nbytes));
2063  return static_cast<size_t>(nbytes);
2064  }
2065  if(zmq_errno() == EAGAIN)
2066  return {};
2067  throw error_t();
2068  }
2069 #endif
2070 
2071 #if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0)
2072  void join(const char* group)
2073  {
2074  int rc = zmq_join(_handle, group);
2075  if(rc != 0)
2076  throw error_t();
2077  }
2078 
2079  void leave(const char* group)
2080  {
2081  int rc = zmq_leave(_handle, group);
2082  if(rc != 0)
2083  throw error_t();
2084  }
2085 #endif
2086 
2087  ZMQ_NODISCARD void* handle() ZMQ_NOTHROW
2088  {
2089  return _handle;
2090  }
2091  ZMQ_NODISCARD const void* handle() const ZMQ_NOTHROW
2092  {
2093  return _handle;
2094  }
2095 
2096  ZMQ_EXPLICIT operator bool() const ZMQ_NOTHROW
2097  {
2098  return _handle != ZMQ_NULLPTR;
2099  }
2100  // note: non-const operator bool can be removed once
2101  // operator void* is removed from socket_t
2102  ZMQ_EXPLICIT operator bool() ZMQ_NOTHROW
2103  {
2104  return _handle != ZMQ_NULLPTR;
2105  }
2106 
2107 protected:
2108  void* _handle;
2109 
2110 private:
2111  void set_option(int option_, const void* optval_, size_t optvallen_)
2112  {
2113  int rc = zmq_setsockopt(_handle, option_, optval_, optvallen_);
2114  if(rc != 0)
2115  throw error_t();
2116  }
2117 
2118  void get_option(int option_, void* optval_, size_t* optvallen_) const
2119  {
2120  int rc = zmq_getsockopt(_handle, option_, optval_, optvallen_);
2121  if(rc != 0)
2122  throw error_t();
2123  }
2124 };
2125 } // namespace detail
2126 
2127 #ifdef ZMQ_CPP11
2128 enum class socket_type : int
2129 {
2130  req = ZMQ_REQ,
2131  rep = ZMQ_REP,
2132  dealer = ZMQ_DEALER,
2133  router = ZMQ_ROUTER,
2134  pub = ZMQ_PUB,
2135  sub = ZMQ_SUB,
2136  xpub = ZMQ_XPUB,
2137  xsub = ZMQ_XSUB,
2138  push = ZMQ_PUSH,
2139  pull = ZMQ_PULL,
2140 #if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0)
2141  server = ZMQ_SERVER,
2142  client = ZMQ_CLIENT,
2143  radio = ZMQ_RADIO,
2144  dish = ZMQ_DISH,
2145 #endif
2146 #if ZMQ_VERSION_MAJOR >= 4
2147  stream = ZMQ_STREAM,
2148 #endif
2149  pair = ZMQ_PAIR
2150 };
2151 #endif
2152 
2153 struct from_handle_t
2154 {
2155  struct _private
2156  {
2157  }; // disabling use other than with from_handle
2159  {}
2160 };
2161 
2162 ZMQ_CONSTEXPR_VAR from_handle_t from_handle = from_handle_t(from_handle_t::_private());
2163 
2164 // A non-owning nullable reference to a socket.
2165 // The reference is invalidated on socket close or destruction.
2166 class socket_ref : public detail::socket_base
2167 {
2168 public:
2170  {}
2171 #ifdef ZMQ_CPP11
2172  socket_ref(std::nullptr_t) ZMQ_NOTHROW : detail::socket_base()
2173  {}
2174 #endif
2176  {}
2177 };
2178 
2179 #ifdef ZMQ_CPP11
2180 inline bool operator==(socket_ref sr, std::nullptr_t /*p*/) ZMQ_NOTHROW
2181 {
2182  return sr.handle() == nullptr;
2183 }
2184 inline bool operator==(std::nullptr_t /*p*/, socket_ref sr) ZMQ_NOTHROW
2185 {
2186  return sr.handle() == nullptr;
2187 }
2188 inline bool operator!=(socket_ref sr, std::nullptr_t /*p*/) ZMQ_NOTHROW
2189 {
2190  return !(sr == nullptr);
2191 }
2192 inline bool operator!=(std::nullptr_t /*p*/, socket_ref sr) ZMQ_NOTHROW
2193 {
2194  return !(sr == nullptr);
2195 }
2196 #endif
2197 
2199 {
2200  return std::equal_to<void*>()(a.handle(), b.handle());
2201 }
2203 {
2204  return !(a == b);
2205 }
2207 {
2208  return std::less<void*>()(a.handle(), b.handle());
2209 }
2211 {
2212  return b < a;
2213 }
2215 {
2216  return !(a > b);
2217 }
2219 {
2220  return !(a < b);
2221 }
2222 
2223 } // namespace zmq
2224 
2225 #ifdef ZMQ_CPP11
2226 namespace std
2227 {
2228 template <>
2229 struct hash<zmq::socket_ref>
2230 {
2231  size_t operator()(zmq::socket_ref sr) const ZMQ_NOTHROW
2232  {
2233  return hash<void*>()(sr.handle());
2234  }
2235 };
2236 } // namespace std
2237 #endif
2238 
2239 namespace zmq
2240 {
2241 class socket_t : public detail::socket_base
2242 {
2243  friend class monitor_t;
2244 
2245 public:
2247  {}
2248 
2249  socket_t(context_t& context_, int type_)
2250  : detail::socket_base(zmq_socket(context_.handle(), type_)), ctxptr(context_.handle())
2251  {
2252  if(_handle == ZMQ_NULLPTR)
2253  throw error_t();
2254  }
2255 
2256 #ifdef ZMQ_CPP11
2257  socket_t(context_t& context_, socket_type type_)
2258  : socket_t(context_, static_cast<int>(type_))
2259  {}
2260 #endif
2261 
2262 #ifdef ZMQ_HAS_RVALUE_REFS
2263  socket_t(socket_t&& rhs) ZMQ_NOTHROW : detail::socket_base(rhs._handle),
2264  ctxptr(rhs.ctxptr)
2265  {
2266  rhs._handle = ZMQ_NULLPTR;
2267  rhs.ctxptr = ZMQ_NULLPTR;
2268  }
2270  {
2271  close();
2272  std::swap(_handle, rhs._handle);
2273  std::swap(ctxptr, rhs.ctxptr);
2274  return *this;
2275  }
2276 #endif
2277 
2279  {
2280  close();
2281  }
2282 
2283  operator void*() ZMQ_NOTHROW
2284  {
2285  return _handle;
2286  }
2287 
2288  operator void const*() const ZMQ_NOTHROW
2289  {
2290  return _handle;
2291  }
2292 
2294  {
2295  if(_handle == ZMQ_NULLPTR)
2296  // already closed
2297  return;
2298  int rc = zmq_close(_handle);
2299  ZMQ_ASSERT(rc == 0);
2300  _handle = ZMQ_NULLPTR;
2301  ctxptr = ZMQ_NULLPTR;
2302  }
2303 
2305  {
2306  std::swap(_handle, other._handle);
2307  std::swap(ctxptr, other.ctxptr);
2308  }
2309 
2311  {
2312  return socket_ref(from_handle, _handle);
2313  }
2314 
2315 private:
2316  void* ctxptr;
2317 
2320 
2321  // used by monitor_t
2322  socket_t(void* context_, int type_)
2323  : detail::socket_base(zmq_socket(context_, type_)), ctxptr(context_)
2324  {
2325  if(_handle == ZMQ_NULLPTR)
2326  throw error_t();
2327  if(ctxptr == ZMQ_NULLPTR)
2328  throw error_t();
2329  }
2330 };
2331 
2332 inline void swap(socket_t& a, socket_t& b) ZMQ_NOTHROW
2333 {
2334  a.swap(b);
2335 }
2336 
2337 ZMQ_DEPRECATED("from 4.3.1, use proxy taking socket_t objects")
2338 inline void proxy(void* frontend, void* backend, void* capture)
2339 {
2340  int rc = zmq_proxy(frontend, backend, capture);
2341  if(rc != 0)
2342  throw error_t();
2343 }
2344 
2345 inline void proxy(socket_ref frontend, socket_ref backend,
2346  socket_ref capture = socket_ref())
2347 {
2348  int rc = zmq_proxy(frontend.handle(), backend.handle(), capture.handle());
2349  if(rc != 0)
2350  throw error_t();
2351 }
2352 
2353 #ifdef ZMQ_HAS_PROXY_STEERABLE
2354 ZMQ_DEPRECATED("from 4.3.1, use proxy_steerable taking socket_t objects")
2355 inline void proxy_steerable(void* frontend, void* backend, void* capture, void* control)
2356 {
2357  int rc = zmq_proxy_steerable(frontend, backend, capture, control);
2358  if(rc != 0)
2359  throw error_t();
2360 }
2361 
2362 inline void proxy_steerable(socket_ref frontend, socket_ref backend, socket_ref capture,
2363  socket_ref control)
2364 {
2365  int rc = zmq_proxy_steerable(frontend.handle(), backend.handle(), capture.handle(),
2366  control.handle());
2367  if(rc != 0)
2368  throw error_t();
2369 }
2370 #endif
2371 
2372 class monitor_t
2373 {
2374 public:
2376  {}
2377 
2378  virtual ~monitor_t()
2379  {
2380  close();
2381  }
2382 
2383 #ifdef ZMQ_HAS_RVALUE_REFS
2385  {
2386  std::swap(_socket, rhs._socket);
2387  std::swap(_monitor_socket, rhs._monitor_socket);
2388  }
2389 
2391  {
2392  close();
2393  _socket = socket_ref();
2394  std::swap(_socket, rhs._socket);
2395  std::swap(_monitor_socket, rhs._monitor_socket);
2396  return *this;
2397  }
2398 #endif
2399 
2400  void monitor(socket_t& socket, std::string const& addr, int events = ZMQ_EVENT_ALL)
2401  {
2402  monitor(socket, addr.c_str(), events);
2403  }
2404 
2405  void monitor(socket_t& socket, const char* addr_, int events = ZMQ_EVENT_ALL)
2406  {
2407  init(socket, addr_, events);
2408  while(true)
2409  {
2410  check_event(-1);
2411  }
2412  }
2413 
2414  void init(socket_t& socket, std::string const& addr, int events = ZMQ_EVENT_ALL)
2415  {
2416  init(socket, addr.c_str(), events);
2417  }
2418 
2419  void init(socket_t& socket, const char* addr_, int events = ZMQ_EVENT_ALL)
2420  {
2421  int rc = zmq_socket_monitor(socket.handle(), addr_, events);
2422  if(rc != 0)
2423  throw error_t();
2424 
2425  _socket = socket;
2426  _monitor_socket = socket_t(socket.ctxptr, ZMQ_PAIR);
2427  _monitor_socket.connect(addr_);
2428 
2430  }
2431 
2432  bool check_event(int timeout = 0)
2433  {
2434  assert(_monitor_socket);
2435 
2436  zmq_msg_t eventMsg;
2437  zmq_msg_init(&eventMsg);
2438 
2439  zmq::pollitem_t items[] = {
2440  { _monitor_socket.handle(), 0, ZMQ_POLLIN, 0 },
2441  };
2442 
2443  zmq::poll(&items[0], 1, timeout);
2444 
2445  if(items[0].revents & ZMQ_POLLIN)
2446  {
2447  int rc = zmq_msg_recv(&eventMsg, _monitor_socket.handle(), 0);
2448  if(rc == -1 && zmq_errno() == ETERM)
2449  return false;
2450  assert(rc != -1);
2451  }
2452  else
2453  {
2454  zmq_msg_close(&eventMsg);
2455  return false;
2456  }
2457 
2458 #if ZMQ_VERSION_MAJOR >= 4
2459  const char* data = static_cast<const char*>(zmq_msg_data(&eventMsg));
2460  zmq_event_t msgEvent;
2461  memcpy(&msgEvent.event, data, sizeof(uint16_t));
2462  data += sizeof(uint16_t);
2463  memcpy(&msgEvent.value, data, sizeof(int32_t));
2464  zmq_event_t* event = &msgEvent;
2465 #else
2466  zmq_event_t* event = static_cast<zmq_event_t*>(zmq_msg_data(&eventMsg));
2467 #endif
2468 
2469 #ifdef ZMQ_NEW_MONITOR_EVENT_LAYOUT
2470  zmq_msg_t addrMsg;
2471  zmq_msg_init(&addrMsg);
2472  int rc = zmq_msg_recv(&addrMsg, _monitor_socket.handle(), 0);
2473  if(rc == -1 && zmq_errno() == ETERM)
2474  {
2475  zmq_msg_close(&eventMsg);
2476  return false;
2477  }
2478 
2479  assert(rc != -1);
2480  const char* str = static_cast<const char*>(zmq_msg_data(&addrMsg));
2481  std::string address(str, str + zmq_msg_size(&addrMsg));
2482  zmq_msg_close(&addrMsg);
2483 #else
2484  // 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.
2485  std::string address = event->data.connected.addr;
2486 #endif
2487 
2488 #ifdef ZMQ_EVENT_MONITOR_STOPPED
2489  if(event->event == ZMQ_EVENT_MONITOR_STOPPED)
2490  {
2491  zmq_msg_close(&eventMsg);
2492  return false;
2493  }
2494 
2495 #endif
2496 
2497  switch(event->event)
2498  {
2499  case ZMQ_EVENT_CONNECTED:
2500  on_event_connected(*event, address.c_str());
2501  break;
2502  case ZMQ_EVENT_CONNECT_DELAYED:
2503  on_event_connect_delayed(*event, address.c_str());
2504  break;
2505  case ZMQ_EVENT_CONNECT_RETRIED:
2506  on_event_connect_retried(*event, address.c_str());
2507  break;
2508  case ZMQ_EVENT_LISTENING:
2509  on_event_listening(*event, address.c_str());
2510  break;
2511  case ZMQ_EVENT_BIND_FAILED:
2512  on_event_bind_failed(*event, address.c_str());
2513  break;
2514  case ZMQ_EVENT_ACCEPTED:
2515  on_event_accepted(*event, address.c_str());
2516  break;
2517  case ZMQ_EVENT_ACCEPT_FAILED:
2518  on_event_accept_failed(*event, address.c_str());
2519  break;
2520  case ZMQ_EVENT_CLOSED:
2521  on_event_closed(*event, address.c_str());
2522  break;
2523  case ZMQ_EVENT_CLOSE_FAILED:
2524  on_event_close_failed(*event, address.c_str());
2525  break;
2526  case ZMQ_EVENT_DISCONNECTED:
2527  on_event_disconnected(*event, address.c_str());
2528  break;
2529 #ifdef ZMQ_BUILD_DRAFT_API
2530 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3)
2531  case ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL:
2532  on_event_handshake_failed_no_detail(*event, address.c_str());
2533  break;
2534  case ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL:
2535  on_event_handshake_failed_protocol(*event, address.c_str());
2536  break;
2537  case ZMQ_EVENT_HANDSHAKE_FAILED_AUTH:
2538  on_event_handshake_failed_auth(*event, address.c_str());
2539  break;
2540  case ZMQ_EVENT_HANDSHAKE_SUCCEEDED:
2541  on_event_handshake_succeeded(*event, address.c_str());
2542  break;
2543 #elif ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 1)
2544  case ZMQ_EVENT_HANDSHAKE_FAILED:
2545  on_event_handshake_failed(*event, address.c_str());
2546  break;
2547  case ZMQ_EVENT_HANDSHAKE_SUCCEED:
2548  on_event_handshake_succeed(*event, address.c_str());
2549  break;
2550 #endif
2551 #endif
2552  default:
2553  on_event_unknown(*event, address.c_str());
2554  break;
2555  }
2556  zmq_msg_close(&eventMsg);
2557 
2558  return true;
2559  }
2560 
2561 #ifdef ZMQ_EVENT_MONITOR_STOPPED
2562  void abort()
2563  {
2564  if(_socket)
2565  zmq_socket_monitor(_socket.handle(), ZMQ_NULLPTR, 0);
2566 
2567  _socket = socket_ref();
2568  }
2569 #endif
2570  virtual void on_monitor_started()
2571  {}
2572  virtual void on_event_connected(const zmq_event_t& event_, const char* addr_)
2573  {
2574  (void)event_;
2575  (void)addr_;
2576  }
2577  virtual void on_event_connect_delayed(const zmq_event_t& event_, const char* addr_)
2578  {
2579  (void)event_;
2580  (void)addr_;
2581  }
2582  virtual void on_event_connect_retried(const zmq_event_t& event_, const char* addr_)
2583  {
2584  (void)event_;
2585  (void)addr_;
2586  }
2587  virtual void on_event_listening(const zmq_event_t& event_, const char* addr_)
2588  {
2589  (void)event_;
2590  (void)addr_;
2591  }
2592  virtual void on_event_bind_failed(const zmq_event_t& event_, const char* addr_)
2593  {
2594  (void)event_;
2595  (void)addr_;
2596  }
2597  virtual void on_event_accepted(const zmq_event_t& event_, const char* addr_)
2598  {
2599  (void)event_;
2600  (void)addr_;
2601  }
2602  virtual void on_event_accept_failed(const zmq_event_t& event_, const char* addr_)
2603  {
2604  (void)event_;
2605  (void)addr_;
2606  }
2607  virtual void on_event_closed(const zmq_event_t& event_, const char* addr_)
2608  {
2609  (void)event_;
2610  (void)addr_;
2611  }
2612  virtual void on_event_close_failed(const zmq_event_t& event_, const char* addr_)
2613  {
2614  (void)event_;
2615  (void)addr_;
2616  }
2617  virtual void on_event_disconnected(const zmq_event_t& event_, const char* addr_)
2618  {
2619  (void)event_;
2620  (void)addr_;
2621  }
2622 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3)
2624  const char* addr_)
2625  {
2626  (void)event_;
2627  (void)addr_;
2628  }
2630  const char* addr_)
2631  {
2632  (void)event_;
2633  (void)addr_;
2634  }
2635  virtual void on_event_handshake_failed_auth(const zmq_event_t& event_,
2636  const char* addr_)
2637  {
2638  (void)event_;
2639  (void)addr_;
2640  }
2641  virtual void on_event_handshake_succeeded(const zmq_event_t& event_, const char* addr_)
2642  {
2643  (void)event_;
2644  (void)addr_;
2645  }
2646 #elif ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 1)
2647  virtual void on_event_handshake_failed(const zmq_event_t& event_, const char* addr_)
2648  {
2649  (void)event_;
2650  (void)addr_;
2651  }
2652  virtual void on_event_handshake_succeed(const zmq_event_t& event_, const char* addr_)
2653  {
2654  (void)event_;
2655  (void)addr_;
2656  }
2657 #endif
2658  virtual void on_event_unknown(const zmq_event_t& event_, const char* addr_)
2659  {
2660  (void)event_;
2661  (void)addr_;
2662  }
2663 
2664 private:
2667 
2670 
2672  {
2673  if(_socket)
2674  zmq_socket_monitor(_socket.handle(), ZMQ_NULLPTR, 0);
2676  }
2677 };
2678 
2679 #if defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER)
2680 
2681 // polling events
2682 enum class event_flags : short
2683 {
2684  none = 0,
2685  pollin = ZMQ_POLLIN,
2686  pollout = ZMQ_POLLOUT,
2687  pollerr = ZMQ_POLLERR,
2688  pollpri = ZMQ_POLLPRI
2689 };
2690 
2691 constexpr event_flags operator|(event_flags a, event_flags b) noexcept
2692 {
2693  return detail::enum_bit_or(a, b);
2694 }
2695 constexpr event_flags operator&(event_flags a, event_flags b) noexcept
2696 {
2697  return detail::enum_bit_and(a, b);
2698 }
2699 constexpr event_flags operator^(event_flags a, event_flags b) noexcept
2700 {
2701  return detail::enum_bit_xor(a, b);
2702 }
2703 constexpr event_flags operator~(event_flags a) noexcept
2704 {
2705  return detail::enum_bit_not(a);
2706 }
2707 
2708 struct no_user_data;
2709 
2710 // layout compatible with zmq_poller_event_t
2711 template <class T = no_user_data>
2712 struct poller_event
2713 {
2714  socket_ref socket;
2715 #ifdef _WIN32
2716  SOCKET fd;
2717 #else
2718  int fd;
2719 #endif
2720  T* user_data;
2721  event_flags events;
2722 };
2723 
2724 template <typename T = no_user_data>
2725 class poller_t
2726 {
2727 public:
2728  using event_type = poller_event<T>;
2729 
2730  poller_t() : poller_ptr(zmq_poller_new())
2731  {
2732  if(!poller_ptr)
2733  throw error_t();
2734  }
2735 
2736  template <typename Dummy = void,
2738  Dummy>::type>
2739  void add(zmq::socket_ref socket, event_flags events, T* user_data)
2740  {
2741  add_impl(socket, events, user_data);
2742  }
2743 
2744  void add(zmq::socket_ref socket, event_flags events)
2745  {
2746  add_impl(socket, events, nullptr);
2747  }
2748 
2749  void remove(zmq::socket_ref socket)
2750  {
2751  if(0 != zmq_poller_remove(poller_ptr.get(), socket.handle()))
2752  {
2753  throw error_t();
2754  }
2755  }
2756 
2757  void modify(zmq::socket_ref socket, event_flags events)
2758  {
2759  if(0 !=
2760  zmq_poller_modify(poller_ptr.get(), socket.handle(), static_cast<short>(events)))
2761  {
2762  throw error_t();
2763  }
2764  }
2765 
2766  size_t wait_all(std::vector<event_type>& poller_events,
2767  const std::chrono::milliseconds timeout)
2768  {
2769  int rc = zmq_poller_wait_all(
2770  poller_ptr.get(), reinterpret_cast<zmq_poller_event_t*>(poller_events.data()),
2771  static_cast<int>(poller_events.size()), static_cast<long>(timeout.count()));
2772  if(rc > 0)
2773  return static_cast<size_t>(rc);
2774 
2775 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3)
2776  if(zmq_errno() == EAGAIN)
2777 #else
2778  if(zmq_errno() == ETIMEDOUT)
2779 #endif
2780  return 0;
2781 
2782  throw error_t();
2783  }
2784 
2785 private:
2786  struct destroy_poller_t
2787  {
2788  void operator()(void* ptr) noexcept
2789  {
2790  int rc = zmq_poller_destroy(&ptr);
2791  ZMQ_ASSERT(rc == 0);
2792  }
2793  };
2794 
2795  std::unique_ptr<void, destroy_poller_t> poller_ptr;
2796 
2797  void add_impl(zmq::socket_ref socket, event_flags events, T* user_data)
2798  {
2799  if(0 != zmq_poller_add(poller_ptr.get(), socket.handle(), user_data,
2800  static_cast<short>(events)))
2801  {
2802  throw error_t();
2803  }
2804  }
2805 };
2806 #endif // defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER)
2807 
2808 inline std::ostream& operator<<(std::ostream& os, const message_t& msg)
2809 {
2810  return os << msg.str();
2811 }
2812 
2813 } // namespace zmq
2814 
2815 #endif // __ZMQ_HPP_INCLUDED__
zmq_event_t
Definition: 3rdparty/cppzmq/zmq.hpp:207
cx::size
constexpr auto size(const C &c) -> decltype(c.size())
Definition: wildcards.hpp:636
zmq::monitor_t::on_monitor_started
virtual void on_monitor_started()
Definition: 3rdparty/cppzmq/zmq.hpp:2488
BT::enable_if
typename std::enable_if< Predicate::value >::type * enable_if
Definition: basic_types.h:305
zmq::message_t::handle
const ZMQ_NODISCARD zmq_msg_t * handle() const ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:733
zmq::socket_t::ctxptr
void * ctxptr
Definition: 3rdparty/cppzmq/zmq.hpp:2245
zmq::swap
void swap(message_t &a, message_t &b) ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:748
zmq::poll
int poll(zmq_pollitem_t *items_, size_t nitems_, long timeout_=-1)
Definition: 3rdparty/cppzmq/zmq.hpp:318
zmq::monitor_t::on_event_handshake_failed_auth
virtual void on_event_handshake_failed_auth(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2554
zmq::message_t::move
void move(message_t &msg_)
Definition: src/loggers/zmq.hpp:538
zmq::message_t
Definition: 3rdparty/cppzmq/zmq.hpp:408
zmq::from_handle_t
Definition: 3rdparty/cppzmq/zmq.hpp:2094
zmq::proxy
void proxy(void *frontend, void *backend, void *capture)
Definition: 3rdparty/cppzmq/zmq.hpp:2267
lexy::_unicode_db::uppercase
@ uppercase
Definition: unicode_database.hpp:72
zmq::monitor_t::monitor
void monitor(socket_t &socket, std::string const &addr, int events=ZMQ_EVENT_ALL)
Definition: src/loggers/zmq.hpp:2400
zmq::detail::socket_base::connected
bool connected() const ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:1936
zmq::socket_t::swap
void swap(socket_t &other) ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:2304
zmq::context_t::context_t
context_t()
Definition: src/loggers/zmq.hpp:801
zmq::monitor_t::on_event_handshake_failed_no_detail
virtual void on_event_handshake_failed_no_detail(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2542
zmq::monitor_t::on_event_unknown
virtual void on_event_unknown(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2580
zmq::from_handle_t::from_handle_t
ZMQ_CONSTEXPR_FN ZMQ_EXPLICIT from_handle_t(_private) ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:2158
zmq::monitor_t::on_event_bind_failed
virtual void on_event_bind_failed(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2511
zmq::pollitem_t
zmq_pollitem_t pollitem_t
Definition: 3rdparty/cppzmq/zmq.hpp:276
zmq::message_t::copy
void copy(message_t const *msg_)
Definition: 3rdparty/cppzmq/zmq.hpp:573
zmq::monitor_t::~monitor_t
virtual ~monitor_t()
Definition: src/loggers/zmq.hpp:2378
zmq::message_t::to_string
std::string to_string() const
Definition: src/loggers/zmq.hpp:662
zmq::context_t::operator=
void operator=(const context_t &) ZMQ_DELETED_FUNCTION
zmq::context_t::setctxopt
int setctxopt(int option_, int optval_)
Definition: 3rdparty/cppzmq/zmq.hpp:835
zmq::message_t::handle
ZMQ_NODISCARD zmq_msg_t * handle() ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:729
literals
Definition: json.hpp:24461
detail::is_range
Definition: json.hpp:3725
zmq::socket_t
Definition: 3rdparty/cppzmq/zmq.hpp:2181
zmq::context_t::swap
void swap(context_t &other) ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:924
zmq::error_t::errnum
int errnum
Definition: 3rdparty/cppzmq/zmq.hpp:301
zmq::message_t::data
void * data() ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:593
zmq::socket_t::socket_t
socket_t(void *context_, int type_)
Definition: src/loggers/zmq.hpp:2322
zmq::monitor_t::on_event_disconnected
virtual void on_event_disconnected(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2536
zmq::operator>
bool operator>(const detail::socket_base &a, const detail::socket_base &b) ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:2151
zmq::monitor_t::monitor_t
monitor_t()
Definition: src/loggers/zmq.hpp:2375
zmq::message_t::data
const void * data() const ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:571
zmq::from_handle
ZMQ_CONSTEXPR_VAR from_handle_t from_handle
Definition: 3rdparty/cppzmq/zmq.hpp:2102
zmq::detail::socket_base::ZMQ_CPP11_DEPRECATED
ZMQ_CPP11_DEPRECATED("from 4.4.1, use send taking message_t or buffer (for contiguous " "ranges), and send_flags") bool send(T first
zmq::monitor_t::on_event_accept_failed
virtual void on_event_accept_failed(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2521
zmq::detail::socket_base::bind
void bind(const char *addr_)
Definition: src/loggers/zmq.hpp:1893
zmq::detail::socket_base::setsockopt
void setsockopt(int option_, T const &optval)
Definition: 3rdparty/cppzmq/zmq.hpp:1735
zmq::monitor_t::monitor
void monitor(socket_t &socket, const char *addr_, int events=ZMQ_EVENT_ALL)
Definition: src/loggers/zmq.hpp:2405
zmq::message_t::more
bool more() const ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:560
zmq::monitor_t::on_event_listening
virtual void on_event_listening(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2506
zmq::message_t::swap
void swap(message_t &other) ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:723
detail
detail namespace with internal helper functions
Definition: json.hpp:248
zmq::detail::socket_base::unbind
void unbind(std::string const &addr)
Definition: src/loggers/zmq.hpp:1900
ZMQ_OVERRIDE
#define ZMQ_OVERRIDE
Definition: src/loggers/zmq.hpp:89
zmq::operator<
bool operator<(const detail::socket_base &a, const detail::socket_base &b) ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:2147
zmq::monitor_t::check_event
bool check_event(int timeout=0)
Definition: 3rdparty/cppzmq/zmq.hpp:2361
zmq::operator>=
bool operator>=(const detail::socket_base &a, const detail::socket_base &b) ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:2159
zmq::error_t::error_t
error_t() ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:280
magic_enum::bitwise_operators::operator^
constexpr E operator^(E lhs, E rhs) noexcept
Definition: magic_enum.hpp:1437
ZMQ_DEPRECATED
#define ZMQ_DEPRECATED(msg)
Definition: 3rdparty/cppzmq/zmq.hpp:71
zmq::message_t::message_t
message_t(size_t size_)
Definition: src/loggers/zmq.hpp:396
zmq::detail::socket_base::send
size_t send(const void *buf_, size_t len_, int flags_=0)
Definition: 3rdparty/cppzmq/zmq.hpp:1916
zmq::message_t::equal
bool equal(const message_t *other) const ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:615
zmq::detail::socket_base::socket_base
ZMQ_EXPLICIT socket_base(void *handle) ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:1739
lexyd::hex
_d< 16 > hex
Definition: digit.hpp:237
magic_enum::detail::value
constexpr E value(std::size_t i) noexcept
Definition: magic_enum.hpp:664
zmq::socket_t::operator=
void operator=(const socket_t &) ZMQ_DELETED_FUNCTION
zmq::operator==
bool operator==(const detail::socket_base &a, const detail::socket_base &b) ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:2139
zmq::context_t::close
void close() ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:866
zmq::socket_ref
Definition: 3rdparty/cppzmq/zmq.hpp:2107
zmq::detail::socket_base::disconnect
void disconnect(const char *addr_)
Definition: src/loggers/zmq.hpp:1929
zmq::message_t::message_t
message_t(ForwardIter first, ForwardIter last)
Definition: src/loggers/zmq.hpp:404
cx::end
constexpr auto end(const C &c) -> decltype(c.end())
Definition: wildcards.hpp:686
detail::void
j template void())
Definition: json.hpp:4893
zmq::monitor_t::init
void init(socket_t &socket, std::string const &addr, int events=ZMQ_EVENT_ALL)
Definition: 3rdparty/cppzmq/zmq.hpp:2343
lexy::operator|
constexpr auto operator|(First first, Second second)
Composes two callbacks.
Definition: composition.hpp:100
zmq
Definition: 3rdparty/cppzmq/zmq.hpp:228
zmq::context_t
Definition: 3rdparty/cppzmq/zmq.hpp:798
zmq::detail::socket_base::set_option
void set_option(int option_, const void *optval_, size_t optvallen_)
Definition: 3rdparty/cppzmq/zmq.hpp:2078
zmq::message_t::get
int get(int property_)
Definition: src/loggers/zmq.hpp:616
zmq_event_t::event
uint16_t event
Definition: 3rdparty/cppzmq/zmq.hpp:209
zmq::context_t::handle
ZMQ_NODISCARD void * handle() ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:913
zmq::socket_t::monitor_t
friend class monitor_t
Definition: 3rdparty/cppzmq/zmq.hpp:2183
zmq::detail::socket_base::last
T last
Definition: 3rdparty/cppzmq/zmq.hpp:1942
zmq::monitor_t::on_event_handshake_failed_protocol
virtual void on_event_handshake_failed_protocol(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2548
zmq::operator<<
std::ostream & operator<<(std::ostream &os, const message_t &msg)
Definition: 3rdparty/cppzmq/zmq.hpp:2755
lexy::_detail::void_t
void void_t
Definition: detect.hpp:12
detail::range_value_t
value_type_t< iterator_traits< iterator_t< T > >> range_value_t
Definition: json.hpp:3747
ZMQ_NULLPTR
#define ZMQ_NULLPTR
Definition: src/loggers/zmq.hpp:90
zmq::version
void version(int *major_, int *minor_, int *patch_)
Definition: 3rdparty/cppzmq/zmq.hpp:380
zmq::error_t::num
int num() const ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:288
zmq::context_t::ptr
void * ptr
Definition: 3rdparty/cppzmq/zmq.hpp:906
lexy::buffer
buffer(const CharT *, const CharT *) -> buffer< deduce_encoding< CharT >>
zmq::message_t::operator!=
bool operator!=(const message_t &other) const ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:610
zmq::monitor_t::_socket
socket_ref _socket
Definition: 3rdparty/cppzmq/zmq.hpp:2590
zmq::socket_ref::socket_ref
socket_ref(from_handle_t, void *handle) ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:2175
ZMQ_ASSERT
#define ZMQ_ASSERT(expression)
Definition: src/loggers/zmq.hpp:217
zmq::message_t::gets
const char * gets(const char *property_)
Definition: src/loggers/zmq.hpp:626
ZMQ_CPP11_DEPRECATED
#define ZMQ_CPP11_DEPRECATED(msg)
Definition: src/loggers/zmq.hpp:93
zmq::socket_t::close
void close() ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:2225
zmq::monitor_t::on_event_close_failed
virtual void on_event_close_failed(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2531
ZMQ_DELETED_FUNCTION
#define ZMQ_DELETED_FUNCTION
Definition: src/loggers/zmq.hpp:174
zmq::context_t::shutdown
void shutdown() ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:892
zmq::monitor_t::on_event_closed
virtual void on_event_closed(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2526
zmq::proxy_steerable
void proxy_steerable(void *frontend, void *backend, void *capture, void *control)
Definition: 3rdparty/cppzmq/zmq.hpp:2285
zmq::message_t::rebuild
void rebuild()
Definition: src/loggers/zmq.hpp:490
lexy::_detail::is_ascii
constexpr bool is_ascii(CharT c)
Definition: encoding.hpp:291
zmq::socket_t::socket_t
socket_t() ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:2246
zmq::monitor_t
Definition: 3rdparty/cppzmq/zmq.hpp:2304
zmq::monitor_t::on_event_handshake_succeeded
virtual void on_event_handshake_succeeded(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2560
magic_enum::detail::n
constexpr auto n() noexcept
Definition: magic_enum.hpp:417
zmq::detail::socket_base::socket_base
socket_base() ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:1737
zmq::message_t::message_t
message_t() ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:390
zmq::from_handle_t::_private
Definition: 3rdparty/cppzmq/zmq.hpp:2096
ZMQ_NODISCARD
#define ZMQ_NODISCARD
Definition: src/loggers/zmq.hpp:75
zmq::message_t::rebuild
void rebuild(const void *data_, size_t size_)
Definition: src/loggers/zmq.hpp:509
zmq::message_t::message_t
message_t(const void *data_, size_t size_)
Definition: src/loggers/zmq.hpp:417
zmq::free_fn
zmq_free_fn free_fn
Definition: 3rdparty/cppzmq/zmq.hpp:275
detail::get
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition: json.hpp:5342
zmq::monitor_t::on_event_connect_retried
virtual void on_event_connect_retried(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2500
cx::begin
constexpr auto begin(const C &c) -> decltype(c.begin())
Definition: wildcards.hpp:661
magic_enum::bitwise_operators::operator~
constexpr E operator~(E rhs) noexcept
Definition: magic_enum.hpp:1422
zmq::monitor_t::init
void init(socket_t &socket, const char *addr_, int events=ZMQ_EVENT_ALL)
Definition: src/loggers/zmq.hpp:2419
zmq::detail::socket_base::getsockopt
void getsockopt(int option_, void *optval_, size_t *optvallen_) const
Definition: 3rdparty/cppzmq/zmq.hpp:1749
zmq::detail::socket_base::connect
void connect(const char *addr_)
Definition: src/loggers/zmq.hpp:1917
zmq::socket_t::socket_t
socket_t(context_t &context_, int type_)
Definition: src/loggers/zmq.hpp:2249
detail::hash
std::size_t hash(const BasicJsonType &j)
hash a JSON value
Definition: json.hpp:6022
ZMQ_CONSTEXPR_VAR
#define ZMQ_CONSTEXPR_VAR
Definition: src/loggers/zmq.hpp:92
zmq::detail::socket_base::flags_
T int flags_
Definition: 3rdparty/cppzmq/zmq.hpp:1942
zmq::detail::socket_base
Definition: 3rdparty/cppzmq/zmq.hpp:1727
zmq::operator!=
bool operator!=(const detail::socket_base &a, const detail::socket_base &b) ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:2143
std
Definition: std.hpp:31
zmq::detail::socket_base::get_option
void get_option(int option_, void *optval_, size_t *optvallen_) const
Definition: 3rdparty/cppzmq/zmq.hpp:2085
lexyd::ascii::control
constexpr auto control
Definition: ascii.hpp:42
zmq::monitor_t::on_event_connected
virtual void on_event_connected(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2489
zmq::detail::socket_base::disconnect
void disconnect(std::string const &addr)
Definition: src/loggers/zmq.hpp:1924
zmq::detail::socket_base::connect
void connect(std::string const &addr)
Definition: src/loggers/zmq.hpp:1912
lexyd::byte
constexpr auto byte
Matches an arbitrary byte.
Definition: byte.hpp:133
zmq::message_t::data
T * data() ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:587
zmq::detail::socket_base::bind
void bind(std::string const &addr)
Definition: src/loggers/zmq.hpp:1888
ZMQ_NOTHROW
#define ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:87
ZMQ_CONSTEXPR_FN
#define ZMQ_CONSTEXPR_FN
Definition: src/loggers/zmq.hpp:91
zmq::message_t::copy
void copy(message_t &msg_)
Definition: src/loggers/zmq.hpp:553
zmq::message_t::rebuild
void rebuild(size_t size_)
Definition: src/loggers/zmq.hpp:499
zmq::message_t::str
std::string str() const
Definition: 3rdparty/cppzmq/zmq.hpp:693
ZMQ_EXPLICIT
#define ZMQ_EXPLICIT
Definition: src/loggers/zmq.hpp:88
detail::value_t
value_t
the JSON type enumeration
Definition: json.hpp:2872
zmq::socket_t::~socket_t
~socket_t() ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:2278
zmq::message_t::empty
ZMQ_NODISCARD bool empty() const ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:581
zmq::message_t::operator==
bool operator==(const message_t &other) const ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:604
zmq::error_t::error_t
error_t(int err) ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:282
zmq::message_t::operator=
void operator=(const message_t &) ZMQ_DELETED_FUNCTION
zmq::socket_ref::socket_ref
socket_ref() ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:2169
zmq::monitor_t::close
void close() ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:2593
lexyd::operator+
constexpr auto operator+(Rule rule, _br< Condition, R... >)
Definition: branch.hpp:72
zmq::monitor_t::on_event_accepted
virtual void on_event_accepted(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2516
std::swap
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression, cppcoreguidelines-noexcept-swap, performance-noexcept-swap) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition: json.hpp:24537
zmq::context_t::~context_t
~context_t() ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:834
zmq::context_t::context_t
context_t(int io_threads_, int max_sockets_=ZMQ_MAX_SOCKETS_DFLT)
Definition: src/loggers/zmq.hpp:808
zmq::monitor_t::on_event_connect_delayed
virtual void on_event_connect_delayed(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2494
zmq::detail::socket_base::unbind
void unbind(const char *addr_)
Definition: src/loggers/zmq.hpp:1905
zmq::message_t::msg
zmq_msg_t msg
Definition: 3rdparty/cppzmq/zmq.hpp:740
zmq_event_t::value
int32_t value
Definition: 3rdparty/cppzmq/zmq.hpp:210
lexy::_detail::declval
std::add_rvalue_reference_t< T > declval()
zmq::message_t::move
void move(message_t const *msg_)
Definition: 3rdparty/cppzmq/zmq.hpp:558
zmq::message_t::size
size_t size() const ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:600
zmq::error_t::what
virtual const char * what() const ZMQ_NOTHROW ZMQ_OVERRIDE
Definition: src/loggers/zmq.hpp:284
lexyd::capture
constexpr auto capture(Token)
Captures whatever the token matches as a lexeme; does not include trailing whitespace.
Definition: capture.hpp:127
zmq::message_t::data
T const * data() const ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:593
zmq::context_t::getctxopt
int getctxopt(int option_)
Definition: 3rdparty/cppzmq/zmq.hpp:843
zmq::message_t::~message_t
~message_t() ZMQ_NOTHROW
Definition: src/loggers/zmq.hpp:484
lexyd::p
constexpr auto p
Parses the production.
Definition: production.hpp:127
zmq::message_t::rebuild
void rebuild(void *data_, size_t size_, free_fn *ffn_, void *hint_=ZMQ_NULLPTR)
Definition: src/loggers/zmq.hpp:520
zmq::error_t
Definition: 3rdparty/cppzmq/zmq.hpp:289
lexy::_detail::string_view
basic_string_view< char > string_view
Definition: string_view.hpp:192
zmq::message_t::message_t
message_t(void *data_, size_t size_, free_fn *ffn_, void *hint_=ZMQ_NULLPTR)
Definition: src/loggers/zmq.hpp:430
zmq::monitor_t::operator=
void operator=(const monitor_t &) ZMQ_DELETED_FUNCTION
zmq::operator<=
bool operator<=(const detail::socket_base &a, const detail::socket_base &b) ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:2155
lexyd::operator&
constexpr auto operator&(C1 c1, C2 c2) -> _cand< decltype(_make_char_class(c1)), decltype(_make_char_class(c2))>
Definition: char_class.hpp:585
zmq::monitor_t::_monitor_socket
socket_t _monitor_socket
Definition: 3rdparty/cppzmq/zmq.hpp:2591


behaviortree_cpp_v4
Author(s): Davide Faconti
autogenerated on Fri Dec 13 2024 03:19:17