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