DDS_TypeCode * outer_struct_get_typecode(struct DDS_TypeCodeFactory *tcf) { static DDS_TypeCode *tc = NULL; DDS_TypeCode *innerTC = NULL; struct DDS_StructMemberSeq members = DDS_SEQUENCE_INITIALIZER; DDS_ExceptionCode_t ex; /* First, we create the typeCode for a struct */ tc = DDS_TypeCodeFactory_create_struct_tc(tcf, "OuterStruct", &members, &ex); if (ex != DDS_NO_EXCEPTION_CODE) { fprintf(stderr, "! Unable to create struct TC\n"); goto fail; } innerTC = inner_struct_get_typecode(tcf); if (innerTC == NULL) { fprintf(stderr, "! Unable to create struct TC\n"); goto fail; } /* Member 1 of outer struct will be a struct of type inner_struct * called inner*/ DDS_TypeCode_add_member(tc, "inner", DDS_TYPECODE_MEMBER_ID_INVALID, innerTC, DDS_TYPECODE_NONKEY_REQUIRED_MEMBER, &ex); if (ex != DDS_NO_EXCEPTION_CODE) { fprintf(stderr, "! Unable to add member x\n"); goto fail; } if (innerTC != NULL) { DDS_TypeCodeFactory_delete_tc(tcf, innerTC, NULL); } DDS_StructMemberSeq_finalize(&members); return tc; fail: if (tc != NULL) { DDS_TypeCodeFactory_delete_tc(tcf, tc, &ex); } if (innerTC != NULL) { DDS_TypeCodeFactory_delete_tc(tcf, innerTC, NULL); } DDS_StructMemberSeq_finalize(&members); return NULL; }
DDS_TypeCode * inner_struct_get_typecode(struct DDS_TypeCodeFactory *tcf) { static DDS_TypeCode *tc = NULL; struct DDS_StructMemberSeq members = DDS_SEQUENCE_INITIALIZER; DDS_ExceptionCode_t ex; /* First, we create the typeCode for a struct */ tc = DDS_TypeCodeFactory_create_struct_tc(tcf, "InnerStruct", &members, &ex); if (ex != DDS_NO_EXCEPTION_CODE) { fprintf(stderr, "! Unable to create struct TC\n"); goto fail; } /* Member 1 will be a double named x */ DDS_TypeCode_add_member(tc, "x", DDS_TYPECODE_MEMBER_ID_INVALID, DDS_TypeCodeFactory_get_primitive_tc(tcf, DDS_TK_DOUBLE), DDS_TYPECODE_NONKEY_REQUIRED_MEMBER, &ex); if (ex != DDS_NO_EXCEPTION_CODE) { fprintf(stderr, "! Unable to add member x\n"); goto fail; } /* Member 2 will be a double named y */ DDS_TypeCode_add_member(tc, "y", DDS_TYPECODE_MEMBER_ID_INVALID, DDS_TypeCodeFactory_get_primitive_tc(tcf, DDS_TK_DOUBLE), DDS_TYPECODE_NONKEY_REQUIRED_MEMBER, &ex); if (ex != DDS_NO_EXCEPTION_CODE) { fprintf(stderr, "! Unable to add member y\n"); goto fail; } DDS_StructMemberSeq_finalize(&members); return tc; fail: if (tc != NULL) { DDS_TypeCodeFactory_delete_tc(tcf, tc, &ex); } DDS_StructMemberSeq_finalize(&members); return NULL; }
DDS_TypeCode * type_w_sequence_get_typecode(DDS_TypeCodeFactory *tcf) { static DDS_TypeCode * tc = NULL; struct DDS_TypeCode * sequenceTC = NULL; struct DDS_StructMemberSeq members = DDS_SEQUENCE_INITIALIZER; DDS_ExceptionCode_t err; sequenceTC = sequence_get_typecode(tcf); if (sequenceTC == NULL) { fprintf(stderr, "! Unable to get sequenceTC\n"); goto fail; } tc = DDS_TypeCodeFactory_create_struct_tc(tcf, "TypeWithSequence", &members, &err); if (tc == NULL) { fprintf(stderr, "! Unable to create Type with sequence TC\n"); goto fail; } DDS_TypeCode_add_member(tc, "sequence_member", DDS_TYPECODE_MEMBER_ID_INVALID, sequenceTC, DDS_TYPECODE_NONKEY_MEMBER, &err); if (sequenceTC != NULL) { DDS_TypeCodeFactory_delete_tc(tcf, sequenceTC, &err); } DDS_StructMemberSeq_finalize(&members); return tc; fail: if (tc != NULL) { DDS_TypeCodeFactory_delete_tc(tcf, tc, &err); } if (sequenceTC != NULL) { DDS_TypeCodeFactory_delete_tc(tcf, sequenceTC, &err); } DDS_StructMemberSeq_finalize(&members); return NULL; }
DDS_TypeCode * create_type_code( std::string type_name, const void * untyped_members, const char * introspection_identifier) { auto members = static_cast<const MembersType *>(untyped_members); if (!members) { RMW_SET_ERROR_MSG("members handle is null"); return NULL; } DDS_TypeCodeFactory * factory = DDS_TypeCodeFactory::get_instance(); if (!factory) { RMW_SET_ERROR_MSG("failed to get typecode factory"); return NULL; } // Past this point, a failure results in unrolling code in the goto fail block. DDS_StructMemberSeq struct_members; DDS_ExceptionCode_t ex = DDS_NO_EXCEPTION_CODE; // Start initializing elements. DDS_TypeCode * type_code = factory->create_struct_tc(type_name.c_str(), struct_members, ex); if (!type_code || ex != DDS_NO_EXCEPTION_CODE) { RMW_SET_ERROR_MSG("failed to create struct typecode"); goto fail; } USING_INTROSPECTION_TYPEIDS() for (uint32_t i = 0; i < members->member_count_; ++i) { auto * member = members->members_ + i; const DDS_TypeCode * member_type_code = nullptr; DDS_TypeCode * member_type_code_non_const = nullptr; switch (member->type_id_) { case rosidl_typesupport_introspection_cpp::ROS_TYPE_BOOL: member_type_code = factory->get_primitive_tc(DDS_TK_BOOLEAN); break; case rosidl_typesupport_introspection_cpp::ROS_TYPE_BYTE: member_type_code = factory->get_primitive_tc(DDS_TK_OCTET); break; case rosidl_typesupport_introspection_cpp::ROS_TYPE_CHAR: member_type_code = factory->get_primitive_tc(DDS_TK_CHAR); break; case rosidl_typesupport_introspection_cpp::ROS_TYPE_FLOAT32: member_type_code = factory->get_primitive_tc(DDS_TK_FLOAT); break; case rosidl_typesupport_introspection_cpp::ROS_TYPE_FLOAT64: member_type_code = factory->get_primitive_tc(DDS_TK_DOUBLE); break; case rosidl_typesupport_introspection_cpp::ROS_TYPE_INT8: member_type_code = factory->get_primitive_tc(DDS_TK_OCTET); break; case rosidl_typesupport_introspection_cpp::ROS_TYPE_UINT8: member_type_code = factory->get_primitive_tc(DDS_TK_OCTET); break; case rosidl_typesupport_introspection_cpp::ROS_TYPE_INT16: member_type_code = factory->get_primitive_tc(DDS_TK_SHORT); break; case rosidl_typesupport_introspection_cpp::ROS_TYPE_UINT16: member_type_code = factory->get_primitive_tc(DDS_TK_USHORT); break; case rosidl_typesupport_introspection_cpp::ROS_TYPE_INT32: member_type_code = factory->get_primitive_tc(DDS_TK_LONG); break; case rosidl_typesupport_introspection_cpp::ROS_TYPE_UINT32: member_type_code = factory->get_primitive_tc(DDS_TK_ULONG); break; case rosidl_typesupport_introspection_cpp::ROS_TYPE_INT64: member_type_code = factory->get_primitive_tc(DDS_TK_LONGLONG); break; case rosidl_typesupport_introspection_cpp::ROS_TYPE_UINT64: member_type_code = factory->get_primitive_tc(DDS_TK_ULONGLONG); break; case rosidl_typesupport_introspection_cpp::ROS_TYPE_STRING: { DDS_UnsignedLong max_string_size; if (member->string_upper_bound_) { if (member->string_upper_bound_ > (std::numeric_limits<DDS_UnsignedLong>::max)()) { RMW_SET_ERROR_MSG( "failed to create string typecode since the upper bound exceeds the DDS type"); goto fail; } max_string_size = static_cast<DDS_UnsignedLong>(member->string_upper_bound_); } else { max_string_size = RTI_INT32_MAX; } member_type_code_non_const = factory->create_string_tc(max_string_size, ex); member_type_code = member_type_code_non_const; } if (!member_type_code || ex != DDS_NO_EXCEPTION_CODE) { RMW_SET_ERROR_MSG("failed to create string typecode"); goto fail; } break; case rosidl_typesupport_introspection_cpp::ROS_TYPE_MESSAGE: { if (!member->members_) { RMW_SET_ERROR_MSG("members handle is null"); return NULL; } auto sub_members = static_cast<const MembersType *>(member->members_->data); if (!sub_members) { RMW_SET_ERROR_MSG("sub members handle is null"); return NULL; } std::string field_type_name = _create_type_name<MembersType>(sub_members, "msg"); member_type_code = create_type_code<MembersType>(field_type_name, sub_members, introspection_identifier); if (!member_type_code) { // error string was set within the function goto fail; } } break; default: RMW_SET_ERROR_MSG( (std::string("unknown type id ") + std::to_string(member->type_id_)).c_str()); goto fail; } if (!member_type_code) { RMW_SET_ERROR_MSG("failed to create typecode"); goto fail; } if (member->is_array_) { if (member->array_size_) { if (member->array_size_ > (std::numeric_limits<DDS_UnsignedLong>::max)()) { RMW_SET_ERROR_MSG("failed to create array typecode since the size exceeds the DDS type"); goto fail; } DDS_UnsignedLong array_size = static_cast<DDS_UnsignedLong>(member->array_size_); if (!member->is_upper_bound_) { member_type_code_non_const = factory->create_array_tc(array_size, member_type_code, ex); member_type_code = member_type_code_non_const; if (!member_type_code || ex != DDS_NO_EXCEPTION_CODE) { RMW_SET_ERROR_MSG("failed to create array typecode"); goto fail; } } else { member_type_code_non_const = factory->create_sequence_tc(array_size, member_type_code, ex); member_type_code = member_type_code_non_const; if (!member_type_code || ex != DDS_NO_EXCEPTION_CODE) { RMW_SET_ERROR_MSG("failed to create sequence typecode"); goto fail; } } } else { member_type_code_non_const = factory->create_sequence_tc( RTI_INT32_MAX, member_type_code, ex); member_type_code = member_type_code_non_const; if (!member_type_code || ex != DDS_NO_EXCEPTION_CODE) { RMW_SET_ERROR_MSG("failed to create sequence typecode"); goto fail; } } } auto zero_based_index = type_code->add_member( (std::string(member->name_) + "_").c_str(), i, member_type_code, DDS_TYPECODE_NONKEY_REQUIRED_MEMBER, ex); if (ex != DDS_NO_EXCEPTION_CODE) { RMW_SET_ERROR_MSG("failed to add member"); goto fail; } if (zero_based_index != i) { RMW_SET_ERROR_MSG("unexpected member index"); return NULL; } } // since empty message definitions are not supported // we have to add the same dummy field as in rosidl_generator_dds_idl if (members->member_count_ == 0) { const DDS_TypeCode * member_type_code; member_type_code = factory->get_primitive_tc(DDS_TK_BOOLEAN); if (!member_type_code) { RMW_SET_ERROR_MSG("failed to get primitive typecode"); goto fail; } type_code->add_member("_dummy", DDS_TYPECODE_MEMBER_ID_INVALID, member_type_code, DDS_TYPECODE_NONKEY_REQUIRED_MEMBER, ex); if (ex != DDS_NO_EXCEPTION_CODE) { RMW_SET_ERROR_MSG("failed to add member"); goto fail; } } DDS_StructMemberSeq_finalize(&struct_members); return type_code; fail: if (type_code) { if (factory) { DDS_ExceptionCode_t exc = DDS_NO_EXCEPTION_CODE; factory->delete_tc(type_code, exc); if (exc != DDS_NO_EXCEPTION_CODE) { std::stringstream ss; ss << "failed to delete type code during handling of failure at " << __FILE__ << ":" << __LINE__ << '\n'; (std::cerr << ss.str()).flush(); } } else { std::stringstream ss; ss << "leaking type code during handling of failure at " << __FILE__ << ":" << __LINE__ << '\n'; (std::cerr << ss.str()).flush(); } } return nullptr; }