libqi-api  2.4.3.28
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
structtypeinterface.hxx
Go to the documentation of this file.
1 #pragma once
2 /*
3 ** Copyright (C) 2013 Aldebaran Robotics
4 ** See COPYING for the license
5 */
6 
7 #ifndef _QITYPE_DETAILS_TYPETUPLE_HXX_
8 #define _QITYPE_DETAILS_TYPETUPLE_HXX_
9 
10 #include <boost/type_traits.hpp>
11 #include <boost/utility/enable_if.hpp>
12 #include <qi/type/fwd.hpp>
14 #include <qi/preproc.hpp>
15 
16 namespace qi
17 {
18  namespace detail {
19 
20  template<typename T> struct StructVersioningDelegateDrop
21  {
22  static bool canDropFields(void*, const std::vector<std::string>&) { return false;}
23  };
24  template<typename T> struct StructVersioningDelegateFill
25  {
26  static bool fillMissingFields(StructTypeInterface* type, std::map<std::string, ::qi::AnyValue>& fields, const std::vector<std::string>& missing) { return false;}
27  };
29  std::map<std::string, ::qi::AnyValue>& fields,
30  const std::vector<std::string>& missing,
31  const char** which=0, int whichLength=0);
32 
38 #define QI_TYPE_STRUCT_EXTENSION_FILL_FIELDS(name, ...) \
39  namespace qi { namespace detail { template<> struct StructVersioningDelegateFill<name> { \
40  static bool fillMissingFields(StructTypeInterface* type, std::map<std::string, ::qi::AnyValue>& fields, const std::vector<std::string>& missing) \
41  { \
42  const char* which[] = {__VA_ARGS__ }; \
43  int count = sizeof(which) / sizeof(char*); \
44  return fillMissingFieldsWithDefaultValues(type, fields, missing, which, count); \
45  } \
46  };}}
47 #define QI_TYPE_STRUCT_EXTENSION_FILL_ALL(name, ...) \
49  namespace qi { namespace detail { template<> struct StructVersioningDelegateFill<name> { \
50  static bool fillMissingFields(StructTypeInterface* type, std::map<std::string, ::qi::AnyValue>& fields, const std::vector<std::string>& missing) \
51  { \
52  return fillMissingFieldsWithDefaultValues(type, fields, missing); \
53  } \
54  };}}
55 #define QI_TYPE_STRUCT_EXTENSION_DROP_ALL(name) \
57  namespace qi { namespace detail { template<> struct StructVersioningDelegateDrop<name> { \
58  static bool canDropFields(void*, const std::vector<std::string>&) { return true;} \
59  };}}
60 
62 #define QI_TYPE_STRUCT_EXTENSION_DROP_FIELDS(name, ...) \
63  namespace qi { namespace detail { template<> struct StructVersioningDelegateDrop<name> { \
64  static bool canDropFields(void*, const std::vector<std::string>& fields) { \
65  const char* okFields[] = {__VA_ARGS__ }; \
66  int count = sizeof(okFields) / sizeof(char*); \
67  for (unsigned i=0; i<fields.size(); ++i) \
68  if (std::find(okFields, okFields+count, fields[i]) == okFields+count) return false; \
69  return true; \
70  } \
71  };}}
72 
77 #define QI_TYPE_STRUCT_EXTENSION_DROP_HANDLER(name, f) \
78  namespace qi { namespace detail { template<> struct StructVersioningDelegateDrop<name> { \
79  static bool canDropFields(void* store, const std::vector<std::string>& fields) { \
80  return f((name*)store, fields);} \
81  };}}
82 
89 #define QI_TYPE_STRUCT_EXTENSION_FILL_HANDLER(name, f) \
90  namespace qi { namespace detail { template<> struct StructVersioningDelegateFill<name> { \
91  static bool fillMissingFields(StructTypeInterface* type, std::map<std::string, ::qi::AnyValue>& fields, const std::vector<std::string>& missing) \
92  { \
93  return f(fields, missing) ; \
94  }};}}
95 
102 #define QI_TYPE_STRUCT_EXTENSION_ALL(name) \
103  QI_TYPE_STRUCT_EXTENSION_DROP_ALL(name); \
104  QI_TYPE_STRUCT_EXTENSION_FILL_ALL(name)
105 
107 #define QI_TYPE_STRUCT_EXTENSION_FIELDS(name, ...) \
108  QI_TYPE_STRUCT_EXTENSION_DROP_FIELDS(name, __VA_ARGS__); \
109  QI_TYPE_STRUCT_EXTENSION_FILL_FIELDS(name, __VA_ARGS__)
110 
111  //keep only the class name. (remove :: and namespaces)
112  QI_API std::string normalizeClassName(const std::string &name);
113 
114  template<typename T> void setFromStorage(T& ref, void* storage)
115  {
116  ref = *(T*)typeOf<T>()->ptrFromStorage(&storage);
117  }
118 
119  /* Helpers around accessors
120  */
121  template<typename A> TypeInterface* fieldType(A)
122  {
123  static TypeInterface* res = 0;
124  QI_ONCE(res = qi::typeOf<typename detail::Accessor<A>::value_type>());
125  return res;
126  }
127 
128  template<typename C, typename A> void* fieldStorage(C* inst, A accessor)
129  {
130  return fieldType(accessor)->initializeStorage(
131  (void*)&detail::Accessor<A>::access(inst, accessor));
132  }
133 
134  template<typename C, typename A>
135  typename detail::Accessor<A>::value_type&
136  fieldValue(C* instance, A accessor, void** data)
137  {
138  typedef typename detail::Accessor<A>::value_type T;
139  return *(T*)fieldType(accessor)->ptrFromStorage(data);
140  }
141  }
142 }
143 
144 
145 #define __QI_TYPE_STRUCT_DECLARE(name, extra) \
146 namespace qi { \
147  template<> struct TypeImpl<name>: public ::qi::StructTypeInterface \
148  { \
149  public: \
150  typedef name ClassType; \
151  TypeImpl(); \
152  virtual std::vector< ::qi::TypeInterface*> memberTypes(); \
153  virtual std::vector<std::string> elementsName(); \
154  virtual std::string className(); \
155  virtual void* get(void* storage, unsigned int index); \
156  virtual void set(void** storage, unsigned int index, void* valStorage); \
157  virtual bool canDropFields(void* storage, const std::vector<std::string>& fieldNames); \
158  virtual bool fillMissingFields(std::map<std::string, ::qi::AnyValue>& fields, const std::vector<std::string>& missing); \
159  extra \
160  typedef ::qi::DefaultTypeImplMethods<name, ::qi::TypeByPointerPOD<name> > Impl; \
161  _QI_BOUNCE_TYPE_METHODS(Impl); \
162  }; }
163 
164 
165 #define __QI_TUPLE_TYPE(_, what, field) res.push_back(::qi::typeOf(ptr->field));
166 #define __QI_TUPLE_GET(_, what, field) if (i == index) return ::qi::typeOf(ptr->field)->initializeStorage(&ptr->field); i++;
167 #define __QI_TUPLE_SET(_, what, field) if (i == index) ::qi::detail::setFromStorage(ptr->field, valueStorage); i++;
168 #define __QI_TUPLE_FIELD_NAME(_, what, field) res.push_back(BOOST_PP_STRINGIZE(QI_DELAY(field)));
169 #define __QI_TYPE_STRUCT_IMPLEMENT(name, inl, onSet, ...) \
170 namespace qi { \
171  inl TypeImpl<name>::TypeImpl() { \
172  ::qi::registerStruct(this); \
173  } \
174  inl std::vector< ::qi::TypeInterface*> TypeImpl<name>::memberTypes() \
175  { \
176  name* ptr = 0; \
177  std::vector< ::qi::TypeInterface*> res; \
178  QI_VAARGS_APPLY(__QI_TUPLE_TYPE, _, __VA_ARGS__); \
179  return res; \
180  } \
181  inl void* TypeImpl<name>::get(void* storage, unsigned int index) \
182  { \
183  unsigned int i = 0; \
184  name* ptr = (name*)ptrFromStorage(&storage); \
185  QI_VAARGS_APPLY(__QI_TUPLE_GET, _, __VA_ARGS__); \
186  return 0; \
187  } \
188  inl void TypeImpl<name>::set(void** storage, unsigned int index, void* valueStorage)\
189  { \
190  unsigned int i=0; \
191  name* ptr = (name*)ptrFromStorage(storage); \
192  QI_VAARGS_APPLY(__QI_TUPLE_SET, _, __VA_ARGS__); \
193  onSet \
194  }\
195  inl std::vector<std::string> TypeImpl<name>::elementsName() \
196  { \
197  std::vector<std::string> res; \
198  QI_VAARGS_APPLY(__QI_TUPLE_FIELD_NAME, _, __VA_ARGS__); \
199  return res; \
200  }\
201  inl std::string TypeImpl<name>::className() \
202  {\
203  return ::qi::detail::normalizeClassName(BOOST_PP_STRINGIZE(name));\
204  }\
205  inl bool TypeImpl<name>::canDropFields(void* storage, const std::vector<std::string>& fieldNames) {return ::qi::detail::StructVersioningDelegateDrop<name>::canDropFields(storage, fieldNames);} \
206  inl bool TypeImpl<name>::fillMissingFields(std::map<std::string, ::qi::AnyValue>& fields, const std::vector<std::string>& missing) {return ::qi::detail::StructVersioningDelegateFill<name>::fillMissingFields(this, fields, missing);} \
207 }
208 
209 
210 
212 #define QI_STRUCT_HELPER(name, func) (name, func, FUNC)
213 #define QI_STRUCT_FIELD(name, field) (name, field, FIELD)
215 
216 // construct pointer-to accessor from free-function
217 #define __QI_STRUCT_ACCESS_FUNC(fname, field) &field
218 // construct pointer-to-accessor from member function/field
219 #define __QI_STRUCT_ACCESS_FIELD(fname, field) &ClassType::field
220 
221 // invoke the correct __QI_STRUCT_ACCESS_ macro using type
222 #define __QI_STRUCT_ACCESS_BOUNCE2(name, accessor, type) \
223  QI_CAT(__QI_STRUCT_ACCESS_, type)(name, accessor)
224 
225 // bounce with default value FIELD for argument 3
226 #define __QI_STRUCT_ACCESS_BOUNCE1(x, y) \
227  __QI_STRUCT_ACCESS_BOUNCE2(x, y, FIELD)
228 
229 // arg-count overload, bounce to __QI_STRUCT_ACCESS_BOUNCE<N>
230 #define __QI_STRUCT_ACCESS_BOUNCE(...) \
231  QI_CAT(__QI_STRUCT_ACCESS_BOUNCE, QI_LIST_VASIZE((__VA_ARGS__)))(__VA_ARGS__)
232 
233 // accept (name, accessor, type) and (name, accessor) defaulting type to field
234 #define __QI_STRUCT_ACCESS(tuple) QI_DELAY(__QI_STRUCT_ACCESS_BOUNCE)tuple
235 
236 
237 #define __QI_ATUPLE_TYPE(_, what, field) res.push_back(::qi::detail::fieldType(__QI_STRUCT_ACCESS(field)));
238 #define __QI_ATUPLE_GET(_, what, field) if (i == index) return ::qi::detail::fieldStorage(ptr, __QI_STRUCT_ACCESS(field)); i++;
239 #define __QI_ATUPLE_FIELD_NAME(_, what, field) res.push_back(QI_PAIR_FIRST(field));
240 #define __QI_ATUPLE_FROMDATA(idx, what, field) ::qi::detail::fieldValue(ptr, __QI_STRUCT_ACCESS(field), const_cast<void**>(&data[idx]))
241 #define __QI_TYPE_STRUCT_AGREGATE_CONSTRUCTOR_IMPLEMENT(name, inl, onSet, ...)\
242  namespace qi { \
243  inl TypeImpl<name>::TypeImpl() { \
244  ::qi::registerStruct(this); \
245  } \
246  inl std::vector< ::qi::TypeInterface*> TypeImpl<name>::memberTypes() \
247  { \
248  std::vector< ::qi::TypeInterface*> res; \
249  QI_VAARGS_APPLY(__QI_ATUPLE_TYPE, name, __VA_ARGS__); \
250  return res; \
251  } \
252  \
253  inl void* TypeImpl<name>::get(void* storage, unsigned int index) \
254  { \
255  unsigned int i = 0; \
256  name* ptr = (name*)ptrFromStorage(&storage); \
257  QI_VAARGS_APPLY(__QI_ATUPLE_GET, name, __VA_ARGS__); \
258  return 0; \
259  } \
260  \
261  inl void TypeImpl<name>::set(void** storage, unsigned int index, void* valueStorage)\
262  {\
263  throw std::runtime_error("single-field set not implemented");\
264  }\
265  \
266  inl void TypeImpl<name>::set(void** storage, const std::vector<void*>& data) \
267  {\
268  name* ptr = (name*)ptrFromStorage(storage); \
269  *ptr = name(QI_VAARGS_MAP(__QI_ATUPLE_FROMDATA, name, __VA_ARGS__)); \
270  }\
271  \
272  inl std::vector<std::string> TypeImpl<name>::elementsName() \
273  { \
274  std::vector<std::string> res; \
275  QI_VAARGS_APPLY(__QI_ATUPLE_FIELD_NAME, _, __VA_ARGS__); \
276  return res; \
277  }\
278  inl std::string TypeImpl<name>::className() \
279  \
280  { \
281  return ::qi::detail::normalizeClassName(BOOST_PP_STRINGIZE(name));\
282  } \
283  inl bool TypeImpl<name>::canDropFields(void* storage, const std::vector<std::string>& fieldNames) {return ::qi::detail::StructVersioningDelegateDrop<name>::canDropFields(storage, fieldNames);} \
284  inl bool TypeImpl<name>::fillMissingFields(std::map<std::string, ::qi::AnyValue>& fields, const std::vector<std::string>& missing) {return ::qi::detail::StructVersioningDelegateFill<name>::fillMissingFields(this, fields, missing);} \
285  }
286 
287 
289 #define QI_TYPE_STRUCT_PRIVATE_ACCESS(name) \
290 friend class qi::TypeImpl<name>;
291 
301 #define QI_TYPE_STRUCT(name, ...) \
302  QI_TYPE_STRUCT_DECLARE(name) \
303  __QI_TYPE_STRUCT_IMPLEMENT(name, inline, , __VA_ARGS__)
304 
308 #define QI_TYPE_STRUCT_EX(name, onSet, ...) \
309  QI_TYPE_STRUCT_DECLARE(name) \
310  __QI_TYPE_STRUCT_IMPLEMENT(name, inline, onSet, __VA_ARGS__)
311 
312 #define QI_TYPE_STRUCT_IMPLEMENT(name, ...) \
313  __QI_TYPE_STRUCT_IMPLEMENT(name, , , __VA_ARGS__)
314 
337 #define QI_TYPE_STRUCT_AGREGATE_CONSTRUCTOR(name, ...) \
338  __QI_TYPE_STRUCT_DECLARE(name, \
339  virtual void set(void** storage, const std::vector<void*>&);) \
340  __QI_TYPE_STRUCT_AGREGATE_CONSTRUCTOR_IMPLEMENT(name, inline, , __VA_ARGS__)
341 
348 #define QI_TYPE_STRUCT_REGISTER(name, ...) \
349 namespace _qi_ { \
350  QI_TYPE_STRUCT(name, __VA_ARGS__) \
351 } \
352 QI_TYPE_REGISTER_CUSTOM(name, _qi_::qi::TypeImpl<name>)
353 
359 #define QI_TYPE_STRUCT_AGREGATE_CONSTRUCTOR_REGISTER(name, ...) \
360 namespace _qi_ { \
361  QI_TYPE_STRUCT_AGREGATE_CONSTRUCTOR(name, __VA_ARGS__); \
362 } \
363 QI_TYPE_REGISTER_CUSTOM(name, _qi_::qi::TypeImpl<name>)
364 
372 #define QI_TYPE_STRUCT_BOUNCE(name, bounceTo, conversion) \
373 namespace qi { \
374 template<> class TypeImpl<name>: public ::qi::StructTypeInterfaceBouncer<name, bounceTo> \
375 { \
376 public: \
377  void adaptStorage(void** storage, void** adapted) \
378  { \
379  name* ptr = (name*)ptrFromStorage(storage); \
380  bounceTo * tptr = conversion(ptr); \
381  *adapted = bounceType()->initializeStorage(tptr); \
382  } \
383  std::string className() \
384  { \
385  return ::qi::detail::normalizeClassName(BOOST_PP_STRINGIZE(name)); \
386  } \
387 };}
388 
392 #define QI_TYPE_STRUCT_BOUNCE_REGISTER(name, bounceTo, conversion) \
393 namespace _qi_ { \
394  QI_TYPE_STRUCT_BOUNCE(name, bounceTo, conversion); \
395 } \
396 QI_TYPE_REGISTER_CUSTOM(name, _qi_::qi::TypeImpl<name>)
397 
398 
399 
400 namespace qi {
401  template<typename T, typename TO>
403  {
404  public:
406  {
407  static TypeInterface* result = 0;
408  if (!result)
409  result = typeOf<TO>();
410  return static_cast<StructTypeInterface*>(result);
411  }
412 
413  virtual void adaptStorage(void** storage, void** adapted) = 0;
414 
416  virtual std::vector<TypeInterface*> memberTypes()
417  {
418  return bounceType()->memberTypes();
419  }
420 
421  virtual void* get(void* storage, unsigned int index)
422  {
423  void* astorage;
424  adaptStorage(&storage, &astorage);
425  return bounceType()->get(astorage, index);
426  }
427 
428  virtual std::vector<void*> get(void* storage)
429  {
430  void* astorage;
431  adaptStorage(&storage, &astorage);
432  return bounceType()->get(astorage);
433  }
434 
435  virtual void set(void** storage, const std::vector<void*>& vals)
436  {
437  void* astorage;
438  adaptStorage(storage, &astorage);
439  bounceType()->set(&astorage, vals);
440  }
441 
442  virtual void set(void** storage, unsigned int index, void* valStorage)
443  {
444  void* astorage;
445  adaptStorage(storage, &astorage);
446  bounceType()->set(&astorage, index, valStorage);
447  }
448 
449  virtual std::vector<std::string> elementsName()
450  {
451  return bounceType()->elementsName();
452  }
453 
454  virtual bool fillMissingFields(std::map<std::string, ::qi::AnyValue>& fields, const std::vector<std::string>& missing) {
455  return bounceType()->fillMissingFields(fields, missing);
456  }
457 
459  };
460 
461  template<typename F, typename S>
462  class TypeImpl<std::pair<F, S> >: public StructTypeInterface
463  {
464  public:
466  typedef typename std::pair<F, S> BackendType;
468  {
469  _memberTypes.push_back(typeOf<F>());
470  _memberTypes.push_back(typeOf<S>());
471  }
472  std::vector<TypeInterface*> _memberTypes;
473 
474  std::vector<TypeInterface*> memberTypes() { return _memberTypes;}
475  void* get(void* storage, unsigned int index)
476  {
477  BackendType* ptr = (BackendType*)ptrFromStorage(&storage);
478  // Will work if F or S are references
479  if (!index)
480  return typeOf<F>()->initializeStorage(const_cast<void*>((void*)&ptr->first));
481  else
482  return typeOf<S>()->initializeStorage(const_cast<void*>((void*)&ptr->second));
483  }
484  void set(void** storage, unsigned int index, void* valStorage)
485  {
486  BackendType* ptr = (BackendType*)ptrFromStorage(storage);
487  const std::vector<TypeInterface*>& types = _memberTypes;
488 
489 
490  // FIXME cheating, we do not go through TypeInterface of S and F for copy
491  // because typeerasure does not expose the interface
492  if (!index)
493  detail::TypeTraitCopy<typename boost::remove_const<F>::type, true>::copy(const_cast<void*>((void*)&ptr->first), types[0]->ptrFromStorage(&valStorage));
494  else
495  detail::TypeTraitCopy<typename boost::remove_const<S>::type, true>::copy(const_cast<void*>((void*)&ptr->second), types[1]->ptrFromStorage(&valStorage));
496  }
497  _QI_BOUNCE_TYPE_METHODS(Methods);
498  };
499 
500 }
501 #endif // _QITYPE_DETAILS_TYPETUPLE_HXX_
virtual void * ptrFromStorage(void **)=0
void setFromStorage(T &ref, void *storage)
#define QI_API
Definition: api.hpp:34
std::vector< TypeInterface * > memberTypes()
bool fillMissingFieldsWithDefaultValues(StructTypeInterface *type, std::map< std::string,::qi::AnyValue > &fields, const std::vector< std::string > &missing, const char **which=0, int whichLength=0)
DefaultTypeImplMethods< std::pair< F, S >, TypeByPointerPOD< std::pair< F, S > > > Methods
virtual std::vector< TypeInterface * > memberTypes()=0
detail::Accessor< A >::value_type & fieldValue(C *instance, A accessor, void **data)
virtual std::vector< TypeInterface * > memberTypes()
#define _QI_BOUNCE_TYPE_METHODS(Bounce)
Implement all methods of Type as bouncers to Bouncer.
Definition: typeimpl.hxx:275
virtual bool fillMissingFields(std::map< std::string, AnyValue > &fields, const std::vector< std::string > &missing)
Fill missing fields caused by conversion from a different struct. Return whether fill succeeded...
std::vector< TypeInterface * > _memberTypes
static bool fillMissingFields(StructTypeInterface *type, std::map< std::string,::qi::AnyValue > &fields, const std::vector< std::string > &missing)
#define QI_ONCE(code)
Execute code once, parallel calls are blocked until code finishes.
Definition: atomic.hpp:298
virtual std::vector< void * > get(void *storage)
Get all the fields storages of the struct (not a copy)
virtual std::vector< std::string > elementsName()
Get the names of the fields of the struct.
static bool canDropFields(void *, const std::vector< std::string > &)
virtual void adaptStorage(void **storage, void **adapted)=0
virtual std::vector< std::string > elementsName()
Get the names of the fields of the struct.
virtual void set(void **storage, unsigned int index, void *valStorage)
Set the fields of the struct at index (copies the value given)
StructTypeInterface * bounceType()
TypeInterface * typeOf()
Definition: type.hxx:91
void * fieldStorage(C *inst, A accessor)
TypeInterface * fieldType(A)
virtual void * initializeStorage(void *ptr=0)
Definition: typeimpl.hxx:294
virtual void set(void **storage, const std::vector< void * > &)
Set all the fields of the struct (copies the values given in the vector)
virtual void set(void **storage, const std::vector< void * > &vals)
Set all the fields of the struct (copies the values given in the vector)
virtual bool fillMissingFields(std::map< std::string,::qi::AnyValue > &fields, const std::vector< std::string > &missing)
std::string normalizeClassName(const std::string &name)
void set(void **storage, unsigned int index, void *valStorage)
Set the fields of the struct at index (copies the value given)
virtual void * ptrFromStorage(void **s)
Definition: typeimpl.hxx:294
DefaultTypeImplMethods< T, TypeByPointerPOD< T > > Methods
virtual void * initializeStorage(void *ptr=0)=0