15 #include "rclcpp/expand_topic_or_service_name.hpp"
21 #include "rclcpp/exceptions.hpp"
22 #include "rcutils/logging_macros.h"
23 #include "rcutils/types/string_map.h"
24 #include "rmw/error_handling.h"
25 #include "rmw/validate_namespace.h"
26 #include "rmw/validate_node_name.h"
27 #include "rmw/validate_full_topic_name.h"
29 using rclcpp::exceptions::throw_from_rcl_error;
33 const std::string & name,
34 const std::string & node_name,
35 const std::string & namespace_,
38 char * expanded_topic =
nullptr;
40 rcutils_allocator_t rcutils_allocator = rcutils_get_default_allocator();
41 rcutils_string_map_t substitutions_map = rcutils_get_zero_initialized_string_map();
43 rcutils_ret_t rcutils_ret = rcutils_string_map_init(&substitutions_map, 0, rcutils_allocator);
44 if (rcutils_ret != RCUTILS_RET_OK) {
45 if (rcutils_ret == RCUTILS_RET_BAD_ALLOC) {
46 throw_from_rcl_error(
RCL_RET_BAD_ALLOC,
"", rcutils_get_error_state(), rcutils_reset_error);
48 throw_from_rcl_error(
RCL_RET_ERROR,
"", rcutils_get_error_state(), rcutils_reset_error);
53 const rcutils_error_state_t * error_state = rcl_get_error_state();
55 rcutils_ret = rcutils_string_map_fini(&substitutions_map);
56 if (rcutils_ret != RCUTILS_RET_OK) {
57 RCUTILS_LOG_ERROR_NAMED(
59 "failed to fini string_map (%d) during error handling: %s",
61 rcutils_get_error_string().str);
62 rcutils_reset_error();
64 throw_from_rcl_error(ret,
"", error_state);
77 result = expanded_topic;
78 allocator.deallocate(expanded_topic, allocator.state);
81 rcutils_ret = rcutils_string_map_fini(&substitutions_map);
82 if (rcutils_ret != RCUTILS_RET_OK) {
83 throw_from_rcl_error(
RCL_RET_ERROR,
"", rcutils_get_error_state(), rcutils_reset_error);
91 int validation_result;
95 throw_from_rcl_error(ret);
99 const char * validation_message =
103 throw InvalidServiceNameError(name.c_str(), validation_message, invalid_index);
106 throw InvalidTopicNameError(name.c_str(), validation_message, invalid_index);
109 throw std::runtime_error(
"topic name unexpectedly valid");
115 int validation_result;
116 size_t invalid_index;
118 rmw_validate_node_name(node_name.c_str(), &validation_result, &invalid_index);
119 if (rmw_ret != RMW_RET_OK) {
120 if (rmw_ret == RMW_RET_INVALID_ARGUMENT) {
121 throw_from_rcl_error(
123 rmw_get_error_state(), rmw_reset_error);
125 throw_from_rcl_error(
127 rmw_get_error_state(), rmw_reset_error);
130 if (validation_result != RMW_NODE_NAME_VALID) {
133 rmw_node_name_validation_result_string(validation_result),
136 throw std::runtime_error(
"invalid rcl node name but valid rmw node name");
142 int validation_result;
143 size_t invalid_index;
145 rmw_validate_namespace(namespace_.c_str(), &validation_result, &invalid_index);
146 if (rmw_ret != RMW_RET_OK) {
147 if (rmw_ret == RMW_RET_INVALID_ARGUMENT) {
148 throw_from_rcl_error(
150 rmw_get_error_state(), rmw_reset_error);
152 throw_from_rcl_error(
154 rmw_get_error_state(), rmw_reset_error);
157 if (validation_result != RMW_NAMESPACE_VALID) {
160 rmw_namespace_validation_result_string(validation_result),
163 throw std::runtime_error(
"invalid rcl namespace but valid rmw namespace");
167 throw_from_rcl_error(ret);
172 int validation_result;
173 size_t invalid_index;
175 rmw_validate_full_topic_name(result.c_str(), &validation_result, &invalid_index);
176 if (rmw_ret != RMW_RET_OK) {
177 if (rmw_ret == RMW_RET_INVALID_ARGUMENT) {
178 throw_from_rcl_error(
180 rmw_get_error_state(), rmw_reset_error);
182 throw_from_rcl_error(
184 rmw_get_error_state(), rmw_reset_error);
187 if (validation_result != RMW_TOPIC_VALID) {
191 rmw_full_topic_name_validation_result_string(validation_result),
196 rmw_full_topic_name_validation_result_string(validation_result),
#define rcl_get_default_allocator
Return a properly initialized rcl_allocator_t with default values.
rcutils_allocator_t rcl_allocator_t
Encapsulation of an allocator.
Thrown when a node namespace is invalid.
Thrown when a node name is invalid.
Thrown when a service name is invalid.
Thrown when a topic name is invalid.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_expand_topic_name(const char *input_topic_name, const char *node_name, const char *node_namespace, const rcutils_string_map_t *substitutions, rcl_allocator_t allocator, char **output_topic_name)
Expand a given topic name into a fully-qualified topic name.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_get_default_topic_name_substitutions(rcutils_string_map_t *string_map)
Fill a given string map with the default substitution pairs.
RCLCPP_PUBLIC std::string expand_topic_or_service_name(const std::string &name, const std::string &node_name, const std::string &namespace_, bool is_service=false)
Expand a topic or service name and throw if it is not valid.
#define RCL_RET_NODE_INVALID_NAMESPACE
Invalid node namespace return code.
#define RCL_RET_UNKNOWN_SUBSTITUTION
Topic name substitution is unknown.
#define RCL_RET_OK
Success return code.
#define RCL_RET_BAD_ALLOC
Failed to allocate memory return code.
#define RCL_RET_INVALID_ARGUMENT
Invalid argument return code.
#define RCL_RET_ERROR
Unspecified error return code.
#define RCL_RET_TOPIC_NAME_INVALID
Topic name does not pass validation.
#define RCL_RET_NODE_INVALID_NAME
Invalid node name return code.
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_validate_topic_name(const char *topic_name, int *validation_result, size_t *invalid_index)
Validate a given topic name.
#define RCL_TOPIC_NAME_VALID
The topic name is valid.
RCL_PUBLIC RCL_WARN_UNUSED const char * rcl_topic_name_validation_result_string(int validation_result)
Return a validation result description, or NULL if unknown or RCL_TOPIC_NAME_VALID.