MIP_SDK  v3.0.0-208-gdb90bae
MicroStrain Communications Library for embedded systems
mip_meta_utils.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include "mip_structures.hpp"
4 
6 {
7  //
8  // Gets the "Type" enum value given a C++ template type.
9  //
10  template<class T, class=void> struct ParamType { static inline constexpr Type value = Type::NONE; };
11 
12  template<> struct ParamType<char, void> { static constexpr inline Type value = Type::CHAR; };
13  template<> struct ParamType<bool, void> { static constexpr inline Type value = Type::BOOL; };
14  template<> struct ParamType<uint8_t, void> { static constexpr inline Type value = Type::U8; };
15  template<> struct ParamType< int8_t, void> { static constexpr inline Type value = Type::S8; };
16  template<> struct ParamType<uint16_t, void> { static constexpr inline Type value = Type::U16; };
17  template<> struct ParamType< int16_t, void> { static constexpr inline Type value = Type::S16; };
18  template<> struct ParamType<uint32_t, void> { static constexpr inline Type value = Type::U32; };
19  template<> struct ParamType< int32_t, void> { static constexpr inline Type value = Type::S32; };
20  template<> struct ParamType<uint64_t, void> { static constexpr inline Type value = Type::U64; };
21  template<> struct ParamType< int64_t, void> { static constexpr inline Type value = Type::S64; };
22  template<> struct ParamType<float, void> { static constexpr inline Type value = Type::FLOAT; };
23  template<> struct ParamType<double, void> { static constexpr inline Type value = Type::DOUBLE; };
24  template<class T> struct ParamType<Bitfield<T>, void> { static constexpr inline Type value = Type::BITS; };
25  template<class T> struct ParamType<T, typename std::enable_if<std::is_enum<T>::value, T>::type> { static constexpr inline Type value = Type::ENUM; };
26  template<class T> struct ParamType<T, typename EnableForFieldTypes<T>::type> { static constexpr inline Type value = Type::STRUCT; };
27  template<class T> struct ParamType<T, typename std::enable_if<std::is_union<T>::value, T>::type> { static constexpr inline Type value = Type::UNION; };
28 
29 
30  //
31  // Gets the template type given a compile-time "Type" enum value.
32  // Note: this only works with basic/built-in/arithmetic types, not structs/enums/etc.
33  //
34  template<Type Kind>
35  struct ParamEnum { using type = void; };
36 
37  template<> struct ParamEnum<Type::CHAR > { using type = char; };
38  template<> struct ParamEnum<Type::BOOL > { using type = bool; };
39  template<> struct ParamEnum<Type::U8 > { using type = uint8_t; };
40  template<> struct ParamEnum<Type::S8 > { using type = int8_t; };
41  template<> struct ParamEnum<Type::U16 > { using type = uint16_t; };
42  template<> struct ParamEnum<Type::S16 > { using type = int16_t; };
43  template<> struct ParamEnum<Type::U32 > { using type = uint32_t; };
44  template<> struct ParamEnum<Type::S32 > { using type = int32_t; };
45  template<> struct ParamEnum<Type::U64 > { using type = uint64_t; };
46  template<> struct ParamEnum<Type::S64 > { using type = int64_t; };
47  template<> struct ParamEnum<Type::FLOAT > { using type = float; };
48  template<> struct ParamEnum<Type::DOUBLE> { using type = double; };
49 
50 
51  // Gets a void pointer to the member identified by Ptr, given an
52  // instance of field passed by void pointer.
53  /*template<class Field, class T, T Field::*Ptr>
54  void* access(void* p)
55  {
56  return &(static_cast<Field*>(p)->*Ptr);
57  }
58 
59  template<class Field, class T, auto Ptr>
60  void* access(void* p)
61  {
62  Field* f = static_cast<Field*>(p);
63  auto& param = f->*Ptr;
64  return &param;
65  }*/
66 
67  // template<class Field, class T, auto Ptr>
68  // void* access(void* p);
69 
70 
71 #ifdef MICROSTRAIN_HAS_OPTIONAL
72  inline std::optional<uint64_t> extractIntegralType(mip::metadata::Type type, microstrain::Span<const uint8_t> payload, size_t offset=0)
75  {
76  switch(type)
77  {
78  case mip::metadata::Type::BOOL: return microstrain::extract< bool, microstrain::serialization::Endian::big>(payload.data(), payload.size(), offset);
79  case mip::metadata::Type::U8: return microstrain::extract< uint8_t, microstrain::serialization::Endian::big>(payload.data(), payload.size(), offset);
80  case mip::metadata::Type::S8: return microstrain::extract< int8_t, microstrain::serialization::Endian::big>(payload.data(), payload.size(), offset);
81  case mip::metadata::Type::U16: return microstrain::extract<uint16_t, microstrain::serialization::Endian::big>(payload.data(), payload.size(), offset);
82  case mip::metadata::Type::S16: return microstrain::extract< int32_t, microstrain::serialization::Endian::big>(payload.data(), payload.size(), offset);
83  case mip::metadata::Type::U32: return microstrain::extract<uint32_t, microstrain::serialization::Endian::big>(payload.data(), payload.size(), offset);
84  case mip::metadata::Type::S32: return microstrain::extract< int64_t, microstrain::serialization::Endian::big>(payload.data(), payload.size(), offset);
85  case mip::metadata::Type::U64: return microstrain::extract<uint64_t, microstrain::serialization::Endian::big>(payload.data(), payload.size(), offset);
86  case mip::metadata::Type::S64: return microstrain::extract< int64_t, microstrain::serialization::Endian::big>(payload.data(), payload.size(), offset);
87  default: return std::nullopt;
88  }
89  }
90 #endif // MICROSTRAIN_HAS_OPTIONAL
91 
99  inline Type serializedType(const TypeInfo& type)
100  {
101  if (type.isBasicType())
102  return type.type;
103 
104  if (const EnumInfo* ptr = type.enumPointer())
105  return ptr->type;
106 
107  if (const BitfieldInfo* ptr = type.bitfieldPointer())
108  return ptr->type;
109 
110  return Type::NONE;
111  }
112 
115  constexpr size_t serializedSizeForBasicType(Type type, const void* info = nullptr)
116  {
117  switch(type)
118  {
119  case Type::CHAR:
120  case Type::BOOL:
121  case Type::U8:
122  case Type::S8:
123  return 1;
124  case Type::U16:
125  case Type::S16:
126  return 2;
127  case Type::U32:
128  case Type::S32:
129  case Type::FLOAT:
130  return 4;
131  case Type::U64:
132  case Type::S64:
133  case Type::DOUBLE:
134  return 8;
135 
136  case Type::ENUM:
137  if (!info)
138  return 0;
139  return serializedSizeForBasicType(static_cast<const EnumInfo* >(info)->type);
140 
141  case Type::BITS:
142  if (!info)
143  return 0;
144  return serializedSizeForBasicType(static_cast<const BitfieldInfo* >(info)->type);
145 
146  default:
147  return 0;
148  }
149  }
150  constexpr size_t serializedSizeForBasicType(const TypeInfo& type) { return serializedSizeForBasicType(type.type, type.infoPtr); }
151 
152  constexpr const char* nameForBasicType(Type type)
153  {
154  switch(type)
155  {
156  case Type::NONE: return "none";
157  case Type::BOOL: return "bool";
158  case Type::CHAR: return "char";
159  case Type::U8: return "u8";
160  case Type::S8: return "s8";
161  case Type::U16: return "u16";
162  case Type::S16: return "s16";
163  case Type::U32: return "u32";
164  case Type::S32: return "s32";
165  case Type::U64: return "u64";
166  case Type::S64: return "s64";
167  case Type::FLOAT: return "float";
168  case Type::DOUBLE: return "double";
169  case Type::ENUM: return "enum";
170  case Type::BITS: return "bitfield";
171  case Type::STRUCT: return "struct";
172  case Type::UNION: return "union";
173  default: return nullptr;
174  }
175  }
176 
177  constexpr const char* nameOfType(const TypeInfo& type)
178  {
179  switch(type.type)
180  {
181  default: return nameForBasicType(type.type);
182  case Type::ENUM: return type.infoPtr ? static_cast<const EnumInfo* >(type.infoPtr)->name : "enum";
183  case Type::BITS: return type.infoPtr ? static_cast<const BitfieldInfo*>(type.infoPtr)->name : "bitfield";
184  case Type::STRUCT: return type.infoPtr ? static_cast<const StructInfo* >(type.infoPtr)->name : "struct";
185  case Type::UNION: return type.infoPtr ? static_cast<const UnionInfo* >(type.infoPtr)->name : "union";
186  }
187  }
188 
189  constexpr void getOffsetForAlignment(const TypeInfo& type, size_t& current_offset);
190 
191  constexpr size_t sizeForBasicType(const TypeInfo& type);
192 
197  constexpr size_t sizeForBasicType(const Type type, const void* info = nullptr)
198  {
199  switch (type)
200  {
201  case Type::CHAR:
202  {
203  return sizeof(char);
204  }
205  case Type::BOOL:
206  {
207  return sizeof(bool);
208  }
209  case Type::U8:
210  {
211  return sizeof(uint8_t);
212  }
213  case Type::S8:
214  {
215  return sizeof(int8_t);
216  }
217  case Type::U16:
218  {
219  return sizeof(uint16_t);
220  }
221  case Type::S16:
222  {
223  return sizeof(int16_t);
224  }
225  case Type::U32:
226  {
227  return sizeof(uint32_t);
228  }
229  case Type::S32:
230  {
231  return sizeof(int32_t);
232  }
233  case Type::U64:
234  {
235  return sizeof(uint64_t);
236  }
237  case Type::S64:
238  {
239  return sizeof(int64_t);
240  }
241  case Type::FLOAT:
242  {
243  return sizeof(float);
244  }
245  case Type::DOUBLE:
246  {
247  return sizeof(double);
248  }
249  case Type::ENUM:
250  {
251  if (!info)
252  {
253  return 0;
254  }
255 
256  return sizeForBasicType(static_cast<const EnumInfo*>(info)->type);
257  }
258  case Type::BITS:
259  {
260  if (!info)
261  {
262  return 0;
263  }
264 
265  return sizeForBasicType(static_cast<const BitfieldInfo*>(info)->type);
266  }
267  case Type::STRUCT:
268  {
269  size_t total_size = 0;
270 
271  if (!info)
272  {
273  return total_size;
274  }
275 
276  if (const StructInfo* struct_info = static_cast<const StructInfo*>(info))
277  {
278  for (const ParameterInfo& param : struct_info->parameters)
279  {
280  getOffsetForAlignment(param.type, total_size);
281  total_size += sizeForBasicType(param.type);
282  }
283  }
284 
285  return total_size;
286  }
287  case Type::UNION:
288  {
289  size_t highest_size = 0;
290 
291  if (!info)
292  {
293  return highest_size;
294  }
295 
296  if (const StructInfo* struct_info = static_cast<const StructInfo*>(info))
297  {
298  for (const ParameterInfo& param : struct_info->parameters)
299  {
300  const size_t param_size = sizeForBasicType(param.type);
301 
302  if (param_size > highest_size)
303  {
304  highest_size = param_size;
305  }
306  }
307  }
308 
309  return highest_size;
310  }
311  default:
312  {
313  return 0;
314  }
315  }
316  }
317  constexpr size_t sizeForBasicType(const TypeInfo& type) { return sizeForBasicType(type.type, type.infoPtr); }
318 
319  constexpr size_t alignmentForBasicType(const TypeInfo& type);
320 
325  constexpr size_t alignmentForBasicType(const Type type, const void* info = nullptr)
326  {
327  switch (type)
328  {
329  case Type::CHAR:
330  {
331  return alignof(char);
332  }
333  case Type::BOOL:
334  {
335  return alignof(bool);
336  }
337  case Type::U8:
338  {
339  return alignof(uint8_t);
340  }
341  case Type::S8:
342  {
343  return alignof(int8_t);
344  }
345  case Type::U16:
346  {
347  return alignof(uint16_t);
348  }
349  case Type::S16:
350  {
351  return alignof(int16_t);
352  }
353  case Type::U32:
354  {
355  return alignof(uint32_t);
356  }
357  case Type::S32:
358  {
359  return alignof(int32_t);
360  }
361  case Type::U64:
362  {
363  return alignof(uint64_t);
364  }
365  case Type::S64:
366  {
367  return alignof(int64_t);
368  }
369  case Type::FLOAT:
370  {
371  return alignof(float);
372  }
373  case Type::DOUBLE:
374  {
375  return alignof(double);
376  }
377  case Type::ENUM:
378  {
379  if (!info)
380  {
381  return 0;
382  }
383 
384  return alignmentForBasicType(static_cast<const EnumInfo*>(info)->type);
385  }
386  case Type::BITS:
387  {
388  if (!info)
389  {
390  return 0;
391  }
392 
393  return alignmentForBasicType(static_cast<const BitfieldInfo*>(info)->type);
394  }
395  case Type::UNION:
396  case Type::STRUCT:
397  {
398  size_t highest_alignment = 0;
399 
400  if (!info)
401  {
402  return highest_alignment;
403  }
404 
405  if (const StructInfo* struct_info = static_cast<const StructInfo*>(info))
406  {
407  for (const ParameterInfo& param : struct_info->parameters)
408  {
409  const size_t param_alignment = alignmentForBasicType(param.type);
410 
411  if (param_alignment > highest_alignment)
412  {
413  highest_alignment = param_alignment;
414  }
415  }
416  }
417 
418  return highest_alignment;
419  }
420  default:
421  {
422  return 0;
423  }
424  }
425  }
426  constexpr size_t alignmentForBasicType(const TypeInfo& type) { return alignmentForBasicType(type.type, type.infoPtr); }
427 
428  constexpr void getOffsetForAlignment(const TypeInfo& type, size_t& current_offset)
429  {
430  const size_t align = alignmentForBasicType(type);
431 
432  if (align != 0)
433  {
434  const size_t align_offset = current_offset % align;
435 
436  if (align_offset != 0)
437  {
438  current_offset += align - align_offset;
439  }
440  }
441  }
442 
456  const inline ParameterInfo* getParameterInfoFromStructMemberOffset(const size_t offset, const StructInfo& field_info)
457  {
458  size_t check_offset = 0;
459 
460  for (const ParameterInfo& param : field_info.parameters)
461  {
462  getOffsetForAlignment(param.type, check_offset);
463 
464  if (offset == check_offset)
465  {
466  return &param;
467  }
468 
469  if (offset < check_offset)
470  {
471  break;
472  }
473 
474  check_offset += sizeForBasicType(param.type);
475  }
476 
477  return nullptr;
478  }
479 
494  const inline ParameterInfo* getNestedParameterInfoFromStructMemberOffset(const size_t base_offset, const size_t nested_offset, const StructInfo& field_info)
495  {
496  if (const ParameterInfo* base_param = getParameterInfoFromStructMemberOffset(base_offset, field_info))
497  {
498  switch (base_param->type.type)
499  {
500  case Type::STRUCT:
501  {
502  const StructInfo* struct_info = static_cast<const StructInfo*>(base_param->type.infoPtr);
503  return getParameterInfoFromStructMemberOffset(nested_offset, *struct_info);
504  }
505  case Type::UNION:
506  {
507  const UnionInfo* union_info = static_cast<const UnionInfo*>(base_param->type.infoPtr);
508  return getParameterInfoFromStructMemberOffset(nested_offset, *union_info);
509  }
510  default:
511  {
512  break;
513  }
514  }
515  }
516 
517  return nullptr;
518  }
519 
532  const inline ParameterInfo* getParameterInfoForMember(const StructInfo& struct_info, const char* param_name, const size_t dummy = 0)
533  {
534  // Dummy variable for macro checks
535  (void)dummy;
536 
537  for (const ParameterInfo& param : struct_info.parameters)
538  {
539  if (strcmp(param.name, param_name) == 0)
540  {
541  return &param;
542  }
543  }
544 
545  return nullptr;
546  }
547 
561  #define GET_MIP_METADATA_NESTED_PARAM_INFO(MemberParameter, NestedMemberField) \
562  mip::metadata::utils::getParameterInfoForMember(mip::metadata::MetadataFor<decltype(MemberParameter)>::value, #NestedMemberField, \
563  offsetof(decltype(MemberParameter), NestedMemberField)) // Dummy entry to allow offsetof to check the member exists
564 
576  #define GET_MIP_METADATA_PARAM_INFO(MipType, MemberField) \
577  mip::metadata::utils::getParameterInfoForMember(mip::metadata::MetadataFor<MipType>::value, #MemberField, \
578  offsetof(MipType, MemberField)) // Dummy entry to allow offsetof to check the member exists
579 } // namespace mip::metadata
mip::metadata::utils::nameOfType
constexpr const char * nameOfType(const TypeInfo &type)
Definition: mip_meta_utils.hpp:177
microstrain::Span::data
constexpr pointer data() const noexcept
Definition: span.hpp:66
mip::metadata::utils::ParamEnum
Definition: mip_meta_utils.hpp:35
mip::metadata::utils::getParameterInfoForMember
const ParameterInfo * getParameterInfoForMember(const StructInfo &struct_info, const char *param_name, const size_t dummy=0)
Get a pointer to a parameter given the member of a MIP type.
Definition: mip_meta_utils.hpp:532
mip::metadata::utils::ParamEnum< Type::CHAR >::type
char type
Definition: mip_meta_utils.hpp:37
mip::metadata::Type::ENUM
@ ENUM
mip::metadata::Type::NONE
@ NONE
Invalid/unknown.
mip::metadata::utils::serializedType
Type serializedType(const TypeInfo &type)
Determines the type used for serialization purposes.
Definition: mip_meta_utils.hpp:99
mip::metadata::BitfieldInfo
Definition: mip_structures.hpp:89
mip::metadata::utils::alignmentForBasicType
constexpr size_t alignmentForBasicType(const TypeInfo &type)
Definition: mip_meta_utils.hpp:426
mip::metadata::utils::getParameterInfoFromStructMemberOffset
const ParameterInfo * getParameterInfoFromStructMemberOffset(const size_t offset, const StructInfo &field_info)
Get a pointer to a parameter given the offset of the member in the class/struct.
Definition: mip_meta_utils.hpp:456
mip::metadata::ParameterInfo::name
const char * name
Programmatic name (e.g. for printing or language bindings).
Definition: mip_structures.hpp:192
mip::EnableForFieldTypes
std::enable_if< isField< T >::value, T > EnableForFieldTypes
Definition: mip_descriptors.hpp:56
microstrain::Span::size
constexpr size_t size() const noexcept
Definition: span.hpp:68
mip::metadata::utils::ParamEnum< Type::S16 >::type
int16_t type
Definition: mip_meta_utils.hpp:42
mip::metadata::Type::U16
@ U16
mip::metadata::utils::nameForBasicType
constexpr const char * nameForBasicType(Type type)
Definition: mip_meta_utils.hpp:152
mip::metadata::utils::ParamType::value
static constexpr Type value
Definition: mip_meta_utils.hpp:10
microstrain::Span
Implementation of std::span from C++20.
Definition: span.hpp:41
mip::metadata::Type::STRUCT
@ STRUCT
mip::metadata::Type::S32
@ S32
mip::metadata::utils::ParamEnum< Type::FLOAT >::type
float type
Definition: mip_meta_utils.hpp:47
mip::metadata::Type::DOUBLE
@ DOUBLE
mip::metadata::Type
Type
Definition: mip_structures.hpp:21
mip::metadata::Type::CHAR
@ CHAR
mip::metadata::utils::ParamEnum::type
void type
Definition: mip_meta_utils.hpp:35
mip::metadata::ParameterInfo
Definition: mip_structures.hpp:158
mip::metadata::ParameterInfo::type
TypeInfo type
Data type.
Definition: mip_structures.hpp:194
mip::metadata::utils::ParamEnum< Type::DOUBLE >::type
double type
Definition: mip_meta_utils.hpp:48
mip::metadata::utils::ParamType
Definition: mip_meta_utils.hpp:10
mip::metadata::Type::UNION
@ UNION
mip::metadata::Type::S8
@ S8
mip::metadata::Type::FLOAT
@ FLOAT
mip::metadata::Type::S16
@ S16
mip::metadata::Type::S64
@ S64
mip::metadata::TypeInfo::isBasicType
bool isBasicType() const
Definition: mip_structures.hpp:58
mip::metadata::utils::ParamEnum< Type::U8 >::type
uint8_t type
Definition: mip_meta_utils.hpp:39
mip::metadata::Type::U64
@ U64
mip::metadata::utils::sizeForBasicType
constexpr size_t sizeForBasicType(const TypeInfo &type)
Definition: mip_meta_utils.hpp:317
mip::metadata::Type::BOOL
@ BOOL
mip::metadata::utils::ParamEnum< Type::U64 >::type
uint64_t type
Definition: mip_meta_utils.hpp:45
mip::metadata::Type::U8
@ U8
mip_structures.hpp
mip::metadata::StructInfo::parameters
Span< const ParameterInfo > parameters
Definition: mip_structures.hpp:207
mip::metadata::TypeInfo::infoPtr
const void * infoPtr
Definition: mip_structures.hpp:51
mip::metadata::TypeInfo::bitfieldPointer
const BitfieldInfo * bitfieldPointer() const
Definition: mip_structures.hpp:54
mip::metadata::utils::getOffsetForAlignment
constexpr void getOffsetForAlignment(const TypeInfo &type, size_t &current_offset)
Definition: mip_meta_utils.hpp:428
mip::metadata::utils::ParamEnum< Type::S32 >::type
int32_t type
Definition: mip_meta_utils.hpp:44
mip::metadata::EnumInfo
Definition: mip_structures.hpp:63
mip::metadata::utils
Definition: mip_meta_utils.hpp:5
mip::metadata::utils::ParamEnum< Type::U16 >::type
uint16_t type
Definition: mip_meta_utils.hpp:41
mip::metadata::TypeInfo::type
Type type
Definition: mip_structures.hpp:49
mip::metadata::TypeInfo
Definition: mip_structures.hpp:44
mip::metadata::utils::ParamEnum< Type::S8 >::type
int8_t type
Definition: mip_meta_utils.hpp:40
mip::metadata::utils::getNestedParameterInfoFromStructMemberOffset
const ParameterInfo * getNestedParameterInfoFromStructMemberOffset(const size_t base_offset, const size_t nested_offset, const StructInfo &field_info)
Get a pointer to a parameter given the offset of the member in the class/struct.
Definition: mip_meta_utils.hpp:494
mip::metadata::Type::BITS
@ BITS
mip::metadata::StructInfo
Definition: mip_structures.hpp:201
mip::metadata::utils::ParamEnum< Type::U32 >::type
uint32_t type
Definition: mip_meta_utils.hpp:43
mip::Bitfield
A dummy struct which is used to mark bitfield objects.
Definition: mip_descriptors.hpp:61
mip::metadata::TypeInfo::enumPointer
const EnumInfo * enumPointer() const
Definition: mip_structures.hpp:53
mip::metadata::utils::serializedSizeForBasicType
constexpr size_t serializedSizeForBasicType(Type type, const void *info=nullptr)
Gets the size of a basic type (including bitfields and enums if class_ is not NULL).
Definition: mip_meta_utils.hpp:115
mip::metadata::Type::U32
@ U32
mip::metadata::UnionInfo
Definition: mip_structures.hpp:210
mip::metadata::utils::ParamEnum< Type::S64 >::type
int64_t type
Definition: mip_meta_utils.hpp:46
mip::metadata::utils::ParamEnum< Type::BOOL >::type
bool type
Definition: mip_meta_utils.hpp:38