From 6c278c3480996d38742bc1da1ff5f13046370b53 Mon Sep 17 00:00:00 2001 From: Ivan Santiago Paunovic Date: Mon, 19 Oct 2020 10:55:25 -0300 Subject: [PATCH 1/4] Add functions to convert between qos policy values and strings Signed-off-by: Ivan Santiago Paunovic --- rmw/CMakeLists.txt | 1 + rmw/include/rmw/qos_string_conversions.h | 128 +++++++++++++++++++++ rmw/src/qos_string_conversions.c | 139 +++++++++++++++++++++++ rmw/test/CMakeLists.txt | 9 ++ rmw/test/test_qos_string_conversions.cpp | 55 +++++++++ 5 files changed, 332 insertions(+) create mode 100644 rmw/include/rmw/qos_string_conversions.h create mode 100644 rmw/src/qos_string_conversions.c create mode 100644 rmw/test/test_qos_string_conversions.cpp diff --git a/rmw/CMakeLists.txt b/rmw/CMakeLists.txt index 23c94572..93b959e1 100644 --- a/rmw/CMakeLists.txt +++ b/rmw/CMakeLists.txt @@ -32,6 +32,7 @@ set(rmw_sources "src/message_sequence.c" "src/names_and_types.c" "src/publisher_options.c" + "src/qos_string_conversions.c" "src/sanity_checks.c" "src/security_options.c" "src/subscription_options.c" diff --git a/rmw/include/rmw/qos_string_conversions.h b/rmw/include/rmw/qos_string_conversions.h new file mode 100644 index 00000000..78b71033 --- /dev/null +++ b/rmw/include/rmw/qos_string_conversions.h @@ -0,0 +1,128 @@ +// Copyright 2020 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef RMW__QOS_STRING_CONVERSIONS_H_ +#define RMW__QOS_STRING_CONVERSIONS_H_ + +#include "rmw/types.h" +#include "rmw/visibility_control.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/// Return a string representing the policy value. +/** + * Returns `NULL` when `value` is `RMW_QOS_POLICY_*_UNKNOWN` or an undefined enum value. + * + * The stringified version of the policy value can be obtained doing the follwing conversion: + * RMW_QOS_POLICY__ -> lower_case() + * + * For example, the strigified version of `RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC` is + * "manual_by_topic" and `RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT` is `best_effort`. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | Yes + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] value qos policy value to be stringified. + * \return a null terminated string representing the policy value, or + * \return `NULL` if value is `RMW_QOS_POLICY_*_UNKNOWN` or an undefined enum value. + */ +RMW_PUBLIC +const char * +rmw_qos_durability_policy_to_str(enum rmw_qos_durability_policy_t value); + +/// Return a string representing the policy value. +/** + * See \ref rmw_qos_durability_policy_to_str() for more details. + */ +RMW_PUBLIC +const char * +rmw_qos_history_policy_to_str(enum rmw_qos_history_policy_t value); + +/// Return a string representing the policy value. +/** + * See \ref rmw_qos_durability_policy_to_str() for more details. + */ +RMW_PUBLIC +const char * +rmw_qos_liveliness_policy_to_str(enum rmw_qos_liveliness_policy_t value); + +/// Return a string representing the policy value. +/** + * See \ref rmw_qos_durability_policy_to_str() for more details. + */ +RMW_PUBLIC +const char * +rmw_qos_reliability_policy_to_str(enum rmw_qos_reliability_policy_t value); + +/// Return a enum value based on the provided string. +/** + * Returns the enum value based on the provided string, or + * `RMW_QOS_POLICY_*_UNKNOWN` when the provided string is unexpected. + * + * How policy values are stringified is explained in \ref rmw_qos_durability_policy_to_str. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | Yes + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] str string identifying a qos policy value. + * \return the policy value represented by the string, or + * \return `RMW_QOS_POLICY_*_UNKNOWN` if the string doesn't represent any value. + */ +RMW_PUBLIC +enum rmw_qos_durability_policy_t +rmw_qos_durability_policy_from_str(const char * str); + +/// Return a enum value based on the provided string. +/** + * See \ref rmw_qos_durability_policy_from_str() for more details. + */ +RMW_PUBLIC +enum rmw_qos_history_policy_t +rmw_qos_history_policy_from_str(const char * str); + +/// Return a enum value based on the provided string. +/** + * See \ref rmw_qos_durability_policy_from_str() for more details. + */ +RMW_PUBLIC +enum rmw_qos_liveliness_policy_t +rmw_qos_liveliness_policy_from_str(const char * str); + + +/// Return a enum value based on the provided string. +/** + * See \ref rmw_qos_durability_policy_from_str() for more details. + */ +RMW_PUBLIC +enum rmw_qos_reliability_policy_t +rmw_qos_reliability_policy_from_str(const char * str); + +#ifdef __cplusplus +} +#endif + +#endif // RMW__QOS_STRING_CONVERSIONS_H_ diff --git a/rmw/src/qos_string_conversions.c b/rmw/src/qos_string_conversions.c new file mode 100644 index 00000000..7d67b9b0 --- /dev/null +++ b/rmw/src/qos_string_conversions.c @@ -0,0 +1,139 @@ +// Copyright 2020 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "rmw/qos_string_conversions.h" + +const char * +rmw_qos_durability_policy_to_str(enum rmw_qos_durability_policy_t value) +{ + switch (value) { + case RMW_QOS_POLICY_DURABILITY_SYSTEM_DEFAULT: + return "system_default"; + case RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL: + return "transient_local"; + case RMW_QOS_POLICY_DURABILITY_VOLATILE: + return "volatile"; + case RMW_QOS_POLICY_DURABILITY_UNKNOWN: // fallthrough + default: + return NULL; + } +} + +const char * +rmw_qos_history_policy_to_str(enum rmw_qos_history_policy_t value) +{ + switch (value) { + case RMW_QOS_POLICY_HISTORY_SYSTEM_DEFAULT: + return "system_default"; + case RMW_QOS_POLICY_HISTORY_KEEP_LAST: + return "keep_last"; + case RMW_QOS_POLICY_HISTORY_KEEP_ALL: + return "keep_all"; + case RMW_QOS_POLICY_HISTORY_UNKNOWN: // fallthrough + default: + return NULL; + } +} + +const char * +rmw_qos_liveliness_policy_to_str(enum rmw_qos_liveliness_policy_t value) +{ + switch (value) { + case RMW_QOS_POLICY_LIVELINESS_SYSTEM_DEFAULT: + return "system_default"; + case RMW_QOS_POLICY_LIVELINESS_AUTOMATIC: + return "automatic"; + case RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC: + return "manual_by_topic"; + case RMW_QOS_POLICY_LIVELINESS_UNKNOWN: // fallthrough + default: + return NULL; + } +} + +const char * +rmw_qos_reliability_policy_to_str(enum rmw_qos_reliability_policy_t value) +{ + switch (value) { + case RMW_QOS_POLICY_RELIABILITY_SYSTEM_DEFAULT: + return "system_default"; + case RMW_QOS_POLICY_RELIABILITY_RELIABLE: + return "reliable"; + case RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT: + return "best_effort"; + case RMW_QOS_POLICY_RELIABILITY_UNKNOWN: // fallthrough + default: + return NULL; + } +} + +enum rmw_qos_durability_policy_t +rmw_qos_durability_policy_from_str(const char * str) +{ + if (0 == strcmp("system_default", str)) { + return RMW_QOS_POLICY_DURABILITY_SYSTEM_DEFAULT; + } + if (0 == strcmp("transient_local", str)) { + return RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL; + } + if (0 == strcmp("volatile", str)) { + return RMW_QOS_POLICY_DURABILITY_VOLATILE; + } + return RMW_QOS_POLICY_DURABILITY_UNKNOWN; +} + +enum rmw_qos_history_policy_t +rmw_qos_history_policy_from_str(const char * str) +{ + if (0 == strcmp("system_default", str)) { + return RMW_QOS_POLICY_HISTORY_SYSTEM_DEFAULT; + } + if (0 == strcmp("keep_last", str)) { + return RMW_QOS_POLICY_HISTORY_KEEP_LAST; + } + if (0 == strcmp("keep_all", str)) { + return RMW_QOS_POLICY_HISTORY_KEEP_ALL; + } + return RMW_QOS_POLICY_HISTORY_UNKNOWN; +} + +enum rmw_qos_liveliness_policy_t +rmw_qos_liveliness_policy_from_str(const char * str) +{ + if (0 == strcmp("system_default", str)) { + return RMW_QOS_POLICY_LIVELINESS_SYSTEM_DEFAULT; + } + if (0 == strcmp("automatic", str)) { + return RMW_QOS_POLICY_LIVELINESS_AUTOMATIC; + } + if (0 == strcmp("manual_by_topic", str)) { + return RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC; + } + return RMW_QOS_POLICY_LIVELINESS_UNKNOWN; +} + +enum rmw_qos_reliability_policy_t +rmw_qos_reliability_policy_from_str(const char * str) +{ + if (0 == strcmp("system_default", str)) { + return RMW_QOS_POLICY_RELIABILITY_SYSTEM_DEFAULT; + } + if (0 == strcmp("reliable", str)) { + return RMW_QOS_POLICY_RELIABILITY_RELIABLE; + } + if (0 == strcmp("best_effort", str)) { + return RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT; + } + return RMW_QOS_POLICY_RELIABILITY_UNKNOWN; +} diff --git a/rmw/test/CMakeLists.txt b/rmw/test/CMakeLists.txt index f34824c1..cea827e8 100644 --- a/rmw/test/CMakeLists.txt +++ b/rmw/test/CMakeLists.txt @@ -75,6 +75,15 @@ if(TARGET test_publisher_options) target_link_libraries(test_publisher_options ${PROJECT_NAME}) endif() +ament_add_gtest(test_qos_string_conversions +test_qos_string_conversions.cpp + # Append the directory of librmw so it is found at test time. + APPEND_LIBRARY_DIRS "$" +) +if(TARGET test_qos_string_conversions) + target_link_libraries(test_qos_string_conversions ${PROJECT_NAME}) +endif() + ament_add_gmock(test_sanity_checks test_sanity_checks.cpp # Append the directory of librmw so it is found at test time. diff --git a/rmw/test/test_qos_string_conversions.cpp b/rmw/test/test_qos_string_conversions.cpp new file mode 100644 index 00000000..a024c4d9 --- /dev/null +++ b/rmw/test/test_qos_string_conversions.cpp @@ -0,0 +1,55 @@ +// Copyright 2020 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "rmw/qos_string_conversions.h" +#include "rmw/types.h" + +// Converts to string and back to the policy value, check that it's the same +#define TEST_QOS_POLICY_VALUE_STRINGIFY(kind, value) \ + do { \ + EXPECT_EQ( \ + value, rmw_qos_ ## kind ## _policy_from_str(rmw_qos_ ## kind ## _policy_to_str(value))); \ + } while (0) + +// Check unrecognized string as input of from_str, check UNKNOWN as input of to_str. +#define TEST_QOS_POLICY_STRINGIFY_CORNER_CASES(kind, kind_upper) \ + do { \ + EXPECT_EQ( \ + NULL, rmw_qos_ ## kind ## _policy_to_str(RMW_QOS_POLICY_ ## kind_upper ## _UNKNOWN)); \ + EXPECT_EQ( \ + RMW_QOS_POLICY_ ## kind_upper ## _UNKNOWN, \ + rmw_qos_ ## kind ## _policy_from_str("this could never be a stringified policy value")); \ + } while (0) + +TEST(test_qos_policy_stringify, test_normal_use) { + TEST_QOS_POLICY_VALUE_STRINGIFY(durability, RMW_QOS_POLICY_DURABILITY_SYSTEM_DEFAULT); + TEST_QOS_POLICY_VALUE_STRINGIFY(durability, RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL); + TEST_QOS_POLICY_VALUE_STRINGIFY(durability, RMW_QOS_POLICY_DURABILITY_VOLATILE); + TEST_QOS_POLICY_VALUE_STRINGIFY(history, RMW_QOS_POLICY_HISTORY_KEEP_LAST); + TEST_QOS_POLICY_VALUE_STRINGIFY(history, RMW_QOS_POLICY_HISTORY_KEEP_ALL); + TEST_QOS_POLICY_VALUE_STRINGIFY(history, RMW_QOS_POLICY_HISTORY_SYSTEM_DEFAULT); + TEST_QOS_POLICY_VALUE_STRINGIFY(liveliness, RMW_QOS_POLICY_LIVELINESS_AUTOMATIC); + TEST_QOS_POLICY_VALUE_STRINGIFY(liveliness, RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC); + TEST_QOS_POLICY_VALUE_STRINGIFY(liveliness, RMW_QOS_POLICY_LIVELINESS_SYSTEM_DEFAULT); + TEST_QOS_POLICY_VALUE_STRINGIFY(reliability, RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT); + TEST_QOS_POLICY_VALUE_STRINGIFY(reliability, RMW_QOS_POLICY_RELIABILITY_RELIABLE); + TEST_QOS_POLICY_VALUE_STRINGIFY(reliability, RMW_QOS_POLICY_RELIABILITY_SYSTEM_DEFAULT); + + TEST_QOS_POLICY_STRINGIFY_CORNER_CASES(durability, DURABILITY); + TEST_QOS_POLICY_STRINGIFY_CORNER_CASES(history, HISTORY); + TEST_QOS_POLICY_STRINGIFY_CORNER_CASES(liveliness, LIVELINESS); + TEST_QOS_POLICY_STRINGIFY_CORNER_CASES(reliability, RELIABILITY); +} From 327a99b19d7c69303c8e041c7d39500d17443c32 Mon Sep 17 00:00:00 2001 From: Ivan Santiago Paunovic Date: Mon, 19 Oct 2020 13:45:38 -0300 Subject: [PATCH 2/4] typo Signed-off-by: Ivan Santiago Paunovic Co-authored-by: Jacob Perron --- rmw/include/rmw/qos_string_conversions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rmw/include/rmw/qos_string_conversions.h b/rmw/include/rmw/qos_string_conversions.h index 78b71033..eb004a0b 100644 --- a/rmw/include/rmw/qos_string_conversions.h +++ b/rmw/include/rmw/qos_string_conversions.h @@ -30,7 +30,7 @@ extern "C" * The stringified version of the policy value can be obtained doing the follwing conversion: * RMW_QOS_POLICY__ -> lower_case() * - * For example, the strigified version of `RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC` is + * For example, the stringified version of `RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC` is * "manual_by_topic" and `RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT` is `best_effort`. * *
From 1d1da7794cec7b8313a7dce247892ffdcca8dc63 Mon Sep 17 00:00:00 2001 From: Ivan Santiago Paunovic Date: Mon, 19 Oct 2020 13:45:50 -0300 Subject: [PATCH 3/4] style Signed-off-by: Ivan Santiago Paunovic Co-authored-by: Jacob Perron --- rmw/include/rmw/qos_string_conversions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rmw/include/rmw/qos_string_conversions.h b/rmw/include/rmw/qos_string_conversions.h index eb004a0b..27d14dfa 100644 --- a/rmw/include/rmw/qos_string_conversions.h +++ b/rmw/include/rmw/qos_string_conversions.h @@ -31,7 +31,7 @@ extern "C" * RMW_QOS_POLICY__ -> lower_case() * * For example, the stringified version of `RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC` is - * "manual_by_topic" and `RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT` is `best_effort`. + * "manual_by_topic" and `RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT` is "best_effort". * *
* Attribute | Adherence From 27c95b6e33ea766f4245fc9b04ac91045991875a Mon Sep 17 00:00:00 2001 From: Ivan Santiago Paunovic Date: Mon, 19 Oct 2020 13:52:40 -0300 Subject: [PATCH 4/4] Use strncmp Signed-off-by: Ivan Santiago Paunovic --- rmw/src/qos_string_conversions.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/rmw/src/qos_string_conversions.c b/rmw/src/qos_string_conversions.c index 7d67b9b0..8a8f0942 100644 --- a/rmw/src/qos_string_conversions.c +++ b/rmw/src/qos_string_conversions.c @@ -78,16 +78,19 @@ rmw_qos_reliability_policy_to_str(enum rmw_qos_reliability_policy_t value) } } +#define RMW_QOS_STREQ_WITH_LITERAL(string_literal, string) \ + (0 == strncmp(string_literal, str, sizeof(string_literal))) + enum rmw_qos_durability_policy_t rmw_qos_durability_policy_from_str(const char * str) { - if (0 == strcmp("system_default", str)) { + if (RMW_QOS_STREQ_WITH_LITERAL("system_default", str)) { return RMW_QOS_POLICY_DURABILITY_SYSTEM_DEFAULT; } - if (0 == strcmp("transient_local", str)) { + if (RMW_QOS_STREQ_WITH_LITERAL("transient_local", str)) { return RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL; } - if (0 == strcmp("volatile", str)) { + if (RMW_QOS_STREQ_WITH_LITERAL("volatile", str)) { return RMW_QOS_POLICY_DURABILITY_VOLATILE; } return RMW_QOS_POLICY_DURABILITY_UNKNOWN; @@ -96,13 +99,13 @@ rmw_qos_durability_policy_from_str(const char * str) enum rmw_qos_history_policy_t rmw_qos_history_policy_from_str(const char * str) { - if (0 == strcmp("system_default", str)) { + if (RMW_QOS_STREQ_WITH_LITERAL("system_default", str)) { return RMW_QOS_POLICY_HISTORY_SYSTEM_DEFAULT; } - if (0 == strcmp("keep_last", str)) { + if (RMW_QOS_STREQ_WITH_LITERAL("keep_last", str)) { return RMW_QOS_POLICY_HISTORY_KEEP_LAST; } - if (0 == strcmp("keep_all", str)) { + if (RMW_QOS_STREQ_WITH_LITERAL("keep_all", str)) { return RMW_QOS_POLICY_HISTORY_KEEP_ALL; } return RMW_QOS_POLICY_HISTORY_UNKNOWN; @@ -111,13 +114,13 @@ rmw_qos_history_policy_from_str(const char * str) enum rmw_qos_liveliness_policy_t rmw_qos_liveliness_policy_from_str(const char * str) { - if (0 == strcmp("system_default", str)) { + if (RMW_QOS_STREQ_WITH_LITERAL("system_default", str)) { return RMW_QOS_POLICY_LIVELINESS_SYSTEM_DEFAULT; } - if (0 == strcmp("automatic", str)) { + if (RMW_QOS_STREQ_WITH_LITERAL("automatic", str)) { return RMW_QOS_POLICY_LIVELINESS_AUTOMATIC; } - if (0 == strcmp("manual_by_topic", str)) { + if (RMW_QOS_STREQ_WITH_LITERAL("manual_by_topic", str)) { return RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC; } return RMW_QOS_POLICY_LIVELINESS_UNKNOWN; @@ -126,13 +129,13 @@ rmw_qos_liveliness_policy_from_str(const char * str) enum rmw_qos_reliability_policy_t rmw_qos_reliability_policy_from_str(const char * str) { - if (0 == strcmp("system_default", str)) { + if (RMW_QOS_STREQ_WITH_LITERAL("system_default", str)) { return RMW_QOS_POLICY_RELIABILITY_SYSTEM_DEFAULT; } - if (0 == strcmp("reliable", str)) { + if (RMW_QOS_STREQ_WITH_LITERAL("reliable", str)) { return RMW_QOS_POLICY_RELIABILITY_RELIABLE; } - if (0 == strcmp("best_effort", str)) { + if (RMW_QOS_STREQ_WITH_LITERAL("best_effort", str)) { return RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT; } return RMW_QOS_POLICY_RELIABILITY_UNKNOWN;