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:50 UTC

[celix] branch feature/stringview_support_for_properties created (now 63f13c5)

This is an automated email from the ASF dual-hosted git repository.

pnoltes pushed a change to branch feature/stringview_support_for_properties
in repository https://gitbox.apache.org/repos/asf/celix.git.


      at 63f13c5  Updates C++ properties to support string_view if C++17 is used.

This branch includes the following new commits:

     new 63f13c5  Updates C++ properties to support string_view if C++17 is used.

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


[celix] 01/01: Updates C++ properties to support string_view if C++17 is used.

Posted by pn...@apache.org.
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.