diff --git a/rcl/include/rcl/graph.h b/rcl/include/rcl/graph.h index 8fb9f97a3..dfcd3cf68 100644 --- a/rcl/include/rcl/graph.h +++ b/rcl/include/rcl/graph.h @@ -292,6 +292,37 @@ rcl_get_service_names_and_types( rcl_allocator_t * allocator, rcl_names_and_types_t * service_names_and_types); +/// Initialize a rcl_names_and_types_t object. +/** + * This function initializes the string array for the names and allocates space + * for all the string arrays for the types according to the given size, but + * it does not initialize the string array for each set of types. + * However, the string arrays for each set of types is zero initialized. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[inout] names_and_types object to be initialized + * \param[in] size the number of names and sets of types to be stored + * \param[in] allocator to be used to allocate and deallocate memory + * \returns `RCL_RET_OK` on success, or + * \returns `RCL_RET_INVALID_ARGUMENT` if any arguments are invalid, or + * \returns `RCL_BAD_ALLOC` if memory allocation fails, or + * \returns `RCL_RET_ERROR` when an unspecified error occurs. + */ +RCL_PUBLIC +RCL_WARN_UNUSED +rcl_ret_t +rcl_names_and_types_init( + rcl_names_and_types_t * names_and_types, + size_t size, + rcl_allocator_t * allocator); + /// Finalize a rcl_names_and_types_t object. /** * The object is populated when given to one of the rcl_get_*_names_and_types() diff --git a/rcl/src/rcl/graph.c b/rcl/src/rcl/graph.c index d41df2529..574a7d0f2 100644 --- a/rcl/src/rcl/graph.c +++ b/rcl/src/rcl/graph.c @@ -193,6 +193,17 @@ rcl_get_service_names_and_types( return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret); } +rcl_ret_t +rcl_names_and_types_init( + rcl_names_and_types_t * names_and_types, + size_t size, + rcl_allocator_t * allocator) +{ + RCL_CHECK_ARGUMENT_FOR_NULL(names_and_types, RCL_RET_INVALID_ARGUMENT); + rmw_ret_t rmw_ret = rmw_names_and_types_init(names_and_types, size, allocator); + return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret); +} + rcl_ret_t rcl_names_and_types_fini(rcl_names_and_types_t * topic_names_and_types) { diff --git a/rcl/test/rcl/test_graph.cpp b/rcl/test/rcl/test_graph.cpp index 287ee0f2d..4e424ae1b 100644 --- a/rcl/test/rcl/test_graph.cpp +++ b/rcl/test/rcl/test_graph.cpp @@ -170,6 +170,41 @@ TEST_F( EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; } +/* Test the rcl_names_and_types_init function. + */ +TEST_F( + CLASSNAME(TestGraphFixture, RMW_IMPLEMENTATION), + test_rcl_names_and_types_init +) { + rcl_ret_t ret; + rcl_allocator_t allocator = rcl_get_default_allocator(); + rcl_names_and_types_t nat = rcl_get_zero_initialized_names_and_types(); + // invalid names and types + ret = rcl_names_and_types_init(nullptr, 10, &allocator); + EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string().str; + rcl_reset_error(); + // invalid allocator + ret = rcl_names_and_types_init(&nat, 10, nullptr); + EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string().str; + rcl_reset_error(); + // zero size + ret = rcl_names_and_types_init(&nat, 0, &allocator); + EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; + EXPECT_EQ(nat.names.size, 0u); + ret = rcl_names_and_types_fini(&nat); + ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; + // non-zero size + size_t num_names = 10u; + ret = rcl_names_and_types_init(&nat, num_names, &allocator); + EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; + EXPECT_EQ(nat.names.size, num_names); + for (size_t i = 0; i < num_names; i++) { + EXPECT_EQ(nat.types[i].size, 0u); + } + ret = rcl_names_and_types_fini(&nat); + EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; +} + /* Test the rcl_count_publishers function. * * This does not test content the response.