dbus-cxx
messageiterator.h
Go to the documentation of this file.
1// SPDX-License-Identifier: LGPL-3.0-or-later OR BSD-3-Clause
2/***************************************************************************
3 * Copyright (C) 2007,2009,2010 by Rick L. Vinyard, Jr. *
4 * rvinyard@cs.nmsu.edu *
5 * *
6 * This file is part of the dbus-cxx library. *
7 ***************************************************************************/
8#include <stdint.h>
9#include <dbus-cxx/demangle.h>
10#include <dbus-cxx/types.h>
11#include <dbus-cxx/variant.h>
14#include <map>
15#include <memory>
16#include <string>
17#include <tuple>
18#include <type_traits>
19#include <vector>
20#include "enums.h"
21#include "error.h"
22#include "headerlog.h"
23#include "signature.h"
24
25#ifndef DBUSCXX_MESSAGEITERATOR_H
26#define DBUSCXX_MESSAGEITERATOR_H
27
28#if defined(__GNUC__) && (__GNUC__ <= 8)
29 /*
30 * There seems to be a bug with G++ on versions <= 8 where the operator Variant()
31 * is trying to call the constructor instead of actually calling the operator on
32 * the iterator. This macro works around this bug
33 */
34 #define DBUSCXX_MESSAGEITERATOR_OPERATOR_VARIANT(iter) iter.operator DBus::Variant()
35 #define DBUSCXX_MESSAGEITERATOR_OPERATOR_SIGNATURE(iter) iter.operator DBus::Signature()
36 #define DBUSCXX_MESSAGEITERATOR_OPERATOR_MULTIPLE_RETURN(iter) iter.operator DBus::MultipleReturn()
37#else
38 #define DBUSCXX_MESSAGEITERATOR_OPERATOR_VARIANT(iter) (DBus::Variant)iter
39 #define DBUSCXX_MESSAGEITERATOR_OPERATOR_SIGNATURE(iter) (DBus::Signature)iter
40 #define DBUSCXX_MESSAGEITERATOR_OPERATOR_MULTIPLE_RETURN(iter) (DBus::MultipleReturn)iter
41#endif
42
43namespace DBus {
44
45class FileDescriptor;
46class Message;
47template<typename ... T> class MultipleReturn;
48
57
58private:
69 const Message* message,
70 std::shared_ptr<Demarshaling> demarshal );
71
72public:
73
75
77
78 MessageIterator( std::shared_ptr<Message> message );
79
84 const Message* message() const;
85
87 void invalidate();
88
90 bool is_valid() const;
91
93 bool has_next() const;
94
103 bool next();
104
106
108
109 bool operator==( const MessageIterator& other );
110
112 DataType arg_type() const;
113
119 DataType element_type() const;
120
122 bool is_fixed() const;
123
125 bool is_container() const;
126
128 bool is_array() const;
129
131 bool is_dict() const;
132
139
141 std::string signature() const;
142
143 operator bool();
144 operator uint8_t();
145 operator uint16_t();
146 operator int16_t();
147 operator uint32_t();
148 operator int32_t();
149 operator uint64_t();
150 operator int64_t();
151 operator double();
152 operator std::string();
153 operator std::shared_ptr<FileDescriptor>();
154 operator Variant();
155
156 template <typename T>
157 operator std::vector<T>() {
158 if( !this->is_array() ) {
159 throw ErrorInvalidTypecast( "MessageIterator: Extracting non array into std::vector" );
160 }
161 std::vector<T> ret;
162 get_array<T>(ret);
163
164 return ret;
165 }
166
167 template <typename Key, typename Data>
168 operator std::map<Key, Data>() {
169 if( !this->is_dict() ) {
170 throw ErrorInvalidTypecast( "MessageIterator: Extracting non dict into std::map" );
171 }
172
173 return get_dict<Key, Data>();
174 }
175
176 template <typename... T>
177 operator std::tuple<T...>() {
178 std::tuple<T...> tup;
179 get_struct<T...>( tup );
180 return tup;
181 }
182
183 template <typename... T>
184 operator DBus::MultipleReturn<T...>() {
185 DBus::MultipleReturn<T...> multi_ret;
186 get_multiplereturn<T...>( multi_ret );
187 return multi_ret;
188 }
189
190 bool get_bool();
191 uint8_t get_uint8();
192 uint16_t get_uint16();
193 int16_t get_int16();
194 uint32_t get_uint32();
195 int32_t get_int32();
196 uint64_t get_uint64();
197 int64_t get_int64();
198 double get_double();
199 std::string get_string();
200 std::shared_ptr<FileDescriptor> get_filedescriptor();
203
207 template <typename T>
208 void get_array( std::vector<T>& array ) {
209 if( !this->is_array() ) { /* Should never happen */
210 throw ErrorInvalidTypecast( "MessageIterator: Extracting non array into std::vector" );
211 }
212
213 array.clear();
214
215 MessageIterator subiter = this->recurse();
216
217 while( subiter.is_valid() ) {
218 //NOTE: we don't need to do subiter.next() here, because
219 //operator>> does that for us
220 T val {};
221 subiter >> val;
222 array.push_back( val );
223 }
224 }
225
226 template <typename... T>
227 void get_struct( std::tuple<T...>& tup ) {
228 MessageIterator subiter = this->recurse();
229 std::apply( [subiter]( auto&& ...arg ) mutable {
230 ( subiter >> ... >> arg );
231 },
232 tup );
233 }
234
235 template <typename Key, typename Data>
236 void get_dict( std::map<Key, Data>& dict ) {
237 MessageIterator subiter = this->recurse();
238
239 while( subiter.is_valid() ) {
240 MessageIterator subSubiter = subiter.recurse();
241
242 // When we recurse the second time, our demarshaling gets aligned.
243 // This may cause the subiter to then become invalid because of
244 // the new byte offset, so we need a second is_valid() check here.
245 if( !subiter.is_valid() ){
246 break;
247 }
248
249 while( subSubiter.is_valid() ) {
250 Key val_key;
251 Data val_data;
252
253 subSubiter >> val_key;
254 subSubiter >> val_data;
255 dict[ val_key ] = val_data;
256 subSubiter.next();
257 }
258
259 subiter.next();
260 }
261 }
262
263 template <typename... T>
265 std::tuple<T...> tup;
266 std::apply( [this]( auto&& ...arg ) mutable {
267 ( *this >> ... >> arg );
268 },
269 tup );
270
271 v.m_data = tup;
272 }
273
274 template <typename Key, typename Data>
275 std::map<Key, Data> get_dict() {
276 std::map<Key, Data> newMap;
277 get_dict( newMap );
278 return newMap;
279 }
280
281 template <typename Key, typename Data>
282 MessageIterator& operator>>( std::map<Key, Data>& m ) {
283 if( !this->is_dict() ) {
284 throw ErrorInvalidTypecast( "MessageIterator: Extracting non dict into std::map" );
285 }
286
287 get_dict<Key, Data>( m );
288 this->next();
289 return *this;
290 }
291
292 template <typename... T>
293 MessageIterator& operator>>( std::tuple<T...>& v ) {
294 this->get_struct<T...>( v );
295 this->next();
296 return *this;
297 }
298
299 template <typename T>
300 MessageIterator& operator>>( std::vector<T>& v ) {
301 if( !this->is_array() ) {
302 throw ErrorInvalidTypecast( "MessageIterator: Extracting non array into std::vector" );
303 }
304
305 this->get_array<T>( v );
306 this->next();
307 return *this;
308 }
309
311 v = this->get_variant();
312 this->next();
313 return *this;
314 }
315
316 template<typename ... T>
318 this->get_multiplereturn<T...>(v);
319 this->next();
320 return *this;
321 }
322
323 template <typename T>
325 v = static_cast<T>( *this );
326 this->next();
327 return *this;
328 }
329
330 template<typename T>
331 T get(){
332 T ret = (T)(*this);
333 this->next();
334 return ret;
335 }
336
337
338private:
340
347 void align( int alignment );
348
349private:
350 class priv_data;
351
352 std::shared_ptr<priv_data> m_priv;
353
354 friend class Variant;
355};
356
357}
358
359#endif
Definition: error.h:341
Extraction iterator allowing values to be retrieved from a message.
Definition: messageiterator.h:56
MessageIterator()
Definition: messageiterator.cpp:69
int64_t get_int64()
Definition: messageiterator.cpp:542
std::map< Key, Data > get_dict()
Definition: messageiterator.h:275
int32_t get_int32()
Definition: messageiterator.cpp:526
MessageIterator & operator>>(std::map< Key, Data > &m)
Definition: messageiterator.h:282
void get_multiplereturn(MultipleReturn< T... > &v)
Definition: messageiterator.h:264
std::shared_ptr< priv_data > m_priv
Definition: messageiterator.h:352
bool is_fixed() const
True if the element type is a fixed type.
Definition: messageiterator.cpp:186
void get_array(std::vector< T > &array)
Get values in an array, pushing them back one at a time.
Definition: messageiterator.h:208
std::string signature() const
Returns the current signature of the iterator.
Definition: messageiterator.cpp:215
SignatureIterator signature_iterator()
Definition: messageiterator.cpp:613
uint16_t get_uint16()
Definition: messageiterator.cpp:518
MessageIterator recurse()
If the iterator points to a container recurses into the container returning a sub-iterator.
Definition: messageiterator.cpp:204
uint32_t get_uint32()
Definition: messageiterator.cpp:534
T get()
Definition: messageiterator.h:331
MessageIterator & operator>>(MultipleReturn< T... > &v)
Definition: messageiterator.h:317
uint64_t get_uint64()
Definition: messageiterator.cpp:550
bool is_array() const
True if the iterator points to an array.
Definition: messageiterator.cpp:196
DataType arg_type() const
Returns the argument type that the iterator points to.
Definition: messageiterator.cpp:174
bool is_dict() const
True if the iterator points to a dictionary.
Definition: messageiterator.cpp:200
MessageIterator & operator++()
Definition: messageiterator.cpp:157
MessageIterator & operator>>(T &v)
Definition: messageiterator.h:324
const Message * message() const
Returns a pointer to the message associated with this iterator or NULL if no message is associated.
Definition: messageiterator.cpp:98
bool is_valid() const
True if this is a valid iterator.
Definition: messageiterator.cpp:106
void invalidate()
Invalidates the iterator.
Definition: messageiterator.cpp:102
friend class Variant
Definition: messageiterator.h:354
bool operator==(const MessageIterator &other)
Definition: messageiterator.cpp:169
double get_double()
Definition: messageiterator.cpp:558
DataType element_type() const
Returns the element type of the array that the iterator points to.
Definition: messageiterator.cpp:178
void get_struct(std::tuple< T... > &tup)
Definition: messageiterator.h:227
MessageIterator & operator>>(std::tuple< T... > &v)
Definition: messageiterator.h:293
bool next()
Moves the iterator to the next field and invalidates it if it moves beyond the last field.
Definition: messageiterator.cpp:134
bool has_next() const
True if there are any more fields left to iterate over.
Definition: messageiterator.cpp:128
void get_dict(std::map< Key, Data > &dict)
Definition: messageiterator.h:236
MessageIterator & operator>>(Variant &v)
Definition: messageiterator.h:310
std::string get_string()
Definition: messageiterator.cpp:566
bool get_bool()
Definition: messageiterator.cpp:494
bool is_container() const
True if the iterator points to a container.
Definition: messageiterator.cpp:191
void align(int alignment)
Align our memory to the specified location.
Definition: messageiterator.cpp:609
MessageIterator & operator>>(std::vector< T > &v)
Definition: messageiterator.h:300
Signature get_signature()
Definition: messageiterator.cpp:605
Variant get_variant()
Definition: messageiterator.cpp:598
std::shared_ptr< FileDescriptor > get_filedescriptor()
Definition: messageiterator.cpp:578
int16_t get_int16()
Definition: messageiterator.cpp:510
uint8_t get_uint8()
Definition: messageiterator.cpp:502
This class represents a basic DBus message and also serves as a base class for the specialized messag...
Definition: message.h:45
Definition: multiplereturn.h:29
std::tuple< Ts... > m_data
Definition: multiplereturn.h:31
A SignatureIterator allows you to iterate over a given DBus signature, and to extract useful informat...
Definition: signatureiterator.h:33
Represents a DBus signature.
Definition: signature.h:78
A Variant is a type-safe union for DBus operations.
Definition: variant.h:42
Global DBus namespace, where everything happens.
Definition: callmessage.cpp:18
DataType
Definition: enums.h:52