diff --git a/rosbag2/include/rosbag2/typesupport_helpers.hpp b/rosbag2/include/rosbag2/typesupport_helpers.hpp index fda9de6a85..d8519a0389 100644 --- a/rosbag2/include/rosbag2/typesupport_helpers.hpp +++ b/rosbag2/include/rosbag2/typesupport_helpers.hpp @@ -16,6 +16,7 @@ #define ROSBAG2__TYPESUPPORT_HELPERS_HPP_ #include +#include #include #include "rosidl_generator_cpp/message_type_support_decl.hpp" @@ -28,9 +29,14 @@ ROSBAG2_PUBLIC const rosidl_message_type_support_t * get_typesupport(const std::string & type, const std::string & typesupport_identifier); +[[deprecated("use extract_type_identifier(const std::string & full_type) instead")]] ROSBAG2_PUBLIC const std::pair extract_type_and_package(const std::string & full_type); +ROSBAG2_PUBLIC +const std::tuple +extract_type_identifier(const std::string & full_type); + } // namespace rosbag2 #endif // ROSBAG2__TYPESUPPORT_HELPERS_HPP_ diff --git a/rosbag2/src/rosbag2/typesupport_helpers.cpp b/rosbag2/src/rosbag2/typesupport_helpers.cpp index d8c3e02ec9..d4cd3e0b22 100644 --- a/rosbag2/src/rosbag2/typesupport_helpers.cpp +++ b/rosbag2/src/rosbag2/typesupport_helpers.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "ament_index_cpp/get_resources.hpp" @@ -62,6 +63,17 @@ std::string get_typesupport_library_path( } const std::pair extract_type_and_package(const std::string & full_type) +{ + std::string package_name; + std::string type_name; + + std::tie(package_name, std::ignore, type_name) = extract_type_identifier(full_type); + + return {package_name, type_name}; +} + +const std::tuple +extract_type_identifier(const std::string & full_type) { char type_separator = '/'; auto sep_position_back = full_type.find_last_of(type_separator); @@ -75,17 +87,23 @@ const std::pair extract_type_and_package(const std::st } std::string package_name = full_type.substr(0, sep_position_front); + std::string middle_module = ""; + if (sep_position_back - sep_position_front > 0) { + middle_module = + full_type.substr(sep_position_front + 1, sep_position_back - sep_position_front - 1); + } std::string type_name = full_type.substr(sep_position_back + 1); - return {package_name, type_name}; + return std::make_tuple(package_name, middle_module, type_name); } const rosidl_message_type_support_t * get_typesupport(const std::string & type, const std::string & typesupport_identifier) { std::string package_name; + std::string middle_module; std::string type_name; - std::tie(package_name, type_name) = extract_type_and_package(type); + std::tie(package_name, middle_module, type_name) = extract_type_identifier(type); std::string poco_dynamic_loading_error = "Something went wrong loading the typesupport library " "for message type " + package_name + "/" + type_name + "."; @@ -96,7 +114,7 @@ get_typesupport(const std::string & type, const std::string & typesupport_identi auto typesupport_library = std::make_shared(library_path); auto symbol_name = typesupport_identifier + "__get_message_type_support_handle__" + - package_name + "__msg__" + type_name; + package_name + "__" + (middle_module.empty() ? "msg" : middle_module) + "__" + type_name; if (!typesupport_library->hasSymbol(symbol_name)) { throw std::runtime_error(poco_dynamic_loading_error + " Symbol not found."); diff --git a/rosbag2/test/rosbag2/test_typesupport_helpers.cpp b/rosbag2/test/rosbag2/test_typesupport_helpers.cpp index f7ad099891..0d3187b2a0 100644 --- a/rosbag2/test/rosbag2/test_typesupport_helpers.cpp +++ b/rosbag2/test/rosbag2/test_typesupport_helpers.cpp @@ -24,18 +24,25 @@ using namespace ::testing; // NOLINT TEST(TypesupportHelpersTest, throws_exception_if_filetype_has_no_type) { - EXPECT_ANY_THROW(rosbag2::extract_type_and_package("just_a_package_name")); + EXPECT_ANY_THROW(rosbag2::extract_type_identifier("just_a_package_name")); } TEST(TypesupportHelpersTest, throws_exception_if_filetype_has_slash_at_the_start_only) { - EXPECT_ANY_THROW(rosbag2::extract_type_and_package("/name_with_slash_at_start")); + EXPECT_ANY_THROW(rosbag2::extract_type_identifier("/name_with_slash_at_start")); } TEST(TypesupportHelpersTest, throws_exception_if_filetype_has_slash_at_the_end_only) { - EXPECT_ANY_THROW(rosbag2::extract_type_and_package("name_with_slash_at_end/")); + EXPECT_ANY_THROW(rosbag2::extract_type_identifier("name_with_slash_at_end/")); } -TEST(TypesupportHelpersTest, separates_into_package_and_name_for_correct_package) { +#if !defined(_WIN32) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#else // !defined(_WIN32) +# pragma warning(push) +# pragma warning(disable: 4996) +#endif +TEST(TypesupportHelpersTest, separates_into_package_and_name_for_correct_package_legacy) { std::string package; std::string name; std::tie(package, name) = rosbag2::extract_type_and_package("package/name"); @@ -44,13 +51,42 @@ TEST(TypesupportHelpersTest, separates_into_package_and_name_for_correct_package EXPECT_THAT(name, StrEq("name")); } +TEST(TypesupportHelpersTest, separates_into_package_and_name_for_multiple_slashes_legacy) { + std::string package; + std::string name; + std::tie(package, name) = + rosbag2::extract_type_and_package("package/middle_module/name"); + + EXPECT_THAT(package, StrEq("package")); + EXPECT_THAT(name, StrEq("name")); +} +#if !defined(_WIN32) +# pragma GCC diagnostic pop +#else // !defined(_WIN32) +# pragma warning(pop) +#endif + +TEST(TypesupportHelpersTest, separates_into_package_and_name_for_correct_package) { + std::string package; + std::string middle_module; + std::string name; + std::tie(package, middle_module, name) = rosbag2::extract_type_identifier("package/name"); + + EXPECT_THAT(package, StrEq("package")); + EXPECT_THAT(middle_module, StrEq("")); + EXPECT_THAT(name, StrEq("name")); +} + TEST(TypesupportHelpersTest, separates_into_package_and_name_for_multiple_slashes) { std::string package; + std::string middle_module; std::string name; - std::tie(package, name) = rosbag2::extract_type_and_package("name/with/multiple_slashes"); + std::tie(package, middle_module, name) = + rosbag2::extract_type_identifier("package/middle_module/name"); - EXPECT_THAT(package, StrEq("name")); - EXPECT_THAT(name, StrEq("multiple_slashes")); + EXPECT_THAT(package, StrEq("package")); + EXPECT_THAT(middle_module, StrEq("middle_module")); + EXPECT_THAT(name, StrEq("name")); } TEST(TypesupportHelpersTest, throws_exception_if_library_cannot_be_found) { @@ -58,10 +94,18 @@ TEST(TypesupportHelpersTest, throws_exception_if_library_cannot_be_found) { rosbag2::get_typesupport("invalid/message", "rosidl_typesupport_cpp"), std::runtime_error); } -TEST(TypesupportHelpersTest, returns_c_type_info_for_valid_library) { +TEST(TypesupportHelpersTest, returns_c_type_info_for_valid_legacy_library) { auto string_typesupport = rosbag2::get_typesupport("test_msgs/BasicTypes", "rosidl_typesupport_cpp"); EXPECT_THAT(std::string(string_typesupport->typesupport_identifier), ContainsRegex("rosidl_typesupport")); } + +TEST(TypesupportHelpersTest, returns_c_type_info_for_valid_library) { + auto string_typesupport = + rosbag2::get_typesupport("test_msgs/msg/BasicTypes", "rosidl_typesupport_cpp"); + + EXPECT_THAT(std::string(string_typesupport->typesupport_identifier), + ContainsRegex("rosidl_typesupport")); +}