sdbus-c++  0.8.3
High-level C++ D-Bus library based on systemd D-Bus implementation
Message.h
Go to the documentation of this file.
1 
27 #ifndef SDBUS_CXX_MESSAGE_H_
28 #define SDBUS_CXX_MESSAGE_H_
29 
30 #include <sdbus-c++/TypeTraits.h>
31 #include <sdbus-c++/Error.h>
32 #include <string>
33 #include <vector>
34 #include <map>
35 #include <memory>
36 #include <utility>
37 #include <cstdint>
38 #include <cassert>
39 #include <functional>
40 
41 // Forward declarations
42 namespace sdbus {
43  class Variant;
44  class ObjectPath;
45  class Signature;
46  template <typename... _ValueTypes> class Struct;
47  class UnixFd;
48  class MethodReply;
49  namespace internal {
50  class ISdBus;
51  }
52 }
53 
54 namespace sdbus {
55 
56  // Assume the caller has already obtained message ownership
57  struct adopt_message_t { explicit adopt_message_t() = default; };
58  inline constexpr adopt_message_t adopt_message{};
59 
60  /********************************************/
74  class [[nodiscard]] Message
75  {
76  public:
77  Message& operator<<(bool item);
78  Message& operator<<(int16_t item);
79  Message& operator<<(int32_t item);
80  Message& operator<<(int64_t item);
81  Message& operator<<(uint8_t item);
82  Message& operator<<(uint16_t item);
83  Message& operator<<(uint32_t item);
84  Message& operator<<(uint64_t item);
85  Message& operator<<(double item);
86  Message& operator<<(const char *item);
87  Message& operator<<(const std::string &item);
88  Message& operator<<(const Variant &item);
89  Message& operator<<(const ObjectPath &item);
90  Message& operator<<(const Signature &item);
91  Message& operator<<(const UnixFd &item);
92 
93  Message& operator>>(bool& item);
94  Message& operator>>(int16_t& item);
95  Message& operator>>(int32_t& item);
96  Message& operator>>(int64_t& item);
97  Message& operator>>(uint8_t& item);
98  Message& operator>>(uint16_t& item);
99  Message& operator>>(uint32_t& item);
100  Message& operator>>(uint64_t& item);
101  Message& operator>>(double& item);
102  Message& operator>>(char*& item);
103  Message& operator>>(std::string &item);
104  Message& operator>>(Variant &item);
105  Message& operator>>(ObjectPath &item);
106  Message& operator>>(Signature &item);
107  Message& operator>>(UnixFd &item);
108 
109  Message& openContainer(const std::string& signature);
110  Message& closeContainer();
111  Message& openDictEntry(const std::string& signature);
112  Message& closeDictEntry();
113  Message& openVariant(const std::string& signature);
114  Message& closeVariant();
115  Message& openStruct(const std::string& signature);
116  Message& closeStruct();
117 
118  Message& enterContainer(const std::string& signature);
119  Message& exitContainer();
120  Message& enterDictEntry(const std::string& signature);
121  Message& exitDictEntry();
122  Message& enterVariant(const std::string& signature);
123  Message& exitVariant();
124  Message& enterStruct(const std::string& signature);
125  Message& exitStruct();
126 
127  explicit operator bool() const;
128  void clearFlags();
129 
130  std::string getInterfaceName() const;
131  std::string getMemberName() const;
132  std::string getSender() const;
133  void peekType(std::string& type, std::string& contents) const;
134  bool isValid() const;
135  bool isEmpty() const;
136 
137  void copyTo(Message& destination, bool complete) const;
138  void seal();
139  void rewind(bool complete);
140 
141  class Factory;
142 
143  protected:
144  Message() = default;
145  explicit Message(internal::ISdBus* sdbus) noexcept;
146  Message(void *msg, internal::ISdBus* sdbus) noexcept;
147  Message(void *msg, internal::ISdBus* sdbus, adopt_message_t) noexcept;
148 
149  Message(const Message&) noexcept;
150  Message& operator=(const Message&) noexcept;
151  Message(Message&& other) noexcept;
152  Message& operator=(Message&& other) noexcept;
153 
154  ~Message();
155 
156  friend Factory;
157 
158  protected:
159  void* msg_{};
160  internal::ISdBus* sdbus_{};
161  mutable bool ok_{true};
162  };
163 
164  struct dont_request_slot_t { explicit dont_request_slot_t() = default; };
165  inline constexpr dont_request_slot_t dont_request_slot{};
166 
167  class MethodCall : public Message
168  {
169  using Message::Message;
170  friend Factory;
171 
172  public:
173  using Slot = std::unique_ptr<void, std::function<void(void*)>>;
174 
175  MethodCall() = default;
176 
177  MethodReply send(uint64_t timeout) const;
178  void send(void* callback, void* userData, uint64_t timeout, dont_request_slot_t) const;
179  [[nodiscard]] Slot send(void* callback, void* userData, uint64_t timeout) const;
180 
181  MethodReply createReply() const;
182  MethodReply createErrorReply(const sdbus::Error& error) const;
183 
184  void dontExpectReply();
185  bool doesntExpectReply() const;
186 
187  private:
188  MethodReply sendWithReply(uint64_t timeout = 0) const;
189  MethodReply sendWithNoReply() const;
190  };
191 
192  class MethodReply : public Message
193  {
194  using Message::Message;
195  friend Factory;
196 
197  public:
198  MethodReply() = default;
199  void send() const;
200  };
201 
202  class Signal : public Message
203  {
204  using Message::Message;
205  friend Factory;
206 
207  public:
208  Signal() = default;
209  void send() const;
210  };
211 
212  class PropertySetCall : public Message
213  {
214  using Message::Message;
215  friend Factory;
216 
217  public:
218  PropertySetCall() = default;
219  };
220 
221  class PropertyGetReply : public Message
222  {
223  using Message::Message;
224  friend Factory;
225 
226  public:
227  PropertyGetReply() = default;
228  };
229 
230  class PlainMessage : public Message
231  {
232  using Message::Message;
233  friend Factory;
234 
235  public:
236  PlainMessage() = default;
237  };
238 
239  template <typename _Element>
240  inline Message& operator<<(Message& msg, const std::vector<_Element>& items)
241  {
242  msg.openContainer(signature_of<_Element>::str());
243 
244  for (const auto& item : items)
245  msg << item;
246 
247  msg.closeContainer();
248 
249  return msg;
250  }
251 
252  template <typename _Key, typename _Value>
253  inline Message& operator<<(Message& msg, const std::map<_Key, _Value>& items)
254  {
255  const std::string dictEntrySignature = signature_of<_Key>::str() + signature_of<_Value>::str();
256  const std::string arraySignature = "{" + dictEntrySignature + "}";
257 
258  msg.openContainer(arraySignature);
259 
260  for (const auto& item : items)
261  {
262  msg.openDictEntry(dictEntrySignature);
263  msg << item.first;
264  msg << item.second;
265  msg.closeDictEntry();
266  }
267 
268  msg.closeContainer();
269 
270  return msg;
271  }
272 
273  namespace detail
274  {
275  template <typename... _Args>
276  void serialize_pack(Message& msg, _Args&&... args)
277  {
278  (void)(msg << ... << args);
279  }
280 
281  template <class _Tuple, std::size_t... _Is>
282  void serialize_tuple( Message& msg
283  , const _Tuple& t
284  , std::index_sequence<_Is...>)
285  {
286  serialize_pack(msg, std::get<_Is>(t)...);
287  }
288  }
289 
290  template <typename... _ValueTypes>
291  inline Message& operator<<(Message& msg, const Struct<_ValueTypes...>& item)
292  {
293  auto structSignature = signature_of<Struct<_ValueTypes...>>::str();
294  assert(structSignature.size() > 2);
295  // Remove opening and closing parenthesis from the struct signature to get contents signature
296  auto structContentSignature = structSignature.substr(1, structSignature.size()-2);
297 
298  msg.openStruct(structContentSignature);
299  detail::serialize_tuple(msg, item, std::index_sequence_for<_ValueTypes...>{});
300  msg.closeStruct();
301 
302  return msg;
303  }
304 
305  template <typename... _ValueTypes>
306  inline Message& operator<<(Message& msg, const std::tuple<_ValueTypes...>& item)
307  {
308  detail::serialize_tuple(msg, item, std::index_sequence_for<_ValueTypes...>{});
309  return msg;
310  }
311 
312 
313  template <typename _Element>
314  inline Message& operator>>(Message& msg, std::vector<_Element>& items)
315  {
316  if(!msg.enterContainer(signature_of<_Element>::str()))
317  return msg;
318 
319  while (true)
320  {
321  _Element elem;
322  if (msg >> elem)
323  items.emplace_back(std::move(elem));
324  else
325  break;
326  }
327 
328  msg.clearFlags();
329 
330  msg.exitContainer();
331 
332  return msg;
333  }
334 
335  template <typename _Key, typename _Value>
336  inline Message& operator>>(Message& msg, std::map<_Key, _Value>& items)
337  {
338  const std::string dictEntrySignature = signature_of<_Key>::str() + signature_of<_Value>::str();
339  const std::string arraySignature = "{" + dictEntrySignature + "}";
340 
341  if (!msg.enterContainer(arraySignature))
342  return msg;
343 
344  while (true)
345  {
346  if (!msg.enterDictEntry(dictEntrySignature))
347  break;
348 
349  _Key key;
350  _Value value;
351  msg >> key >> value;
352 
353  items.emplace(std::move(key), std::move(value));
354 
355  msg.exitDictEntry();
356  }
357 
358  msg.clearFlags();
359 
360  msg.exitContainer();
361 
362  return msg;
363  }
364 
365  namespace detail
366  {
367  template <typename... _Args>
368  void deserialize_pack(Message& msg, _Args&... args)
369  {
370  (void)(msg >> ... >> args);
371  }
372 
373  template <class _Tuple, std::size_t... _Is>
374  void deserialize_tuple( Message& msg
375  , _Tuple& t
376  , std::index_sequence<_Is...> )
377  {
378  deserialize_pack(msg, std::get<_Is>(t)...);
379  }
380  }
381 
382  template <typename... _ValueTypes>
383  inline Message& operator>>(Message& msg, Struct<_ValueTypes...>& item)
384  {
385  auto structSignature = signature_of<Struct<_ValueTypes...>>::str();
386  // Remove opening and closing parenthesis from the struct signature to get contents signature
387  auto structContentSignature = structSignature.substr(1, structSignature.size()-2);
388 
389  if (!msg.enterStruct(structContentSignature))
390  return msg;
391 
392  detail::deserialize_tuple(msg, item, std::index_sequence_for<_ValueTypes...>{});
393 
394  msg.exitStruct();
395 
396  return msg;
397  }
398 
399  template <typename... _ValueTypes>
400  inline Message& operator>>(Message& msg, std::tuple<_ValueTypes...>& item)
401  {
402  detail::deserialize_tuple(msg, item, std::index_sequence_for<_ValueTypes...>{});
403  return msg;
404  }
405 
406 }
407 
408 #endif /* SDBUS_CXX_MESSAGE_H_ */
Definition: Message.h:192
Definition: TypeTraits.h:63
Definition: Message.h:164
Definition: Message.h:74
Definition: Types.h:53
Definition: Error.h:42
Definition: Message.h:202
Definition: Types.h:152
Definition: Message.h:221
Definition: Message.h:46
Definition: Message.h:212
Definition: Types.h:196
Definition: Types.h:170
Definition: Message.h:57
Definition: AdaptorInterfaces.h:36
Definition: Message.h:230
Definition: Message.h:167