dbus-cxx logo
messageiterator.h
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2007,2009,2010 by Rick L. Vinyard, Jr. *
3  * rvinyard@cs.nmsu.edu *
4  * *
5  * This file is part of the dbus-cxx library. *
6  * *
7  * The dbus-cxx library is free software; you can redistribute it and/or *
8  * modify it under the terms of the GNU General Public License *
9  * version 3 as published by the Free Software Foundation. *
10  * *
11  * The dbus-cxx library is distributed in the hope that it will be *
12  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty *
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14  * General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU General Public License *
17  * along with this software. If not see <http://www.gnu.org/licenses/>. *
18  ***************************************************************************/
19 #include <dbus/dbus.h>
20 #include <dbus-cxx/types.h>
21 
22 #ifndef DBUSCXX_MESSAGEITERATOR_H
23 #define DBUSCXX_MESSAGEITERATOR_H
24 
25 namespace DBus
26 {
27 
28  class Message;
29 
38  {
39  public:
40 
42 
44 
45  MessageIterator( DBusCxxPointer<Message> message );
46 
51  const Message* message() const;
52 
54  DBusMessageIter* cobj();
55 
57  bool init( const Message& message );
58 
60  void invalidate();
61 
63  bool is_valid() const;
64 
66  bool has_next() const;
67 
73  bool next();
74 
76 
78 
79  bool operator==( const MessageIterator& other );
80 
82  Type arg_type() const;
83 
89  Type element_type() const;
90 
92  bool is_fixed() const;
93 
95  bool is_container() const;
96 
98  bool is_array() const;
99 
101  bool is_dict() const;
102 
109 
111  std::string signature() const;
112 
121 // void value( std::vector<std::string>& temp );
122 
123 // void value( std::string& temp );
124 
125 // void value( Variant& temp );
126 
127 // template <typename T0>
128 // void value( Struct<T0>& temp ) {
129 // if ( this->element_type() != TYPE_STRUCT ) throw ErrorInvalidTypecast();
130 // MessageIterator subiter = this->recurse();
131 // subiter.value( boost::get<0>( temp ) );
132 // }
133 
134 // template <typename T0, typename T1>
135 // void value( Struct<T0,T1>& temp ) {
136 // if ( this->element_type() != TYPE_STRUCT ) throw ErrorInvalidTypecast();
137 // MessageIterator subiter = this->recurse();
138 // subiter.value( boost::get<0>( temp ) );
139 // subiter.value( boost::get<1>( temp ) );
140 // }
141 
142 // template <typename T0, typename T1, typename T2>
143 // void value( Struct<T0,T1,T2>& temp ) {
144 // if ( this->element_type() != TYPE_STRUCT ) throw ErrorInvalidTypecast();
145 // MessageIterator subiter = this->recurse();
146 // subiter.value( boost::get<0>( temp ) );
147 // subiter.value( boost::get<1>( temp ) );
148 // subiter.value( boost::get<2>( temp ) );
149 // }
150 //
151 // template <typename T0, typename T1, typename T2, typename T3>
152 // void value( Struct<T0,T1,T2,T3>& temp ) {
153 // if ( this->element_type() != TYPE_STRUCT ) throw ErrorInvalidTypecast();
154 // MessageIterator subiter = this->recurse();
155 // subiter.value( boost::get<0>( temp ) );
156 // subiter.value( boost::get<1>( temp ) );
157 // subiter.value( boost::get<2>( temp ) );
158 // subiter.value( boost::get<3>( temp ) );
159 // }
160 //
161 // template <typename T0, typename T1, typename T2, typename T3, typename T4>
162 // void value( Struct<T0,T1,T2,T3,T4>& temp ) {
163 // if ( this->element_type() != TYPE_STRUCT ) throw ErrorInvalidTypecast();
164 // MessageIterator subiter = this->recurse();
165 // subiter.value( boost::get<0>( temp ) );
166 // subiter.value( boost::get<1>( temp ) );
167 // subiter.value( boost::get<2>( temp ) );
168 // subiter.value( boost::get<3>( temp ) );
169 // subiter.value( boost::get<4>( temp ) );
170 // }
171 //
172 // template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5>
173 // void value( Struct<T0,T1,T2,T3,T4,T5>& temp ) {
174 // if ( this->element_type() != TYPE_STRUCT ) throw ErrorInvalidTypecast();
175 // MessageIterator subiter = this->recurse();
176 // subiter.value( boost::get<0>( temp ) );
177 // subiter.value( boost::get<1>( temp ) );
178 // subiter.value( boost::get<2>( temp ) );
179 // subiter.value( boost::get<3>( temp ) );
180 // subiter.value( boost::get<4>( temp ) );
181 // subiter.value( boost::get<5>( temp ) );
182 // }
183 //
184 // template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
185 // void value( Struct<T0,T1,T2,T3,T4,T5,T6>& temp ) {
186 // if ( this->element_type() != TYPE_STRUCT ) throw ErrorInvalidTypecast();
187 // MessageIterator subiter = this->recurse();
188 // subiter.value( boost::get<0>( temp ) );
189 // subiter.value( boost::get<1>( temp ) );
190 // subiter.value( boost::get<2>( temp ) );
191 // subiter.value( boost::get<3>( temp ) );
192 // subiter.value( boost::get<4>( temp ) );
193 // subiter.value( boost::get<5>( temp ) );
194 // subiter.value( boost::get<6>( temp ) );
195 // }
196 
197 // template <typename Key, typename Data>
198 // void value( std::vector<std::pair<Key,Data> >& temp ) {
199 // if ( this->element_type() != TYPE_ARRAY )
200 // throw ErrorInvalidTypecast( "Extracting non-array type into dictionary" );
201 //
202 // temp.clear();
203 // MessageIterator subiter = this->recurse();
204 // MessageIterator subsubiter;
205 // Key k;
206 // Data d;
207 //
208 // while ( subiter.has_next() ) {
209 // if ( subiter.element_type() != TYPE_DICT_ENTRY )
210 // throw ErrorInvalidTypecast( "Extracting non-dictionary-entry type into dictionary entry" );
211 // subsubiter = subiter.recurse();
212 // subsubiter.value( k );
213 // ++subsubiter;
214 // subsubiter.value( d );
215 // temp.push_back( std::make_pair( k,d ) );
216 // ++subiter;
217 // }
218 // }
219 
220 
221 
222  operator bool();
223  operator uint8_t();
224  operator uint16_t();
225  operator int16_t();
226  operator uint32_t();
227  operator int32_t();
228  operator uint64_t();
229  operator int64_t();
230  operator double();
231  operator const char*();
232 
233  operator char();
234  operator int8_t();
235  operator float();
236  #if DBUS_CXX_SIZEOF_LONG_INT == 4
237  operator long int();
238  operator unsigned long int();
239  #endif
240 
241  template <typename T>
242  operator std::vector<T>() {
243  if ( not this->is_array() )
244  throw ErrorInvalidTypecast::create( "MessageIterator: Extracting non array into std::vector" );
245 
246  if ( this->is_fixed() )
247  return get_array_simple<T>();
248  else
249  return get_array_complex<T>();
250  }
251 
252  template <typename Key, typename Data>
253  operator std::map<Key,Data>() {
254  if ( not this->is_dict() )
255  throw ErrorInvalidTypecast::create( "MessageIterator: Extracting non dict into std::map" );
256 
257  return get_dict<Key,Data>();
258  }
259 
260  bool get_bool();
261  uint8_t get_uint8();
262  uint16_t get_uint16();
263  int16_t get_int16();
264  uint32_t get_uint32();
265  int32_t get_int32();
266  uint64_t get_uint64();
267  int64_t get_int64();
268  double get_double();
269  const char* get_string();
271 
272  template <typename T>
273  void get_array_simple( std::vector<T>& array ) {
274  if ( not this->is_fixed() ) /* This should never happen */
275  throw ErrorInvalidTypecast::create( "MessageIterator: Extracting non fixed array into std::vector" );
276 
277  T type;
278  if ( this->element_type() != DBus::type( type ) ) {
279  std::string s = "MessageIterator: Extracting DBus array type ";
280  s += type_string(type);
281  s += " into C++ vector with RTTI type ";
282  s += typeid( T ).name();
283  throw ErrorInvalidTypecast::create( s.c_str() );
284  }
285 
286  int elements;
287  T* values;
288 
289  MessageIterator subiter = this->recurse();
290 
291  array.clear();
292 
293  // Get the underlying array
294  dbus_message_iter_get_fixed_array( subiter.cobj(), &values, &elements );
295 
296  // Iteratively add the elements to the array
297  for ( int i=0; i < elements; i++ )
298  array.push_back( values[i] );
299  }
300 
301  template <typename T>
302  std::vector<T> get_array_simple() {
303  if ( not this->is_fixed() ) /* This should never happen */
304  throw ErrorInvalidTypecast::create( "MessageIterator: Extracting non fixed array into std::vector" );
305 
306  T type;
307  if ( this->element_type() != DBus::type( type ) ) {
308  std::string s = "MessageIterator: Extracting DBus array type ";
309  s += type_string(type);
310  s += " into C++ vector with RTTI type ";
311  s += typeid( T ).name();
312  throw ErrorInvalidTypecast::create( s.c_str() );
313  }
314 
315  std::vector<T> array;
316  int elements;
317  T* values;
318 
319  MessageIterator subiter = this->recurse();
320 
321  // Get the underlying array
322  dbus_message_iter_get_fixed_array( subiter.cobj(), &values, &elements );
323 
324  // Iteratively add the elements to the array
325  for ( int i=0; i < elements; i++ )
326  array.push_back( values[i] );
327 
328  return array;
329  }
330 
331  template <typename T>
332  void get_array_complex(std::vector<T> &array) {
333  if ( not this->is_array() ) /* Should never happen */
334  throw ErrorInvalidTypecast::create( "MessageIterator: Extracting non array into std::vector" );
335 
336  T type;
337  if ( this->element_type() != DBus::type( type ) ) {
338  std::string s = "MessageIterator: Extracting DBus array type ";
339  s += type_string(type);
340  s += " into C++ vector with RTTI type ";
341  s += typeid( T ).name();
342  throw ErrorInvalidTypecast::create( s.c_str() );
343  }
344 
345  array.clear();
346 
347  MessageIterator subiter = this->recurse();
348  while( subiter.is_valid() )
349  {
350  //NOTE: we don't need to do subiter.next() here, because
351  //operator>> does that for us
352  T val;
353  subiter >> val;
354  array.push_back( val );
355  }
356  }
357 
358  template <typename T>
359  std::vector<T> get_array_complex() {
360  if ( not this->is_array() ) /* Should never happen */
361  throw ErrorInvalidTypecast::create( "MessageIterator: Extracting non array into std::vector" );
362 
363  T type;
364  if ( this->element_type() != DBus::type( type ) ) {
365  std::string s = "MessageIterator: Extracting DBus array type ";
366  s += type_string(type);
367  s += " into C++ vector with RTTI type ";
368  s += typeid( T ).name();
369  throw ErrorInvalidTypecast::create( s.c_str() );
370  }
371 
372  std::vector<T> array;
373 
374  MessageIterator subiter = this->recurse();
375  while( subiter.is_valid() )
376  {
377  T val;
378  subiter >> val;
379  array.push_back( val );
380  }
381 
382  return array;
383  }
384 
385  template <typename Key, typename Data>
386  void get_dict( std::map<Key,Data>& dict ){
387  Key val_key;
388  Data val_data;
389 
390  MessageIterator subiter = this->recurse();
391  while( subiter.is_valid() ) {
392  MessageIterator subSubiter = subiter.recurse();
393  while( subSubiter.is_valid() )
394  {
395  subSubiter >> val_key;
396  subSubiter >> val_data;
397  dict[ val_key ] = val_data;
398  subSubiter.next();
399  }
400  subiter.next();
401  }
402  }
403 
404  template <typename Key, typename Data>
405  std::map<Key,Data> get_dict(){
406  std::map<Key,Data> newMap;
407  get_dict( newMap );
408  return newMap;
409  }
410 
411 /*
412  template <typename T>
413  void get_array(std::vector<T>& array) {
414 
415  if ( not this->is_array() )
416  throw ErrorInvalidTypecast::create( "MessageIterator: Extracting non array into std::vector" );
417 
418  if ( not this->is_fixed() ){
419 //OKAY, so this is not fixed.
420 //go and extract elements one at a time.
421  T type;
422  MessageIterator subiter = this->recurse();
423 
424  array.clear();
425 
426  subiter >> type;
427 
428  array.push_back( type );
429 
430  return;
431 DBUS_CXX_DEBUG( "ERR: " << __FILE__ << __LINE__ );
432  throw ErrorInvalidTypecast::create( "MessageIterator: Extracting non fixed array into std::vector" );
433 }
434 
435  T type;
436  if ( this->element_type() != DBus::type( type ) ) {
437  std::string s = "MessageIterator: Extracting DBus array type ";
438  s += type_string(type);
439  s += " into C++ vector with RTTI type ";
440  s += typeid( T ).name();
441  throw ErrorInvalidTypecast::create( s.c_str() );
442  }
443 
444  int elements;
445  T* values;
446 
447  MessageIterator subiter = this->recurse();
448 
449  array.clear();
450 
451  // Get the underlying array
452  dbus_message_iter_get_fixed_array( subiter.cobj(), &values, &elements );
453 
454  // Iteratively add the elements to the array
455  for ( int i=0; i < elements; i++ )
456  array.push_back( values[i] );
457 
458  }
459 */
460 
461  /*template<>
462  void get_array<std::string>(std::vector<std::string> &array) {
463  if ( not this->is_array() )
464  throw ErrorInvalidTypecast::create( "MessageIterator: Extracting non array into std::vector" );
465 
466  if ( this->element_type() != DBus::type<std::string>() ) {
467  std::string s = "MessageIterator: Extracting DBus array type ";
468  s += type_string<std::string>();
469  s += " into C++ vector with RTTI type ";
470  s += typeid(std::string).name();
471  throw ErrorInvalidTypecast::create( s.c_str() );
472  }
473 
474  for(MessageIterator subiter = this->recurse(); subiter.is_valid(); subiter.next())
475  {
476  std::string v = subiter.get_string();
477  array.push_back(v);
478  }
479  }
480 */
481 
482  template <typename Key, typename Data>
483  MessageIterator& operator>>( std::map<Key,Data>& m )
484  {
485  if ( not this->is_dict() )
486  throw ErrorInvalidTypecast::create( "MessageIterator: Extracting non dict into std::map" );
487  try{
488  get_dict<Key,Data>( m );
489  this->next();
490  return *this;
491  }catch(DBusCxxPointer<DBus::ErrorInvalidTypecast> e){
492  //TODO make sure we don't need this? it doesn't make much sense
493  throw (ErrorInvalidTypecast)*e;
494  }
495  }
496 
497 
498  template <typename T>
499  MessageIterator& operator>>( std::vector<T>& v )
500  {
501  if ( not this->is_array() )
502  throw ErrorInvalidTypecast::create( "MessageIterator: Extracting non array into std::vector" );
503  try{
504  // this->get_array<T>(v);
505  if ( this->is_fixed() )
506  get_array_simple<T>( v );
507  else
508  get_array_complex<T>( v );
509  this->next();
510  return *this;
511  }catch(DBusCxxPointer<DBus::ErrorInvalidTypecast> e){
512  throw (ErrorInvalidTypecast)*e;
513  }
514  }
515 
516  template <typename T>
518  {
519  try{
520  v = (T)(*this);
521  this->next();
522  return *this;
523  }catch(DBusCxxPointer<DBus::ErrorInvalidTypecast> e){
524  throw (ErrorInvalidTypecast)*e;
525  }
526  }
527 
528  template <typename T>
530  {
531  try{
532  MessageIterator subiter = this->recurse();
533  dbus_message_iter_get_basic(subiter.cobj(), &v.data);
534  this->next();
535  return *this;
536  }catch(DBusCxxPointer<DBus::ErrorInvalidTypecast> e){
537  throw (ErrorInvalidTypecast)*e;
538  }
539  }
540 
541  template <typename T>
542  void value( T& temp ) {
543  if ( this->arg_type() != DBus::type( temp ) ) {
544  std::string s = "MessageIterator: Extracting DBus type ";
545  s += type_string( temp );
546  s += " into C++ RTTI type ";
547  s += typeid( T ).name();
548  throw ErrorInvalidTypecast( s.c_str() );
549  }
550  dbus_message_iter_get_basic( &m_cobj, &temp );
551  }
552 
553  protected:
555  DBusMessageIter m_cobj;
556 
557  };
558 
559 /*
560  template<>
561  void inline MessageIterator::get_array(std::vector<std::string> &array) {
562  std::string s_;
563  if ( not this->is_array() )
564  throw ErrorInvalidTypecast::create( "MessageIterator: Extracting non array into std::vector" );
565 
566  if ( this->element_type() != DBus::type(s_) ) {
567  std::string s = "MessageIterator: Extracting DBus array type ";
568  s += type_string(s_);
569  s += " into C++ vector with RTTI type ";
570  s += typeid(std::string).name();
571  throw ErrorInvalidTypecast::create( s.c_str() );
572  }
573 
574  for(MessageIterator subiter = this->recurse(); subiter.is_valid(); subiter.next())
575  {
576  std::string v = subiter.get_string();
577  array.push_back(v);
578  }
579  }
580 */
581 
582 }
583 
584 #endif
uint32_t get_uint32()
Definition: messageiterator.cpp:514
MessageIterator & operator++()
Definition: messageiterator.cpp:106
MessageIterator recurse()
If the iterator points to a container recurses into the container returning a sub-iterator.
Definition: messageiterator.cpp:157
DBusMessageIter * cobj()
Returns a pointer to the underlying DBusMessageIter object.
Definition: messageiterator.cpp:53
std::map< Key, Data > get_dict()
Definition: messageiterator.h:405
uint16_t get_uint16()
Definition: messageiterator.cpp:494
bool get_bool()
Definition: messageiterator.cpp:464
bool init(const Message &message)
Initializes the iterator for the specified message.
Definition: messageiterator.cpp:58
Definition: accumulators.h:24
void get_dict(std::map< Key, Data > &dict)
Definition: messageiterator.h:386
bool operator==(const MessageIterator &other)
Definition: messageiterator.cpp:120
const char * get_string()
Definition: messageiterator.cpp:554
uint8_t get_uint8()
Definition: messageiterator.cpp:474
Type element_type() const
Returns the element type of the array that the iterator points to.
Definition: messageiterator.cpp:130
DBusMessageIter m_cobj
Definition: messageiterator.h:555
std::vector< T > get_array_simple()
Definition: messageiterator.h:302
bool is_dict() const
True if the iterator points to a dictionary.
Definition: messageiterator.cpp:152
MessageIterator & operator>>(std::vector< T > &v)
Definition: messageiterator.h:499
bool is_valid() const
True if this is a valid iterator.
Definition: messageiterator.cpp:76
bool is_fixed() const
True if the element type is a fixed type.
Definition: messageiterator.cpp:137
int64_t get_int64()
Definition: messageiterator.cpp:524
A Variant is a type of DBus object that can be one of several different types of normal DBus object...
Definition: variant.h:33
Type arg_type() const
Returns the argument type that the iterator points to.
Definition: messageiterator.cpp:125
MessageIterator & operator>>(Variant< T > &v)
Definition: messageiterator.h:529
MessageIterator & operator>>(std::map< Key, Data > &m)
Definition: messageiterator.h:483
uint64_t get_uint64()
Definition: messageiterator.cpp:534
FileDescriptor get_filedescriptor()
Definition: messageiterator.cpp:563
const Message * message() const
Returns a pointer to the message associated with this iterator or NULL if no message is associated...
Definition: messageiterator.cpp:48
This class represents a basic DBus message and also serves as a base class for the specialized messag...
Definition: message.h:56
void get_array_simple(std::vector< T > &array)
Definition: messageiterator.h:273
const Message * m_message
Definition: messageiterator.h:554
std::string signature() const
Returns the current signature of the iterator.
Definition: messageiterator.cpp:168
MessageIterator()
Definition: messageiterator.cpp:28
void get_array_complex(std::vector< T > &array)
Definition: messageiterator.h:332
int16_t get_int16()
Definition: messageiterator.cpp:484
std::string type_string(uint8_t &)
Definition: types.h:91
void invalidate()
Invalidates the iterator.
Definition: messageiterator.cpp:70
A FileDescriptor holds a UNIX file descriptor that can be passed between processes.
Definition: filedescriptor.h:30
double get_double()
Definition: messageiterator.cpp:544
void value(T &temp)
Definition: messageiterator.h:542
MessageIterator & operator>>(T &v)
Definition: messageiterator.h:517
Type
Definition: enums.h:41
std::vector< T > get_array_complex()
Definition: messageiterator.h:359
Type type(uint8_t)
Definition: types.h:38
bool next()
Moves the iterator to the next field and invalidates it if it moves beyond the last field...
Definition: messageiterator.cpp:89
Extraction iterator allowing values to be retrieved from a message.
Definition: messageiterator.h:37
int32_t get_int32()
Definition: messageiterator.cpp:504
T data
Definition: variant.h:36
bool is_array() const
True if the iterator points to an array.
Definition: messageiterator.cpp:147
bool is_container() const
True if the iterator points to a container.
Definition: messageiterator.cpp:142
bool has_next() const
True if there are any more fields left to iterate over.
Definition: messageiterator.cpp:83

Generated on Sun Mar 19 2017 14:54:27 for dbus-cxx by doxygen 1.8.8