diff --git a/include/fastrtps/types/TypeDescriptor.h b/include/fastrtps/types/TypeDescriptor.h index 2d2c7a24df6..89aef5acd09 100644 --- a/include/fastrtps/types/TypeDescriptor.h +++ b/include/fastrtps/types/TypeDescriptor.h @@ -25,6 +25,23 @@ namespace eprosima { namespace fastrtps { namespace types { +enum FSM_INPUTS +{ + LETTER = 1, + NUMBER, + UNDERSCORE, + COLON, + OTHER +}; + +enum FSM_STATES +{ + INVALID = 0, + SINGLECOLON, + DOUBLECOLON, + VALID +}; + class TypeDescriptor { protected: @@ -38,6 +55,13 @@ class TypeDescriptor DynamicType_ptr key_element_type_; // Key Type for maps. std::vector annotation_; // Annotations to apply + const int stateTable[4][6] = { + /* Input: letter, number, underscore, colon, other */ + {INVALID, VALID, INVALID, INVALID, INVALID, INVALID}, + {SINGLECOLON, INVALID, INVALID, INVALID, DOUBLECOLON, INVALID}, + {DOUBLECOLON, VALID, INVALID, INVALID, INVALID, INVALID}, + {VALID, VALID, VALID, VALID, SINGLECOLON, INVALID}}; + void clean(); bool is_type_name_consistent( diff --git a/src/cpp/dynamic-types/TypeDescriptor.cpp b/src/cpp/dynamic-types/TypeDescriptor.cpp index 31693034249..4d4835fdc76 100644 --- a/src/cpp/dynamic-types/TypeDescriptor.cpp +++ b/src/cpp/dynamic-types/TypeDescriptor.cpp @@ -249,20 +249,41 @@ bool TypeDescriptor::is_consistent() const bool TypeDescriptor::is_type_name_consistent( const std::string& sName) const { - // The first letter must start with a letter ( uppercase or lowercase ) - if (sName.length() > 0 && std::isalpha(sName[0])) - { - // All characters must be letters, numbers or underscore. - for (uint32_t i = 1; i < sName.length(); ++i) + // Implement an FSM string parser to deal with both a plain type name + // and a fully qualified name. According to the DDS xtypes standard, + // type's fully qualified name is a concatenation of module names with + // the name of a type inside of those modules. + int currState = INVALID; + for (uint32_t i = 0; i < sName.length(); ++i) + { + int col = 0; + if (std::isalpha(sName[i])) { - if (!std::isalnum(sName[i]) && sName[i] != 95) - { - return false; - } + col = LETTER; + } + else if (std::isdigit(sName[i])) + { + col = NUMBER; + } + else if (sName[i] == '_') + { + col = UNDERSCORE; + } + else if (sName[i] == ':') + { + col = COLON; + } + else + { + col = OTHER; + } + currState = stateTable[currState][col]; + if (currState == INVALID) + { + return false; } - return true; } - return false; + return true; } void TypeDescriptor::set_kind( diff --git a/test/unittest/xtypes/XTypesTests.cpp b/test/unittest/xtypes/XTypesTests.cpp index 403f7650580..6c049955f15 100644 --- a/test/unittest/xtypes/XTypesTests.cpp +++ b/test/unittest/xtypes/XTypesTests.cpp @@ -18,27 +18,31 @@ #include "idl/TypesTypeObject.h" #include "idl/WideEnumTypeObject.h" #include +#include +#include using namespace eprosima::fastrtps; using namespace eprosima::fastrtps::types; -class XTypesTests: public ::testing::Test +class XTypesTests : public ::testing::Test { - public: - XTypesTests() - { - //registerTypesTypes(); - } - - ~XTypesTests() - { - TypeObjectFactory::delete_instance(); - eprosima::fastdds::dds::Log::KillThread(); - } - - virtual void TearDown() - { - } +public: + + XTypesTests() + { + //registerTypesTypes(); + } + + ~XTypesTests() + { + TypeObjectFactory::delete_instance(); + eprosima::fastdds::dds::Log::KillThread(); + } + + virtual void TearDown() + { + } + }; TEST_F(XTypesTests, EnumMinimalCoercion) @@ -731,7 +735,58 @@ TEST_F(XTypesTests, SimpleUnionCompleteCoercion) ASSERT_FALSE(basic_wide_union->consistent(*basic_union, consistencyQos)); } -int main(int argc, char **argv) +TEST_F(XTypesTests, TypeDescriptorFullyQualifiedName) +{ + DynamicTypeBuilder_ptr my_builder(DynamicTypeBuilderFactory::get_instance()->create_struct_builder()); + my_builder->add_member(0, "x", DynamicTypeBuilderFactory::get_instance()->create_float32_type()); + my_builder->add_member(0, "y", DynamicTypeBuilderFactory::get_instance()->create_float32_type()); + my_builder->add_member(0, "z", DynamicTypeBuilderFactory::get_instance()->create_float32_type()); + const TypeDescriptor* my_descriptor = my_builder->get_type_descriptor(); + + my_builder->set_name("Position"); + ASSERT_TRUE(my_descriptor->is_consistent()); + my_builder->set_name("Position_"); + ASSERT_TRUE(my_descriptor->is_consistent()); + my_builder->set_name("Position123"); + ASSERT_TRUE(my_descriptor->is_consistent()); + my_builder->set_name("position_123"); + ASSERT_TRUE(my_descriptor->is_consistent()); + my_builder->set_name("_Position"); + ASSERT_FALSE(my_descriptor->is_consistent()); + my_builder->set_name("123Position"); + ASSERT_FALSE(my_descriptor->is_consistent()); + my_builder->set_name("Position&"); + ASSERT_FALSE(my_descriptor->is_consistent()); + + my_builder->set_name("my_interface::action::dds_::Position"); + ASSERT_TRUE(my_descriptor->is_consistent()); + my_builder->set_name("my_interface:action::dds_::Position"); + ASSERT_FALSE(my_descriptor->is_consistent()); + my_builder->set_name("my_interface:::action::dds_::Position"); + ASSERT_FALSE(my_descriptor->is_consistent()); + my_builder->set_name("_my_interface::action::dds_::Position"); + ASSERT_FALSE(my_descriptor->is_consistent()); + my_builder->set_name("1my_interface::action::dds_::Position"); + ASSERT_FALSE(my_descriptor->is_consistent()); + my_builder->set_name(":my_interface::action::dds_::Position"); + ASSERT_FALSE(my_descriptor->is_consistent()); + my_builder->set_name("::my_interface::action::dds_::Position"); + ASSERT_FALSE(my_descriptor->is_consistent()); + my_builder->set_name("$my_interface::action::dds_::Position"); + ASSERT_FALSE(my_descriptor->is_consistent()); + my_builder->set_name("my_interface::2action::dds_::Position"); + ASSERT_FALSE(my_descriptor->is_consistent()); + my_builder->set_name("my_interface::_action::dds_::Position"); + ASSERT_FALSE(my_descriptor->is_consistent()); + my_builder->set_name("my_interface::*action::dds_::Position"); + ASSERT_FALSE(my_descriptor->is_consistent()); + my_builder->set_name("my_interface::action*::dds_::Position"); + ASSERT_FALSE(my_descriptor->is_consistent()); +} + +int main( + int argc, + char** argv) { eprosima::fastdds::dds::Log::SetVerbosity(eprosima::fastdds::dds::Log::Info);