diff --git a/rcl/include/rcl/client.h b/rcl/include/rcl/client.h index ad8131b..d8bba97 100644 --- a/rcl/include/rcl/client.h +++ b/rcl/include/rcl/client.h @@ -370,6 +370,28 @@ RCL_WARN_UNUSED rmw_client_t * rcl_client_get_rmw_handle(const rcl_client_t * client); +/// Check that the client is valid. +/** + * The bool returned is `false` if client is invalid + * The bool returned is `true` otherwise. + * In the case where `false` is to be returned, an + * error message is set. + * This function cannot fail. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] client pointer to the rcl client + * \return `true` if `client` is valid, otherwise `false` + */ +bool +rcl_client_is_valid(const rcl_client_t * client); + #if __cplusplus } #endif diff --git a/rcl/include/rcl/publisher.h b/rcl/include/rcl/publisher.h index aba70c8..315df65 100644 --- a/rcl/include/rcl/publisher.h +++ b/rcl/include/rcl/publisher.h @@ -336,6 +336,29 @@ RCL_WARN_UNUSED rmw_publisher_t * rcl_publisher_get_rmw_handle(const rcl_publisher_t * publisher); +/// Check that the publisher is valid +/** + * The bool returned is `false` if `publisher` is invalid. + * The bool returned is `true` otherwise. + * In the case where `false` is to be returned, an + * error message is set. + * This function cannot fail. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] publisher pointer to the rcl publisher + * \return `true` if the publisher is valid, otherwise `false` + */ + +bool +rcl_publisher_is_valid(const rcl_publisher_t * publisher); + #if __cplusplus } #endif diff --git a/rcl/include/rcl/service.h b/rcl/include/rcl/service.h index d4a6ac6..44e6f7e 100644 --- a/rcl/include/rcl/service.h +++ b/rcl/include/rcl/service.h @@ -382,6 +382,28 @@ RCL_WARN_UNUSED rmw_service_t * rcl_service_get_rmw_handle(const rcl_service_t * service); +/// Check that the service is valid. +/** + * The bool returned is `false` if `service` is invalid. + * The bool returned is `true` otherwise. + * In the case where `false` is to be returned, an + * error message is set. + * This function cannot fail. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] service pointer to the rcl service + * \return `true` if `service` is valid, otherwise `false` + */ +bool +rcl_service_is_valid(const rcl_service_t * service); + #if __cplusplus } #endif diff --git a/rcl/include/rcl/subscription.h b/rcl/include/rcl/subscription.h index dbcb175..e78c213 100644 --- a/rcl/include/rcl/subscription.h +++ b/rcl/include/rcl/subscription.h @@ -339,6 +339,28 @@ RCL_WARN_UNUSED rmw_subscription_t * rcl_subscription_get_rmw_handle(const rcl_subscription_t * subscription); +/// Check that the subscription is valid. +/** + * The bool returned is `false` if `subscription` is invalid. + * The bool returned is `true` otherwise. + * In the case where `false` is to be returned, an + * error message is set. + * This function cannot fail. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] subscription pointer to the rcl subscription + * \return `true` if `subscription` is valid, otherwise `false` + */ +bool +rcl_subscription_is_valid(const rcl_subscription_t * subscription); + #if __cplusplus } #endif diff --git a/rcl/src/rcl/client.c b/rcl/src/rcl/client.c index a0c6e98..6777bbc 100644 --- a/rcl/src/rcl/client.c +++ b/rcl/src/rcl/client.c @@ -201,29 +201,29 @@ rcl_client_get_default_options() const char * rcl_client_get_service_name(const rcl_client_t * client) { - const rcl_client_options_t * options = rcl_client_get_options(client); - if (!options) { + if (!rcl_client_is_valid(client)) { return NULL; // error already set } - RCL_CHECK_FOR_NULL_WITH_MSG( - client->impl->rmw_handle, "client is invalid", return NULL, options->allocator); return client->impl->rmw_handle->service_name; } +/* *INDENT-OFF* */ +#define _client_get_options(client) &client->impl->options; +/* *INDENT-ON* */ + const rcl_client_options_t * rcl_client_get_options(const rcl_client_t * client) { - RCL_CHECK_ARGUMENT_FOR_NULL(client, NULL, rcl_get_default_allocator()); - RCL_CHECK_FOR_NULL_WITH_MSG( - client->impl, "client is invalid", return NULL, rcl_get_default_allocator()); - return &client->impl->options; + if (!rcl_client_is_valid(client)) { + return NULL; // error already set + } + return _client_get_options(client); } rmw_client_t * rcl_client_get_rmw_handle(const rcl_client_t * client) { - const rcl_client_options_t * options = rcl_client_get_options(client); - if (!options) { + if (!rcl_client_is_valid(client)) { return NULL; // error already set } return client->impl->rmw_handle; @@ -234,12 +234,12 @@ RCL_WARN_UNUSED rcl_ret_t rcl_send_request(const rcl_client_t * client, const void * ros_request, int64_t * sequence_number) { - RCL_CHECK_ARGUMENT_FOR_NULL(client, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator()); + if (!rcl_client_is_valid(client)) { + return RCL_RET_CLIENT_INVALID; + } RCL_CHECK_ARGUMENT_FOR_NULL(ros_request, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator()); RCL_CHECK_ARGUMENT_FOR_NULL( sequence_number, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator()); - RCL_CHECK_FOR_NULL_WITH_MSG( - client->impl, "client is invalid", return RCL_RET_CLIENT_INVALID, rcl_get_default_allocator()); *sequence_number = rcl_atomic_load_int64_t(&client->impl->sequence_number); if (rmw_send_request( client->impl->rmw_handle, ros_request, sequence_number) != RMW_RET_OK) @@ -259,9 +259,10 @@ rcl_take_response( rmw_request_id_t * request_header, void * ros_response) { - RCL_CHECK_ARGUMENT_FOR_NULL(client, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator()); - RCL_CHECK_FOR_NULL_WITH_MSG( - client->impl, "client is invalid", return RCL_RET_CLIENT_INVALID, rcl_get_default_allocator()); + if (!rcl_client_is_valid(client)) { + return RCL_RET_CLIENT_INVALID; + } + RCL_CHECK_ARGUMENT_FOR_NULL( request_header, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator()); RCL_CHECK_ARGUMENT_FOR_NULL(ros_response, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator()); @@ -280,7 +281,18 @@ rcl_take_response( return RCL_RET_OK; } - +bool rcl_client_is_valid(const rcl_client_t * client) +{ + const rcl_client_options_t * options; + RCL_CHECK_ARGUMENT_FOR_NULL( + client, false, rcl_get_default_allocator()); + options = _client_get_options(client); + RCL_CHECK_FOR_NULL_WITH_MSG( + options, "client's options pointer is invalid", return false, rcl_get_default_allocator()); + RCL_CHECK_FOR_NULL_WITH_MSG( + client->impl, "client's rmw implementation is invalid", return false, options->allocator); + return true; +} #if __cplusplus } #endif diff --git a/rcl/src/rcl/publisher.c b/rcl/src/rcl/publisher.c index 1adf98f..655b26d 100644 --- a/rcl/src/rcl/publisher.c +++ b/rcl/src/rcl/publisher.c @@ -199,16 +199,11 @@ rcl_publisher_get_default_options() rcl_ret_t rcl_publish(const rcl_publisher_t * publisher, const void * ros_message) { - RCL_CHECK_ARGUMENT_FOR_NULL(publisher, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator()); - const rcl_publisher_options_t * options = rcl_publisher_get_options(publisher); - if (!options) { + if (!rcl_publisher_is_valid(publisher)) { return RCL_RET_PUBLISHER_INVALID; } - RCL_CHECK_ARGUMENT_FOR_NULL(ros_message, RCL_RET_INVALID_ARGUMENT, options->allocator); - RCL_CHECK_FOR_NULL_WITH_MSG( - publisher->impl, "publisher is invalid", return RCL_RET_PUBLISHER_INVALID, options->allocator); if (rmw_publish(publisher->impl->rmw_handle, ros_message) != RMW_RET_OK) { - RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), options->allocator); + RCL_SET_ERROR_MSG(rmw_get_error_string_safe(), rcl_get_default_allocator()); return RCL_RET_ERROR; } return RCL_RET_OK; @@ -217,35 +212,49 @@ rcl_publish(const rcl_publisher_t * publisher, const void * ros_message) const char * rcl_publisher_get_topic_name(const rcl_publisher_t * publisher) { - const rcl_publisher_options_t * options = rcl_publisher_get_options(publisher); - if (!options) { + if (!rcl_publisher_is_valid(publisher)) { return NULL; } - RCL_CHECK_FOR_NULL_WITH_MSG( - publisher->impl, "publisher is invalid", return NULL, options->allocator); - RCL_CHECK_FOR_NULL_WITH_MSG( - publisher->impl->rmw_handle, "publisher is invalid", return NULL, options->allocator); return publisher->impl->rmw_handle->topic_name; } +/* *INDENT-OFF* */ +#define _publisher_get_options(pub) &pub->impl->options +/* *INDENT-ON* */ + const rcl_publisher_options_t * rcl_publisher_get_options(const rcl_publisher_t * publisher) { - RCL_CHECK_ARGUMENT_FOR_NULL(publisher, NULL, rcl_get_default_allocator()); - RCL_CHECK_FOR_NULL_WITH_MSG( - publisher->impl, "publisher is invalid", return NULL, rcl_get_default_allocator()); - return &publisher->impl->options; + if (!rcl_publisher_is_valid(publisher)) { + return NULL; + } + return _publisher_get_options(publisher); } rmw_publisher_t * rcl_publisher_get_rmw_handle(const rcl_publisher_t * publisher) { - RCL_CHECK_ARGUMENT_FOR_NULL(publisher, NULL, rcl_get_default_allocator()); - RCL_CHECK_FOR_NULL_WITH_MSG( - publisher->impl, "publisher is invalid", return NULL, rcl_get_default_allocator()); + if (!rcl_publisher_is_valid(publisher)) { + return NULL; + } return publisher->impl->rmw_handle; } +bool +rcl_publisher_is_valid(const rcl_publisher_t * publisher) +{ + const rcl_publisher_options_t * options; + RCL_CHECK_ARGUMENT_FOR_NULL(publisher, false, rcl_get_default_allocator()); + options = _publisher_get_options(publisher); + RCL_CHECK_FOR_NULL_WITH_MSG( + options, "publisher's options pointer is invalid", return false, rcl_get_default_allocator()); + RCL_CHECK_FOR_NULL_WITH_MSG( + publisher->impl, "publisher implementation is invalid", return false, options->allocator); + RCL_CHECK_FOR_NULL_WITH_MSG( + publisher->impl->rmw_handle, "publisher rmw handle invalid", return false, options->allocator); + return true; +} + #if __cplusplus } #endif diff --git a/rcl/src/rcl/service.c b/rcl/src/rcl/service.c index dd37f27..ebfcb34 100644 --- a/rcl/src/rcl/service.c +++ b/rcl/src/rcl/service.c @@ -211,21 +211,25 @@ rcl_service_get_service_name(const rcl_service_t * service) return service->impl->rmw_handle->service_name; } +/* *INDENT-OFF* */ +#define _service_get_options(service) &service->impl->options +/* *INDENT-ON* */ + const rcl_service_options_t * rcl_service_get_options(const rcl_service_t * service) { - RCL_CHECK_ARGUMENT_FOR_NULL(service, NULL, rcl_get_default_allocator()); - RCL_CHECK_FOR_NULL_WITH_MSG( - service->impl, "service is invalid", return NULL, rcl_get_default_allocator()); - return &service->impl->options; + if (!rcl_service_is_valid(service)) { + return NULL; + } + return _service_get_options(service); } rmw_service_t * rcl_service_get_rmw_handle(const rcl_service_t * service) { - RCL_CHECK_ARGUMENT_FOR_NULL(service, NULL, rcl_get_default_allocator()); - RCL_CHECK_FOR_NULL_WITH_MSG( - service->impl, "service is invalid", return NULL, rcl_get_default_allocator()); + if (!rcl_service_is_valid(service)) { + return NULL; + } return service->impl->rmw_handle; } @@ -235,11 +239,7 @@ rcl_take_request( rmw_request_id_t * request_header, void * ros_request) { - RCL_CHECK_ARGUMENT_FOR_NULL(service, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator()); const rcl_service_options_t * options = rcl_service_get_options(service); - if (!options) { - return RCL_RET_SERVICE_INVALID; - } RCL_CHECK_ARGUMENT_FOR_NULL(request_header, RCL_RET_INVALID_ARGUMENT, options->allocator); RCL_CHECK_ARGUMENT_FOR_NULL(ros_request, RCL_RET_INVALID_ARGUMENT, options->allocator); @@ -262,11 +262,7 @@ rcl_send_response( rmw_request_id_t * request_header, void * ros_response) { - RCL_CHECK_ARGUMENT_FOR_NULL(service, RCL_RET_INVALID_ARGUMENT, rcl_get_default_allocator()); const rcl_service_options_t * options = rcl_service_get_options(service); - if (!options) { - return RCL_RET_SERVICE_INVALID; - } RCL_CHECK_ARGUMENT_FOR_NULL(request_header, RCL_RET_INVALID_ARGUMENT, options->allocator); RCL_CHECK_ARGUMENT_FOR_NULL(ros_response, RCL_RET_INVALID_ARGUMENT, options->allocator); @@ -280,6 +276,27 @@ rcl_send_response( return RCL_RET_OK; } +bool +rcl_service_is_valid(const rcl_service_t * service) +{ + const rcl_service_options_t * options; + RCL_CHECK_ARGUMENT_FOR_NULL(service, false, rcl_get_default_allocator()); + options = _service_get_options(service); + RCL_CHECK_FOR_NULL_WITH_MSG(options, + "service's options pointer is invalid", + return false, + rcl_get_default_allocator()); + RCL_CHECK_FOR_NULL_WITH_MSG(service->impl, + "service implementation is invalid", + return false, + options->allocator); + RCL_CHECK_FOR_NULL_WITH_MSG(service->impl->rmw_handle, + "service's rmw handle is invalid", + return false, + options->allocator); + return true; +} + #if __cplusplus } #endif diff --git a/rcl/src/rcl/subscription.c b/rcl/src/rcl/subscription.c index 343c393..fd3cd73 100644 --- a/rcl/src/rcl/subscription.c +++ b/rcl/src/rcl/subscription.c @@ -231,34 +231,55 @@ rcl_take( const char * rcl_subscription_get_topic_name(const rcl_subscription_t * subscription) { - const rcl_subscription_options_t * options = rcl_subscription_get_options(subscription); - if (!options) { + if (!rcl_subscription_is_valid(subscription)) { return NULL; } - RCL_CHECK_FOR_NULL_WITH_MSG( - subscription->impl->rmw_handle, - "subscription is invalid", return NULL, options->allocator); return subscription->impl->rmw_handle->topic_name; } +/* *INDENT-OFF* */ +#define _subscription_get_options(subscription) &subscription->impl->options +/* *INDENT-ON* */ + const rcl_subscription_options_t * rcl_subscription_get_options(const rcl_subscription_t * subscription) { - RCL_CHECK_ARGUMENT_FOR_NULL(subscription, NULL, rcl_get_default_allocator()); - RCL_CHECK_FOR_NULL_WITH_MSG( - subscription->impl, "subscription is invalid", return NULL, rcl_get_default_allocator()); - return &subscription->impl->options; + if (!rcl_subscription_is_valid(subscription)) { + return NULL; + } + return _subscription_get_options(subscription); } rmw_subscription_t * rcl_subscription_get_rmw_handle(const rcl_subscription_t * subscription) { - RCL_CHECK_ARGUMENT_FOR_NULL(subscription, NULL, rcl_get_default_allocator()); - RCL_CHECK_FOR_NULL_WITH_MSG( - subscription->impl, "subscription is invalid", return NULL, rcl_get_default_allocator()); + if (!rcl_subscription_is_valid(subscription)) { + return NULL; + } return subscription->impl->rmw_handle; } +bool +rcl_subscription_is_valid(const rcl_subscription_t * subscription) +{ + const rcl_subscription_options_t * options; + RCL_CHECK_ARGUMENT_FOR_NULL(subscription, false, rcl_get_default_allocator()); + options = _subscription_get_options(subscription); + RCL_CHECK_FOR_NULL_WITH_MSG(options, + "subscription's option pointer is invalid", + return false, + rcl_get_default_allocator()); + RCL_CHECK_FOR_NULL_WITH_MSG(subscription->impl, + "subscription implementation is invalid", + return false, + options->allocator); + RCL_CHECK_FOR_NULL_WITH_MSG(subscription->impl->rmw_handle, + "subscription implementation rmw_handle is invalid", + return false, + options->allocator); + return true; +} + #if __cplusplus } #endif