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

pnoltes pushed a commit to branch feature/674-improve-properties
in repository https://gitbox.apache.org/repos/asf/celix.git


The following commit(s) were added to refs/heads/feature/674-improve-properties 
by this push:
     new 5963dbc9 Update C++ Properties for vector support
5963dbc9 is described below

commit 5963dbc9fd54694f87a19ff0d842dccf7d0b0d48
Author: Pepijn Noltes <[email protected]>
AuthorDate: Mon Jan 8 23:33:15 2024 +0100

    Update C++ Properties for vector support
---
 libs/utils/gtest/src/CxxPropertiesTestSuite.cc     | 120 +++++++++
 .../gtest/src/PropertiesErrorInjectionTestSuite.cc |   2 +-
 libs/utils/include/celix/Properties.h              | 269 +++++++++++++++++++--
 libs/utils/include/celix_properties.h              |   6 +-
 libs/utils/src/properties.c                        |  32 +--
 5 files changed, 390 insertions(+), 39 deletions(-)

diff --git a/libs/utils/gtest/src/CxxPropertiesTestSuite.cc 
b/libs/utils/gtest/src/CxxPropertiesTestSuite.cc
index f041a187..ea910f95 100644
--- a/libs/utils/gtest/src/CxxPropertiesTestSuite.cc
+++ b/libs/utils/gtest/src/CxxPropertiesTestSuite.cc
@@ -185,6 +185,125 @@ TEST_F(CxxPropertiesTestSuite, GetAsVersionTest) {
     EXPECT_EQ(props.getAsVersion("key", celix::Version{4, 5, 6}), ver);
 }
 
+
+TEST_F(CxxPropertiesTestSuite, GetTest) {
+    celix::Properties props{};
+
+    props.set("key1", "value1"); //string
+    props.set("key2", 2); //long
+    props.set("key3", 3.3); //double
+    props.set("key4", true); //bool
+    props.set("key5", celix::Version{1, 2, 3}); //version
+
+    //Test get with valid key
+    EXPECT_EQ(props.get("key1"), "value1");
+    EXPECT_EQ(props.getAsLong("key2", -1), 2);
+    EXPECT_EQ(props.getAsDouble("key3", -1), 3.3);
+    EXPECT_EQ(props.getAsBool("key4", false), true);
+    celix::Version checkVersion{1, 2, 3};
+    EXPECT_EQ(props.getAsVersion("key5", celix::Version{1, 2, 4}), 
checkVersion);
+
+    // Test get with invalid key and default value
+    EXPECT_EQ(props.get("non_existent_key", "default_value"), "default_value");
+    EXPECT_EQ(props.getLong("non_existent_key", 1), 1);
+    EXPECT_EQ(props.getDouble("non_existent_key", 1.1), 1.1);
+    EXPECT_EQ(props.getBool("non_existent_key", true), true);
+    celix::Version checkVersion2{1, 2, 4};
+    EXPECT_EQ(props.getVersion("non_existent_key", checkVersion2), 
checkVersion2);
+
+    // Test get with an existing key, but invalid type and default value
+    EXPECT_EQ(props.get("key5", "default_value"), "1.2.3"); // Note get always 
returns the string value or string
+                                                            // representation 
of the value (in this case the version)
+    EXPECT_EQ(props.getLong("key1", 1), 1); //key1 is a string
+    EXPECT_EQ(props.getDouble("key1", 1.1), 1.1); //key1 is a string
+    EXPECT_EQ(props.getBool("key1", true), true); //key1 is a string
+    EXPECT_EQ(props.getVersion("key1", checkVersion2), checkVersion2); //key1 
is a string
+}
+
+TEST_F(CxxPropertiesTestSuite, ArrayListTest) {
+    celix::Properties props{};
+    EXPECT_EQ(0, props.size());
+
+    // Test set
+    props.setStrings("key1", {"value1", "value2"});
+    props.setLongs("key2", {1, 2});
+    props.setDoubles("key3", {1.1, 2.2});
+    props.setBooleans("key4", {true, false});
+    props.setVersions("key5", {celix::Version{1, 2, 3}, celix::Version{2, 3, 
4}});
+    EXPECT_EQ(5, props.size());
+
+    // Test getAs with valid key
+    auto strings = props.getAsStringVector("key1");
+    EXPECT_EQ(strings.size(), 2);
+    EXPECT_EQ(strings[0], "value1");
+    auto longs = props.getAsLongVector("key2");
+    EXPECT_EQ(longs.size(), 2);
+    EXPECT_EQ(longs[0], 1);
+    auto doubles = props.getAsDoubleVector("key3");
+    EXPECT_EQ(doubles.size(), 2);
+    EXPECT_EQ(doubles[0], 1.1);
+    auto booleans = props.getAsBoolVector("key4");
+    EXPECT_EQ(booleans.size(), 2);
+    EXPECT_EQ(booleans[0], true);
+    auto versions = props.getAsVersionVector("key5");
+    EXPECT_EQ(versions.size(), 2);
+    celix::Version checkVersion{1, 2, 3};
+    EXPECT_EQ(versions[0], checkVersion);
+
+    // Test getAs with invalid key and default value
+    strings = props.getAsStringVector("non_existent_key", {"default_value"});
+    EXPECT_EQ(strings.size(), 1);
+    EXPECT_EQ(strings[0], "default_value");
+    longs = props.getAsLongVector("non_existent_key", {1});
+    EXPECT_EQ(longs.size(), 1);
+    EXPECT_EQ(longs[0], 1);
+    doubles = props.getAsDoubleVector("non_existent_key", {1.1});
+    EXPECT_EQ(doubles.size(), 1);
+    EXPECT_EQ(doubles[0], 1.1);
+    booleans = props.getAsBoolVector("non_existent_key", {true});
+    EXPECT_EQ(booleans.size(), 1);
+    EXPECT_EQ(booleans[0], true);
+    versions = props.getAsVersionVector("non_existent_key", {celix::Version{1, 
2, 3}});
+    EXPECT_EQ(versions.size(), 1);
+    EXPECT_EQ(versions[0], checkVersion);
+
+
+    // Test get with a valid key
+    strings = props.getStringVector("key1");
+    EXPECT_EQ(strings.size(), 2);
+    EXPECT_EQ(strings[1], "value2");
+    longs = props.getLongVector("key2");
+    EXPECT_EQ(longs.size(), 2);
+    EXPECT_EQ(longs[1], 2);
+    doubles = props.getDoubleVector("key3");
+    EXPECT_EQ(doubles.size(), 2);
+    EXPECT_EQ(doubles[1], 2.2);
+    booleans = props.getBoolVector("key4");
+    EXPECT_EQ(booleans.size(), 2);
+    EXPECT_EQ(booleans[1], false);
+    versions = props.getVersionVector("key5");
+    EXPECT_EQ(versions.size(), 2);
+    celix::Version checkVersion2{2, 3, 4};
+    EXPECT_EQ(versions[1], checkVersion2);
+
+    // Test get with an existing key, but invalid type and default value
+    strings = props.getStringVector("key5", {"default_value"}); //key5 is a 
version
+    EXPECT_EQ(strings.size(), 1);
+    EXPECT_EQ(strings[0], "default_value");
+    longs = props.getLongVector("key1", {1}); //key1 is a string
+    EXPECT_EQ(longs.size(), 1);
+    EXPECT_EQ(longs[0], 1);
+    doubles = props.getDoubleVector("key1", {1.1}); //key1 is a string
+    EXPECT_EQ(doubles.size(), 1);
+    EXPECT_EQ(doubles[0], 1.1);
+    booleans = props.getBoolVector("key1", {true}); //key1 is a string
+    EXPECT_EQ(booleans.size(), 1);
+    EXPECT_EQ(booleans[0], true);
+    versions = props.getVersionVector("key1", {celix::Version{1, 2, 3}}); 
//key1 is a string
+    EXPECT_EQ(versions.size(), 1);
+    EXPECT_EQ(versions[0], checkVersion);
+}
+
 TEST_F(CxxPropertiesTestSuite, StoreAndLoadTest) {
     std::string path{"cxx_store_and_load_test.properties"};
 
@@ -200,6 +319,7 @@ TEST_F(CxxPropertiesTestSuite, StoreAndLoadTest) {
 
     try {
         loadedProps = celix::Properties::load("non-existence");
+        (void)loadedProps;
         FAIL() << "Expected exception not thrown";
     } catch (const celix::IOException& e) {
         EXPECT_TRUE(strstr(e.what(), "Cannot load celix::Properties"));
diff --git a/libs/utils/gtest/src/PropertiesErrorInjectionTestSuite.cc 
b/libs/utils/gtest/src/PropertiesErrorInjectionTestSuite.cc
index c7fb01ba..b167f7f1 100644
--- a/libs/utils/gtest/src/PropertiesErrorInjectionTestSuite.cc
+++ b/libs/utils/gtest/src/PropertiesErrorInjectionTestSuite.cc
@@ -256,7 +256,7 @@ TEST_F(PropertiesErrorInjectionTestSuite, LoadFailureTest) {
     fclose(memStream);
 }
 
-TEST_F(PropertiesErrorInjectionTestSuite, SetWithoutCopyFailureTest) {
+TEST_F(PropertiesErrorInjectionTestSuite, AssignFailureTest) {
     //Given a filled properties and a key and value
     celix_autoptr(celix_properties_t) props = celix_properties_create();
     fillOptimizationCache(props);
diff --git a/libs/utils/include/celix/Properties.h 
b/libs/utils/include/celix/Properties.h
index 6f29e9e0..47a3ffdc 100644
--- a/libs/utils/include/celix/Properties.h
+++ b/libs/utils/include/celix/Properties.h
@@ -25,6 +25,7 @@
 #include <memory>
 #include <string>
 #include <type_traits>
+#include <vector>
 
 #include "celix_properties.h"
 #include "celix_utils.h"
@@ -121,20 +122,24 @@ namespace celix {
     public:
         using const_iterator = ConstPropertiesIterator; //note currently only 
a const iterator is supported.
 
-        /**
-         * @brief Enum representing the possible types of a property value.
-         */
-        enum class ValueType {
-            Unset,    /**< Property value is not set. */
-            String,   /**< Property value is a string. */
-            Long,     /**< Property value is a long integer. */
-            Double,   /**< Property value is a double. */
-            Bool,     /**< Property value is a boolean. */
-            Version   /**< Property value is a Celix version. */
-        };
-
-
-        class ValueRef {
+      /**
+       * @brief Enum representing the possible types of a property value.
+       */
+      enum class ValueType {
+          Unset,        /**< Property value is not set. */
+          String,       /**< Property value is a string. */
+          Long,         /**< Property value is a long integer. */
+          Double,       /**< Property value is a double. */
+          Bool,         /**< Property value is a boolean. */
+          Version,      /**< Property value is a Celix version. */
+          LongArray,    /**< Property value is an array of long integers. */
+          DoubleArray,  /**< Property value is an array of doubles. */
+          BooleanArray, /**< Property value is an array of booleans. */
+          VersionArray, /**< Property value is an array of Celix versions. */
+          StringArray   /**< Property value is an array of strings. */
+      };
+
+      class ValueRef {
         public:
             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} {}
@@ -304,6 +309,11 @@ namespace celix {
             return celix_properties_getAsLong(cProps.get(), key.c_str(), 
defaultValue);
         }
 
+        // TODO doc
+        long getLong(const std::string& key, long defaultValue) const {
+            return celix_properties_getLong(cProps.get(), key.c_str(), 
defaultValue);
+        }
+
         /**
          * @brief Get the value of the property with key as a double.
          *
@@ -316,6 +326,11 @@ namespace celix {
             return celix_properties_getAsDouble(cProps.get(), key.c_str(), 
defaultValue);
         }
 
+        // TODO doc
+        double getDouble(const std::string& key, double defaultValue) const {
+            return celix_properties_getDouble(cProps.get(), key.c_str(), 
defaultValue);
+        }
+
         /**
          * @brief Get the value of the property with key as a boolean.
          *
@@ -328,6 +343,11 @@ namespace celix {
             return celix_properties_getAsBool(cProps.get(), key.c_str(), 
defaultValue);
         }
 
+        // TODO doc
+        bool getBool(const std::string& key, bool defaultValue) const {
+            return celix_properties_getBool(cProps.get(), key.c_str(), 
defaultValue);
+        }
+
         /**
          * @brief Get the value of the property with key as a Celix version.
          *
@@ -353,6 +373,132 @@ namespace celix {
             return defaultValue;
         }
 
+        // TODO doc
+        celix::Version getVersion(const std::string& key, celix::Version 
defaultValue = {}) const {
+            auto* v = celix_properties_getVersion(cProps.get(), key.c_str(), 
nullptr);
+            if (v) {
+                return celix::Version{celix_version_getMajor(v),
+                                      celix_version_getMinor(v),
+                                      celix_version_getMicro(v),
+                                      celix_version_getQualifier(v)};
+            }
+            return defaultValue;
+        }
+
+        // TODO doc
+        std::vector<long> getAsLongVector(const std::string& key, const 
std::vector<long>& defaultValue = {}) const {
+            celix_autoptr(celix_array_list_t) list;
+            celix_status_t status = 
celix_properties_getAsLongArrayList(cProps.get(), key.c_str(), nullptr, &list);
+            throwIfEnomem(status);
+            return convertToVector<long>(list, defaultValue, 
celix_arrayList_getLong);
+        }
+
+        // TODO doc
+        std::vector<long> getLongVector(const std::string& key, const 
std::vector<long>& defaultValue = {}) const {
+            const auto* list = celix_properties_getLongArrayList(cProps.get(), 
key.c_str(), nullptr);
+            return convertToVector<long>(list, defaultValue, 
celix_arrayList_getLong);
+        }
+
+        // TODO doc
+        std::vector<bool> getAsBoolVector(const std::string& key, const 
std::vector<bool>& defaultValue = {}) const {
+            celix_autoptr(celix_array_list_t) list;
+            celix_status_t status = 
celix_properties_getAsBoolArrayList(cProps.get(), key.c_str(), nullptr, &list);
+            throwIfEnomem(status);
+            return convertToVector<bool>(list, defaultValue, 
celix_arrayList_getBool);
+        }
+
+        // TODO doc
+        std::vector<bool> getBoolVector(const std::string& key, const 
std::vector<bool>& defaultValue = {}) const {
+            const auto* list = celix_properties_getBoolArrayList(cProps.get(), 
key.c_str(), nullptr);
+            return convertToVector<bool>(list, defaultValue, 
celix_arrayList_getBool);
+        }
+
+        // TODO doc
+        std::vector<double> getAsDoubleVector(const std::string& key,
+                                              const std::vector<double>& 
defaultValue = {}) const {
+            celix_autoptr(celix_array_list_t) list;
+            celix_status_t status = 
celix_properties_getAsDoubleArrayList(cProps.get(), key.c_str(), nullptr, 
&list);
+            throwIfEnomem(status);
+            return convertToVector<double>(list, defaultValue, 
celix_arrayList_getDouble);
+        }
+
+        // TODO doc
+        std::vector<double> getDoubleVector(const std::string& key,
+                                            const std::vector<double>& 
defaultValue = {}) const {
+            const auto* list = 
celix_properties_getDoubleArrayList(cProps.get(), key.c_str(), nullptr);
+            return convertToVector<double>(list, defaultValue, 
celix_arrayList_getDouble);
+        }
+
+        // TODO doc
+        std::vector<celix::Version> getAsVersionVector(const std::string& key,
+                                                       const 
std::vector<celix::Version>& defaultValue = {}) const {
+            celix_autoptr(celix_array_list_t) list;
+            celix_status_t status = 
celix_properties_getAsVersionArrayList(cProps.get(), key.c_str(), nullptr, 
&list);
+            throwIfEnomem(status);
+            if (list) {
+                std::vector<celix::Version> result{};
+                for (int i = 0; i < celix_arrayList_size(list); ++i) {
+                    auto* v = 
static_cast<celix_version_t*>(celix_arrayList_get(list, i));
+                    result.emplace_back(celix_version_getMajor(v),
+                                        celix_version_getMinor(v),
+                                        celix_version_getMicro(v),
+                                        celix_version_getQualifier(v));
+                }
+                return result;
+            }
+            return defaultValue;
+        }
+
+        // TODO doc
+        std::vector<celix::Version> getVersionVector(const std::string& key,
+                                                     const 
std::vector<celix::Version>& defaultValue = {}) const {
+            const auto* list = 
celix_properties_getVersionArrayList(cProps.get(), key.c_str(), nullptr);
+            if (list) {
+                std::vector<celix::Version> result{};
+                for (int i = 0; i < celix_arrayList_size(list); ++i) {
+                    auto* v = 
static_cast<celix_version_t*>(celix_arrayList_get(list, i));
+                    result.emplace_back(celix_version_getMajor(v),
+                                        celix_version_getMinor(v),
+                                        celix_version_getMicro(v),
+                                        celix_version_getQualifier(v));
+                }
+                return result;
+            }
+            return defaultValue;
+        }
+
+        // TODO doc
+        std::vector<std::string> getAsStringVector(const std::string& key,
+                                                   const 
std::vector<std::string>& defaultValue = {}) const {
+            celix_autoptr(celix_array_list_t) list;
+            celix_status_t status = 
celix_properties_getAsStringArrayList(cProps.get(), key.c_str(), nullptr, 
&list);
+            throwIfEnomem(status);
+            if (list) {
+                std::vector<std::string> result{};
+                for (int i = 0; i < celix_arrayList_size(list); ++i) {
+                    auto* s = celix_arrayList_getString(list, i);
+                    result.emplace_back(s);
+                }
+                return result;
+            }
+            return defaultValue;
+        }
+
+        // TODO doc
+        std::vector<std::string> getStringVector(const std::string& key,
+                                                 const 
std::vector<std::string>& defaultValue = {}) const {
+            const auto* list = 
celix_properties_getStringArrayList(cProps.get(), key.c_str(), nullptr);
+            if (list) {
+                std::vector<std::string> result{};
+                for (int i = 0; i < celix_arrayList_size(list); ++i) {
+                    auto* s = celix_arrayList_getString(list, i);
+                    result.emplace_back(s);
+                }
+                return result;
+            }
+            return defaultValue;
+        }
+
         /**
          * @brief Set the value of a property.
          *
@@ -468,6 +614,62 @@ namespace celix {
             throwIfEnomem(status);
         }
 
+        // TODO doc
+        void setStrings(const std::string& key, const 
std::vector<std::string>& values) {
+            celix_array_list_create_options_t opts{};
+            opts.simpleRemovedCallback = free;
+            celix_autoptr(celix_array_list_t) list = 
celix_arrayList_createWithOptions(&opts);
+            throwIfNull(list);
+            for (const auto& v : values) {
+                auto* s = celix_utils_strdup(v.c_str());
+                throwIfNull(s);
+                celix_status_t status = celix_arrayList_addString(list, s);
+                throwIfEnomem(status);
+            }
+            auto status = celix_properties_assignStringArrayList(cProps.get(), 
key.data(), celix_steal_ptr(list));
+            throwIfEnomem(status);
+        }
+
+        // TODO doc
+        void setVersions(const std::string& key, const 
std::vector<celix::Version>& values) {
+            celix_array_list_create_options_t opts{};
+            opts.simpleRemovedCallback = (void 
(*)(void*))celix_version_destroy;
+            celix_autoptr(celix_array_list_t) list = 
celix_arrayList_createWithOptions(&opts);
+            throwIfNull(list);
+            for (const auto& v : values) {
+                auto* cVer = celix_version_create(v.getMajor(), v.getMinor(), 
v.getMicro(), v.getQualifier().c_str());
+                throwIfNull(cVer);
+                celix_status_t status = celix_arrayList_add(list, cVer);
+                throwIfEnomem(status);
+            }
+            auto status = 
celix_properties_assignVersionArrayList(cProps.get(), key.data(), 
celix_steal_ptr(list));
+            throwIfEnomem(status);
+        }
+
+        // TODO doc
+        void setBooleans(const std::string& key, const std::vector<bool>& 
values) {
+            celix_autoptr(celix_array_list_t) list = celix_arrayList_create();
+            throwIfNull(list);
+            for (const auto& b : values) {
+                celix_status_t status = celix_arrayList_addBool(list, b);
+                throwIfEnomem(status);
+            }
+            auto status = celix_properties_assignBoolArrayList(cProps.get(), 
key.data(), celix_steal_ptr(list));
+            throwIfEnomem(status);
+        }
+
+        // TODO doc
+        void setLongs(const std::string& key, const std::vector<long>& values) 
{
+            auto status = celix_properties_setLongs(cProps.get(), key.data(), 
values.data(), values.size());
+            throwIfEnomem(status);
+        }
+
+        // TODO doc
+        void setDoubles(const std::string& key, const std::vector<double>& 
values) {
+            auto status = celix_properties_setDoubles(cProps.get(), 
key.data(), values.data(), values.size());
+            throwIfEnomem(status);
+        }
+
         /**
          * @brief Returns the number of properties in the Properties object.
          */
@@ -535,19 +737,24 @@ namespace celix {
         Properties(celix_properties_t* props, bool takeOwnership) :
             cProps{props, [takeOwnership](celix_properties_t* p){ if 
(takeOwnership) { celix_properties_destroy(p); }}} {}
 
-        std::shared_ptr<celix_properties_t> createCProps(celix_properties_t* 
p) {
-            if (!p) {
-                throw std::bad_alloc();
-            }
+        static std::shared_ptr<celix_properties_t> 
createCProps(celix_properties_t* p) {
+            throwIfNull(p);
             return std::shared_ptr<celix_properties_t>{p, 
[](celix_properties_t* p) { celix_properties_destroy(p); }};
         }
 
-        void throwIfEnomem(int status) {
+        static void throwIfEnomem(int status) {
             if (status == CELIX_ENOMEM) {
                 throw std::bad_alloc();
             }
         }
 
+        template<typename T>
+        static void throwIfNull(T* ptr) {
+            if (ptr == nullptr) {
+                throw std::bad_alloc();
+            }
+        }
+
         static celix::Properties::ValueType getAndConvertType(
                 const std::shared_ptr<celix_properties_t>& cProperties,
                 const char* key) {
@@ -563,6 +770,16 @@ namespace celix {
                     return ValueType::Bool;
                 case CELIX_PROPERTIES_VALUE_TYPE_VERSION:
                     return ValueType::Version;
+                case CELIX_PROPERTIES_VALUE_TYPE_LONG_ARRAY:
+                    return ValueType::LongArray;
+                case CELIX_PROPERTIES_VALUE_TYPE_DOUBLE_ARRAY:
+                    return ValueType::DoubleArray;
+                case CELIX_PROPERTIES_VALUE_TYPE_BOOL_ARRAY:
+                    return ValueType::BooleanArray;
+                case CELIX_PROPERTIES_VALUE_TYPE_VERSION_ARRAY:
+                    return ValueType::VersionArray;
+                case CELIX_PROPERTIES_VALUE_TYPE_STRING_ARRAY:
+                    return ValueType::StringArray;
                 default: /*unset*/
                     return ValueType::Unset;
             }
@@ -583,6 +800,20 @@ namespace celix {
             }
         }
 
+        template<typename T>
+        std::vector<T> convertToVector(const celix_array_list_t* list, const 
std::vector<T>& defaultValue, T (*get)(const celix_array_list_t*, int index)) 
const {
+            if (list) {
+                std::vector<T> result{};
+                result.reserve(celix_arrayList_size(list));
+                for (int i = 0; i < celix_arrayList_size(list); ++i) {
+                    T value = get(list, i);
+                    result.emplace_back(value);
+                }
+                return result;
+            }
+            return defaultValue;
+        }
+
         std::shared_ptr<celix_properties_t> cProps;
     };
 }
diff --git a/libs/utils/include/celix_properties.h 
b/libs/utils/include/celix_properties.h
index 900b0d3c..66114728 100644
--- a/libs/utils/include/celix_properties.h
+++ b/libs/utils/include/celix_properties.h
@@ -790,9 +790,9 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_properties_assignStringArrayList(celix_p
  *         and CELIX_ILLEGAL_ARGUMENT if the provided key is NULL or the 
values array is NULL.
  */
 CELIX_UTILS_EXPORT celix_status_t 
celix_properties_setStrings(celix_properties_t* properties,
-                                                               const char* key,
-                                                               const char** 
values,
-                                                               size_t 
nrOfValues);
+                                                              const char* key,
+                                                              const char* 
const* values,
+                                                              size_t 
nrOfValues);
 
 /**
  * @brief Get a property value as an array of strings, making a copy of the 
array.
diff --git a/libs/utils/src/properties.c b/libs/utils/src/properties.c
index fc32350d..3ad83f68 100644
--- a/libs/utils/src/properties.c
+++ b/libs/utils/src/properties.c
@@ -35,7 +35,6 @@
 #include "celix_stdlib_cleanup.h"
 #include "celix_convert_utils.h"
 #include "celix_utils_private_constants.h"
-#include "celix_stdio_cleanup.h"
 
 static const char* const CELIX_PROPERTIES_BOOL_TRUE_STRVAL = "true";
 static const char* const CELIX_PROPERTIES_BOOL_FALSE_STRVAL = "false";
@@ -139,19 +138,20 @@ static celix_status_t 
celix_properties_fillEntry(celix_properties_t* properties,
                                                  celix_properties_entry_t* 
entry,
                                                  const 
celix_properties_entry_t* prototype) {
     char convertedValueBuffer[21] = {0};
-    *entry = *prototype;
-    if (prototype->valueType == CELIX_PROPERTIES_VALUE_TYPE_VERSION) {
-        bool written = celix_version_fillString(prototype->typed.versionValue, 
convertedValueBuffer, sizeof(convertedValueBuffer));
+    memcpy(entry, prototype, sizeof(*entry));
+    entry->value = NULL;
+    if (entry->valueType == CELIX_PROPERTIES_VALUE_TYPE_VERSION) {
+        bool written = celix_version_fillString(entry->typed.versionValue, 
convertedValueBuffer, sizeof(convertedValueBuffer));
         if (written) {
             entry->value = celix_properties_createString(properties, 
convertedValueBuffer);
         } else {
-            entry->value = 
celix_version_toString(prototype->typed.versionValue);
+            entry->value = celix_version_toString(entry->typed.versionValue);
         }
-    } else if (prototype->valueType == CELIX_PROPERTIES_VALUE_TYPE_LONG) {
+    } else if (entry->valueType == CELIX_PROPERTIES_VALUE_TYPE_LONG) {
         // LONG_MAX str is 19 chars, LONG_MIN str is 20 chars
         (void)snprintf(convertedValueBuffer, sizeof(convertedValueBuffer), 
"%li", entry->typed.longValue);
         entry->value = celix_properties_createString(properties, 
convertedValueBuffer);
-    } else if (prototype->valueType == CELIX_PROPERTIES_VALUE_TYPE_DOUBLE) {
+    } else if (entry->valueType == CELIX_PROPERTIES_VALUE_TYPE_DOUBLE) {
         int written = snprintf(convertedValueBuffer, 
sizeof(convertedValueBuffer), "%f", entry->typed.doubleValue);
         if (written >= 0 || written < sizeof(convertedValueBuffer)) {
             entry->value = celix_properties_createString(properties, 
convertedValueBuffer);
@@ -160,21 +160,21 @@ static celix_status_t 
celix_properties_fillEntry(celix_properties_t* properties,
             asprintf(&val, "%f", entry->typed.doubleValue);
             entry->value = val;
         }
-    } else if (prototype->valueType == CELIX_PROPERTIES_VALUE_TYPE_BOOL) {
+    } else if (entry->valueType == CELIX_PROPERTIES_VALUE_TYPE_BOOL) {
         entry->value = entry->typed.boolValue ? 
CELIX_PROPERTIES_BOOL_TRUE_STRVAL : CELIX_PROPERTIES_BOOL_FALSE_STRVAL;
-    } else if (prototype->valueType == CELIX_PROPERTIES_VALUE_TYPE_LONG_ARRAY) 
{
+    } else if (entry->valueType == CELIX_PROPERTIES_VALUE_TYPE_LONG_ARRAY) {
         entry->value = 
celix_utils_longArrayListToString(entry->typed.arrayValue);
-    } else if (prototype->valueType == 
CELIX_PROPERTIES_VALUE_TYPE_DOUBLE_ARRAY) {
+    } else if (entry->valueType == CELIX_PROPERTIES_VALUE_TYPE_DOUBLE_ARRAY) {
         entry->value = 
celix_utils_doubleArrayListToString(entry->typed.arrayValue);
-    } else if (prototype->valueType == CELIX_PROPERTIES_VALUE_TYPE_BOOL_ARRAY) 
{
+    } else if (entry->valueType == CELIX_PROPERTIES_VALUE_TYPE_BOOL_ARRAY) {
         entry->value = 
celix_utils_boolArrayListToString(entry->typed.arrayValue);
-    } else if (prototype->valueType == 
CELIX_PROPERTIES_VALUE_TYPE_STRING_ARRAY) {
+    } else if (entry->valueType == CELIX_PROPERTIES_VALUE_TYPE_STRING_ARRAY) {
         entry->value = 
celix_utils_stringArrayListToString(entry->typed.arrayValue);
-    } else if (prototype->valueType == 
CELIX_PROPERTIES_VALUE_TYPE_VERSION_ARRAY) {
+    } else if (entry->valueType == CELIX_PROPERTIES_VALUE_TYPE_VERSION_ARRAY) {
         entry->value = 
celix_utils_versionArrayListToString(entry->typed.arrayValue);
     } else /*string value*/ {
-        assert(prototype->valueType == CELIX_PROPERTIES_VALUE_TYPE_STRING);
-        entry->value = celix_properties_createString(properties, 
prototype->typed.strValue);
+        assert(entry->valueType == CELIX_PROPERTIES_VALUE_TYPE_STRING);
+        entry->value = celix_properties_createString(properties, 
entry->typed.strValue);
         entry->typed.strValue = entry->value;
     }
 
@@ -1167,7 +1167,7 @@ 
celix_properties_assignStringArrayList(celix_properties_t* properties, const cha
 }
 
 celix_status_t
-celix_properties_setStrings(celix_properties_t* properties, const char* key, 
const char** values, size_t nrOfValues) {
+celix_properties_setStrings(celix_properties_t* properties, const char* key, 
const char* const * values, size_t nrOfValues) {
     assert(values != NULL);
     celix_array_list_create_options_t opts = 
CELIX_EMPTY_ARRAY_LIST_CREATE_OPTIONS;
     opts.simpleRemovedCallback = free;

Reply via email to