diff --git a/rosidl_parser/rosidl_parser/definition.py b/rosidl_parser/rosidl_parser/definition.py index cfb295a27..273c306b9 100644 --- a/rosidl_parser/rosidl_parser/definition.py +++ b/rosidl_parser/rosidl_parser/definition.py @@ -508,6 +508,16 @@ def __init__(self, namespaced_type: NamespacedType, members=None): self.namespaced_type = namespaced_type self.members = members or [] + def has_any_member_with_annotation(self, name: str): + """ + Check whether any member has a particular annotation. + + :param str name: the name of the annotation + :returns: True if there is at least one member with the annotation, False otherwise + """ + has_any = [member.name for member in self.members if member.has_annotation(name)] + return bool(has_any) + class Include: """An include statement.""" diff --git a/rosidl_parser/test/test_parser.py b/rosidl_parser/test/test_parser.py index 447655a17..b58f55721 100644 --- a/rosidl_parser/test/test_parser.py +++ b/rosidl_parser/test/test_parser.py @@ -203,16 +203,19 @@ def test_message_parser_annotations(message_idl_file): assert structure.annotations[1].value == 'SHMEM_REF' assert len(structure.members[2].annotations) == 1 + assert structure.has_any_member_with_annotation('autoid') is False assert structure.members[2].annotations[0].name == 'default' assert len(structure.members[2].annotations[0].value) == 1 assert 'value' in structure.members[2].annotations[0].value assert structure.members[2].annotations[0].value['value'] == 123 + assert structure.has_any_member_with_annotation('default') assert len(structure.members[3].annotations) == 2 assert structure.members[3].annotations[0].name == 'key' assert structure.members[3].annotations[0].value is None + assert structure.has_any_member_with_annotation('key') assert structure.members[3].annotations[1].name == 'range' assert len(structure.members[3].annotations[1].value) == 2 @@ -220,6 +223,7 @@ def test_message_parser_annotations(message_idl_file): assert structure.members[3].annotations[1].value['min'] == -10 assert 'max' in structure.members[3].annotations[1].value assert structure.members[3].annotations[1].value['max'] == 10 + assert structure.has_any_member_with_annotation('range') assert isinstance(structure.members[32].type, BasicType) assert structure.members[32].type.typename == 'float' diff --git a/rosidl_typesupport_introspection_c/include/rosidl_typesupport_introspection_c/message_introspection.h b/rosidl_typesupport_introspection_c/include/rosidl_typesupport_introspection_c/message_introspection.h index 0d16e5923..63f3467d4 100644 --- a/rosidl_typesupport_introspection_c/include/rosidl_typesupport_introspection_c/message_introspection.h +++ b/rosidl_typesupport_introspection_c/include/rosidl_typesupport_introspection_c/message_introspection.h @@ -39,6 +39,8 @@ typedef struct rosidl_typesupport_introspection_c__MessageMember_s /// If the type_id_ value is rosidl_typesupport_introspection_c__ROS_TYPE_MESSAGE, /// this points to an array describing the fields of the sub-interface. const rosidl_message_type_support_t * members_; + /// True if this field is annotated as `@key`, false otherwise. + bool is_key_; /// True if this field is an array type, false if it is any other type. An /// array has the same value for / type_id_. bool is_array_; @@ -90,6 +92,8 @@ typedef struct rosidl_typesupport_introspection_c__MessageMembers_s uint32_t member_count_; /// The size of the interface structure in memory size_t size_of_; + /// A boolean value indicating if there are any members annotated as `@key` in the structure. + bool has_any_key_member_; /// A pointer to the array that describes each field of the interface const rosidl_typesupport_introspection_c__MessageMember * members_; /// The function used to initialise the interface's in-memory representation diff --git a/rosidl_typesupport_introspection_c/resource/msg__type_support.c.em b/rosidl_typesupport_introspection_c/resource/msg__type_support.c.em index de392983f..19b00ebef 100644 --- a/rosidl_typesupport_introspection_c/resource/msg__type_support.c.em +++ b/rosidl_typesupport_introspection_c/resource/msg__type_support.c.em @@ -238,6 +238,8 @@ for index, member in enumerate(message.structure.members): print(' 0, // upper bound of string') # const rosidl_message_type_support_t * members_ print(' NULL, // members of sub message (initialized later)') + # bool is_key_ + print(' %s, // is key' % ('true' if member.has_annotation('key') else 'false')) # bool is_array_ print(' %s, // is array' % ('true' if isinstance(member.type, AbstractNestedType) else 'false')) # size_t array_size_ @@ -276,6 +278,11 @@ static const rosidl_typesupport_introspection_c__MessageMembers @(function_prefi "@(message.structure.namespaced_type.name)", // message name @(len(message.structure.members)), // number of fields sizeof(@('__'.join([package_name] + list(interface_path.parents[0].parts) + [message.structure.namespaced_type.name]))), +@[ if message.structure.has_any_member_with_annotation('key') ]@ + true, // has_any_key_member_ +@[ else]@ + false, // has_any_key_member_ +@[ end if]@ @(function_prefix)__@(message.structure.namespaced_type.name)_message_member_array, // message members @(function_prefix)__@(message.structure.namespaced_type.name)_init_function, // function to initialize message memory (memory has to be allocated) @(function_prefix)__@(message.structure.namespaced_type.name)_fini_function // function to terminate message instance (will not free memory) diff --git a/rosidl_typesupport_introspection_cpp/include/rosidl_typesupport_introspection_cpp/message_introspection.hpp b/rosidl_typesupport_introspection_cpp/include/rosidl_typesupport_introspection_cpp/message_introspection.hpp index 6c01c2ce8..e89d2de30 100644 --- a/rosidl_typesupport_introspection_cpp/include/rosidl_typesupport_introspection_cpp/message_introspection.hpp +++ b/rosidl_typesupport_introspection_cpp/include/rosidl_typesupport_introspection_cpp/message_introspection.hpp @@ -41,6 +41,8 @@ typedef struct ROSIDL_TYPESUPPORT_INTROSPECTION_CPP_PUBLIC MessageMember_s /// If the type_id_ value is rosidl_typesupport_introspection_cpp::ROS_TYPE_MESSAGE /// this points to an array describing the fields of the sub-interface. const rosidl_message_type_support_t * members_; + /// True if this field is annotated as `@key`, false otherwise. + bool is_key_; /// True if this field is an array, false if it is a unary type. An array has the same value for /// type_id_. bool is_array_; @@ -97,6 +99,8 @@ typedef struct ROSIDL_TYPESUPPORT_INTROSPECTION_CPP_PUBLIC MessageMembers_s uint32_t member_count_; /// The size of the interface structure in memory size_t size_of_; + /// A boolean value indicating if there are any members annotated as `@key` in the structure. + bool has_any_key_member_; /// A pointer to the array that describes each field of the interface const MessageMember * members_; /// The function used to initialise the interface's in-memory representation diff --git a/rosidl_typesupport_introspection_cpp/resource/msg__type_support.cpp.em b/rosidl_typesupport_introspection_cpp/resource/msg__type_support.cpp.em index 679907386..392fc8394 100644 --- a/rosidl_typesupport_introspection_cpp/resource/msg__type_support.cpp.em +++ b/rosidl_typesupport_introspection_cpp/resource/msg__type_support.cpp.em @@ -204,6 +204,8 @@ for index, member in enumerate(message.structure.members): print(' 0, // upper bound of string') # const rosidl_message_type_support_t * members_ print(' ::rosidl_typesupport_introspection_cpp::get_message_type_support_handle<%s>(), // members of sub message' % '::'.join(type_.namespaced_name())) + # bool is_key_ + print(' %s, // is key' % ('true' if member.has_annotation('key') else 'false')) # bool is_array_ print(' %s, // is array' % ('true' if isinstance(member.type, AbstractNestedType) else 'false')) # size_t array_size_ @@ -242,6 +244,11 @@ static const ::rosidl_typesupport_introspection_cpp::MessageMembers @(message.st "@(message.structure.namespaced_type.name)", // message name @(len(message.structure.members)), // number of fields sizeof(@('::'.join([package_name] + list(interface_path.parents[0].parts) + [message.structure.namespaced_type.name]))), +@[ if message.structure.has_any_member_with_annotation('key') ]@ + true, // has_any_key_member_ +@[ else]@ + false, // has_any_key_member_ +@[ end if]@ @(message.structure.namespaced_type.name)_message_member_array, // message members @(message.structure.namespaced_type.name)_init_function, // function to initialize message memory (memory has to be allocated) @(message.structure.namespaced_type.name)_fini_function // function to terminate message instance (will not free memory)