You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2021/11/28 16:22:51 UTC
[celix] 01/01: Updates C++ properties to support string_view if C++17 is used.
This is an automated email from the ASF dual-hosted git repository.
pnoltes pushed a commit to branch feature/stringview_support_for_properties
in repository https://gitbox.apache.org/repos/asf/celix.git
commit 63f13c5491fe37f79002d7a6b65a1ae2ae070af4
Author: Pepijn Noltes <pn...@apache.org>
AuthorDate: Sun Nov 28 17:01:07 2021 +0100
Updates C++ properties to support string_view if C++17 is used.
---
libs/utils/gtest/CMakeLists.txt | 13 ++-
libs/utils/gtest/src/CxxPropertiesTestSuite.cc | 59 +++++++++++-
libs/utils/include/celix/Properties.h | 123 ++++++++++++++++++++++++-
3 files changed, 189 insertions(+), 6 deletions(-)
diff --git a/libs/utils/gtest/CMakeLists.txt b/libs/utils/gtest/CMakeLists.txt
index 6cb860d..0802214 100644
--- a/libs/utils/gtest/CMakeLists.txt
+++ b/libs/utils/gtest/CMakeLists.txt
@@ -54,7 +54,7 @@ target_compile_definitions(test_utils PRIVATE -DTEST_ZIP_LOCATION=\"${TEST_ZIP_F
target_compile_definitions(test_utils PRIVATE -DTEST_A_FILE_LOCATION=\"${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt\")
target_compile_definitions(test_utils PRIVATE -DTEST_A_DIR_LOCATION=\"${CMAKE_CURRENT_SOURCE_DIR}\")
-####### linkig zip against test executable to text extract zip from data ###############################################
+####### linking zip against test executable to text extract zip from data ###############################################
if (UNIX AND NOT APPLE)
target_link_libraries(test_utils PRIVATE -Wl,--format=binary -Wl,"test.zip" -Wl,--format=default)
else ()
@@ -64,3 +64,14 @@ endif ()
add_test(NAME test_utils COMMAND test_utils)
setup_target_for_coverage(test_utils SCAN_DIR ..)
+
+#Setting standard to C++11 and testing C++ Properties to ensure that this still support C++11.
+#Note that celix Properties are used in the C++11 dependency manager and this be backwards compatible with Celix 2.2.1
+set(CMAKE_CXX_STANDARD 11)
+add_executable(test_properties_with_cxx11
+ src/CxxPropertiesTestSuite.cc
+)
+target_link_libraries(test_properties_with_cxx11 PRIVATE Celix::utils GTest::gtest GTest::gtest_main)
+add_test(NAME test_properties_with_cxx11 COMMAND test_properties_with_cxx11)
+setup_target_for_coverage(test_properties_with_cxx11 SCAN_DIR ..)
+
diff --git a/libs/utils/gtest/src/CxxPropertiesTestSuite.cc b/libs/utils/gtest/src/CxxPropertiesTestSuite.cc
index 8f151e4..060562b 100644
--- a/libs/utils/gtest/src/CxxPropertiesTestSuite.cc
+++ b/libs/utils/gtest/src/CxxPropertiesTestSuite.cc
@@ -87,4 +87,61 @@ TEST_F(CxxPropertiesTestSuite, testWrap) {
EXPECT_EQ(1, celix_properties_size(props));
celix_properties_destroy(props);
-}
\ No newline at end of file
+}
+
+#if __cplusplus >= 201703L //C++17 or higher
+TEST_F(CxxPropertiesTestSuite, testStringView) {
+ constexpr std::string_view stringViewKey = "KEY1";
+ constexpr std::string_view stringViewValue = "VALUE1";
+ std::string stringKey{"KEY2"};
+ std::string stringValue{"VALUE2"};
+ const char* charKey = "KEY3";
+ const char* charValue = "VALUE3";
+
+ {
+ //rule: I can create properties with initializer_list using std::string, const char* and string_view
+ celix::Properties props {
+ {charKey, charValue},
+ {stringKey, stringValue},
+ {stringViewKey, stringViewValue}
+ };
+ EXPECT_EQ(props.size(), 3);
+
+ //rule: I can use the subscript operator using string_view objects
+ constexpr std::string_view k = "KEY2";
+ constexpr std::string_view v = "VALUE_NEW";
+ std::string check = props[k];
+ EXPECT_EQ(check, "VALUE2");
+ props[k] = v;
+ check = props[k];
+ EXPECT_EQ(check, v);
+ }
+
+ {
+ //rule: I can use set/get with string_view
+ constexpr std::string_view key = "TEST_KEY";
+ constexpr std::string_view value = "TEST_VALUE";
+
+ celix::Properties props{};
+
+ props.set(key, value);
+ EXPECT_EQ(value, props.get(key));
+ props[key] = value;
+ EXPECT_EQ(value, props.get(key));
+ EXPECT_EQ(1, props.size());
+
+ props.set(key, std::string{"string value"});
+ EXPECT_EQ("string value", props.get(key));
+ props.set(key, "string value");
+ EXPECT_EQ("string value", props.get(key));
+ EXPECT_EQ(1, props.size());
+
+ props.set(key, 1L); //long
+ EXPECT_EQ(1L, props.getAsLong(key, -1));
+ props.set(key, 1.0); //double
+ EXPECT_EQ(1.0, props.getAsDouble(key, -1));
+ props.set(key, true); //bool
+ EXPECT_EQ(true, props.getAsBool(key, false));
+ }
+}
+#endif
diff --git a/libs/utils/include/celix/Properties.h b/libs/utils/include/celix/Properties.h
index 7698e77..0d00cd2 100644
--- a/libs/utils/include/celix/Properties.h
+++ b/libs/utils/include/celix/Properties.h
@@ -103,14 +103,36 @@ namespace celix {
class ValueRef {
public:
- ValueRef(std::shared_ptr<celix_properties_t> _props, std::string _key) : props{std::move(_props)}, key{std::move(_key)} {}
+ ValueRef(std::shared_ptr<celix_properties_t> _props, std::string _key) : props{std::move(_props)}, stringKey{std::move(_key)}, charKey{nullptr} {}
+
+ ValueRef(std::shared_ptr<celix_properties_t> _props, const char* _key) : props{std::move(_props)}, stringKey{}, charKey{_key} {}
+
+#if __cplusplus >= 201703L //C++17 or higher
+ ValueRef& operator=(std::string_view value) {
+ if (charKey == nullptr) {
+ celix_properties_set(props.get(), stringKey.c_str(), value.data());
+ } else {
+ celix_properties_set(props.get(), charKey, value.data());
+ }
+ return *this;
+ }
+#else
ValueRef& operator=(const std::string& value) {
- celix_properties_set(props.get(), key.c_str(), value.c_str());
+ if (charKey == nullptr) {
+ celix_properties_set(props.get(), stringKey.c_str(), value.c_str());
+ } else {
+ celix_properties_set(props.get(), charKey, value.c_str());
+ }
return *this;
}
+#endif
[[nodiscard]] const char* getValue() const {
- return celix_properties_get(props.get(), key.c_str(), nullptr);
+ if (charKey == nullptr) {
+ return celix_properties_get(props.get(), stringKey.c_str(), nullptr);
+ } else {
+ return celix_properties_get(props.get(), charKey, nullptr);
+ }
}
operator std::string() const {
@@ -119,7 +141,8 @@ namespace celix {
}
private:
std::shared_ptr<celix_properties_t> props;
- std::string key;
+ std::string stringKey;
+ const char* charKey;
};
@@ -138,11 +161,19 @@ namespace celix {
Properties(const Properties& rhs) :
cProps{celix_properties_copy(rhs.cProps.get()), [](celix_properties_t* p) { celix_properties_destroy(p); }} {}
+#if __cplusplus >= 201703L //C++17 or higher
+ Properties(std::initializer_list<std::pair<std::string_view, std::string_view>> list) : cProps{celix_properties_create(), [](celix_properties_t* p) { celix_properties_destroy(p); }} {
+ for(auto &entry : list) {
+ celix_properties_set(cProps.get(), entry.first.data(), entry.second.data());
+ }
+ }
+#else
Properties(std::initializer_list<std::pair<std::string, std::string>> list) : cProps{celix_properties_create(), [](celix_properties_t* p) { celix_properties_destroy(p); }} {
for(auto &entry : list) {
celix_properties_set(cProps.get(), entry.first.c_str(), entry.second.c_str());
}
}
+#endif
/**
* @brief Wraps C properties, but does not take ownership -> dtor will not destroy properties
@@ -162,6 +193,21 @@ namespace celix {
return cProps.get();
}
+#if __cplusplus >= 201703L //C++17 or higher
+ /**
+ * @brief Get the value for a property key
+ */
+ ValueRef operator[](std::string_view key) {
+ return ValueRef{cProps, key.data()};
+ }
+
+ /**
+ * @brief Get the value for a property key
+ */
+ ValueRef operator[](std::string_view key) const {
+ return ValueRef{cProps, key.data()};
+ }
+#else
/**
* @brief Get the value for a property key
*/
@@ -175,6 +221,7 @@ namespace celix {
ValueRef operator[](std::string key) const {
return ValueRef{cProps, std::move(key)};
}
+#endif
/**
* @brief begin iterator
@@ -208,6 +255,73 @@ namespace celix {
return iter;
}
+#if __cplusplus >= 201703L //C++17 or higher
+ /**
+ * @brief Get the value for a property key or return the defaultValue if the key does not exists.
+ */
+ [[nodiscard]] std::string get(std::string_view key, std::string_view defaultValue = {}) const {
+ const char* found = celix_properties_get(cProps.get(), key.data(), nullptr);
+ return found == nullptr ? std::string{defaultValue} : std::string{found};
+ }
+
+ /**
+ * @brief Get the value as long for a property key or return the defaultValue if the key does not exists.
+ */
+ [[nodiscard]] long getAsLong(std::string_view key, long defaultValue) const {
+ return celix_properties_getAsLong(cProps.get(), key.data(), defaultValue);
+ }
+
+ /**
+ * @brief Get the value as double for a property key or return the defaultValue if the key does not exists.
+ */
+ [[nodiscard]] double getAsDouble(std::string_view key, double defaultValue) const {
+ return celix_properties_getAsDouble(cProps.get(), key.data(), defaultValue);
+ }
+
+ /**
+ * @brief Get the value as bool for a property key or return the defaultValue if the key does not exists.
+ */
+ [[nodiscard]] bool getAsBool(std::string_view key, bool defaultValue) const {
+ return celix_properties_getAsBool(cProps.get(), key.data(), defaultValue);
+ }
+
+ /**
+ * @brief Sets a property
+ */
+ void set(std::string_view key, std::string_view value) {
+ celix_properties_set(cProps.get(), key.data(), value.data());
+ }
+
+ /**
+ * @brief Sets a property
+ */
+ void set(std::string_view key, std::string value) {
+ celix_properties_set(cProps.get(), key.data(), value.data());
+ }
+
+ /**
+ * @brief Sets a property
+ */
+ void set(std::string_view key, const char* value) {
+ celix_properties_set(cProps.get(), key.data(), value);
+ }
+
+ /**
+ * @brief Sets a bool property
+ */
+ void set(std::string_view key, bool value) {
+ celix_properties_setBool(cProps.get(), key.data(), value);
+ }
+
+ /**
+ * @brief Sets a T property. Will use std::to_string to convert the value to string.
+ */
+ template<typename T>
+ void set(std::string_view key, T value) {
+ using namespace std;
+ celix_properties_set(cProps.get(), key.data(), to_string(value).c_str());
+ }
+#else
/**
* @brief Get the value for a property key or return the defaultValue if the key does not exists.
*/
@@ -266,6 +380,7 @@ namespace celix {
using namespace std;
celix_properties_set(cProps.get(), key.c_str(), to_string(value).c_str());
}
+#endif
/**
* @brief Returns the nr of properties.