Skip to content

Commit

Permalink
Refs #17138. Support unions.
Browse files Browse the repository at this point in the history
Signed-off-by: Ricardo González Moreno <[email protected]>
  • Loading branch information
richiware committed Jan 24, 2024
1 parent b84d195 commit b76946c
Show file tree
Hide file tree
Showing 10 changed files with 2,538 additions and 647 deletions.
1,180 changes: 889 additions & 291 deletions src/cpp/fastdds/xtypes/dynamic_types/DynamicDataImpl.cpp

Large diffs are not rendered by default.

97 changes: 91 additions & 6 deletions src/cpp/fastdds/xtypes/dynamic_types/DynamicDataImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <vector>

#include "DynamicTypeImpl.hpp"
#include "TypeForKind.hpp"

namespace eprosima {

Expand All @@ -40,6 +41,8 @@ class DynamicDataImpl : public traits<DynamicData>::base_type

std::vector<MemberId> loaned_values_;

MemberId selected_union_member_ {MEMBER_ID_INVALID};

public:

DynamicDataImpl(
Expand Down Expand Up @@ -400,6 +403,62 @@ class DynamicDataImpl : public traits<DynamicData>::base_type
const traits<DynamicTypeImpl>::ref_type type,
size_t& current_alignment) const noexcept;

/*!
* Auxiliary function for checking the new discriminator value set by the user is correct.
*/
template<typename T, typename std::enable_if<std::is_integral<T>::value, bool>::type = true>
bool check_new_discriminator_value(
const T& value)
{
bool ret_value = false;

if (MEMBER_ID_INVALID != selected_union_member_) // There is a member selected by current discriminator.
{
traits<DynamicTypeMember>::ref_type selected_member;
type_->get_member(selected_member, selected_union_member_);
auto sm_impl = traits<DynamicTypeMember>::narrow<DynamicTypeMemberImpl>(selected_member);

for (auto label : sm_impl->get_descriptor().label())
{
if (static_cast<int32_t>(value) == label)
{
ret_value = true;
break;
}
}
}
else // It is selected the implicit default member.
{
ret_value = true;

if (type_->default_discriminator_value() != static_cast<int32_t>(value))
{
for (auto member : type_->get_all_members_by_index())
{
auto m_impl = traits<DynamicTypeMember>::narrow<DynamicTypeMemberImpl>(member);

for (auto label : m_impl->get_descriptor().label())
{
if (static_cast<int32_t>(value) == label)
{
ret_value = false;
break;
}
}
}
}
}

return ret_value;
}

template<typename T, typename std::enable_if<!std::is_integral<T>::value, bool>::type = true>
bool check_new_discriminator_value(
const T&)
{
return false;
}

/*!
* Auxiliary function to clear completely a sequence.
* Only valid for TK_ARRAY or TK_SEQUENCE.
Expand Down Expand Up @@ -456,6 +515,11 @@ class DynamicDataImpl : public traits<DynamicData>::base_type
*/
uint32_t get_sequence_length();

template<TypeKind TK >
ReturnCode_t get_primitive_value(
TypeForKind<TK>& value,
MemberId member_id) noexcept;

/*!
* Auxiliary template with the common code for getting the values of a sequence from a TK_ARRAY or TK_SEQUENCE.
*/
Expand All @@ -464,15 +528,29 @@ class DynamicDataImpl : public traits<DynamicData>::base_type
Sequence& value,
MemberId id) noexcept;

template<typename T, int TK, class Sequence>
template<TypeKind TK >
ReturnCode_t get_value(
T& value,
TypeForKind<TK>& value,
MemberId id) noexcept;

void set_value(
const ObjectName& value,
/*!
* Auxiliary function for setting the discriminator value to a label of the member specified by the MemberId.
*/
void set_discriminator_value(
MemberId id) noexcept;

/*!
* Auxiliary function to set the discriminator value on already given discriminator DynamicData.
*/
void set_discriminator_value(
int32_t new_discriminator_value,
const traits<DynamicTypeImpl>::ref_type& discriminator_type,
traits<DynamicDataImpl>::ref_type& data) noexcept;

template<TypeKind TK>
ReturnCode_t set_primitive_value(
const TypeForKind<TK>& value) noexcept;

/*!
* Auxiliary template with the common code for setting the values of a sequence into a TK_ARRAY or TK_SEQUENCE.
*/
Expand All @@ -481,13 +559,20 @@ class DynamicDataImpl : public traits<DynamicData>::base_type
MemberId id,
const Sequence& value) noexcept;


/*!
* Auxiliary function to set the default value,specified by MemberDescriptor::default_value, to primitive types.
*/
void set_value(
const ObjectName& value) noexcept;

/*!
* Auxiliary template with the common code for setting the value of a primitive type
*/
template<typename T, int TK, class Sequence>
template<TypeKind TK>
ReturnCode_t set_value(
MemberId id,
const T& value) noexcept;
const TypeForKind<TK>& value) noexcept;

void set_default_value(
const traits<DynamicTypeMemberImpl>::ref_type member,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,13 @@ traits<DynamicTypeBuilder>::ref_type DynamicTypeBuilderFactoryImpl::create_type(
traits<TypeDescriptor>::ref_type descriptor) noexcept
{
auto descriptor_impl = traits<TypeDescriptor>::narrow<TypeDescriptorImpl>(descriptor);
return std::make_shared<DynamicTypeBuilderImpl>(*descriptor_impl);

if (descriptor_impl->is_consistent())
{
return std::make_shared<DynamicTypeBuilderImpl>(*descriptor_impl);
}

return {};
}

traits<DynamicTypeBuilder>::ref_type DynamicTypeBuilderFactoryImpl::create_type_copy(
Expand Down
30 changes: 25 additions & 5 deletions src/cpp/fastdds/xtypes/dynamic_types/DynamicTypeBuilderImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,18 @@ DynamicTypeBuilderImpl::DynamicTypeBuilderImpl(
}
else if (TK_UNION == type_descriptor_.kind())
{
// MemberId 0 is reserved to discriminator.
MemberDescriptorImpl discriminator_descriptor;
discriminator_descriptor.id(0);
discriminator_descriptor.index(0);
discriminator_descriptor.name("discriminator");
discriminator_descriptor.type(type_descriptor.discriminator_type());

traits<DynamicTypeMemberImpl>::ref_type dyn_member = std::make_shared<DynamicTypeMemberImpl>(
discriminator_descriptor);
members_.push_back(dyn_member);
member_by_name_.emplace(std::make_pair("discriminator", dyn_member));
member_.emplace(std::make_pair(0, dyn_member));
next_index_ = 1;
next_id_ = 1;
}
}
Expand Down Expand Up @@ -261,16 +272,24 @@ ReturnCode_t DynamicTypeBuilderImpl::add_member(
EPROSIMA_LOG_ERROR(DYN_TYPES,
"Member " << member_impl->member_descriptor_.name().c_str() << " already contains the label " <<
label);
return false;
return RETCODE_BAD_PARAMETER;
}
}

if (new_label >= default_union_label_)
// Recalculate the default discriminator value (for default case or default implicit member).
if (new_label >= default_discriminator_value_)
{
default_union_label_ = new_label + 1;
default_discriminator_value_ = new_label + 1;
}
}
}

// In case of default case, store the related MemberId.
if (descriptor_impl->is_default_label())
{
assert(MEMBER_ID_INVALID != descriptor_impl->id());
default_union_member_ = descriptor_impl->id();
}
}

const auto& member_name = descriptor_impl->name();
Expand Down Expand Up @@ -437,7 +456,8 @@ traits<DynamicType>::ref_type DynamicTypeBuilderImpl::build() noexcept
ret_val->member_ = member_;
ret_val->member_by_name_ = member_by_name_;
ret_val->members_ = members_;
ret_val->default_union_label_ = default_union_label_;
ret_val->default_discriminator_value_ = default_discriminator_value_;
ret_val->default_union_member_ = default_union_member_;
}

return ret_val;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@ class DynamicTypeBuilderImpl : public traits<DynamicTypeBuilder>::base_type

MemberId next_id_ {0};

int32_t default_union_label_ {0};
int32_t default_discriminator_value_ {0};

MemberId default_union_member_ {MEMBER_ID_INVALID};
};

} // namespace dds
Expand Down
14 changes: 13 additions & 1 deletion src/cpp/fastdds/xtypes/dynamic_types/DynamicTypeImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,16 @@ class DynamicTypeImpl : public virtual traits<DynamicType>::base_type
return type_descriptor_;
}

int32_t default_discriminator_value() const noexcept
{
return default_discriminator_value_;
}

MemberId default_union_member() const noexcept
{
return default_union_member_;
}

protected:

traits<DynamicType>::ref_type _this();
Expand All @@ -112,7 +122,9 @@ class DynamicTypeImpl : public virtual traits<DynamicType>::base_type

std::vector<VerbatimTextDescriptorImpl> verbatim_;

int32_t default_union_label_ {0};
int32_t default_discriminator_value_ {0};

MemberId default_union_member_ {MEMBER_ID_INVALID};
};

} // namespace dds
Expand Down
49 changes: 44 additions & 5 deletions src/cpp/fastdds/xtypes/dynamic_types/TypeDescriptorImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include <fastdds/dds/xtypes/dynamic_types/DynamicType.hpp>
#include <fastdds/dds/xtypes/dynamic_types/Types.hpp>

#include "DynamicTypeImpl.hpp"

namespace eprosima {
namespace fastdds {
namespace dds {
Expand Down Expand Up @@ -188,13 +190,50 @@ bool TypeDescriptorImpl::is_consistent() noexcept
}

// Only union types need the discriminator of the union
if (TK_UNION == kind_ && !discriminator_type_)
if (TK_UNION == kind_)
{
EPROSIMA_LOG_ERROR(DYN_TYPES, "Descriptor describes an UNION but discriminant_type was not set");
return false;
if (!discriminator_type_)
{
EPROSIMA_LOG_ERROR(DYN_TYPES, "Descriptor describes an UNION but discriminant_type was not set");
return false;
}
else
{
// Check discriminator kind and the type is a integer (labels are int32_t).
// boolean, byte, char8, char16, int8, uint8, int16, uint16, int32, uint32, enumera, alias
TypeKind discriminator_kind = discriminator_type_->get_kind();
auto discriminator_type = traits<DynamicType>::narrow<DynamicTypeImpl>(discriminator_type_);

if (TK_ALIAS == discriminator_kind) // If alias, get enclosing type.
{
do {
discriminator_type = traits<DynamicType>::narrow<DynamicTypeImpl>(
discriminator_type->get_descriptor().base_type());
discriminator_kind = discriminator_type->get_kind();
} while (TK_ALIAS == discriminator_kind);
}

switch (discriminator_kind)
{
case TK_BOOLEAN:
case TK_BYTE:
case TK_CHAR8:
case TK_CHAR16:
case TK_INT8:
case TK_UINT8:
case TK_INT16:
case TK_UINT16:
case TK_INT32:
case TK_UINT32:
case TK_ENUM:
break;
default:
EPROSIMA_LOG_ERROR(DYN_TYPES, "Discriminantor kind was not valid");
return false;
break;
}
}
}
// TODO(richiware) if union, check discriminator kind and the type is a integer (labels are UINT64).
//boolean, byte, char8, char16, int8, uint8, int16, uint16, int32, uint32, enumera, alias

// ElementType is used by these types to set the "value" type of the element, otherwise it should be null.
if (!element_type_ && (
Expand Down
Loading

0 comments on commit b76946c

Please sign in to comment.