15#ifndef DDSTRUCTURE_GENERATOR_H_INCLUDED
16#define DDSTRUCTURE_GENERATOR_H_INCLUDED
32 static constexpr size_t array_size = 1;
37struct ArrayMember<T[]> {
39 static constexpr size_t array_size = 0;
43template <
typename ValueType,
size_t value_array_size>
44struct ArrayMember<std::array<ValueType, value_array_size>> {
45 using value_type = ValueType;
46 static constexpr size_t array_size = value_array_size;
50template <
typename ValueType,
size_t value_array_size>
51struct ArrayMember<ValueType[value_array_size]> {
52 using value_type = ValueType;
53 static constexpr size_t array_size = value_array_size;
57struct MemberTypeCheck {
58 using member_type =
typename std::remove_pointer<T>::type;
59 using value_type =
typename ArrayMember<member_type>::value_type;
60 static constexpr size_t array_size = ArrayMember<member_type>::array_size;
63template <
typename T,
typename MemberType>
64size_t getOffsetOfMember(MemberType T::*member)
69#pragma warning(disable : 6011)
71 return reinterpret_cast<size_t>(&(start->*member));
116template <
typename T,
bool align_with_padding = true>
118 static_assert(std::is_trivially_copyable<T>::value,
119 "You can only use structs with plain old datatypes and complex members. Do not "
130 : _structure(name, struct_version, alignof(T))
140 template <
typename MemberType>
143 using ValueType =
typename detail::MemberTypeCheck<MemberType>::value_type;
145 static_assert(!std::is_enum<ValueType>::value,
146 "For elements with enum type you must specify the DDEnum before! "
147 "Use createElement(name, member_offset, dd_enum);");
148 static_assert(std::is_arithmetic<ValueType>::value,
149 "For elements with complex structure types you must specify the used "
150 "DDStructure before! Use createElement(name, member_offset, dd_structure);");
151 static_assert(detail::MemberTypeCheck<MemberType>::array_size != 0,
152 "For dynamic arrays the array_size must be specified! Use "
153 "createElement(name, member_offset, array_size_name);");
155 PaddingAlignmentGuard padding_alignment_guard(*
this);
158 *evaluateAlignment(name, detail::getOffsetOfMember(member_offset),
alignof(MemberType)),
160 detail::MemberTypeCheck<MemberType>::array_size);
176 template <
typename MemberType>
178 MemberType T::*member_offset,
179 const std::string& valid_element_count_or_array_size_name)
181 using ValueType =
typename detail::MemberTypeCheck<MemberType>::value_type;
183 static_assert(!std::is_enum<ValueType>::value,
184 "For elements with enum type you must specify the DDEnum before! "
185 "Use createElement(name, member_offset, dd_enum);");
186 static_assert(std::is_arithmetic<ValueType>::value,
187 "For elements with complex structure types you must specify the used "
188 "DDStructure before! Use createElement(name, member_offset, dd_structure);");
190 PaddingAlignmentGuard padding_alignment_guard(*
this);
191 using ValueType =
typename detail::MemberTypeCheck<MemberType>::value_type;
192 return createArrayElement(
194 *evaluateAlignment(name, detail::getOffsetOfMember(member_offset),
alignof(MemberType)),
196 detail::MemberTypeCheck<MemberType>::array_size,
197 valid_element_count_or_array_size_name);
206 template <
typename MemberType>
226 template <
typename MemberType>
228 MemberType T::*member_offset,
229 const std::string& valid_element_count_or_array_size_name)
231 createElement(name, member_offset, valid_element_count_or_array_size_name);
242 template <
typename MemberType>
244 MemberType T::*member_offset,
248 detail::MemberTypeCheck<MemberType>::array_size != 0,
249 "For dynamic arrays the array_size must be specified! Use createElement(name, "
250 "member_offset, array_size_name);");
252 PaddingAlignmentGuard padding_alignment_guard(*
this);
255 *evaluateAlignment(name, detail::getOffsetOfMember(member_offset),
alignof(MemberType)),
257 detail::MemberTypeCheck<MemberType>::array_size);
274 template <
typename MemberType>
276 MemberType T::*member_offset,
278 const std::string& valid_element_count_or_array_size_name)
280 PaddingAlignmentGuard padding_alignment_guard(*
this);
281 return createArrayElement(
283 *evaluateAlignment(name, detail::getOffsetOfMember(member_offset),
alignof(MemberType)),
285 detail::MemberTypeCheck<MemberType>::array_size,
286 valid_element_count_or_array_size_name);
296 template <
typename MemberType>
298 MemberType T::*member_offset,
319 template <
typename MemberType>
321 MemberType T::*member_offset,
323 const std::string& valid_element_count_or_array_size_name)
325 createElement(name, member_offset, enum_type, valid_element_count_or_array_size_name);
336 template <
typename MemberType>
338 MemberType T::*member_offset,
341 static_assert(detail::MemberTypeCheck<MemberType>::array_size != 0,
342 "For dynamic arrays the array_size must be specified! Use addElement(name, "
343 "member_offset, array_size_name);");
345 PaddingAlignmentGuard padding_alignment_guard(*
this);
348 *evaluateAlignment(name, detail::getOffsetOfMember(member_offset),
alignof(MemberType)),
350 detail::MemberTypeCheck<MemberType>::array_size);
367 template <
typename MemberType>
369 MemberType T::*member_offset,
371 const std::string& valid_element_count_or_array_size_name)
373 PaddingAlignmentGuard padding_alignment_guard(*
this);
376 *evaluateAlignment(name, detail::getOffsetOfMember(member_offset),
alignof(MemberType)),
378 detail::MemberTypeCheck<MemberType>::array_size,
379 valid_element_count_or_array_size_name);
389 template <
typename MemberType>
391 MemberType T::*member_offset,
412 template <
typename MemberType>
414 MemberType T::*member_offset,
416 const std::string& valid_element_count_or_array_size_name)
430 return _structure.getStructDescription();
439 return _structure.getStructName();
452 return _structure.getDD();
465 return _structure.getStructType();
486 return _structure.getSize();
495 return _structure.getAlignment();
515 _structure.setStructInfo(comment);
522 const std::string& description = {},
523 const std::string& comment = {},
524 const std::string& value = {},
525 const std::string& minimum_value = {},
526 const std::string& maximum_value = {},
527 const std::string& default_value = {},
528 const std::string& scale = {},
529 const std::string& offset = {})
531 _structure.setElementInfo(element_name,
553 _structure.setElementUnit(element_name,
unit);
567 _structure.setElementUnit(element_name, base_unit);
585 if constexpr (align_with_padding) {
586 const auto current_struct_size = _structure.
getSize();
587 if (
sizeof(T) > current_struct_size) {
589 "__padding_final",
sizeof(T) - current_struct_size, 1);
590 _padded_final =
true;
597 if constexpr (align_with_padding) {
599 _structure.popLastElement();
600 _padded_final =
false;
605 struct PaddingAlignmentGuard {
607 : _padded_structure(padded_structure)
609 padded_structure.popAlignment();
612 ~PaddingAlignmentGuard()
614 _padded_structure.pushAlignment();
621 void validate()
const
623 if constexpr (!align_with_padding) {
624 if (_structure.getSize() !=
sizeof(T)) {
625 throw ddl::dd::Error(
626 "DDStructureGenerator::validate",
627 "The generated struct '" + _structure.getStructName() +
628 "' does not have the expected size of (" + std::to_string(
sizeof(T)) +
629 ") - The evaluated a size is (" + std::to_string(_structure.getSize()) +
630 "). Check if there are missing or misordered elements. ");
636 size_t member_offset,
637 size_t member_type_alignment)
640 const auto struct_access = _structure.getDD().getStructTypeAccess(
getStructName());
641 const auto current_struct_offset = struct_access.getStaticUnalignedStructSize();
643 if (member_offset < current_struct_offset) {
644 throw ddl::dd::Error(
646 {std::to_string(member_offset)},
647 "The evaluated struct size of '" +
getStructName() +
"' is already (" +
648 std::to_string(current_struct_offset) +
") - Trying to add a member at (" +
649 std::to_string(member_offset) +
650 ") at a address prior the last element. Check misordered addElement calls.");
654 const auto difference = member_offset - current_struct_offset;
658 const size_t minimum_alignment =
659 member_type_alignment >
alignof(T) ?
alignof(T) : member_type_alignment;
661 const auto valid_alignment_range = {1u, 2u, 4u, 8u, 16u, 32u, 64u};
664 for (
const size_t alignment: valid_alignment_range) {
666 if (alignment <=
alignof(T)) {
667 if (alignment >= minimum_alignment) {
668 if ((alignment > difference) && ((member_offset % alignment) == 0)) {
681 if (difference < minimum_alignment) {
682 for (
const size_t alignment: valid_alignment_range) {
683 if (alignment < minimum_alignment) {
684 if ((alignment > difference) && ((member_offset % alignment) == 0)) {
697 if constexpr (align_with_padding) {
698 if (difference != 0) {
699 _structure.addElement<uint8_t>(
"__padding_" + element_name, difference, 1);
705 throw ddl::dd::Error(
707 {std::to_string(member_offset)},
709 "' it is not possible to find a valid member alignment to reach offset (" +
710 std::to_string(member_offset) +
") from position (" +
711 std::to_string(current_struct_offset) +
")");
715 template <
typename DDMemberType>
718 const DDMemberType& used_type,
721 return _structure.createElement(name, used_type, array_size, alignment);
724 template <
typename DDMemberType>
725 DDElementRef createArrayElement(
const std::string& name,
727 const DDMemberType& used_type,
729 const std::string& corresponding_element_name)
731 if (array_size == 0) {
733 return _structure.createElement(DDElement(name,
737 dd::ArraySize(corresponding_element_name)));
740 auto element = _structure.createElement(name, used_type, array_size, alignment);
741 element.setValidElementCount(corresponding_element_name);
746 DDStructure _structure;
747 bool _padded_final =
false;
Utility class for a complete valid data definition of one StructType::Element and its dependencies....
Definition ddelement_ref.h:35
const dd::StructType::Element & getElement() const
Get the Element object.
DDElementRef & setValidElementCount(const std::string &valid_element_count)
Sets the 'valid_element_count' attribute to the element.
Utility class for a complete valid data definition of one StructType::Element and its dependencies....
Definition ddelement.h:36
dd::datamodel::StructType::DeserializedInfo Deserialized
Deserialized definiton for one element.
Definition ddelement.h:41
Utility class for a complete valid data definition of one EnumType and its dependencies....
Definition ddenum.h:29
DDElementRef createElement(const std::string &name, MemberType T::*member_offset, const DDStructure &struct_type)
Definition ddstructure_generator.h:337
const dd::StructType & getStructType() const
Get the Struct Type object.
Definition ddstructure_generator.h:462
DDElementRef getElement(const std::string &element_name)
Gets a element reference to the element with name element_name owned by the DDStructureGenerator.
Definition ddstructure_generator.h:577
DDStructureGenerator & addElement(const std::string &name, MemberType T::*member_offset)
Definition ddstructure_generator.h:207
void setElementInfo(const std::string &element_name, const std::string &description={}, const std::string &comment={}, const std::string &value={}, const std::string &minimum_value={}, const std::string &maximum_value={}, const std::string &default_value={}, const std::string &scale={}, const std::string &offset={})
Set additional element information to the given element_name.
Definition ddstructure_generator.h:521
DDStructureGenerator(const std::string &name, uint32_t struct_version=1)
CTOR to create a structure type based on a type.
Definition ddstructure_generator.h:129
DDStructureGenerator & addElement(const std::string &name, MemberType T::*member_offset, const DDStructure &struct_type, const std::string &valid_element_count_or_array_size_name)
Definition ddstructure_generator.h:413
const dd::DataDefinition & getDD() const
returns a valid DDL.
Definition ddstructure_generator.h:449
DDElement createElement(const std::string &name, MemberType T::*member_offset, const DDEnum &enum_type, const std::string &valid_element_count_or_array_size_name)
Definition ddstructure_generator.h:275
DDStructureGenerator & addElement(const std::string &name, MemberType T::*member_offset, const DDEnum &enum_type)
Definition ddstructure_generator.h:297
std::string getStructDescription() const
Gets the structs data definition as XML String.
Definition ddstructure_generator.h:427
void setElementUnit(const std::string &element_name, const DDUnit &unit)
Sets additional element unit information to the given element_name. Any other unit information will b...
Definition ddstructure_generator.h:551
void setElementUnit(const std::string &element_name, const dd::BaseUnit &base_unit)
Sets additional element base unit information to the given element_name.
Definition ddstructure_generator.h:565
DDStructureGenerator & addElement(const std::string &name, MemberType T::*member_offset, const std::string &valid_element_count_or_array_size_name)
Definition ddstructure_generator.h:227
size_t getAlignment() const
Retrieves the current evaluated alignment of the structure.
Definition ddstructure_generator.h:493
DDStructureGenerator & addElement(const std::string &name, MemberType T::*member_offset, const DDStructure &struct_type)
Definition ddstructure_generator.h:390
DDElementRef createElement(const std::string &name, MemberType T::*member_offset, const DDStructure &struct_type, const std::string &valid_element_count_or_array_size_name)
Definition ddstructure_generator.h:368
DDElementRef createElement(const std::string &name, MemberType T::*member_offset, const DDEnum &enum_type)
Definition ddstructure_generator.h:243
void setStructInfo(const std::string &comment)
Set additional struct information like comment. This is important to create additional info in type r...
Definition ddstructure_generator.h:513
DDStructureGenerator & addElement(const std::string &name, MemberType T::*member_offset, const DDEnum &enum_type, const std::string &valid_element_count_or_array_size_name)
Definition ddstructure_generator.h:320
const DDStructure & getStructure() const
Get the current valid DDStructure object.
Definition ddstructure_generator.h:474
size_t getSize() const
Retrieves the current evaluated size of the structure.
Definition ddstructure_generator.h:484
DDElementRef createElement(const std::string &name, MemberType T::*member_offset)
Definition ddstructure_generator.h:141
std::string getStructName() const
Gets the Struct Name.
Definition ddstructure_generator.h:437
DDElementRef createElement(const std::string &name, MemberType T::*member_offset, const std::string &valid_element_count_or_array_size_name)
Definition ddstructure_generator.h:177
Utility class for a complete valid data definition of one StructType and its dependencies....
Definition ddstructure.h:57
DDStructure & addElement(const std::string &element_name, const dd::DataType &data_type, size_t array_size=1)
Adds one element to the struct using a (POD) DataType.
size_t getSize() const
Retrieves the current evaluated deserialized size (in bytes) of the structure.
The unit class holding a reference to its complete DD (references to baseunits and prefixes)
Definition ddunit.h:92
Generator template to create DataType for the plain c-types.
Definition dd_predefined_datatypes.h:38
The Data Definiton class uses the validation model to keep a Data Definition datamodel (ddl::dd::data...
Definition dd.h:92
datamodel::StructType StructType
Definition dd.h:59
utility::Optional< size_t > OptionalSize
Optional Size Type.
Definition dd_common_types.h:38
datamodel::BaseUnit BaseUnit
Definition dd.h:39
definiton of the unit namespace
Definition dd_predefined_units.h:55
definition of the ddl namespace
Definition codec.h:21